@caupulican/pi-adaptative 0.86.14 → 0.90.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/CHANGELOG.md +49 -0
- package/README.md +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +14 -15
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +14 -16
- package/dist/bundled-resources/skills/worker-profile-writer/SKILL.md +4 -4
- package/dist/core/agent-session.d.ts +23 -33
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +76 -109
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/contracts.d.ts +1 -1
- package/dist/core/autonomy/contracts.js.map +1 -1
- package/dist/core/autonomy/gates.d.ts.map +1 -1
- package/dist/core/autonomy/gates.js +16 -0
- package/dist/core/autonomy/gates.js.map +1 -1
- package/dist/core/autonomy/subagent-prompt.d.ts +2 -1
- package/dist/core/autonomy/subagent-prompt.d.ts.map +1 -1
- package/dist/core/autonomy/subagent-prompt.js +2 -18
- package/dist/core/autonomy/subagent-prompt.js.map +1 -1
- package/dist/core/background-tool-task-controller.js +5 -5
- package/dist/core/background-tool-task-controller.js.map +1 -1
- package/dist/core/compaction-controller.d.ts +22 -2
- package/dist/core/compaction-controller.d.ts.map +1 -1
- package/dist/core/compaction-controller.js +75 -39
- package/dist/core/compaction-controller.js.map +1 -1
- package/dist/core/context/brain-curator.d.ts +2 -3
- package/dist/core/context/brain-curator.d.ts.map +1 -1
- package/dist/core/context/brain-curator.js +3 -20
- package/dist/core/context/brain-curator.js.map +1 -1
- package/dist/core/context/context-composition.d.ts +2 -1
- package/dist/core/context/context-composition.d.ts.map +1 -1
- package/dist/core/context/context-composition.js +6 -1
- package/dist/core/context/context-composition.js.map +1 -1
- package/dist/core/context/memory-prompt-block.js +1 -1
- package/dist/core/context/memory-prompt-block.js.map +1 -1
- package/dist/core/context/tool-output-packer.js +1 -1
- package/dist/core/context/tool-output-packer.js.map +1 -1
- package/dist/core/context-gc.js +10 -10
- package/dist/core/context-gc.js.map +1 -1
- package/dist/core/context-pipeline.d.ts +4 -4
- package/dist/core/context-pipeline.js +4 -4
- package/dist/core/context-pipeline.js.map +1 -1
- package/dist/core/default-tool-surface.d.ts.map +1 -1
- package/dist/core/default-tool-surface.js +1 -2
- package/dist/core/default-tool-surface.js.map +1 -1
- package/dist/core/delegation/session-worker-claim.d.ts +2 -2
- package/dist/core/delegation/session-worker-claim.js +2 -2
- package/dist/core/delegation/session-worker-claim.js.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.js +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-resource-materializer.js +3 -3
- package/dist/core/delegation/worker-resource-materializer.js.map +1 -1
- package/dist/core/delegation/worker-runner.d.ts +2 -13
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +5 -67
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/extensions/builtin.js +4 -4
- package/dist/core/extensions/builtin.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +6 -2
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +21 -9
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +12 -3
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/foreground-terminal-handoff-controller.js +2 -2
- package/dist/core/foreground-terminal-handoff-controller.js.map +1 -1
- package/dist/core/goals/compact-goal-context.d.ts.map +1 -1
- package/dist/core/goals/compact-goal-context.js +13 -9
- package/dist/core/goals/compact-goal-context.js.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.js +1 -1
- package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
- package/dist/core/human-input-controller.js +1 -1
- package/dist/core/human-input-controller.js.map +1 -1
- package/dist/core/improvement-loop.js +13 -13
- package/dist/core/improvement-loop.js.map +1 -1
- package/dist/core/learning/reflection-engine.d.ts +2 -1
- package/dist/core/learning/reflection-engine.d.ts.map +1 -1
- package/dist/core/learning/reflection-engine.js +4 -24
- package/dist/core/learning/reflection-engine.js.map +1 -1
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js +1 -1
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/model-router/route-judge.d.ts +2 -1
- package/dist/core/model-router/route-judge.d.ts.map +1 -1
- package/dist/core/model-router/route-judge.js +4 -12
- package/dist/core/model-router/route-judge.js.map +1 -1
- package/dist/core/models/perf-profile.d.ts +1 -1
- package/dist/core/models/perf-profile.d.ts.map +1 -1
- package/dist/core/models/perf-profile.js +2 -8
- package/dist/core/models/perf-profile.js.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.d.ts +1 -1
- package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.js +1 -6
- package/dist/core/orchestration/lane-tool-manifests.js.map +1 -1
- package/dist/core/process-matrix/resume-launcher.js +3 -3
- package/dist/core/process-matrix/resume-launcher.js.map +1 -1
- package/dist/core/process-matrix/runtime.d.ts +2 -0
- package/dist/core/process-matrix/runtime.d.ts.map +1 -1
- package/dist/core/process-matrix/runtime.js +23 -19
- package/dist/core/process-matrix/runtime.js.map +1 -1
- package/dist/core/provider-prompt-contracts.d.ts +34 -0
- package/dist/core/provider-prompt-contracts.d.ts.map +1 -0
- package/dist/core/provider-prompt-contracts.js +133 -0
- package/dist/core/provider-prompt-contracts.js.map +1 -0
- package/dist/core/provider-request-context-controller.d.ts +40 -0
- package/dist/core/provider-request-context-controller.d.ts.map +1 -0
- package/dist/core/provider-request-context-controller.js +68 -0
- package/dist/core/provider-request-context-controller.js.map +1 -0
- package/dist/core/provider-request-runtime-controller.d.ts +22 -0
- package/dist/core/provider-request-runtime-controller.d.ts.map +1 -0
- package/dist/core/provider-request-runtime-controller.js +87 -0
- package/dist/core/provider-request-runtime-controller.js.map +1 -0
- package/dist/core/provider-tool-text.d.ts +7 -0
- package/dist/core/provider-tool-text.d.ts.map +1 -0
- package/dist/core/provider-tool-text.js +42 -0
- package/dist/core/provider-tool-text.js.map +1 -0
- package/dist/core/research/model-fitness.d.ts +2 -5
- package/dist/core/research/model-fitness.d.ts.map +1 -1
- package/dist/core/research/model-fitness.js +2 -20
- package/dist/core/research/model-fitness.js.map +1 -1
- package/dist/core/research/research-runner.d.ts +2 -1
- package/dist/core/research/research-runner.d.ts.map +1 -1
- package/dist/core/research/research-runner.js +6 -21
- package/dist/core/research/research-runner.js.map +1 -1
- package/dist/core/risk-classifier.d.ts.map +1 -1
- package/dist/core/risk-classifier.js +9 -1
- package/dist/core/risk-classifier.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +3 -0
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +20 -25
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/scout-controller.d.ts +2 -1
- package/dist/core/scout-controller.d.ts.map +1 -1
- package/dist/core/scout-controller.js +2 -16
- package/dist/core/scout-controller.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.js +6 -6
- package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
- package/dist/core/secrets/credential-manager.d.ts +11 -1
- package/dist/core/secrets/credential-manager.d.ts.map +1 -1
- package/dist/core/secrets/credential-manager.js +28 -7
- package/dist/core/secrets/credential-manager.js.map +1 -1
- package/dist/core/secrets/credential-migration-source.d.ts +20 -0
- package/dist/core/secrets/credential-migration-source.d.ts.map +1 -0
- package/dist/core/secrets/credential-migration-source.js +113 -0
- package/dist/core/secrets/credential-migration-source.js.map +1 -0
- package/dist/core/secrets/credential-session-connection.d.ts +9 -0
- package/dist/core/secrets/credential-session-connection.d.ts.map +1 -0
- package/dist/core/secrets/credential-session-connection.js +39 -0
- package/dist/core/secrets/credential-session-connection.js.map +1 -0
- package/dist/core/security/untrusted-boundary.d.ts +2 -2
- package/dist/core/security/untrusted-boundary.d.ts.map +1 -1
- package/dist/core/security/untrusted-boundary.js +3 -10
- package/dist/core/security/untrusted-boundary.js.map +1 -1
- package/dist/core/session-role.d.ts.map +1 -1
- package/dist/core/session-role.js +1 -2
- package/dist/core/session-role.js.map +1 -1
- package/dist/core/skill-vault.d.ts +98 -0
- package/dist/core/skill-vault.d.ts.map +1 -0
- package/dist/core/skill-vault.js +270 -0
- package/dist/core/skill-vault.js.map +1 -0
- package/dist/core/skills.d.ts +10 -9
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +42 -50
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt-builder.d.ts +1 -1
- package/dist/core/system-prompt-builder.d.ts.map +1 -1
- package/dist/core/system-prompt-builder.js +20 -60
- package/dist/core/system-prompt-builder.js.map +1 -1
- package/dist/core/system-prompt.d.ts +4 -4
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +87 -121
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tasks/task-state.d.ts.map +1 -1
- package/dist/core/tasks/task-state.js +6 -7
- package/dist/core/tasks/task-state.js.map +1 -1
- package/dist/core/tool-capability-policy.d.ts.map +1 -1
- package/dist/core/tool-capability-policy.js +2 -1
- package/dist/core/tool-capability-policy.js.map +1 -1
- package/dist/core/tool-protocol-controller.d.ts.map +1 -1
- package/dist/core/tool-protocol-controller.js +4 -7
- package/dist/core/tool-protocol-controller.js.map +1 -1
- package/dist/core/tool-selection/promotion.d.ts.map +1 -1
- package/dist/core/tool-selection/promotion.js +2 -6
- package/dist/core/tool-selection/promotion.js.map +1 -1
- package/dist/core/toolkit/reflex-interpreter.d.ts +2 -1
- package/dist/core/toolkit/reflex-interpreter.d.ts.map +1 -1
- package/dist/core/toolkit/reflex-interpreter.js +2 -14
- package/dist/core/toolkit/reflex-interpreter.js.map +1 -1
- package/dist/core/tools/ask-question.js +6 -6
- package/dist/core/tools/ask-question.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +8 -7
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/delegate-status.d.ts +17 -13
- package/dist/core/tools/delegate-status.d.ts.map +1 -1
- package/dist/core/tools/delegate-status.js +111 -226
- package/dist/core/tools/delegate-status.js.map +1 -1
- package/dist/core/tools/delegate.d.ts +29 -2
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +149 -48
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/edit.d.ts +4 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +34 -3
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/extensionify-runtime.js +4 -4
- package/dist/core/tools/extensionify-runtime.js.map +1 -1
- package/dist/core/tools/file-failure-recovery.d.ts +17 -0
- package/dist/core/tools/file-failure-recovery.d.ts.map +1 -0
- package/dist/core/tools/file-failure-recovery.js +43 -0
- package/dist/core/tools/file-failure-recovery.js.map +1 -0
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +2 -4
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/goal.js +3 -3
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/tools/grep.js +2 -2
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +2 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +2 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts +3 -0
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +14 -0
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/model-fitness.js +4 -4
- package/dist/core/tools/model-fitness.js.map +1 -1
- package/dist/core/tools/profile-writer.d.ts +30 -16
- package/dist/core/tools/profile-writer.d.ts.map +1 -1
- package/dist/core/tools/profile-writer.js +98 -59
- package/dist/core/tools/profile-writer.js.map +1 -1
- package/dist/core/tools/python.js +6 -6
- package/dist/core/tools/python.js.map +1 -1
- package/dist/core/tools/read.d.ts +3 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +17 -0
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/run-process.js +4 -4
- package/dist/core/tools/run-process.js.map +1 -1
- package/dist/core/tools/run-toolkit-script.js +4 -4
- package/dist/core/tools/run-toolkit-script.js.map +1 -1
- package/dist/core/tools/secret-store.d.ts +32 -3
- package/dist/core/tools/secret-store.d.ts.map +1 -1
- package/dist/core/tools/secret-store.js +141 -34
- package/dist/core/tools/secret-store.js.map +1 -1
- package/dist/core/tools/skill.d.ts +29 -0
- package/dist/core/tools/skill.d.ts.map +1 -0
- package/dist/core/tools/skill.js +79 -0
- package/dist/core/tools/skill.js.map +1 -0
- package/dist/core/tools/task-steps.js +4 -4
- package/dist/core/tools/task-steps.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +4 -0
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/core/tools/worktree-sync.js +6 -6
- package/dist/core/tools/worktree-sync.js.map +1 -1
- package/dist/core/tools/write.d.ts +4 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +39 -3
- package/dist/core/tools/write.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/interactive-event-controller.js +1 -1
- package/dist/modes/interactive/interactive-event-controller.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/report-commands.js +1 -1
- package/dist/modes/interactive/report-commands.js.map +1 -1
- package/dist/modes/interactive/secret-menu-controller.d.ts.map +1 -1
- package/dist/modes/interactive/secret-menu-controller.js +2 -18
- package/dist/modes/interactive/secret-menu-controller.js.map +1 -1
- package/dist/modes/interactive/session-flow-commands.js +1 -1
- package/dist/modes/interactive/session-flow-commands.js.map +1 -1
- package/docs/compaction.md +45 -25
- package/docs/extensions.md +23 -7
- package/docs/settings.md +3 -3
- package/docs/skills.md +14 -10
- package/docs/task-steps.md +2 -2
- package/docs/tmux-agent-manager.md +1 -1
- package/docs/tool-repair.md +18 -1
- package/docs/usage.md +4 -2
- package/docs/worker-profiles.md +3 -3
- package/docs/worktree-sync.md +2 -2
- package/examples/extensions/custom-compaction.ts +5 -17
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/summarize.ts +3 -5
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/04-skills.ts +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
- package/dist/core/util/json-size.d.ts +0 -3
- package/dist/core/util/json-size.d.ts.map +0 -1
- package/dist/core/util/json-size.js +0 -95
- package/dist/core/util/json-size.js.map +0 -1
|
@@ -1,22 +1,66 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
import { defineTool } from "../extensions/types.js";
|
|
3
3
|
import { CredentialManagerError, CredentialStorageError, } from "../secrets/credential-manager.js";
|
|
4
|
+
import { CredentialMigrationSourceError, resolveCredentialMigrationSources, } from "../secrets/credential-migration-source.js";
|
|
5
|
+
import { connectCredentialSessionWithMaskedPrompt, isCredentialSessionKeyRequired, } from "../secrets/credential-session-connection.js";
|
|
6
|
+
import { SECRET_VARIABLE_NAME_MAX_CHARS, SECRET_VARIABLE_NAME_PATTERN } from "../secrets/secret-dotenv.js";
|
|
4
7
|
import { emptyOrchestrationCall, OrchestrationPanelComponent, } from "./orchestration-panel.js";
|
|
8
|
+
const migrationSourceSchema = Type.Union([
|
|
9
|
+
Type.Object({
|
|
10
|
+
kind: Type.Literal("environment"),
|
|
11
|
+
name: Type.String({ maxLength: SECRET_VARIABLE_NAME_MAX_CHARS, pattern: SECRET_VARIABLE_NAME_PATTERN }),
|
|
12
|
+
}, { additionalProperties: false }),
|
|
13
|
+
Type.Object({ kind: Type.Literal("dotenv_file"), path: Type.String({ minLength: 1, maxLength: 4096 }) }, { additionalProperties: false }),
|
|
14
|
+
Type.Object({
|
|
15
|
+
kind: Type.Literal("file"),
|
|
16
|
+
path: Type.String({ minLength: 1, maxLength: 4096 }),
|
|
17
|
+
variable: Type.String({ maxLength: SECRET_VARIABLE_NAME_MAX_CHARS, pattern: SECRET_VARIABLE_NAME_PATTERN }),
|
|
18
|
+
}, { additionalProperties: false }),
|
|
19
|
+
]);
|
|
5
20
|
const secretStoreSchema = Type.Object({
|
|
6
|
-
action: Type.Union([Type.Literal("status"), Type.Literal("list"), Type.Literal("activate")], {
|
|
7
|
-
description: "
|
|
21
|
+
action: Type.Union([Type.Literal("status"), Type.Literal("list"), Type.Literal("activate"), Type.Literal("migrate")], {
|
|
22
|
+
description: "Inspect, activate, or migrate model-blind credential sources.",
|
|
8
23
|
}),
|
|
9
24
|
profile: Type.Optional(Type.String({
|
|
10
25
|
minLength: 1,
|
|
11
26
|
maxLength: 96,
|
|
12
27
|
pattern: "^[A-Za-z0-9][A-Za-z0-9._-]*$",
|
|
13
|
-
description: "
|
|
28
|
+
description: "Profile to activate or create during migration.",
|
|
29
|
+
})),
|
|
30
|
+
description: Type.Optional(Type.String({ minLength: 1, maxLength: 256 })),
|
|
31
|
+
overwrite: Type.Optional(Type.Boolean({ description: "Explicitly replace an existing profile while preserving project bindings." })),
|
|
32
|
+
sources: Type.Optional(Type.Array(migrationSourceSchema, {
|
|
33
|
+
minItems: 1,
|
|
34
|
+
maxItems: 64,
|
|
35
|
+
description: "Host-side credential sources. Values are never accepted in tool arguments.",
|
|
14
36
|
})),
|
|
15
37
|
}, { additionalProperties: false });
|
|
16
38
|
function result(details, text) {
|
|
17
39
|
return { content: [{ type: "text", text }], details };
|
|
18
40
|
}
|
|
41
|
+
function ownerSetupRequired(action) {
|
|
42
|
+
const message = "Bitwarden needs one owner input: a BW_SESSION key supplied through Pi's masked prompt or process environment, never through chat.";
|
|
43
|
+
return result({
|
|
44
|
+
action,
|
|
45
|
+
status: "unavailable",
|
|
46
|
+
...(action === "status" ? { connected: false } : {}),
|
|
47
|
+
code: "owner_setup_required",
|
|
48
|
+
message,
|
|
49
|
+
}, message);
|
|
50
|
+
}
|
|
51
|
+
function cancelled(action) {
|
|
52
|
+
return result({ action, status: "cancelled", code: "cancelled" }, "Credential action cancelled.");
|
|
53
|
+
}
|
|
19
54
|
function invalid(input) {
|
|
55
|
+
if (input.action === "migrate") {
|
|
56
|
+
if (!input.profile || !input.sources) {
|
|
57
|
+
return result({ action: input.action, status: "error", code: "missing_migration_input" }, "Credential migration requires a profile and at least one source.");
|
|
58
|
+
}
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
if (input.description !== undefined || input.sources !== undefined || input.overwrite !== undefined) {
|
|
62
|
+
return result({ action: input.action, status: "error", code: "unexpected_migration_input" }, `Action ${input.action} does not accept migration inputs.`);
|
|
63
|
+
}
|
|
20
64
|
if (input.action !== "activate" && input.profile !== undefined) {
|
|
21
65
|
return result({
|
|
22
66
|
action: input.action,
|
|
@@ -28,9 +72,21 @@ function invalid(input) {
|
|
|
28
72
|
return undefined;
|
|
29
73
|
}
|
|
30
74
|
function failed(input, error) {
|
|
31
|
-
const known = error instanceof CredentialManagerError ||
|
|
75
|
+
const known = error instanceof CredentialManagerError ||
|
|
76
|
+
error instanceof CredentialStorageError ||
|
|
77
|
+
error instanceof CredentialMigrationSourceError;
|
|
32
78
|
const code = known ? error.code : "safe_failure";
|
|
33
|
-
const
|
|
79
|
+
const migrationMessages = {
|
|
80
|
+
duplicate_variable: "Credential migration defines the same variable more than once.",
|
|
81
|
+
invalid_source: "Credential migration source data is invalid.",
|
|
82
|
+
source_not_found: "A requested credential source is unavailable.",
|
|
83
|
+
source_unavailable: "A requested credential source could not be read.",
|
|
84
|
+
};
|
|
85
|
+
const message = error instanceof CredentialMigrationSourceError
|
|
86
|
+
? (migrationMessages[error.code] ?? "Credential migration failed safely without exposing values.")
|
|
87
|
+
: known
|
|
88
|
+
? error.message
|
|
89
|
+
: "Credential action failed safely without exposing values.";
|
|
34
90
|
const status = ["owner_setup_required", "not_connected", "provider_unavailable"].includes(code)
|
|
35
91
|
? "unavailable"
|
|
36
92
|
: "error";
|
|
@@ -45,7 +101,7 @@ function failed(input, error) {
|
|
|
45
101
|
function panelModel(details, expanded) {
|
|
46
102
|
if (!details)
|
|
47
103
|
return { label: "secrets", status: "error", emptyText: "No credential result was retained." };
|
|
48
|
-
const success = ["activated", "available", "listed"].includes(details.status);
|
|
104
|
+
const success = ["activated", "available", "listed", "migrated"].includes(details.status);
|
|
49
105
|
return {
|
|
50
106
|
label: "secrets",
|
|
51
107
|
action: details.status,
|
|
@@ -74,17 +130,22 @@ function panelModel(details, expanded) {
|
|
|
74
130
|
}
|
|
75
131
|
export function createSecretStoreToolDefinition(options) {
|
|
76
132
|
const { manager } = options;
|
|
133
|
+
const resolveSources = options.resolveMigrationSources ?? resolveCredentialMigrationSources;
|
|
77
134
|
return defineTool({
|
|
78
135
|
name: "secret_store",
|
|
79
136
|
label: "Secret Store",
|
|
80
|
-
description: "Discover and activate
|
|
81
|
-
promptSnippet: "
|
|
137
|
+
description: "Discover, migrate, and activate Bitwarden credential profiles for the current project without exposing values.",
|
|
138
|
+
promptSnippet: "Migrate accessible credentials into Bitwarden, activate project credentials; never expose values.",
|
|
82
139
|
promptGuidelines: [
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
140
|
+
"Active user-plane host gate authorizes model-blind migration; never ask duplicate confirmation.",
|
|
141
|
+
"Credentials needed: call secret_store. If disconnected, TUI asks for one masked BW_SESSION only; never request chat/setup work.",
|
|
142
|
+
"activate before credential work; TUI/print/RPC return metadata only.",
|
|
143
|
+
"One project binding: omit profile. Multiple: use list, select authorized profile.",
|
|
144
|
+
"Never request credentials in chat/tool arguments.",
|
|
145
|
+
"After activation, run consumer normally; never print/inspect/grep/echo credential environment values.",
|
|
146
|
+
"migrate accepts environment names, dotenv paths, key-file paths; never credential values.",
|
|
147
|
+
"Migration keeps sources. overwrite only for intentional Bitwarden profile replacement.",
|
|
148
|
+
"owner_setup_required without UI: report only BW_SESSION missing, supplied out of band to Pi; never request more/retry.",
|
|
88
149
|
],
|
|
89
150
|
parameters: secretStoreSchema,
|
|
90
151
|
executionMode: "sequential",
|
|
@@ -104,7 +165,7 @@ export function createSecretStoreToolDefinition(options) {
|
|
|
104
165
|
},
|
|
105
166
|
async execute(_toolCallId, input, signal, _onUpdate, ctx) {
|
|
106
167
|
if (signal?.aborted) {
|
|
107
|
-
return
|
|
168
|
+
return cancelled(input.action);
|
|
108
169
|
}
|
|
109
170
|
const validation = invalid(input);
|
|
110
171
|
if (validation)
|
|
@@ -112,31 +173,77 @@ export function createSecretStoreToolDefinition(options) {
|
|
|
112
173
|
try {
|
|
113
174
|
if (input.action === "status") {
|
|
114
175
|
const status = manager.status;
|
|
115
|
-
if (!status.sessionAvailable)
|
|
116
|
-
return
|
|
117
|
-
action: input.action,
|
|
118
|
-
status: "unavailable",
|
|
119
|
-
connected: false,
|
|
120
|
-
code: "owner_setup_required",
|
|
121
|
-
message: "The owner must connect Bitwarden with /secrets.",
|
|
122
|
-
}, "Bitwarden owner setup is required. Run /secrets in a TUI session.");
|
|
123
|
-
}
|
|
176
|
+
if (!status.sessionAvailable)
|
|
177
|
+
return ownerSetupRequired(input.action);
|
|
124
178
|
return result({ action: input.action, status: "available", connected: status.connected }, status.connected
|
|
125
179
|
? "Bitwarden is connected for this Pi session."
|
|
126
180
|
: "A Bitwarden session key is available and will be validated on activation.");
|
|
127
181
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
182
|
+
const executeCredentialAction = async () => {
|
|
183
|
+
if (input.action === "list") {
|
|
184
|
+
const profiles = await manager.listForProject(ctx.cwd, signal);
|
|
185
|
+
return result({ action: input.action, status: "listed", profiles }, `Found ${profiles.length} credential profile${profiles.length === 1 ? "" : "s"}; only metadata was returned.`);
|
|
186
|
+
}
|
|
187
|
+
if (input.action === "migrate") {
|
|
188
|
+
const { profile, sources } = input;
|
|
189
|
+
if (!profile || !sources) {
|
|
190
|
+
return result({ action: input.action, status: "error", code: "missing_migration_input" }, "Credential migration requires a profile and at least one source.");
|
|
191
|
+
}
|
|
192
|
+
await manager.prepareForMigration(ctx.cwd, { profile, replaceExisting: input.overwrite === true }, signal);
|
|
193
|
+
let variables = await resolveSources(sources, ctx.cwd, signal);
|
|
194
|
+
try {
|
|
195
|
+
const migrated = await manager.storeVariablesForProject(ctx.cwd, {
|
|
196
|
+
profile,
|
|
197
|
+
...(input.description ? { description: input.description } : {}),
|
|
198
|
+
variables,
|
|
199
|
+
replaceExisting: input.overwrite === true,
|
|
200
|
+
}, signal);
|
|
201
|
+
return result({
|
|
202
|
+
action: input.action,
|
|
203
|
+
status: "migrated",
|
|
204
|
+
profile: migrated.profile,
|
|
205
|
+
variableNames: migrated.variableNames,
|
|
206
|
+
project: migrated.project,
|
|
207
|
+
sourceRetained: true,
|
|
208
|
+
}, `Migrated and activated ${migrated.profile} for ${migrated.project}. Source material was retained.`);
|
|
209
|
+
}
|
|
210
|
+
finally {
|
|
211
|
+
for (const variable of variables)
|
|
212
|
+
variable.value = "";
|
|
213
|
+
variables = [];
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const activated = await manager.activateForProject(ctx.cwd, input.profile, signal);
|
|
217
|
+
return result({
|
|
218
|
+
action: input.action,
|
|
219
|
+
status: "activated",
|
|
220
|
+
profile: activated.profile,
|
|
221
|
+
variableNames: activated.variableNames,
|
|
222
|
+
project: activated.project,
|
|
223
|
+
}, `Activated ${activated.profile} for ${activated.project}. Credential values remain hidden.`);
|
|
224
|
+
};
|
|
225
|
+
const connectWithOwnerKey = async () => {
|
|
226
|
+
if (!ctx.hasUI)
|
|
227
|
+
return ownerSetupRequired(input.action);
|
|
228
|
+
const connection = await connectCredentialSessionWithMaskedPrompt(manager, ctx.ui, signal);
|
|
229
|
+
return connection === "connected" ? undefined : cancelled(input.action);
|
|
230
|
+
};
|
|
231
|
+
if (!manager.status.sessionAvailable) {
|
|
232
|
+
const setup = await connectWithOwnerKey();
|
|
233
|
+
if (setup)
|
|
234
|
+
return setup;
|
|
235
|
+
}
|
|
236
|
+
try {
|
|
237
|
+
return await executeCredentialAction();
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
if (!isCredentialSessionKeyRequired(error))
|
|
241
|
+
throw error;
|
|
242
|
+
const setup = await connectWithOwnerKey();
|
|
243
|
+
if (setup)
|
|
244
|
+
return setup;
|
|
245
|
+
return await executeCredentialAction();
|
|
131
246
|
}
|
|
132
|
-
const activated = await manager.activateForProject(ctx.cwd, input.profile, signal);
|
|
133
|
-
return result({
|
|
134
|
-
action: input.action,
|
|
135
|
-
status: "activated",
|
|
136
|
-
profile: activated.profile,
|
|
137
|
-
variableNames: activated.variableNames,
|
|
138
|
-
project: activated.project,
|
|
139
|
-
}, `Activated ${activated.profile} for ${activated.project}. Credential values remain hidden.`);
|
|
140
247
|
}
|
|
141
248
|
catch (error) {
|
|
142
249
|
return failed(input, error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-store.js","sourceRoot":"","sources":["../../../src/core/tools/secret-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { defineTool } from \"../extensions/types.ts\";\nimport {\n\ttype CredentialManager,\n\tCredentialManagerError,\n\ttype CredentialProfileSummary,\n\tCredentialStorageError,\n} from \"../secrets/credential-manager.ts\";\nimport {\n\temptyOrchestrationCall,\n\tOrchestrationPanelComponent,\n\ttype OrchestrationPanelModel,\n} from \"./orchestration-panel.ts\";\n\nconst secretStoreSchema = Type.Object(\n\t{\n\t\taction: Type.Union([Type.Literal(\"status\"), Type.Literal(\"list\"), Type.Literal(\"activate\")], {\n\t\t\tdescription: \"Credential-use action. Credential mutation is owner-only through /secrets.\",\n\t\t}),\n\t\tprofile: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tminLength: 1,\n\t\t\t\tmaxLength: 96,\n\t\t\t\tpattern: \"^[A-Za-z0-9][A-Za-z0-9._-]*$\",\n\t\t\t\tdescription: \"Bound profile to activate. Omit when the project has exactly one bound profile.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type SecretStoreToolInput = Static<typeof secretStoreSchema>;\n\nexport type SecretStoreStatus = \"activated\" | \"available\" | \"cancelled\" | \"error\" | \"listed\" | \"unavailable\";\n\nexport interface SecretStoreToolDetails {\n\taction: SecretStoreToolInput[\"action\"];\n\tstatus: SecretStoreStatus;\n\tprofile?: string;\n\tvariableNames?: string[];\n\tprofiles?: CredentialProfileSummary[];\n\tproject?: string;\n\tconnected?: boolean;\n\tcode?: string;\n\tmessage?: string;\n}\n\nexport interface SecretStoreToolOptions {\n\tmanager: CredentialManager;\n}\n\ntype SecretStoreResult = {\n\tcontent: Array<{ type: \"text\"; text: string }>;\n\tdetails: SecretStoreToolDetails;\n};\n\nfunction result(details: SecretStoreToolDetails, text: string): SecretStoreResult {\n\treturn { content: [{ type: \"text\", text }], details };\n}\n\nfunction invalid(input: SecretStoreToolInput): SecretStoreResult | undefined {\n\tif (input.action !== \"activate\" && input.profile !== undefined) {\n\t\treturn result(\n\t\t\t{\n\t\t\t\taction: input.action,\n\t\t\t\tstatus: \"error\",\n\t\t\t\tcode: \"unexpected_profile\",\n\t\t\t\tmessage: `Action ${input.action} does not accept a profile.`,\n\t\t\t},\n\t\t\t`Secret store request is invalid: action ${input.action} does not accept a profile.`,\n\t\t);\n\t}\n\treturn undefined;\n}\n\nfunction failed(input: SecretStoreToolInput, error: unknown): SecretStoreResult {\n\tconst known = error instanceof CredentialManagerError || error instanceof CredentialStorageError;\n\tconst code = known ? error.code : \"safe_failure\";\n\tconst message = known ? error.message : \"Credential activation failed safely without exposing values.\";\n\tconst status: SecretStoreStatus = [\"owner_setup_required\", \"not_connected\", \"provider_unavailable\"].includes(code)\n\t\t? \"unavailable\"\n\t\t: \"error\";\n\treturn result(\n\t\t{\n\t\t\taction: input.action,\n\t\t\tstatus,\n\t\t\t...(input.profile ? { profile: input.profile } : {}),\n\t\t\tcode,\n\t\t\tmessage,\n\t\t},\n\t\t`Credential action failed: ${message}`,\n\t);\n}\n\nfunction panelModel(details: SecretStoreToolDetails | undefined, expanded: boolean): OrchestrationPanelModel {\n\tif (!details) return { label: \"secrets\", status: \"error\", emptyText: \"No credential result was retained.\" };\n\tconst success = [\"activated\", \"available\", \"listed\"].includes(details.status);\n\treturn {\n\t\tlabel: \"secrets\",\n\t\taction: details.status,\n\t\tstatus: success ? \"success\" : details.status === \"cancelled\" ? \"warning\" : \"error\",\n\t\tsummary: [\n\t\t\tdetails.profile,\n\t\t\tdetails.project,\n\t\t\tdetails.variableNames\n\t\t\t\t? `${details.variableNames.length} variable${details.variableNames.length === 1 ? \"\" : \"s\"}`\n\t\t\t\t: undefined,\n\t\t\tdetails.profiles ? `${details.profiles.length} profile${details.profiles.length === 1 ? \"\" : \"s\"}` : undefined,\n\t\t].filter((value): value is string => value !== undefined),\n\t\trows: expanded\n\t\t\t? details.profiles?.map((profile) => ({\n\t\t\t\t\tstatus: profile.boundToCurrentProject ? (\"succeeded\" as const) : (\"info\" as const),\n\t\t\t\t\tlabel: profile.profile,\n\t\t\t\t\tmeta: [\n\t\t\t\t\t\t`${profile.variableNames.length} variable${profile.variableNames.length === 1 ? \"\" : \"s\"}`,\n\t\t\t\t\t\tprofile.boundToCurrentProject ? \"bound here\" : \"not bound here\",\n\t\t\t\t\t],\n\t\t\t\t\tdetails: profile.description ? [profile.description] : undefined,\n\t\t\t\t}))\n\t\t\t: undefined,\n\t\tnotices:\n\t\t\texpanded && details.message ? [{ status: success ? \"info\" : \"error\", text: details.message }] : undefined,\n\t};\n}\n\nexport function createSecretStoreToolDefinition(options: SecretStoreToolOptions) {\n\tconst { manager } = options;\n\treturn defineTool<typeof secretStoreSchema, SecretStoreToolDetails>({\n\t\tname: \"secret_store\",\n\t\tlabel: \"Secret Store\",\n\t\tdescription:\n\t\t\t\"Discover and activate owner-authorized Bitwarden credential profiles for the current project without exposing values.\",\n\t\tpromptSnippet:\n\t\t\t\"Activate project credentials with secret_store before credential-dependent commands. Credential setup and mutation are owner-only through /secrets.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use secret_store activate before credential-dependent work. It works in TUI, print, and RPC modes and returns metadata only.\",\n\t\t\t\"Omit profile when the project has one binding. Use list to select among multiple authorized profiles.\",\n\t\t\t\"Never ask the owner to paste a credential into chat or pass a value through tool arguments.\",\n\t\t\t\"After activation, run the consuming command normally. Never print, inspect, grep, or echo credential environment values.\",\n\t\t\t\"If owner_setup_required is returned, tell the owner to run /secrets in a TUI session. Do not repeatedly retry.\",\n\t\t],\n\t\tparameters: secretStoreSchema,\n\t\texecutionMode: \"sequential\",\n\t\trenderShell: \"self\",\n\t\trenderCall() {\n\t\t\treturn emptyOrchestrationCall();\n\t\t},\n\t\trenderResult(toolResult, { expanded, isPartial }, theme: Theme) {\n\t\t\tif (isPartial) {\n\t\t\t\treturn new OrchestrationPanelComponent(theme, {\n\t\t\t\t\tlabel: \"secrets\",\n\t\t\t\t\taction: \"activating\",\n\t\t\t\t\tstatus: \"running\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn new OrchestrationPanelComponent(theme, panelModel(toolResult.details, expanded), expanded);\n\t\t},\n\t\tasync execute(_toolCallId, input, signal, _onUpdate, ctx) {\n\t\t\tif (signal?.aborted) {\n\t\t\t\treturn result(\n\t\t\t\t\t{ action: input.action, status: \"cancelled\", code: \"cancelled\" },\n\t\t\t\t\t\"Credential action cancelled.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst validation = invalid(input);\n\t\t\tif (validation) return validation;\n\t\t\ttry {\n\t\t\t\tif (input.action === \"status\") {\n\t\t\t\t\tconst status = manager.status;\n\t\t\t\t\tif (!status.sessionAvailable) {\n\t\t\t\t\t\treturn result(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\taction: input.action,\n\t\t\t\t\t\t\t\tstatus: \"unavailable\",\n\t\t\t\t\t\t\t\tconnected: false,\n\t\t\t\t\t\t\t\tcode: \"owner_setup_required\",\n\t\t\t\t\t\t\t\tmessage: \"The owner must connect Bitwarden with /secrets.\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"Bitwarden owner setup is required. Run /secrets in a TUI session.\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn result(\n\t\t\t\t\t\t{ action: input.action, status: \"available\", connected: status.connected },\n\t\t\t\t\t\tstatus.connected\n\t\t\t\t\t\t\t? \"Bitwarden is connected for this Pi session.\"\n\t\t\t\t\t\t\t: \"A Bitwarden session key is available and will be validated on activation.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (input.action === \"list\") {\n\t\t\t\t\tconst profiles = await manager.listForProject(ctx.cwd, signal);\n\t\t\t\t\treturn result(\n\t\t\t\t\t\t{ action: input.action, status: \"listed\", profiles },\n\t\t\t\t\t\t`Found ${profiles.length} credential profile${profiles.length === 1 ? \"\" : \"s\"}; only metadata was returned.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst activated = await manager.activateForProject(ctx.cwd, input.profile, signal);\n\t\t\t\treturn result(\n\t\t\t\t\t{\n\t\t\t\t\t\taction: input.action,\n\t\t\t\t\t\tstatus: \"activated\",\n\t\t\t\t\t\tprofile: activated.profile,\n\t\t\t\t\t\tvariableNames: activated.variableNames,\n\t\t\t\t\t\tproject: activated.project,\n\t\t\t\t\t},\n\t\t\t\t\t`Activated ${activated.profile} for ${activated.project}. Credential values remain hidden.`,\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\treturn failed(input, error);\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"secret-store.js","sourceRoot":"","sources":["../../../src/core/tools/secret-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { defineTool } from \"../extensions/types.ts\";\nimport {\n\ttype CredentialManager,\n\tCredentialManagerError,\n\ttype CredentialProfileSummary,\n\tCredentialStorageError,\n} from \"../secrets/credential-manager.ts\";\nimport {\n\tCredentialMigrationSourceError,\n\ttype CredentialMigrationSourceResolver,\n\tresolveCredentialMigrationSources,\n} from \"../secrets/credential-migration-source.ts\";\nimport {\n\tconnectCredentialSessionWithMaskedPrompt,\n\tisCredentialSessionKeyRequired,\n} from \"../secrets/credential-session-connection.ts\";\nimport { SECRET_VARIABLE_NAME_MAX_CHARS, SECRET_VARIABLE_NAME_PATTERN } from \"../secrets/secret-dotenv.ts\";\nimport {\n\temptyOrchestrationCall,\n\tOrchestrationPanelComponent,\n\ttype OrchestrationPanelModel,\n} from \"./orchestration-panel.ts\";\n\nconst migrationSourceSchema = Type.Union([\n\tType.Object(\n\t\t{\n\t\t\tkind: Type.Literal(\"environment\"),\n\t\t\tname: Type.String({ maxLength: SECRET_VARIABLE_NAME_MAX_CHARS, pattern: SECRET_VARIABLE_NAME_PATTERN }),\n\t\t},\n\t\t{ additionalProperties: false },\n\t),\n\tType.Object(\n\t\t{ kind: Type.Literal(\"dotenv_file\"), path: Type.String({ minLength: 1, maxLength: 4096 }) },\n\t\t{ additionalProperties: false },\n\t),\n\tType.Object(\n\t\t{\n\t\t\tkind: Type.Literal(\"file\"),\n\t\t\tpath: Type.String({ minLength: 1, maxLength: 4096 }),\n\t\t\tvariable: Type.String({ maxLength: SECRET_VARIABLE_NAME_MAX_CHARS, pattern: SECRET_VARIABLE_NAME_PATTERN }),\n\t\t},\n\t\t{ additionalProperties: false },\n\t),\n]);\n\nconst secretStoreSchema = Type.Object(\n\t{\n\t\taction: Type.Union(\n\t\t\t[Type.Literal(\"status\"), Type.Literal(\"list\"), Type.Literal(\"activate\"), Type.Literal(\"migrate\")],\n\t\t\t{\n\t\t\t\tdescription: \"Inspect, activate, or migrate model-blind credential sources.\",\n\t\t\t},\n\t\t),\n\t\tprofile: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tminLength: 1,\n\t\t\t\tmaxLength: 96,\n\t\t\t\tpattern: \"^[A-Za-z0-9][A-Za-z0-9._-]*$\",\n\t\t\t\tdescription: \"Profile to activate or create during migration.\",\n\t\t\t}),\n\t\t),\n\t\tdescription: Type.Optional(Type.String({ minLength: 1, maxLength: 256 })),\n\t\toverwrite: Type.Optional(\n\t\t\tType.Boolean({ description: \"Explicitly replace an existing profile while preserving project bindings.\" }),\n\t\t),\n\t\tsources: Type.Optional(\n\t\t\tType.Array(migrationSourceSchema, {\n\t\t\t\tminItems: 1,\n\t\t\t\tmaxItems: 64,\n\t\t\t\tdescription: \"Host-side credential sources. Values are never accepted in tool arguments.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type SecretStoreToolInput = Static<typeof secretStoreSchema>;\n\nexport type SecretStoreStatus =\n\t| \"activated\"\n\t| \"available\"\n\t| \"cancelled\"\n\t| \"error\"\n\t| \"listed\"\n\t| \"migrated\"\n\t| \"unavailable\";\n\nexport interface SecretStoreToolDetails {\n\taction: SecretStoreToolInput[\"action\"];\n\tstatus: SecretStoreStatus;\n\tprofile?: string;\n\tvariableNames?: string[];\n\tprofiles?: CredentialProfileSummary[];\n\tproject?: string;\n\tconnected?: boolean;\n\tcode?: string;\n\tmessage?: string;\n\tsourceRetained?: boolean;\n}\n\nexport interface SecretStoreToolOptions {\n\tmanager: CredentialManager;\n\tresolveMigrationSources?: CredentialMigrationSourceResolver;\n}\n\ntype SecretStoreResult = {\n\tcontent: Array<{ type: \"text\"; text: string }>;\n\tdetails: SecretStoreToolDetails;\n};\n\nfunction result(details: SecretStoreToolDetails, text: string): SecretStoreResult {\n\treturn { content: [{ type: \"text\", text }], details };\n}\n\nfunction ownerSetupRequired(action: SecretStoreToolInput[\"action\"]): SecretStoreResult {\n\tconst message =\n\t\t\"Bitwarden needs one owner input: a BW_SESSION key supplied through Pi's masked prompt or process environment, never through chat.\";\n\treturn result(\n\t\t{\n\t\t\taction,\n\t\t\tstatus: \"unavailable\",\n\t\t\t...(action === \"status\" ? { connected: false } : {}),\n\t\t\tcode: \"owner_setup_required\",\n\t\t\tmessage,\n\t\t},\n\t\tmessage,\n\t);\n}\n\nfunction cancelled(action: SecretStoreToolInput[\"action\"]): SecretStoreResult {\n\treturn result({ action, status: \"cancelled\", code: \"cancelled\" }, \"Credential action cancelled.\");\n}\n\nfunction invalid(input: SecretStoreToolInput): SecretStoreResult | undefined {\n\tif (input.action === \"migrate\") {\n\t\tif (!input.profile || !input.sources) {\n\t\t\treturn result(\n\t\t\t\t{ action: input.action, status: \"error\", code: \"missing_migration_input\" },\n\t\t\t\t\"Credential migration requires a profile and at least one source.\",\n\t\t\t);\n\t\t}\n\t\treturn undefined;\n\t}\n\tif (input.description !== undefined || input.sources !== undefined || input.overwrite !== undefined) {\n\t\treturn result(\n\t\t\t{ action: input.action, status: \"error\", code: \"unexpected_migration_input\" },\n\t\t\t`Action ${input.action} does not accept migration inputs.`,\n\t\t);\n\t}\n\tif (input.action !== \"activate\" && input.profile !== undefined) {\n\t\treturn result(\n\t\t\t{\n\t\t\t\taction: input.action,\n\t\t\t\tstatus: \"error\",\n\t\t\t\tcode: \"unexpected_profile\",\n\t\t\t\tmessage: `Action ${input.action} does not accept a profile.`,\n\t\t\t},\n\t\t\t`Secret store request is invalid: action ${input.action} does not accept a profile.`,\n\t\t);\n\t}\n\treturn undefined;\n}\n\nfunction failed(input: SecretStoreToolInput, error: unknown): SecretStoreResult {\n\tconst known =\n\t\terror instanceof CredentialManagerError ||\n\t\terror instanceof CredentialStorageError ||\n\t\terror instanceof CredentialMigrationSourceError;\n\tconst code = known ? error.code : \"safe_failure\";\n\tconst migrationMessages: Record<string, string> = {\n\t\tduplicate_variable: \"Credential migration defines the same variable more than once.\",\n\t\tinvalid_source: \"Credential migration source data is invalid.\",\n\t\tsource_not_found: \"A requested credential source is unavailable.\",\n\t\tsource_unavailable: \"A requested credential source could not be read.\",\n\t};\n\tconst message =\n\t\terror instanceof CredentialMigrationSourceError\n\t\t\t? (migrationMessages[error.code] ?? \"Credential migration failed safely without exposing values.\")\n\t\t\t: known\n\t\t\t\t? error.message\n\t\t\t\t: \"Credential action failed safely without exposing values.\";\n\tconst status: SecretStoreStatus = [\"owner_setup_required\", \"not_connected\", \"provider_unavailable\"].includes(code)\n\t\t? \"unavailable\"\n\t\t: \"error\";\n\treturn result(\n\t\t{\n\t\t\taction: input.action,\n\t\t\tstatus,\n\t\t\t...(input.profile ? { profile: input.profile } : {}),\n\t\t\tcode,\n\t\t\tmessage,\n\t\t},\n\t\t`Credential action failed: ${message}`,\n\t);\n}\n\nfunction panelModel(details: SecretStoreToolDetails | undefined, expanded: boolean): OrchestrationPanelModel {\n\tif (!details) return { label: \"secrets\", status: \"error\", emptyText: \"No credential result was retained.\" };\n\tconst success = [\"activated\", \"available\", \"listed\", \"migrated\"].includes(details.status);\n\treturn {\n\t\tlabel: \"secrets\",\n\t\taction: details.status,\n\t\tstatus: success ? \"success\" : details.status === \"cancelled\" ? \"warning\" : \"error\",\n\t\tsummary: [\n\t\t\tdetails.profile,\n\t\t\tdetails.project,\n\t\t\tdetails.variableNames\n\t\t\t\t? `${details.variableNames.length} variable${details.variableNames.length === 1 ? \"\" : \"s\"}`\n\t\t\t\t: undefined,\n\t\t\tdetails.profiles ? `${details.profiles.length} profile${details.profiles.length === 1 ? \"\" : \"s\"}` : undefined,\n\t\t].filter((value): value is string => value !== undefined),\n\t\trows: expanded\n\t\t\t? details.profiles?.map((profile) => ({\n\t\t\t\t\tstatus: profile.boundToCurrentProject ? (\"succeeded\" as const) : (\"info\" as const),\n\t\t\t\t\tlabel: profile.profile,\n\t\t\t\t\tmeta: [\n\t\t\t\t\t\t`${profile.variableNames.length} variable${profile.variableNames.length === 1 ? \"\" : \"s\"}`,\n\t\t\t\t\t\tprofile.boundToCurrentProject ? \"bound here\" : \"not bound here\",\n\t\t\t\t\t],\n\t\t\t\t\tdetails: profile.description ? [profile.description] : undefined,\n\t\t\t\t}))\n\t\t\t: undefined,\n\t\tnotices:\n\t\t\texpanded && details.message ? [{ status: success ? \"info\" : \"error\", text: details.message }] : undefined,\n\t};\n}\n\nexport function createSecretStoreToolDefinition(options: SecretStoreToolOptions) {\n\tconst { manager } = options;\n\tconst resolveSources = options.resolveMigrationSources ?? resolveCredentialMigrationSources;\n\treturn defineTool<typeof secretStoreSchema, SecretStoreToolDetails>({\n\t\tname: \"secret_store\",\n\t\tlabel: \"Secret Store\",\n\t\tdescription:\n\t\t\t\"Discover, migrate, and activate Bitwarden credential profiles for the current project without exposing values.\",\n\t\tpromptSnippet:\n\t\t\t\"Migrate accessible credentials into Bitwarden, activate project credentials; never expose values.\",\n\t\tpromptGuidelines: [\n\t\t\t\"Active user-plane host gate authorizes model-blind migration; never ask duplicate confirmation.\",\n\t\t\t\"Credentials needed: call secret_store. If disconnected, TUI asks for one masked BW_SESSION only; never request chat/setup work.\",\n\t\t\t\"activate before credential work; TUI/print/RPC return metadata only.\",\n\t\t\t\"One project binding: omit profile. Multiple: use list, select authorized profile.\",\n\t\t\t\"Never request credentials in chat/tool arguments.\",\n\t\t\t\"After activation, run consumer normally; never print/inspect/grep/echo credential environment values.\",\n\t\t\t\"migrate accepts environment names, dotenv paths, key-file paths; never credential values.\",\n\t\t\t\"Migration keeps sources. overwrite only for intentional Bitwarden profile replacement.\",\n\t\t\t\"owner_setup_required without UI: report only BW_SESSION missing, supplied out of band to Pi; never request more/retry.\",\n\t\t],\n\t\tparameters: secretStoreSchema,\n\t\texecutionMode: \"sequential\",\n\t\trenderShell: \"self\",\n\t\trenderCall() {\n\t\t\treturn emptyOrchestrationCall();\n\t\t},\n\t\trenderResult(toolResult, { expanded, isPartial }, theme: Theme) {\n\t\t\tif (isPartial) {\n\t\t\t\treturn new OrchestrationPanelComponent(theme, {\n\t\t\t\t\tlabel: \"secrets\",\n\t\t\t\t\taction: \"activating\",\n\t\t\t\t\tstatus: \"running\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn new OrchestrationPanelComponent(theme, panelModel(toolResult.details, expanded), expanded);\n\t\t},\n\t\tasync execute(_toolCallId, input, signal, _onUpdate, ctx) {\n\t\t\tif (signal?.aborted) {\n\t\t\t\treturn cancelled(input.action);\n\t\t\t}\n\t\t\tconst validation = invalid(input);\n\t\t\tif (validation) return validation;\n\t\t\ttry {\n\t\t\t\tif (input.action === \"status\") {\n\t\t\t\t\tconst status = manager.status;\n\t\t\t\t\tif (!status.sessionAvailable) return ownerSetupRequired(input.action);\n\t\t\t\t\treturn result(\n\t\t\t\t\t\t{ action: input.action, status: \"available\", connected: status.connected },\n\t\t\t\t\t\tstatus.connected\n\t\t\t\t\t\t\t? \"Bitwarden is connected for this Pi session.\"\n\t\t\t\t\t\t\t: \"A Bitwarden session key is available and will be validated on activation.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst executeCredentialAction = async (): Promise<SecretStoreResult> => {\n\t\t\t\t\tif (input.action === \"list\") {\n\t\t\t\t\t\tconst profiles = await manager.listForProject(ctx.cwd, signal);\n\t\t\t\t\t\treturn result(\n\t\t\t\t\t\t\t{ action: input.action, status: \"listed\", profiles },\n\t\t\t\t\t\t\t`Found ${profiles.length} credential profile${profiles.length === 1 ? \"\" : \"s\"}; only metadata was returned.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tif (input.action === \"migrate\") {\n\t\t\t\t\t\tconst { profile, sources } = input;\n\t\t\t\t\t\tif (!profile || !sources) {\n\t\t\t\t\t\t\treturn result(\n\t\t\t\t\t\t\t\t{ action: input.action, status: \"error\", code: \"missing_migration_input\" },\n\t\t\t\t\t\t\t\t\"Credential migration requires a profile and at least one source.\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait manager.prepareForMigration(\n\t\t\t\t\t\t\tctx.cwd,\n\t\t\t\t\t\t\t{ profile, replaceExisting: input.overwrite === true },\n\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tlet variables = await resolveSources(sources, ctx.cwd, signal);\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst migrated = await manager.storeVariablesForProject(\n\t\t\t\t\t\t\t\tctx.cwd,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tprofile,\n\t\t\t\t\t\t\t\t\t...(input.description ? { description: input.description } : {}),\n\t\t\t\t\t\t\t\t\tvariables,\n\t\t\t\t\t\t\t\t\treplaceExisting: input.overwrite === true,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn result(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\taction: input.action,\n\t\t\t\t\t\t\t\t\tstatus: \"migrated\",\n\t\t\t\t\t\t\t\t\tprofile: migrated.profile,\n\t\t\t\t\t\t\t\t\tvariableNames: migrated.variableNames,\n\t\t\t\t\t\t\t\t\tproject: migrated.project,\n\t\t\t\t\t\t\t\t\tsourceRetained: true,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t`Migrated and activated ${migrated.profile} for ${migrated.project}. Source material was retained.`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tfor (const variable of variables) variable.value = \"\";\n\t\t\t\t\t\t\tvariables = [];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tconst activated = await manager.activateForProject(ctx.cwd, input.profile, signal);\n\t\t\t\t\treturn result(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taction: input.action,\n\t\t\t\t\t\t\tstatus: \"activated\",\n\t\t\t\t\t\t\tprofile: activated.profile,\n\t\t\t\t\t\t\tvariableNames: activated.variableNames,\n\t\t\t\t\t\t\tproject: activated.project,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t`Activated ${activated.profile} for ${activated.project}. Credential values remain hidden.`,\n\t\t\t\t\t);\n\t\t\t\t};\n\n\t\t\t\tconst connectWithOwnerKey = async (): Promise<SecretStoreResult | undefined> => {\n\t\t\t\t\tif (!ctx.hasUI) return ownerSetupRequired(input.action);\n\t\t\t\t\tconst connection = await connectCredentialSessionWithMaskedPrompt(manager, ctx.ui, signal);\n\t\t\t\t\treturn connection === \"connected\" ? undefined : cancelled(input.action);\n\t\t\t\t};\n\n\t\t\t\tif (!manager.status.sessionAvailable) {\n\t\t\t\t\tconst setup = await connectWithOwnerKey();\n\t\t\t\t\tif (setup) return setup;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\treturn await executeCredentialAction();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isCredentialSessionKeyRequired(error)) throw error;\n\t\t\t\t\tconst setup = await connectWithOwnerKey();\n\t\t\t\t\tif (setup) return setup;\n\t\t\t\t\treturn await executeCredentialAction();\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\treturn failed(input, error);\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type Static, Type } from "typebox";
|
|
2
|
+
import type { ToolDefinition } from "../extensions/types.ts";
|
|
3
|
+
import type { SkillLoadResult, SkillSearchResult, SkillVaultController, SkillVaultStatus } from "../skill-vault.ts";
|
|
4
|
+
declare const skillSchema: Type.TObject<{
|
|
5
|
+
action: Type.TUnion<[Type.TLiteral<"search">, Type.TLiteral<"load">, Type.TLiteral<"unload">, Type.TLiteral<"status">]>;
|
|
6
|
+
query: Type.TOptional<Type.TString>;
|
|
7
|
+
name: Type.TOptional<Type.TString>;
|
|
8
|
+
}>;
|
|
9
|
+
export type SkillToolInput = Static<typeof skillSchema>;
|
|
10
|
+
export type SkillToolDetails = {
|
|
11
|
+
action: "search";
|
|
12
|
+
result: SkillSearchResult;
|
|
13
|
+
} | {
|
|
14
|
+
action: "load";
|
|
15
|
+
result: SkillLoadResult;
|
|
16
|
+
} | {
|
|
17
|
+
action: "unload";
|
|
18
|
+
result: {
|
|
19
|
+
ok: true;
|
|
20
|
+
unloaded?: string;
|
|
21
|
+
};
|
|
22
|
+
} | {
|
|
23
|
+
action: "status";
|
|
24
|
+
result: SkillVaultStatus;
|
|
25
|
+
};
|
|
26
|
+
/** One compact agent surface over the host-owned skill lifecycle. */
|
|
27
|
+
export declare function createSkillVaultToolDefinition(vault: SkillVaultController): ToolDefinition<typeof skillSchema>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=skill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../../src/core/tools/skill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEpH,QAAA,MAAM,WAAW;;;;EAUhB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AACxD,MAAM,MAAM,gBAAgB,GACzB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,iBAAiB,CAAA;CAAE,GAC/C;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,GAC3C;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAC7D;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAalD,qEAAqE;AACrE,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,oBAAoB,GAAG,cAAc,CAAC,OAAO,WAAW,CAAC,CA2D9G"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
const skillSchema = Type.Object({
|
|
3
|
+
action: Type.Union([Type.Literal("search"), Type.Literal("load"), Type.Literal("unload"), Type.Literal("status")], { description: "search | load | unload | status" }),
|
|
4
|
+
query: Type.Optional(Type.String({ description: "search query" })),
|
|
5
|
+
name: Type.Optional(Type.String({ description: "exact load name" })),
|
|
6
|
+
}, { additionalProperties: false });
|
|
7
|
+
function searchText(result) {
|
|
8
|
+
if (result.candidates.length === 0)
|
|
9
|
+
return "skill search: no match";
|
|
10
|
+
return result.candidates.map((candidate) => `${candidate.name}: ${candidate.description}`).join("\n");
|
|
11
|
+
}
|
|
12
|
+
function statusText(result) {
|
|
13
|
+
if (result.state === "unloaded")
|
|
14
|
+
return `skill state: unloaded${result.reason ? `, ${result.reason}` : ""}`;
|
|
15
|
+
if (result.state === "loaded_pending")
|
|
16
|
+
return `skill state: loaded_pending, ${result.name}, applies next request`;
|
|
17
|
+
return `skill state: active, ${result.name}, idle ${Math.round(result.idleForMs ?? 0)}ms, expires ${Math.round(result.expiresInMs ?? 0)}ms`;
|
|
18
|
+
}
|
|
19
|
+
/** One compact agent surface over the host-owned skill lifecycle. */
|
|
20
|
+
export function createSkillVaultToolDefinition(vault) {
|
|
21
|
+
return {
|
|
22
|
+
name: "skill",
|
|
23
|
+
label: "skill",
|
|
24
|
+
description: "Skill vault. Specialist guidance useful: search, load exact name before work. Host injects body transiently, expires idle; unload optional.",
|
|
25
|
+
promptSnippet: "Search/load skill.",
|
|
26
|
+
parameters: skillSchema,
|
|
27
|
+
async execute(_toolCallId, input) {
|
|
28
|
+
switch (input.action) {
|
|
29
|
+
case "search": {
|
|
30
|
+
if (!input.query?.trim()) {
|
|
31
|
+
const result = { candidates: [] };
|
|
32
|
+
return {
|
|
33
|
+
content: [{ type: "text", text: "skill search requires query" }],
|
|
34
|
+
details: { action: "search", result },
|
|
35
|
+
isError: true,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const result = vault.search(input.query);
|
|
39
|
+
return {
|
|
40
|
+
content: [{ type: "text", text: searchText(result) }],
|
|
41
|
+
details: { action: "search", result },
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
case "load": {
|
|
45
|
+
const result = input.name?.trim()
|
|
46
|
+
? vault.load(input.name.trim(), "model")
|
|
47
|
+
: { ok: false, reason: "not_found", message: "skill load requires exact name" };
|
|
48
|
+
return {
|
|
49
|
+
content: [
|
|
50
|
+
{
|
|
51
|
+
type: "text",
|
|
52
|
+
text: result.ok
|
|
53
|
+
? `skill loaded: ${result.name}, applies next request`
|
|
54
|
+
: `skill load failed: ${result.message}`,
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
details: { action: "load", result },
|
|
58
|
+
isError: !result.ok,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
case "unload": {
|
|
62
|
+
const result = vault.unload();
|
|
63
|
+
return {
|
|
64
|
+
content: [{ type: "text", text: `skill unloaded: ${result.unloaded ?? "none"}` }],
|
|
65
|
+
details: { action: "unload", result },
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
case "status": {
|
|
69
|
+
const result = vault.status();
|
|
70
|
+
return {
|
|
71
|
+
content: [{ type: "text", text: statusText(result) }],
|
|
72
|
+
details: { action: "status", result },
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.js","sourceRoot":"","sources":["../../../src/core/tools/skill.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport type { SkillLoadResult, SkillSearchResult, SkillVaultController, SkillVaultStatus } from \"../skill-vault.ts\";\n\nconst skillSchema = Type.Object(\n\t{\n\t\taction: Type.Union(\n\t\t\t[Type.Literal(\"search\"), Type.Literal(\"load\"), Type.Literal(\"unload\"), Type.Literal(\"status\")],\n\t\t\t{ description: \"search | load | unload | status\" },\n\t\t),\n\t\tquery: Type.Optional(Type.String({ description: \"search query\" })),\n\t\tname: Type.Optional(Type.String({ description: \"exact load name\" })),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type SkillToolInput = Static<typeof skillSchema>;\nexport type SkillToolDetails =\n\t| { action: \"search\"; result: SkillSearchResult }\n\t| { action: \"load\"; result: SkillLoadResult }\n\t| { action: \"unload\"; result: { ok: true; unloaded?: string } }\n\t| { action: \"status\"; result: SkillVaultStatus };\n\nfunction searchText(result: SkillSearchResult): string {\n\tif (result.candidates.length === 0) return \"skill search: no match\";\n\treturn result.candidates.map((candidate) => `${candidate.name}: ${candidate.description}`).join(\"\\n\");\n}\n\nfunction statusText(result: SkillVaultStatus): string {\n\tif (result.state === \"unloaded\") return `skill state: unloaded${result.reason ? `, ${result.reason}` : \"\"}`;\n\tif (result.state === \"loaded_pending\") return `skill state: loaded_pending, ${result.name}, applies next request`;\n\treturn `skill state: active, ${result.name}, idle ${Math.round(result.idleForMs ?? 0)}ms, expires ${Math.round(result.expiresInMs ?? 0)}ms`;\n}\n\n/** One compact agent surface over the host-owned skill lifecycle. */\nexport function createSkillVaultToolDefinition(vault: SkillVaultController): ToolDefinition<typeof skillSchema> {\n\treturn {\n\t\tname: \"skill\",\n\t\tlabel: \"skill\",\n\t\tdescription:\n\t\t\t\"Skill vault. Specialist guidance useful: search, load exact name before work. Host injects body transiently, expires idle; unload optional.\",\n\t\tpromptSnippet: \"Search/load skill.\",\n\t\tparameters: skillSchema,\n\t\tasync execute(_toolCallId, input) {\n\t\t\tswitch (input.action) {\n\t\t\t\tcase \"search\": {\n\t\t\t\t\tif (!input.query?.trim()) {\n\t\t\t\t\t\tconst result: SkillSearchResult = { candidates: [] };\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: \"skill search requires query\" }],\n\t\t\t\t\t\t\tdetails: { action: \"search\" as const, result },\n\t\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tconst result = vault.search(input.query);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: searchText(result) }],\n\t\t\t\t\t\tdetails: { action: \"search\" as const, result },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcase \"load\": {\n\t\t\t\t\tconst result: SkillLoadResult = input.name?.trim()\n\t\t\t\t\t\t? vault.load(input.name.trim(), \"model\")\n\t\t\t\t\t\t: { ok: false, reason: \"not_found\", message: \"skill load requires exact name\" };\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\t\t\ttext: result.ok\n\t\t\t\t\t\t\t\t\t? `skill loaded: ${result.name}, applies next request`\n\t\t\t\t\t\t\t\t\t: `skill load failed: ${result.message}`,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdetails: { action: \"load\" as const, result },\n\t\t\t\t\t\tisError: !result.ok,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcase \"unload\": {\n\t\t\t\t\tconst result = vault.unload();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: `skill unloaded: ${result.unloaded ?? \"none\"}` }],\n\t\t\t\t\t\tdetails: { action: \"unload\" as const, result },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcase \"status\": {\n\t\t\t\t\tconst result = vault.status();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: statusText(result) }],\n\t\t\t\t\t\tdetails: { action: \"status\" as const, result },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
|
|
@@ -175,10 +175,10 @@ export function createTaskStepsToolDefinition(deps) {
|
|
|
175
175
|
description: "Track the session's ordered multi-step checklist with status, notes, and evidence. Use goal for durable outcomes and delegate for workers.",
|
|
176
176
|
promptSnippet: "Track multi-step session work.",
|
|
177
177
|
promptGuidelines: [
|
|
178
|
-
"Use for complex
|
|
179
|
-
"Batch
|
|
180
|
-
"
|
|
181
|
-
"Before final
|
|
178
|
+
"Use for complex/explicitly tracked work, not one-step work. Keep one in_progress step.",
|
|
179
|
+
"Batch transitions. Address first open step; record evidence/blocker. Never call only to narrate unchanged state.",
|
|
180
|
+
"intake preserves every supplied item; link steps to active goal requirementIds.",
|
|
181
|
+
"Before final: clear stale in_progress, discuss/defer remainder. Goal owns outcomes; delegate owns workers.",
|
|
182
182
|
],
|
|
183
183
|
parameters: taskStepsSchema,
|
|
184
184
|
renderShell: "self",
|