@namzu/cli 12.1.0 → 13.0.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/README.md +25 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +119 -60
- package/dist/cli.js.map +1 -1
- package/dist/commands/acp.d.ts +24 -8
- package/dist/commands/acp.d.ts.map +1 -1
- package/dist/commands/acp.js +221 -80
- package/dist/commands/acp.js.map +1 -1
- package/dist/commands/drain.d.ts.map +1 -1
- package/dist/commands/drain.js +45 -9
- package/dist/commands/drain.js.map +1 -1
- package/dist/commands/prior-messages.d.ts +11 -0
- package/dist/commands/prior-messages.d.ts.map +1 -0
- package/dist/commands/prior-messages.js +280 -0
- package/dist/commands/prior-messages.js.map +1 -0
- package/dist/commands/resume.d.ts.map +1 -1
- package/dist/commands/resume.js +21 -19
- package/dist/commands/resume.js.map +1 -1
- package/dist/commands/run-stream.d.ts +5 -3
- package/dist/commands/run-stream.d.ts.map +1 -1
- package/dist/commands/run-stream.js +66 -62
- package/dist/commands/run-stream.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +50 -37
- package/dist/commands/run.js.map +1 -1
- package/dist/config/debug.d.ts +55 -0
- package/dist/config/debug.d.ts.map +1 -0
- package/dist/config/debug.js +126 -0
- package/dist/config/debug.js.map +1 -0
- package/dist/config/load.d.ts +88 -4
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +386 -56
- package/dist/config/load.js.map +1 -1
- package/dist/config/schema.d.ts +87 -5
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +5 -5
- package/dist/config/schema.js.map +1 -1
- package/dist/config/trusted-project-context.d.ts +11 -0
- package/dist/config/trusted-project-context.d.ts.map +1 -0
- package/dist/config/trusted-project-context.js +28 -0
- package/dist/config/trusted-project-context.js.map +1 -0
- package/dist/context/project-path.d.ts +3 -0
- package/dist/context/project-path.d.ts.map +1 -0
- package/dist/context/project-path.js +16 -0
- package/dist/context/project-path.js.map +1 -0
- package/dist/context/project-tracker.d.ts +30 -0
- package/dist/context/project-tracker.d.ts.map +1 -0
- package/dist/context/project-tracker.js +217 -0
- package/dist/context/project-tracker.js.map +1 -0
- package/dist/context/sandbox.d.ts +29 -9
- package/dist/context/sandbox.d.ts.map +1 -1
- package/dist/context/sandbox.js +8 -0
- package/dist/context/sandbox.js.map +1 -1
- package/dist/exit-codes.d.ts +5 -4
- package/dist/exit-codes.d.ts.map +1 -1
- package/dist/exit-codes.js +5 -4
- package/dist/exit-codes.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/integrations/clipboard/text.d.ts +43 -0
- package/dist/integrations/clipboard/text.d.ts.map +1 -0
- package/dist/integrations/clipboard/text.js +43 -0
- package/dist/integrations/clipboard/text.js.map +1 -0
- package/dist/integrations/mcp/servers.d.ts +9 -0
- package/dist/integrations/mcp/servers.d.ts.map +1 -1
- package/dist/integrations/mcp/servers.js +11 -4
- package/dist/integrations/mcp/servers.js.map +1 -1
- package/dist/integrations/notifications/terminal.d.ts +32 -0
- package/dist/integrations/notifications/terminal.d.ts.map +1 -0
- package/dist/integrations/notifications/terminal.js +46 -0
- package/dist/integrations/notifications/terminal.js.map +1 -0
- package/dist/integrations/plugins/runtime.d.ts +17 -0
- package/dist/integrations/plugins/runtime.d.ts.map +1 -0
- package/dist/integrations/plugins/runtime.js +100 -0
- package/dist/integrations/plugins/runtime.js.map +1 -0
- package/dist/integrations/providers/credential-store.d.ts +17 -0
- package/dist/integrations/providers/credential-store.d.ts.map +1 -1
- package/dist/integrations/providers/credential-store.js +114 -2
- package/dist/integrations/providers/credential-store.js.map +1 -1
- package/dist/integrations/providers/index.d.ts +2 -2
- package/dist/integrations/providers/index.d.ts.map +1 -1
- package/dist/integrations/providers/index.js +2 -2
- package/dist/integrations/providers/index.js.map +1 -1
- package/dist/integrations/providers/keychain.d.ts +0 -13
- package/dist/integrations/providers/keychain.d.ts.map +1 -1
- package/dist/integrations/providers/keychain.js +0 -76
- package/dist/integrations/providers/keychain.js.map +1 -1
- package/dist/integrations/providers/oauth.d.ts +45 -16
- package/dist/integrations/providers/oauth.d.ts.map +1 -1
- package/dist/integrations/providers/oauth.js +170 -43
- package/dist/integrations/providers/oauth.js.map +1 -1
- package/dist/integrations/providers/subscription-login.d.ts +2 -0
- package/dist/integrations/providers/subscription-login.d.ts.map +1 -1
- package/dist/integrations/providers/subscription-login.js +117 -14
- package/dist/integrations/providers/subscription-login.js.map +1 -1
- package/dist/integrations/sessions/store.d.ts +111 -1
- package/dist/integrations/sessions/store.d.ts.map +1 -1
- package/dist/integrations/sessions/store.js +400 -7
- package/dist/integrations/sessions/store.js.map +1 -1
- package/dist/integrations/sessions/transcript-export.d.ts +25 -0
- package/dist/integrations/sessions/transcript-export.d.ts.map +1 -0
- package/dist/integrations/sessions/transcript-export.js +441 -0
- package/dist/integrations/sessions/transcript-export.js.map +1 -0
- package/dist/integrations/sessions/turn-evidence.d.ts +138 -0
- package/dist/integrations/sessions/turn-evidence.d.ts.map +1 -0
- package/dist/integrations/sessions/turn-evidence.js +506 -0
- package/dist/integrations/sessions/turn-evidence.js.map +1 -0
- package/dist/integrations/subagents/runtime.d.ts +7 -12
- package/dist/integrations/subagents/runtime.d.ts.map +1 -1
- package/dist/integrations/subagents/runtime.js +19 -10
- package/dist/integrations/subagents/runtime.js.map +1 -1
- package/dist/integrations/trust/store.d.ts.map +1 -1
- package/dist/integrations/trust/store.js +27 -13
- package/dist/integrations/trust/store.js.map +1 -1
- package/dist/permissions/canonical-project.d.ts +9 -0
- package/dist/permissions/canonical-project.d.ts.map +1 -0
- package/dist/permissions/canonical-project.js +13 -0
- package/dist/permissions/canonical-project.js.map +1 -0
- package/dist/permissions/checks.d.ts +65 -0
- package/dist/permissions/checks.d.ts.map +1 -0
- package/dist/permissions/checks.js +122 -0
- package/dist/permissions/checks.js.map +1 -0
- package/dist/permissions/headless-trust.d.ts +9 -5
- package/dist/permissions/headless-trust.d.ts.map +1 -1
- package/dist/permissions/headless-trust.js +18 -4
- package/dist/permissions/headless-trust.js.map +1 -1
- package/dist/permissions/rules.d.ts +16 -7
- package/dist/permissions/rules.d.ts.map +1 -1
- package/dist/permissions/rules.js +78 -13
- package/dist/permissions/rules.js.map +1 -1
- package/dist/tui/App.d.ts +5 -2
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +1555 -143
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/Composer.d.ts +14 -3
- package/dist/tui/Composer.d.ts.map +1 -1
- package/dist/tui/Composer.js +53 -15
- package/dist/tui/Composer.js.map +1 -1
- package/dist/tui/EditPromptPicker.d.ts +8 -0
- package/dist/tui/EditPromptPicker.d.ts.map +1 -0
- package/dist/tui/EditPromptPicker.js +18 -0
- package/dist/tui/EditPromptPicker.js.map +1 -0
- package/dist/tui/LiveActivity.d.ts.map +1 -1
- package/dist/tui/LiveActivity.js +2 -1
- package/dist/tui/LiveActivity.js.map +1 -1
- package/dist/tui/Markdown.d.ts.map +1 -1
- package/dist/tui/Markdown.js +2 -1
- package/dist/tui/Markdown.js.map +1 -1
- package/dist/tui/PermissionOverlay.d.ts.map +1 -1
- package/dist/tui/PermissionOverlay.js +7 -1
- package/dist/tui/PermissionOverlay.js.map +1 -1
- package/dist/tui/Picker.d.ts +4 -4
- package/dist/tui/Picker.d.ts.map +1 -1
- package/dist/tui/Picker.js +86 -7
- package/dist/tui/Picker.js.map +1 -1
- package/dist/tui/ResumePicker.d.ts.map +1 -1
- package/dist/tui/ResumePicker.js +1 -1
- package/dist/tui/ResumePicker.js.map +1 -1
- package/dist/tui/Transcript.d.ts +4 -2
- package/dist/tui/Transcript.d.ts.map +1 -1
- package/dist/tui/Transcript.js +31 -5
- package/dist/tui/Transcript.js.map +1 -1
- package/dist/tui/agent.d.ts +123 -19
- package/dist/tui/agent.d.ts.map +1 -1
- package/dist/tui/agent.js +665 -143
- package/dist/tui/agent.js.map +1 -1
- package/dist/tui/compact-transcript.d.ts +24 -0
- package/dist/tui/compact-transcript.d.ts.map +1 -0
- package/dist/tui/compact-transcript.js +46 -0
- package/dist/tui/compact-transcript.js.map +1 -0
- package/dist/tui/conversation-history.d.ts +33 -0
- package/dist/tui/conversation-history.d.ts.map +1 -0
- package/dist/tui/conversation-history.js +42 -0
- package/dist/tui/conversation-history.js.map +1 -0
- package/dist/tui/edit-prompts.d.ts +23 -0
- package/dist/tui/edit-prompts.d.ts.map +1 -0
- package/dist/tui/edit-prompts.js +35 -0
- package/dist/tui/edit-prompts.js.map +1 -0
- package/dist/tui/live-window.d.ts +3 -1
- package/dist/tui/live-window.d.ts.map +1 -1
- package/dist/tui/live-window.js +20 -8
- package/dist/tui/live-window.js.map +1 -1
- package/dist/tui/slashCommands.d.ts +178 -9
- package/dist/tui/slashCommands.d.ts.map +1 -1
- package/dist/tui/slashCommands.js +339 -15
- package/dist/tui/slashCommands.js.map +1 -1
- package/dist/tui/terminal-display.d.ts +12 -0
- package/dist/tui/terminal-display.d.ts.map +1 -0
- package/dist/tui/terminal-display.js +65 -0
- package/dist/tui/terminal-display.js.map +1 -0
- package/dist/tui/types.d.ts +14 -2
- package/dist/tui/types.d.ts.map +1 -1
- package/dist/tui/workspace-diff.d.ts +40 -0
- package/dist/tui/workspace-diff.d.ts.map +1 -0
- package/dist/tui/workspace-diff.js +101 -0
- package/dist/tui/workspace-diff.js.map +1 -0
- package/package.json +7 -7
package/dist/exit-codes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exit-codes.d.ts","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"exit-codes.d.ts","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,eAAO,MAAM,OAAO,IAAI,CAAA;AACxB,eAAO,MAAM,SAAS,IAAI,CAAA;AAC1B,eAAO,MAAM,cAAc,IAAI,CAAA;AAC/B,eAAO,MAAM,UAAU,KAAK,CAAA;AAC5B,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAClC,eAAO,MAAM,mBAAmB,KAAK,CAAA;AACrC,eAAO,MAAM,cAAc,KAAK,CAAA;AAChC,eAAO,MAAM,eAAe,KAAK,CAAA;AAEjC,MAAM,MAAM,WAAW,GACpB,OAAO,OAAO,GACd,OAAO,SAAS,GAChB,OAAO,cAAc,GACrB,OAAO,UAAU,GACjB,OAAO,gBAAgB,GACvB,OAAO,mBAAmB,GAC1B,OAAO,cAAc,GACrB,OAAO,eAAe,CAAA"}
|
package/dist/exit-codes.js
CHANGED
|
@@ -37,10 +37,11 @@
|
|
|
37
37
|
* nothing else is. A caller who cannot tell them
|
|
38
38
|
* apart matches on the message string, and then
|
|
39
39
|
* the message can never be reworded.
|
|
40
|
-
* 78 EXIT_BAD_CONFIG — sysexits EX_CONFIG; a config
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
40
|
+
* 78 EXIT_BAD_CONFIG — sysexits EX_CONFIG; a config source is present
|
|
41
|
+
* and cannot be read or contains a known setting
|
|
42
|
+
* with an invalid value, so the run refuses rather
|
|
43
|
+
* than silently substituting another setting.
|
|
44
|
+
* Distinct from 2 for
|
|
44
45
|
* the reason 2 is distinct from 0: "namzu is not
|
|
45
46
|
* configured here" and "your configuration is
|
|
46
47
|
* unreadable" are fixed by opposite actions, and a
|
package/dist/exit-codes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAA;AACxB,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAA;AAC1B,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAA;AAC/B,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,CAAA;AAC5B,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAA;AAClC,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAA;AACrC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAA;AAChC,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,6 @@ export { runCli, type RunCliOptions } from './cli.js';
|
|
|
12
12
|
export type { CommandContext, CommandDef, CommandHandler, CommandHandlerArgs, } from './commands/types.js';
|
|
13
13
|
export { registerAll, registerCommand, type RegisterOptions, } from './commands/registry.js';
|
|
14
14
|
export { createFormatter, type FormatName, type Formatter, type FormatterOptions, isFormatName, } from './output/index.js';
|
|
15
|
-
export { ConfigLoadError, loadConfig, loadConfigWithProvenance, type ConfigProvenance, type ConfigSource, type LoadConfigOptions, } from './config/load.js';
|
|
16
|
-
export { DEFAULT_CONFIG, type NamzuCliConfig } from './config/schema.js';
|
|
15
|
+
export { ConfigLoadError, ConfigValueError, loadConfig, loadConfigWithProvenance, type ConfigProvenance, type ConfigSource, type ConfigValueSource, type LoadConfigOptions, } from './config/load.js';
|
|
16
|
+
export { DEFAULT_CONFIG, type NamzuCliConfig, type PluginConfig, type PluginScope, type TerminalNotificationEvent, type TerminalNotificationMethod, type TuiConfig, } from './config/schema.js';
|
|
17
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACN,oBAAoB,EACpB,MAAM,EACN,cAAc,EACd,mBAAmB,EACnB,SAAS,GACT,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAE5D,OAAO,EACN,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,GACpB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACN,KAAK,eAAe,EACpB,2BAA2B,EAC3B,iBAAiB,EACjB,oBAAoB,GACpB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAGvD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAA;AACrD,YAAY,EACX,cAAc,EACd,UAAU,EACV,cAAc,EACd,kBAAkB,GAClB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACN,WAAW,EACX,eAAe,EACf,KAAK,eAAe,GACpB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACN,eAAe,EACf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,YAAY,GACZ,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACN,eAAe,EACf,UAAU,EACV,wBAAwB,EACxB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACtB,MAAM,kBAAkB,CAAA;AACzB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACN,oBAAoB,EACpB,MAAM,EACN,cAAc,EACd,mBAAmB,EACnB,SAAS,GACT,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAE5D,OAAO,EACN,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,GACpB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACN,KAAK,eAAe,EACpB,2BAA2B,EAC3B,iBAAiB,EACjB,oBAAoB,GACpB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAGvD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAA;AACrD,YAAY,EACX,cAAc,EACd,UAAU,EACV,cAAc,EACd,kBAAkB,GAClB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACN,WAAW,EACX,eAAe,EACf,KAAK,eAAe,GACpB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACN,eAAe,EACf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,YAAY,GACZ,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACN,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,wBAAwB,EACxB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACtB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACN,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,SAAS,GACd,MAAM,oBAAoB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,6 @@ export { runDoctorCommand } from './commands/doctor.js';
|
|
|
12
12
|
export { runCli } from './cli.js';
|
|
13
13
|
export { registerAll, registerCommand, } from './commands/registry.js';
|
|
14
14
|
export { createFormatter, isFormatName, } from './output/index.js';
|
|
15
|
-
export { ConfigLoadError, loadConfig, loadConfigWithProvenance, } from './config/load.js';
|
|
16
|
-
export { DEFAULT_CONFIG } from './config/schema.js';
|
|
15
|
+
export { ConfigLoadError, ConfigValueError, loadConfig, loadConfigWithProvenance, } from './config/load.js';
|
|
16
|
+
export { DEFAULT_CONFIG, } from './config/schema.js';
|
|
17
17
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,iEAAiE;AACjE,OAAO,EACN,oBAAoB,EACpB,MAAM,EACN,cAAc,EACd,mBAAmB,EACnB,SAAS,GACT,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EACN,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,GACpB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAEN,2BAA2B,EAC3B,iBAAiB,EACjB,oBAAoB,GACpB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEvD,yCAAyC;AACzC,OAAO,EAAE,MAAM,EAAsB,MAAM,UAAU,CAAA;AAOrD,OAAO,EACN,WAAW,EACX,eAAe,GAEf,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACN,eAAe,EAIf,YAAY,GACZ,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACN,eAAe,EACf,UAAU,EACV,wBAAwB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,iEAAiE;AACjE,OAAO,EACN,oBAAoB,EACpB,MAAM,EACN,cAAc,EACd,mBAAmB,EACnB,SAAS,GACT,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EACN,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,GACpB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAEN,2BAA2B,EAC3B,iBAAiB,EACjB,oBAAoB,GACpB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEvD,yCAAyC;AACzC,OAAO,EAAE,MAAM,EAAsB,MAAM,UAAU,CAAA;AAOrD,OAAO,EACN,WAAW,EACX,eAAe,GAEf,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACN,eAAe,EAIf,YAAY,GACZ,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACN,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,wBAAwB,GAKxB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACN,cAAc,GAOd,MAAM,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ask an interactive terminal to place text on its clipboard via OSC 52.
|
|
3
|
+
*
|
|
4
|
+
* This deliberately does not spawn a platform clipboard command. `/copy` is a
|
|
5
|
+
* TUI operation, not permission to run arbitrary host code outside the agent's
|
|
6
|
+
* sandbox and approval path. The escape payload is base64, so model-authored
|
|
7
|
+
* control characters cannot terminate the sequence and inject another one.
|
|
8
|
+
*
|
|
9
|
+
* OSC 52 has no portable acknowledgement. A successful write proves only that
|
|
10
|
+
* the complete request reached Ink's stdout; a terminal, multiplexer or remote
|
|
11
|
+
* hop may still ignore it. The result therefore says `request-sent`, never
|
|
12
|
+
* `copied`, and the caller must preserve that distinction in its message.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Bound the raw UTF-8 text before base64 expands it by roughly one third.
|
|
16
|
+
*
|
|
17
|
+
* Terminal limits vary and cannot be negotiated. Refusing above a stated cap
|
|
18
|
+
* is honest; truncating would put something on the clipboard that is not the
|
|
19
|
+
* answer the operator asked for.
|
|
20
|
+
*/
|
|
21
|
+
export declare const MAX_CLIPBOARD_TEXT_BYTES = 100000;
|
|
22
|
+
export interface TerminalClipboardOutput {
|
|
23
|
+
/** Whether Ink is attached to an interactive terminal. */
|
|
24
|
+
readonly isTTY?: boolean;
|
|
25
|
+
/** Ink's stdout writer, which preserves the frame around out-of-band output. */
|
|
26
|
+
readonly write: (data: string) => void;
|
|
27
|
+
}
|
|
28
|
+
export type ClipboardWriteResult = {
|
|
29
|
+
readonly kind: 'request-sent';
|
|
30
|
+
readonly bytes: number;
|
|
31
|
+
} | {
|
|
32
|
+
readonly kind: 'unavailable';
|
|
33
|
+
readonly detail: string;
|
|
34
|
+
} | {
|
|
35
|
+
readonly kind: 'too-large';
|
|
36
|
+
readonly bytes: number;
|
|
37
|
+
readonly limit: number;
|
|
38
|
+
} | {
|
|
39
|
+
readonly kind: 'write-failed';
|
|
40
|
+
readonly detail: string;
|
|
41
|
+
};
|
|
42
|
+
export declare function writeClipboardText(text: string, output: TerminalClipboardOutput): ClipboardWriteResult;
|
|
43
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/integrations/clipboard/text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,SAAU,CAAA;AAE/C,MAAM,WAAW,uBAAuB;IACvC,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;IACxB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACtC;AAED,MAAM,MAAM,oBAAoB,GAC7B;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC9E;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE7D,wBAAgB,kBAAkB,CACjC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,uBAAuB,GAC7B,oBAAoB,CAqBtB"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ask an interactive terminal to place text on its clipboard via OSC 52.
|
|
3
|
+
*
|
|
4
|
+
* This deliberately does not spawn a platform clipboard command. `/copy` is a
|
|
5
|
+
* TUI operation, not permission to run arbitrary host code outside the agent's
|
|
6
|
+
* sandbox and approval path. The escape payload is base64, so model-authored
|
|
7
|
+
* control characters cannot terminate the sequence and inject another one.
|
|
8
|
+
*
|
|
9
|
+
* OSC 52 has no portable acknowledgement. A successful write proves only that
|
|
10
|
+
* the complete request reached Ink's stdout; a terminal, multiplexer or remote
|
|
11
|
+
* hop may still ignore it. The result therefore says `request-sent`, never
|
|
12
|
+
* `copied`, and the caller must preserve that distinction in its message.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Bound the raw UTF-8 text before base64 expands it by roughly one third.
|
|
16
|
+
*
|
|
17
|
+
* Terminal limits vary and cannot be negotiated. Refusing above a stated cap
|
|
18
|
+
* is honest; truncating would put something on the clipboard that is not the
|
|
19
|
+
* answer the operator asked for.
|
|
20
|
+
*/
|
|
21
|
+
export const MAX_CLIPBOARD_TEXT_BYTES = 100_000;
|
|
22
|
+
export function writeClipboardText(text, output) {
|
|
23
|
+
if (!output.isTTY) {
|
|
24
|
+
return { kind: 'unavailable', detail: 'stdout is not an interactive terminal' };
|
|
25
|
+
}
|
|
26
|
+
const bytes = Buffer.byteLength(text, 'utf8');
|
|
27
|
+
if (bytes > MAX_CLIPBOARD_TEXT_BYTES) {
|
|
28
|
+
return { kind: 'too-large', bytes, limit: MAX_CLIPBOARD_TEXT_BYTES };
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const encoded = Buffer.from(text, 'utf8').toString('base64');
|
|
32
|
+
// `c` selects the clipboard; BEL terminates the OSC control sequence.
|
|
33
|
+
output.write(`\x1b]52;c;${encoded}\x07`);
|
|
34
|
+
return { kind: 'request-sent', bytes };
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
return {
|
|
38
|
+
kind: 'write-failed',
|
|
39
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../../src/integrations/clipboard/text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,OAAO,CAAA;AAe/C,MAAM,UAAU,kBAAkB,CACjC,IAAY,EACZ,MAA+B;IAE/B,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,uCAAuC,EAAE,CAAA;IAChF,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC7C,IAAI,KAAK,GAAG,wBAAwB,EAAE,CAAC;QACtC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAA;IACrE,CAAC;IAED,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAC5D,sEAAsE;QACtE,MAAM,CAAC,KAAK,CAAC,aAAa,OAAO,MAAM,CAAC,CAAA;QACxC,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,CAAA;IACvC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,OAAO;YACN,IAAI,EAAE,cAAc;YACpB,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAA;IACF,CAAC;AACF,CAAC"}
|
|
@@ -78,6 +78,15 @@ export type McpServersConfig = Readonly<Record<string, McpServerSpec>>;
|
|
|
78
78
|
export interface ConnectedMcpServer {
|
|
79
79
|
readonly name: string;
|
|
80
80
|
readonly toolCount: number;
|
|
81
|
+
/**
|
|
82
|
+
* What this server actually contributes, by tool name.
|
|
83
|
+
*
|
|
84
|
+
* Carried from the listing rather than recovered later. The names arrive
|
|
85
|
+
* prefixed with the server's own (`mcp_tickets_create`), so a caller COULD
|
|
86
|
+
* split them back apart — but that turns an encoding this file owns into a
|
|
87
|
+
* format two places have to agree about, and the list is free right here.
|
|
88
|
+
*/
|
|
89
|
+
readonly tools: readonly string[];
|
|
81
90
|
}
|
|
82
91
|
export interface FailedMcpServer {
|
|
83
92
|
readonly name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"servers.d.ts","sourceRoot":"","sources":["../../../src/integrations/mcp/servers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAEN,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEnB,MAAM,YAAY,CAAA;AAEnB;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,QAAS,CAAA;AAExC;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,OAAQ,CAAA;AAErC,gFAAgF;AAChF,MAAM,WAAW,aAAa;IAC7B,oCAAoC;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/C;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACvC,gEAAgE;IAChE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,mCAAmC;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACnD;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAA;AAEtE,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"servers.d.ts","sourceRoot":"","sources":["../../../src/integrations/mcp/servers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAEN,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEnB,MAAM,YAAY,CAAA;AAEnB;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,QAAS,CAAA;AAExC;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,OAAQ,CAAA;AAErC,gFAAgF;AAChF,MAAM,WAAW,aAAa;IAC7B,oCAAoC;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/C;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACvC,gEAAgE;IAChE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,mCAAmC;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACnD;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAA;AAEtE,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CACjC;AAED,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,aAAa;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,CAAA;IACzC,QAAQ,CAAC,SAAS,EAAE,SAAS,kBAAkB,EAAE,CAAA;IACjD,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;IAC3C;;;;;;;OAOG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,iBAAiB,GAAG,MAAM,CAwBhG;AAkBD,wBAAsB,iBAAiB,CACtC,MAAM,EAAE,gBAAgB,GAAG,SAAS,EACpC,OAAO,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC/B,OAAO,CAAC,aAAa,CAAC,CA0ExB"}
|
|
@@ -118,10 +118,17 @@ export async function connectMcpServers(config, options) {
|
|
|
118
118
|
try {
|
|
119
119
|
await withDeadline(client.connect(), CONNECT_TIMEOUT_MS, `server "${name}"`);
|
|
120
120
|
const listed = await withDeadline(client.listTools(), CONNECT_TIMEOUT_MS, `server "${name}" listing its tools`);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
121
|
+
// Adapted once, then read twice. Adapting a second time to collect
|
|
122
|
+
// the names would build a parallel set of definitions bound to the
|
|
123
|
+
// same client — cheap today and exactly the kind of duplicate a
|
|
124
|
+
// future adapter with a side effect turns into a bug.
|
|
125
|
+
const adapted = listed.map((tool) => mcpToolToToolDefinition(tool, client, name));
|
|
126
|
+
tools.push(...adapted);
|
|
127
|
+
connected.push({
|
|
128
|
+
name,
|
|
129
|
+
toolCount: adapted.length,
|
|
130
|
+
tools: adapted.map((tool) => tool.name),
|
|
131
|
+
});
|
|
125
132
|
clients.push(client);
|
|
126
133
|
}
|
|
127
134
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"servers.js","sourceRoot":"","sources":["../../../src/integrations/mcp/servers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EACN,SAAS,EAGT,uBAAuB,GACvB,MAAM,YAAY,CAAA;AAEnB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAA;AAExC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"servers.js","sourceRoot":"","sources":["../../../src/integrations/mcp/servers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { TerminalNotificationEvent, TerminalNotificationMethod } from '../../config/schema.js';
|
|
2
|
+
/** A semantic TUI moment, before it is rendered for a terminal protocol. */
|
|
3
|
+
export type TerminalNotification = {
|
|
4
|
+
readonly kind: 'approval-required';
|
|
5
|
+
} | {
|
|
6
|
+
readonly kind: 'turn-settled';
|
|
7
|
+
readonly outcome: 'completed' | 'stopped' | 'failed';
|
|
8
|
+
};
|
|
9
|
+
export interface TerminalNotificationOutput {
|
|
10
|
+
readonly isTTY?: boolean;
|
|
11
|
+
readonly write: (data: string) => void;
|
|
12
|
+
}
|
|
13
|
+
export type TerminalNotificationResult = {
|
|
14
|
+
readonly kind: 'request-sent';
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: 'unavailable';
|
|
17
|
+
readonly detail: string;
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: 'write-failed';
|
|
20
|
+
readonly detail: string;
|
|
21
|
+
};
|
|
22
|
+
/** Whether one configured setting includes this semantic event. */
|
|
23
|
+
export declare function terminalNotificationEnabled(setting: boolean | readonly TerminalNotificationEvent[] | undefined, notification: TerminalNotification): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Send one fixed, content-free notification request through Ink's stdout.
|
|
26
|
+
*
|
|
27
|
+
* Neither protocol acknowledges that a terminal displayed anything. Success
|
|
28
|
+
* therefore means only that the request was written, never that a desktop
|
|
29
|
+
* notification appeared or a bell was audible.
|
|
30
|
+
*/
|
|
31
|
+
export declare function writeTerminalNotification(notification: TerminalNotification, method: TerminalNotificationMethod, output: TerminalNotificationOutput): TerminalNotificationResult;
|
|
32
|
+
//# sourceMappingURL=terminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../../src/integrations/notifications/terminal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAA;AAEnG,4EAA4E;AAC5E,MAAM,MAAM,oBAAoB,GAC7B;IAAE,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAA;CAAE,GACtC;IACA,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;IAC7B,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAA;CACnD,CAAA;AAEJ,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACtC;AAED,MAAM,MAAM,0BAA0B,GACnC;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACjC;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE7D,mEAAmE;AACnE,wBAAgB,2BAA2B,CAC1C,OAAO,EAAE,OAAO,GAAG,SAAS,yBAAyB,EAAE,GAAG,SAAS,EACnE,YAAY,EAAE,oBAAoB,GAChC,OAAO,CAIT;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACxC,YAAY,EAAE,oBAAoB,EAClC,MAAM,EAAE,0BAA0B,EAClC,MAAM,EAAE,0BAA0B,GAChC,0BAA0B,CAe5B"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Whether one configured setting includes this semantic event. */
|
|
2
|
+
export function terminalNotificationEnabled(setting, notification) {
|
|
3
|
+
if (setting === true)
|
|
4
|
+
return true;
|
|
5
|
+
if (!Array.isArray(setting))
|
|
6
|
+
return false;
|
|
7
|
+
return setting.includes(notification.kind);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Send one fixed, content-free notification request through Ink's stdout.
|
|
11
|
+
*
|
|
12
|
+
* Neither protocol acknowledges that a terminal displayed anything. Success
|
|
13
|
+
* therefore means only that the request was written, never that a desktop
|
|
14
|
+
* notification appeared or a bell was audible.
|
|
15
|
+
*/
|
|
16
|
+
export function writeTerminalNotification(notification, method, output) {
|
|
17
|
+
if (!output.isTTY) {
|
|
18
|
+
return { kind: 'unavailable', detail: 'stdout is not an interactive terminal' };
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
if (method === 'bel')
|
|
22
|
+
output.write('\x07');
|
|
23
|
+
else
|
|
24
|
+
output.write(`\x1b]9;${notificationText(notification)}\x07`);
|
|
25
|
+
return { kind: 'request-sent' };
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
return {
|
|
29
|
+
kind: 'write-failed',
|
|
30
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function notificationText(notification) {
|
|
35
|
+
if (notification.kind === 'approval-required')
|
|
36
|
+
return 'Namzu: approval required';
|
|
37
|
+
switch (notification.outcome) {
|
|
38
|
+
case 'completed':
|
|
39
|
+
return 'Namzu: turn completed';
|
|
40
|
+
case 'stopped':
|
|
41
|
+
return 'Namzu: turn needs attention';
|
|
42
|
+
case 'failed':
|
|
43
|
+
return 'Namzu: turn failed';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../../src/integrations/notifications/terminal.ts"],"names":[],"mappings":"AAoBA,mEAAmE;AACnE,MAAM,UAAU,2BAA2B,CAC1C,OAAmE,EACnE,YAAkC;IAElC,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IACjC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IACzC,OAAO,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;AAC3C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CACxC,YAAkC,EAClC,MAAkC,EAClC,MAAkC;IAElC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,uCAAuC,EAAE,CAAA;IAChF,CAAC;IAED,IAAI,CAAC;QACJ,IAAI,MAAM,KAAK,KAAK;YAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;;YACrC,MAAM,CAAC,KAAK,CAAC,UAAU,gBAAgB,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;QACjE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAA;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,OAAO;YACN,IAAI,EAAE,cAAc;YACpB,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAA;IACF,CAAC;AACF,CAAC;AAED,SAAS,gBAAgB,CAAC,YAAkC;IAC3D,IAAI,YAAY,CAAC,IAAI,KAAK,mBAAmB;QAAE,OAAO,0BAA0B,CAAA;IAChF,QAAQ,YAAY,CAAC,OAAO,EAAE,CAAC;QAC9B,KAAK,WAAW;YACf,OAAO,uBAAuB,CAAA;QAC/B,KAAK,SAAS;YACb,OAAO,6BAA6B,CAAA;QACrC,KAAK,QAAQ;YACZ,OAAO,oBAAoB,CAAA;IAC7B,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PluginLifecycleManager, SkillRegistry, type ToolRegistry } from '@namzu/sdk';
|
|
2
|
+
import type { PluginConfig } from '../../config/schema.js';
|
|
3
|
+
export interface CliPluginRuntime {
|
|
4
|
+
readonly manager: PluginLifecycleManager;
|
|
5
|
+
readonly skills: SkillRegistry;
|
|
6
|
+
readonly pluginCount: number;
|
|
7
|
+
close(): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Build the executable extension runtime owned by one agent session.
|
|
11
|
+
*
|
|
12
|
+
* The exact `enabled === true` check is the default-off boundary. Nothing in
|
|
13
|
+
* the plugin directories is discovered, read, or imported on every other
|
|
14
|
+
* value. Callers invoke this only after project trust has pinned `cwd`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createCliPluginRuntime(config: PluginConfig | undefined, tools: ToolRegistry, cwd: string): Promise<CliPluginRuntime | undefined>;
|
|
17
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/integrations/plugins/runtime.ts"],"names":[],"mappings":"AAEA,OAAO,EACN,sBAAsB,EAEtB,aAAa,EAEb,KAAK,YAAY,EAEjB,MAAM,YAAY,CAAA;AAEnB,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,wBAAwB,CAAA;AAGvE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAA;IACxC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACtB;AAMD;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC3C,MAAM,EAAE,YAAY,GAAG,SAAS,EAChC,KAAK,EAAE,YAAY,EACnB,GAAG,EAAE,MAAM,GACT,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAmFvC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { PluginLifecycleManager, PluginRegistry, SkillRegistry, SkillTool, discoverAllPluginDirs, } from '@namzu/sdk';
|
|
3
|
+
import { cliLogger } from '../../logging.js';
|
|
4
|
+
function message(error) {
|
|
5
|
+
return error instanceof Error ? error.message : String(error);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Build the executable extension runtime owned by one agent session.
|
|
9
|
+
*
|
|
10
|
+
* The exact `enabled === true` check is the default-off boundary. Nothing in
|
|
11
|
+
* the plugin directories is discovered, read, or imported on every other
|
|
12
|
+
* value. Callers invoke this only after project trust has pinned `cwd`.
|
|
13
|
+
*/
|
|
14
|
+
export async function createCliPluginRuntime(config, tools, cwd) {
|
|
15
|
+
if (config?.enabled !== true)
|
|
16
|
+
return undefined;
|
|
17
|
+
const log = cliLogger();
|
|
18
|
+
const plugins = new PluginRegistry();
|
|
19
|
+
const skills = new SkillRegistry(log);
|
|
20
|
+
const manager = new PluginLifecycleManager({
|
|
21
|
+
pluginRegistry: plugins,
|
|
22
|
+
toolRegistry: tools,
|
|
23
|
+
skillRegistry: skills,
|
|
24
|
+
scopeRoots: { project: cwd, user: homedir() },
|
|
25
|
+
log,
|
|
26
|
+
...(config.hookTimeoutMs !== undefined ? { hookTimeoutMs: config.hookTimeoutMs } : {}),
|
|
27
|
+
});
|
|
28
|
+
const allowedScopes = config.allowedScopes ?? ['project', 'user'];
|
|
29
|
+
const discovered = await discoverAllPluginDirs(cwd, {
|
|
30
|
+
enabled: true,
|
|
31
|
+
autoDiscovery: config.autoDiscovery ?? true,
|
|
32
|
+
allowedScopes,
|
|
33
|
+
log,
|
|
34
|
+
});
|
|
35
|
+
const installed = [];
|
|
36
|
+
let ownsSkillTool = false;
|
|
37
|
+
try {
|
|
38
|
+
for (const scope of allowedScopes) {
|
|
39
|
+
const dirs = [...discovered[scope]].sort((a, b) => a.localeCompare(b));
|
|
40
|
+
for (const dir of dirs) {
|
|
41
|
+
const plugin = await manager.install(dir, scope);
|
|
42
|
+
installed.push(plugin);
|
|
43
|
+
await manager.enable(plugin.id);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (skills.size > 0 && !tools.has(SkillTool.name)) {
|
|
47
|
+
tools.register(SkillTool);
|
|
48
|
+
ownsSkillTool = true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (ownsSkillTool)
|
|
53
|
+
tools.unregister(SkillTool.name);
|
|
54
|
+
const cleanupErrors = [];
|
|
55
|
+
for (const plugin of [...installed].reverse()) {
|
|
56
|
+
try {
|
|
57
|
+
await manager.uninstall(plugin.id);
|
|
58
|
+
}
|
|
59
|
+
catch (cleanupError) {
|
|
60
|
+
cleanupErrors.push(cleanupError);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const cleanupSuffix = cleanupErrors.length === 0
|
|
64
|
+
? ''
|
|
65
|
+
: ` Cleanup also failed: ${cleanupErrors.map(message).join('; ')}`;
|
|
66
|
+
throw new Error(`Plugin runtime could not start: ${message(error)}.${cleanupSuffix}`, {
|
|
67
|
+
cause: error,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
let closePromise;
|
|
71
|
+
return {
|
|
72
|
+
manager,
|
|
73
|
+
skills,
|
|
74
|
+
pluginCount: installed.length,
|
|
75
|
+
close() {
|
|
76
|
+
if (closePromise)
|
|
77
|
+
return closePromise;
|
|
78
|
+
closePromise = (async () => {
|
|
79
|
+
const errors = [];
|
|
80
|
+
if (ownsSkillTool) {
|
|
81
|
+
tools.unregister(SkillTool.name);
|
|
82
|
+
ownsSkillTool = false;
|
|
83
|
+
}
|
|
84
|
+
for (const plugin of [...installed].reverse()) {
|
|
85
|
+
try {
|
|
86
|
+
await manager.uninstall(plugin.id);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
errors.push(error);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (errors.length > 0) {
|
|
93
|
+
throw new AggregateError(errors, 'One or more plugins could not be uninstalled.');
|
|
94
|
+
}
|
|
95
|
+
})();
|
|
96
|
+
return closePromise;
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/integrations/plugins/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -47,6 +47,13 @@ export declare const CREDENTIALS_FILE_VERSION: 1;
|
|
|
47
47
|
export declare class CredentialStoreError extends Error {
|
|
48
48
|
readonly name = "CredentialStoreError";
|
|
49
49
|
}
|
|
50
|
+
export type ConditionalCredentialWrite = {
|
|
51
|
+
readonly replaced: true;
|
|
52
|
+
readonly current: AgentOAuthCredential;
|
|
53
|
+
} | {
|
|
54
|
+
readonly replaced: false;
|
|
55
|
+
readonly current: AgentOAuthCredential | null;
|
|
56
|
+
};
|
|
50
57
|
export declare function credentialsPath(home?: string): string;
|
|
51
58
|
/**
|
|
52
59
|
* The stored subscription credential, or `null` when there is none.
|
|
@@ -68,6 +75,16 @@ export declare function readStoredSubscriptionCredential(home?: string): AgentOA
|
|
|
68
75
|
* removes.
|
|
69
76
|
*/
|
|
70
77
|
export declare function writeStoredSubscriptionCredential(cred: AgentOAuthCredential, home?: string): string;
|
|
78
|
+
/**
|
|
79
|
+
* Replace exactly the credential a refresh was derived from.
|
|
80
|
+
*
|
|
81
|
+
* Comparison and rename happen under the same store-owned cross-process lock.
|
|
82
|
+
* A changed record is returned to the caller and is never overwritten. This is
|
|
83
|
+
* the durable authority boundary a post-network plain reread cannot provide:
|
|
84
|
+
* without the lock, another writer can still rotate the credential between
|
|
85
|
+
* the comparison and the rename.
|
|
86
|
+
*/
|
|
87
|
+
export declare function replaceStoredSubscriptionCredential(expected: AgentOAuthCredential, replacement: AgentOAuthCredential, home?: string): ConditionalCredentialWrite;
|
|
71
88
|
/** Remove the stored credential. Absence is success. */
|
|
72
89
|
export declare function clearStoredSubscriptionCredential(home?: string): void;
|
|
73
90
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credential-store.d.ts","sourceRoot":"","sources":["../../../src/integrations/providers/credential-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;
|
|
1
|
+
{"version":3,"file":"credential-store.d.ts","sourceRoot":"","sources":["../../../src/integrations/providers/credential-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAoBH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAKzD,eAAO,MAAM,wBAAwB,EAAG,CAAU,CAAA;AAElD,wFAAwF;AACxF,qBAAa,oBAAqB,SAAQ,KAAK;IAC9C,SAAkB,IAAI,0BAAyB;CAC/C;AAED,MAAM,MAAM,0BAA0B,GACnC;IAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GACnE;IAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAA;CAAE,CAAA;AAE9E,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAAkB,GAAG,MAAM,CAEhE;AAED;;;;;;;;GAQG;AACH,wBAAgB,gCAAgC,CAC/C,IAAI,GAAE,MAAkB,GACtB,oBAAoB,GAAG,IAAI,CA2B7B;AAED;;;;;;;;GAQG;AACH,wBAAgB,iCAAiC,CAChD,IAAI,EAAE,oBAAoB,EAC1B,IAAI,GAAE,MAAkB,GACtB,MAAM,CAIR;AAED;;;;;;;;GAQG;AACH,wBAAgB,mCAAmC,CAClD,QAAQ,EAAE,oBAAoB,EAC9B,WAAW,EAAE,oBAAoB,EACjC,IAAI,GAAE,MAAkB,GACtB,0BAA0B,CAS5B;AAsDD,wDAAwD;AACxD,wBAAgB,iCAAiC,CAAC,IAAI,GAAE,MAAkB,GAAG,IAAI,CAIhF;AA+FD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAiBlD;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAMpE;AAgDD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBvD;AAED,qFAAqF;AACrF,wBAAgB,cAAc,IAAI,MAAM,GAAG,IAAI,CAc9C;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAoCjF"}
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
*/
|
|
44
44
|
import { execFileSync } from 'node:child_process';
|
|
45
45
|
import { randomBytes } from 'node:crypto';
|
|
46
|
-
import { closeSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, writeSync, } from 'node:fs';
|
|
46
|
+
import { closeSync, fsyncSync, linkSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, writeFileSync, writeSync, } from 'node:fs';
|
|
47
47
|
import { homedir, platform, tmpdir } from 'node:os';
|
|
48
48
|
import { dirname, join } from 'node:path';
|
|
49
49
|
const FILE_MODE = 0o600;
|
|
@@ -110,6 +110,29 @@ export function readStoredSubscriptionCredential(home = homedir()) {
|
|
|
110
110
|
export function writeStoredSubscriptionCredential(cred, home = homedir()) {
|
|
111
111
|
const path = credentialsPath(home);
|
|
112
112
|
mkdirSync(dirname(path), { recursive: true, mode: DIR_MODE });
|
|
113
|
+
return withCredentialStoreLock(path, () => writeStoredSubscriptionCredentialUnlocked(cred, path));
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Replace exactly the credential a refresh was derived from.
|
|
117
|
+
*
|
|
118
|
+
* Comparison and rename happen under the same store-owned cross-process lock.
|
|
119
|
+
* A changed record is returned to the caller and is never overwritten. This is
|
|
120
|
+
* the durable authority boundary a post-network plain reread cannot provide:
|
|
121
|
+
* without the lock, another writer can still rotate the credential between
|
|
122
|
+
* the comparison and the rename.
|
|
123
|
+
*/
|
|
124
|
+
export function replaceStoredSubscriptionCredential(expected, replacement, home = homedir()) {
|
|
125
|
+
const path = credentialsPath(home);
|
|
126
|
+
mkdirSync(dirname(path), { recursive: true, mode: DIR_MODE });
|
|
127
|
+
return withCredentialStoreLock(path, () => {
|
|
128
|
+
const current = readStoredSubscriptionCredential(home);
|
|
129
|
+
if (!sameCredential(current, expected))
|
|
130
|
+
return { replaced: false, current };
|
|
131
|
+
writeStoredSubscriptionCredentialUnlocked(replacement, path);
|
|
132
|
+
return { replaced: true, current: replacement };
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function writeStoredSubscriptionCredentialUnlocked(cred, path) {
|
|
113
136
|
const tmp = `${path}.tmp.${process.pid}.${randomBytes(6).toString('hex')}`;
|
|
114
137
|
const body = `${JSON.stringify({
|
|
115
138
|
version: CREDENTIALS_FILE_VERSION,
|
|
@@ -152,7 +175,96 @@ export function writeStoredSubscriptionCredential(cred, home = homedir()) {
|
|
|
152
175
|
}
|
|
153
176
|
/** Remove the stored credential. Absence is success. */
|
|
154
177
|
export function clearStoredSubscriptionCredential(home = homedir()) {
|
|
155
|
-
|
|
178
|
+
const path = credentialsPath(home);
|
|
179
|
+
mkdirSync(dirname(path), { recursive: true, mode: DIR_MODE });
|
|
180
|
+
withCredentialStoreLock(path, () => rmSync(path, { force: true }));
|
|
181
|
+
}
|
|
182
|
+
function sameCredential(left, right) {
|
|
183
|
+
if (!left)
|
|
184
|
+
return false;
|
|
185
|
+
if (left.accessToken !== right.accessToken ||
|
|
186
|
+
left.refreshToken !== right.refreshToken ||
|
|
187
|
+
left.expiresAt !== right.expiresAt) {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
const leftScopes = left.scopes ?? [];
|
|
191
|
+
const rightScopes = right.scopes ?? [];
|
|
192
|
+
return (leftScopes.length === rightScopes.length &&
|
|
193
|
+
leftScopes.every((scope, index) => scope === rightScopes[index]));
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Run one synchronous store mutation with cross-process exclusion.
|
|
197
|
+
*
|
|
198
|
+
* The lock is held only across local read/rename work, never across a network
|
|
199
|
+
* request. A dead owner can leave a complete lock behind. It is deliberately
|
|
200
|
+
* not stolen automatically: pathname-based stale reclamation cannot prove it
|
|
201
|
+
* is unlinking the inode it inspected, so a delayed reclaimer can delete a new
|
|
202
|
+
* owner's lock and admit two writers. A present lock is a refusal until an
|
|
203
|
+
* operator proves no process owns the store and removes it.
|
|
204
|
+
*/
|
|
205
|
+
function withCredentialStoreLock(path, operation) {
|
|
206
|
+
const lockPath = `${path}.lock`;
|
|
207
|
+
const token = `${process.pid}:${Date.now()}:${randomBytes(12).toString('hex')}`;
|
|
208
|
+
const published = publishLockAtomically(lockPath, token);
|
|
209
|
+
if (!published.acquired) {
|
|
210
|
+
throw new CredentialStoreError(`could not acquire the credential-store lock for ${path}: another owner or an unrecovered process lock is present (${published.error instanceof Error ? published.error.message : String(published.error)}). Refusing concurrent mutation; after proving no Namzu process is using this credential store, remove ${lockPath} and retry.`);
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
return operation();
|
|
214
|
+
}
|
|
215
|
+
finally {
|
|
216
|
+
// Do not remove a successor's lock if an external actor replaced the file.
|
|
217
|
+
try {
|
|
218
|
+
if (readFileSync(lockPath, 'utf8') === token)
|
|
219
|
+
rmSync(lockPath, { force: true });
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
// The mutation already has its result. A missing/replaced lock is not
|
|
223
|
+
// evidence that the credential itself failed to publish.
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Publish a complete owner record at the canonical name in one filesystem op.
|
|
229
|
+
*
|
|
230
|
+
* Creating the canonical file and then writing its token has a fatal crash
|
|
231
|
+
* window: an empty lock names no owner and can never be reclaimed safely. The
|
|
232
|
+
* candidate is completed and synced first; `linkSync` is the exclusive claim.
|
|
233
|
+
* A pre-link crash can leave candidate debris, but it never blocks the store.
|
|
234
|
+
*/
|
|
235
|
+
function publishLockAtomically(lockPath, token) {
|
|
236
|
+
const candidatePath = `${lockPath}.candidate.${process.pid}.${randomBytes(12).toString('hex')}`;
|
|
237
|
+
let fd;
|
|
238
|
+
try {
|
|
239
|
+
fd = openSync(candidatePath, 'wx', FILE_MODE);
|
|
240
|
+
writeFileSync(fd, token, 'utf8');
|
|
241
|
+
fsyncSync(fd);
|
|
242
|
+
closeSync(fd);
|
|
243
|
+
fd = undefined;
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
if (fd !== undefined)
|
|
247
|
+
closeSync(fd);
|
|
248
|
+
rmSync(candidatePath, { force: true });
|
|
249
|
+
throw new CredentialStoreError(`could not prepare the credential-store lock: ${error instanceof Error ? error.message : String(error)}`);
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
linkSync(candidatePath, lockPath);
|
|
253
|
+
return { acquired: true };
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
return { acquired: false, error };
|
|
257
|
+
}
|
|
258
|
+
finally {
|
|
259
|
+
try {
|
|
260
|
+
rmSync(candidatePath, { force: true });
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
// Candidate debris is non-canonical and cannot block another owner.
|
|
264
|
+
// Once the hard link succeeds, cleanup must not erase that acquisition
|
|
265
|
+
// result and skip the token-checked canonical release path.
|
|
266
|
+
}
|
|
267
|
+
}
|
|
156
268
|
}
|
|
157
269
|
/**
|
|
158
270
|
* Make `path` readable and writable by its owner and by nobody else, and
|