@namzu/cli 0.0.3 → 0.1.0
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/dist/bin.js +4 -32
- package/dist/bin.js.map +1 -1
- package/dist/cli.d.ts +14 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +124 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.test.d.ts +2 -0
- package/dist/cli.test.d.ts.map +1 -0
- package/dist/cli.test.js +94 -0
- package/dist/cli.test.js.map +1 -0
- package/dist/commands/doctor.d.ts +6 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +10 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/providers.d.ts +17 -0
- package/dist/commands/providers.d.ts.map +1 -0
- package/dist/commands/providers.js +274 -0
- package/dist/commands/providers.js.map +1 -0
- package/dist/commands/registry.d.ts +11 -0
- package/dist/commands/registry.d.ts.map +1 -0
- package/dist/commands/registry.js +28 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/commands/run.d.ts +14 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +73 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/stubs.d.ts +12 -0
- package/dist/commands/stubs.d.ts.map +1 -0
- package/dist/commands/stubs.js +32 -0
- package/dist/commands/stubs.js.map +1 -0
- package/dist/commands/tools.d.ts +16 -0
- package/dist/commands/tools.d.ts.map +1 -0
- package/dist/commands/tools.js +161 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commands/types.d.ts +25 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +2 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/config/load.d.ts +25 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +92 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/load.test.d.ts +2 -0
- package/dist/config/load.test.d.ts.map +1 -0
- package/dist/config/load.test.js +57 -0
- package/dist/config/load.test.js.map +1 -0
- package/dist/config/schema.d.ts +29 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +13 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/doctor/registry.d.ts.map +1 -1
- package/dist/doctor/registry.js +3 -1
- package/dist/doctor/registry.js.map +1 -1
- package/dist/doctor/registry.test.js +4 -1
- package/dist/doctor/registry.test.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/integrations/clawtool/agents.d.ts +31 -0
- package/dist/integrations/clawtool/agents.d.ts.map +1 -0
- package/dist/integrations/clawtool/agents.js +30 -0
- package/dist/integrations/clawtool/agents.js.map +1 -0
- package/dist/integrations/clawtool/agents.test.d.ts +2 -0
- package/dist/integrations/clawtool/agents.test.d.ts.map +1 -0
- package/dist/integrations/clawtool/agents.test.js +79 -0
- package/dist/integrations/clawtool/agents.test.js.map +1 -0
- package/dist/integrations/clawtool/auth.d.ts +26 -0
- package/dist/integrations/clawtool/auth.d.ts.map +1 -0
- package/dist/integrations/clawtool/auth.js +56 -0
- package/dist/integrations/clawtool/auth.js.map +1 -0
- package/dist/integrations/clawtool/auth.test.d.ts +2 -0
- package/dist/integrations/clawtool/auth.test.d.ts.map +1 -0
- package/dist/integrations/clawtool/auth.test.js +40 -0
- package/dist/integrations/clawtool/auth.test.js.map +1 -0
- package/dist/integrations/clawtool/binary.d.ts +25 -0
- package/dist/integrations/clawtool/binary.d.ts.map +1 -0
- package/dist/integrations/clawtool/binary.js +50 -0
- package/dist/integrations/clawtool/binary.js.map +1 -0
- package/dist/integrations/clawtool/binary.test.d.ts +2 -0
- package/dist/integrations/clawtool/binary.test.d.ts.map +1 -0
- package/dist/integrations/clawtool/binary.test.js +42 -0
- package/dist/integrations/clawtool/binary.test.js.map +1 -0
- package/dist/integrations/clawtool/daemon.d.ts +37 -0
- package/dist/integrations/clawtool/daemon.d.ts.map +1 -0
- package/dist/integrations/clawtool/daemon.js +109 -0
- package/dist/integrations/clawtool/daemon.js.map +1 -0
- package/dist/integrations/clawtool/daemon.test.d.ts +11 -0
- package/dist/integrations/clawtool/daemon.test.d.ts.map +1 -0
- package/dist/integrations/clawtool/daemon.test.js +118 -0
- package/dist/integrations/clawtool/daemon.test.js.map +1 -0
- package/dist/integrations/clawtool/dispatch.d.ts +33 -0
- package/dist/integrations/clawtool/dispatch.d.ts.map +1 -0
- package/dist/integrations/clawtool/dispatch.js +155 -0
- package/dist/integrations/clawtool/dispatch.js.map +1 -0
- package/dist/integrations/clawtool/dispatch.test.d.ts +2 -0
- package/dist/integrations/clawtool/dispatch.test.d.ts.map +1 -0
- package/dist/integrations/clawtool/dispatch.test.js +138 -0
- package/dist/integrations/clawtool/dispatch.test.js.map +1 -0
- package/dist/integrations/clawtool/index.d.ts +11 -0
- package/dist/integrations/clawtool/index.d.ts.map +1 -0
- package/dist/integrations/clawtool/index.js +10 -0
- package/dist/integrations/clawtool/index.js.map +1 -0
- package/dist/integrations/clawtool/mcp.d.ts +51 -0
- package/dist/integrations/clawtool/mcp.d.ts.map +1 -0
- package/dist/integrations/clawtool/mcp.js +156 -0
- package/dist/integrations/clawtool/mcp.js.map +1 -0
- package/dist/integrations/clawtool/mcp.test.d.ts +2 -0
- package/dist/integrations/clawtool/mcp.test.d.ts.map +1 -0
- package/dist/integrations/clawtool/mcp.test.js +126 -0
- package/dist/integrations/clawtool/mcp.test.js.map +1 -0
- package/dist/integrations/clawtool/paths.d.ts +8 -0
- package/dist/integrations/clawtool/paths.d.ts.map +1 -0
- package/dist/integrations/clawtool/paths.js +19 -0
- package/dist/integrations/clawtool/paths.js.map +1 -0
- package/dist/integrations/clawtool/peers.d.ts +67 -0
- package/dist/integrations/clawtool/peers.d.ts.map +1 -0
- package/dist/integrations/clawtool/peers.js +150 -0
- package/dist/integrations/clawtool/peers.js.map +1 -0
- package/dist/integrations/clawtool/plugin.d.ts +42 -0
- package/dist/integrations/clawtool/plugin.d.ts.map +1 -0
- package/dist/integrations/clawtool/plugin.js +38 -0
- package/dist/integrations/clawtool/plugin.js.map +1 -0
- package/dist/integrations/clawtool/state.d.ts +11 -0
- package/dist/integrations/clawtool/state.d.ts.map +1 -0
- package/dist/integrations/clawtool/state.js +41 -0
- package/dist/integrations/clawtool/state.js.map +1 -0
- package/dist/integrations/clawtool/state.test.d.ts +2 -0
- package/dist/integrations/clawtool/state.test.d.ts.map +1 -0
- package/dist/integrations/clawtool/state.test.js +38 -0
- package/dist/integrations/clawtool/state.test.js.map +1 -0
- package/dist/integrations/clawtool/tooling.d.ts +50 -0
- package/dist/integrations/clawtool/tooling.d.ts.map +1 -0
- package/dist/integrations/clawtool/tooling.js +89 -0
- package/dist/integrations/clawtool/tooling.js.map +1 -0
- package/dist/integrations/clawtool/tooling.test.d.ts +2 -0
- package/dist/integrations/clawtool/tooling.test.d.ts.map +1 -0
- package/dist/integrations/clawtool/tooling.test.js +58 -0
- package/dist/integrations/clawtool/tooling.test.js.map +1 -0
- package/dist/integrations/clawtool/types.d.ts +41 -0
- package/dist/integrations/clawtool/types.d.ts.map +1 -0
- package/dist/integrations/clawtool/types.js +9 -0
- package/dist/integrations/clawtool/types.js.map +1 -0
- package/dist/integrations/clipboard/image.d.ts +18 -0
- package/dist/integrations/clipboard/image.d.ts.map +1 -0
- package/dist/integrations/clipboard/image.js +88 -0
- package/dist/integrations/clipboard/image.js.map +1 -0
- package/dist/integrations/providers/discover.d.ts +68 -0
- package/dist/integrations/providers/discover.d.ts.map +1 -0
- package/dist/integrations/providers/discover.js +108 -0
- package/dist/integrations/providers/discover.js.map +1 -0
- package/dist/integrations/providers/discover.test.d.ts +2 -0
- package/dist/integrations/providers/discover.test.d.ts.map +1 -0
- package/dist/integrations/providers/discover.test.js +120 -0
- package/dist/integrations/providers/discover.test.js.map +1 -0
- package/dist/integrations/providers/index.d.ts +10 -0
- package/dist/integrations/providers/index.d.ts.map +1 -0
- package/dist/integrations/providers/index.js +12 -0
- package/dist/integrations/providers/index.js.map +1 -0
- package/dist/integrations/providers/keychain.d.ts +44 -0
- package/dist/integrations/providers/keychain.d.ts.map +1 -0
- package/dist/integrations/providers/keychain.js +154 -0
- package/dist/integrations/providers/keychain.js.map +1 -0
- package/dist/integrations/providers/keychain.test.d.ts +2 -0
- package/dist/integrations/providers/keychain.test.d.ts.map +1 -0
- package/dist/integrations/providers/keychain.test.js +21 -0
- package/dist/integrations/providers/keychain.test.js.map +1 -0
- package/dist/integrations/providers/mask.d.ts +7 -0
- package/dist/integrations/providers/mask.d.ts.map +1 -0
- package/dist/integrations/providers/mask.js +14 -0
- package/dist/integrations/providers/mask.js.map +1 -0
- package/dist/integrations/providers/mask.test.d.ts +2 -0
- package/dist/integrations/providers/mask.test.d.ts.map +1 -0
- package/dist/integrations/providers/mask.test.js +20 -0
- package/dist/integrations/providers/mask.test.js.map +1 -0
- package/dist/integrations/providers/oauth.d.ts +28 -0
- package/dist/integrations/providers/oauth.d.ts.map +1 -0
- package/dist/integrations/providers/oauth.js +65 -0
- package/dist/integrations/providers/oauth.js.map +1 -0
- package/dist/integrations/providers/oauth.test.d.ts +2 -0
- package/dist/integrations/providers/oauth.test.d.ts.map +1 -0
- package/dist/integrations/providers/oauth.test.js +86 -0
- package/dist/integrations/providers/oauth.test.js.map +1 -0
- package/dist/integrations/providers/preferences.d.ts +43 -0
- package/dist/integrations/providers/preferences.d.ts.map +1 -0
- package/dist/integrations/providers/preferences.js +111 -0
- package/dist/integrations/providers/preferences.js.map +1 -0
- package/dist/integrations/providers/preferences.test.d.ts +2 -0
- package/dist/integrations/providers/preferences.test.d.ts.map +1 -0
- package/dist/integrations/providers/preferences.test.js +68 -0
- package/dist/integrations/providers/preferences.test.js.map +1 -0
- package/dist/integrations/providers/registry.d.ts +31 -0
- package/dist/integrations/providers/registry.d.ts.map +1 -0
- package/dist/integrations/providers/registry.js +79 -0
- package/dist/integrations/providers/registry.js.map +1 -0
- package/dist/integrations/providers/schema.d.ts +73 -0
- package/dist/integrations/providers/schema.d.ts.map +1 -0
- package/dist/integrations/providers/schema.js +70 -0
- package/dist/integrations/providers/schema.js.map +1 -0
- package/dist/integrations/providers/schema.test.d.ts +2 -0
- package/dist/integrations/providers/schema.test.d.ts.map +1 -0
- package/dist/integrations/providers/schema.test.js +43 -0
- package/dist/integrations/providers/schema.test.js.map +1 -0
- package/dist/integrations/providers/secrets.d.ts +37 -0
- package/dist/integrations/providers/secrets.d.ts.map +1 -0
- package/dist/integrations/providers/secrets.js +69 -0
- package/dist/integrations/providers/secrets.js.map +1 -0
- package/dist/integrations/providers/store.d.ts +32 -0
- package/dist/integrations/providers/store.d.ts.map +1 -0
- package/dist/integrations/providers/store.js +133 -0
- package/dist/integrations/providers/store.js.map +1 -0
- package/dist/integrations/providers/store.test.d.ts +2 -0
- package/dist/integrations/providers/store.test.d.ts.map +1 -0
- package/dist/integrations/providers/store.test.js +127 -0
- package/dist/integrations/providers/store.test.js.map +1 -0
- package/dist/integrations/sessions/store.d.ts +40 -0
- package/dist/integrations/sessions/store.d.ts.map +1 -0
- package/dist/integrations/sessions/store.js +90 -0
- package/dist/integrations/sessions/store.js.map +1 -0
- package/dist/integrations/subagents/runtime.d.ts +37 -0
- package/dist/integrations/subagents/runtime.d.ts.map +1 -0
- package/dist/integrations/subagents/runtime.js +183 -0
- package/dist/integrations/subagents/runtime.js.map +1 -0
- package/dist/integrations/trust/store.d.ts +16 -0
- package/dist/integrations/trust/store.d.ts.map +1 -0
- package/dist/integrations/trust/store.js +59 -0
- package/dist/integrations/trust/store.js.map +1 -0
- package/dist/integrations/trust/store.test.d.ts +2 -0
- package/dist/integrations/trust/store.test.d.ts.map +1 -0
- package/dist/integrations/trust/store.test.js +50 -0
- package/dist/integrations/trust/store.test.js.map +1 -0
- package/dist/integrations/updates.d.ts +27 -0
- package/dist/integrations/updates.d.ts.map +1 -0
- package/dist/integrations/updates.js +99 -0
- package/dist/integrations/updates.js.map +1 -0
- package/dist/memory/store.d.ts +29 -0
- package/dist/memory/store.d.ts.map +1 -0
- package/dist/memory/store.js +74 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/memory/store.test.d.ts +2 -0
- package/dist/memory/store.test.d.ts.map +1 -0
- package/dist/memory/store.test.js +63 -0
- package/dist/memory/store.test.js.map +1 -0
- package/dist/output/formatter.d.ts +30 -0
- package/dist/output/formatter.d.ts.map +1 -0
- package/dist/output/formatter.js +16 -0
- package/dist/output/formatter.js.map +1 -0
- package/dist/output/formatter.test.d.ts +2 -0
- package/dist/output/formatter.test.d.ts.map +1 -0
- package/dist/output/formatter.test.js +88 -0
- package/dist/output/formatter.test.js.map +1 -0
- package/dist/output/index.d.ts +5 -0
- package/dist/output/index.d.ts.map +1 -0
- package/dist/output/index.js +22 -0
- package/dist/output/index.js.map +1 -0
- package/dist/output/json.d.ts +13 -0
- package/dist/output/json.d.ts.map +1 -0
- package/dist/output/json.js +51 -0
- package/dist/output/json.js.map +1 -0
- package/dist/output/text.d.ts +13 -0
- package/dist/output/text.d.ts.map +1 -0
- package/dist/output/text.js +36 -0
- package/dist/output/text.js.map +1 -0
- package/dist/output/yaml.d.ts +13 -0
- package/dist/output/yaml.d.ts.map +1 -0
- package/dist/output/yaml.js +26 -0
- package/dist/output/yaml.js.map +1 -0
- package/dist/skills/store.d.ts +49 -0
- package/dist/skills/store.d.ts.map +1 -0
- package/dist/skills/store.js +109 -0
- package/dist/skills/store.js.map +1 -0
- package/dist/skills/store.test.d.ts +2 -0
- package/dist/skills/store.test.d.ts.map +1 -0
- package/dist/skills/store.test.js +80 -0
- package/dist/skills/store.test.js.map +1 -0
- package/dist/tui/App.d.ts +18 -0
- package/dist/tui/App.d.ts.map +1 -0
- package/dist/tui/App.js +742 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/Composer.d.ts +17 -0
- package/dist/tui/Composer.d.ts.map +1 -0
- package/dist/tui/Composer.js +123 -0
- package/dist/tui/Composer.js.map +1 -0
- package/dist/tui/LiveActivity.d.ts +22 -0
- package/dist/tui/LiveActivity.d.ts.map +1 -0
- package/dist/tui/LiveActivity.js +46 -0
- package/dist/tui/LiveActivity.js.map +1 -0
- package/dist/tui/Markdown.d.ts +18 -0
- package/dist/tui/Markdown.d.ts.map +1 -0
- package/dist/tui/Markdown.js +68 -0
- package/dist/tui/Markdown.js.map +1 -0
- package/dist/tui/PermissionOverlay.d.ts +14 -0
- package/dist/tui/PermissionOverlay.d.ts.map +1 -0
- package/dist/tui/PermissionOverlay.js +22 -0
- package/dist/tui/PermissionOverlay.js.map +1 -0
- package/dist/tui/Picker.d.ts +20 -0
- package/dist/tui/Picker.d.ts.map +1 -0
- package/dist/tui/Picker.js +72 -0
- package/dist/tui/Picker.js.map +1 -0
- package/dist/tui/ResumePicker.d.ts +12 -0
- package/dist/tui/ResumePicker.d.ts.map +1 -0
- package/dist/tui/ResumePicker.js +26 -0
- package/dist/tui/ResumePicker.js.map +1 -0
- package/dist/tui/StatusBar.d.ts +22 -0
- package/dist/tui/StatusBar.d.ts.map +1 -0
- package/dist/tui/StatusBar.js +73 -0
- package/dist/tui/StatusBar.js.map +1 -0
- package/dist/tui/Transcript.d.ts +29 -0
- package/dist/tui/Transcript.d.ts.map +1 -0
- package/dist/tui/Transcript.js +105 -0
- package/dist/tui/Transcript.js.map +1 -0
- package/dist/tui/TrustPrompt.d.ts +11 -0
- package/dist/tui/TrustPrompt.d.ts.map +1 -0
- package/dist/tui/TrustPrompt.js +13 -0
- package/dist/tui/TrustPrompt.js.map +1 -0
- package/dist/tui/agent.d.ts +163 -0
- package/dist/tui/agent.d.ts.map +1 -0
- package/dist/tui/agent.js +684 -0
- package/dist/tui/agent.js.map +1 -0
- package/dist/tui/agent.test.d.ts +2 -0
- package/dist/tui/agent.test.d.ts.map +1 -0
- package/dist/tui/agent.test.js +225 -0
- package/dist/tui/agent.test.js.map +1 -0
- package/dist/tui/index.d.ts +7 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +29 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/logo.d.ts +23 -0
- package/dist/tui/logo.d.ts.map +1 -0
- package/dist/tui/logo.js +35 -0
- package/dist/tui/logo.js.map +1 -0
- package/dist/tui/markdownParser.d.ts +45 -0
- package/dist/tui/markdownParser.d.ts.map +1 -0
- package/dist/tui/markdownParser.js +127 -0
- package/dist/tui/markdownParser.js.map +1 -0
- package/dist/tui/markdownParser.test.d.ts +2 -0
- package/dist/tui/markdownParser.test.d.ts.map +1 -0
- package/dist/tui/markdownParser.test.js +90 -0
- package/dist/tui/markdownParser.test.js.map +1 -0
- package/dist/tui/mentions.d.ts +22 -0
- package/dist/tui/mentions.d.ts.map +1 -0
- package/dist/tui/mentions.js +59 -0
- package/dist/tui/mentions.js.map +1 -0
- package/dist/tui/mentions.test.d.ts +2 -0
- package/dist/tui/mentions.test.d.ts.map +1 -0
- package/dist/tui/mentions.test.js +35 -0
- package/dist/tui/mentions.test.js.map +1 -0
- package/dist/tui/slashCommands.d.ts +64 -0
- package/dist/tui/slashCommands.d.ts.map +1 -0
- package/dist/tui/slashCommands.js +153 -0
- package/dist/tui/slashCommands.js.map +1 -0
- package/dist/tui/slashCommands.test.d.ts +2 -0
- package/dist/tui/slashCommands.test.d.ts.map +1 -0
- package/dist/tui/slashCommands.test.js +114 -0
- package/dist/tui/slashCommands.test.js.map +1 -0
- package/dist/tui/theme.d.ts +34 -0
- package/dist/tui/theme.d.ts.map +1 -0
- package/dist/tui/theme.js +32 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/tui/types.d.ts +27 -0
- package/dist/tui/types.d.ts.map +1 -0
- package/dist/tui/types.js +7 -0
- package/dist/tui/types.js.map +1 -0
- package/package.json +13 -3
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update checks for namzu (npm) and clawtool (`clawtool upgrade --check`),
|
|
3
|
+
* surfaced in the TUI so the user knows when a newer version is out. Both are
|
|
4
|
+
* best-effort with short timeouts: offline / unpublished / no-clawtool just
|
|
5
|
+
* yields `null`, never an error or a hang.
|
|
6
|
+
*/
|
|
7
|
+
import { execFile } from 'node:child_process';
|
|
8
|
+
import { findBinary } from './clawtool/binary.js';
|
|
9
|
+
const NPM_TIMEOUT_MS = 2_500;
|
|
10
|
+
const CLAWTOOL_TIMEOUT_MS = 5_000;
|
|
11
|
+
/** Compare dotted numeric versions; >0 if a>b, <0 if a<b, 0 if equal. */
|
|
12
|
+
export function compareVersions(a, b) {
|
|
13
|
+
const parse = (v) => v
|
|
14
|
+
.replace(/^v/, '')
|
|
15
|
+
.split('-')[0] // drop pre-release suffix
|
|
16
|
+
?.split('.')
|
|
17
|
+
.map((n) => Number.parseInt(n, 10) || 0) ?? [];
|
|
18
|
+
const pa = parse(a);
|
|
19
|
+
const pb = parse(b);
|
|
20
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
21
|
+
const d = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
22
|
+
if (d !== 0)
|
|
23
|
+
return d;
|
|
24
|
+
}
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
/** Newer @namzu/cli on npm, or null when up to date / unreachable. */
|
|
28
|
+
export async function checkNamzuUpdate(current) {
|
|
29
|
+
const controller = new AbortController();
|
|
30
|
+
const timer = setTimeout(() => controller.abort(), NPM_TIMEOUT_MS);
|
|
31
|
+
try {
|
|
32
|
+
const res = await fetch('https://registry.npmjs.org/@namzu/cli/latest', {
|
|
33
|
+
signal: controller.signal,
|
|
34
|
+
headers: { accept: 'application/json' },
|
|
35
|
+
});
|
|
36
|
+
if (!res.ok)
|
|
37
|
+
return null;
|
|
38
|
+
const data = (await res.json());
|
|
39
|
+
const latest = typeof data.version === 'string' ? data.version : null;
|
|
40
|
+
if (!latest || compareVersions(latest, current) <= 0)
|
|
41
|
+
return null;
|
|
42
|
+
return { name: 'namzu', current, latest, how: 'npm i -g @namzu/cli' };
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function run(bin, args) {
|
|
52
|
+
return new Promise((resolve) => {
|
|
53
|
+
execFile(bin, args, { timeout: CLAWTOOL_TIMEOUT_MS }, (_err, stdout) => resolve(stdout ?? ''));
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Newer clawtool, or null. Prefers the machine-readable
|
|
58
|
+
* `upgrade --check --json` (newer binaries); falls back to parsing the
|
|
59
|
+
* `current -> latest` line in the plain `upgrade --check` output (older
|
|
60
|
+
* binaries that predate `--json`).
|
|
61
|
+
*/
|
|
62
|
+
export async function checkClawtoolUpdate() {
|
|
63
|
+
let bin;
|
|
64
|
+
try {
|
|
65
|
+
bin = findBinary();
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const how = 'clawtool upgrade';
|
|
71
|
+
// JSON path (preferred).
|
|
72
|
+
try {
|
|
73
|
+
const data = JSON.parse(await run(bin, ['upgrade', '--check', '--json']));
|
|
74
|
+
if (data.update_available && data.current && data.latest) {
|
|
75
|
+
return { name: 'clawtool', current: data.current, latest: data.latest, how };
|
|
76
|
+
}
|
|
77
|
+
if (data.current)
|
|
78
|
+
return null; // valid JSON, no update
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// fall through to plain parsing
|
|
82
|
+
}
|
|
83
|
+
// Plain-output fallback: a line like `0.22.159 -> 0.22.160`.
|
|
84
|
+
const plain = await run(bin, ['upgrade', '--check']);
|
|
85
|
+
const m = plain.match(/(\d+\.\d+\.\d+)\s*->\s*(\d+\.\d+\.\d+)/);
|
|
86
|
+
if (m?.[1] && m[2] && compareVersions(m[2], m[1]) > 0) {
|
|
87
|
+
return { name: 'clawtool', current: m[1], latest: m[2], how };
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
/** Run both checks in parallel; returns whichever have an update available. */
|
|
92
|
+
export async function checkUpdates(namzuVersion) {
|
|
93
|
+
const [namzu, clawtool] = await Promise.all([
|
|
94
|
+
checkNamzuUpdate(namzuVersion),
|
|
95
|
+
checkClawtoolUpdate(),
|
|
96
|
+
]);
|
|
97
|
+
return [namzu, clawtool].filter((u) => u !== null);
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=updates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updates.js","sourceRoot":"","sources":["../../src/integrations/updates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistent memory under `~/.namzu/` — Hermes-parity flat markdown.
|
|
3
|
+
*
|
|
4
|
+
* - `USER.md` — durable facts about the user (role, preferences).
|
|
5
|
+
* - `MEMORY.md` — durable facts/decisions the agent should carry across
|
|
6
|
+
* sessions.
|
|
7
|
+
*
|
|
8
|
+
* Both are plain markdown the user and agent can read and edit. The TUI
|
|
9
|
+
* injects their contents into the agent's system prompt on every turn so
|
|
10
|
+
* namzu remembers across runs, and `/remember` appends to `MEMORY.md`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function memoryDir(home?: string): string;
|
|
13
|
+
export declare function userFilePath(home?: string): string;
|
|
14
|
+
export declare function memoryFilePath(home?: string): string;
|
|
15
|
+
export interface MemoryContent {
|
|
16
|
+
readonly user: string | null;
|
|
17
|
+
readonly memory: string | null;
|
|
18
|
+
}
|
|
19
|
+
/** Read USER.md + MEMORY.md, returning null for absent/empty files. */
|
|
20
|
+
export declare function readMemory(home?: string): MemoryContent;
|
|
21
|
+
/**
|
|
22
|
+
* Compose the memory system-prompt block, or `null` when there's nothing
|
|
23
|
+
* to inject. The block is framed so the model treats it as background
|
|
24
|
+
* knowledge, not as a user instruction for the current turn.
|
|
25
|
+
*/
|
|
26
|
+
export declare function composeMemoryPrompt(content: MemoryContent): string | null;
|
|
27
|
+
/** Append a fact to MEMORY.md as a markdown bullet, creating the file. */
|
|
28
|
+
export declare function appendMemory(text: string, home?: string): void;
|
|
29
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/memory/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,wBAAgB,SAAS,CAAC,IAAI,GAAE,MAAkB,GAAG,MAAM,CAE1D;AAED,wBAAgB,YAAY,CAAC,IAAI,GAAE,MAAkB,GAAG,MAAM,CAE7D;AAED,wBAAgB,cAAc,CAAC,IAAI,GAAE,MAAkB,GAAG,MAAM,CAE/D;AAED,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAWD,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,IAAI,GAAE,MAAkB,GAAG,aAAa,CAKlE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAgBzE;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAkB,GAAG,IAAI,CAMzE"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistent memory under `~/.namzu/` — Hermes-parity flat markdown.
|
|
3
|
+
*
|
|
4
|
+
* - `USER.md` — durable facts about the user (role, preferences).
|
|
5
|
+
* - `MEMORY.md` — durable facts/decisions the agent should carry across
|
|
6
|
+
* sessions.
|
|
7
|
+
*
|
|
8
|
+
* Both are plain markdown the user and agent can read and edit. The TUI
|
|
9
|
+
* injects their contents into the agent's system prompt on every turn so
|
|
10
|
+
* namzu remembers across runs, and `/remember` appends to `MEMORY.md`.
|
|
11
|
+
*/
|
|
12
|
+
import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
|
|
13
|
+
import { homedir } from 'node:os';
|
|
14
|
+
import { dirname, join } from 'node:path';
|
|
15
|
+
const DIR_MODE = 0o700;
|
|
16
|
+
const FILE_MODE = 0o600;
|
|
17
|
+
export function memoryDir(home = homedir()) {
|
|
18
|
+
return join(home, '.namzu');
|
|
19
|
+
}
|
|
20
|
+
export function userFilePath(home = homedir()) {
|
|
21
|
+
return join(memoryDir(home), 'USER.md');
|
|
22
|
+
}
|
|
23
|
+
export function memoryFilePath(home = homedir()) {
|
|
24
|
+
return join(memoryDir(home), 'MEMORY.md');
|
|
25
|
+
}
|
|
26
|
+
function readIfPresent(path) {
|
|
27
|
+
try {
|
|
28
|
+
const text = readFileSync(path, 'utf8').trim();
|
|
29
|
+
return text.length > 0 ? text : null;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Read USER.md + MEMORY.md, returning null for absent/empty files. */
|
|
36
|
+
export function readMemory(home = homedir()) {
|
|
37
|
+
return {
|
|
38
|
+
user: readIfPresent(userFilePath(home)),
|
|
39
|
+
memory: readIfPresent(memoryFilePath(home)),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Compose the memory system-prompt block, or `null` when there's nothing
|
|
44
|
+
* to inject. The block is framed so the model treats it as background
|
|
45
|
+
* knowledge, not as a user instruction for the current turn.
|
|
46
|
+
*/
|
|
47
|
+
export function composeMemoryPrompt(content) {
|
|
48
|
+
const sections = [];
|
|
49
|
+
if (content.user) {
|
|
50
|
+
sections.push(`## About the user\n\n${content.user}`);
|
|
51
|
+
}
|
|
52
|
+
if (content.memory) {
|
|
53
|
+
sections.push(`## Durable memory\n\n${content.memory}`);
|
|
54
|
+
}
|
|
55
|
+
if (sections.length === 0)
|
|
56
|
+
return null;
|
|
57
|
+
return [
|
|
58
|
+
'The following is persistent context carried across sessions. Treat it as',
|
|
59
|
+
'background knowledge about the user and prior work. Do not repeat it back',
|
|
60
|
+
'verbatim unless asked.',
|
|
61
|
+
'',
|
|
62
|
+
sections.join('\n\n'),
|
|
63
|
+
].join('\n');
|
|
64
|
+
}
|
|
65
|
+
/** Append a fact to MEMORY.md as a markdown bullet, creating the file. */
|
|
66
|
+
export function appendMemory(text, home = homedir()) {
|
|
67
|
+
const trimmed = text.trim();
|
|
68
|
+
if (trimmed.length === 0)
|
|
69
|
+
return;
|
|
70
|
+
const path = memoryFilePath(home);
|
|
71
|
+
mkdirSync(dirname(path), { recursive: true, mode: DIR_MODE });
|
|
72
|
+
appendFileSync(path, `- ${trimmed}\n`, { mode: FILE_MODE });
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/memory/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEzC,MAAM,QAAQ,GAAG,KAAK,CAAA;AACtB,MAAM,SAAS,GAAG,KAAK,CAAA;AAEvB,MAAM,UAAU,SAAS,CAAC,OAAe,OAAO,EAAE;IACjD,OAAO,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;AAC5B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe,OAAO,EAAE;IACpD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,CAAA;AACxC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe,OAAO,EAAE;IACtD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,CAAA;AAC1C,CAAC;AAOD,SAAS,aAAa,CAAC,IAAY;IAClC,IAAI,CAAC;QACJ,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAA;QAC9C,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;IACrC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAA;IACZ,CAAC;AACF,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,UAAU,CAAC,OAAe,OAAO,EAAE;IAClD,OAAO;QACN,IAAI,EAAE,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;KAC3C,CAAA;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAsB;IACzD,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IACtD,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,QAAQ,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACxD,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACtC,OAAO;QACN,0EAA0E;QAC1E,2EAA2E;QAC3E,wBAAwB;QACxB,EAAE;QACF,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;KACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACb,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,OAAe,OAAO,EAAE;IAClE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAChC,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,CAAA;IACjC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;IAC7D,cAAc,CAAC,IAAI,EAAE,KAAK,OAAO,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAA;AAC5D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.test.d.ts","sourceRoot":"","sources":["../../src/memory/store.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { mkdirSync } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
6
|
+
import { appendMemory, composeMemoryPrompt, memoryFilePath, readMemory, userFilePath, } from './store.js';
|
|
7
|
+
let home;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
home = mkdtempSync(join(tmpdir(), 'namzu-mem-'));
|
|
10
|
+
mkdirSync(join(home, '.namzu'), { recursive: true });
|
|
11
|
+
});
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
rmSync(home, { recursive: true, force: true });
|
|
14
|
+
});
|
|
15
|
+
describe('readMemory', () => {
|
|
16
|
+
it('returns nulls when nothing is stored', () => {
|
|
17
|
+
expect(readMemory(home)).toEqual({ user: null, memory: null });
|
|
18
|
+
});
|
|
19
|
+
it('reads USER.md and MEMORY.md and trims', () => {
|
|
20
|
+
writeFileSync(userFilePath(home), ' I am Bahadir, a TS dev.\n');
|
|
21
|
+
writeFileSync(memoryFilePath(home), '- prefers tabs\n');
|
|
22
|
+
expect(readMemory(home)).toEqual({
|
|
23
|
+
user: 'I am Bahadir, a TS dev.',
|
|
24
|
+
memory: '- prefers tabs',
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
it('treats whitespace-only files as empty', () => {
|
|
28
|
+
writeFileSync(memoryFilePath(home), ' \n\n');
|
|
29
|
+
expect(readMemory(home).memory).toBeNull();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('composeMemoryPrompt', () => {
|
|
33
|
+
it('returns null when there is nothing to inject', () => {
|
|
34
|
+
expect(composeMemoryPrompt({ user: null, memory: null })).toBeNull();
|
|
35
|
+
});
|
|
36
|
+
it('includes only the sections that have content', () => {
|
|
37
|
+
const onlyUser = composeMemoryPrompt({ user: 'role: dev', memory: null });
|
|
38
|
+
expect(onlyUser).toContain('## About the user');
|
|
39
|
+
expect(onlyUser).toContain('role: dev');
|
|
40
|
+
expect(onlyUser).not.toContain('## Durable memory');
|
|
41
|
+
const both = composeMemoryPrompt({ user: 'role: dev', memory: '- likes tabs' });
|
|
42
|
+
expect(both).toContain('## About the user');
|
|
43
|
+
expect(both).toContain('## Durable memory');
|
|
44
|
+
expect(both).toContain('- likes tabs');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe('appendMemory', () => {
|
|
48
|
+
it('appends a bullet, creating the file', () => {
|
|
49
|
+
appendMemory('first fact', home);
|
|
50
|
+
appendMemory('second fact', home);
|
|
51
|
+
expect(readFileSync(memoryFilePath(home), 'utf8')).toBe('- first fact\n- second fact\n');
|
|
52
|
+
});
|
|
53
|
+
it('ignores empty input', () => {
|
|
54
|
+
appendMemory(' ', home);
|
|
55
|
+
expect(readMemory(home).memory).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
it('round-trips into the injected prompt', () => {
|
|
58
|
+
appendMemory('namzu is built on @namzu/sdk', home);
|
|
59
|
+
const prompt = composeMemoryPrompt(readMemory(home));
|
|
60
|
+
expect(prompt).toContain('namzu is built on @namzu/sdk');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=store.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.test.js","sourceRoot":"","sources":["../../src/memory/store.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output formatter abstraction for the @namzu/cli binary.
|
|
3
|
+
*
|
|
4
|
+
* Commands write structured data through a Formatter rather than building
|
|
5
|
+
* strings directly. The active formatter is selected by the global
|
|
6
|
+
* `--format` flag (default `text`). `--quiet` suppresses non-essential
|
|
7
|
+
* (info/notice) output but always lets errors through.
|
|
8
|
+
*
|
|
9
|
+
* The doctor command predates this abstraction and continues to format its
|
|
10
|
+
* own output via its `--json` flag; future milestones will unify when the
|
|
11
|
+
* doctor JSON shape is reviewed as part of a deliberate session.
|
|
12
|
+
*/
|
|
13
|
+
export type FormatName = 'text' | 'json' | 'yaml';
|
|
14
|
+
export interface FormatterOptions {
|
|
15
|
+
readonly quiet: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface Formatter {
|
|
18
|
+
readonly name: FormatName;
|
|
19
|
+
/** Emit a structured success payload to stdout. */
|
|
20
|
+
print(data: unknown): void;
|
|
21
|
+
/** Emit a non-essential message; suppressed in quiet mode. */
|
|
22
|
+
info(message: string): void;
|
|
23
|
+
/** Emit a structured error payload to stderr; never suppressed. */
|
|
24
|
+
error(payload: {
|
|
25
|
+
message: string;
|
|
26
|
+
details?: unknown;
|
|
27
|
+
}): void;
|
|
28
|
+
}
|
|
29
|
+
export declare function isFormatName(value: string): value is FormatName;
|
|
30
|
+
//# sourceMappingURL=formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/output/formatter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;AAEjD,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,mDAAmD;IACnD,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IAC1B,8DAA8D;IAC9D,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,mEAAmE;IACnE,KAAK,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAA;CAC5D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,UAAU,CAE/D"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output formatter abstraction for the @namzu/cli binary.
|
|
3
|
+
*
|
|
4
|
+
* Commands write structured data through a Formatter rather than building
|
|
5
|
+
* strings directly. The active formatter is selected by the global
|
|
6
|
+
* `--format` flag (default `text`). `--quiet` suppresses non-essential
|
|
7
|
+
* (info/notice) output but always lets errors through.
|
|
8
|
+
*
|
|
9
|
+
* The doctor command predates this abstraction and continues to format its
|
|
10
|
+
* own output via its `--json` flag; future milestones will unify when the
|
|
11
|
+
* doctor JSON shape is reviewed as part of a deliberate session.
|
|
12
|
+
*/
|
|
13
|
+
export function isFormatName(value) {
|
|
14
|
+
return value === 'text' || value === 'json' || value === 'yaml';
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/output/formatter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAkBH,MAAM,UAAU,YAAY,CAAC,KAAa;IACzC,OAAO,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,MAAM,CAAA;AAChE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.test.d.ts","sourceRoot":"","sources":["../../src/output/formatter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import { createFormatter, isFormatName } from './index.js';
|
|
3
|
+
describe('formatter factory', () => {
|
|
4
|
+
let stdout;
|
|
5
|
+
let stderr;
|
|
6
|
+
let originalStdoutWrite;
|
|
7
|
+
let originalStderrWrite;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
stdout = '';
|
|
10
|
+
stderr = '';
|
|
11
|
+
originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
12
|
+
originalStderrWrite = process.stderr.write.bind(process.stderr);
|
|
13
|
+
process.stdout.write = ((chunk) => {
|
|
14
|
+
stdout += typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString('utf8');
|
|
15
|
+
return true;
|
|
16
|
+
});
|
|
17
|
+
process.stderr.write = ((chunk) => {
|
|
18
|
+
stderr += typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString('utf8');
|
|
19
|
+
return true;
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
process.stdout.write = originalStdoutWrite;
|
|
24
|
+
process.stderr.write = originalStderrWrite;
|
|
25
|
+
});
|
|
26
|
+
it('isFormatName narrows known names', () => {
|
|
27
|
+
expect(isFormatName('text')).toBe(true);
|
|
28
|
+
expect(isFormatName('json')).toBe(true);
|
|
29
|
+
expect(isFormatName('yaml')).toBe(true);
|
|
30
|
+
expect(isFormatName('xml')).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
it('json formatter emits parseable JSON to stdout', () => {
|
|
33
|
+
const f = createFormatter('json', { quiet: false });
|
|
34
|
+
f.print({ hello: 'world', n: 1 });
|
|
35
|
+
const parsed = JSON.parse(stdout);
|
|
36
|
+
expect(parsed.hello).toBe('world');
|
|
37
|
+
expect(parsed.n).toBe(1);
|
|
38
|
+
});
|
|
39
|
+
it('yaml formatter emits yaml to stdout', () => {
|
|
40
|
+
const f = createFormatter('yaml', { quiet: false });
|
|
41
|
+
f.print({ hello: 'world' });
|
|
42
|
+
expect(stdout).toContain('hello: world');
|
|
43
|
+
});
|
|
44
|
+
it('text formatter passes strings through verbatim', () => {
|
|
45
|
+
const f = createFormatter('text', { quiet: false });
|
|
46
|
+
f.print('hello');
|
|
47
|
+
expect(stdout).toBe('hello\n');
|
|
48
|
+
});
|
|
49
|
+
it('info is suppressed in quiet mode for every format', () => {
|
|
50
|
+
for (const name of ['text', 'json', 'yaml']) {
|
|
51
|
+
stdout = '';
|
|
52
|
+
stderr = '';
|
|
53
|
+
const f = createFormatter(name, { quiet: true });
|
|
54
|
+
f.info('this should not appear');
|
|
55
|
+
expect(stderr).toBe('');
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
it('errors are never suppressed by quiet mode', () => {
|
|
59
|
+
for (const name of ['text', 'json', 'yaml']) {
|
|
60
|
+
stdout = '';
|
|
61
|
+
stderr = '';
|
|
62
|
+
const f = createFormatter(name, { quiet: true });
|
|
63
|
+
f.error({ message: 'boom' });
|
|
64
|
+
expect(stderr).toContain('boom');
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
it('json formatter does not crash on circular references', () => {
|
|
68
|
+
const f = createFormatter('json', { quiet: false });
|
|
69
|
+
const obj = { a: 1 };
|
|
70
|
+
obj.self = obj;
|
|
71
|
+
f.print(obj);
|
|
72
|
+
expect(stdout).toContain('"a": 1');
|
|
73
|
+
expect(stdout).toContain('[Circular]');
|
|
74
|
+
});
|
|
75
|
+
it('text formatter does not blow the stack on circular references', () => {
|
|
76
|
+
const f = createFormatter('text', { quiet: false });
|
|
77
|
+
const obj = { a: 1 };
|
|
78
|
+
obj.self = obj;
|
|
79
|
+
f.print(obj);
|
|
80
|
+
expect(stdout).toContain('Circular');
|
|
81
|
+
});
|
|
82
|
+
it('json formatter serializes bigint via toString instead of throwing', () => {
|
|
83
|
+
const f = createFormatter('json', { quiet: false });
|
|
84
|
+
f.print({ big: 12345678901234567890n });
|
|
85
|
+
expect(stdout).toContain('12345678901234567890');
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=formatter.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.test.js","sourceRoot":"","sources":["../../src/output/formatter.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type FormatName, type Formatter, type FormatterOptions, isFormatName } from './formatter.js';
|
|
2
|
+
export { isFormatName };
|
|
3
|
+
export type { FormatName, Formatter, FormatterOptions };
|
|
4
|
+
export declare function createFormatter(name: FormatName, opts: FormatterOptions): Formatter;
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/output/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,YAAY,EACZ,MAAM,gBAAgB,CAAA;AAKvB,OAAO,EAAE,YAAY,EAAE,CAAA;AACvB,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAA;AAEvD,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,gBAAgB,GAAG,SAAS,CAenF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { isFormatName, } from './formatter.js';
|
|
2
|
+
import { JsonFormatter } from './json.js';
|
|
3
|
+
import { TextFormatter } from './text.js';
|
|
4
|
+
import { YamlFormatter } from './yaml.js';
|
|
5
|
+
export { isFormatName };
|
|
6
|
+
export function createFormatter(name, opts) {
|
|
7
|
+
switch (name) {
|
|
8
|
+
case 'text':
|
|
9
|
+
return new TextFormatter(opts);
|
|
10
|
+
case 'json':
|
|
11
|
+
return new JsonFormatter(opts);
|
|
12
|
+
case 'yaml':
|
|
13
|
+
return new YamlFormatter(opts);
|
|
14
|
+
default: {
|
|
15
|
+
// Exhaustiveness: TS will fail to compile this assignment if a new
|
|
16
|
+
// FormatName variant is added without updating the switch.
|
|
17
|
+
const _exhaustive = name;
|
|
18
|
+
throw new Error(`Unknown format: ${String(_exhaustive)}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/output/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,YAAY,GACZ,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAEzC,OAAO,EAAE,YAAY,EAAE,CAAA;AAGvB,MAAM,UAAU,eAAe,CAAC,IAAgB,EAAE,IAAsB;IACvE,QAAQ,IAAI,EAAE,CAAC;QACd,KAAK,MAAM;YACV,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,CAAA;QAC/B,KAAK,MAAM;YACV,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,CAAA;QAC/B,KAAK,MAAM;YACV,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,CAAA;QAC/B,OAAO,CAAC,CAAC,CAAC;YACT,mEAAmE;YACnE,2DAA2D;YAC3D,MAAM,WAAW,GAAU,IAAI,CAAA;YAC/B,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;QAC1D,CAAC;IACF,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Formatter, FormatterOptions } from './formatter.js';
|
|
2
|
+
export declare class JsonFormatter implements Formatter {
|
|
3
|
+
private readonly opts;
|
|
4
|
+
readonly name: "json";
|
|
5
|
+
constructor(opts: FormatterOptions);
|
|
6
|
+
print(data: unknown): void;
|
|
7
|
+
info(message: string): void;
|
|
8
|
+
error(payload: {
|
|
9
|
+
message: string;
|
|
10
|
+
details?: unknown;
|
|
11
|
+
}): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/output/json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEjE,qBAAa,aAAc,YAAW,SAAS;IAGlC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAS;gBAEF,IAAI,EAAE,gBAAgB;IAEnD,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAI1B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK3B,KAAK,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;CAQ5D"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export class JsonFormatter {
|
|
2
|
+
opts;
|
|
3
|
+
name = 'json';
|
|
4
|
+
constructor(opts) {
|
|
5
|
+
this.opts = opts;
|
|
6
|
+
}
|
|
7
|
+
print(data) {
|
|
8
|
+
process.stdout.write(`${safeStringify(data)}\n`);
|
|
9
|
+
}
|
|
10
|
+
info(message) {
|
|
11
|
+
if (this.opts.quiet)
|
|
12
|
+
return;
|
|
13
|
+
process.stderr.write(`${JSON.stringify({ level: 'info', message })}\n`);
|
|
14
|
+
}
|
|
15
|
+
error(payload) {
|
|
16
|
+
const out = {
|
|
17
|
+
level: 'error',
|
|
18
|
+
message: payload.message,
|
|
19
|
+
};
|
|
20
|
+
if (payload.details !== undefined)
|
|
21
|
+
out.details = payload.details;
|
|
22
|
+
process.stderr.write(`${safeStringify(out)}\n`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* `JSON.stringify` throws on circular references. The CLI must never crash
|
|
27
|
+
* a command in the middle of emitting structured output, so we substitute
|
|
28
|
+
* a sentinel for cycles and fall back to a safe shape on serializer error.
|
|
29
|
+
*/
|
|
30
|
+
function safeStringify(data) {
|
|
31
|
+
const seen = new WeakSet();
|
|
32
|
+
try {
|
|
33
|
+
return JSON.stringify(data, (_key, value) => {
|
|
34
|
+
if (typeof value === 'object' && value !== null) {
|
|
35
|
+
if (seen.has(value))
|
|
36
|
+
return '[Circular]';
|
|
37
|
+
seen.add(value);
|
|
38
|
+
}
|
|
39
|
+
if (typeof value === 'bigint')
|
|
40
|
+
return value.toString();
|
|
41
|
+
return value;
|
|
42
|
+
}, 2);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
return JSON.stringify({
|
|
46
|
+
error: 'unserializable',
|
|
47
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/output/json.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,aAAa;IAGI;IAFpB,IAAI,GAAG,MAAe,CAAA;IAE/B,YAA6B,IAAsB;QAAtB,SAAI,GAAJ,IAAI,CAAkB;IAAG,CAAC;IAEvD,KAAK,CAAC,IAAa;QAClB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACjD,CAAC;IAED,IAAI,CAAC,OAAe;QACnB,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAM;QAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,CAAA;IACxE,CAAC;IAED,KAAK,CAAC,OAA+C;QACpD,MAAM,GAAG,GAA4B;YACpC,KAAK,EAAE,OAAO;YACd,OAAO,EAAE,OAAO,CAAC,OAAO;SACxB,CAAA;QACD,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;YAAE,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAA;QAChE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAChD,CAAC;CACD;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAC,IAAa;IACnC,MAAM,IAAI,GAAG,IAAI,OAAO,EAAU,CAAA;IAClC,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,SAAS,CACpB,IAAI,EACJ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YACf,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACjD,IAAI,IAAI,CAAC,GAAG,CAAC,KAAe,CAAC;oBAAE,OAAO,YAAY,CAAA;gBAClD,IAAI,CAAC,GAAG,CAAC,KAAe,CAAC,CAAA;YAC1B,CAAC;YACD,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAA;YACtD,OAAO,KAAK,CAAA;QACb,CAAC,EACD,CAAC,CACD,CAAA;IACF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,OAAO,IAAI,CAAC,SAAS,CAAC;YACrB,KAAK,EAAE,gBAAgB;YACvB,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAC,CAAA;IACH,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Formatter, FormatterOptions } from './formatter.js';
|
|
2
|
+
export declare class TextFormatter implements Formatter {
|
|
3
|
+
private readonly opts;
|
|
4
|
+
readonly name: "text";
|
|
5
|
+
constructor(opts: FormatterOptions);
|
|
6
|
+
print(data: unknown): void;
|
|
7
|
+
info(message: string): void;
|
|
8
|
+
error(payload: {
|
|
9
|
+
message: string;
|
|
10
|
+
details?: unknown;
|
|
11
|
+
}): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/output/text.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEjE,qBAAa,aAAc,YAAW,SAAS;IAGlC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAS;gBAEF,IAAI,EAAE,gBAAgB;IAEnD,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAI1B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK3B,KAAK,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;CAM5D"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { inspect } from 'node:util';
|
|
2
|
+
export class TextFormatter {
|
|
3
|
+
opts;
|
|
4
|
+
name = 'text';
|
|
5
|
+
constructor(opts) {
|
|
6
|
+
this.opts = opts;
|
|
7
|
+
}
|
|
8
|
+
print(data) {
|
|
9
|
+
process.stdout.write(`${renderText(data)}\n`);
|
|
10
|
+
}
|
|
11
|
+
info(message) {
|
|
12
|
+
if (this.opts.quiet)
|
|
13
|
+
return;
|
|
14
|
+
process.stderr.write(`${message}\n`);
|
|
15
|
+
}
|
|
16
|
+
error(payload) {
|
|
17
|
+
process.stderr.write(`Error: ${payload.message}\n`);
|
|
18
|
+
if (payload.details !== undefined) {
|
|
19
|
+
process.stderr.write(`${renderText(payload.details)}\n`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function renderText(data) {
|
|
24
|
+
if (data === null || data === undefined)
|
|
25
|
+
return '';
|
|
26
|
+
if (typeof data === 'string')
|
|
27
|
+
return data;
|
|
28
|
+
if (typeof data === 'number' || typeof data === 'boolean' || typeof data === 'bigint') {
|
|
29
|
+
return String(data);
|
|
30
|
+
}
|
|
31
|
+
// `depth: 6` is generous for CLI payloads while keeping pathological
|
|
32
|
+
// (deeply nested or self-referencing) graphs from exhausting stack/heap.
|
|
33
|
+
// `inspect` already marks already-seen objects as `[Circular]`.
|
|
34
|
+
return inspect(data, { depth: 6, colors: false, compact: false });
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/output/text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAInC,MAAM,OAAO,aAAa;IAGI;IAFpB,IAAI,GAAG,MAAe,CAAA;IAE/B,YAA6B,IAAsB;QAAtB,SAAI,GAAJ,IAAI,CAAkB;IAAG,CAAC;IAEvD,KAAK,CAAC,IAAa;QAClB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC9C,CAAC;IAED,IAAI,CAAC,OAAe;QACnB,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAM;QAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAA;IACrC,CAAC;IAED,KAAK,CAAC,OAA+C;QACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,OAAO,CAAC,OAAO,IAAI,CAAC,CAAA;QACnD,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QACzD,CAAC;IACF,CAAC;CACD;AAED,SAAS,UAAU,CAAC,IAAa;IAChC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,CAAA;IAClD,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IACzC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvF,OAAO,MAAM,CAAC,IAAI,CAAC,CAAA;IACpB,CAAC;IACD,qEAAqE;IACrE,yEAAyE;IACzE,gEAAgE;IAChE,OAAO,OAAO,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;AAClE,CAAC"}
|