feat(mcp): improve remote ingest guidance
Make upload-ticket auth the default remote-agent path by returning complete upload URLs and updating service output/docs. Add validate_upload and preview_upload_metadata for lightweight file checks and exact sha256 duplicate warnings before ingest. Expose version, capability schema, file-index freshness, queue state, and known limitations through get_mcp_capabilities. Validation: python3 -m unittest discover -v; python3 -m compileall obsidian_wiki tests scripts; git diff --check.
This commit is contained in:
@@ -236,6 +236,81 @@ class McpIngestTests(unittest.TestCase):
|
||||
with self.assertRaises(IngestError):
|
||||
self.manager.create_completed_upload(file_name="too-large.pdf", payload=b"x" * 101)
|
||||
|
||||
def test_validate_upload_plan_reports_limits_and_exact_duplicates(self):
|
||||
duplicate_digest = self._sha256(b"already archived")
|
||||
registry = self.vault / "_meta" / "source-registry.jsonl"
|
||||
registry.parent.mkdir(parents=True)
|
||||
registry.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"record_type": "source_archive",
|
||||
"source_id": "sha256:" + duplicate_digest,
|
||||
"archive_path": "_sources/archive/existing.pdf",
|
||||
"original_name": "existing.pdf",
|
||||
}
|
||||
)
|
||||
+ "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
result = self.manager.validate_upload_plan(
|
||||
[
|
||||
{"file_name": "existing.pdf", "size_bytes": 12, "sha256": duplicate_digest},
|
||||
{"file_name": "too-large.pdf", "size_bytes": 101, "sha256": "b" * 64},
|
||||
{"file_name": "../secret.pdf", "size_bytes": 10, "sha256": "c" * 64},
|
||||
{"file_name": "bad-sha.pdf", "size_bytes": 10, "sha256": "not-a-sha"},
|
||||
],
|
||||
project="bjd",
|
||||
doc_type_hint="drawing",
|
||||
)
|
||||
|
||||
self.assertFalse(result["ok"])
|
||||
self.assertEqual(result["project"], "bjd")
|
||||
self.assertEqual(result["doc_type_hint"], "drawing")
|
||||
self.assertEqual(result["max_file_bytes"], 100)
|
||||
self.assertEqual(result["max_files_per_job"], 10)
|
||||
self.assertEqual(result["files"][0]["status"], "warning")
|
||||
self.assertTrue(result["files"][0]["duplicates"])
|
||||
self.assertEqual(result["files"][1]["status"], "error")
|
||||
self.assertIn("exceeds max upload size", result["files"][1]["errors"][0])
|
||||
self.assertIn("unsafe file name", result["files"][2]["errors"][0])
|
||||
self.assertIn("sha256", result["files"][3]["errors"][0])
|
||||
|
||||
def test_preview_upload_metadata_reports_duplicate_and_requires_completed_uploads(self):
|
||||
payload = b"duplicate payload"
|
||||
digest = self._sha256(payload)
|
||||
registry = self.vault / "_meta" / "source-registry.jsonl"
|
||||
registry.parent.mkdir(parents=True)
|
||||
registry.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"record_type": "source_archive",
|
||||
"source_id": "sha256:" + digest,
|
||||
"archive_path": "_sources/archive/duplicate.pdf",
|
||||
"original_name": "duplicate.pdf",
|
||||
}
|
||||
)
|
||||
+ "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
complete = self.manager.create_completed_upload(
|
||||
"duplicate.pdf",
|
||||
payload,
|
||||
project="bjd",
|
||||
doc_type_hint="drawing",
|
||||
)
|
||||
incomplete = self.manager.create_upload("pending.pdf", 7, self._sha256(b"pending"))
|
||||
|
||||
preview = self.manager.preview_upload_metadata([complete["upload_id"]])
|
||||
|
||||
self.assertTrue(preview["ok"])
|
||||
self.assertEqual(preview["next_action"], "start_ingest_job")
|
||||
self.assertEqual(preview["uploads"][0]["file_extension"], ".pdf")
|
||||
self.assertTrue(preview["uploads"][0]["duplicates"])
|
||||
self.assertEqual(preview["uploads"][0]["duplicate_count"], 1)
|
||||
with self.assertRaises(IngestError):
|
||||
self.manager.preview_upload_metadata([incomplete["upload_id"]])
|
||||
|
||||
def test_start_ingest_job_constructs_restricted_opencode_command(self):
|
||||
payload = b"source data"
|
||||
upload = self._complete_upload("source.pdf", payload)
|
||||
|
||||
Reference in New Issue
Block a user