@cerefox/memory 0.8.3 → 0.9.1
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 +614 -347
- package/dist/frontend/assets/{index-CAp2_lFX.js → index-De3R6K8J.js} +29 -29
- package/dist/frontend/assets/{index-CAp2_lFX.js.map → index-De3R6K8J.js.map} +1 -1
- package/dist/frontend/index.html +1 -1
- 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 +44 -38
- package/docs/guides/cli.md +206 -64
- package/docs/guides/configuration.md +28 -37
- package/docs/guides/connect-agents.md +157 -180
- package/docs/guides/operational-cost.md +1 -1
- package/docs/guides/ops-scripts.md +74 -54
- package/docs/guides/quickstart.md +28 -22
- package/docs/guides/setup-cloud-run.md +12 -2
- package/docs/guides/setup-local.md +16 -10
- package/docs/guides/setup-supabase.md +57 -162
- package/docs/guides/upgrading.md +44 -31
- 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.
|
|
7187
|
+
var PKG_VERSION = "0.9.1";
|
|
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();
|
|
@@ -39930,6 +39930,7 @@ var {
|
|
|
39930
39930
|
|
|
39931
39931
|
// src/cli/program.ts
|
|
39932
39932
|
init_meta();
|
|
39933
|
+
init_cli_core();
|
|
39933
39934
|
|
|
39934
39935
|
// src/cli/commands/backup.ts
|
|
39935
39936
|
init_cli_core();
|
|
@@ -40001,6 +40002,9 @@ function registerBackup(program2) {
|
|
|
40001
40002
|
|
|
40002
40003
|
// src/cli/commands/completion.ts
|
|
40003
40004
|
init_cli_core();
|
|
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";
|
|
40004
40008
|
function collectCompletionInfo() {
|
|
40005
40009
|
const program2 = buildProgram();
|
|
40006
40010
|
const subcommands = [];
|
|
@@ -40092,26 +40096,84 @@ function fishScript(info2) {
|
|
|
40092
40096
|
`) + `
|
|
40093
40097
|
`;
|
|
40094
40098
|
}
|
|
40095
|
-
function
|
|
40099
|
+
function scriptFor(shell) {
|
|
40096
40100
|
const info2 = collectCompletionInfo();
|
|
40097
|
-
let script;
|
|
40098
40101
|
switch (shell) {
|
|
40099
40102
|
case "bash":
|
|
40100
|
-
|
|
40101
|
-
break;
|
|
40103
|
+
return bashScript(info2);
|
|
40102
40104
|
case "zsh":
|
|
40103
|
-
|
|
40104
|
-
break;
|
|
40105
|
+
return zshScript(info2);
|
|
40105
40106
|
case "fish":
|
|
40106
|
-
|
|
40107
|
-
|
|
40108
|
-
|
|
40109
|
-
|
|
40107
|
+
return fishScript(info2);
|
|
40108
|
+
}
|
|
40109
|
+
}
|
|
40110
|
+
function detectShell() {
|
|
40111
|
+
const sh = (process.env.SHELL ?? "").split("/").pop() ?? "";
|
|
40112
|
+
if (sh === "bash" || sh === "zsh" || sh === "fish")
|
|
40113
|
+
return sh;
|
|
40114
|
+
return null;
|
|
40115
|
+
}
|
|
40116
|
+
var RC_BEGIN = "# >>> cerefox shell completion (managed by `cerefox completion install`) >>>";
|
|
40117
|
+
var RC_END = "# <<< cerefox shell completion <<<";
|
|
40118
|
+
async function installMode(options) {
|
|
40119
|
+
const shell = options.shell ?? detectShell();
|
|
40120
|
+
if (!shell) {
|
|
40121
|
+
throw userError("Could not detect your shell from $SHELL. Pass --shell bash|zsh|fish.");
|
|
40122
|
+
}
|
|
40123
|
+
if (shell !== "bash" && shell !== "zsh" && shell !== "fish") {
|
|
40124
|
+
throw userError(`Unsupported --shell "${shell}". Use bash, zsh, or fish.`);
|
|
40125
|
+
}
|
|
40126
|
+
const home = homedir3();
|
|
40127
|
+
const scriptPath = join3(home, `.cerefox-completion.${shell}`);
|
|
40128
|
+
writeFileSync2(scriptPath, scriptFor(shell), "utf8");
|
|
40129
|
+
println(c.green(`✓ Wrote completion script: ${scriptPath}`));
|
|
40130
|
+
if (shell === "fish") {
|
|
40131
|
+
println(c.dim(" For fish, also copy it into ~/.config/fish/completions/cerefox.fish (or `source` it)."));
|
|
40132
|
+
return;
|
|
40133
|
+
}
|
|
40134
|
+
const rcPath = join3(home, shell === "zsh" ? ".zshrc" : ".bashrc");
|
|
40135
|
+
const sourceLine = `[ -s "${scriptPath}" ] && source "${scriptPath}"`;
|
|
40136
|
+
const block = `${RC_BEGIN}
|
|
40137
|
+
${sourceLine}
|
|
40138
|
+
${RC_END}
|
|
40139
|
+
`;
|
|
40140
|
+
const existing = existsSync3(rcPath) ? readFileSync3(rcPath, "utf8") : "";
|
|
40141
|
+
if (existing.includes(RC_BEGIN)) {
|
|
40142
|
+
println(c.dim(` ${rcPath} already sources the completion (left as-is).`));
|
|
40143
|
+
} else {
|
|
40144
|
+
const interactive = process.stdout.isTTY && !options.yes;
|
|
40145
|
+
if (interactive) {
|
|
40146
|
+
const ok2 = await confirm(`Add a completion source line to ${rcPath}?`, false);
|
|
40147
|
+
if (!ok2) {
|
|
40148
|
+
println(c.dim(`Skipped the rc edit. Add this line to ${rcPath} yourself:`));
|
|
40149
|
+
println(` ${sourceLine}`);
|
|
40150
|
+
return;
|
|
40151
|
+
}
|
|
40152
|
+
}
|
|
40153
|
+
writeFileSync2(rcPath, (existing.endsWith(`
|
|
40154
|
+
`) || existing === "" ? existing : existing + `
|
|
40155
|
+
`) + `
|
|
40156
|
+
` + block, "utf8");
|
|
40157
|
+
println(c.green(`✓ Added completion to ${rcPath}.`));
|
|
40158
|
+
}
|
|
40159
|
+
println(c.dim(` Activate now: exec ${shell} (or open a new terminal).`));
|
|
40160
|
+
}
|
|
40161
|
+
async function action2(target, options) {
|
|
40162
|
+
if (target === "install") {
|
|
40163
|
+
await installMode(options);
|
|
40164
|
+
return;
|
|
40165
|
+
}
|
|
40166
|
+
if (target !== "bash" && target !== "zsh" && target !== "fish") {
|
|
40167
|
+
throw userError(`Unknown shell "${target}". Supported: bash, zsh, fish (or 'install').`);
|
|
40168
|
+
}
|
|
40169
|
+
println(scriptFor(target));
|
|
40170
|
+
if (process.stdout.isTTY) {
|
|
40171
|
+
eprintln(c.dim(`
|
|
40172
|
+
# Tip: \`cerefox completion install\` writes this + wires your shell rc automatically.`));
|
|
40110
40173
|
}
|
|
40111
|
-
println(script);
|
|
40112
40174
|
}
|
|
40113
40175
|
function registerCompletion(program2) {
|
|
40114
|
-
program2.command("completion").description("
|
|
40176
|
+
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);
|
|
40115
40177
|
}
|
|
40116
40178
|
|
|
40117
40179
|
// src/cli/commands/config-get.ts
|
|
@@ -40144,10 +40206,41 @@ function registerConfigGet(program2) {
|
|
|
40144
40206
|
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);
|
|
40145
40207
|
}
|
|
40146
40208
|
|
|
40209
|
+
// src/cli/commands/config-list.ts
|
|
40210
|
+
init_cli_core();
|
|
40211
|
+
var CONFIG_KEYS = [
|
|
40212
|
+
{
|
|
40213
|
+
key: "usage_tracking_enabled",
|
|
40214
|
+
description: "'true'/'false' — log reads + writes to cerefox_usage_log. Default off."
|
|
40215
|
+
},
|
|
40216
|
+
{
|
|
40217
|
+
key: "require_requestor_identity",
|
|
40218
|
+
description: "'true'/'false' — require requestor/author on MCP tool calls. Default off."
|
|
40219
|
+
},
|
|
40220
|
+
{
|
|
40221
|
+
key: "requestor_identity_format",
|
|
40222
|
+
description: "Regex the requestor/author must match (only enforced when the above is on)."
|
|
40223
|
+
}
|
|
40224
|
+
];
|
|
40225
|
+
function action4(options) {
|
|
40226
|
+
if (options.json) {
|
|
40227
|
+
printJson({ keys: CONFIG_KEYS.map((k) => k.key) });
|
|
40228
|
+
return;
|
|
40229
|
+
}
|
|
40230
|
+
println(c.bold("Runtime config keys (stored in cerefox_config; read with `cerefox config get <key>`):"));
|
|
40231
|
+
for (const { key, description } of CONFIG_KEYS) {
|
|
40232
|
+
println(` ${c.bold(key)}`);
|
|
40233
|
+
println(c.dim(` ${description}`));
|
|
40234
|
+
}
|
|
40235
|
+
}
|
|
40236
|
+
function registerConfigList(parent) {
|
|
40237
|
+
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);
|
|
40238
|
+
}
|
|
40239
|
+
|
|
40147
40240
|
// src/cli/commands/config-set.ts
|
|
40148
40241
|
init_cli_core();
|
|
40149
40242
|
init_client();
|
|
40150
|
-
async function
|
|
40243
|
+
async function action5(key, value) {
|
|
40151
40244
|
const client = getClient();
|
|
40152
40245
|
try {
|
|
40153
40246
|
await client.rpc("cerefox_set_config", { p_key: key, p_value: value });
|
|
@@ -40158,7 +40251,7 @@ async function action4(key, value) {
|
|
|
40158
40251
|
println(c.green("✓ ") + `${key} = ${value}`);
|
|
40159
40252
|
}
|
|
40160
40253
|
function registerConfigSet(program2) {
|
|
40161
|
-
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(
|
|
40254
|
+
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);
|
|
40162
40255
|
}
|
|
40163
40256
|
|
|
40164
40257
|
// src/cli/commands/configure-agent.ts
|
|
@@ -40167,13 +40260,13 @@ init_cli_core();
|
|
|
40167
40260
|
// src/cli/util/mcp-config-writers.ts
|
|
40168
40261
|
import {
|
|
40169
40262
|
copyFileSync,
|
|
40170
|
-
existsSync as
|
|
40263
|
+
existsSync as existsSync4,
|
|
40171
40264
|
mkdirSync as mkdirSync2,
|
|
40172
|
-
readFileSync as
|
|
40173
|
-
writeFileSync as
|
|
40265
|
+
readFileSync as readFileSync4,
|
|
40266
|
+
writeFileSync as writeFileSync3
|
|
40174
40267
|
} from "node:fs";
|
|
40175
|
-
import { homedir as
|
|
40176
|
-
import { dirname, join as
|
|
40268
|
+
import { homedir as homedir4, platform } from "node:os";
|
|
40269
|
+
import { dirname, join as join4 } from "node:path";
|
|
40177
40270
|
import { spawnSync } from "node:child_process";
|
|
40178
40271
|
|
|
40179
40272
|
// ../../node_modules/.bun/smol-toml@1.6.1/node_modules/smol-toml/dist/error.js
|
|
@@ -41275,17 +41368,17 @@ function defaultCerefoxEntry() {
|
|
|
41275
41368
|
};
|
|
41276
41369
|
}
|
|
41277
41370
|
function claudeCodeUserConfigPath() {
|
|
41278
|
-
return
|
|
41371
|
+
return join4(homedir4(), ".claude.json");
|
|
41279
41372
|
}
|
|
41280
41373
|
function claudeDesktopConfigPath() {
|
|
41281
|
-
const home =
|
|
41374
|
+
const home = homedir4();
|
|
41282
41375
|
if (platform() === "darwin") {
|
|
41283
|
-
return
|
|
41376
|
+
return join4(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
41284
41377
|
}
|
|
41285
41378
|
if (platform() === "win32") {
|
|
41286
|
-
return
|
|
41379
|
+
return join4(process.env.APPDATA ?? home, "Claude", "claude_desktop_config.json");
|
|
41287
41380
|
}
|
|
41288
|
-
return
|
|
41381
|
+
return join4(home, ".config", "Claude", "claude_desktop_config.json");
|
|
41289
41382
|
}
|
|
41290
41383
|
function claudeCodeDelegated() {
|
|
41291
41384
|
const entry = defaultCerefoxEntry();
|
|
@@ -41295,13 +41388,13 @@ function claudeCodeDelegated() {
|
|
|
41295
41388
|
};
|
|
41296
41389
|
}
|
|
41297
41390
|
function cursorConfigPath() {
|
|
41298
|
-
return
|
|
41391
|
+
return join4(homedir4(), ".cursor", "mcp.json");
|
|
41299
41392
|
}
|
|
41300
41393
|
function codexConfigPath() {
|
|
41301
|
-
return
|
|
41394
|
+
return join4(homedir4(), ".codex", "config.toml");
|
|
41302
41395
|
}
|
|
41303
41396
|
function geminiConfigPath() {
|
|
41304
|
-
return
|
|
41397
|
+
return join4(homedir4(), ".gemini", "settings.json");
|
|
41305
41398
|
}
|
|
41306
41399
|
var WRITERS = {
|
|
41307
41400
|
"claude-code": {
|
|
@@ -41359,15 +41452,15 @@ function directWrite(writer, configPath, opts) {
|
|
|
41359
41452
|
if (!opts.dryRun)
|
|
41360
41453
|
mkdirSync2(dirname(configPath), { recursive: true });
|
|
41361
41454
|
let existing = {};
|
|
41362
|
-
let
|
|
41455
|
+
let action6 = "created";
|
|
41363
41456
|
let backupPath = null;
|
|
41364
|
-
if (
|
|
41457
|
+
if (existsSync4(configPath)) {
|
|
41365
41458
|
try {
|
|
41366
|
-
const raw =
|
|
41459
|
+
const raw = readFileSync4(configPath, "utf8");
|
|
41367
41460
|
existing = format === "toml" ? parse(raw) : JSON.parse(raw);
|
|
41368
|
-
|
|
41461
|
+
action6 = hasCerefoxEntry(existing, format) ? "replaced" : "merged";
|
|
41369
41462
|
} catch {
|
|
41370
|
-
|
|
41463
|
+
action6 = "replaced";
|
|
41371
41464
|
}
|
|
41372
41465
|
if (!opts.noBackup && !opts.dryRun) {
|
|
41373
41466
|
backupPath = configPath + ".pre-cerefox.bak";
|
|
@@ -41382,9 +41475,9 @@ function directWrite(writer, configPath, opts) {
|
|
|
41382
41475
|
const body = format === "toml" ? stringify(existing) + `
|
|
41383
41476
|
` : JSON.stringify(existing, null, 2) + `
|
|
41384
41477
|
`;
|
|
41385
|
-
|
|
41478
|
+
writeFileSync3(configPath, body, "utf8");
|
|
41386
41479
|
}
|
|
41387
|
-
return { configPath, backupPath, action:
|
|
41480
|
+
return { configPath, backupPath, action: action6, serverEntry: entry };
|
|
41388
41481
|
}
|
|
41389
41482
|
function hasCerefoxEntry(existing, format) {
|
|
41390
41483
|
const key = format === "toml" ? "mcp_servers" : "mcpServers";
|
|
@@ -41408,7 +41501,7 @@ function delegatedWrite(writer, opts) {
|
|
|
41408
41501
|
};
|
|
41409
41502
|
}
|
|
41410
41503
|
let backupPath = null;
|
|
41411
|
-
if (!opts.noBackup &&
|
|
41504
|
+
if (!opts.noBackup && existsSync4(writer.configPath)) {
|
|
41412
41505
|
backupPath = writer.configPath + ".pre-cerefox.bak";
|
|
41413
41506
|
copyFileSync(writer.configPath, backupPath);
|
|
41414
41507
|
}
|
|
@@ -41433,7 +41526,7 @@ function delegatedWrite(writer, opts) {
|
|
|
41433
41526
|
}
|
|
41434
41527
|
|
|
41435
41528
|
// src/cli/commands/configure-agent.ts
|
|
41436
|
-
function
|
|
41529
|
+
function action6(options) {
|
|
41437
41530
|
const writer = WRITERS[options.tool];
|
|
41438
41531
|
if (!writer) {
|
|
41439
41532
|
throw userError(`Unknown --tool "${options.tool}".`, `Supported clients: ${Object.keys(WRITERS).join(", ")}.`);
|
|
@@ -41485,13 +41578,13 @@ function restartHint(id) {
|
|
|
41485
41578
|
}
|
|
41486
41579
|
}
|
|
41487
41580
|
function registerConfigureAgent(program2) {
|
|
41488
|
-
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(
|
|
41581
|
+
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);
|
|
41489
41582
|
}
|
|
41490
41583
|
|
|
41491
41584
|
// src/cli/commands/delete-doc.ts
|
|
41492
41585
|
init_cli_core();
|
|
41493
41586
|
init_client();
|
|
41494
|
-
async function
|
|
41587
|
+
async function action7(documentId, options) {
|
|
41495
41588
|
const client = getClient();
|
|
41496
41589
|
const { data: doc, error } = await client.raw.from("cerefox_documents").select("id, title, total_chars, chunk_count, deleted_at").eq("id", documentId).maybeSingle();
|
|
41497
41590
|
if (error) {
|
|
@@ -41530,14 +41623,14 @@ async function action6(documentId, options) {
|
|
|
41530
41623
|
}
|
|
41531
41624
|
}
|
|
41532
41625
|
function registerDeleteDoc(program2) {
|
|
41533
|
-
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(
|
|
41626
|
+
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);
|
|
41534
41627
|
}
|
|
41535
41628
|
|
|
41536
41629
|
// src/cli/commands/delete-project.ts
|
|
41537
41630
|
init_cli_core();
|
|
41538
41631
|
init_client();
|
|
41539
41632
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
41540
|
-
async function
|
|
41633
|
+
async function action8(target, options) {
|
|
41541
41634
|
const client = getClient();
|
|
41542
41635
|
const isUuid = UUID_RE.test(target);
|
|
41543
41636
|
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();
|
|
@@ -41573,19 +41666,19 @@ async function action7(target, options) {
|
|
|
41573
41666
|
println(c.green(`✓ Deleted project "${project.name}" (id: ${project.id}).`));
|
|
41574
41667
|
}
|
|
41575
41668
|
function registerDeleteProject(program2) {
|
|
41576
|
-
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(
|
|
41669
|
+
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);
|
|
41577
41670
|
}
|
|
41578
41671
|
|
|
41579
41672
|
// src/cli/commands/deploy-server.ts
|
|
41580
41673
|
init_cli_core();
|
|
41581
41674
|
init_config();
|
|
41582
41675
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
41583
|
-
import { existsSync as
|
|
41676
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
41584
41677
|
import { readdirSync as readdirSync2 } from "node:fs";
|
|
41585
41678
|
|
|
41586
41679
|
// ../../_shared/server-assets/index.ts
|
|
41587
|
-
import { existsSync as
|
|
41588
|
-
import { dirname as dirname2, join as
|
|
41680
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
41681
|
+
import { dirname as dirname2, join as join5 } from "node:path";
|
|
41589
41682
|
import { fileURLToPath } from "node:url";
|
|
41590
41683
|
import { cwd as processCwd2 } from "node:process";
|
|
41591
41684
|
function moduleDir() {
|
|
@@ -41593,25 +41686,25 @@ function moduleDir() {
|
|
|
41593
41686
|
}
|
|
41594
41687
|
function bundledServerAssets(serverAssetsRoot) {
|
|
41595
41688
|
return {
|
|
41596
|
-
schemaFile:
|
|
41597
|
-
rpcsFile:
|
|
41598
|
-
migrationsDir:
|
|
41599
|
-
functionsDir:
|
|
41689
|
+
schemaFile: join5(serverAssetsRoot, "db", "schema.sql"),
|
|
41690
|
+
rpcsFile: join5(serverAssetsRoot, "db", "rpcs.sql"),
|
|
41691
|
+
migrationsDir: join5(serverAssetsRoot, "db", "migrations"),
|
|
41692
|
+
functionsDir: join5(serverAssetsRoot, "supabase", "functions"),
|
|
41600
41693
|
layout: "bundled"
|
|
41601
41694
|
};
|
|
41602
41695
|
}
|
|
41603
41696
|
function sourceServerAssets(repoRoot) {
|
|
41604
|
-
const dbDir =
|
|
41697
|
+
const dbDir = join5(repoRoot, "src", "cerefox", "db");
|
|
41605
41698
|
return {
|
|
41606
|
-
schemaFile:
|
|
41607
|
-
rpcsFile:
|
|
41608
|
-
migrationsDir:
|
|
41609
|
-
functionsDir:
|
|
41699
|
+
schemaFile: join5(dbDir, "schema.sql"),
|
|
41700
|
+
rpcsFile: join5(dbDir, "rpcs.sql"),
|
|
41701
|
+
migrationsDir: join5(dbDir, "migrations"),
|
|
41702
|
+
functionsDir: join5(repoRoot, "supabase", "functions"),
|
|
41610
41703
|
layout: "source"
|
|
41611
41704
|
};
|
|
41612
41705
|
}
|
|
41613
41706
|
function serverAssetsUsable(p) {
|
|
41614
|
-
return
|
|
41707
|
+
return existsSync5(p.schemaFile) && existsSync5(p.rpcsFile);
|
|
41615
41708
|
}
|
|
41616
41709
|
function resolveServerAssets(opts = {}) {
|
|
41617
41710
|
if (opts.assetsDir) {
|
|
@@ -41620,21 +41713,21 @@ function resolveServerAssets(opts = {}) {
|
|
|
41620
41713
|
const here = opts.moduleDirOverride ?? moduleDir();
|
|
41621
41714
|
const cwd = opts.cwd ?? processCwd2();
|
|
41622
41715
|
const candidates = [
|
|
41623
|
-
bundledServerAssets(
|
|
41624
|
-
sourceServerAssets(
|
|
41716
|
+
bundledServerAssets(join5(here, "..", "server-assets")),
|
|
41717
|
+
sourceServerAssets(join5(here, "..", "..")),
|
|
41625
41718
|
sourceServerAssets(cwd)
|
|
41626
41719
|
];
|
|
41627
41720
|
for (const candidate of candidates) {
|
|
41628
41721
|
if (serverAssetsUsable(candidate))
|
|
41629
41722
|
return candidate;
|
|
41630
41723
|
}
|
|
41631
|
-
return sourceServerAssets(
|
|
41724
|
+
return sourceServerAssets(join5(here, "..", ".."));
|
|
41632
41725
|
}
|
|
41633
41726
|
|
|
41634
41727
|
// ../../_shared/db-deploy/index.ts
|
|
41635
41728
|
init_src();
|
|
41636
|
-
import { existsSync as
|
|
41637
|
-
import { join as
|
|
41729
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync } from "node:fs";
|
|
41730
|
+
import { join as join6 } from "node:path";
|
|
41638
41731
|
var RESET_SQL = `
|
|
41639
41732
|
DROP TABLE IF EXISTS cerefox_chunks CASCADE;
|
|
41640
41733
|
DROP TABLE IF EXISTS cerefox_documents CASCADE;
|
|
@@ -41651,13 +41744,13 @@ CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
|
41651
41744
|
CREATE EXTENSION IF NOT EXISTS "vector";
|
|
41652
41745
|
`;
|
|
41653
41746
|
function listMigrationFiles(migrationsDir) {
|
|
41654
|
-
if (!
|
|
41747
|
+
if (!existsSync6(migrationsDir))
|
|
41655
41748
|
return [];
|
|
41656
41749
|
return readdirSync(migrationsDir).filter((n) => n.endsWith(".sql")).sort();
|
|
41657
41750
|
}
|
|
41658
41751
|
function buildDeploySteps(assets, opts = {}) {
|
|
41659
|
-
const schemaSql =
|
|
41660
|
-
const rpcsSql =
|
|
41752
|
+
const schemaSql = readFileSync5(assets.schemaFile, "utf8");
|
|
41753
|
+
const rpcsSql = readFileSync5(assets.rpcsFile, "utf8");
|
|
41661
41754
|
const steps = [];
|
|
41662
41755
|
if (opts.reset) {
|
|
41663
41756
|
steps.push({ label: "Reset: drop existing Cerefox objects", sql: RESET_SQL });
|
|
@@ -41750,7 +41843,7 @@ async function runDbMigrate(opts) {
|
|
|
41750
41843
|
}
|
|
41751
41844
|
const applied = [];
|
|
41752
41845
|
for (const f of pending) {
|
|
41753
|
-
const body =
|
|
41846
|
+
const body = readFileSync5(join6(opts.assets.migrationsDir, f), "utf8");
|
|
41754
41847
|
log(`Applying ${f}…`);
|
|
41755
41848
|
try {
|
|
41756
41849
|
await sql.begin(async (tx) => {
|
|
@@ -41778,7 +41871,7 @@ async function applyRpcs(opts) {
|
|
|
41778
41871
|
log("Refresh RPCs (rpcs.sql)…");
|
|
41779
41872
|
if (opts.dryRun)
|
|
41780
41873
|
return { ok: true };
|
|
41781
|
-
const rpcsSql =
|
|
41874
|
+
const rpcsSql = readFileSync5(opts.assets.rpcsFile, "utf8");
|
|
41782
41875
|
const sql = src_default(opts.dbUrl, { prepare: false, onnotice: () => {} });
|
|
41783
41876
|
try {
|
|
41784
41877
|
await sql.unsafe(rpcsSql);
|
|
@@ -41811,11 +41904,11 @@ function parseProjectRef(supabaseUrl) {
|
|
|
41811
41904
|
}
|
|
41812
41905
|
}
|
|
41813
41906
|
function listEdgeFunctions(functionsDir) {
|
|
41814
|
-
if (!
|
|
41907
|
+
if (!existsSync7(functionsDir))
|
|
41815
41908
|
return [];
|
|
41816
41909
|
return readdirSync2(functionsDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("cerefox-")).map((e) => e.name).sort();
|
|
41817
41910
|
}
|
|
41818
|
-
async function
|
|
41911
|
+
async function action9(options) {
|
|
41819
41912
|
const settings = loadSettings();
|
|
41820
41913
|
const assets = resolveServerAssets();
|
|
41821
41914
|
const doSchema = !options.functionsOnly;
|
|
@@ -41830,7 +41923,7 @@ async function action8(options) {
|
|
|
41830
41923
|
});
|
|
41831
41924
|
checks.push({
|
|
41832
41925
|
label: "Bundled schema assets present",
|
|
41833
|
-
ok:
|
|
41926
|
+
ok: existsSync7(assets.schemaFile) && existsSync7(assets.rpcsFile),
|
|
41834
41927
|
remediation: "Schema files not found. Reinstall the package, or run from a repo " + "clone (src/cerefox/db/)."
|
|
41835
41928
|
});
|
|
41836
41929
|
}
|
|
@@ -41998,10 +42091,116 @@ Proceed with deployment to Supabase?`, true);
|
|
|
41998
42091
|
println(c.dim("Verify with: cerefox doctor"));
|
|
41999
42092
|
}
|
|
42000
42093
|
function registerDeployServer(program2) {
|
|
42001
|
-
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(
|
|
42094
|
+
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);
|
|
42002
42095
|
}
|
|
42003
42096
|
|
|
42004
|
-
// src/cli/commands/
|
|
42097
|
+
// src/cli/commands/document-edit.ts
|
|
42098
|
+
init_cli_core();
|
|
42099
|
+
init_client();
|
|
42100
|
+
function parseMetaPair(pair) {
|
|
42101
|
+
const eq = pair.indexOf("=");
|
|
42102
|
+
if (eq <= 0)
|
|
42103
|
+
throw userError(`--set-meta expects key=value, got "${pair}".`);
|
|
42104
|
+
const key = pair.slice(0, eq).trim();
|
|
42105
|
+
const raw = pair.slice(eq + 1);
|
|
42106
|
+
let value = raw;
|
|
42107
|
+
try {
|
|
42108
|
+
value = JSON.parse(raw);
|
|
42109
|
+
} catch {
|
|
42110
|
+
value = raw;
|
|
42111
|
+
}
|
|
42112
|
+
return [key, value];
|
|
42113
|
+
}
|
|
42114
|
+
async function action10(documentId, options) {
|
|
42115
|
+
const hasTitle = options.title !== undefined;
|
|
42116
|
+
const sets = options.setMeta ?? [];
|
|
42117
|
+
const unsets = options.unsetMeta ?? [];
|
|
42118
|
+
if (!hasTitle && sets.length === 0 && unsets.length === 0) {
|
|
42119
|
+
throw userError("Nothing to edit — pass --title and/or --set-meta / --unset-meta.");
|
|
42120
|
+
}
|
|
42121
|
+
if (hasTitle && !options.title.trim())
|
|
42122
|
+
throw userError("--title cannot be empty.");
|
|
42123
|
+
const client = getClient();
|
|
42124
|
+
const { data: doc, error } = await client.raw.from("cerefox_documents").select("id, title, metadata, deleted_at").eq("id", documentId).maybeSingle();
|
|
42125
|
+
if (error)
|
|
42126
|
+
throw systemError(`Lookup failed: ${error.message}`);
|
|
42127
|
+
if (!doc)
|
|
42128
|
+
throw notFound(`Document ${documentId} not found.`);
|
|
42129
|
+
if (doc.deleted_at) {
|
|
42130
|
+
throw userError(`Document ${documentId} is soft-deleted — restore it first (cerefox document restore).`);
|
|
42131
|
+
}
|
|
42132
|
+
const metadata = { ...doc.metadata ?? {} };
|
|
42133
|
+
for (const pair of sets) {
|
|
42134
|
+
const [k, v] = parseMetaPair(pair);
|
|
42135
|
+
metadata[k] = v;
|
|
42136
|
+
}
|
|
42137
|
+
for (const k of unsets)
|
|
42138
|
+
delete metadata[k.trim()];
|
|
42139
|
+
const newTitle = hasTitle ? options.title.trim() : doc.title;
|
|
42140
|
+
const titleChanged = newTitle !== doc.title;
|
|
42141
|
+
const { error: updErr } = await client.raw.from("cerefox_documents").update({ title: newTitle, metadata, updated_at: new Date().toISOString() }).eq("id", documentId);
|
|
42142
|
+
if (updErr)
|
|
42143
|
+
throw systemError(`Update failed: ${updErr.message}`);
|
|
42144
|
+
if (titleChanged) {
|
|
42145
|
+
const { error: ftsErr } = await client.raw.rpc("cerefox_update_chunk_fts", {
|
|
42146
|
+
p_document_id: documentId,
|
|
42147
|
+
p_new_title: newTitle
|
|
42148
|
+
});
|
|
42149
|
+
if (ftsErr)
|
|
42150
|
+
throw systemError(`Title updated but FTS refresh failed: ${ftsErr.message}`);
|
|
42151
|
+
}
|
|
42152
|
+
const author = resolveAuthor(options.author);
|
|
42153
|
+
const authorType = resolveAuthorType(options.authorType);
|
|
42154
|
+
await client.raw.rpc("cerefox_create_audit_entry", {
|
|
42155
|
+
p_document_id: documentId,
|
|
42156
|
+
p_operation: "update-metadata",
|
|
42157
|
+
p_author: author,
|
|
42158
|
+
p_author_type: authorType,
|
|
42159
|
+
p_description: `Edited${titleChanged ? " title" : ""}` + (sets.length ? ` · set ${sets.length} meta key(s)` : "") + (unsets.length ? ` · unset ${unsets.length} meta key(s)` : "")
|
|
42160
|
+
});
|
|
42161
|
+
println(c.green(`✓ Edited "${newTitle}" (id: ${documentId}).`));
|
|
42162
|
+
if (titleChanged) {
|
|
42163
|
+
println(c.dim(" Title changed: FTS refreshed; semantic embeddings update on next `cerefox server reindex`."));
|
|
42164
|
+
}
|
|
42165
|
+
}
|
|
42166
|
+
function collect(value, prev) {
|
|
42167
|
+
return [...prev, value];
|
|
42168
|
+
}
|
|
42169
|
+
function registerDocumentEdit(parent) {
|
|
42170
|
+
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);
|
|
42171
|
+
}
|
|
42172
|
+
|
|
42173
|
+
// src/cli/commands/document-restore.ts
|
|
42174
|
+
init_cli_core();
|
|
42175
|
+
init_client();
|
|
42176
|
+
async function action11(documentId, options) {
|
|
42177
|
+
const client = getClient();
|
|
42178
|
+
const { data: doc, error } = await client.raw.from("cerefox_documents").select("id, title, deleted_at").eq("id", documentId).maybeSingle();
|
|
42179
|
+
if (error)
|
|
42180
|
+
throw systemError(`Lookup failed: ${error.message}`);
|
|
42181
|
+
if (!doc)
|
|
42182
|
+
throw notFound(`Document ${documentId} not found.`);
|
|
42183
|
+
if (!doc.deleted_at) {
|
|
42184
|
+
println(c.dim(`Document ${documentId} ("${doc.title}") is not soft-deleted — nothing to restore.`));
|
|
42185
|
+
return;
|
|
42186
|
+
}
|
|
42187
|
+
const author = resolveAuthor(options.author);
|
|
42188
|
+
const authorType = resolveAuthorType(options.authorType);
|
|
42189
|
+
if (author === "unknown") {
|
|
42190
|
+
warn("No --author / CEREFOX_AUTHOR_NAME set — audit log will record this restore as 'unknown'.");
|
|
42191
|
+
}
|
|
42192
|
+
await client.rpc("cerefox_restore_document", {
|
|
42193
|
+
p_document_id: documentId,
|
|
42194
|
+
p_author: author,
|
|
42195
|
+
p_author_type: authorType
|
|
42196
|
+
});
|
|
42197
|
+
println(c.green(`✓ Restored "${doc.title}" (id: ${documentId}) from the trash.`));
|
|
42198
|
+
}
|
|
42199
|
+
function registerDocumentRestore(parent) {
|
|
42200
|
+
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);
|
|
42201
|
+
}
|
|
42202
|
+
|
|
42203
|
+
// src/cli/commands/guides.ts
|
|
42005
42204
|
init_cli_core();
|
|
42006
42205
|
init_bundled_docs();
|
|
42007
42206
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
@@ -42012,36 +42211,117 @@ function openInBrowser(path) {
|
|
|
42012
42211
|
println(c.dim(`(could not auto-open; the file is at: ${path})`));
|
|
42013
42212
|
}
|
|
42014
42213
|
}
|
|
42015
|
-
function
|
|
42016
|
-
const
|
|
42017
|
-
if (options.list || !topic && !options.print) {
|
|
42018
|
-
if (docs.length === 0) {
|
|
42019
|
-
println("(no bundled docs found)");
|
|
42020
|
-
return;
|
|
42021
|
-
}
|
|
42022
|
-
println(c.bold("Available docs:"));
|
|
42023
|
-
println("");
|
|
42024
|
-
printTable(docs.map((d) => ({
|
|
42025
|
-
topic: d.topic,
|
|
42026
|
-
size_kb: Math.round(d.size / 1024) + " KB"
|
|
42027
|
-
})));
|
|
42028
|
-
println("");
|
|
42029
|
-
println(c.dim("Run `cerefox docs <topic>` to open in browser, or `--print` for stdout."));
|
|
42030
|
-
return;
|
|
42031
|
-
}
|
|
42032
|
-
const doc = topic ? readBundledDoc(topic) : null;
|
|
42214
|
+
function resolveDoc(topic) {
|
|
42215
|
+
const doc = readBundledDoc(topic);
|
|
42033
42216
|
if (!doc) {
|
|
42034
|
-
throw notFound(`No bundled
|
|
42217
|
+
throw notFound(`No bundled guide named "${topic}".`, "Run `cerefox guides list` to see available topics.");
|
|
42035
42218
|
}
|
|
42036
|
-
|
|
42037
|
-
|
|
42219
|
+
return doc;
|
|
42220
|
+
}
|
|
42221
|
+
function listAction() {
|
|
42222
|
+
const docs = listBundledDocs();
|
|
42223
|
+
if (docs.length === 0) {
|
|
42224
|
+
println("(no bundled guides found)");
|
|
42038
42225
|
return;
|
|
42039
42226
|
}
|
|
42227
|
+
println(c.bold("Available guides:"));
|
|
42228
|
+
println("");
|
|
42229
|
+
printTable(docs.map((d) => ({ topic: d.topic, size_kb: Math.round(d.size / 1024) + " KB" })));
|
|
42230
|
+
println("");
|
|
42231
|
+
println(c.dim("Open with `cerefox guides open <topic>` (browser) or `cerefox guides show <topic>` (stdout)."));
|
|
42232
|
+
}
|
|
42233
|
+
function openAction(topic) {
|
|
42234
|
+
const doc = resolveDoc(topic);
|
|
42040
42235
|
println(c.dim(`Opening ${doc.path} …`));
|
|
42041
42236
|
openInBrowser(doc.path);
|
|
42042
42237
|
}
|
|
42043
|
-
function
|
|
42044
|
-
|
|
42238
|
+
function showAction(topic) {
|
|
42239
|
+
println(resolveDoc(topic).content);
|
|
42240
|
+
}
|
|
42241
|
+
function registerGuides(parent) {
|
|
42242
|
+
parent.command("list").description("List the bundled documentation topics.").action(listAction);
|
|
42243
|
+
parent.command("open").description("Open a bundled guide in your browser.").argument("<topic>", "Topic (e.g. quickstart, connect-agents).").action(openAction);
|
|
42244
|
+
parent.command("show").description("Print a bundled guide to stdout.").argument("<topic>", "Topic (e.g. quickstart, connect-agents).").action(showAction);
|
|
42245
|
+
}
|
|
42246
|
+
|
|
42247
|
+
// src/cli/commands/project-create.ts
|
|
42248
|
+
init_cli_core();
|
|
42249
|
+
init_client();
|
|
42250
|
+
async function action12(name, options) {
|
|
42251
|
+
const trimmed = name.trim();
|
|
42252
|
+
if (!trimmed)
|
|
42253
|
+
throw userError("Project name is required.");
|
|
42254
|
+
const client = getClient();
|
|
42255
|
+
const { data, error } = await client.raw.from("cerefox_projects").insert({ name: trimmed, description: (options.description ?? "").trim() }).select("id, name, description").maybeSingle();
|
|
42256
|
+
if (error || !data) {
|
|
42257
|
+
throw systemError(`Create failed: ${error?.message ?? "no row returned"}`);
|
|
42258
|
+
}
|
|
42259
|
+
println(c.green(`✓ Created project "${data.name}" (id: ${data.id}).`));
|
|
42260
|
+
}
|
|
42261
|
+
function registerProjectCreate(parent) {
|
|
42262
|
+
parent.command("create").description("Create a new (empty) project.").argument("<name>", "Project name (must be unique).").option("--description <text>", "Optional project description.").action(action12);
|
|
42263
|
+
}
|
|
42264
|
+
|
|
42265
|
+
// src/cli/commands/project-edit.ts
|
|
42266
|
+
init_cli_core();
|
|
42267
|
+
init_client();
|
|
42268
|
+
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
42269
|
+
async function action13(target, options) {
|
|
42270
|
+
const update = {};
|
|
42271
|
+
if (options.name !== undefined) {
|
|
42272
|
+
const n = options.name.trim();
|
|
42273
|
+
if (!n)
|
|
42274
|
+
throw userError("--name cannot be empty.");
|
|
42275
|
+
update.name = n;
|
|
42276
|
+
}
|
|
42277
|
+
if (options.description !== undefined)
|
|
42278
|
+
update.description = options.description.trim();
|
|
42279
|
+
if (Object.keys(update).length === 0) {
|
|
42280
|
+
throw userError("Nothing to update — pass --name and/or --description.");
|
|
42281
|
+
}
|
|
42282
|
+
const client = getClient();
|
|
42283
|
+
const isUuid = UUID_RE2.test(target);
|
|
42284
|
+
const { data: project, error: lookupErr } = await client.raw.from("cerefox_projects").select("id, name").eq(isUuid ? "id" : "name", target).maybeSingle();
|
|
42285
|
+
if (lookupErr)
|
|
42286
|
+
throw systemError(`Lookup failed: ${lookupErr.message}`);
|
|
42287
|
+
if (!project)
|
|
42288
|
+
throw notFound(`Project "${target}" not found.`);
|
|
42289
|
+
const { data, error } = await client.raw.from("cerefox_projects").update(update).eq("id", project.id).select("id, name, description").maybeSingle();
|
|
42290
|
+
if (error || !data) {
|
|
42291
|
+
throw systemError(`Update failed: ${error?.message ?? "no row returned"}`);
|
|
42292
|
+
}
|
|
42293
|
+
println(c.green(`✓ Updated project "${data.name}" (id: ${data.id}).`));
|
|
42294
|
+
}
|
|
42295
|
+
function registerProjectEdit(parent) {
|
|
42296
|
+
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);
|
|
42297
|
+
}
|
|
42298
|
+
|
|
42299
|
+
// src/cli/commands/version-archive.ts
|
|
42300
|
+
init_cli_core();
|
|
42301
|
+
init_client();
|
|
42302
|
+
async function setArchived(versionId, archived, options) {
|
|
42303
|
+
const client = getClient();
|
|
42304
|
+
const { data, error } = await client.raw.from("cerefox_document_versions").update({ archived }).eq("id", versionId).select("document_id, version_number").maybeSingle();
|
|
42305
|
+
if (error)
|
|
42306
|
+
throw systemError(`Update failed: ${error.message}`);
|
|
42307
|
+
if (!data)
|
|
42308
|
+
throw notFound(`Version ${versionId} not found.`);
|
|
42309
|
+
const author = resolveAuthor(options.author);
|
|
42310
|
+
const authorType = resolveAuthorType(options.authorType);
|
|
42311
|
+
const op = archived ? "archive" : "unarchive";
|
|
42312
|
+
await client.raw.rpc("cerefox_create_audit_entry", {
|
|
42313
|
+
p_document_id: data.document_id,
|
|
42314
|
+
p_version_id: versionId,
|
|
42315
|
+
p_operation: op,
|
|
42316
|
+
p_author: author,
|
|
42317
|
+
p_author_type: authorType,
|
|
42318
|
+
p_description: `Version ${data.version_number} ${op}d`
|
|
42319
|
+
});
|
|
42320
|
+
println(c.green(`✓ Version ${data.version_number} (${versionId}) ${op}d.`));
|
|
42321
|
+
}
|
|
42322
|
+
function registerVersionArchive(parent) {
|
|
42323
|
+
parent.command("archive").description("Archive a document version (protect it from version cleanup).").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, true, options));
|
|
42324
|
+
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));
|
|
42045
42325
|
}
|
|
42046
42326
|
|
|
42047
42327
|
// ../../node_modules/.bun/ora@9.4.0/node_modules/ora/index.js
|
|
@@ -45431,12 +45711,12 @@ init_cli_core();
|
|
|
45431
45711
|
|
|
45432
45712
|
// src/cli/util/checks.ts
|
|
45433
45713
|
init_meta();
|
|
45434
|
-
import { existsSync as
|
|
45435
|
-
import { homedir as
|
|
45436
|
-
import { join as
|
|
45714
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7, realpathSync, statSync as statSync2 } from "node:fs";
|
|
45715
|
+
import { homedir as homedir5 } from "node:os";
|
|
45716
|
+
import { join as join8 } from "node:path";
|
|
45437
45717
|
|
|
45438
45718
|
// ../../_shared/ef-meta/index.ts
|
|
45439
|
-
var EF_VERSION = "0.
|
|
45719
|
+
var EF_VERSION = "0.9.1";
|
|
45440
45720
|
|
|
45441
45721
|
// src/cli/util/checks.ts
|
|
45442
45722
|
init_config();
|
|
@@ -45587,7 +45867,7 @@ function checkConfig() {
|
|
|
45587
45867
|
hint: "Run `cerefox init` to bootstrap."
|
|
45588
45868
|
};
|
|
45589
45869
|
}
|
|
45590
|
-
if (!
|
|
45870
|
+
if (!existsSync9(envPath)) {
|
|
45591
45871
|
return {
|
|
45592
45872
|
name: "config",
|
|
45593
45873
|
status: "error",
|
|
@@ -45715,9 +45995,9 @@ var SCHEMA_VERSION_RE = /^--\s*@version:\s*(\S+)/m;
|
|
|
45715
45995
|
function readBundledSchemaVersion() {
|
|
45716
45996
|
try {
|
|
45717
45997
|
const assets = resolveServerAssets();
|
|
45718
|
-
if (!
|
|
45998
|
+
if (!existsSync9(assets.schemaFile))
|
|
45719
45999
|
return null;
|
|
45720
|
-
const m =
|
|
46000
|
+
const m = readFileSync7(assets.schemaFile, "utf8").match(SCHEMA_VERSION_RE);
|
|
45721
46001
|
return m ? m[1] : null;
|
|
45722
46002
|
} catch {
|
|
45723
46003
|
return null;
|
|
@@ -45786,10 +46066,10 @@ async function checkSchemaVersion() {
|
|
|
45786
46066
|
}
|
|
45787
46067
|
}
|
|
45788
46068
|
function hasCerefoxInJsonFile(path) {
|
|
45789
|
-
if (!
|
|
46069
|
+
if (!existsSync9(path))
|
|
45790
46070
|
return false;
|
|
45791
46071
|
try {
|
|
45792
|
-
const parsed = JSON.parse(
|
|
46072
|
+
const parsed = JSON.parse(readFileSync7(path, "utf8"));
|
|
45793
46073
|
const mcpServers = parsed.mcpServers;
|
|
45794
46074
|
return Boolean(mcpServers && typeof mcpServers === "object" && "cerefox" in mcpServers);
|
|
45795
46075
|
} catch {
|
|
@@ -45797,10 +46077,10 @@ function hasCerefoxInJsonFile(path) {
|
|
|
45797
46077
|
}
|
|
45798
46078
|
}
|
|
45799
46079
|
function checkMcpConfigs() {
|
|
45800
|
-
const home =
|
|
45801
|
-
const claudeCodeUser =
|
|
45802
|
-
const claudeCodeProj =
|
|
45803
|
-
const claudeDesktop = process.platform === "darwin" ?
|
|
46080
|
+
const home = homedir5();
|
|
46081
|
+
const claudeCodeUser = join8(home, ".claude.json");
|
|
46082
|
+
const claudeCodeProj = join8(process.cwd(), ".mcp.json");
|
|
46083
|
+
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");
|
|
45804
46084
|
const found = [];
|
|
45805
46085
|
if (hasCerefoxInJsonFile(claudeCodeUser))
|
|
45806
46086
|
found.push("Claude Code (user)");
|
|
@@ -45823,10 +46103,10 @@ function checkMcpConfigs() {
|
|
|
45823
46103
|
};
|
|
45824
46104
|
}
|
|
45825
46105
|
function checkLegacyShadowEnv() {
|
|
45826
|
-
const home =
|
|
45827
|
-
const homeEnv =
|
|
45828
|
-
const cwdEnv =
|
|
45829
|
-
if (!
|
|
46106
|
+
const home = homedir5();
|
|
46107
|
+
const homeEnv = join8(home, USER_STATE_DIR_NAME, ".env");
|
|
46108
|
+
const cwdEnv = join8(process.cwd(), ".env");
|
|
46109
|
+
if (!existsSync9(homeEnv) || !existsSync9(cwdEnv))
|
|
45830
46110
|
return null;
|
|
45831
46111
|
try {
|
|
45832
46112
|
if (realpathSync(homeEnv) === realpathSync(cwdEnv))
|
|
@@ -46001,7 +46281,7 @@ function symbol(status) {
|
|
|
46001
46281
|
return cErr.dim("ℹ");
|
|
46002
46282
|
}
|
|
46003
46283
|
}
|
|
46004
|
-
async function
|
|
46284
|
+
async function action14(options) {
|
|
46005
46285
|
const useSpinner = !options.json && process.stderr.isTTY;
|
|
46006
46286
|
const spinner = useSpinner ? ora({ text: "Starting checks…", spinner: "dots", stream: process.stderr }).start() : null;
|
|
46007
46287
|
const results = await runAllChecks({
|
|
@@ -46058,13 +46338,13 @@ async function action10(options) {
|
|
|
46058
46338
|
}
|
|
46059
46339
|
}
|
|
46060
46340
|
function registerDoctor(program2) {
|
|
46061
|
-
program2.command("doctor").description("Run diagnostic checks against the installed Cerefox.").option("--json", "Emit machine-readable JSON (no colours, structured output).").action(
|
|
46341
|
+
program2.command("doctor").description("Run diagnostic checks against the installed Cerefox.").option("--json", "Emit machine-readable JSON (no colours, structured output).").action(action14);
|
|
46062
46342
|
}
|
|
46063
46343
|
|
|
46064
46344
|
// src/cli/commands/get-audit-log.ts
|
|
46065
46345
|
init_cli_core();
|
|
46066
46346
|
init_client();
|
|
46067
|
-
async function
|
|
46347
|
+
async function action15(options) {
|
|
46068
46348
|
const limit = parsePositiveInt(options.limit, "--limit", 50);
|
|
46069
46349
|
const client = getClient();
|
|
46070
46350
|
const data = await client.rpc("cerefox_list_audit_entries", {
|
|
@@ -46102,14 +46382,14 @@ async function action11(options) {
|
|
|
46102
46382
|
})));
|
|
46103
46383
|
}
|
|
46104
46384
|
function registerGetAuditLog(program2) {
|
|
46105
|
-
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(
|
|
46385
|
+
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);
|
|
46106
46386
|
}
|
|
46107
46387
|
|
|
46108
46388
|
// src/cli/commands/get-doc.ts
|
|
46109
46389
|
init_cli_core();
|
|
46110
46390
|
init_cli_core();
|
|
46111
46391
|
init_client();
|
|
46112
|
-
async function
|
|
46392
|
+
async function action16(documentId, options) {
|
|
46113
46393
|
const client = getClient();
|
|
46114
46394
|
const rows = await client.rpc("cerefox_get_document", {
|
|
46115
46395
|
p_document_id: documentId,
|
|
@@ -46139,18 +46419,18 @@ async function action12(documentId, options) {
|
|
|
46139
46419
|
println(doc.full_content);
|
|
46140
46420
|
}
|
|
46141
46421
|
function registerGetDoc(program2) {
|
|
46142
|
-
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(
|
|
46422
|
+
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);
|
|
46143
46423
|
}
|
|
46144
46424
|
|
|
46145
46425
|
// src/cli/commands/ingest.ts
|
|
46146
46426
|
init_dist4();
|
|
46147
46427
|
init_cli_core();
|
|
46148
46428
|
init_config();
|
|
46149
|
-
import { readFileSync as
|
|
46429
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
46150
46430
|
import { basename as basename2, extname as extname2 } from "node:path";
|
|
46151
46431
|
|
|
46152
46432
|
// src/ingestion/pipeline.ts
|
|
46153
|
-
import { readFileSync as
|
|
46433
|
+
import { readFileSync as readFileSync8 } from "node:fs";
|
|
46154
46434
|
import { basename, extname, resolve as resolve3 } from "node:path";
|
|
46155
46435
|
|
|
46156
46436
|
// ../../_shared/ingest/chunker.ts
|
|
@@ -46834,7 +47114,7 @@ ${c2.content}`);
|
|
|
46834
47114
|
};
|
|
46835
47115
|
}
|
|
46836
47116
|
async ingestFile(path, opts = {}) {
|
|
46837
|
-
const text =
|
|
47117
|
+
const text = readFileSync8(path, "utf8");
|
|
46838
47118
|
const absPath = resolve3(path);
|
|
46839
47119
|
const stem = basename(absPath, extname(absPath));
|
|
46840
47120
|
return this.ingestText({
|
|
@@ -46868,7 +47148,7 @@ async function readContent(path, paste) {
|
|
|
46868
47148
|
}
|
|
46869
47149
|
let content;
|
|
46870
47150
|
try {
|
|
46871
|
-
content =
|
|
47151
|
+
content = readFileSync9(path, "utf8");
|
|
46872
47152
|
} catch (err) {
|
|
46873
47153
|
const msg = err instanceof Error ? err.message : String(err);
|
|
46874
47154
|
throw userError(`Cannot read ${path}: ${msg}`);
|
|
@@ -46876,7 +47156,7 @@ async function readContent(path, paste) {
|
|
|
46876
47156
|
const titleFromPath = basename2(path, extname2(path));
|
|
46877
47157
|
return { content, titleFromPath };
|
|
46878
47158
|
}
|
|
46879
|
-
async function
|
|
47159
|
+
async function action17(path, options) {
|
|
46880
47160
|
const { content, titleFromPath } = await readContent(path, Boolean(options.paste));
|
|
46881
47161
|
const title = options.title ?? titleFromPath;
|
|
46882
47162
|
if (!title || title.trim() === "") {
|
|
@@ -46948,7 +47228,7 @@ async function action13(path, options) {
|
|
|
46948
47228
|
}
|
|
46949
47229
|
}
|
|
46950
47230
|
function registerIngest(program2) {
|
|
46951
|
-
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(
|
|
47231
|
+
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);
|
|
46952
47232
|
}
|
|
46953
47233
|
|
|
46954
47234
|
// src/cli/commands/ingest-dir.ts
|
|
@@ -46957,7 +47237,7 @@ init_cli_core();
|
|
|
46957
47237
|
init_config();
|
|
46958
47238
|
var import_cli_progress = __toESM(require_cli_progress(), 1);
|
|
46959
47239
|
import { readdirSync as readdirSync4, statSync as statSync3 } from "node:fs";
|
|
46960
|
-
import { basename as basename3, extname as extname3, join as
|
|
47240
|
+
import { basename as basename3, extname as extname3, join as join9 } from "node:path";
|
|
46961
47241
|
function walk(dir, extensions) {
|
|
46962
47242
|
let entries;
|
|
46963
47243
|
try {
|
|
@@ -46967,7 +47247,7 @@ function walk(dir, extensions) {
|
|
|
46967
47247
|
}
|
|
46968
47248
|
const files = [];
|
|
46969
47249
|
for (const name of entries) {
|
|
46970
|
-
const full =
|
|
47250
|
+
const full = join9(dir, name);
|
|
46971
47251
|
let stat;
|
|
46972
47252
|
try {
|
|
46973
47253
|
stat = statSync3(full);
|
|
@@ -46984,7 +47264,7 @@ function walk(dir, extensions) {
|
|
|
46984
47264
|
}
|
|
46985
47265
|
return files;
|
|
46986
47266
|
}
|
|
46987
|
-
async function
|
|
47267
|
+
async function action18(dir, options) {
|
|
46988
47268
|
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));
|
|
46989
47269
|
const files = walk(dir, extensions);
|
|
46990
47270
|
if (files.length === 0) {
|
|
@@ -47057,7 +47337,7 @@ async function action14(dir, options) {
|
|
|
47057
47337
|
}
|
|
47058
47338
|
}
|
|
47059
47339
|
function registerIngestDir(program2) {
|
|
47060
|
-
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(
|
|
47340
|
+
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);
|
|
47061
47341
|
}
|
|
47062
47342
|
|
|
47063
47343
|
// src/cli/commands/init.ts
|
|
@@ -47067,20 +47347,20 @@ import { spawnSync as spawnSync4 } from "node:child_process";
|
|
|
47067
47347
|
import {
|
|
47068
47348
|
chmodSync,
|
|
47069
47349
|
copyFileSync as copyFileSync2,
|
|
47070
|
-
existsSync as
|
|
47350
|
+
existsSync as existsSync10,
|
|
47071
47351
|
mkdirSync as mkdirSync3,
|
|
47072
|
-
readFileSync as
|
|
47073
|
-
writeFileSync as
|
|
47352
|
+
readFileSync as readFileSync11,
|
|
47353
|
+
writeFileSync as writeFileSync4
|
|
47074
47354
|
} from "node:fs";
|
|
47075
|
-
import { homedir as
|
|
47076
|
-
import { dirname as dirname4, join as
|
|
47355
|
+
import { homedir as homedir6 } from "node:os";
|
|
47356
|
+
import { dirname as dirname4, join as join10 } from "node:path";
|
|
47077
47357
|
async function readConfigFile(path) {
|
|
47078
|
-
if (!
|
|
47358
|
+
if (!existsSync10(path)) {
|
|
47079
47359
|
throw userError(`--config file not found: ${path}`);
|
|
47080
47360
|
}
|
|
47081
47361
|
let parsed;
|
|
47082
47362
|
try {
|
|
47083
|
-
parsed = JSON.parse(
|
|
47363
|
+
parsed = JSON.parse(readFileSync11(path, "utf8"));
|
|
47084
47364
|
} catch (err) {
|
|
47085
47365
|
throw userError(`--config: invalid JSON in ${path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
47086
47366
|
}
|
|
@@ -47122,7 +47402,7 @@ function parseDotEnvFile(content) {
|
|
|
47122
47402
|
return map;
|
|
47123
47403
|
}
|
|
47124
47404
|
function answersFromEnvFile(path) {
|
|
47125
|
-
const parsed = parseDotEnvFile(
|
|
47405
|
+
const parsed = parseDotEnvFile(readFileSync11(path, "utf8"));
|
|
47126
47406
|
const required = ["CEREFOX_SUPABASE_URL", "CEREFOX_SUPABASE_KEY", "OPENAI_API_KEY"];
|
|
47127
47407
|
for (const key of required) {
|
|
47128
47408
|
if (!parsed[key] || parsed[key].trim() === "") {
|
|
@@ -47378,7 +47658,7 @@ async function postWriteLifecycle(envPath, options) {
|
|
|
47378
47658
|
}
|
|
47379
47659
|
function writeAnswersTo(target, answers) {
|
|
47380
47660
|
mkdirSync3(dirname4(target), { recursive: true });
|
|
47381
|
-
|
|
47661
|
+
writeFileSync4(target, buildEnvFile(answers), "utf8");
|
|
47382
47662
|
if (process.platform !== "win32") {
|
|
47383
47663
|
try {
|
|
47384
47664
|
chmodSync(target, 384);
|
|
@@ -47387,13 +47667,13 @@ function writeAnswersTo(target, answers) {
|
|
|
47387
47667
|
}
|
|
47388
47668
|
}
|
|
47389
47669
|
}
|
|
47390
|
-
async function
|
|
47391
|
-
const homeEnv =
|
|
47392
|
-
const cwdEnv =
|
|
47670
|
+
async function action20(options) {
|
|
47671
|
+
const homeEnv = join10(homedir6(), USER_STATE_DIR_NAME, ".env");
|
|
47672
|
+
const cwdEnv = join10(process.cwd(), ".env");
|
|
47393
47673
|
const explicitDir = (process.env.CEREFOX_CONFIG_DIR ?? "").trim();
|
|
47394
47674
|
if (explicitDir) {
|
|
47395
47675
|
const target2 = resolveEnvFile();
|
|
47396
|
-
if (
|
|
47676
|
+
if (existsSync10(target2) && !options.force) {
|
|
47397
47677
|
println(c.yellow(`⚠ Config already exists at ${target2}.`));
|
|
47398
47678
|
const ok2 = await confirm("Overwrite?", true);
|
|
47399
47679
|
if (!ok2) {
|
|
@@ -47415,7 +47695,7 @@ async function action16(options) {
|
|
|
47415
47695
|
await postWriteLifecycle(target2, options);
|
|
47416
47696
|
return;
|
|
47417
47697
|
}
|
|
47418
|
-
if (
|
|
47698
|
+
if (existsSync10(homeEnv) && !options.force) {
|
|
47419
47699
|
println(c.yellow(`⚠ Config already exists at ${homeEnv}.`));
|
|
47420
47700
|
const ok2 = await confirm("Overwrite?", true);
|
|
47421
47701
|
if (!ok2) {
|
|
@@ -47436,7 +47716,7 @@ async function action16(options) {
|
|
|
47436
47716
|
await postWriteLifecycle(homeEnv, options);
|
|
47437
47717
|
return;
|
|
47438
47718
|
}
|
|
47439
|
-
if (
|
|
47719
|
+
if (existsSync10(cwdEnv) && !options.force && !options.config) {
|
|
47440
47720
|
printMigrationMenu(cwdEnv, homeEnv);
|
|
47441
47721
|
const ch = await promptMigrationChoice();
|
|
47442
47722
|
println("");
|
|
@@ -47496,13 +47776,13 @@ async function action16(options) {
|
|
|
47496
47776
|
await postWriteLifecycle(target, options);
|
|
47497
47777
|
}
|
|
47498
47778
|
function registerInit(program2) {
|
|
47499
|
-
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(
|
|
47779
|
+
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);
|
|
47500
47780
|
}
|
|
47501
47781
|
|
|
47502
47782
|
// src/cli/commands/list-docs.ts
|
|
47503
47783
|
init_cli_core();
|
|
47504
47784
|
init_client();
|
|
47505
|
-
async function
|
|
47785
|
+
async function action21(options) {
|
|
47506
47786
|
const limit = parsePositiveInt(options.limit, "--limit", 100);
|
|
47507
47787
|
const client = getClient();
|
|
47508
47788
|
let projectId;
|
|
@@ -47557,13 +47837,13 @@ async function action17(options) {
|
|
|
47557
47837
|
})));
|
|
47558
47838
|
}
|
|
47559
47839
|
function registerListDocs(program2) {
|
|
47560
|
-
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(
|
|
47840
|
+
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);
|
|
47561
47841
|
}
|
|
47562
47842
|
|
|
47563
47843
|
// src/cli/commands/list-metadata-keys.ts
|
|
47564
47844
|
init_cli_core();
|
|
47565
47845
|
init_client();
|
|
47566
|
-
async function
|
|
47846
|
+
async function action22(options) {
|
|
47567
47847
|
const client = getClient();
|
|
47568
47848
|
const data = await client.rpc("cerefox_list_metadata_keys");
|
|
47569
47849
|
if (data === null) {
|
|
@@ -47591,13 +47871,13 @@ async function action18(options) {
|
|
|
47591
47871
|
})));
|
|
47592
47872
|
}
|
|
47593
47873
|
function registerListMetadataKeys(program2) {
|
|
47594
|
-
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(
|
|
47874
|
+
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);
|
|
47595
47875
|
}
|
|
47596
47876
|
|
|
47597
47877
|
// src/cli/commands/list-projects.ts
|
|
47598
47878
|
init_cli_core();
|
|
47599
47879
|
init_client();
|
|
47600
|
-
async function
|
|
47880
|
+
async function action23(options) {
|
|
47601
47881
|
const client = getClient();
|
|
47602
47882
|
const { data, error: error2 } = await client.raw.from("cerefox_projects").select("id, name, description, created_at").order("name", { ascending: true });
|
|
47603
47883
|
if (error2) {
|
|
@@ -47626,13 +47906,13 @@ async function action19(options) {
|
|
|
47626
47906
|
})), "(no projects)");
|
|
47627
47907
|
}
|
|
47628
47908
|
function registerListProjects(program2) {
|
|
47629
|
-
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(
|
|
47909
|
+
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);
|
|
47630
47910
|
}
|
|
47631
47911
|
|
|
47632
47912
|
// src/cli/commands/list-versions.ts
|
|
47633
47913
|
init_cli_core();
|
|
47634
47914
|
init_client();
|
|
47635
|
-
async function
|
|
47915
|
+
async function action24(documentId, options) {
|
|
47636
47916
|
const client = getClient();
|
|
47637
47917
|
const data = await client.rpc("cerefox_list_document_versions", {
|
|
47638
47918
|
p_document_id: documentId
|
|
@@ -47673,7 +47953,7 @@ async function action20(documentId, options) {
|
|
|
47673
47953
|
})));
|
|
47674
47954
|
}
|
|
47675
47955
|
function registerListVersions(program2) {
|
|
47676
|
-
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(
|
|
47956
|
+
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);
|
|
47677
47957
|
}
|
|
47678
47958
|
|
|
47679
47959
|
// src/cli/commands/mcp.ts
|
|
@@ -47688,7 +47968,7 @@ function registerMcp(program2) {
|
|
|
47688
47968
|
// src/cli/commands/metadata-search.ts
|
|
47689
47969
|
init_cli_core();
|
|
47690
47970
|
init_client();
|
|
47691
|
-
async function
|
|
47971
|
+
async function action25(options) {
|
|
47692
47972
|
const metadataFilter = parseJsonObjectArg(options.metadataFilter, "--metadata-filter");
|
|
47693
47973
|
if (!metadataFilter || Object.keys(metadataFilter).length === 0) {
|
|
47694
47974
|
throw userError("--metadata-filter is required and must be a non-empty JSON object.", `Example: --metadata-filter '{"type":"decision-log"}'.`);
|
|
@@ -47751,7 +48031,7 @@ async function action21(options) {
|
|
|
47751
48031
|
}
|
|
47752
48032
|
}
|
|
47753
48033
|
function registerMetadataSearch(program2) {
|
|
47754
|
-
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(
|
|
48034
|
+
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);
|
|
47755
48035
|
}
|
|
47756
48036
|
|
|
47757
48037
|
// src/cli/commands/reindex.ts
|
|
@@ -47759,7 +48039,7 @@ init_dist4();
|
|
|
47759
48039
|
init_cli_core();
|
|
47760
48040
|
init_config();
|
|
47761
48041
|
var DEFAULT_MODEL = "text-embedding-3-small";
|
|
47762
|
-
async function
|
|
48042
|
+
async function action26(options) {
|
|
47763
48043
|
const settings = loadSettings();
|
|
47764
48044
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
47765
48045
|
throw userError("Supabase credentials not configured — run `cerefox init` first.");
|
|
@@ -47838,41 +48118,41 @@ ${c2.content}`;
|
|
|
47838
48118
|
}
|
|
47839
48119
|
}
|
|
47840
48120
|
function registerReindex(program2) {
|
|
47841
|
-
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(
|
|
48121
|
+
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);
|
|
47842
48122
|
}
|
|
47843
48123
|
|
|
47844
48124
|
// src/cli/commands/restore.ts
|
|
47845
48125
|
init_cli_core();
|
|
47846
48126
|
init_client();
|
|
47847
|
-
import { existsSync as
|
|
47848
|
-
import { homedir as
|
|
47849
|
-
import { join as
|
|
48127
|
+
import { existsSync as existsSync11, readFileSync as readFileSync12, readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
|
|
48128
|
+
import { homedir as homedir7 } from "node:os";
|
|
48129
|
+
import { join as join11, resolve as resolve4 } from "node:path";
|
|
47850
48130
|
function expandHome2(path) {
|
|
47851
48131
|
if (path === "~")
|
|
47852
|
-
return
|
|
48132
|
+
return homedir7();
|
|
47853
48133
|
if (path.startsWith("~/"))
|
|
47854
|
-
return
|
|
48134
|
+
return join11(homedir7(), path.slice(2));
|
|
47855
48135
|
return path;
|
|
47856
48136
|
}
|
|
47857
48137
|
function resolveBackupFile(target) {
|
|
47858
48138
|
const path = resolve4(expandHome2(target));
|
|
47859
|
-
if (!
|
|
48139
|
+
if (!existsSync11(path)) {
|
|
47860
48140
|
throw userError(`Backup path not found: ${target}`);
|
|
47861
48141
|
}
|
|
47862
48142
|
const stat = statSync4(path);
|
|
47863
48143
|
if (stat.isFile())
|
|
47864
48144
|
return path;
|
|
47865
|
-
const candidates = readdirSync5(path).filter((n) => n.endsWith(".json") && n.startsWith("cerefox-")).map((n) => ({ name: n, mtime: statSync4(
|
|
48145
|
+
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);
|
|
47866
48146
|
if (candidates.length === 0) {
|
|
47867
48147
|
throw userError(`No cerefox-*.json files in ${path}`);
|
|
47868
48148
|
}
|
|
47869
|
-
return
|
|
48149
|
+
return join11(path, candidates[0].name);
|
|
47870
48150
|
}
|
|
47871
|
-
async function
|
|
48151
|
+
async function action27(target, options) {
|
|
47872
48152
|
const file = resolveBackupFile(target);
|
|
47873
48153
|
let payload;
|
|
47874
48154
|
try {
|
|
47875
|
-
payload = JSON.parse(
|
|
48155
|
+
payload = JSON.parse(readFileSync12(file, "utf8"));
|
|
47876
48156
|
} catch (err) {
|
|
47877
48157
|
throw userError(`Could not parse backup file ${file}: ${err instanceof Error ? err.message : String(err)}`);
|
|
47878
48158
|
}
|
|
@@ -47924,7 +48204,7 @@ async function action23(target, options) {
|
|
|
47924
48204
|
}
|
|
47925
48205
|
}
|
|
47926
48206
|
function registerRestore(program2) {
|
|
47927
|
-
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(
|
|
48207
|
+
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);
|
|
47928
48208
|
}
|
|
47929
48209
|
|
|
47930
48210
|
// src/cli/commands/search.ts
|
|
@@ -47949,7 +48229,7 @@ async function embedQuery(query) {
|
|
|
47949
48229
|
}
|
|
47950
48230
|
|
|
47951
48231
|
// src/cli/commands/search.ts
|
|
47952
|
-
async function
|
|
48232
|
+
async function action28(query, options) {
|
|
47953
48233
|
if (!query || query.trim() === "") {
|
|
47954
48234
|
throw userError("Empty query.");
|
|
47955
48235
|
}
|
|
@@ -48038,8 +48318,14 @@ async function action24(query, options) {
|
|
|
48038
48318
|
p_result_count: accepted.length
|
|
48039
48319
|
}).then(() => {}, () => {});
|
|
48040
48320
|
if (options.json) {
|
|
48321
|
+
const jsonResults = options.onlyMetadata ? accepted.map((r) => {
|
|
48322
|
+
const copy = { ...r };
|
|
48323
|
+
delete copy.full_content;
|
|
48324
|
+
delete copy.content;
|
|
48325
|
+
return copy;
|
|
48326
|
+
}) : accepted;
|
|
48041
48327
|
printJson({
|
|
48042
|
-
results:
|
|
48328
|
+
results: jsonResults,
|
|
48043
48329
|
query,
|
|
48044
48330
|
mode,
|
|
48045
48331
|
match_count: matchCount,
|
|
@@ -48059,13 +48345,25 @@ async function action24(query, options) {
|
|
|
48059
48345
|
const doc2 = row;
|
|
48060
48346
|
const title = doc2.doc_title ?? "Untitled";
|
|
48061
48347
|
const docId = doc2.document_id ? ` [id: ${doc2.document_id}]` : "";
|
|
48062
|
-
const score = doc2.best_score != null ? `
|
|
48063
|
-
const
|
|
48064
|
-
|
|
48348
|
+
const score = doc2.best_score != null ? ` · score ${doc2.best_score.toFixed(3)}` : "";
|
|
48349
|
+
const counts = ` · ${doc2.chunk_count} chunk${doc2.chunk_count === 1 ? "" : "s"} · ${doc2.total_chars.toLocaleString()} chars`;
|
|
48350
|
+
const kind = doc2.is_partial ? " · partial" : " · full";
|
|
48351
|
+
println(c.bold(`## ${title}${docId}${score}${counts}${kind}`));
|
|
48352
|
+
const bestMatch = doc2.best_chunk_heading_path?.length ? doc2.best_chunk_heading_path.join(" › ") : null;
|
|
48353
|
+
const updated = doc2.doc_updated_at ? doc2.doc_updated_at.slice(0, 10) : null;
|
|
48354
|
+
if (bestMatch || updated) {
|
|
48355
|
+
const bits = [
|
|
48356
|
+
bestMatch ? `best match: ${bestMatch}` : null,
|
|
48357
|
+
updated ? `updated ${updated}` : null
|
|
48358
|
+
].filter(Boolean);
|
|
48359
|
+
println(c.dim(` ${bits.join(" · ")}`));
|
|
48360
|
+
}
|
|
48361
|
+
if (options.onlyMetadata)
|
|
48362
|
+
continue;
|
|
48065
48363
|
println("");
|
|
48066
48364
|
println(doc2.full_content ?? "");
|
|
48067
48365
|
println("");
|
|
48068
|
-
println(c.dim("
|
|
48366
|
+
println(c.dim("════════════════════════════════════════"));
|
|
48069
48367
|
println("");
|
|
48070
48368
|
} else {
|
|
48071
48369
|
const chunk = row;
|
|
@@ -48083,7 +48381,7 @@ async function action24(query, options) {
|
|
|
48083
48381
|
}
|
|
48084
48382
|
}
|
|
48085
48383
|
function registerSearch(program2) {
|
|
48086
|
-
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(
|
|
48384
|
+
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);
|
|
48087
48385
|
}
|
|
48088
48386
|
|
|
48089
48387
|
// src/cli/commands/self-update.ts
|
|
@@ -48130,7 +48428,7 @@ async function fetchLatestVersion() {
|
|
|
48130
48428
|
}
|
|
48131
48429
|
return body.version;
|
|
48132
48430
|
}
|
|
48133
|
-
async function
|
|
48431
|
+
async function action29(options) {
|
|
48134
48432
|
let target;
|
|
48135
48433
|
try {
|
|
48136
48434
|
target = options.version ?? await fetchLatestVersion();
|
|
@@ -48182,7 +48480,7 @@ async function action25(options) {
|
|
|
48182
48480
|
}
|
|
48183
48481
|
function registerSelfUpdate(program2) {
|
|
48184
48482
|
const desc = "Upgrade Cerefox in place. Alias: `cerefox upgrade`.";
|
|
48185
|
-
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(
|
|
48483
|
+
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);
|
|
48186
48484
|
declaration(program2.command("self-update"));
|
|
48187
48485
|
declaration(program2.command("upgrade"));
|
|
48188
48486
|
}
|
|
@@ -48201,7 +48499,7 @@ function symbol2(status) {
|
|
|
48201
48499
|
return cErr.dim("ℹ");
|
|
48202
48500
|
}
|
|
48203
48501
|
}
|
|
48204
|
-
async function
|
|
48502
|
+
async function action30(options) {
|
|
48205
48503
|
const useSpinner = !options.json && process.stderr.isTTY;
|
|
48206
48504
|
const spinner = useSpinner ? ora({ text: "Starting checks…", spinner: "dots", stream: process.stderr }).start() : null;
|
|
48207
48505
|
const results = await runFastChecks({
|
|
@@ -48222,105 +48520,7 @@ async function action26(options) {
|
|
|
48222
48520
|
}
|
|
48223
48521
|
}
|
|
48224
48522
|
function registerStatus(program2) {
|
|
48225
|
-
program2.command("status").description("Quick sanity check (fast subset of `cerefox doctor`).").option("--json", "Emit machine-readable JSON.").action(
|
|
48226
|
-
}
|
|
48227
|
-
|
|
48228
|
-
// src/cli/commands/sync-docs.ts
|
|
48229
|
-
init_cli_core();
|
|
48230
|
-
init_mcp_tools();
|
|
48231
|
-
init_config();
|
|
48232
|
-
init_client();
|
|
48233
|
-
import {
|
|
48234
|
-
existsSync as existsSync11,
|
|
48235
|
-
readFileSync as readFileSync12,
|
|
48236
|
-
readdirSync as readdirSync6,
|
|
48237
|
-
statSync as statSync5
|
|
48238
|
-
} from "node:fs";
|
|
48239
|
-
import { basename as basename5, extname as extname5, join as join11, relative } from "node:path";
|
|
48240
|
-
var ROOT_LEVEL_DOCS = ["README.md", "AGENT_GUIDE.md", "AGENT_QUICK_REFERENCE.md"];
|
|
48241
|
-
function walkMarkdown(dir) {
|
|
48242
|
-
const out = [];
|
|
48243
|
-
if (!existsSync11(dir))
|
|
48244
|
-
return out;
|
|
48245
|
-
for (const name of readdirSync6(dir)) {
|
|
48246
|
-
const full = join11(dir, name);
|
|
48247
|
-
let stat;
|
|
48248
|
-
try {
|
|
48249
|
-
stat = statSync5(full);
|
|
48250
|
-
} catch {
|
|
48251
|
-
continue;
|
|
48252
|
-
}
|
|
48253
|
-
if (stat.isDirectory()) {
|
|
48254
|
-
out.push(...walkMarkdown(full));
|
|
48255
|
-
} else if (stat.isFile() && name.toLowerCase().endsWith(".md")) {
|
|
48256
|
-
out.push(full);
|
|
48257
|
-
}
|
|
48258
|
-
}
|
|
48259
|
-
return out;
|
|
48260
|
-
}
|
|
48261
|
-
async function action27(options) {
|
|
48262
|
-
const cwd = process.cwd();
|
|
48263
|
-
const project = options.project ?? "cerefox";
|
|
48264
|
-
const targets = [];
|
|
48265
|
-
for (const rel of ROOT_LEVEL_DOCS) {
|
|
48266
|
-
const abs = join11(cwd, rel);
|
|
48267
|
-
if (existsSync11(abs))
|
|
48268
|
-
targets.push({ abs, rel });
|
|
48269
|
-
}
|
|
48270
|
-
for (const abs of walkMarkdown(join11(cwd, "docs"))) {
|
|
48271
|
-
targets.push({ abs, rel: relative(cwd, abs) });
|
|
48272
|
-
}
|
|
48273
|
-
if (targets.length === 0) {
|
|
48274
|
-
println(c.dim(`(no markdown files found in ${cwd})`));
|
|
48275
|
-
return;
|
|
48276
|
-
}
|
|
48277
|
-
println(c.bold(`Syncing ${targets.length} markdown file(s) to project "${project}"`));
|
|
48278
|
-
if (options.dryRun)
|
|
48279
|
-
println(c.yellow("(dry run — no writes)"));
|
|
48280
|
-
println("");
|
|
48281
|
-
if (options.dryRun) {
|
|
48282
|
-
printTable(targets.map((t) => ({
|
|
48283
|
-
file: t.rel,
|
|
48284
|
-
title: basename5(t.abs, extname5(t.abs))
|
|
48285
|
-
})));
|
|
48286
|
-
return;
|
|
48287
|
-
}
|
|
48288
|
-
const client = getClient();
|
|
48289
|
-
const settings = loadSettings();
|
|
48290
|
-
const author = resolveAuthor(undefined);
|
|
48291
|
-
const authorType = resolveAuthorType("agent");
|
|
48292
|
-
const outcomes = [];
|
|
48293
|
-
for (const t of targets) {
|
|
48294
|
-
const content = readFileSync12(t.abs, "utf8");
|
|
48295
|
-
const title = basename5(t.abs, extname5(t.abs));
|
|
48296
|
-
try {
|
|
48297
|
-
const message = await ingestTool.handler(client.raw, {
|
|
48298
|
-
title,
|
|
48299
|
-
content,
|
|
48300
|
-
source: "sync-docs",
|
|
48301
|
-
metadata: { source_path: t.rel },
|
|
48302
|
-
update_if_exists: true,
|
|
48303
|
-
project_name: project,
|
|
48304
|
-
author,
|
|
48305
|
-
author_type: authorType
|
|
48306
|
-
}, { openaiApiKey: settings.openaiApiKey, accessPath: "cli" });
|
|
48307
|
-
outcomes.push({ file: t.rel, status: "ok", detail: message });
|
|
48308
|
-
} catch (err) {
|
|
48309
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
48310
|
-
outcomes.push({ file: t.rel, status: "error", detail: msg });
|
|
48311
|
-
}
|
|
48312
|
-
}
|
|
48313
|
-
const ok2 = outcomes.filter((o) => o.status === "ok");
|
|
48314
|
-
const errs = outcomes.filter((o) => o.status === "error");
|
|
48315
|
-
println("");
|
|
48316
|
-
println(c.bold(`Summary: ${ok2.length} ok · ${errs.length} error${errs.length === 1 ? "" : "s"}`));
|
|
48317
|
-
if (errs.length > 0) {
|
|
48318
|
-
println("");
|
|
48319
|
-
printTable(errs.map((e) => ({ file: e.file, error: e.detail.slice(0, 100) })));
|
|
48320
|
-
}
|
|
48321
|
-
}
|
|
48322
|
-
function registerSyncDocs(program2) {
|
|
48323
|
-
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(action27);
|
|
48523
|
+
program2.command("status").description("Quick sanity check (fast subset of `cerefox doctor`).").option("--json", "Emit machine-readable JSON.").action(action30);
|
|
48324
48524
|
}
|
|
48325
48525
|
|
|
48326
48526
|
// src/cli/program.ts
|
|
@@ -49655,7 +49855,7 @@ var _baseMimes = {
|
|
|
49655
49855
|
var baseMimes = _baseMimes;
|
|
49656
49856
|
|
|
49657
49857
|
// ../../node_modules/.bun/@hono+node-server@2.0.4+1bbe96acb4c5ebf1/node_modules/@hono/node-server/dist/serve-static.mjs
|
|
49658
|
-
import { createReadStream, existsSync as existsSync12, statSync as
|
|
49858
|
+
import { createReadStream, existsSync as existsSync12, statSync as statSync5 } from "node:fs";
|
|
49659
49859
|
import { join as join12 } from "node:path";
|
|
49660
49860
|
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;
|
|
49661
49861
|
var ENCODINGS = {
|
|
@@ -49667,7 +49867,7 @@ var ENCODINGS_ORDERED_KEYS = Object.keys(ENCODINGS);
|
|
|
49667
49867
|
var getStats = (path) => {
|
|
49668
49868
|
let stats;
|
|
49669
49869
|
try {
|
|
49670
|
-
stats =
|
|
49870
|
+
stats = statSync5(path);
|
|
49671
49871
|
} catch {}
|
|
49672
49872
|
return stats;
|
|
49673
49873
|
};
|
|
@@ -51575,7 +51775,7 @@ function registerConfigRoutes(app, ctx) {
|
|
|
51575
51775
|
}
|
|
51576
51776
|
|
|
51577
51777
|
// src/web/routes/discovery.ts
|
|
51578
|
-
var
|
|
51778
|
+
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
51579
51779
|
var DOC_COLS = "id, title, source, source_path, content_hash, metadata, chunk_count, total_chars, review_status, created_at, updated_at, deleted_at";
|
|
51580
51780
|
function jsonByteLength(value) {
|
|
51581
51781
|
return Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
@@ -52021,7 +52221,7 @@ function registerDiscoveryRoutes(app, ctx) {
|
|
|
52021
52221
|
if (!path) {
|
|
52022
52222
|
return c2.json({ tried_path: "", anchor, matches: [] });
|
|
52023
52223
|
}
|
|
52024
|
-
if (
|
|
52224
|
+
if (UUID_RE3.test(path)) {
|
|
52025
52225
|
if (path === fromDocId) {
|
|
52026
52226
|
return c2.json({ tried_path: path, anchor, matches: [] });
|
|
52027
52227
|
}
|
|
@@ -52047,7 +52247,7 @@ function registerDiscoveryRoutes(app, ctx) {
|
|
|
52047
52247
|
if (!normalised) {
|
|
52048
52248
|
return c2.json({ tried_path: "", anchor, matches: [] });
|
|
52049
52249
|
}
|
|
52050
|
-
const
|
|
52250
|
+
const basename5 = normalised.split("/").pop() ?? normalised;
|
|
52051
52251
|
const project = (rows, method) => rows.filter((r) => r.id !== fromDocId).map((r) => ({
|
|
52052
52252
|
document_id: r.id,
|
|
52053
52253
|
title: r.title ?? "",
|
|
@@ -52062,8 +52262,8 @@ function registerDiscoveryRoutes(app, ctx) {
|
|
|
52062
52262
|
return c2.json({ tried_path: normalised, anchor, matches });
|
|
52063
52263
|
}
|
|
52064
52264
|
}
|
|
52065
|
-
if (
|
|
52066
|
-
const { data } = await ctx.supabase.from("cerefox_documents").select("id, title, source_path").is("deleted_at", null).like("source_path", `%/${
|
|
52265
|
+
if (basename5 !== normalised) {
|
|
52266
|
+
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);
|
|
52067
52267
|
const rows = data ?? [];
|
|
52068
52268
|
const matches = project(rows, "basename");
|
|
52069
52269
|
if (matches.length > 0) {
|
|
@@ -52071,7 +52271,7 @@ function registerDiscoveryRoutes(app, ctx) {
|
|
|
52071
52271
|
}
|
|
52072
52272
|
}
|
|
52073
52273
|
{
|
|
52074
|
-
const stem =
|
|
52274
|
+
const stem = basename5.replace(/\.md$/i, "").replace(/[-_]+/g, " ").trim();
|
|
52075
52275
|
if (stem) {
|
|
52076
52276
|
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);
|
|
52077
52277
|
const rows = data ?? [];
|
|
@@ -52619,10 +52819,10 @@ import { execFileSync } from "node:child_process";
|
|
|
52619
52819
|
import {
|
|
52620
52820
|
existsSync as existsSync13,
|
|
52621
52821
|
readFileSync as readFileSync13,
|
|
52622
|
-
readdirSync as
|
|
52623
|
-
statSync as
|
|
52822
|
+
readdirSync as readdirSync6,
|
|
52823
|
+
statSync as statSync6
|
|
52624
52824
|
} from "node:fs";
|
|
52625
|
-
import { basename as
|
|
52825
|
+
import { basename as basename5, dirname as dirname5, join as join13, resolve as resolve5 } from "node:path";
|
|
52626
52826
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
52627
52827
|
var TOP_LEVEL_DOCS = [
|
|
52628
52828
|
{ filename: "README.md", path: "README.md", category: "readme" },
|
|
@@ -52650,7 +52850,7 @@ function resolveDocsRoots() {
|
|
|
52650
52850
|
let pkgTopLevel = null;
|
|
52651
52851
|
for (const pkg of pkgRootCandidates) {
|
|
52652
52852
|
const guides = join13(pkg, "docs", "guides");
|
|
52653
|
-
if (existsSync13(guides) &&
|
|
52853
|
+
if (existsSync13(guides) && statSync6(guides).isDirectory()) {
|
|
52654
52854
|
pkgGuides = guides;
|
|
52655
52855
|
pkgTopLevel = pkg;
|
|
52656
52856
|
break;
|
|
@@ -52679,7 +52879,7 @@ function slugifiedTitle(filename) {
|
|
|
52679
52879
|
return filename.replace(/\.md$/i, "").replace(/[-_]+/g, " ").replace(/\b\w/g, (m) => m.toUpperCase());
|
|
52680
52880
|
}
|
|
52681
52881
|
function entryForFile(absPath, relPath, category) {
|
|
52682
|
-
const title = readH1(absPath) ?? slugifiedTitle(
|
|
52882
|
+
const title = readH1(absPath) ?? slugifiedTitle(basename5(relPath));
|
|
52683
52883
|
return { path: relPath, title, category };
|
|
52684
52884
|
}
|
|
52685
52885
|
function listBundledDocs2() {
|
|
@@ -52696,7 +52896,7 @@ function listBundledDocs2() {
|
|
|
52696
52896
|
}
|
|
52697
52897
|
const guidesRoot = pkgGuides ?? repoGuides;
|
|
52698
52898
|
if (guidesRoot) {
|
|
52699
|
-
const names =
|
|
52899
|
+
const names = readdirSync6(guidesRoot).filter((n) => n.endsWith(".md")).sort();
|
|
52700
52900
|
for (const name of names) {
|
|
52701
52901
|
const abs = join13(guidesRoot, name);
|
|
52702
52902
|
entries.push(entryForFile(abs, `guides/${name}`, "guide"));
|
|
@@ -52712,7 +52912,7 @@ function readDoc(docPath) {
|
|
|
52712
52912
|
if (!candidate.startsWith(resolve5(root) + "/") && candidate !== resolve5(root)) {
|
|
52713
52913
|
continue;
|
|
52714
52914
|
}
|
|
52715
|
-
if (existsSync13(candidate) &&
|
|
52915
|
+
if (existsSync13(candidate) && statSync6(candidate).isFile()) {
|
|
52716
52916
|
try {
|
|
52717
52917
|
return readFileSync13(candidate, "utf8");
|
|
52718
52918
|
} catch {
|
|
@@ -52880,14 +53080,14 @@ function registerProjectsRoutes(app, ctx) {
|
|
|
52880
53080
|
}
|
|
52881
53081
|
|
|
52882
53082
|
// src/web/static.ts
|
|
52883
|
-
import { existsSync as existsSync14, statSync as
|
|
53083
|
+
import { existsSync as existsSync14, statSync as statSync7 } from "node:fs";
|
|
52884
53084
|
import { dirname as dirname6, join as join14 } from "node:path";
|
|
52885
53085
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
52886
53086
|
function moduleDir3() {
|
|
52887
53087
|
return dirname6(fileURLToPath4(import.meta.url));
|
|
52888
53088
|
}
|
|
52889
53089
|
function isUsableSpaDir(dir) {
|
|
52890
|
-
return existsSync14(dir) &&
|
|
53090
|
+
return existsSync14(dir) && statSync7(dir).isDirectory() && existsSync14(join14(dir, "index.html"));
|
|
52891
53091
|
}
|
|
52892
53092
|
function resolveSpaDist() {
|
|
52893
53093
|
const here = moduleDir3();
|
|
@@ -52909,7 +53109,7 @@ function resolveStaticDir() {
|
|
|
52909
53109
|
join14(here, "..", "..", "..", "..", "web", "static")
|
|
52910
53110
|
];
|
|
52911
53111
|
for (const c2 of candidates) {
|
|
52912
|
-
if (existsSync14(c2) &&
|
|
53112
|
+
if (existsSync14(c2) && statSync7(c2).isDirectory())
|
|
52913
53113
|
return c2;
|
|
52914
53114
|
}
|
|
52915
53115
|
return null;
|
|
@@ -53058,11 +53258,11 @@ import {
|
|
|
53058
53258
|
openSync,
|
|
53059
53259
|
readFileSync as readFileSync15,
|
|
53060
53260
|
rmSync,
|
|
53061
|
-
writeFileSync as
|
|
53261
|
+
writeFileSync as writeFileSync5
|
|
53062
53262
|
} from "node:fs";
|
|
53063
|
-
import { homedir as
|
|
53263
|
+
import { homedir as homedir8 } from "node:os";
|
|
53064
53264
|
import { join as join16 } from "node:path";
|
|
53065
|
-
var STATE_DIR = join16(
|
|
53265
|
+
var STATE_DIR = join16(homedir8(), ".cerefox");
|
|
53066
53266
|
var PID_FILE = join16(STATE_DIR, "web.pid");
|
|
53067
53267
|
var LOG_FILE = join16(STATE_DIR, "web.log");
|
|
53068
53268
|
var daemonPaths = { stateDir: STATE_DIR, pidFile: PID_FILE, logFile: LOG_FILE };
|
|
@@ -53089,7 +53289,7 @@ function readPidFile() {
|
|
|
53089
53289
|
}
|
|
53090
53290
|
function writePidFile(info3) {
|
|
53091
53291
|
ensureStateDir();
|
|
53092
|
-
|
|
53292
|
+
writeFileSync5(PID_FILE, JSON.stringify(info3, null, 2) + `
|
|
53093
53293
|
`, "utf8");
|
|
53094
53294
|
}
|
|
53095
53295
|
function removePidFile() {
|
|
@@ -53313,15 +53513,58 @@ function registerWeb(program2) {
|
|
|
53313
53513
|
}
|
|
53314
53514
|
|
|
53315
53515
|
// src/cli/program.ts
|
|
53516
|
+
function moveInto(parent, register, newName) {
|
|
53517
|
+
register(parent);
|
|
53518
|
+
const cmd = parent.commands[parent.commands.length - 1];
|
|
53519
|
+
cmd.name(newName);
|
|
53520
|
+
return cmd;
|
|
53521
|
+
}
|
|
53522
|
+
var RENAMED_VERBS = [
|
|
53523
|
+
["get-doc", "document get"],
|
|
53524
|
+
["list-docs", "document list"],
|
|
53525
|
+
["delete-doc", "document delete"],
|
|
53526
|
+
["ingest", "document ingest"],
|
|
53527
|
+
["ingest-dir", "document ingest-dir"],
|
|
53528
|
+
["list-projects", "project list"],
|
|
53529
|
+
["delete-project", "project delete"],
|
|
53530
|
+
["list-versions", "document version list"],
|
|
53531
|
+
["get-audit-log", "audit list"],
|
|
53532
|
+
["list-metadata-keys", "metadata keys"],
|
|
53533
|
+
["metadata-search", "metadata search"],
|
|
53534
|
+
["config-get", "config get"],
|
|
53535
|
+
["config-set", "config set"],
|
|
53536
|
+
["restore", "backup restore"],
|
|
53537
|
+
["deploy-server", "server deploy"],
|
|
53538
|
+
["reindex", "server reindex"],
|
|
53539
|
+
["docs", "guides"],
|
|
53540
|
+
["sync-self-docs", "guides ingest"]
|
|
53541
|
+
];
|
|
53542
|
+
function registerRenameHusks(program2) {
|
|
53543
|
+
for (const [oldName, newForm] of RENAMED_VERBS) {
|
|
53544
|
+
program2.command(oldName, { hidden: true }).allowUnknownOption(true).allowExcessArguments(true).argument("[args...]", "(renamed)").action(() => {
|
|
53545
|
+
eprintln(c.yellow(`✗ \`cerefox ${oldName}\` was renamed.`));
|
|
53546
|
+
eprintln(` Use \`cerefox ${newForm}\` instead (run \`cerefox ${newForm.split(" ")[0]} --help\`).`);
|
|
53547
|
+
process.exit(1);
|
|
53548
|
+
});
|
|
53549
|
+
}
|
|
53550
|
+
}
|
|
53316
53551
|
function buildProgram() {
|
|
53317
|
-
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", `
|
|
53318
|
-
|
|
53319
|
-
` + `
|
|
53320
|
-
` + `
|
|
53321
|
-
` + `
|
|
53322
|
-
` + `
|
|
53323
|
-
` + `
|
|
53324
|
-
` + `
|
|
53552
|
+
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}
|
|
53553
|
+
` + ` project list · create · edit · delete
|
|
53554
|
+
` + ` metadata keys · search
|
|
53555
|
+
` + ` audit list
|
|
53556
|
+
` + ` config list · get · set
|
|
53557
|
+
` + ` backup create · restore
|
|
53558
|
+
` + ` server deploy · reindex
|
|
53559
|
+
` + ` guides list · open · show · ingest (bundled documentation)
|
|
53560
|
+
` + `
|
|
53561
|
+
Top-level commands:
|
|
53562
|
+
` + ` search · init · doctor · status · configure-agent · self-update
|
|
53563
|
+
` + ` mcp · web · completion
|
|
53564
|
+
` + `
|
|
53565
|
+
Renamed in v0.9.0: the old flat verbs (get-doc, list-docs, ingest, …)
|
|
53566
|
+
` + ` now live under the groups above. The old names still run but exit with
|
|
53567
|
+
` + ` a pointer to the new form. They are removed in v1.0.
|
|
53325
53568
|
` + `
|
|
53326
53569
|
Exit codes:
|
|
53327
53570
|
` + ` 0 success 2 system error (unreachable Supabase, RPC failure, …)
|
|
@@ -53333,34 +53576,58 @@ Learn more:
|
|
|
53333
53576
|
` + ` https://github.com/fstamatelopoulos/cerefox
|
|
53334
53577
|
`);
|
|
53335
53578
|
registerSearch(program2);
|
|
53336
|
-
registerGetDoc(program2);
|
|
53337
|
-
registerListDocs(program2);
|
|
53338
|
-
registerListVersions(program2);
|
|
53339
|
-
registerListProjects(program2);
|
|
53340
|
-
registerListMetadataKeys(program2);
|
|
53341
|
-
registerMetadataSearch(program2);
|
|
53342
|
-
registerGetAuditLog(program2);
|
|
53343
|
-
registerIngest(program2);
|
|
53344
|
-
registerIngestDir(program2);
|
|
53345
|
-
registerDeleteDoc(program2);
|
|
53346
|
-
registerDeleteProject(program2);
|
|
53347
|
-
registerMcp(program2);
|
|
53348
|
-
registerWeb(program2);
|
|
53349
53579
|
registerInit(program2);
|
|
53350
53580
|
registerDoctor(program2);
|
|
53351
53581
|
registerStatus(program2);
|
|
53352
53582
|
registerConfigureAgent(program2);
|
|
53353
53583
|
registerSelfUpdate(program2);
|
|
53354
|
-
|
|
53355
|
-
|
|
53356
|
-
registerBackup(program2);
|
|
53357
|
-
registerRestore(program2);
|
|
53358
|
-
registerSyncDocs(program2);
|
|
53359
|
-
registerDocs(program2);
|
|
53360
|
-
registerReindex(program2);
|
|
53361
|
-
registerConfigGet(program2);
|
|
53362
|
-
registerConfigSet(program2);
|
|
53584
|
+
registerMcp(program2);
|
|
53585
|
+
registerWeb(program2);
|
|
53363
53586
|
registerCompletion(program2);
|
|
53587
|
+
const document2 = program2.command("document").description("Documents: get, list, edit, delete, restore, ingest, ingest-dir, version.");
|
|
53588
|
+
moveInto(document2, registerGetDoc, "get");
|
|
53589
|
+
moveInto(document2, registerListDocs, "list");
|
|
53590
|
+
moveInto(document2, registerDeleteDoc, "delete");
|
|
53591
|
+
registerDocumentRestore(document2);
|
|
53592
|
+
registerDocumentEdit(document2);
|
|
53593
|
+
moveInto(document2, registerIngest, "ingest");
|
|
53594
|
+
moveInto(document2, registerIngestDir, "ingest-dir");
|
|
53595
|
+
const documentVersion = document2.command("version").description("Document versions: list, archive, unarchive.");
|
|
53596
|
+
moveInto(documentVersion, registerListVersions, "list");
|
|
53597
|
+
registerVersionArchive(documentVersion);
|
|
53598
|
+
const project = program2.command("project").description("Projects: list, create, edit, delete.");
|
|
53599
|
+
moveInto(project, registerListProjects, "list");
|
|
53600
|
+
registerProjectCreate(project);
|
|
53601
|
+
registerProjectEdit(project);
|
|
53602
|
+
moveInto(project, registerDeleteProject, "delete");
|
|
53603
|
+
const metadata = program2.command("metadata").description("Metadata: keys, search.");
|
|
53604
|
+
moveInto(metadata, registerListMetadataKeys, "keys");
|
|
53605
|
+
moveInto(metadata, registerMetadataSearch, "search");
|
|
53606
|
+
const audit = program2.command("audit").description("Audit log: list.");
|
|
53607
|
+
moveInto(audit, registerGetAuditLog, "list");
|
|
53608
|
+
const config2 = program2.command("config").description("Runtime config: list, get, set.");
|
|
53609
|
+
registerConfigList(config2);
|
|
53610
|
+
moveInto(config2, registerConfigGet, "get");
|
|
53611
|
+
moveInto(config2, registerConfigSet, "set");
|
|
53612
|
+
const backup = program2.command("backup").description("Backup + restore the knowledge base: create, restore.").action(() => {
|
|
53613
|
+
eprintln(c.yellow("`cerefox backup` needs a subcommand."));
|
|
53614
|
+
eprintln(" Use `cerefox backup create` or `cerefox backup restore`.");
|
|
53615
|
+
process.exit(1);
|
|
53616
|
+
});
|
|
53617
|
+
moveInto(backup, registerBackup, "create");
|
|
53618
|
+
moveInto(backup, registerRestore, "restore");
|
|
53619
|
+
const server = program2.command("server").description("Server side: deploy, reindex.");
|
|
53620
|
+
moveInto(server, registerDeployServer, "deploy");
|
|
53621
|
+
moveInto(server, registerReindex, "reindex");
|
|
53622
|
+
const guides = program2.command("guides").description("Bundled docs: list, open, show, ingest (into the KB).");
|
|
53623
|
+
registerGuides(guides);
|
|
53624
|
+
moveInto(guides, registerSyncSelfDocs, "ingest");
|
|
53625
|
+
registerRenameHusks(program2);
|
|
53626
|
+
program2.command("sync-docs", { hidden: true }).allowUnknownOption(true).allowExcessArguments(true).argument("[args...]", "(removed)").action(() => {
|
|
53627
|
+
eprintln(c.yellow("✗ `cerefox sync-docs` was removed from the CLI in v0.9.1."));
|
|
53628
|
+
eprintln(" It synced a local repo clone (contributor op). From a repo clone: `bun scripts/sync_docs.ts`.");
|
|
53629
|
+
process.exit(1);
|
|
53630
|
+
});
|
|
53364
53631
|
return program2;
|
|
53365
53632
|
}
|
|
53366
53633
|
|