@cerefox/memory 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT_GUIDE.md +28 -26
- package/AGENT_QUICK_REFERENCE.md +12 -12
- package/dist/bin/cerefox.js +646 -427
- package/dist/server-assets/_shared/ef-meta/index.ts +1 -1
- package/dist/server-assets/_shared/mcp-tools/get-help-content.ts +2 -2
- package/docs/guides/access-paths.md +40 -34
- package/docs/guides/cli.md +158 -16
- package/docs/guides/configuration.md +20 -29
- package/docs/guides/connect-agents.md +154 -177
- package/docs/guides/ops-scripts.md +73 -53
- package/docs/guides/quickstart.md +26 -20
- package/docs/guides/setup-cloud-run.md +12 -2
- package/docs/guides/setup-local.md +14 -8
- package/docs/guides/setup-supabase.md +57 -162
- package/docs/guides/upgrading.md +43 -30
- package/package.json +1 -1
package/dist/bin/cerefox.js
CHANGED
|
@@ -7184,7 +7184,7 @@ var exports_meta = {};
|
|
|
7184
7184
|
__export(exports_meta, {
|
|
7185
7185
|
PKG_VERSION: () => PKG_VERSION
|
|
7186
7186
|
});
|
|
7187
|
-
var PKG_VERSION = "0.9.
|
|
7187
|
+
var PKG_VERSION = "0.9.2";
|
|
7188
7188
|
var init_meta = () => {};
|
|
7189
7189
|
|
|
7190
7190
|
// ../../node_modules/.bun/tslib@2.8.1/node_modules/tslib/tslib.js
|
|
@@ -24628,16 +24628,16 @@ var init_src = __esm(() => {
|
|
|
24628
24628
|
});
|
|
24629
24629
|
|
|
24630
24630
|
// src/cli/util/bundled-docs.ts
|
|
24631
|
-
import { existsSync as
|
|
24632
|
-
import { dirname as dirname3, join as
|
|
24631
|
+
import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync6, statSync } from "node:fs";
|
|
24632
|
+
import { dirname as dirname3, join as join7, resolve as resolve2 } from "node:path";
|
|
24633
24633
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
24634
24634
|
function findPackageRoot() {
|
|
24635
24635
|
let dir = dirname3(fileURLToPath2(import.meta.url));
|
|
24636
24636
|
for (let i = 0;i < 10; i++) {
|
|
24637
|
-
const pkgJson =
|
|
24638
|
-
if (
|
|
24637
|
+
const pkgJson = join7(dir, "package.json");
|
|
24638
|
+
if (existsSync8(pkgJson)) {
|
|
24639
24639
|
try {
|
|
24640
|
-
const parsed = JSON.parse(
|
|
24640
|
+
const parsed = JSON.parse(readFileSync6(pkgJson, "utf8"));
|
|
24641
24641
|
if (parsed.name === "@cerefox/memory")
|
|
24642
24642
|
return dir;
|
|
24643
24643
|
} catch {}
|
|
@@ -24650,40 +24650,40 @@ function findPackageRoot() {
|
|
|
24650
24650
|
return resolve2(dirname3(fileURLToPath2(import.meta.url)), "..", "..", "..");
|
|
24651
24651
|
}
|
|
24652
24652
|
function bundledDocsDir() {
|
|
24653
|
-
const inPackage =
|
|
24654
|
-
if (
|
|
24653
|
+
const inPackage = join7(PACKAGE_ROOT, "docs");
|
|
24654
|
+
if (existsSync8(inPackage))
|
|
24655
24655
|
return inPackage;
|
|
24656
24656
|
return resolve2(PACKAGE_ROOT, "..", "..", "docs");
|
|
24657
24657
|
}
|
|
24658
24658
|
function agentGuidePath() {
|
|
24659
24659
|
const candidates = [
|
|
24660
|
-
|
|
24660
|
+
join7(PACKAGE_ROOT, "AGENT_GUIDE.md"),
|
|
24661
24661
|
resolve2(PACKAGE_ROOT, "..", "..", "AGENT_GUIDE.md")
|
|
24662
24662
|
];
|
|
24663
24663
|
for (const c2 of candidates)
|
|
24664
|
-
if (
|
|
24664
|
+
if (existsSync8(c2))
|
|
24665
24665
|
return c2;
|
|
24666
24666
|
return null;
|
|
24667
24667
|
}
|
|
24668
24668
|
function agentQuickReferencePath() {
|
|
24669
24669
|
const candidates = [
|
|
24670
|
-
|
|
24670
|
+
join7(PACKAGE_ROOT, "AGENT_QUICK_REFERENCE.md"),
|
|
24671
24671
|
resolve2(PACKAGE_ROOT, "..", "..", "AGENT_QUICK_REFERENCE.md")
|
|
24672
24672
|
];
|
|
24673
24673
|
for (const c2 of candidates)
|
|
24674
|
-
if (
|
|
24674
|
+
if (existsSync8(c2))
|
|
24675
24675
|
return c2;
|
|
24676
24676
|
return null;
|
|
24677
24677
|
}
|
|
24678
24678
|
function listBundledDocs() {
|
|
24679
24679
|
const entries = [];
|
|
24680
24680
|
const docsDir = bundledDocsDir();
|
|
24681
|
-
const guidesDir =
|
|
24682
|
-
if (
|
|
24681
|
+
const guidesDir = join7(docsDir, "guides");
|
|
24682
|
+
if (existsSync8(guidesDir) && statSync(guidesDir).isDirectory()) {
|
|
24683
24683
|
for (const name of readdirSync3(guidesDir)) {
|
|
24684
24684
|
if (!name.endsWith(".md"))
|
|
24685
24685
|
continue;
|
|
24686
|
-
const full =
|
|
24686
|
+
const full = join7(guidesDir, name);
|
|
24687
24687
|
entries.push({
|
|
24688
24688
|
topic: name.replace(/\.md$/, ""),
|
|
24689
24689
|
path: full,
|
|
@@ -24712,7 +24712,7 @@ function readBundledDoc(topic) {
|
|
|
24712
24712
|
return {
|
|
24713
24713
|
topic: entry.topic,
|
|
24714
24714
|
path: entry.path,
|
|
24715
|
-
content:
|
|
24715
|
+
content: readFileSync6(entry.path, "utf8")
|
|
24716
24716
|
};
|
|
24717
24717
|
}
|
|
24718
24718
|
var PACKAGE_ROOT;
|
|
@@ -25748,7 +25748,7 @@ var init_get_document = __esm(() => {
|
|
|
25748
25748
|
});
|
|
25749
25749
|
|
|
25750
25750
|
// ../../_shared/mcp-tools/get-help-content.ts
|
|
25751
|
-
var HELP_FULL = '# Cerefox Knowledge Base -- Agent Quick Reference\n\nCerefox is a persistent, shared knowledge base. You have **10 MCP tools** (9 of them have CLI equivalents — `cerefox_get_help` is MCP-only). For the full guide, search Cerefox for "How AI Agents Use Cerefox" or call `cerefox_get_help` to retrieve this content over MCP.\n\n## Tools\n\n| Tool | Purpose | Key params |\n|------|---------|------------|\n| `cerefox_search` | Find documents (hybrid FTS + semantic) | `query` (required), `project_name`, `metadata_filter`, `requestor` |\n| `cerefox_ingest` | Save or update a document | `title`, `content` (required), `document_id` (update by ID), `update_if_exists`, `project_name` (single, non-destructive add on update), `project_names` (list, destructive replace on update), `metadata`, `author` |\n| `cerefox_get_document` | Get full document by ID | `document_id` (required) |\n| `cerefox_list_versions` | Version history of a document | `document_id` (required) |\n| `cerefox_metadata_search` | Find docs by metadata (no text query) | `metadata_filter` (required), `include_content`, `updated_since` |\n| `cerefox_list_metadata_keys` | Discover available metadata keys | (none required) |\n| `cerefox_list_projects` | List all projects | (none required) |\n| `cerefox_set_document_projects` | Set doc\'s project memberships to exactly the given list (destructive replace; metadata-only, no content change) | `document_id`, `project_names` (required) |\n| `cerefox_get_audit_log` | Query write operation history | `document_id`, `author`, `operation`, `since` |\n| `cerefox_get_help` | Retrieve Cerefox conventions (this reference) over MCP. **Call this whenever uncertain.** | `topic` (optional, case-insensitive H2 substring match) |\n\n## Essential Rules\n\n1. **Search before ingesting** -- check if the document exists first.\n2. **Prefer ID-based updates** -- pass `document_id` from search results for deterministic updates. Falls back to title-matching with `update_if_exists: true`.\n3. **Set `author`/`requestor`** to your name on every call (e.g., "Claude Code", "archiver"). On MCP, pass as parameters. On CLI, pass `--author`/`--author-type`/`--requestor` flags, or rely on `CEREFOX_AUTHOR_NAME`/`CEREFOX_AUTHOR_TYPE`/`CEREFOX_REQUESTOR_NAME` env vars set in the user\'s `.env`.\n4. **Use `document_id` from search results** `[id: uuid]` for get_document and list_versions.\n5. **Add metadata** -- at minimum `type` ("decision-log", "research", "design-doc") and `status` ("active", "draft").\n6. **Write structured Markdown** with H1/H2/H3 headings for good chunking and search.\n7. **Deletes are soft (recoverable); purge is web-UI-only.** If you decide to delete, surface it to the user (`I soft-deleted X — recoverable from the Cerefox web UI trash`). You cannot un-do your own delete from agent code by design.\n8. **Cross-doc links inside content**: **always use `[Text](document-uuid)`.** UUIDs are the only fully reliable link form — stable across title changes, never ambiguous, no encoding gotchas. Every `cerefox_search` result shows `[id: <uuid>]` after the title; grab it and use it. Title-based linking (`[Text](<Title With Spaces>)`) is fragile (breaks on colons, parens, ampersands, brackets — silently navigates to wrong page) — **don\'t write title-based links**; do an extra search to get the UUID instead. Repo-path forms (`[Text](docs/path.md)`) exist for repo-ingested files; don\'t construct manually. See `AGENT_GUIDE.md → Writing linkable content` for the full rule.\n9. **Project memberships — non-destructive by default**: on `cerefox_ingest` updates, **`project_name` (singular) is a non-destructive add** (ensures membership, preserves others). Use **`project_names` (list)** when you want to set the doc\'s full project set in one call (destructive replace). For metadata-only project changes without writing content, use **`cerefox_set_document_projects(document_id, project_names)`** — that tool is the destructive-replace contract made explicit. Never call `cerefox_set_document_projects` with a single name when you mean "add" — that would REMOVE the doc from all other projects. When in doubt, use `cerefox_ingest` with singular `project_name`.\n\n## Update Workflow (ID-based -- preferred)\n\n```\nsearch("topic") -> find doc [id: abc123] -> get_document(abc123) -> modify ->\ningest(title="Same Title", content="...", document_id="abc123", author="my-agent")\n```\n\n## Update Workflow (title-based -- fallback)\n\n```\nsearch("topic") -> find doc -> modify ->\ningest(title="Same Title", content="...", update_if_exists=true, author="my-agent")\n```\n\n## Catch-Up Workflow\n\n```\nmetadata_search(metadata_filter={"type": "decision-log"}, updated_since="2026-03-28T00:00:00Z")\n```\n\n## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI.
|
|
25751
|
+
var HELP_FULL = '# Cerefox Knowledge Base -- Agent Quick Reference\n\nCerefox is a persistent, shared knowledge base. You have **10 MCP tools** (9 of them have CLI equivalents — `cerefox_get_help` is MCP-only). For the full guide, search Cerefox for "How AI Agents Use Cerefox" or call `cerefox_get_help` to retrieve this content over MCP.\n\n## Tools\n\n| Tool | Purpose | Key params |\n|------|---------|------------|\n| `cerefox_search` | Find documents (hybrid FTS + semantic) | `query` (required), `project_name`, `metadata_filter`, `requestor` |\n| `cerefox_ingest` | Save or update a document | `title`, `content` (required), `document_id` (update by ID), `update_if_exists`, `project_name` (single, non-destructive add on update), `project_names` (list, destructive replace on update), `metadata`, `author` |\n| `cerefox_get_document` | Get full document by ID | `document_id` (required) |\n| `cerefox_list_versions` | Version history of a document | `document_id` (required) |\n| `cerefox_metadata_search` | Find docs by metadata (no text query) | `metadata_filter` (required), `include_content`, `updated_since` |\n| `cerefox_list_metadata_keys` | Discover available metadata keys | (none required) |\n| `cerefox_list_projects` | List all projects | (none required) |\n| `cerefox_set_document_projects` | Set doc\'s project memberships to exactly the given list (destructive replace; metadata-only, no content change) | `document_id`, `project_names` (required) |\n| `cerefox_get_audit_log` | Query write operation history | `document_id`, `author`, `operation`, `since` |\n| `cerefox_get_help` | Retrieve Cerefox conventions (this reference) over MCP. **Call this whenever uncertain.** | `topic` (optional, case-insensitive H2 substring match) |\n\n## Essential Rules\n\n1. **Search before ingesting** -- check if the document exists first.\n2. **Prefer ID-based updates** -- pass `document_id` from search results for deterministic updates. Falls back to title-matching with `update_if_exists: true`.\n3. **Set `author`/`requestor`** to your name on every call (e.g., "Claude Code", "archiver"). On MCP, pass as parameters. On CLI, pass `--author`/`--author-type`/`--requestor` flags, or rely on `CEREFOX_AUTHOR_NAME`/`CEREFOX_AUTHOR_TYPE`/`CEREFOX_REQUESTOR_NAME` env vars set in the user\'s `.env`.\n4. **Use `document_id` from search results** `[id: uuid]` for get_document and list_versions.\n5. **Add metadata** -- at minimum `type` ("decision-log", "research", "design-doc") and `status` ("active", "draft").\n6. **Write structured Markdown** with H1/H2/H3 headings for good chunking and search.\n7. **Deletes are soft (recoverable); purge is web-UI-only.** If you decide to delete, surface it to the user (`I soft-deleted X — recoverable from the Cerefox web UI trash`). You cannot un-do your own delete from agent code by design.\n8. **Cross-doc links inside content**: **always use `[Text](document-uuid)`.** UUIDs are the only fully reliable link form — stable across title changes, never ambiguous, no encoding gotchas. Every `cerefox_search` result shows `[id: <uuid>]` after the title; grab it and use it. Title-based linking (`[Text](<Title With Spaces>)`) is fragile (breaks on colons, parens, ampersands, brackets — silently navigates to wrong page) — **don\'t write title-based links**; do an extra search to get the UUID instead. Repo-path forms (`[Text](docs/path.md)`) exist for repo-ingested files; don\'t construct manually. See `AGENT_GUIDE.md → Writing linkable content` for the full rule.\n9. **Project memberships — non-destructive by default**: on `cerefox_ingest` updates, **`project_name` (singular) is a non-destructive add** (ensures membership, preserves others). Use **`project_names` (list)** when you want to set the doc\'s full project set in one call (destructive replace). For metadata-only project changes without writing content, use **`cerefox_set_document_projects(document_id, project_names)`** — that tool is the destructive-replace contract made explicit. Never call `cerefox_set_document_projects` with a single name when you mean "add" — that would REMOVE the doc from all other projects. When in doubt, use `cerefox_ingest` with singular `project_name`.\n\n## Update Workflow (ID-based -- preferred)\n\n```\nsearch("topic") -> find doc [id: abc123] -> get_document(abc123) -> modify ->\ningest(title="Same Title", content="...", document_id="abc123", author="my-agent")\n```\n\n## Update Workflow (title-based -- fallback)\n\n```\nsearch("topic") -> find doc -> modify ->\ningest(title="Same Title", content="...", update_if_exists=true, author="my-agent")\n```\n\n## Catch-Up Workflow\n\n```\nmetadata_search(metadata_filter={"type": "decision-log"}, updated_since="2026-03-28T00:00:00Z")\n```\n\n## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.\n\nSame operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); short forms (`--filter`, `--project`, `--count`, `--update`, `--version`) work as aliases.\n\n| MCP tool | CLI |\n|---|---|\n| `cerefox_search` | `cerefox search "<q>" --requestor "<your-name>"` |\n| `cerefox_ingest` (paste) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --author "<your-name>" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --document-id "<uuid>" --author "<your-name>" --author-type agent` |\n| `cerefox_get_document` | `cerefox document get <id> --version-id <vid> --requestor "<your-name>"` |\n| `cerefox_list_versions` | `cerefox document version list <id> --requestor "<your-name>"` |\n| `cerefox_list_projects` | `cerefox project list --requestor "<your-name>"` |\n| `cerefox_list_metadata_keys` | `cerefox metadata keys` |\n| `cerefox_metadata_search` | `cerefox metadata search --metadata-filter \'<json>\' --requestor "<your-name>"` |\n| `cerefox_set_document_projects` | _MCP-only; a CLI command will be added in a future release. Until then, run via MCP if available._ |\n| `cerefox_get_audit_log` | `cerefox audit list --requestor "<your-name>"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox guides show agent-quick-reference` (or `cerefox guides list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`document ingest`, `document ingest-dir`): `--author "<your-name>" --author-type agent`\n- Reads: `--requestor "<your-name>"`\n\nOr have your user set `CEREFOX_AUTHOR_NAME` / `CEREFOX_AUTHOR_TYPE` / `CEREFOX_REQUESTOR_NAME` in their `.env` to apply defaults once.\n', HELP_SECTIONS, HELP_SECTION_HEADINGS;
|
|
25752
25752
|
var init_get_help_content = __esm(() => {
|
|
25753
25753
|
HELP_SECTIONS = {
|
|
25754
25754
|
Tools: "## Tools\n\n| Tool | Purpose | Key params |\n|------|---------|------------|\n| `cerefox_search` | Find documents (hybrid FTS + semantic) | `query` (required), `project_name`, `metadata_filter`, `requestor` |\n| `cerefox_ingest` | Save or update a document | `title`, `content` (required), `document_id` (update by ID), `update_if_exists`, `project_name` (single, non-destructive add on update), `project_names` (list, destructive replace on update), `metadata`, `author` |\n| `cerefox_get_document` | Get full document by ID | `document_id` (required) |\n| `cerefox_list_versions` | Version history of a document | `document_id` (required) |\n| `cerefox_metadata_search` | Find docs by metadata (no text query) | `metadata_filter` (required), `include_content`, `updated_since` |\n| `cerefox_list_metadata_keys` | Discover available metadata keys | (none required) |\n| `cerefox_list_projects` | List all projects | (none required) |\n| `cerefox_set_document_projects` | Set doc's project memberships to exactly the given list (destructive replace; metadata-only, no content change) | `document_id`, `project_names` (required) |\n| `cerefox_get_audit_log` | Query write operation history | `document_id`, `author`, `operation`, `since` |\n| `cerefox_get_help` | Retrieve Cerefox conventions (this reference) over MCP. **Call this whenever uncertain.** | `topic` (optional, case-insensitive H2 substring match) |",
|
|
@@ -25756,7 +25756,7 @@ var init_get_help_content = __esm(() => {
|
|
|
25756
25756
|
"Update Workflow (ID-based -- preferred)": '## Update Workflow (ID-based -- preferred)\n\n```\nsearch("topic") -> find doc [id: abc123] -> get_document(abc123) -> modify ->\ningest(title="Same Title", content="...", document_id="abc123", author="my-agent")\n```',
|
|
25757
25757
|
"Update Workflow (title-based -- fallback)": '## Update Workflow (title-based -- fallback)\n\n```\nsearch("topic") -> find doc -> modify ->\ningest(title="Same Title", content="...", update_if_exists=true, author="my-agent")\n```',
|
|
25758
25758
|
"Catch-Up Workflow": '## Catch-Up Workflow\n\n```\nmetadata_search(metadata_filter={"type": "decision-log"}, updated_since="2026-03-28T00:00:00Z")\n```',
|
|
25759
|
-
"CLI fallback (when MCP is unavailable)": '## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI.
|
|
25759
|
+
"CLI fallback (when MCP is unavailable)": '## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.\n\nSame operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); short forms (`--filter`, `--project`, `--count`, `--update`, `--version`) work as aliases.\n\n| MCP tool | CLI |\n|---|---|\n| `cerefox_search` | `cerefox search "<q>" --requestor "<your-name>"` |\n| `cerefox_ingest` (paste) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --author "<your-name>" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --document-id "<uuid>" --author "<your-name>" --author-type agent` |\n| `cerefox_get_document` | `cerefox document get <id> --version-id <vid> --requestor "<your-name>"` |\n| `cerefox_list_versions` | `cerefox document version list <id> --requestor "<your-name>"` |\n| `cerefox_list_projects` | `cerefox project list --requestor "<your-name>"` |\n| `cerefox_list_metadata_keys` | `cerefox metadata keys` |\n| `cerefox_metadata_search` | `cerefox metadata search --metadata-filter \'<json>\' --requestor "<your-name>"` |\n| `cerefox_set_document_projects` | _MCP-only; a CLI command will be added in a future release. Until then, run via MCP if available._ |\n| `cerefox_get_audit_log` | `cerefox audit list --requestor "<your-name>"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox guides show agent-quick-reference` (or `cerefox guides list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`document ingest`, `document ingest-dir`): `--author "<your-name>" --author-type agent`\n- Reads: `--requestor "<your-name>"`\n\nOr have your user set `CEREFOX_AUTHOR_NAME` / `CEREFOX_AUTHOR_TYPE` / `CEREFOX_REQUESTOR_NAME` in their `.env` to apply defaults once.'
|
|
25760
25760
|
};
|
|
25761
25761
|
HELP_SECTION_HEADINGS = ["Tools", "Essential Rules", "Update Workflow (ID-based -- preferred)", "Update Workflow (title-based -- fallback)", "Catch-Up Workflow", "CLI fallback (when MCP is unavailable)"];
|
|
25762
25762
|
});
|
|
@@ -26758,7 +26758,7 @@ __export(exports_sync_self_docs, {
|
|
|
26758
26758
|
runSyncSelfDocs: () => runSyncSelfDocs,
|
|
26759
26759
|
registerSyncSelfDocs: () => registerSyncSelfDocs
|
|
26760
26760
|
});
|
|
26761
|
-
import { readFileSync as
|
|
26761
|
+
import { readFileSync as readFileSync10 } from "node:fs";
|
|
26762
26762
|
import { basename as basename4, extname as extname4 } from "node:path";
|
|
26763
26763
|
async function runSyncSelfDocs(options = {}) {
|
|
26764
26764
|
const project = options.project ?? "_cerefox-self-docs";
|
|
@@ -26785,7 +26785,7 @@ async function runSyncSelfDocs(options = {}) {
|
|
|
26785
26785
|
const authorType = resolveAuthorType("agent");
|
|
26786
26786
|
const outcomes = [];
|
|
26787
26787
|
for (const doc of docs) {
|
|
26788
|
-
const content =
|
|
26788
|
+
const content = readFileSync10(doc.path, "utf8");
|
|
26789
26789
|
const m = content.match(/^#\s+(.+)$/m);
|
|
26790
26790
|
const title = m ? m[1].trim() : basename4(doc.path, extname4(doc.path));
|
|
26791
26791
|
try {
|
|
@@ -26819,11 +26819,11 @@ async function runSyncSelfDocs(options = {}) {
|
|
|
26819
26819
|
printTable(outcomes.filter((o) => o.status === "error").map((o) => ({ topic: o.topic, error: o.detail.slice(0, 100) })));
|
|
26820
26820
|
}
|
|
26821
26821
|
}
|
|
26822
|
-
async function
|
|
26822
|
+
async function action19(options) {
|
|
26823
26823
|
await runSyncSelfDocs(options);
|
|
26824
26824
|
}
|
|
26825
26825
|
function registerSyncSelfDocs(program2) {
|
|
26826
|
-
program2.command("sync-self-docs").description("Ingest bundled Cerefox docs under the _cerefox-self-docs project.").option("--dry-run", "List what would be ingested without writing.").option("--project <name>", "Override the target project name.", "_cerefox-self-docs").action(
|
|
26826
|
+
program2.command("sync-self-docs").description("Ingest bundled Cerefox docs under the _cerefox-self-docs project.").option("--dry-run", "List what would be ingested without writing.").option("--project <name>", "Override the target project name.", "_cerefox-self-docs").action(action19);
|
|
26827
26827
|
}
|
|
26828
26828
|
var init_sync_self_docs = __esm(() => {
|
|
26829
26829
|
init_cli_core();
|
|
@@ -40002,117 +40002,245 @@ function registerBackup(program2) {
|
|
|
40002
40002
|
|
|
40003
40003
|
// src/cli/commands/completion.ts
|
|
40004
40004
|
init_cli_core();
|
|
40005
|
-
|
|
40005
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
40006
|
+
import { homedir as homedir3 } from "node:os";
|
|
40007
|
+
import { join as join3 } from "node:path";
|
|
40008
|
+
function isHidden(cmd) {
|
|
40009
|
+
return Boolean(cmd._hidden);
|
|
40010
|
+
}
|
|
40011
|
+
function visibleSubs(cmd) {
|
|
40012
|
+
return cmd.commands.filter((c2) => c2.name() !== "help" && !isHidden(c2));
|
|
40013
|
+
}
|
|
40014
|
+
function longFlags(cmd) {
|
|
40015
|
+
const flags = [];
|
|
40016
|
+
for (const opt of cmd.options) {
|
|
40017
|
+
if (opt.long)
|
|
40018
|
+
flags.push(opt.long);
|
|
40019
|
+
}
|
|
40020
|
+
return flags;
|
|
40021
|
+
}
|
|
40022
|
+
function collectNodes() {
|
|
40006
40023
|
const program2 = buildProgram();
|
|
40007
|
-
const
|
|
40008
|
-
|
|
40009
|
-
|
|
40010
|
-
|
|
40011
|
-
|
|
40012
|
-
for (const
|
|
40013
|
-
|
|
40014
|
-
|
|
40015
|
-
|
|
40016
|
-
|
|
40017
|
-
|
|
40018
|
-
|
|
40019
|
-
|
|
40020
|
-
|
|
40021
|
-
|
|
40022
|
-
}
|
|
40023
|
-
function bashScript(info2) {
|
|
40024
|
-
const cmdNames = info2.subcommands.map((s) => s.name).join(" ");
|
|
40025
|
-
const cases = info2.subcommands.map((s) => ` ${s.name})
|
|
40026
|
-
opts="${s.flags.join(" ")}"
|
|
40027
|
-
;;`).join(`
|
|
40024
|
+
const nodes = [];
|
|
40025
|
+
const walk = (cmd, path) => {
|
|
40026
|
+
const subs = visibleSubs(cmd);
|
|
40027
|
+
const candidates = [...subs.map((s) => s.name()), ...longFlags(cmd), "--help"];
|
|
40028
|
+
nodes.push({ path, candidates });
|
|
40029
|
+
for (const s of subs) {
|
|
40030
|
+
walk(s, path === "" ? s.name() : `${path} ${s.name()}`);
|
|
40031
|
+
}
|
|
40032
|
+
};
|
|
40033
|
+
walk(program2, "");
|
|
40034
|
+
nodes.sort((a, b) => a.path.localeCompare(b.path));
|
|
40035
|
+
return nodes;
|
|
40036
|
+
}
|
|
40037
|
+
function bashScript(nodes) {
|
|
40038
|
+
const candCases = nodes.map((n) => ` "${n.path}") echo "${n.candidates.join(" ")}" ;;`).join(`
|
|
40028
40039
|
`);
|
|
40040
|
+
const pathPatterns = nodes.filter((n) => n.path !== "").map((n) => `"${n.path}"`).join("|");
|
|
40029
40041
|
return `# Cerefox bash completion. Source from ~/.bashrc:
|
|
40030
40042
|
# source <(cerefox completion bash)
|
|
40031
40043
|
#
|
|
40044
|
+
_cerefox_candidates() {
|
|
40045
|
+
case "$1" in
|
|
40046
|
+
${candCases}
|
|
40047
|
+
*) echo "--help" ;;
|
|
40048
|
+
esac
|
|
40049
|
+
}
|
|
40050
|
+
_cerefox_is_path() {
|
|
40051
|
+
case "$1" in
|
|
40052
|
+
${pathPatterns}) return 0 ;;
|
|
40053
|
+
*) return 1 ;;
|
|
40054
|
+
esac
|
|
40055
|
+
}
|
|
40032
40056
|
_cerefox_completion() {
|
|
40033
|
-
local cur
|
|
40057
|
+
local cur path trial w i
|
|
40034
40058
|
COMPREPLY=()
|
|
40035
40059
|
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
40036
|
-
|
|
40037
|
-
|
|
40038
|
-
|
|
40039
|
-
|
|
40040
|
-
|
|
40041
|
-
|
|
40042
|
-
|
|
40043
|
-
$
|
|
40044
|
-
|
|
40045
|
-
|
|
40046
|
-
|
|
40047
|
-
|
|
40048
|
-
COMPREPLY=( $(compgen -W "
|
|
40060
|
+
path=""
|
|
40061
|
+
i=1
|
|
40062
|
+
while [ "$i" -lt "\${COMP_CWORD}" ]; do
|
|
40063
|
+
w="\${COMP_WORDS[$i]}"
|
|
40064
|
+
case "$w" in -*) break ;; esac
|
|
40065
|
+
if [ -z "$path" ]; then trial="$w"; else trial="$path $w"; fi
|
|
40066
|
+
if _cerefox_is_path "$trial"; then
|
|
40067
|
+
path="$trial"; i=$((i + 1))
|
|
40068
|
+
else
|
|
40069
|
+
break
|
|
40070
|
+
fi
|
|
40071
|
+
done
|
|
40072
|
+
COMPREPLY=( $(compgen -W "$(_cerefox_candidates "$path")" -- "$cur") )
|
|
40049
40073
|
return 0
|
|
40050
40074
|
}
|
|
40051
40075
|
complete -F _cerefox_completion cerefox
|
|
40052
40076
|
`;
|
|
40053
40077
|
}
|
|
40054
|
-
function zshScript(
|
|
40055
|
-
const
|
|
40056
|
-
const cases = info2.subcommands.map((s) => {
|
|
40057
|
-
const flagList = s.flags.map((f) => `'${f}'`).join(" ");
|
|
40058
|
-
return ` ${s.name}) flags=(${flagList}) ;;`;
|
|
40059
|
-
}).join(`
|
|
40078
|
+
function zshScript(nodes) {
|
|
40079
|
+
const candCases = nodes.map((n) => ` "${n.path}") REPLY="${n.candidates.join(" ")}" ;;`).join(`
|
|
40060
40080
|
`);
|
|
40081
|
+
const pathPatterns = nodes.filter((n) => n.path !== "").map((n) => `"${n.path}"`).join("|");
|
|
40061
40082
|
return `#compdef cerefox
|
|
40062
40083
|
# Cerefox zsh completion. Save and source from ~/.zshrc:
|
|
40063
40084
|
# source <(cerefox completion zsh)
|
|
40064
40085
|
#
|
|
40065
|
-
|
|
40066
|
-
|
|
40067
|
-
|
|
40068
|
-
|
|
40069
|
-
_values 'cerefox subcommand' $cmds
|
|
40070
|
-
return
|
|
40071
|
-
fi
|
|
40072
|
-
case "$words[2]" in
|
|
40073
|
-
${cases}
|
|
40074
|
-
*) flags=() ;;
|
|
40086
|
+
_cerefox_candidates() {
|
|
40087
|
+
case "$1" in
|
|
40088
|
+
${candCases}
|
|
40089
|
+
*) REPLY="--help" ;;
|
|
40075
40090
|
esac
|
|
40076
|
-
|
|
40091
|
+
}
|
|
40092
|
+
_cerefox_is_path() {
|
|
40093
|
+
case "$1" in
|
|
40094
|
+
${pathPatterns}) return 0 ;;
|
|
40095
|
+
*) return 1 ;;
|
|
40096
|
+
esac
|
|
40097
|
+
}
|
|
40098
|
+
_cerefox() {
|
|
40099
|
+
local path trial w i REPLY
|
|
40100
|
+
path=""
|
|
40101
|
+
i=2
|
|
40102
|
+
while (( i < CURRENT )); do
|
|
40103
|
+
w="\${words[i]}"
|
|
40104
|
+
case "$w" in -*) break ;; esac
|
|
40105
|
+
if [[ -z "$path" ]]; then trial="$w"; else trial="$path $w"; fi
|
|
40106
|
+
if _cerefox_is_path "$trial"; then
|
|
40107
|
+
path="$trial"; (( i++ ))
|
|
40108
|
+
else
|
|
40109
|
+
break
|
|
40110
|
+
fi
|
|
40111
|
+
done
|
|
40112
|
+
_cerefox_candidates "$path"
|
|
40113
|
+
compadd -- \${=REPLY}
|
|
40077
40114
|
}
|
|
40078
40115
|
compdef _cerefox cerefox
|
|
40079
40116
|
`;
|
|
40080
40117
|
}
|
|
40081
|
-
function fishScript(
|
|
40082
|
-
const
|
|
40083
|
-
|
|
40084
|
-
|
|
40085
|
-
|
|
40086
|
-
|
|
40087
|
-
|
|
40088
|
-
|
|
40089
|
-
|
|
40090
|
-
|
|
40091
|
-
|
|
40092
|
-
|
|
40093
|
-
|
|
40118
|
+
function fishScript(nodes) {
|
|
40119
|
+
const candCases = nodes.map((n) => ` case "${n.path}"
|
|
40120
|
+
echo "${n.candidates.join(" ")}"`).join(`
|
|
40121
|
+
`);
|
|
40122
|
+
const pathList = nodes.filter((n) => n.path !== "").map((n) => `"${n.path}"`).join(" ");
|
|
40123
|
+
return `# Cerefox fish completion. Save to ~/.config/fish/completions/cerefox.fish
|
|
40124
|
+
function __cerefox_candidates
|
|
40125
|
+
switch "$argv[1]"
|
|
40126
|
+
${candCases}
|
|
40127
|
+
case '*'
|
|
40128
|
+
echo "--help"
|
|
40129
|
+
end
|
|
40130
|
+
end
|
|
40131
|
+
function __cerefox_is_path
|
|
40132
|
+
for p in ${pathList}
|
|
40133
|
+
if test "$argv[1]" = "$p"
|
|
40134
|
+
return 0
|
|
40135
|
+
end
|
|
40136
|
+
end
|
|
40137
|
+
return 1
|
|
40138
|
+
end
|
|
40139
|
+
function __cerefox_complete
|
|
40140
|
+
set -l tokens (commandline -opc)
|
|
40141
|
+
set -l path ""
|
|
40142
|
+
set -l i 2
|
|
40143
|
+
while test $i -le (count $tokens)
|
|
40144
|
+
set -l w $tokens[$i]
|
|
40145
|
+
if string match -q -- '-*' $w
|
|
40146
|
+
break
|
|
40147
|
+
end
|
|
40148
|
+
set -l trial
|
|
40149
|
+
if test -z "$path"
|
|
40150
|
+
set trial $w
|
|
40151
|
+
else
|
|
40152
|
+
set trial "$path $w"
|
|
40153
|
+
end
|
|
40154
|
+
if __cerefox_is_path "$trial"
|
|
40155
|
+
set path "$trial"
|
|
40156
|
+
set i (math $i + 1)
|
|
40157
|
+
else
|
|
40158
|
+
break
|
|
40159
|
+
end
|
|
40160
|
+
end
|
|
40161
|
+
string split ' ' -- (__cerefox_candidates "$path")
|
|
40162
|
+
end
|
|
40163
|
+
complete -c cerefox -f -a '(__cerefox_complete)'
|
|
40094
40164
|
`;
|
|
40095
40165
|
}
|
|
40096
|
-
function
|
|
40097
|
-
const
|
|
40098
|
-
let script;
|
|
40166
|
+
function scriptFor(shell) {
|
|
40167
|
+
const nodes = collectNodes();
|
|
40099
40168
|
switch (shell) {
|
|
40100
40169
|
case "bash":
|
|
40101
|
-
|
|
40102
|
-
break;
|
|
40170
|
+
return bashScript(nodes);
|
|
40103
40171
|
case "zsh":
|
|
40104
|
-
|
|
40105
|
-
break;
|
|
40172
|
+
return zshScript(nodes);
|
|
40106
40173
|
case "fish":
|
|
40107
|
-
|
|
40108
|
-
|
|
40109
|
-
|
|
40110
|
-
|
|
40174
|
+
return fishScript(nodes);
|
|
40175
|
+
}
|
|
40176
|
+
}
|
|
40177
|
+
function detectShell() {
|
|
40178
|
+
const sh = (process.env.SHELL ?? "").split("/").pop() ?? "";
|
|
40179
|
+
if (sh === "bash" || sh === "zsh" || sh === "fish")
|
|
40180
|
+
return sh;
|
|
40181
|
+
return null;
|
|
40182
|
+
}
|
|
40183
|
+
var RC_BEGIN = "# >>> cerefox shell completion (managed by `cerefox completion install`) >>>";
|
|
40184
|
+
var RC_END = "# <<< cerefox shell completion <<<";
|
|
40185
|
+
async function installMode(options) {
|
|
40186
|
+
const shell = options.shell ?? detectShell();
|
|
40187
|
+
if (!shell) {
|
|
40188
|
+
throw userError("Could not detect your shell from $SHELL. Pass --shell bash|zsh|fish.");
|
|
40189
|
+
}
|
|
40190
|
+
if (shell !== "bash" && shell !== "zsh" && shell !== "fish") {
|
|
40191
|
+
throw userError(`Unsupported --shell "${shell}". Use bash, zsh, or fish.`);
|
|
40192
|
+
}
|
|
40193
|
+
const home = homedir3();
|
|
40194
|
+
const scriptPath = join3(home, `.cerefox-completion.${shell}`);
|
|
40195
|
+
writeFileSync2(scriptPath, scriptFor(shell), "utf8");
|
|
40196
|
+
println(c.green(`✓ Wrote completion script: ${scriptPath}`));
|
|
40197
|
+
if (shell === "fish") {
|
|
40198
|
+
println(c.dim(" For fish, also copy it into ~/.config/fish/completions/cerefox.fish (or `source` it)."));
|
|
40199
|
+
return;
|
|
40200
|
+
}
|
|
40201
|
+
const rcPath = join3(home, shell === "zsh" ? ".zshrc" : ".bashrc");
|
|
40202
|
+
const sourceLine = `[ -s "${scriptPath}" ] && source "${scriptPath}"`;
|
|
40203
|
+
const block = `${RC_BEGIN}
|
|
40204
|
+
${sourceLine}
|
|
40205
|
+
${RC_END}
|
|
40206
|
+
`;
|
|
40207
|
+
const existing = existsSync3(rcPath) ? readFileSync3(rcPath, "utf8") : "";
|
|
40208
|
+
if (existing.includes(RC_BEGIN)) {
|
|
40209
|
+
println(c.dim(` ${rcPath} already sources the completion (left as-is).`));
|
|
40210
|
+
} else {
|
|
40211
|
+
const interactive = process.stdout.isTTY && !options.yes;
|
|
40212
|
+
if (interactive) {
|
|
40213
|
+
const ok2 = await confirm(`Add a completion source line to ${rcPath}?`, false);
|
|
40214
|
+
if (!ok2) {
|
|
40215
|
+
println(c.dim(`Skipped the rc edit. Add this line to ${rcPath} yourself:`));
|
|
40216
|
+
println(` ${sourceLine}`);
|
|
40217
|
+
return;
|
|
40218
|
+
}
|
|
40219
|
+
}
|
|
40220
|
+
writeFileSync2(rcPath, (existing.endsWith(`
|
|
40221
|
+
`) || existing === "" ? existing : existing + `
|
|
40222
|
+
`) + `
|
|
40223
|
+
` + block, "utf8");
|
|
40224
|
+
println(c.green(`✓ Added completion to ${rcPath}.`));
|
|
40225
|
+
}
|
|
40226
|
+
println(c.dim(` Activate now: exec ${shell} (or open a new terminal).`));
|
|
40227
|
+
}
|
|
40228
|
+
async function action2(target, options) {
|
|
40229
|
+
if (target === "install") {
|
|
40230
|
+
await installMode(options);
|
|
40231
|
+
return;
|
|
40232
|
+
}
|
|
40233
|
+
if (target !== "bash" && target !== "zsh" && target !== "fish") {
|
|
40234
|
+
throw userError(`Unknown shell "${target}". Supported: bash, zsh, fish (or 'install').`);
|
|
40235
|
+
}
|
|
40236
|
+
println(scriptFor(target));
|
|
40237
|
+
if (process.stdout.isTTY) {
|
|
40238
|
+
eprintln(c.dim(`
|
|
40239
|
+
# Tip: \`cerefox completion install\` writes this + wires your shell rc automatically.`));
|
|
40111
40240
|
}
|
|
40112
|
-
println(script);
|
|
40113
40241
|
}
|
|
40114
40242
|
function registerCompletion(program2) {
|
|
40115
|
-
program2.command("completion").description("
|
|
40243
|
+
program2.command("completion").description("Shell tab-completion. `install` to auto-wire your shell, or a shell name to print the script.").argument("<shell>", "bash | zsh | fish (print the script), or 'install' (auto-wire).").option("--shell <shell>", "For 'install': override the auto-detected shell.").option("--yes", "For 'install': skip the rc-edit confirmation (used by install.sh).").action(action2);
|
|
40116
40244
|
}
|
|
40117
40245
|
|
|
40118
40246
|
// src/cli/commands/config-get.ts
|
|
@@ -40145,10 +40273,41 @@ function registerConfigGet(program2) {
|
|
|
40145
40273
|
program2.command("config-get").description("Read a runtime config value from the cerefox_config table.").argument("<key>", "Config key (e.g. usage_tracking_enabled).").option("--json", "Emit JSON.").action(action3);
|
|
40146
40274
|
}
|
|
40147
40275
|
|
|
40276
|
+
// src/cli/commands/config-list.ts
|
|
40277
|
+
init_cli_core();
|
|
40278
|
+
var CONFIG_KEYS = [
|
|
40279
|
+
{
|
|
40280
|
+
key: "usage_tracking_enabled",
|
|
40281
|
+
description: "'true'/'false' — log reads + writes to cerefox_usage_log. Default off."
|
|
40282
|
+
},
|
|
40283
|
+
{
|
|
40284
|
+
key: "require_requestor_identity",
|
|
40285
|
+
description: "'true'/'false' — require requestor/author on MCP tool calls. Default off."
|
|
40286
|
+
},
|
|
40287
|
+
{
|
|
40288
|
+
key: "requestor_identity_format",
|
|
40289
|
+
description: "Regex the requestor/author must match (only enforced when the above is on)."
|
|
40290
|
+
}
|
|
40291
|
+
];
|
|
40292
|
+
function action4(options) {
|
|
40293
|
+
if (options.json) {
|
|
40294
|
+
printJson({ keys: CONFIG_KEYS.map((k) => k.key) });
|
|
40295
|
+
return;
|
|
40296
|
+
}
|
|
40297
|
+
println(c.bold("Runtime config keys (stored in cerefox_config; read with `cerefox config get <key>`):"));
|
|
40298
|
+
for (const { key, description } of CONFIG_KEYS) {
|
|
40299
|
+
println(` ${c.bold(key)}`);
|
|
40300
|
+
println(c.dim(` ${description}`));
|
|
40301
|
+
}
|
|
40302
|
+
}
|
|
40303
|
+
function registerConfigList(parent) {
|
|
40304
|
+
parent.command("list").description("List the runtime config keys (the cerefox_config allow-list; not values).").option("--json", "Emit the key list as JSON.").action(action4);
|
|
40305
|
+
}
|
|
40306
|
+
|
|
40148
40307
|
// src/cli/commands/config-set.ts
|
|
40149
40308
|
init_cli_core();
|
|
40150
40309
|
init_client();
|
|
40151
|
-
async function
|
|
40310
|
+
async function action5(key, value) {
|
|
40152
40311
|
const client = getClient();
|
|
40153
40312
|
try {
|
|
40154
40313
|
await client.rpc("cerefox_set_config", { p_key: key, p_value: value });
|
|
@@ -40159,7 +40318,7 @@ async function action4(key, value) {
|
|
|
40159
40318
|
println(c.green("✓ ") + `${key} = ${value}`);
|
|
40160
40319
|
}
|
|
40161
40320
|
function registerConfigSet(program2) {
|
|
40162
|
-
program2.command("config-set").description("Write a runtime config value into the cerefox_config table.").argument("<key>", "Config key.").argument("<value>", "Value to write.").action(
|
|
40321
|
+
program2.command("config-set").description("Write a runtime config value into the cerefox_config table.").argument("<key>", "Config key.").argument("<value>", "Value to write.").action(action5);
|
|
40163
40322
|
}
|
|
40164
40323
|
|
|
40165
40324
|
// src/cli/commands/configure-agent.ts
|
|
@@ -40168,13 +40327,13 @@ init_cli_core();
|
|
|
40168
40327
|
// src/cli/util/mcp-config-writers.ts
|
|
40169
40328
|
import {
|
|
40170
40329
|
copyFileSync,
|
|
40171
|
-
existsSync as
|
|
40330
|
+
existsSync as existsSync4,
|
|
40172
40331
|
mkdirSync as mkdirSync2,
|
|
40173
|
-
readFileSync as
|
|
40174
|
-
writeFileSync as
|
|
40332
|
+
readFileSync as readFileSync4,
|
|
40333
|
+
writeFileSync as writeFileSync3
|
|
40175
40334
|
} from "node:fs";
|
|
40176
|
-
import { homedir as
|
|
40177
|
-
import { dirname, join as
|
|
40335
|
+
import { homedir as homedir4, platform } from "node:os";
|
|
40336
|
+
import { dirname, join as join4 } from "node:path";
|
|
40178
40337
|
import { spawnSync } from "node:child_process";
|
|
40179
40338
|
|
|
40180
40339
|
// ../../node_modules/.bun/smol-toml@1.6.1/node_modules/smol-toml/dist/error.js
|
|
@@ -41276,17 +41435,17 @@ function defaultCerefoxEntry() {
|
|
|
41276
41435
|
};
|
|
41277
41436
|
}
|
|
41278
41437
|
function claudeCodeUserConfigPath() {
|
|
41279
|
-
return
|
|
41438
|
+
return join4(homedir4(), ".claude.json");
|
|
41280
41439
|
}
|
|
41281
41440
|
function claudeDesktopConfigPath() {
|
|
41282
|
-
const home =
|
|
41441
|
+
const home = homedir4();
|
|
41283
41442
|
if (platform() === "darwin") {
|
|
41284
|
-
return
|
|
41443
|
+
return join4(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
41285
41444
|
}
|
|
41286
41445
|
if (platform() === "win32") {
|
|
41287
|
-
return
|
|
41446
|
+
return join4(process.env.APPDATA ?? home, "Claude", "claude_desktop_config.json");
|
|
41288
41447
|
}
|
|
41289
|
-
return
|
|
41448
|
+
return join4(home, ".config", "Claude", "claude_desktop_config.json");
|
|
41290
41449
|
}
|
|
41291
41450
|
function claudeCodeDelegated() {
|
|
41292
41451
|
const entry = defaultCerefoxEntry();
|
|
@@ -41296,13 +41455,13 @@ function claudeCodeDelegated() {
|
|
|
41296
41455
|
};
|
|
41297
41456
|
}
|
|
41298
41457
|
function cursorConfigPath() {
|
|
41299
|
-
return
|
|
41458
|
+
return join4(homedir4(), ".cursor", "mcp.json");
|
|
41300
41459
|
}
|
|
41301
41460
|
function codexConfigPath() {
|
|
41302
|
-
return
|
|
41461
|
+
return join4(homedir4(), ".codex", "config.toml");
|
|
41303
41462
|
}
|
|
41304
41463
|
function geminiConfigPath() {
|
|
41305
|
-
return
|
|
41464
|
+
return join4(homedir4(), ".gemini", "settings.json");
|
|
41306
41465
|
}
|
|
41307
41466
|
var WRITERS = {
|
|
41308
41467
|
"claude-code": {
|
|
@@ -41360,15 +41519,15 @@ function directWrite(writer, configPath, opts) {
|
|
|
41360
41519
|
if (!opts.dryRun)
|
|
41361
41520
|
mkdirSync2(dirname(configPath), { recursive: true });
|
|
41362
41521
|
let existing = {};
|
|
41363
|
-
let
|
|
41522
|
+
let action6 = "created";
|
|
41364
41523
|
let backupPath = null;
|
|
41365
|
-
if (
|
|
41524
|
+
if (existsSync4(configPath)) {
|
|
41366
41525
|
try {
|
|
41367
|
-
const raw =
|
|
41526
|
+
const raw = readFileSync4(configPath, "utf8");
|
|
41368
41527
|
existing = format === "toml" ? parse(raw) : JSON.parse(raw);
|
|
41369
|
-
|
|
41528
|
+
action6 = hasCerefoxEntry(existing, format) ? "replaced" : "merged";
|
|
41370
41529
|
} catch {
|
|
41371
|
-
|
|
41530
|
+
action6 = "replaced";
|
|
41372
41531
|
}
|
|
41373
41532
|
if (!opts.noBackup && !opts.dryRun) {
|
|
41374
41533
|
backupPath = configPath + ".pre-cerefox.bak";
|
|
@@ -41383,9 +41542,9 @@ function directWrite(writer, configPath, opts) {
|
|
|
41383
41542
|
const body = format === "toml" ? stringify(existing) + `
|
|
41384
41543
|
` : JSON.stringify(existing, null, 2) + `
|
|
41385
41544
|
`;
|
|
41386
|
-
|
|
41545
|
+
writeFileSync3(configPath, body, "utf8");
|
|
41387
41546
|
}
|
|
41388
|
-
return { configPath, backupPath, action:
|
|
41547
|
+
return { configPath, backupPath, action: action6, serverEntry: entry };
|
|
41389
41548
|
}
|
|
41390
41549
|
function hasCerefoxEntry(existing, format) {
|
|
41391
41550
|
const key = format === "toml" ? "mcp_servers" : "mcpServers";
|
|
@@ -41409,7 +41568,7 @@ function delegatedWrite(writer, opts) {
|
|
|
41409
41568
|
};
|
|
41410
41569
|
}
|
|
41411
41570
|
let backupPath = null;
|
|
41412
|
-
if (!opts.noBackup &&
|
|
41571
|
+
if (!opts.noBackup && existsSync4(writer.configPath)) {
|
|
41413
41572
|
backupPath = writer.configPath + ".pre-cerefox.bak";
|
|
41414
41573
|
copyFileSync(writer.configPath, backupPath);
|
|
41415
41574
|
}
|
|
@@ -41434,7 +41593,7 @@ function delegatedWrite(writer, opts) {
|
|
|
41434
41593
|
}
|
|
41435
41594
|
|
|
41436
41595
|
// src/cli/commands/configure-agent.ts
|
|
41437
|
-
function
|
|
41596
|
+
function action6(options) {
|
|
41438
41597
|
const writer = WRITERS[options.tool];
|
|
41439
41598
|
if (!writer) {
|
|
41440
41599
|
throw userError(`Unknown --tool "${options.tool}".`, `Supported clients: ${Object.keys(WRITERS).join(", ")}.`);
|
|
@@ -41486,13 +41645,13 @@ function restartHint(id) {
|
|
|
41486
41645
|
}
|
|
41487
41646
|
}
|
|
41488
41647
|
function registerConfigureAgent(program2) {
|
|
41489
|
-
program2.command("configure-agent").description("Write the MCP server config for a supported client.").requiredOption("-t, --tool <client>", "Target client: claude-code, claude-desktop, cursor, codex, gemini.").option("--config-path <path>", "Override the default config-file path.").option("--no-backup", "Skip the .pre-cerefox.bak backup of any existing config.").option("--dry-run", "Print the planned write without modifying any file.").option("--json", "Emit JSON describing the result.").action(
|
|
41648
|
+
program2.command("configure-agent").description("Write the MCP server config for a supported client.").requiredOption("-t, --tool <client>", "Target client: claude-code, claude-desktop, cursor, codex, gemini.").option("--config-path <path>", "Override the default config-file path.").option("--no-backup", "Skip the .pre-cerefox.bak backup of any existing config.").option("--dry-run", "Print the planned write without modifying any file.").option("--json", "Emit JSON describing the result.").action(action6);
|
|
41490
41649
|
}
|
|
41491
41650
|
|
|
41492
41651
|
// src/cli/commands/delete-doc.ts
|
|
41493
41652
|
init_cli_core();
|
|
41494
41653
|
init_client();
|
|
41495
|
-
async function
|
|
41654
|
+
async function action7(documentId, options) {
|
|
41496
41655
|
const client = getClient();
|
|
41497
41656
|
const { data: doc, error } = await client.raw.from("cerefox_documents").select("id, title, total_chars, chunk_count, deleted_at").eq("id", documentId).maybeSingle();
|
|
41498
41657
|
if (error) {
|
|
@@ -41531,14 +41690,14 @@ async function action6(documentId, options) {
|
|
|
41531
41690
|
}
|
|
41532
41691
|
}
|
|
41533
41692
|
function registerDeleteDoc(program2) {
|
|
41534
|
-
program2.command("delete-doc").description("Soft-delete a document (recoverable via the web UI trash).").argument("<document-id>", "UUID of the document to delete.").option("--reason <text>", "Optional reason recorded in the audit log.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").option("--yes", "Skip the confirmation prompt.").action(
|
|
41693
|
+
program2.command("delete-doc").description("Soft-delete a document (recoverable via the web UI trash).").argument("<document-id>", "UUID of the document to delete.").option("--reason <text>", "Optional reason recorded in the audit log.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").option("--yes", "Skip the confirmation prompt.").action(action7);
|
|
41535
41694
|
}
|
|
41536
41695
|
|
|
41537
41696
|
// src/cli/commands/delete-project.ts
|
|
41538
41697
|
init_cli_core();
|
|
41539
41698
|
init_client();
|
|
41540
41699
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
41541
|
-
async function
|
|
41700
|
+
async function action8(target, options) {
|
|
41542
41701
|
const client = getClient();
|
|
41543
41702
|
const isUuid = UUID_RE.test(target);
|
|
41544
41703
|
const lookup = isUuid ? client.raw.from("cerefox_projects").select("id, name, description").eq("id", target).maybeSingle() : client.raw.from("cerefox_projects").select("id, name, description").eq("name", target).maybeSingle();
|
|
@@ -41574,19 +41733,19 @@ async function action7(target, options) {
|
|
|
41574
41733
|
println(c.green(`✓ Deleted project "${project.name}" (id: ${project.id}).`));
|
|
41575
41734
|
}
|
|
41576
41735
|
function registerDeleteProject(program2) {
|
|
41577
|
-
program2.command("delete-project").description("Delete an empty project (use --force to remove a non-empty one).").argument("<name-or-id>", "Project name (exact match) or UUID.").option("--yes", "Skip the confirmation prompt.").option("--force", "Allow deletion when documents are still linked to the project.").action(
|
|
41736
|
+
program2.command("delete-project").description("Delete an empty project (use --force to remove a non-empty one).").argument("<name-or-id>", "Project name (exact match) or UUID.").option("--yes", "Skip the confirmation prompt.").option("--force", "Allow deletion when documents are still linked to the project.").action(action8);
|
|
41578
41737
|
}
|
|
41579
41738
|
|
|
41580
41739
|
// src/cli/commands/deploy-server.ts
|
|
41581
41740
|
init_cli_core();
|
|
41582
41741
|
init_config();
|
|
41583
41742
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
41584
|
-
import { existsSync as
|
|
41743
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
41585
41744
|
import { readdirSync as readdirSync2 } from "node:fs";
|
|
41586
41745
|
|
|
41587
41746
|
// ../../_shared/server-assets/index.ts
|
|
41588
|
-
import { existsSync as
|
|
41589
|
-
import { dirname as dirname2, join as
|
|
41747
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
41748
|
+
import { dirname as dirname2, join as join5 } from "node:path";
|
|
41590
41749
|
import { fileURLToPath } from "node:url";
|
|
41591
41750
|
import { cwd as processCwd2 } from "node:process";
|
|
41592
41751
|
function moduleDir() {
|
|
@@ -41594,25 +41753,25 @@ function moduleDir() {
|
|
|
41594
41753
|
}
|
|
41595
41754
|
function bundledServerAssets(serverAssetsRoot) {
|
|
41596
41755
|
return {
|
|
41597
|
-
schemaFile:
|
|
41598
|
-
rpcsFile:
|
|
41599
|
-
migrationsDir:
|
|
41600
|
-
functionsDir:
|
|
41756
|
+
schemaFile: join5(serverAssetsRoot, "db", "schema.sql"),
|
|
41757
|
+
rpcsFile: join5(serverAssetsRoot, "db", "rpcs.sql"),
|
|
41758
|
+
migrationsDir: join5(serverAssetsRoot, "db", "migrations"),
|
|
41759
|
+
functionsDir: join5(serverAssetsRoot, "supabase", "functions"),
|
|
41601
41760
|
layout: "bundled"
|
|
41602
41761
|
};
|
|
41603
41762
|
}
|
|
41604
41763
|
function sourceServerAssets(repoRoot) {
|
|
41605
|
-
const dbDir =
|
|
41764
|
+
const dbDir = join5(repoRoot, "src", "cerefox", "db");
|
|
41606
41765
|
return {
|
|
41607
|
-
schemaFile:
|
|
41608
|
-
rpcsFile:
|
|
41609
|
-
migrationsDir:
|
|
41610
|
-
functionsDir:
|
|
41766
|
+
schemaFile: join5(dbDir, "schema.sql"),
|
|
41767
|
+
rpcsFile: join5(dbDir, "rpcs.sql"),
|
|
41768
|
+
migrationsDir: join5(dbDir, "migrations"),
|
|
41769
|
+
functionsDir: join5(repoRoot, "supabase", "functions"),
|
|
41611
41770
|
layout: "source"
|
|
41612
41771
|
};
|
|
41613
41772
|
}
|
|
41614
41773
|
function serverAssetsUsable(p) {
|
|
41615
|
-
return
|
|
41774
|
+
return existsSync5(p.schemaFile) && existsSync5(p.rpcsFile);
|
|
41616
41775
|
}
|
|
41617
41776
|
function resolveServerAssets(opts = {}) {
|
|
41618
41777
|
if (opts.assetsDir) {
|
|
@@ -41621,21 +41780,21 @@ function resolveServerAssets(opts = {}) {
|
|
|
41621
41780
|
const here = opts.moduleDirOverride ?? moduleDir();
|
|
41622
41781
|
const cwd = opts.cwd ?? processCwd2();
|
|
41623
41782
|
const candidates = [
|
|
41624
|
-
bundledServerAssets(
|
|
41625
|
-
sourceServerAssets(
|
|
41783
|
+
bundledServerAssets(join5(here, "..", "server-assets")),
|
|
41784
|
+
sourceServerAssets(join5(here, "..", "..")),
|
|
41626
41785
|
sourceServerAssets(cwd)
|
|
41627
41786
|
];
|
|
41628
41787
|
for (const candidate of candidates) {
|
|
41629
41788
|
if (serverAssetsUsable(candidate))
|
|
41630
41789
|
return candidate;
|
|
41631
41790
|
}
|
|
41632
|
-
return sourceServerAssets(
|
|
41791
|
+
return sourceServerAssets(join5(here, "..", ".."));
|
|
41633
41792
|
}
|
|
41634
41793
|
|
|
41635
41794
|
// ../../_shared/db-deploy/index.ts
|
|
41636
41795
|
init_src();
|
|
41637
|
-
import { existsSync as
|
|
41638
|
-
import { join as
|
|
41796
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync } from "node:fs";
|
|
41797
|
+
import { join as join6 } from "node:path";
|
|
41639
41798
|
var RESET_SQL = `
|
|
41640
41799
|
DROP TABLE IF EXISTS cerefox_chunks CASCADE;
|
|
41641
41800
|
DROP TABLE IF EXISTS cerefox_documents CASCADE;
|
|
@@ -41652,13 +41811,13 @@ CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
|
41652
41811
|
CREATE EXTENSION IF NOT EXISTS "vector";
|
|
41653
41812
|
`;
|
|
41654
41813
|
function listMigrationFiles(migrationsDir) {
|
|
41655
|
-
if (!
|
|
41814
|
+
if (!existsSync6(migrationsDir))
|
|
41656
41815
|
return [];
|
|
41657
41816
|
return readdirSync(migrationsDir).filter((n) => n.endsWith(".sql")).sort();
|
|
41658
41817
|
}
|
|
41659
41818
|
function buildDeploySteps(assets, opts = {}) {
|
|
41660
|
-
const schemaSql =
|
|
41661
|
-
const rpcsSql =
|
|
41819
|
+
const schemaSql = readFileSync5(assets.schemaFile, "utf8");
|
|
41820
|
+
const rpcsSql = readFileSync5(assets.rpcsFile, "utf8");
|
|
41662
41821
|
const steps = [];
|
|
41663
41822
|
if (opts.reset) {
|
|
41664
41823
|
steps.push({ label: "Reset: drop existing Cerefox objects", sql: RESET_SQL });
|
|
@@ -41751,7 +41910,7 @@ async function runDbMigrate(opts) {
|
|
|
41751
41910
|
}
|
|
41752
41911
|
const applied = [];
|
|
41753
41912
|
for (const f of pending) {
|
|
41754
|
-
const body =
|
|
41913
|
+
const body = readFileSync5(join6(opts.assets.migrationsDir, f), "utf8");
|
|
41755
41914
|
log(`Applying ${f}…`);
|
|
41756
41915
|
try {
|
|
41757
41916
|
await sql.begin(async (tx) => {
|
|
@@ -41779,7 +41938,7 @@ async function applyRpcs(opts) {
|
|
|
41779
41938
|
log("Refresh RPCs (rpcs.sql)…");
|
|
41780
41939
|
if (opts.dryRun)
|
|
41781
41940
|
return { ok: true };
|
|
41782
|
-
const rpcsSql =
|
|
41941
|
+
const rpcsSql = readFileSync5(opts.assets.rpcsFile, "utf8");
|
|
41783
41942
|
const sql = src_default(opts.dbUrl, { prepare: false, onnotice: () => {} });
|
|
41784
41943
|
try {
|
|
41785
41944
|
await sql.unsafe(rpcsSql);
|
|
@@ -41812,11 +41971,11 @@ function parseProjectRef(supabaseUrl) {
|
|
|
41812
41971
|
}
|
|
41813
41972
|
}
|
|
41814
41973
|
function listEdgeFunctions(functionsDir) {
|
|
41815
|
-
if (!
|
|
41974
|
+
if (!existsSync7(functionsDir))
|
|
41816
41975
|
return [];
|
|
41817
41976
|
return readdirSync2(functionsDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("cerefox-")).map((e) => e.name).sort();
|
|
41818
41977
|
}
|
|
41819
|
-
async function
|
|
41978
|
+
async function action9(options) {
|
|
41820
41979
|
const settings = loadSettings();
|
|
41821
41980
|
const assets = resolveServerAssets();
|
|
41822
41981
|
const doSchema = !options.functionsOnly;
|
|
@@ -41831,7 +41990,7 @@ async function action8(options) {
|
|
|
41831
41990
|
});
|
|
41832
41991
|
checks.push({
|
|
41833
41992
|
label: "Bundled schema assets present",
|
|
41834
|
-
ok:
|
|
41993
|
+
ok: existsSync7(assets.schemaFile) && existsSync7(assets.rpcsFile),
|
|
41835
41994
|
remediation: "Schema files not found. Reinstall the package, or run from a repo " + "clone (src/cerefox/db/)."
|
|
41836
41995
|
});
|
|
41837
41996
|
}
|
|
@@ -41999,13 +42158,89 @@ Proceed with deployment to Supabase?`, true);
|
|
|
41999
42158
|
println(c.dim("Verify with: cerefox doctor"));
|
|
42000
42159
|
}
|
|
42001
42160
|
function registerDeployServer(program2) {
|
|
42002
|
-
program2.command("deploy-server").description("Deploy/update the Cerefox server side (schema + RPCs + Edge Functions) on Supabase.").option("--dry-run", "Print the plan + pre-flight without deploying.").option("--schema-only", "Deploy/update only the schema + RPCs (skip Edge Functions).").option("--functions-only", "Deploy only the Edge Functions (skip the schema/RPCs).").option("--project-ref <ref>", "Supabase project ref for Edge Function deploys (default: derived from CEREFOX_SUPABASE_URL).").action(
|
|
42161
|
+
program2.command("deploy-server").description("Deploy/update the Cerefox server side (schema + RPCs + Edge Functions) on Supabase.").option("--dry-run", "Print the plan + pre-flight without deploying.").option("--schema-only", "Deploy/update only the schema + RPCs (skip Edge Functions).").option("--functions-only", "Deploy only the Edge Functions (skip the schema/RPCs).").option("--project-ref <ref>", "Supabase project ref for Edge Function deploys (default: derived from CEREFOX_SUPABASE_URL).").action(action9);
|
|
42162
|
+
}
|
|
42163
|
+
|
|
42164
|
+
// src/cli/commands/document-edit.ts
|
|
42165
|
+
init_cli_core();
|
|
42166
|
+
init_client();
|
|
42167
|
+
function parseMetaPair(pair) {
|
|
42168
|
+
const eq = pair.indexOf("=");
|
|
42169
|
+
if (eq <= 0)
|
|
42170
|
+
throw userError(`--set-meta expects key=value, got "${pair}".`);
|
|
42171
|
+
const key = pair.slice(0, eq).trim();
|
|
42172
|
+
const raw = pair.slice(eq + 1);
|
|
42173
|
+
let value = raw;
|
|
42174
|
+
try {
|
|
42175
|
+
value = JSON.parse(raw);
|
|
42176
|
+
} catch {
|
|
42177
|
+
value = raw;
|
|
42178
|
+
}
|
|
42179
|
+
return [key, value];
|
|
42180
|
+
}
|
|
42181
|
+
async function action10(documentId, options) {
|
|
42182
|
+
const hasTitle = options.title !== undefined;
|
|
42183
|
+
const sets = options.setMeta ?? [];
|
|
42184
|
+
const unsets = options.unsetMeta ?? [];
|
|
42185
|
+
if (!hasTitle && sets.length === 0 && unsets.length === 0) {
|
|
42186
|
+
throw userError("Nothing to edit — pass --title and/or --set-meta / --unset-meta.");
|
|
42187
|
+
}
|
|
42188
|
+
if (hasTitle && !options.title.trim())
|
|
42189
|
+
throw userError("--title cannot be empty.");
|
|
42190
|
+
const client = getClient();
|
|
42191
|
+
const { data: doc, error } = await client.raw.from("cerefox_documents").select("id, title, metadata, deleted_at").eq("id", documentId).maybeSingle();
|
|
42192
|
+
if (error)
|
|
42193
|
+
throw systemError(`Lookup failed: ${error.message}`);
|
|
42194
|
+
if (!doc)
|
|
42195
|
+
throw notFound(`Document ${documentId} not found.`);
|
|
42196
|
+
if (doc.deleted_at) {
|
|
42197
|
+
throw userError(`Document ${documentId} is soft-deleted — restore it first (cerefox document restore).`);
|
|
42198
|
+
}
|
|
42199
|
+
const metadata = { ...doc.metadata ?? {} };
|
|
42200
|
+
for (const pair of sets) {
|
|
42201
|
+
const [k, v] = parseMetaPair(pair);
|
|
42202
|
+
metadata[k] = v;
|
|
42203
|
+
}
|
|
42204
|
+
for (const k of unsets)
|
|
42205
|
+
delete metadata[k.trim()];
|
|
42206
|
+
const newTitle = hasTitle ? options.title.trim() : doc.title;
|
|
42207
|
+
const titleChanged = newTitle !== doc.title;
|
|
42208
|
+
const { error: updErr } = await client.raw.from("cerefox_documents").update({ title: newTitle, metadata, updated_at: new Date().toISOString() }).eq("id", documentId);
|
|
42209
|
+
if (updErr)
|
|
42210
|
+
throw systemError(`Update failed: ${updErr.message}`);
|
|
42211
|
+
if (titleChanged) {
|
|
42212
|
+
const { error: ftsErr } = await client.raw.rpc("cerefox_update_chunk_fts", {
|
|
42213
|
+
p_document_id: documentId,
|
|
42214
|
+
p_new_title: newTitle
|
|
42215
|
+
});
|
|
42216
|
+
if (ftsErr)
|
|
42217
|
+
throw systemError(`Title updated but FTS refresh failed: ${ftsErr.message}`);
|
|
42218
|
+
}
|
|
42219
|
+
const author = resolveAuthor(options.author);
|
|
42220
|
+
const authorType = resolveAuthorType(options.authorType);
|
|
42221
|
+
await client.raw.rpc("cerefox_create_audit_entry", {
|
|
42222
|
+
p_document_id: documentId,
|
|
42223
|
+
p_operation: "update-metadata",
|
|
42224
|
+
p_author: author,
|
|
42225
|
+
p_author_type: authorType,
|
|
42226
|
+
p_description: `Edited${titleChanged ? " title" : ""}` + (sets.length ? ` · set ${sets.length} meta key(s)` : "") + (unsets.length ? ` · unset ${unsets.length} meta key(s)` : "")
|
|
42227
|
+
});
|
|
42228
|
+
println(c.green(`✓ Edited "${newTitle}" (id: ${documentId}).`));
|
|
42229
|
+
if (titleChanged) {
|
|
42230
|
+
println(c.dim(" Title changed: FTS refreshed; semantic embeddings update on next `cerefox server reindex`."));
|
|
42231
|
+
}
|
|
42232
|
+
}
|
|
42233
|
+
function collect(value, prev) {
|
|
42234
|
+
return [...prev, value];
|
|
42235
|
+
}
|
|
42236
|
+
function registerDocumentEdit(parent) {
|
|
42237
|
+
parent.command("edit").description("Edit a document's title and/or metadata (non-destructive patch). Content edits: `document ingest --document-id <id> --update`.").argument("<document-id>", "UUID of the document.").option("--title <title>", "New title (refreshes FTS; re-embed on next reindex).").option("--set-meta <key=value>", "Set/overwrite a metadata key (repeatable). Value is JSON-parsed when possible.", collect, []).option("--unset-meta <key>", "Remove a metadata key (repeatable).", collect, []).option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(action10);
|
|
42003
42238
|
}
|
|
42004
42239
|
|
|
42005
42240
|
// src/cli/commands/document-restore.ts
|
|
42006
42241
|
init_cli_core();
|
|
42007
42242
|
init_client();
|
|
42008
|
-
async function
|
|
42243
|
+
async function action11(documentId, options) {
|
|
42009
42244
|
const client = getClient();
|
|
42010
42245
|
const { data: doc, error } = await client.raw.from("cerefox_documents").select("id, title, deleted_at").eq("id", documentId).maybeSingle();
|
|
42011
42246
|
if (error)
|
|
@@ -42029,7 +42264,103 @@ async function action9(documentId, options) {
|
|
|
42029
42264
|
println(c.green(`✓ Restored "${doc.title}" (id: ${documentId}) from the trash.`));
|
|
42030
42265
|
}
|
|
42031
42266
|
function registerDocumentRestore(parent) {
|
|
42032
|
-
parent.command("restore").description("Restore a soft-deleted document from the trash (inverse of `document delete`).").argument("<document-id>", "UUID of the soft-deleted document.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(
|
|
42267
|
+
parent.command("restore").description("Restore a soft-deleted document from the trash (inverse of `document delete`).").argument("<document-id>", "UUID of the soft-deleted document.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(action11);
|
|
42268
|
+
}
|
|
42269
|
+
|
|
42270
|
+
// src/cli/commands/guides.ts
|
|
42271
|
+
init_cli_core();
|
|
42272
|
+
init_bundled_docs();
|
|
42273
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
42274
|
+
function openInBrowser(path) {
|
|
42275
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
42276
|
+
const result = spawnSync3(cmd, [path], { stdio: "ignore" });
|
|
42277
|
+
if (result.status !== 0) {
|
|
42278
|
+
println(c.dim(`(could not auto-open; the file is at: ${path})`));
|
|
42279
|
+
}
|
|
42280
|
+
}
|
|
42281
|
+
function resolveDoc(topic) {
|
|
42282
|
+
const doc = readBundledDoc(topic);
|
|
42283
|
+
if (!doc) {
|
|
42284
|
+
throw notFound(`No bundled guide named "${topic}".`, "Run `cerefox guides list` to see available topics.");
|
|
42285
|
+
}
|
|
42286
|
+
return doc;
|
|
42287
|
+
}
|
|
42288
|
+
function listAction() {
|
|
42289
|
+
const docs = listBundledDocs();
|
|
42290
|
+
if (docs.length === 0) {
|
|
42291
|
+
println("(no bundled guides found)");
|
|
42292
|
+
return;
|
|
42293
|
+
}
|
|
42294
|
+
println(c.bold("Available guides:"));
|
|
42295
|
+
println("");
|
|
42296
|
+
printTable(docs.map((d) => ({ topic: d.topic, size_kb: Math.round(d.size / 1024) + " KB" })));
|
|
42297
|
+
println("");
|
|
42298
|
+
println(c.dim("Open with `cerefox guides open <topic>` (browser) or `cerefox guides show <topic>` (stdout)."));
|
|
42299
|
+
}
|
|
42300
|
+
function openAction(topic) {
|
|
42301
|
+
const doc = resolveDoc(topic);
|
|
42302
|
+
println(c.dim(`Opening ${doc.path} …`));
|
|
42303
|
+
openInBrowser(doc.path);
|
|
42304
|
+
}
|
|
42305
|
+
function showAction(topic) {
|
|
42306
|
+
println(resolveDoc(topic).content);
|
|
42307
|
+
}
|
|
42308
|
+
function registerGuides(parent) {
|
|
42309
|
+
parent.command("list").description("List the bundled documentation topics.").action(listAction);
|
|
42310
|
+
parent.command("open").description("Open a bundled guide in your browser.").argument("<topic>", "Topic (e.g. quickstart, connect-agents).").action(openAction);
|
|
42311
|
+
parent.command("show").description("Print a bundled guide to stdout.").argument("<topic>", "Topic (e.g. quickstart, connect-agents).").action(showAction);
|
|
42312
|
+
}
|
|
42313
|
+
|
|
42314
|
+
// src/cli/commands/project-create.ts
|
|
42315
|
+
init_cli_core();
|
|
42316
|
+
init_client();
|
|
42317
|
+
async function action12(name, options) {
|
|
42318
|
+
const trimmed = name.trim();
|
|
42319
|
+
if (!trimmed)
|
|
42320
|
+
throw userError("Project name is required.");
|
|
42321
|
+
const client = getClient();
|
|
42322
|
+
const { data, error } = await client.raw.from("cerefox_projects").insert({ name: trimmed, description: (options.description ?? "").trim() }).select("id, name, description").maybeSingle();
|
|
42323
|
+
if (error || !data) {
|
|
42324
|
+
throw systemError(`Create failed: ${error?.message ?? "no row returned"}`);
|
|
42325
|
+
}
|
|
42326
|
+
println(c.green(`✓ Created project "${data.name}" (id: ${data.id}).`));
|
|
42327
|
+
}
|
|
42328
|
+
function registerProjectCreate(parent) {
|
|
42329
|
+
parent.command("create").description("Create a new (empty) project.").argument("<name>", "Project name (must be unique).").option("--description <text>", "Optional project description.").action(action12);
|
|
42330
|
+
}
|
|
42331
|
+
|
|
42332
|
+
// src/cli/commands/project-edit.ts
|
|
42333
|
+
init_cli_core();
|
|
42334
|
+
init_client();
|
|
42335
|
+
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
42336
|
+
async function action13(target, options) {
|
|
42337
|
+
const update = {};
|
|
42338
|
+
if (options.name !== undefined) {
|
|
42339
|
+
const n = options.name.trim();
|
|
42340
|
+
if (!n)
|
|
42341
|
+
throw userError("--name cannot be empty.");
|
|
42342
|
+
update.name = n;
|
|
42343
|
+
}
|
|
42344
|
+
if (options.description !== undefined)
|
|
42345
|
+
update.description = options.description.trim();
|
|
42346
|
+
if (Object.keys(update).length === 0) {
|
|
42347
|
+
throw userError("Nothing to update — pass --name and/or --description.");
|
|
42348
|
+
}
|
|
42349
|
+
const client = getClient();
|
|
42350
|
+
const isUuid = UUID_RE2.test(target);
|
|
42351
|
+
const { data: project, error: lookupErr } = await client.raw.from("cerefox_projects").select("id, name").eq(isUuid ? "id" : "name", target).maybeSingle();
|
|
42352
|
+
if (lookupErr)
|
|
42353
|
+
throw systemError(`Lookup failed: ${lookupErr.message}`);
|
|
42354
|
+
if (!project)
|
|
42355
|
+
throw notFound(`Project "${target}" not found.`);
|
|
42356
|
+
const { data, error } = await client.raw.from("cerefox_projects").update(update).eq("id", project.id).select("id, name, description").maybeSingle();
|
|
42357
|
+
if (error || !data) {
|
|
42358
|
+
throw systemError(`Update failed: ${error?.message ?? "no row returned"}`);
|
|
42359
|
+
}
|
|
42360
|
+
println(c.green(`✓ Updated project "${data.name}" (id: ${data.id}).`));
|
|
42361
|
+
}
|
|
42362
|
+
function registerProjectEdit(parent) {
|
|
42363
|
+
parent.command("edit").description("Rename a project and/or change its description.").argument("<name-or-id>", "Project name (exact match) or UUID.").option("--name <new-name>", "New project name.").option("--description <text>", "New project description.").action(action13);
|
|
42033
42364
|
}
|
|
42034
42365
|
|
|
42035
42366
|
// src/cli/commands/version-archive.ts
|
|
@@ -42060,49 +42391,6 @@ function registerVersionArchive(parent) {
|
|
|
42060
42391
|
parent.command("unarchive").description("Unarchive a document version (allow version cleanup again).").argument("<version-id>", "UUID of the version (from `cerefox version list`).").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action((versionId, options) => setArchived(versionId, false, options));
|
|
42061
42392
|
}
|
|
42062
42393
|
|
|
42063
|
-
// src/cli/commands/docs.ts
|
|
42064
|
-
init_cli_core();
|
|
42065
|
-
init_bundled_docs();
|
|
42066
|
-
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
42067
|
-
function openInBrowser(path) {
|
|
42068
|
-
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
42069
|
-
const result = spawnSync3(cmd, [path], { stdio: "ignore" });
|
|
42070
|
-
if (result.status !== 0) {
|
|
42071
|
-
println(c.dim(`(could not auto-open; the file is at: ${path})`));
|
|
42072
|
-
}
|
|
42073
|
-
}
|
|
42074
|
-
function action10(topic, options) {
|
|
42075
|
-
const docs = listBundledDocs();
|
|
42076
|
-
if (options.list || !topic && !options.print) {
|
|
42077
|
-
if (docs.length === 0) {
|
|
42078
|
-
println("(no bundled docs found)");
|
|
42079
|
-
return;
|
|
42080
|
-
}
|
|
42081
|
-
println(c.bold("Available docs:"));
|
|
42082
|
-
println("");
|
|
42083
|
-
printTable(docs.map((d) => ({
|
|
42084
|
-
topic: d.topic,
|
|
42085
|
-
size_kb: Math.round(d.size / 1024) + " KB"
|
|
42086
|
-
})));
|
|
42087
|
-
println("");
|
|
42088
|
-
println(c.dim("Run `cerefox docs <topic>` to open in browser, or `--print` for stdout."));
|
|
42089
|
-
return;
|
|
42090
|
-
}
|
|
42091
|
-
const doc = topic ? readBundledDoc(topic) : null;
|
|
42092
|
-
if (!doc) {
|
|
42093
|
-
throw notFound(`No bundled doc named "${topic}".`, `Run \`cerefox docs --list\` to see available topics.`);
|
|
42094
|
-
}
|
|
42095
|
-
if (options.print) {
|
|
42096
|
-
println(doc.content);
|
|
42097
|
-
return;
|
|
42098
|
-
}
|
|
42099
|
-
println(c.dim(`Opening ${doc.path} …`));
|
|
42100
|
-
openInBrowser(doc.path);
|
|
42101
|
-
}
|
|
42102
|
-
function registerDocs(program2) {
|
|
42103
|
-
program2.command("docs").description("Open bundled Cerefox docs in your browser (or print to stdout).").argument("[topic]", "Doc topic (e.g. quickstart, connect-agents). Omit for the index.").option("--print", "Print to stdout instead of opening a browser.").option("--list", "List available topics.").action(action10);
|
|
42104
|
-
}
|
|
42105
|
-
|
|
42106
42394
|
// ../../node_modules/.bun/ora@9.4.0/node_modules/ora/index.js
|
|
42107
42395
|
import process8 from "node:process";
|
|
42108
42396
|
import { stripVTControlCharacters } from "node:util";
|
|
@@ -42897,13 +43185,13 @@ var restoreCursor = terminal ? onetime_default(() => {
|
|
|
42897
43185
|
var restore_cursor_default = restoreCursor;
|
|
42898
43186
|
|
|
42899
43187
|
// ../../node_modules/.bun/cli-cursor@5.0.0/node_modules/cli-cursor/index.js
|
|
42900
|
-
var
|
|
43188
|
+
var isHidden2 = false;
|
|
42901
43189
|
var cliCursor = {};
|
|
42902
43190
|
cliCursor.show = (writableStream = process5.stderr) => {
|
|
42903
43191
|
if (!writableStream.isTTY) {
|
|
42904
43192
|
return;
|
|
42905
43193
|
}
|
|
42906
|
-
|
|
43194
|
+
isHidden2 = false;
|
|
42907
43195
|
writableStream.write("\x1B[?25h");
|
|
42908
43196
|
};
|
|
42909
43197
|
cliCursor.hide = (writableStream = process5.stderr) => {
|
|
@@ -42911,14 +43199,14 @@ cliCursor.hide = (writableStream = process5.stderr) => {
|
|
|
42911
43199
|
return;
|
|
42912
43200
|
}
|
|
42913
43201
|
restore_cursor_default();
|
|
42914
|
-
|
|
43202
|
+
isHidden2 = true;
|
|
42915
43203
|
writableStream.write("\x1B[?25l");
|
|
42916
43204
|
};
|
|
42917
43205
|
cliCursor.toggle = (force, writableStream) => {
|
|
42918
43206
|
if (force !== undefined) {
|
|
42919
|
-
|
|
43207
|
+
isHidden2 = force;
|
|
42920
43208
|
}
|
|
42921
|
-
if (
|
|
43209
|
+
if (isHidden2) {
|
|
42922
43210
|
cliCursor.show(writableStream);
|
|
42923
43211
|
} else {
|
|
42924
43212
|
cliCursor.hide(writableStream);
|
|
@@ -45490,12 +45778,12 @@ init_cli_core();
|
|
|
45490
45778
|
|
|
45491
45779
|
// src/cli/util/checks.ts
|
|
45492
45780
|
init_meta();
|
|
45493
|
-
import { existsSync as
|
|
45494
|
-
import { homedir as
|
|
45495
|
-
import { join as
|
|
45781
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7, realpathSync, statSync as statSync2 } from "node:fs";
|
|
45782
|
+
import { homedir as homedir5 } from "node:os";
|
|
45783
|
+
import { join as join8 } from "node:path";
|
|
45496
45784
|
|
|
45497
45785
|
// ../../_shared/ef-meta/index.ts
|
|
45498
|
-
var EF_VERSION = "0.
|
|
45786
|
+
var EF_VERSION = "0.9.1";
|
|
45499
45787
|
|
|
45500
45788
|
// src/cli/util/checks.ts
|
|
45501
45789
|
init_config();
|
|
@@ -45646,7 +45934,7 @@ function checkConfig() {
|
|
|
45646
45934
|
hint: "Run `cerefox init` to bootstrap."
|
|
45647
45935
|
};
|
|
45648
45936
|
}
|
|
45649
|
-
if (!
|
|
45937
|
+
if (!existsSync9(envPath)) {
|
|
45650
45938
|
return {
|
|
45651
45939
|
name: "config",
|
|
45652
45940
|
status: "error",
|
|
@@ -45774,9 +46062,9 @@ var SCHEMA_VERSION_RE = /^--\s*@version:\s*(\S+)/m;
|
|
|
45774
46062
|
function readBundledSchemaVersion() {
|
|
45775
46063
|
try {
|
|
45776
46064
|
const assets = resolveServerAssets();
|
|
45777
|
-
if (!
|
|
46065
|
+
if (!existsSync9(assets.schemaFile))
|
|
45778
46066
|
return null;
|
|
45779
|
-
const m =
|
|
46067
|
+
const m = readFileSync7(assets.schemaFile, "utf8").match(SCHEMA_VERSION_RE);
|
|
45780
46068
|
return m ? m[1] : null;
|
|
45781
46069
|
} catch {
|
|
45782
46070
|
return null;
|
|
@@ -45845,10 +46133,10 @@ async function checkSchemaVersion() {
|
|
|
45845
46133
|
}
|
|
45846
46134
|
}
|
|
45847
46135
|
function hasCerefoxInJsonFile(path) {
|
|
45848
|
-
if (!
|
|
46136
|
+
if (!existsSync9(path))
|
|
45849
46137
|
return false;
|
|
45850
46138
|
try {
|
|
45851
|
-
const parsed = JSON.parse(
|
|
46139
|
+
const parsed = JSON.parse(readFileSync7(path, "utf8"));
|
|
45852
46140
|
const mcpServers = parsed.mcpServers;
|
|
45853
46141
|
return Boolean(mcpServers && typeof mcpServers === "object" && "cerefox" in mcpServers);
|
|
45854
46142
|
} catch {
|
|
@@ -45856,10 +46144,10 @@ function hasCerefoxInJsonFile(path) {
|
|
|
45856
46144
|
}
|
|
45857
46145
|
}
|
|
45858
46146
|
function checkMcpConfigs() {
|
|
45859
|
-
const home =
|
|
45860
|
-
const claudeCodeUser =
|
|
45861
|
-
const claudeCodeProj =
|
|
45862
|
-
const claudeDesktop = process.platform === "darwin" ?
|
|
46147
|
+
const home = homedir5();
|
|
46148
|
+
const claudeCodeUser = join8(home, ".claude.json");
|
|
46149
|
+
const claudeCodeProj = join8(process.cwd(), ".mcp.json");
|
|
46150
|
+
const claudeDesktop = process.platform === "darwin" ? join8(home, "Library", "Application Support", "Claude", "claude_desktop_config.json") : process.platform === "win32" ? join8(process.env.APPDATA ?? "", "Claude", "claude_desktop_config.json") : join8(home, ".config", "Claude", "claude_desktop_config.json");
|
|
45863
46151
|
const found = [];
|
|
45864
46152
|
if (hasCerefoxInJsonFile(claudeCodeUser))
|
|
45865
46153
|
found.push("Claude Code (user)");
|
|
@@ -45882,10 +46170,10 @@ function checkMcpConfigs() {
|
|
|
45882
46170
|
};
|
|
45883
46171
|
}
|
|
45884
46172
|
function checkLegacyShadowEnv() {
|
|
45885
|
-
const home =
|
|
45886
|
-
const homeEnv =
|
|
45887
|
-
const cwdEnv =
|
|
45888
|
-
if (!
|
|
46173
|
+
const home = homedir5();
|
|
46174
|
+
const homeEnv = join8(home, USER_STATE_DIR_NAME, ".env");
|
|
46175
|
+
const cwdEnv = join8(process.cwd(), ".env");
|
|
46176
|
+
if (!existsSync9(homeEnv) || !existsSync9(cwdEnv))
|
|
45889
46177
|
return null;
|
|
45890
46178
|
try {
|
|
45891
46179
|
if (realpathSync(homeEnv) === realpathSync(cwdEnv))
|
|
@@ -46060,7 +46348,7 @@ function symbol(status) {
|
|
|
46060
46348
|
return cErr.dim("ℹ");
|
|
46061
46349
|
}
|
|
46062
46350
|
}
|
|
46063
|
-
async function
|
|
46351
|
+
async function action14(options) {
|
|
46064
46352
|
const useSpinner = !options.json && process.stderr.isTTY;
|
|
46065
46353
|
const spinner = useSpinner ? ora({ text: "Starting checks…", spinner: "dots", stream: process.stderr }).start() : null;
|
|
46066
46354
|
const results = await runAllChecks({
|
|
@@ -46117,13 +46405,13 @@ async function action11(options) {
|
|
|
46117
46405
|
}
|
|
46118
46406
|
}
|
|
46119
46407
|
function registerDoctor(program2) {
|
|
46120
|
-
program2.command("doctor").description("Run diagnostic checks against the installed Cerefox.").option("--json", "Emit machine-readable JSON (no colours, structured output).").action(
|
|
46408
|
+
program2.command("doctor").description("Run diagnostic checks against the installed Cerefox.").option("--json", "Emit machine-readable JSON (no colours, structured output).").action(action14);
|
|
46121
46409
|
}
|
|
46122
46410
|
|
|
46123
46411
|
// src/cli/commands/get-audit-log.ts
|
|
46124
46412
|
init_cli_core();
|
|
46125
46413
|
init_client();
|
|
46126
|
-
async function
|
|
46414
|
+
async function action15(options) {
|
|
46127
46415
|
const limit = parsePositiveInt(options.limit, "--limit", 50);
|
|
46128
46416
|
const client = getClient();
|
|
46129
46417
|
const data = await client.rpc("cerefox_list_audit_entries", {
|
|
@@ -46161,14 +46449,14 @@ async function action12(options) {
|
|
|
46161
46449
|
})));
|
|
46162
46450
|
}
|
|
46163
46451
|
function registerGetAuditLog(program2) {
|
|
46164
|
-
program2.command("get-audit-log").description("Query the audit log with optional filters.").option("-d, --document-id <uuid>", "Filter by document.").option("-a, --author <name>", "Filter by author.").option("-o, --operation <type>", "Filter by operation: create, update-content, update-metadata, delete, restore.").option("--since <iso>", "Lower-bound ISO timestamp.").option("--until <iso>", "Upper-bound ISO timestamp.").option("-l, --limit <n>", "Maximum entries (max 200).", "50").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
46452
|
+
program2.command("get-audit-log").description("Query the audit log with optional filters.").option("-d, --document-id <uuid>", "Filter by document.").option("-a, --author <name>", "Filter by author.").option("-o, --operation <type>", "Filter by operation: create, update-content, update-metadata, delete, restore.").option("--since <iso>", "Lower-bound ISO timestamp.").option("--until <iso>", "Upper-bound ISO timestamp.").option("-l, --limit <n>", "Maximum entries (max 200).", "50").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action15);
|
|
46165
46453
|
}
|
|
46166
46454
|
|
|
46167
46455
|
// src/cli/commands/get-doc.ts
|
|
46168
46456
|
init_cli_core();
|
|
46169
46457
|
init_cli_core();
|
|
46170
46458
|
init_client();
|
|
46171
|
-
async function
|
|
46459
|
+
async function action16(documentId, options) {
|
|
46172
46460
|
const client = getClient();
|
|
46173
46461
|
const rows = await client.rpc("cerefox_get_document", {
|
|
46174
46462
|
p_document_id: documentId,
|
|
@@ -46198,18 +46486,18 @@ async function action13(documentId, options) {
|
|
|
46198
46486
|
println(doc.full_content);
|
|
46199
46487
|
}
|
|
46200
46488
|
function registerGetDoc(program2) {
|
|
46201
|
-
program2.command("get-doc").description("Retrieve the full content of a document by ID.").argument("<document-id>", "UUID of the document.").option("--version-id <uuid>", "Specific archived version (default: current).").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
46489
|
+
program2.command("get-doc").description("Retrieve the full content of a document by ID.").argument("<document-id>", "UUID of the document.").option("--version-id <uuid>", "Specific archived version (default: current).").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action16);
|
|
46202
46490
|
}
|
|
46203
46491
|
|
|
46204
46492
|
// src/cli/commands/ingest.ts
|
|
46205
46493
|
init_dist4();
|
|
46206
46494
|
init_cli_core();
|
|
46207
46495
|
init_config();
|
|
46208
|
-
import { readFileSync as
|
|
46496
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
46209
46497
|
import { basename as basename2, extname as extname2 } from "node:path";
|
|
46210
46498
|
|
|
46211
46499
|
// src/ingestion/pipeline.ts
|
|
46212
|
-
import { readFileSync as
|
|
46500
|
+
import { readFileSync as readFileSync8 } from "node:fs";
|
|
46213
46501
|
import { basename, extname, resolve as resolve3 } from "node:path";
|
|
46214
46502
|
|
|
46215
46503
|
// ../../_shared/ingest/chunker.ts
|
|
@@ -46893,7 +47181,7 @@ ${c2.content}`);
|
|
|
46893
47181
|
};
|
|
46894
47182
|
}
|
|
46895
47183
|
async ingestFile(path, opts = {}) {
|
|
46896
|
-
const text =
|
|
47184
|
+
const text = readFileSync8(path, "utf8");
|
|
46897
47185
|
const absPath = resolve3(path);
|
|
46898
47186
|
const stem = basename(absPath, extname(absPath));
|
|
46899
47187
|
return this.ingestText({
|
|
@@ -46927,7 +47215,7 @@ async function readContent(path, paste) {
|
|
|
46927
47215
|
}
|
|
46928
47216
|
let content;
|
|
46929
47217
|
try {
|
|
46930
|
-
content =
|
|
47218
|
+
content = readFileSync9(path, "utf8");
|
|
46931
47219
|
} catch (err) {
|
|
46932
47220
|
const msg = err instanceof Error ? err.message : String(err);
|
|
46933
47221
|
throw userError(`Cannot read ${path}: ${msg}`);
|
|
@@ -46935,7 +47223,7 @@ async function readContent(path, paste) {
|
|
|
46935
47223
|
const titleFromPath = basename2(path, extname2(path));
|
|
46936
47224
|
return { content, titleFromPath };
|
|
46937
47225
|
}
|
|
46938
|
-
async function
|
|
47226
|
+
async function action17(path, options) {
|
|
46939
47227
|
const { content, titleFromPath } = await readContent(path, Boolean(options.paste));
|
|
46940
47228
|
const title = options.title ?? titleFromPath;
|
|
46941
47229
|
if (!title || title.trim() === "") {
|
|
@@ -47007,7 +47295,7 @@ async function action14(path, options) {
|
|
|
47007
47295
|
}
|
|
47008
47296
|
}
|
|
47009
47297
|
function registerIngest(program2) {
|
|
47010
|
-
program2.command("ingest").description("Ingest a file (or stdin paste) into the knowledge base.").argument("[path]", "Path to the file to ingest. Omit when using --paste.").option("--paste", "Read content from stdin instead of a file.").option("-t, --title <title>", "Document title (required with --paste; defaults to filename without extension).").option("-p, --project-name <name>", "Single project membership (non-destructive on update).").option("-P, --project-names <names>", "Comma-separated full project membership set (destructive replace on update).").option("-m, --metadata <json>", "JSON metadata object.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-i, --document-id <uuid>", "Update a specific document by UUID (overrides --update-if-exists).").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(
|
|
47298
|
+
program2.command("ingest").description("Ingest a file (or stdin paste) into the knowledge base.").argument("[path]", "Path to the file to ingest. Omit when using --paste.").option("--paste", "Read content from stdin instead of a file.").option("-t, --title <title>", "Document title (required with --paste; defaults to filename without extension).").option("-p, --project-name <name>", "Single project membership (non-destructive on update).").option("-P, --project-names <names>", "Comma-separated full project membership set (destructive replace on update).").option("-m, --metadata <json>", "JSON metadata object.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-i, --document-id <uuid>", "Update a specific document by UUID (overrides --update-if-exists).").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(action17);
|
|
47011
47299
|
}
|
|
47012
47300
|
|
|
47013
47301
|
// src/cli/commands/ingest-dir.ts
|
|
@@ -47016,7 +47304,7 @@ init_cli_core();
|
|
|
47016
47304
|
init_config();
|
|
47017
47305
|
var import_cli_progress = __toESM(require_cli_progress(), 1);
|
|
47018
47306
|
import { readdirSync as readdirSync4, statSync as statSync3 } from "node:fs";
|
|
47019
|
-
import { basename as basename3, extname as extname3, join as
|
|
47307
|
+
import { basename as basename3, extname as extname3, join as join9 } from "node:path";
|
|
47020
47308
|
function walk(dir, extensions) {
|
|
47021
47309
|
let entries;
|
|
47022
47310
|
try {
|
|
@@ -47026,7 +47314,7 @@ function walk(dir, extensions) {
|
|
|
47026
47314
|
}
|
|
47027
47315
|
const files = [];
|
|
47028
47316
|
for (const name of entries) {
|
|
47029
|
-
const full =
|
|
47317
|
+
const full = join9(dir, name);
|
|
47030
47318
|
let stat;
|
|
47031
47319
|
try {
|
|
47032
47320
|
stat = statSync3(full);
|
|
@@ -47043,7 +47331,7 @@ function walk(dir, extensions) {
|
|
|
47043
47331
|
}
|
|
47044
47332
|
return files;
|
|
47045
47333
|
}
|
|
47046
|
-
async function
|
|
47334
|
+
async function action18(dir, options) {
|
|
47047
47335
|
const extensions = new Set((options.extensions ?? ".md,.txt").split(",").map((e) => e.trim().toLowerCase()).map((e) => e.startsWith(".") ? e : "." + e).filter((e) => e.length > 0));
|
|
47048
47336
|
const files = walk(dir, extensions);
|
|
47049
47337
|
if (files.length === 0) {
|
|
@@ -47116,7 +47404,7 @@ async function action15(dir, options) {
|
|
|
47116
47404
|
}
|
|
47117
47405
|
}
|
|
47118
47406
|
function registerIngestDir(program2) {
|
|
47119
|
-
program2.command("ingest-dir").description("Recursively ingest a directory of markdown / text files.").argument("<dir>", "Root directory to walk.").option("-p, --project-name <name>", "Project membership for all ingested docs.").option("-m, --metadata <json>", "JSON metadata applied to every doc.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").option("-e, --extensions <list>", "Comma-separated file extensions to ingest.", ".md,.txt").action(
|
|
47407
|
+
program2.command("ingest-dir").description("Recursively ingest a directory of markdown / text files.").argument("<dir>", "Root directory to walk.").option("-p, --project-name <name>", "Project membership for all ingested docs.").option("-m, --metadata <json>", "JSON metadata applied to every doc.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").option("-e, --extensions <list>", "Comma-separated file extensions to ingest.", ".md,.txt").action(action18);
|
|
47120
47408
|
}
|
|
47121
47409
|
|
|
47122
47410
|
// src/cli/commands/init.ts
|
|
@@ -47126,20 +47414,20 @@ import { spawnSync as spawnSync4 } from "node:child_process";
|
|
|
47126
47414
|
import {
|
|
47127
47415
|
chmodSync,
|
|
47128
47416
|
copyFileSync as copyFileSync2,
|
|
47129
|
-
existsSync as
|
|
47417
|
+
existsSync as existsSync10,
|
|
47130
47418
|
mkdirSync as mkdirSync3,
|
|
47131
|
-
readFileSync as
|
|
47132
|
-
writeFileSync as
|
|
47419
|
+
readFileSync as readFileSync11,
|
|
47420
|
+
writeFileSync as writeFileSync4
|
|
47133
47421
|
} from "node:fs";
|
|
47134
|
-
import { homedir as
|
|
47135
|
-
import { dirname as dirname4, join as
|
|
47422
|
+
import { homedir as homedir6 } from "node:os";
|
|
47423
|
+
import { dirname as dirname4, join as join10 } from "node:path";
|
|
47136
47424
|
async function readConfigFile(path) {
|
|
47137
|
-
if (!
|
|
47425
|
+
if (!existsSync10(path)) {
|
|
47138
47426
|
throw userError(`--config file not found: ${path}`);
|
|
47139
47427
|
}
|
|
47140
47428
|
let parsed;
|
|
47141
47429
|
try {
|
|
47142
|
-
parsed = JSON.parse(
|
|
47430
|
+
parsed = JSON.parse(readFileSync11(path, "utf8"));
|
|
47143
47431
|
} catch (err) {
|
|
47144
47432
|
throw userError(`--config: invalid JSON in ${path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
47145
47433
|
}
|
|
@@ -47181,7 +47469,7 @@ function parseDotEnvFile(content) {
|
|
|
47181
47469
|
return map;
|
|
47182
47470
|
}
|
|
47183
47471
|
function answersFromEnvFile(path) {
|
|
47184
|
-
const parsed = parseDotEnvFile(
|
|
47472
|
+
const parsed = parseDotEnvFile(readFileSync11(path, "utf8"));
|
|
47185
47473
|
const required = ["CEREFOX_SUPABASE_URL", "CEREFOX_SUPABASE_KEY", "OPENAI_API_KEY"];
|
|
47186
47474
|
for (const key of required) {
|
|
47187
47475
|
if (!parsed[key] || parsed[key].trim() === "") {
|
|
@@ -47437,7 +47725,7 @@ async function postWriteLifecycle(envPath, options) {
|
|
|
47437
47725
|
}
|
|
47438
47726
|
function writeAnswersTo(target, answers) {
|
|
47439
47727
|
mkdirSync3(dirname4(target), { recursive: true });
|
|
47440
|
-
|
|
47728
|
+
writeFileSync4(target, buildEnvFile(answers), "utf8");
|
|
47441
47729
|
if (process.platform !== "win32") {
|
|
47442
47730
|
try {
|
|
47443
47731
|
chmodSync(target, 384);
|
|
@@ -47446,13 +47734,13 @@ function writeAnswersTo(target, answers) {
|
|
|
47446
47734
|
}
|
|
47447
47735
|
}
|
|
47448
47736
|
}
|
|
47449
|
-
async function
|
|
47450
|
-
const homeEnv =
|
|
47451
|
-
const cwdEnv =
|
|
47737
|
+
async function action20(options) {
|
|
47738
|
+
const homeEnv = join10(homedir6(), USER_STATE_DIR_NAME, ".env");
|
|
47739
|
+
const cwdEnv = join10(process.cwd(), ".env");
|
|
47452
47740
|
const explicitDir = (process.env.CEREFOX_CONFIG_DIR ?? "").trim();
|
|
47453
47741
|
if (explicitDir) {
|
|
47454
47742
|
const target2 = resolveEnvFile();
|
|
47455
|
-
if (
|
|
47743
|
+
if (existsSync10(target2) && !options.force) {
|
|
47456
47744
|
println(c.yellow(`⚠ Config already exists at ${target2}.`));
|
|
47457
47745
|
const ok2 = await confirm("Overwrite?", true);
|
|
47458
47746
|
if (!ok2) {
|
|
@@ -47474,7 +47762,7 @@ async function action17(options) {
|
|
|
47474
47762
|
await postWriteLifecycle(target2, options);
|
|
47475
47763
|
return;
|
|
47476
47764
|
}
|
|
47477
|
-
if (
|
|
47765
|
+
if (existsSync10(homeEnv) && !options.force) {
|
|
47478
47766
|
println(c.yellow(`⚠ Config already exists at ${homeEnv}.`));
|
|
47479
47767
|
const ok2 = await confirm("Overwrite?", true);
|
|
47480
47768
|
if (!ok2) {
|
|
@@ -47495,7 +47783,7 @@ async function action17(options) {
|
|
|
47495
47783
|
await postWriteLifecycle(homeEnv, options);
|
|
47496
47784
|
return;
|
|
47497
47785
|
}
|
|
47498
|
-
if (
|
|
47786
|
+
if (existsSync10(cwdEnv) && !options.force && !options.config) {
|
|
47499
47787
|
printMigrationMenu(cwdEnv, homeEnv);
|
|
47500
47788
|
const ch = await promptMigrationChoice();
|
|
47501
47789
|
println("");
|
|
@@ -47555,13 +47843,13 @@ async function action17(options) {
|
|
|
47555
47843
|
await postWriteLifecycle(target, options);
|
|
47556
47844
|
}
|
|
47557
47845
|
function registerInit(program2) {
|
|
47558
|
-
program2.command("init").description("Interactive first-run setup (config, schema deploy stub, optional MCP wiring).").option("-c, --config <file>", "Non-interactive mode: read answers from a JSON file.").option("--force", "Overwrite existing configuration without prompting.").option("--skip-schema", "Skip the schema deploy step.").option("--skip-self-docs", "Skip the bundled self-doc ingest.").option("--skip-agent-config", "Skip the optional MCP agent wiring.").action(
|
|
47846
|
+
program2.command("init").description("Interactive first-run setup (config, schema deploy stub, optional MCP wiring).").option("-c, --config <file>", "Non-interactive mode: read answers from a JSON file.").option("--force", "Overwrite existing configuration without prompting.").option("--skip-schema", "Skip the schema deploy step.").option("--skip-self-docs", "Skip the bundled self-doc ingest.").option("--skip-agent-config", "Skip the optional MCP agent wiring.").action(action20);
|
|
47559
47847
|
}
|
|
47560
47848
|
|
|
47561
47849
|
// src/cli/commands/list-docs.ts
|
|
47562
47850
|
init_cli_core();
|
|
47563
47851
|
init_client();
|
|
47564
|
-
async function
|
|
47852
|
+
async function action21(options) {
|
|
47565
47853
|
const limit = parsePositiveInt(options.limit, "--limit", 100);
|
|
47566
47854
|
const client = getClient();
|
|
47567
47855
|
let projectId;
|
|
@@ -47616,13 +47904,13 @@ async function action18(options) {
|
|
|
47616
47904
|
})));
|
|
47617
47905
|
}
|
|
47618
47906
|
function registerListDocs(program2) {
|
|
47619
|
-
program2.command("list-docs").description("List documents in the knowledge base.").option("-p, --project <name>", "Filter to a specific project.").option("-l, --limit <n>", "Maximum docs to return.", "100").option("--json", "Emit machine-readable JSON.").action(
|
|
47907
|
+
program2.command("list-docs").description("List documents in the knowledge base.").option("-p, --project <name>", "Filter to a specific project.").option("-l, --limit <n>", "Maximum docs to return.", "100").option("--json", "Emit machine-readable JSON.").action(action21);
|
|
47620
47908
|
}
|
|
47621
47909
|
|
|
47622
47910
|
// src/cli/commands/list-metadata-keys.ts
|
|
47623
47911
|
init_cli_core();
|
|
47624
47912
|
init_client();
|
|
47625
|
-
async function
|
|
47913
|
+
async function action22(options) {
|
|
47626
47914
|
const client = getClient();
|
|
47627
47915
|
const data = await client.rpc("cerefox_list_metadata_keys");
|
|
47628
47916
|
if (data === null) {
|
|
@@ -47650,13 +47938,13 @@ async function action19(options) {
|
|
|
47650
47938
|
})));
|
|
47651
47939
|
}
|
|
47652
47940
|
function registerListMetadataKeys(program2) {
|
|
47653
|
-
program2.command("list-metadata-keys").description("List all metadata keys with document counts and example values.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
47941
|
+
program2.command("list-metadata-keys").description("List all metadata keys with document counts and example values.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action22);
|
|
47654
47942
|
}
|
|
47655
47943
|
|
|
47656
47944
|
// src/cli/commands/list-projects.ts
|
|
47657
47945
|
init_cli_core();
|
|
47658
47946
|
init_client();
|
|
47659
|
-
async function
|
|
47947
|
+
async function action23(options) {
|
|
47660
47948
|
const client = getClient();
|
|
47661
47949
|
const { data, error: error2 } = await client.raw.from("cerefox_projects").select("id, name, description, created_at").order("name", { ascending: true });
|
|
47662
47950
|
if (error2) {
|
|
@@ -47685,13 +47973,13 @@ async function action20(options) {
|
|
|
47685
47973
|
})), "(no projects)");
|
|
47686
47974
|
}
|
|
47687
47975
|
function registerListProjects(program2) {
|
|
47688
|
-
program2.command("list-projects").description("List all projects in the knowledge base.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
47976
|
+
program2.command("list-projects").description("List all projects in the knowledge base.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action23);
|
|
47689
47977
|
}
|
|
47690
47978
|
|
|
47691
47979
|
// src/cli/commands/list-versions.ts
|
|
47692
47980
|
init_cli_core();
|
|
47693
47981
|
init_client();
|
|
47694
|
-
async function
|
|
47982
|
+
async function action24(documentId, options) {
|
|
47695
47983
|
const client = getClient();
|
|
47696
47984
|
const data = await client.rpc("cerefox_list_document_versions", {
|
|
47697
47985
|
p_document_id: documentId
|
|
@@ -47732,7 +48020,7 @@ async function action21(documentId, options) {
|
|
|
47732
48020
|
})));
|
|
47733
48021
|
}
|
|
47734
48022
|
function registerListVersions(program2) {
|
|
47735
|
-
program2.command("list-versions").description("List archived versions of a document.").argument("<document-id>", "UUID of the document.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
48023
|
+
program2.command("list-versions").description("List archived versions of a document.").argument("<document-id>", "UUID of the document.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action24);
|
|
47736
48024
|
}
|
|
47737
48025
|
|
|
47738
48026
|
// src/cli/commands/mcp.ts
|
|
@@ -47747,7 +48035,7 @@ function registerMcp(program2) {
|
|
|
47747
48035
|
// src/cli/commands/metadata-search.ts
|
|
47748
48036
|
init_cli_core();
|
|
47749
48037
|
init_client();
|
|
47750
|
-
async function
|
|
48038
|
+
async function action25(options) {
|
|
47751
48039
|
const metadataFilter = parseJsonObjectArg(options.metadataFilter, "--metadata-filter");
|
|
47752
48040
|
if (!metadataFilter || Object.keys(metadataFilter).length === 0) {
|
|
47753
48041
|
throw userError("--metadata-filter is required and must be a non-empty JSON object.", `Example: --metadata-filter '{"type":"decision-log"}'.`);
|
|
@@ -47810,7 +48098,7 @@ async function action22(options) {
|
|
|
47810
48098
|
}
|
|
47811
48099
|
}
|
|
47812
48100
|
function registerMetadataSearch(program2) {
|
|
47813
|
-
program2.command("metadata-search").description("Find documents by metadata criteria (no text query).").requiredOption("-f, --metadata-filter <json>", "JSON object; only docs whose metadata contains ALL pairs are returned.").option("-p, --project-name <name>", "Filter to a specific project.").option("--updated-since <iso>", "Only docs updated on/after this ISO timestamp.").option("--created-since <iso>", "Only docs created on/after this ISO timestamp.").option("--include-content", "Include full document text in results.").option("-l, --limit <n>", "Maximum docs to return.", "10").option("--max-bytes <n>", "Response size budget in bytes (with --include-content).", "200000").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
48101
|
+
program2.command("metadata-search").description("Find documents by metadata criteria (no text query).").requiredOption("-f, --metadata-filter <json>", "JSON object; only docs whose metadata contains ALL pairs are returned.").option("-p, --project-name <name>", "Filter to a specific project.").option("--updated-since <iso>", "Only docs updated on/after this ISO timestamp.").option("--created-since <iso>", "Only docs created on/after this ISO timestamp.").option("--include-content", "Include full document text in results.").option("-l, --limit <n>", "Maximum docs to return.", "10").option("--max-bytes <n>", "Response size budget in bytes (with --include-content).", "200000").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action25);
|
|
47814
48102
|
}
|
|
47815
48103
|
|
|
47816
48104
|
// src/cli/commands/reindex.ts
|
|
@@ -47818,7 +48106,7 @@ init_dist4();
|
|
|
47818
48106
|
init_cli_core();
|
|
47819
48107
|
init_config();
|
|
47820
48108
|
var DEFAULT_MODEL = "text-embedding-3-small";
|
|
47821
|
-
async function
|
|
48109
|
+
async function action26(options) {
|
|
47822
48110
|
const settings = loadSettings();
|
|
47823
48111
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
47824
48112
|
throw userError("Supabase credentials not configured — run `cerefox init` first.");
|
|
@@ -47897,41 +48185,41 @@ ${c2.content}`;
|
|
|
47897
48185
|
}
|
|
47898
48186
|
}
|
|
47899
48187
|
function registerReindex(program2) {
|
|
47900
|
-
program2.command("reindex").description("Re-embed existing document chunks (v0.7+).").option("--all", "Reindex every chunk regardless of embedder.").option("--batch <n>", "Chunks per OpenAI batch call. Capped at 96 internally.", "32").option("--dry-run", "Show counts without re-embedding.").option("-i, --document-id <uuid>", "Limit reindex to a single document.").action(
|
|
48188
|
+
program2.command("reindex").description("Re-embed existing document chunks (v0.7+).").option("--all", "Reindex every chunk regardless of embedder.").option("--batch <n>", "Chunks per OpenAI batch call. Capped at 96 internally.", "32").option("--dry-run", "Show counts without re-embedding.").option("-i, --document-id <uuid>", "Limit reindex to a single document.").action(action26);
|
|
47901
48189
|
}
|
|
47902
48190
|
|
|
47903
48191
|
// src/cli/commands/restore.ts
|
|
47904
48192
|
init_cli_core();
|
|
47905
48193
|
init_client();
|
|
47906
|
-
import { existsSync as
|
|
47907
|
-
import { homedir as
|
|
47908
|
-
import { join as
|
|
48194
|
+
import { existsSync as existsSync11, readFileSync as readFileSync12, readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
|
|
48195
|
+
import { homedir as homedir7 } from "node:os";
|
|
48196
|
+
import { join as join11, resolve as resolve4 } from "node:path";
|
|
47909
48197
|
function expandHome2(path) {
|
|
47910
48198
|
if (path === "~")
|
|
47911
|
-
return
|
|
48199
|
+
return homedir7();
|
|
47912
48200
|
if (path.startsWith("~/"))
|
|
47913
|
-
return
|
|
48201
|
+
return join11(homedir7(), path.slice(2));
|
|
47914
48202
|
return path;
|
|
47915
48203
|
}
|
|
47916
48204
|
function resolveBackupFile(target) {
|
|
47917
48205
|
const path = resolve4(expandHome2(target));
|
|
47918
|
-
if (!
|
|
48206
|
+
if (!existsSync11(path)) {
|
|
47919
48207
|
throw userError(`Backup path not found: ${target}`);
|
|
47920
48208
|
}
|
|
47921
48209
|
const stat = statSync4(path);
|
|
47922
48210
|
if (stat.isFile())
|
|
47923
48211
|
return path;
|
|
47924
|
-
const candidates = readdirSync5(path).filter((n) => n.endsWith(".json") && n.startsWith("cerefox-")).map((n) => ({ name: n, mtime: statSync4(
|
|
48212
|
+
const candidates = readdirSync5(path).filter((n) => n.endsWith(".json") && n.startsWith("cerefox-")).map((n) => ({ name: n, mtime: statSync4(join11(path, n)).mtimeMs })).sort((a, b2) => b2.mtime - a.mtime);
|
|
47925
48213
|
if (candidates.length === 0) {
|
|
47926
48214
|
throw userError(`No cerefox-*.json files in ${path}`);
|
|
47927
48215
|
}
|
|
47928
|
-
return
|
|
48216
|
+
return join11(path, candidates[0].name);
|
|
47929
48217
|
}
|
|
47930
|
-
async function
|
|
48218
|
+
async function action27(target, options) {
|
|
47931
48219
|
const file = resolveBackupFile(target);
|
|
47932
48220
|
let payload;
|
|
47933
48221
|
try {
|
|
47934
|
-
payload = JSON.parse(
|
|
48222
|
+
payload = JSON.parse(readFileSync12(file, "utf8"));
|
|
47935
48223
|
} catch (err) {
|
|
47936
48224
|
throw userError(`Could not parse backup file ${file}: ${err instanceof Error ? err.message : String(err)}`);
|
|
47937
48225
|
}
|
|
@@ -47983,7 +48271,7 @@ async function action24(target, options) {
|
|
|
47983
48271
|
}
|
|
47984
48272
|
}
|
|
47985
48273
|
function registerRestore(program2) {
|
|
47986
|
-
program2.command("restore").description("Restore a JSON-snapshot backup into the knowledge base.").argument("<snapshot>", "Backup file (or directory; most recent is picked) produced by `cerefox backup`.").option("--dry-run", "Print what would be restored without writing.").option("-p, --project-name <name>", "Reserved for future use; currently ignored (project memberships ride along with each doc's metadata).").action(
|
|
48274
|
+
program2.command("restore").description("Restore a JSON-snapshot backup into the knowledge base.").argument("<snapshot>", "Backup file (or directory; most recent is picked) produced by `cerefox backup`.").option("--dry-run", "Print what would be restored without writing.").option("-p, --project-name <name>", "Reserved for future use; currently ignored (project memberships ride along with each doc's metadata).").action(action27);
|
|
47987
48275
|
}
|
|
47988
48276
|
|
|
47989
48277
|
// src/cli/commands/search.ts
|
|
@@ -48008,7 +48296,7 @@ async function embedQuery(query) {
|
|
|
48008
48296
|
}
|
|
48009
48297
|
|
|
48010
48298
|
// src/cli/commands/search.ts
|
|
48011
|
-
async function
|
|
48299
|
+
async function action28(query, options) {
|
|
48012
48300
|
if (!query || query.trim() === "") {
|
|
48013
48301
|
throw userError("Empty query.");
|
|
48014
48302
|
}
|
|
@@ -48097,8 +48385,14 @@ async function action25(query, options) {
|
|
|
48097
48385
|
p_result_count: accepted.length
|
|
48098
48386
|
}).then(() => {}, () => {});
|
|
48099
48387
|
if (options.json) {
|
|
48388
|
+
const jsonResults = options.onlyMetadata ? accepted.map((r) => {
|
|
48389
|
+
const copy = { ...r };
|
|
48390
|
+
delete copy.full_content;
|
|
48391
|
+
delete copy.content;
|
|
48392
|
+
return copy;
|
|
48393
|
+
}) : accepted;
|
|
48100
48394
|
printJson({
|
|
48101
|
-
results:
|
|
48395
|
+
results: jsonResults,
|
|
48102
48396
|
query,
|
|
48103
48397
|
mode,
|
|
48104
48398
|
match_count: matchCount,
|
|
@@ -48118,13 +48412,25 @@ async function action25(query, options) {
|
|
|
48118
48412
|
const doc2 = row;
|
|
48119
48413
|
const title = doc2.doc_title ?? "Untitled";
|
|
48120
48414
|
const docId = doc2.document_id ? ` [id: ${doc2.document_id}]` : "";
|
|
48121
|
-
const score = doc2.best_score != null ? `
|
|
48122
|
-
const
|
|
48123
|
-
|
|
48415
|
+
const score = doc2.best_score != null ? ` · score ${doc2.best_score.toFixed(3)}` : "";
|
|
48416
|
+
const counts = ` · ${doc2.chunk_count} chunk${doc2.chunk_count === 1 ? "" : "s"} · ${doc2.total_chars.toLocaleString()} chars`;
|
|
48417
|
+
const kind = doc2.is_partial ? " · partial" : " · full";
|
|
48418
|
+
println(c.bold(`## ${title}${docId}${score}${counts}${kind}`));
|
|
48419
|
+
const bestMatch = doc2.best_chunk_heading_path?.length ? doc2.best_chunk_heading_path.join(" › ") : null;
|
|
48420
|
+
const updated = doc2.doc_updated_at ? doc2.doc_updated_at.slice(0, 10) : null;
|
|
48421
|
+
if (bestMatch || updated) {
|
|
48422
|
+
const bits = [
|
|
48423
|
+
bestMatch ? `best match: ${bestMatch}` : null,
|
|
48424
|
+
updated ? `updated ${updated}` : null
|
|
48425
|
+
].filter(Boolean);
|
|
48426
|
+
println(c.dim(` ${bits.join(" · ")}`));
|
|
48427
|
+
}
|
|
48428
|
+
if (options.onlyMetadata)
|
|
48429
|
+
continue;
|
|
48124
48430
|
println("");
|
|
48125
48431
|
println(doc2.full_content ?? "");
|
|
48126
48432
|
println("");
|
|
48127
|
-
println(c.dim("
|
|
48433
|
+
println(c.dim("════════════════════════════════════════"));
|
|
48128
48434
|
println("");
|
|
48129
48435
|
} else {
|
|
48130
48436
|
const chunk = row;
|
|
@@ -48142,7 +48448,7 @@ async function action25(query, options) {
|
|
|
48142
48448
|
}
|
|
48143
48449
|
}
|
|
48144
48450
|
function registerSearch(program2) {
|
|
48145
|
-
program2.command("search").description("Search the knowledge base (hybrid FTS + semantic).").argument("<query>", "Natural-language search query.").option("-c, --match-count <n>", "Maximum number of documents to return.", "5").option("-p, --project-name <name>", "Filter results to a specific project.").option("-f, --metadata-filter <json>", "JSON containment filter; only docs whose metadata contains ALL pairs are returned.").option("--mode <mode>", "Search mode: docs (default), hybrid, fts.", "docs").option("--alpha <float>", "Semantic weight 0..1 (default: 0.7).", "0.7").option("--min-score <float>", "Minimum cosine similarity threshold.", "0.5").option("--max-bytes <n>", "Response size budget in bytes.", "200000").option("-r, --requestor <name>", "Agent / user name (recorded in usage log).").option("--json", "Emit machine-readable JSON instead of the default text.").action(
|
|
48451
|
+
program2.command("search").description("Search the knowledge base (hybrid FTS + semantic).").argument("<query>", "Natural-language search query.").option("-c, --match-count <n>", "Maximum number of documents to return.", "5").option("-p, --project-name <name>", "Filter results to a specific project.").option("-f, --metadata-filter <json>", "JSON containment filter; only docs whose metadata contains ALL pairs are returned.").option("--mode <mode>", "Search mode: docs (default), hybrid, fts.", "docs").option("--alpha <float>", "Semantic weight 0..1 (default: 0.7).", "0.7").option("--min-score <float>", "Minimum cosine similarity threshold.", "0.5").option("--max-bytes <n>", "Response size budget in bytes.", "200000").option("-r, --requestor <name>", "Agent / user name (recorded in usage log).").option("--json", "Emit machine-readable JSON instead of the default text.").option("--only-metadata", "List matching docs (id, score, chunks, chars, partial/full) WITHOUT their content — like the web UI's collapsed result list. Grab a [id:…] then `cerefox document get <id>`.").action(action28);
|
|
48146
48452
|
}
|
|
48147
48453
|
|
|
48148
48454
|
// src/cli/commands/self-update.ts
|
|
@@ -48189,7 +48495,7 @@ async function fetchLatestVersion() {
|
|
|
48189
48495
|
}
|
|
48190
48496
|
return body.version;
|
|
48191
48497
|
}
|
|
48192
|
-
async function
|
|
48498
|
+
async function action29(options) {
|
|
48193
48499
|
let target;
|
|
48194
48500
|
try {
|
|
48195
48501
|
target = options.version ?? await fetchLatestVersion();
|
|
@@ -48241,7 +48547,7 @@ async function action26(options) {
|
|
|
48241
48547
|
}
|
|
48242
48548
|
function registerSelfUpdate(program2) {
|
|
48243
48549
|
const desc = "Upgrade Cerefox in place. Alias: `cerefox upgrade`.";
|
|
48244
|
-
const declaration = (cmd) => cmd.description(desc).option("--check", "Print current vs latest; do nothing.").option("--yes", "Non-interactive (skip confirmation).").option("--version <version>", "Pin a specific version (e.g. 0.5.1 or 0.6.0-rc.1).").action(
|
|
48550
|
+
const declaration = (cmd) => cmd.description(desc).option("--check", "Print current vs latest; do nothing.").option("--yes", "Non-interactive (skip confirmation).").option("--version <version>", "Pin a specific version (e.g. 0.5.1 or 0.6.0-rc.1).").action(action29);
|
|
48245
48551
|
declaration(program2.command("self-update"));
|
|
48246
48552
|
declaration(program2.command("upgrade"));
|
|
48247
48553
|
}
|
|
@@ -48260,7 +48566,7 @@ function symbol2(status) {
|
|
|
48260
48566
|
return cErr.dim("ℹ");
|
|
48261
48567
|
}
|
|
48262
48568
|
}
|
|
48263
|
-
async function
|
|
48569
|
+
async function action30(options) {
|
|
48264
48570
|
const useSpinner = !options.json && process.stderr.isTTY;
|
|
48265
48571
|
const spinner = useSpinner ? ora({ text: "Starting checks…", spinner: "dots", stream: process.stderr }).start() : null;
|
|
48266
48572
|
const results = await runFastChecks({
|
|
@@ -48281,105 +48587,7 @@ async function action27(options) {
|
|
|
48281
48587
|
}
|
|
48282
48588
|
}
|
|
48283
48589
|
function registerStatus(program2) {
|
|
48284
|
-
program2.command("status").description("Quick sanity check (fast subset of `cerefox doctor`).").option("--json", "Emit machine-readable JSON.").action(
|
|
48285
|
-
}
|
|
48286
|
-
|
|
48287
|
-
// src/cli/commands/sync-docs.ts
|
|
48288
|
-
init_cli_core();
|
|
48289
|
-
init_mcp_tools();
|
|
48290
|
-
init_config();
|
|
48291
|
-
init_client();
|
|
48292
|
-
import {
|
|
48293
|
-
existsSync as existsSync11,
|
|
48294
|
-
readFileSync as readFileSync12,
|
|
48295
|
-
readdirSync as readdirSync6,
|
|
48296
|
-
statSync as statSync5
|
|
48297
|
-
} from "node:fs";
|
|
48298
|
-
import { basename as basename5, extname as extname5, join as join11, relative } from "node:path";
|
|
48299
|
-
var ROOT_LEVEL_DOCS = ["README.md", "AGENT_GUIDE.md", "AGENT_QUICK_REFERENCE.md"];
|
|
48300
|
-
function walkMarkdown(dir) {
|
|
48301
|
-
const out = [];
|
|
48302
|
-
if (!existsSync11(dir))
|
|
48303
|
-
return out;
|
|
48304
|
-
for (const name of readdirSync6(dir)) {
|
|
48305
|
-
const full = join11(dir, name);
|
|
48306
|
-
let stat;
|
|
48307
|
-
try {
|
|
48308
|
-
stat = statSync5(full);
|
|
48309
|
-
} catch {
|
|
48310
|
-
continue;
|
|
48311
|
-
}
|
|
48312
|
-
if (stat.isDirectory()) {
|
|
48313
|
-
out.push(...walkMarkdown(full));
|
|
48314
|
-
} else if (stat.isFile() && name.toLowerCase().endsWith(".md")) {
|
|
48315
|
-
out.push(full);
|
|
48316
|
-
}
|
|
48317
|
-
}
|
|
48318
|
-
return out;
|
|
48319
|
-
}
|
|
48320
|
-
async function action28(options) {
|
|
48321
|
-
const cwd = process.cwd();
|
|
48322
|
-
const project = options.project ?? "cerefox";
|
|
48323
|
-
const targets = [];
|
|
48324
|
-
for (const rel of ROOT_LEVEL_DOCS) {
|
|
48325
|
-
const abs = join11(cwd, rel);
|
|
48326
|
-
if (existsSync11(abs))
|
|
48327
|
-
targets.push({ abs, rel });
|
|
48328
|
-
}
|
|
48329
|
-
for (const abs of walkMarkdown(join11(cwd, "docs"))) {
|
|
48330
|
-
targets.push({ abs, rel: relative(cwd, abs) });
|
|
48331
|
-
}
|
|
48332
|
-
if (targets.length === 0) {
|
|
48333
|
-
println(c.dim(`(no markdown files found in ${cwd})`));
|
|
48334
|
-
return;
|
|
48335
|
-
}
|
|
48336
|
-
println(c.bold(`Syncing ${targets.length} markdown file(s) to project "${project}"`));
|
|
48337
|
-
if (options.dryRun)
|
|
48338
|
-
println(c.yellow("(dry run — no writes)"));
|
|
48339
|
-
println("");
|
|
48340
|
-
if (options.dryRun) {
|
|
48341
|
-
printTable(targets.map((t) => ({
|
|
48342
|
-
file: t.rel,
|
|
48343
|
-
title: basename5(t.abs, extname5(t.abs))
|
|
48344
|
-
})));
|
|
48345
|
-
return;
|
|
48346
|
-
}
|
|
48347
|
-
const client = getClient();
|
|
48348
|
-
const settings = loadSettings();
|
|
48349
|
-
const author = resolveAuthor(undefined);
|
|
48350
|
-
const authorType = resolveAuthorType("agent");
|
|
48351
|
-
const outcomes = [];
|
|
48352
|
-
for (const t of targets) {
|
|
48353
|
-
const content = readFileSync12(t.abs, "utf8");
|
|
48354
|
-
const title = basename5(t.abs, extname5(t.abs));
|
|
48355
|
-
try {
|
|
48356
|
-
const message = await ingestTool.handler(client.raw, {
|
|
48357
|
-
title,
|
|
48358
|
-
content,
|
|
48359
|
-
source: "sync-docs",
|
|
48360
|
-
metadata: { source_path: t.rel },
|
|
48361
|
-
update_if_exists: true,
|
|
48362
|
-
project_name: project,
|
|
48363
|
-
author,
|
|
48364
|
-
author_type: authorType
|
|
48365
|
-
}, { openaiApiKey: settings.openaiApiKey, accessPath: "cli" });
|
|
48366
|
-
outcomes.push({ file: t.rel, status: "ok", detail: message });
|
|
48367
|
-
} catch (err) {
|
|
48368
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
48369
|
-
outcomes.push({ file: t.rel, status: "error", detail: msg });
|
|
48370
|
-
}
|
|
48371
|
-
}
|
|
48372
|
-
const ok2 = outcomes.filter((o) => o.status === "ok");
|
|
48373
|
-
const errs = outcomes.filter((o) => o.status === "error");
|
|
48374
|
-
println("");
|
|
48375
|
-
println(c.bold(`Summary: ${ok2.length} ok · ${errs.length} error${errs.length === 1 ? "" : "s"}`));
|
|
48376
|
-
if (errs.length > 0) {
|
|
48377
|
-
println("");
|
|
48378
|
-
printTable(errs.map((e) => ({ file: e.file, error: e.detail.slice(0, 100) })));
|
|
48379
|
-
}
|
|
48380
|
-
}
|
|
48381
|
-
function registerSyncDocs(program2) {
|
|
48382
|
-
program2.command("sync-docs").description("Sync repo docs (README, AGENT_*, docs/) into a Cerefox project.").option("--dry-run", "Print what would be synced without writing.").option("-p, --project <name>", "Target project for the sync.", "cerefox").action(action28);
|
|
48590
|
+
program2.command("status").description("Quick sanity check (fast subset of `cerefox doctor`).").option("--json", "Emit machine-readable JSON.").action(action30);
|
|
48383
48591
|
}
|
|
48384
48592
|
|
|
48385
48593
|
// src/cli/program.ts
|
|
@@ -49714,7 +49922,7 @@ var _baseMimes = {
|
|
|
49714
49922
|
var baseMimes = _baseMimes;
|
|
49715
49923
|
|
|
49716
49924
|
// ../../node_modules/.bun/@hono+node-server@2.0.4+1bbe96acb4c5ebf1/node_modules/@hono/node-server/dist/serve-static.mjs
|
|
49717
|
-
import { createReadStream, existsSync as existsSync12, statSync as
|
|
49925
|
+
import { createReadStream, existsSync as existsSync12, statSync as statSync5 } from "node:fs";
|
|
49718
49926
|
import { join as join12 } from "node:path";
|
|
49719
49927
|
var COMPRESSIBLE_CONTENT_TYPE_REGEX = /^\s*(?:text\/[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i;
|
|
49720
49928
|
var ENCODINGS = {
|
|
@@ -49726,7 +49934,7 @@ var ENCODINGS_ORDERED_KEYS = Object.keys(ENCODINGS);
|
|
|
49726
49934
|
var getStats = (path) => {
|
|
49727
49935
|
let stats;
|
|
49728
49936
|
try {
|
|
49729
|
-
stats =
|
|
49937
|
+
stats = statSync5(path);
|
|
49730
49938
|
} catch {}
|
|
49731
49939
|
return stats;
|
|
49732
49940
|
};
|
|
@@ -51634,7 +51842,7 @@ function registerConfigRoutes(app, ctx) {
|
|
|
51634
51842
|
}
|
|
51635
51843
|
|
|
51636
51844
|
// src/web/routes/discovery.ts
|
|
51637
|
-
var
|
|
51845
|
+
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
51638
51846
|
var DOC_COLS = "id, title, source, source_path, content_hash, metadata, chunk_count, total_chars, review_status, created_at, updated_at, deleted_at";
|
|
51639
51847
|
function jsonByteLength(value) {
|
|
51640
51848
|
return Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
@@ -52080,7 +52288,7 @@ function registerDiscoveryRoutes(app, ctx) {
|
|
|
52080
52288
|
if (!path) {
|
|
52081
52289
|
return c2.json({ tried_path: "", anchor, matches: [] });
|
|
52082
52290
|
}
|
|
52083
|
-
if (
|
|
52291
|
+
if (UUID_RE3.test(path)) {
|
|
52084
52292
|
if (path === fromDocId) {
|
|
52085
52293
|
return c2.json({ tried_path: path, anchor, matches: [] });
|
|
52086
52294
|
}
|
|
@@ -52106,7 +52314,7 @@ function registerDiscoveryRoutes(app, ctx) {
|
|
|
52106
52314
|
if (!normalised) {
|
|
52107
52315
|
return c2.json({ tried_path: "", anchor, matches: [] });
|
|
52108
52316
|
}
|
|
52109
|
-
const
|
|
52317
|
+
const basename5 = normalised.split("/").pop() ?? normalised;
|
|
52110
52318
|
const project = (rows, method) => rows.filter((r) => r.id !== fromDocId).map((r) => ({
|
|
52111
52319
|
document_id: r.id,
|
|
52112
52320
|
title: r.title ?? "",
|
|
@@ -52121,8 +52329,8 @@ function registerDiscoveryRoutes(app, ctx) {
|
|
|
52121
52329
|
return c2.json({ tried_path: normalised, anchor, matches });
|
|
52122
52330
|
}
|
|
52123
52331
|
}
|
|
52124
|
-
if (
|
|
52125
|
-
const { data } = await ctx.supabase.from("cerefox_documents").select("id, title, source_path").is("deleted_at", null).like("source_path", `%/${
|
|
52332
|
+
if (basename5 !== normalised) {
|
|
52333
|
+
const { data } = await ctx.supabase.from("cerefox_documents").select("id, title, source_path").is("deleted_at", null).like("source_path", `%/${basename5}`).order("updated_at", { ascending: false }).limit(limit);
|
|
52126
52334
|
const rows = data ?? [];
|
|
52127
52335
|
const matches = project(rows, "basename");
|
|
52128
52336
|
if (matches.length > 0) {
|
|
@@ -52130,7 +52338,7 @@ function registerDiscoveryRoutes(app, ctx) {
|
|
|
52130
52338
|
}
|
|
52131
52339
|
}
|
|
52132
52340
|
{
|
|
52133
|
-
const stem =
|
|
52341
|
+
const stem = basename5.replace(/\.md$/i, "").replace(/[-_]+/g, " ").trim();
|
|
52134
52342
|
if (stem) {
|
|
52135
52343
|
const { data } = await ctx.supabase.from("cerefox_documents").select("id, title, source_path").is("deleted_at", null).ilike("title", `%${stem}%`).order("updated_at", { ascending: false }).limit(limit);
|
|
52136
52344
|
const rows = data ?? [];
|
|
@@ -52678,10 +52886,10 @@ import { execFileSync } from "node:child_process";
|
|
|
52678
52886
|
import {
|
|
52679
52887
|
existsSync as existsSync13,
|
|
52680
52888
|
readFileSync as readFileSync13,
|
|
52681
|
-
readdirSync as
|
|
52682
|
-
statSync as
|
|
52889
|
+
readdirSync as readdirSync6,
|
|
52890
|
+
statSync as statSync6
|
|
52683
52891
|
} from "node:fs";
|
|
52684
|
-
import { basename as
|
|
52892
|
+
import { basename as basename5, dirname as dirname5, join as join13, resolve as resolve5 } from "node:path";
|
|
52685
52893
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
52686
52894
|
var TOP_LEVEL_DOCS = [
|
|
52687
52895
|
{ filename: "README.md", path: "README.md", category: "readme" },
|
|
@@ -52709,7 +52917,7 @@ function resolveDocsRoots() {
|
|
|
52709
52917
|
let pkgTopLevel = null;
|
|
52710
52918
|
for (const pkg of pkgRootCandidates) {
|
|
52711
52919
|
const guides = join13(pkg, "docs", "guides");
|
|
52712
|
-
if (existsSync13(guides) &&
|
|
52920
|
+
if (existsSync13(guides) && statSync6(guides).isDirectory()) {
|
|
52713
52921
|
pkgGuides = guides;
|
|
52714
52922
|
pkgTopLevel = pkg;
|
|
52715
52923
|
break;
|
|
@@ -52738,7 +52946,7 @@ function slugifiedTitle(filename) {
|
|
|
52738
52946
|
return filename.replace(/\.md$/i, "").replace(/[-_]+/g, " ").replace(/\b\w/g, (m) => m.toUpperCase());
|
|
52739
52947
|
}
|
|
52740
52948
|
function entryForFile(absPath, relPath, category) {
|
|
52741
|
-
const title = readH1(absPath) ?? slugifiedTitle(
|
|
52949
|
+
const title = readH1(absPath) ?? slugifiedTitle(basename5(relPath));
|
|
52742
52950
|
return { path: relPath, title, category };
|
|
52743
52951
|
}
|
|
52744
52952
|
function listBundledDocs2() {
|
|
@@ -52755,7 +52963,7 @@ function listBundledDocs2() {
|
|
|
52755
52963
|
}
|
|
52756
52964
|
const guidesRoot = pkgGuides ?? repoGuides;
|
|
52757
52965
|
if (guidesRoot) {
|
|
52758
|
-
const names =
|
|
52966
|
+
const names = readdirSync6(guidesRoot).filter((n) => n.endsWith(".md")).sort();
|
|
52759
52967
|
for (const name of names) {
|
|
52760
52968
|
const abs = join13(guidesRoot, name);
|
|
52761
52969
|
entries.push(entryForFile(abs, `guides/${name}`, "guide"));
|
|
@@ -52771,7 +52979,7 @@ function readDoc(docPath) {
|
|
|
52771
52979
|
if (!candidate.startsWith(resolve5(root) + "/") && candidate !== resolve5(root)) {
|
|
52772
52980
|
continue;
|
|
52773
52981
|
}
|
|
52774
|
-
if (existsSync13(candidate) &&
|
|
52982
|
+
if (existsSync13(candidate) && statSync6(candidate).isFile()) {
|
|
52775
52983
|
try {
|
|
52776
52984
|
return readFileSync13(candidate, "utf8");
|
|
52777
52985
|
} catch {
|
|
@@ -52939,14 +53147,14 @@ function registerProjectsRoutes(app, ctx) {
|
|
|
52939
53147
|
}
|
|
52940
53148
|
|
|
52941
53149
|
// src/web/static.ts
|
|
52942
|
-
import { existsSync as existsSync14, statSync as
|
|
53150
|
+
import { existsSync as existsSync14, statSync as statSync7 } from "node:fs";
|
|
52943
53151
|
import { dirname as dirname6, join as join14 } from "node:path";
|
|
52944
53152
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
52945
53153
|
function moduleDir3() {
|
|
52946
53154
|
return dirname6(fileURLToPath4(import.meta.url));
|
|
52947
53155
|
}
|
|
52948
53156
|
function isUsableSpaDir(dir) {
|
|
52949
|
-
return existsSync14(dir) &&
|
|
53157
|
+
return existsSync14(dir) && statSync7(dir).isDirectory() && existsSync14(join14(dir, "index.html"));
|
|
52950
53158
|
}
|
|
52951
53159
|
function resolveSpaDist() {
|
|
52952
53160
|
const here = moduleDir3();
|
|
@@ -52968,7 +53176,7 @@ function resolveStaticDir() {
|
|
|
52968
53176
|
join14(here, "..", "..", "..", "..", "web", "static")
|
|
52969
53177
|
];
|
|
52970
53178
|
for (const c2 of candidates) {
|
|
52971
|
-
if (existsSync14(c2) &&
|
|
53179
|
+
if (existsSync14(c2) && statSync7(c2).isDirectory())
|
|
52972
53180
|
return c2;
|
|
52973
53181
|
}
|
|
52974
53182
|
return null;
|
|
@@ -53117,11 +53325,11 @@ import {
|
|
|
53117
53325
|
openSync,
|
|
53118
53326
|
readFileSync as readFileSync15,
|
|
53119
53327
|
rmSync,
|
|
53120
|
-
writeFileSync as
|
|
53328
|
+
writeFileSync as writeFileSync5
|
|
53121
53329
|
} from "node:fs";
|
|
53122
|
-
import { homedir as
|
|
53330
|
+
import { homedir as homedir8 } from "node:os";
|
|
53123
53331
|
import { join as join16 } from "node:path";
|
|
53124
|
-
var STATE_DIR = join16(
|
|
53332
|
+
var STATE_DIR = join16(homedir8(), ".cerefox");
|
|
53125
53333
|
var PID_FILE = join16(STATE_DIR, "web.pid");
|
|
53126
53334
|
var LOG_FILE = join16(STATE_DIR, "web.log");
|
|
53127
53335
|
var daemonPaths = { stateDir: STATE_DIR, pidFile: PID_FILE, logFile: LOG_FILE };
|
|
@@ -53148,7 +53356,7 @@ function readPidFile() {
|
|
|
53148
53356
|
}
|
|
53149
53357
|
function writePidFile(info3) {
|
|
53150
53358
|
ensureStateDir();
|
|
53151
|
-
|
|
53359
|
+
writeFileSync5(PID_FILE, JSON.stringify(info3, null, 2) + `
|
|
53152
53360
|
`, "utf8");
|
|
53153
53361
|
}
|
|
53154
53362
|
function removePidFile() {
|
|
@@ -53386,7 +53594,7 @@ var RENAMED_VERBS = [
|
|
|
53386
53594
|
["ingest-dir", "document ingest-dir"],
|
|
53387
53595
|
["list-projects", "project list"],
|
|
53388
53596
|
["delete-project", "project delete"],
|
|
53389
|
-
["list-versions", "version list"],
|
|
53597
|
+
["list-versions", "document version list"],
|
|
53390
53598
|
["get-audit-log", "audit list"],
|
|
53391
53599
|
["list-metadata-keys", "metadata keys"],
|
|
53392
53600
|
["metadata-search", "metadata search"],
|
|
@@ -53394,30 +53602,32 @@ var RENAMED_VERBS = [
|
|
|
53394
53602
|
["config-set", "config set"],
|
|
53395
53603
|
["restore", "backup restore"],
|
|
53396
53604
|
["deploy-server", "server deploy"],
|
|
53397
|
-
["reindex", "server reindex"]
|
|
53605
|
+
["reindex", "server reindex"],
|
|
53606
|
+
["docs", "guides"],
|
|
53607
|
+
["sync-self-docs", "guides ingest"]
|
|
53398
53608
|
];
|
|
53399
53609
|
function registerRenameHusks(program2) {
|
|
53400
53610
|
for (const [oldName, newForm] of RENAMED_VERBS) {
|
|
53401
53611
|
program2.command(oldName, { hidden: true }).allowUnknownOption(true).allowExcessArguments(true).argument("[args...]", "(renamed)").action(() => {
|
|
53402
|
-
eprintln(c.yellow(`✗ \`cerefox ${oldName}\` was renamed
|
|
53612
|
+
eprintln(c.yellow(`✗ \`cerefox ${oldName}\` was renamed.`));
|
|
53403
53613
|
eprintln(` Use \`cerefox ${newForm}\` instead (run \`cerefox ${newForm.split(" ")[0]} --help\`).`);
|
|
53404
53614
|
process.exit(1);
|
|
53405
53615
|
});
|
|
53406
53616
|
}
|
|
53407
53617
|
}
|
|
53408
53618
|
function buildProgram() {
|
|
53409
|
-
const program2 = new Command("cerefox").description("Cerefox — user-owned shared memory for AI agents.").version(PKG_VERSION, "-v, --version", "Print the cerefox version and exit.").addOption(new Option("--json", "Emit machine-readable JSON on stdout instead of the default human text. " + "Available on read commands; ignored on commands without a JSON shape.").hideHelp()).showHelpAfterError("(run `cerefox --help` for usage)").enablePositionalOptions().addHelpText("after", "\nResource groups (run `cerefox <group> --help`):\n" + ` document get · list · delete · ingest · ingest-dir
|
|
53410
|
-
` + ` project list · delete
|
|
53411
|
-
` + ` version list
|
|
53619
|
+
const program2 = new Command("cerefox").description("Cerefox — user-owned shared memory for AI agents.").version(PKG_VERSION, "-v, --version", "Print the cerefox version and exit.").addOption(new Option("--json", "Emit machine-readable JSON on stdout instead of the default human text. " + "Available on read commands; ignored on commands without a JSON shape.").hideHelp()).showHelpAfterError("(run `cerefox --help` for usage)").enablePositionalOptions().addHelpText("after", "\nResource groups (run `cerefox <group> --help`):\n" + ` document get · list · edit · delete · restore · ingest · ingest-dir · version {list·archive·unarchive}
|
|
53620
|
+
` + ` project list · create · edit · delete
|
|
53412
53621
|
` + ` metadata keys · search
|
|
53413
53622
|
` + ` audit list
|
|
53414
|
-
` + ` config get · set
|
|
53623
|
+
` + ` config list · get · set
|
|
53415
53624
|
` + ` backup create · restore
|
|
53416
53625
|
` + ` server deploy · reindex
|
|
53626
|
+
` + ` guides list · open · show · ingest (bundled documentation)
|
|
53417
53627
|
` + `
|
|
53418
53628
|
Top-level commands:
|
|
53419
53629
|
` + ` search · init · doctor · status · configure-agent · self-update
|
|
53420
|
-
` + ` mcp · web ·
|
|
53630
|
+
` + ` mcp · web · completion
|
|
53421
53631
|
` + `
|
|
53422
53632
|
Renamed in v0.9.0: the old flat verbs (get-doc, list-docs, ingest, …)
|
|
53423
53633
|
` + ` now live under the groups above. The old names still run but exit with
|
|
@@ -53440,29 +53650,30 @@ Learn more:
|
|
|
53440
53650
|
registerSelfUpdate(program2);
|
|
53441
53651
|
registerMcp(program2);
|
|
53442
53652
|
registerWeb(program2);
|
|
53443
|
-
registerDocs(program2);
|
|
53444
53653
|
registerCompletion(program2);
|
|
53445
|
-
|
|
53446
|
-
registerSyncSelfDocs(program2);
|
|
53447
|
-
const document2 = program2.command("document").description("Documents: get, list, delete, ingest.");
|
|
53654
|
+
const document2 = program2.command("document").description("Documents: get, list, edit, delete, restore, ingest, ingest-dir, version.");
|
|
53448
53655
|
moveInto(document2, registerGetDoc, "get");
|
|
53449
53656
|
moveInto(document2, registerListDocs, "list");
|
|
53450
53657
|
moveInto(document2, registerDeleteDoc, "delete");
|
|
53451
53658
|
registerDocumentRestore(document2);
|
|
53659
|
+
registerDocumentEdit(document2);
|
|
53452
53660
|
moveInto(document2, registerIngest, "ingest");
|
|
53453
53661
|
moveInto(document2, registerIngestDir, "ingest-dir");
|
|
53454
|
-
const
|
|
53662
|
+
const documentVersion = document2.command("version").description("Document versions: list, archive, unarchive.");
|
|
53663
|
+
moveInto(documentVersion, registerListVersions, "list");
|
|
53664
|
+
registerVersionArchive(documentVersion);
|
|
53665
|
+
const project = program2.command("project").description("Projects: list, create, edit, delete.");
|
|
53455
53666
|
moveInto(project, registerListProjects, "list");
|
|
53667
|
+
registerProjectCreate(project);
|
|
53668
|
+
registerProjectEdit(project);
|
|
53456
53669
|
moveInto(project, registerDeleteProject, "delete");
|
|
53457
|
-
const version4 = program2.command("version").description("Document version history: list, archive, unarchive.");
|
|
53458
|
-
moveInto(version4, registerListVersions, "list");
|
|
53459
|
-
registerVersionArchive(version4);
|
|
53460
53670
|
const metadata = program2.command("metadata").description("Metadata: keys, search.");
|
|
53461
53671
|
moveInto(metadata, registerListMetadataKeys, "keys");
|
|
53462
53672
|
moveInto(metadata, registerMetadataSearch, "search");
|
|
53463
53673
|
const audit = program2.command("audit").description("Audit log: list.");
|
|
53464
53674
|
moveInto(audit, registerGetAuditLog, "list");
|
|
53465
|
-
const config2 = program2.command("config").description("Runtime config: get, set.");
|
|
53675
|
+
const config2 = program2.command("config").description("Runtime config: list, get, set.");
|
|
53676
|
+
registerConfigList(config2);
|
|
53466
53677
|
moveInto(config2, registerConfigGet, "get");
|
|
53467
53678
|
moveInto(config2, registerConfigSet, "set");
|
|
53468
53679
|
const backup = program2.command("backup").description("Backup + restore the knowledge base: create, restore.").action(() => {
|
|
@@ -53475,7 +53686,15 @@ Learn more:
|
|
|
53475
53686
|
const server = program2.command("server").description("Server side: deploy, reindex.");
|
|
53476
53687
|
moveInto(server, registerDeployServer, "deploy");
|
|
53477
53688
|
moveInto(server, registerReindex, "reindex");
|
|
53689
|
+
const guides = program2.command("guides").description("Bundled docs: list, open, show, ingest (into the KB).");
|
|
53690
|
+
registerGuides(guides);
|
|
53691
|
+
moveInto(guides, registerSyncSelfDocs, "ingest");
|
|
53478
53692
|
registerRenameHusks(program2);
|
|
53693
|
+
program2.command("sync-docs", { hidden: true }).allowUnknownOption(true).allowExcessArguments(true).argument("[args...]", "(removed)").action(() => {
|
|
53694
|
+
eprintln(c.yellow("✗ `cerefox sync-docs` was removed from the CLI in v0.9.1."));
|
|
53695
|
+
eprintln(" It synced a local repo clone (contributor op). From a repo clone: `bun scripts/sync_docs.ts`.");
|
|
53696
|
+
process.exit(1);
|
|
53697
|
+
});
|
|
53479
53698
|
return program2;
|
|
53480
53699
|
}
|
|
53481
53700
|
|