@pellux/goodvibes-agent 0.1.117 → 1.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/CHANGELOG.md +13 -4
- package/README.md +35 -14
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +176073 -170980
- package/docs/README.md +11 -5
- package/docs/channels-remote-and-api.md +50 -0
- package/docs/connected-host.md +3 -3
- package/docs/getting-started.md +29 -15
- package/docs/knowledge-artifacts-and-multimodal.md +91 -0
- package/docs/project-planning.md +79 -0
- package/docs/providers-and-routing.md +46 -0
- package/docs/release-and-publishing.md +44 -9
- package/docs/tools-and-commands.md +123 -0
- package/docs/voice-and-live-tts.md +51 -0
- package/package.json +2 -5
- package/src/agent/channel-delivery.ts +201 -0
- package/src/agent/media-generation.ts +159 -0
- package/src/agent/memory-prompt.ts +0 -1
- package/src/agent/note-registry.ts +329 -0
- package/src/agent/operator-actions.ts +343 -0
- package/src/agent/persona-registry.ts +15 -14
- package/src/agent/record-labels.ts +107 -0
- package/src/agent/reminder-schedule-format.ts +33 -24
- package/src/agent/reminder-schedule.ts +26 -25
- package/src/agent/routine-registry.ts +13 -12
- package/src/agent/routine-schedule-args.ts +2 -1
- package/src/agent/routine-schedule-format.ts +77 -53
- package/src/agent/routine-schedule-promotion.ts +34 -32
- package/src/agent/routine-schedule-receipts.ts +28 -26
- package/src/agent/runtime-profile-starters.ts +2 -2
- package/src/agent/runtime-profile.ts +18 -17
- package/src/agent/skill-registry.ts +25 -24
- package/src/cli/agent-knowledge-args.ts +5 -1
- package/src/cli/agent-knowledge-command.ts +39 -33
- package/src/cli/agent-knowledge-format.ts +80 -67
- package/src/cli/agent-knowledge-methods.ts +1 -1
- package/src/cli/agent-knowledge-runtime.ts +32 -26
- package/src/cli/bundle-command.ts +13 -8
- package/src/cli/config-overrides.ts +37 -36
- package/src/cli/external-runtime.ts +10 -4
- package/src/cli/help.ts +29 -11
- package/src/cli/local-library-command.ts +134 -68
- package/src/cli/management-commands.ts +98 -62
- package/src/cli/management.ts +52 -26
- package/src/cli/memory-command.ts +66 -32
- package/src/cli/parser.ts +37 -24
- package/src/cli/profiles-command.ts +52 -35
- package/src/cli/provider-auth-routes.ts +2 -1
- package/src/cli/routines-command.ts +44 -36
- package/src/cli/service-posture.ts +6 -6
- package/src/cli/status.ts +46 -121
- package/src/core/conversation-message-snapshot.ts +131 -0
- package/src/input/agent-workspace-activation.ts +33 -7
- package/src/input/agent-workspace-basic-command-editor-submission.ts +7 -3
- package/src/input/agent-workspace-basic-command-editors.ts +30 -10
- package/src/input/agent-workspace-categories.ts +276 -64
- package/src/input/agent-workspace-channel-command-editor-submission.ts +34 -0
- package/src/input/agent-workspace-channel-command-editors.ts +23 -5
- package/src/input/agent-workspace-channels.ts +35 -2
- package/src/input/agent-workspace-command-editor.ts +18 -2
- package/src/input/agent-workspace-config-reader.ts +16 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +1 -1
- package/src/input/agent-workspace-editors.ts +140 -2
- package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
- package/src/input/agent-workspace-learned-behavior.ts +2 -2
- package/src/input/agent-workspace-library-command-editor-submission.ts +1 -1
- package/src/input/agent-workspace-library-command-editors.ts +2 -2
- package/src/input/agent-workspace-local-operations.ts +218 -0
- package/src/input/agent-workspace-local-selection.ts +75 -0
- package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
- package/src/input/agent-workspace-media-command-editors.ts +27 -0
- package/src/input/agent-workspace-memory-command-editors.ts +1 -1
- package/src/input/agent-workspace-memory-editor.ts +2 -2
- package/src/input/agent-workspace-navigation.ts +38 -2
- package/src/input/agent-workspace-notify-editor-submission.ts +16 -2
- package/src/input/agent-workspace-operations-command-editor-submission.ts +63 -1
- package/src/input/agent-workspace-operations-command-editors.ts +80 -3
- package/src/input/agent-workspace-panel-route.ts +43 -0
- package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
- package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
- package/src/input/agent-workspace-search.ts +169 -0
- package/src/input/agent-workspace-setup.ts +22 -11
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +6 -6
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +10 -10
- package/src/input/agent-workspace-snapshot.ts +112 -13
- package/src/input/agent-workspace-task-command-editors.ts +4 -4
- package/src/input/agent-workspace-token.ts +18 -2
- package/src/input/agent-workspace-types.ts +92 -4
- package/src/input/agent-workspace-voice-media.ts +3 -6
- package/src/input/agent-workspace-web-research-editor.ts +104 -0
- package/src/input/agent-workspace.ts +136 -208
- package/src/input/command-registry.ts +4 -1
- package/src/input/commands/agent-runtime-profile-runtime.ts +45 -41
- package/src/input/commands/agent-skills-runtime.ts +83 -70
- package/src/input/commands/agent-workspace-runtime.ts +23 -7
- package/src/input/commands/brief-runtime.ts +25 -24
- package/src/input/commands/channels-runtime.ts +145 -31
- package/src/input/commands/delegation-runtime.ts +29 -23
- package/src/input/commands/experience-runtime.ts +6 -4
- package/src/input/commands/guidance-runtime.ts +4 -4
- package/src/input/commands/health-runtime.ts +140 -115
- package/src/input/commands/knowledge.ts +57 -56
- package/src/input/commands/local-provider-runtime.ts +36 -18
- package/src/input/commands/local-runtime.ts +138 -16
- package/src/input/commands/local-setup-review.ts +7 -7
- package/src/input/commands/mcp-runtime.ts +56 -35
- package/src/input/commands/notify-runtime.ts +38 -9
- package/src/input/commands/operator-actions-runtime.ts +138 -0
- package/src/input/commands/operator-runtime.ts +6 -17
- package/src/input/commands/personas-runtime.ts +45 -30
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +29 -29
- package/src/input/commands/provider-accounts-runtime.ts +60 -39
- package/src/input/commands/qrcode-runtime.ts +45 -6
- package/src/input/commands/recall-bundle.ts +11 -11
- package/src/input/commands/recall-capture.ts +13 -11
- package/src/input/commands/recall-query.ts +29 -21
- package/src/input/commands/recall-review.ts +2 -1
- package/src/input/commands/routines-runtime.ts +59 -43
- package/src/input/commands/schedule-runtime.ts +33 -20
- package/src/input/commands/security-runtime.ts +4 -4
- package/src/input/commands/session-content.ts +80 -78
- package/src/input/commands/session-workflow.ts +132 -93
- package/src/input/commands/session.ts +3 -174
- package/src/input/commands/shell-core.ts +32 -17
- package/src/input/commands/subscription-runtime.ts +53 -179
- package/src/input/commands/tasks-runtime.ts +20 -20
- package/src/input/commands/work-plan-runtime.ts +33 -8
- package/src/input/commands.ts +2 -2
- package/src/input/feed-context-factory.ts +2 -1
- package/src/input/file-picker.ts +3 -2
- package/src/input/handler-command-route.ts +4 -7
- package/src/input/handler-content-actions.ts +89 -1
- package/src/input/handler-feed-routes.ts +19 -12
- package/src/input/handler-feed.ts +6 -3
- package/src/input/handler-interactions.ts +7 -5
- package/src/input/handler-modal-stack.ts +3 -3
- package/src/input/handler-onboarding.ts +24 -80
- package/src/input/handler-shortcuts.ts +15 -4
- package/src/input/handler.ts +47 -17
- package/src/input/input-history.ts +5 -6
- package/src/input/keybindings.ts +22 -11
- package/src/input/onboarding/onboarding-wizard-apply.ts +13 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +147 -57
- package/src/input/onboarding/onboarding-wizard-steps.ts +46 -29
- package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
- package/src/input/onboarding/onboarding-wizard.ts +68 -0
- package/src/input/profile-picker-modal.ts +31 -12
- package/src/input/session-picker-modal.ts +21 -4
- package/src/input/settings-modal-behavior.ts +0 -3
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal-types.ts +2 -13
- package/src/input/settings-modal.ts +6 -52
- package/src/input/submission-intent.ts +0 -1
- package/src/input/submission-router.ts +3 -3
- package/src/main.ts +18 -8
- package/src/panels/approval-panel.ts +8 -8
- package/src/panels/automation-control-panel.ts +2 -2
- package/src/panels/base-panel.ts +1 -1
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +1 -10
- package/src/panels/builtin/session.ts +9 -9
- package/src/panels/builtin/shared.ts +2 -2
- package/src/panels/cost-tracker-panel.ts +1 -1
- package/src/panels/docs-panel.ts +5 -3
- package/src/panels/index.ts +0 -1
- package/src/panels/knowledge-panel.ts +6 -5
- package/src/panels/memory-panel.ts +7 -6
- package/src/panels/panel-list-panel.ts +36 -80
- package/src/panels/project-planning-panel.ts +18 -11
- package/src/panels/provider-account-snapshot.ts +51 -25
- package/src/panels/provider-accounts-panel.ts +33 -18
- package/src/panels/provider-health-domains.ts +45 -4
- package/src/panels/provider-health-panel.ts +5 -4
- package/src/panels/qr-panel.ts +1 -1
- package/src/panels/schedule-panel.ts +9 -17
- package/src/panels/security-panel.ts +8 -8
- package/src/panels/session-browser-panel.ts +10 -10
- package/src/panels/subscription-panel.ts +3 -3
- package/src/panels/system-messages-panel.ts +1 -1
- package/src/panels/tasks-panel.ts +20 -13
- package/src/panels/tool-inspector-panel.ts +19 -12
- package/src/panels/work-plan-panel.ts +5 -5
- package/src/planning/project-planning-coordinator.ts +1 -1
- package/src/provider-auth-route-display.ts +9 -0
- package/src/renderer/agent-workspace-style.ts +34 -0
- package/src/renderer/agent-workspace.ts +228 -52
- package/src/renderer/autocomplete-overlay.ts +25 -6
- package/src/renderer/bookmark-modal.ts +19 -4
- package/src/renderer/buffer.ts +4 -2
- package/src/renderer/context-inspector.ts +50 -13
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +19 -6
- package/src/renderer/help-overlay.ts +106 -33
- package/src/renderer/history-search-overlay.ts +19 -4
- package/src/renderer/live-tail-modal.ts +27 -5
- package/src/renderer/mcp-workspace.ts +164 -50
- package/src/renderer/model-picker-overlay.ts +58 -2
- package/src/renderer/model-workspace.ts +104 -20
- package/src/renderer/process-modal.ts +27 -6
- package/src/renderer/profile-picker-modal.ts +20 -4
- package/src/renderer/search-overlay.ts +25 -5
- package/src/renderer/selection-modal-overlay.ts +46 -14
- package/src/renderer/session-picker-modal.ts +18 -1
- package/src/renderer/settings-modal-helpers.ts +2 -40
- package/src/renderer/settings-modal.ts +83 -50
- package/src/renderer/tool-call.ts +20 -11
- package/src/runtime/agent-runtime-events.ts +6 -6
- package/src/runtime/bootstrap-command-context.ts +7 -1
- package/src/runtime/bootstrap-command-parts.ts +9 -7
- package/src/runtime/bootstrap-core.ts +19 -1
- package/src/runtime/bootstrap-hook-bridge.ts +7 -18
- package/src/runtime/bootstrap-shell.ts +4 -4
- package/src/runtime/bootstrap.ts +31 -22
- package/src/runtime/connected-host-auth.ts +7 -2
- package/src/runtime/diagnostics/panels/index.ts +2 -2
- package/src/runtime/diagnostics/panels/policy.ts +7 -7
- package/src/runtime/index.ts +2 -1
- package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
- package/src/runtime/onboarding/apply.ts +80 -79
- package/src/runtime/onboarding/derivation.ts +5 -8
- package/src/runtime/onboarding/snapshot.ts +0 -15
- package/src/runtime/onboarding/types.ts +8 -19
- package/src/runtime/onboarding/verify.ts +32 -10
- package/src/runtime/operator-token-cleanup.ts +1 -1
- package/src/runtime/services.ts +91 -22
- package/src/runtime/store/selectors/index.ts +3 -3
- package/src/runtime/store/state.ts +1 -4
- package/src/runtime/surface-feature-flags.ts +41 -6
- package/src/runtime/ui-read-models.ts +3 -4
- package/src/runtime/ui-services.ts +6 -6
- package/src/shell/blocking-input.ts +2 -1
- package/src/shell/ui-openers.ts +3 -13
- package/src/tools/agent-analysis-registry-policy.ts +0 -1
- package/src/tools/agent-channel-send-tool.ts +133 -0
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
- package/src/tools/agent-knowledge-tool.ts +170 -0
- package/src/tools/agent-local-registry-tool.ts +269 -69
- package/src/tools/agent-media-generate-tool.ts +133 -0
- package/src/tools/agent-notify-tool.ts +143 -0
- package/src/tools/agent-operator-action-tool.ts +137 -0
- package/src/tools/agent-operator-briefing-tool.ts +217 -0
- package/src/tools/agent-reminder-schedule-tool.ts +237 -0
- package/src/tools/agent-tool-policy-guard.ts +8 -8
- package/src/tools/agent-work-plan-tool.ts +256 -0
- package/src/version.ts +1 -1
- package/src/input/commands/policy-dispatch.ts +0 -339
- package/src/input/commands/policy.ts +0 -13
- package/src/panels/panel-picker.ts +0 -105
- package/src/panels/policy-panel.ts +0 -308
- package/src/renderer/panel-picker-overlay.ts +0 -202
|
@@ -2,14 +2,14 @@ import type { CommandRegistry } from '../command-registry.ts';
|
|
|
2
2
|
import { networkInterfaces } from 'node:os';
|
|
3
3
|
import {
|
|
4
4
|
buildCompanionConnectionInfo,
|
|
5
|
+
type CompanionConnectionInfo,
|
|
5
6
|
encodeConnectionPayload,
|
|
6
|
-
formatConnectionBlock,
|
|
7
7
|
generateQrMatrix,
|
|
8
8
|
renderQrToString,
|
|
9
9
|
} from '@pellux/goodvibes-sdk/platform/pairing';
|
|
10
10
|
import { GOODVIBES_AGENT_PAIRING_SURFACE } from '../../config/surface.ts';
|
|
11
11
|
import { resolveRuntimeEndpointBinding } from '../../cli/endpoints.ts';
|
|
12
|
-
import { connectedHostTokenRequiredMessage, readConnectedHostOperatorToken } from '../../runtime/connected-host-auth.ts';
|
|
12
|
+
import { connectedHostOperatorTokenFingerprint, connectedHostTokenRequiredMessage, readConnectedHostOperatorToken } from '../../runtime/connected-host-auth.ts';
|
|
13
13
|
import { requirePlatform, requireShellPaths } from './runtime-services.ts';
|
|
14
14
|
|
|
15
15
|
function getLocalNetworkIp(): string {
|
|
@@ -31,13 +31,42 @@ function urlHostForBindHost(host: string): string {
|
|
|
31
31
|
return host || '127.0.0.1';
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
function formatTokenLine(token: string, showToken: boolean): string {
|
|
35
|
+
if (showToken) return `Token: ${token}`;
|
|
36
|
+
return `Token: present sha256:${connectedHostOperatorTokenFingerprint(token)} (hidden in text; QR contains pairing payload)`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function formatAgentPairingBlock(info: CompanionConnectionInfo, qr: string, showToken: boolean): string {
|
|
40
|
+
return [
|
|
41
|
+
`GoodVibes Agent companion pairing v${info.version}`,
|
|
42
|
+
'━━━━━━━━━━━━━━━━━━━━━━━━',
|
|
43
|
+
`Connected host: ${info.url}`,
|
|
44
|
+
`Surface: ${info.surface}`,
|
|
45
|
+
`User: ${info.username}`,
|
|
46
|
+
formatTokenLine(info.token, showToken),
|
|
47
|
+
'',
|
|
48
|
+
'Scan to connect:',
|
|
49
|
+
'',
|
|
50
|
+
qr,
|
|
51
|
+
'',
|
|
52
|
+
showToken
|
|
53
|
+
? 'Manual token display was explicitly confirmed for this command.'
|
|
54
|
+
: 'For manual setup, rerun /pair --show-token --yes to print the token once.',
|
|
55
|
+
'Agent is waiting for the companion app to connect to the owning GoodVibes host.',
|
|
56
|
+
].join('\n');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function shouldShowToken(args: readonly string[]): boolean {
|
|
60
|
+
return args.includes('--show-token') || args.includes('--manual-token');
|
|
61
|
+
}
|
|
62
|
+
|
|
34
63
|
export function registerQrcodeRuntimeCommands(registry: CommandRegistry): void {
|
|
35
64
|
registry.register({
|
|
36
65
|
name: 'qrcode',
|
|
37
66
|
aliases: ['qr', 'pair'],
|
|
38
67
|
description: 'Print companion pairing details and a QR code',
|
|
39
68
|
usage: '',
|
|
40
|
-
handler(
|
|
69
|
+
handler(args, ctx) {
|
|
41
70
|
const shellPaths = requireShellPaths(ctx);
|
|
42
71
|
const configManager = requirePlatform(ctx).configManager;
|
|
43
72
|
const tokenRecord = readConnectedHostOperatorToken(shellPaths.homeDirectory);
|
|
@@ -46,16 +75,26 @@ export function registerQrcodeRuntimeCommands(registry: CommandRegistry): void {
|
|
|
46
75
|
return;
|
|
47
76
|
}
|
|
48
77
|
const binding = resolveRuntimeEndpointBinding(configManager, 'controlPlane');
|
|
49
|
-
const
|
|
78
|
+
const connectedHostUrl = `http://${urlHostForBindHost(binding.host)}:${binding.port}`;
|
|
50
79
|
const info = buildCompanionConnectionInfo({
|
|
51
|
-
daemonUrl,
|
|
80
|
+
daemonUrl: connectedHostUrl,
|
|
52
81
|
token: tokenRecord.token,
|
|
53
82
|
username: 'admin',
|
|
54
83
|
surface: GOODVIBES_AGENT_PAIRING_SURFACE,
|
|
55
84
|
});
|
|
56
85
|
const payload = encodeConnectionPayload(info);
|
|
57
86
|
const qr = renderQrToString(generateQrMatrix(payload));
|
|
58
|
-
|
|
87
|
+
const showToken = shouldShowToken(args);
|
|
88
|
+
if (showToken && !args.includes('--yes')) {
|
|
89
|
+
ctx.print([
|
|
90
|
+
'Manual companion token display requires confirmation.',
|
|
91
|
+
' rerun: /pair --show-token --yes',
|
|
92
|
+
` token fingerprint: sha256:${connectedHostOperatorTokenFingerprint(tokenRecord.token)}`,
|
|
93
|
+
' QR pairing remains available without printing the raw token.',
|
|
94
|
+
].join('\n'));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
ctx.print(formatAgentPairingBlock(info, qr, showToken));
|
|
59
98
|
},
|
|
60
99
|
});
|
|
61
100
|
}
|
|
@@ -31,7 +31,7 @@ export function handleRecallExport(args: string[], context: CommandContext): voi
|
|
|
31
31
|
if (scopeIdx !== -1 && commandArgs[scopeIdx + 1]) {
|
|
32
32
|
const scope = commandArgs[scopeIdx + 1];
|
|
33
33
|
if (!isValidScope(scope)) {
|
|
34
|
-
context.print(`[memory] Unknown scope "${scope}". Valid
|
|
34
|
+
context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES.join(', ')}.`);
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
filter.scope = scope;
|
|
@@ -41,7 +41,7 @@ export function handleRecallExport(args: string[], context: CommandContext): voi
|
|
|
41
41
|
if (clsIdx !== -1 && commandArgs[clsIdx + 1]) {
|
|
42
42
|
const cls = commandArgs[clsIdx + 1];
|
|
43
43
|
if (!isValidClass(cls)) {
|
|
44
|
-
context.print(`[memory] Unknown class "${cls}". Valid
|
|
44
|
+
context.print(`[memory] Unknown class "${cls}". Valid values ${VALID_CLASSES.join(', ')}.`);
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
filter.cls = cls;
|
|
@@ -77,23 +77,23 @@ export async function handleRecallImport(args: string[], context: CommandContext
|
|
|
77
77
|
try {
|
|
78
78
|
bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as MemoryBundle;
|
|
79
79
|
} catch (error) {
|
|
80
|
-
context.print(`[memory] Failed to read memory bundle
|
|
80
|
+
context.print(`[memory] Failed to read memory bundle ${summarizeError(error)}`);
|
|
81
81
|
return;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
const result = await memory.importBundle(bundle);
|
|
85
85
|
context.print(`[memory] Imported bundle from ${targetPath}`);
|
|
86
|
-
context.print(`
|
|
87
|
-
context.print(`
|
|
86
|
+
context.print(` records imported=${result.importedRecords} skipped=${result.skippedRecords}`);
|
|
87
|
+
context.print(` links imported=${result.importedLinks}`);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
function inspectBundle(bundle: MemoryBundle): string {
|
|
91
91
|
return [
|
|
92
92
|
'Memory Handoff Review',
|
|
93
|
-
` scope
|
|
94
|
-
` records
|
|
95
|
-
` links
|
|
96
|
-
` exportedAt
|
|
93
|
+
` scope ${bundle.scope}`,
|
|
94
|
+
` records ${bundle.recordCount}`,
|
|
95
|
+
` links ${bundle.linkCount}`,
|
|
96
|
+
` exportedAt ${new Date(bundle.exportedAt).toISOString()}`,
|
|
97
97
|
].join('\n');
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -116,7 +116,7 @@ export function handleRecallHandoffExport(args: string[], context: CommandContex
|
|
|
116
116
|
const scopeIdx = commandArgs.indexOf('--scope');
|
|
117
117
|
const scopeRaw = scopeIdx !== -1 ? commandArgs[scopeIdx + 1] : 'team';
|
|
118
118
|
if (!scopeRaw || !isValidScope(scopeRaw)) {
|
|
119
|
-
context.print(`[memory] Unknown scope "${scopeRaw ?? ''}". Valid
|
|
119
|
+
context.print(`[memory] Unknown scope "${scopeRaw ?? ''}". Valid values ${VALID_SCOPES.join(', ')}.`);
|
|
120
120
|
return;
|
|
121
121
|
}
|
|
122
122
|
const bundle = memory.exportBundle({ scope: scopeRaw });
|
|
@@ -137,7 +137,7 @@ export function handleRecallHandoffInspect(args: string[], context: CommandConte
|
|
|
137
137
|
const bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as MemoryBundle;
|
|
138
138
|
context.print(inspectBundle(bundle));
|
|
139
139
|
} catch (error) {
|
|
140
|
-
context.print(`[memory] Failed to inspect handoff bundle
|
|
140
|
+
context.print(`[memory] Failed to inspect handoff bundle ${summarizeError(error)}`);
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CommandContext } from '../command-registry.ts';
|
|
2
2
|
import type { ProvenanceLink } from '@pellux/goodvibes-sdk/platform/state';
|
|
3
|
+
import { formatAgentRecordReferences } from '../../agent/record-labels.ts';
|
|
3
4
|
import {
|
|
4
5
|
buildIncidentMemoryAddOptions,
|
|
5
6
|
buildMcpSecurityMemoryAddOptions,
|
|
@@ -17,7 +18,7 @@ export async function handleRecallAdd(args: string[], context: CommandContext):
|
|
|
17
18
|
|
|
18
19
|
const cls = args[0];
|
|
19
20
|
if (!cls || !isValidClass(cls)) {
|
|
20
|
-
context.print(`[memory] Invalid class "${cls ?? ''}". Valid
|
|
21
|
+
context.print(`[memory] Invalid class "${cls ?? ''}". Valid values ${VALID_CLASSES.join(', ')}.`);
|
|
21
22
|
return;
|
|
22
23
|
}
|
|
23
24
|
|
|
@@ -36,7 +37,7 @@ export async function handleRecallAdd(args: string[], context: CommandContext):
|
|
|
36
37
|
const scope = scopeRaw && isValidScope(scopeRaw) ? scopeRaw : 'project';
|
|
37
38
|
|
|
38
39
|
if (scopeRaw && !isValidScope(scopeRaw)) {
|
|
39
|
-
context.print(`[memory] Invalid scope "${scopeRaw}". Valid
|
|
40
|
+
context.print(`[memory] Invalid scope "${scopeRaw}". Valid values ${VALID_SCOPES.join(', ')}.`);
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
42
43
|
|
|
@@ -60,12 +61,13 @@ export async function handleRecallAdd(args: string[], context: CommandContext):
|
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
const record = await memory.add({ scope, cls, summary, detail, tags, provenance });
|
|
63
|
-
context.print(`[memory] Added ${cls}
|
|
64
|
-
context.print(`
|
|
65
|
-
context.print(`
|
|
66
|
-
|
|
64
|
+
context.print(`[memory] Added ${cls}`);
|
|
65
|
+
context.print(` id ${record.id}`);
|
|
66
|
+
context.print(` scope ${record.scope}`);
|
|
67
|
+
context.print(` summary ${record.summary}`);
|
|
68
|
+
if (record.tags.length) context.print(` tags ${record.tags.join(', ')}`);
|
|
67
69
|
if (record.provenance.length) {
|
|
68
|
-
context.print(`
|
|
70
|
+
context.print(` origin ${formatAgentRecordReferences(record.provenance)}`);
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
73
|
|
|
@@ -87,12 +89,12 @@ export async function handleRecallCapture(args: string[], context: CommandContex
|
|
|
87
89
|
? context.extensions.forensicsRegistry.latest()
|
|
88
90
|
: context.extensions.forensicsRegistry.getById(requestedId);
|
|
89
91
|
if (!report) {
|
|
90
|
-
context.print(`[memory] Incident not found
|
|
92
|
+
context.print(`[memory] Incident not found ${requestedId ?? 'latest'}`);
|
|
91
93
|
return;
|
|
92
94
|
}
|
|
93
95
|
const bundle = context.extensions.forensicsRegistry.buildBundle(report.id);
|
|
94
96
|
if (!bundle) {
|
|
95
|
-
context.print(`[memory] Failed to build incident bundle
|
|
97
|
+
context.print(`[memory] Failed to build incident bundle ${report.id}`);
|
|
96
98
|
return;
|
|
97
99
|
}
|
|
98
100
|
const record = await memory.add(buildIncidentMemoryAddOptions(bundle));
|
|
@@ -119,7 +121,7 @@ export async function handleRecallCapture(args: string[], context: CommandContex
|
|
|
119
121
|
}
|
|
120
122
|
const server = context.extensions.mcpRegistry.listServerSecurity().find((entry) => entry.name === serverName);
|
|
121
123
|
if (!server) {
|
|
122
|
-
context.print(`[memory] MCP server not found
|
|
124
|
+
context.print(`[memory] MCP server not found ${serverName}`);
|
|
123
125
|
return;
|
|
124
126
|
}
|
|
125
127
|
const record = await memory.add(buildMcpSecurityMemoryAddOptions(server));
|
|
@@ -139,7 +141,7 @@ export async function handleRecallCapture(args: string[], context: CommandContex
|
|
|
139
141
|
}
|
|
140
142
|
const plugin = pluginManager.list().find((entry) => entry.name === pluginName);
|
|
141
143
|
if (!plugin) {
|
|
142
|
-
context.print(`[memory] Plugin not found
|
|
144
|
+
context.print(`[memory] Plugin not found ${pluginName}`);
|
|
143
145
|
return;
|
|
144
146
|
}
|
|
145
147
|
const quarantineReason = pluginManager.getQuarantineRecord(plugin.name)?.reason;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CommandContext } from '../command-registry.ts';
|
|
2
2
|
import type { MemoryApi } from '@pellux/goodvibes-sdk/platform/knowledge';
|
|
3
3
|
import type { MemorySearchFilter } from '@pellux/goodvibes-sdk/platform/state';
|
|
4
|
+
import { formatAgentRecordReference, formatAgentRecordReferences } from '../../agent/record-labels.ts';
|
|
4
5
|
import { VALID_CLASSES, VALID_SCOPES, isValidClass, isValidScope } from './recall-shared.ts';
|
|
5
6
|
import { requireYesFlag, stripYesFlag } from './confirmation.ts';
|
|
6
7
|
|
|
@@ -8,7 +9,7 @@ export function getMemoryApi(context: CommandContext): MemoryApi | null {
|
|
|
8
9
|
const memoryApi = context.clients?.agentKnowledgeApi?.memory;
|
|
9
10
|
if (!memoryApi) {
|
|
10
11
|
context.print('[memory] Agent Memory API is not available in this runtime.');
|
|
11
|
-
context.print('[memory] Refusing to use default
|
|
12
|
+
context.print('[memory] Refusing to use default knowledge or non-Agent knowledge fallback.');
|
|
12
13
|
return null;
|
|
13
14
|
}
|
|
14
15
|
return memoryApi;
|
|
@@ -29,7 +30,7 @@ export function handleRecallSearch(args: string[], context: CommandContext): voi
|
|
|
29
30
|
const cls = args[clsIdx + 1];
|
|
30
31
|
if (isValidClass(cls)) filter.cls = cls;
|
|
31
32
|
else {
|
|
32
|
-
context.print(`[memory] Unknown class "${cls}". Valid
|
|
33
|
+
context.print(`[memory] Unknown class "${cls}". Valid values ${VALID_CLASSES.join(', ')}.`);
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
36
|
}
|
|
@@ -39,7 +40,7 @@ export function handleRecallSearch(args: string[], context: CommandContext): voi
|
|
|
39
40
|
const scope = args[scopeIdx + 1];
|
|
40
41
|
if (isValidScope(scope)) filter.scope = scope;
|
|
41
42
|
else {
|
|
42
|
-
context.print(`[memory] Unknown scope "${scope}". Valid
|
|
43
|
+
context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES.join(', ')}.`);
|
|
43
44
|
return;
|
|
44
45
|
}
|
|
45
46
|
}
|
|
@@ -63,7 +64,7 @@ export function handleRecallSearch(args: string[], context: CommandContext): voi
|
|
|
63
64
|
return;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
context.print(`[memory] ${results.length} ${semantic ? 'semantic ' : ''}record(s)
|
|
67
|
+
context.print(`[memory] ${results.length} ${semantic ? 'semantic ' : ''}record(s)`);
|
|
67
68
|
for (const record of results) {
|
|
68
69
|
const semanticEntry = semanticResults.find((entry) => entry.record.id === record.id);
|
|
69
70
|
const ts = new Date(record.createdAt).toISOString().slice(0, 16).replace('T', ' ');
|
|
@@ -72,7 +73,7 @@ export function handleRecallSearch(args: string[], context: CommandContext): voi
|
|
|
72
73
|
context.print(` ${record.id} [${record.cls}]${tagStr} ${ts}${scoreStr}`);
|
|
73
74
|
context.print(` ${record.summary}`);
|
|
74
75
|
if (record.provenance.length) {
|
|
75
|
-
context.print(`
|
|
76
|
+
context.print(` origin ${formatAgentRecordReferences(record.provenance)}`);
|
|
76
77
|
}
|
|
77
78
|
}
|
|
78
79
|
}
|
|
@@ -124,29 +125,28 @@ export function handleRecallGet(args: string[], context: CommandContext): void {
|
|
|
124
125
|
}
|
|
125
126
|
const record = memory.get(id);
|
|
126
127
|
if (!record) {
|
|
127
|
-
context.print(`[memory] Record not found
|
|
128
|
+
context.print(`[memory] Record not found ${id}`);
|
|
128
129
|
return;
|
|
129
130
|
}
|
|
130
131
|
const ts = new Date(record.createdAt).toISOString().slice(0, 19).replace('T', ' ');
|
|
131
132
|
context.print(`[memory] ${record.id}`);
|
|
132
|
-
context.print(`
|
|
133
|
-
context.print(`
|
|
134
|
-
context.print(`
|
|
135
|
-
if (record.detail) context.print(`
|
|
136
|
-
if (record.tags.length) context.print(`
|
|
137
|
-
context.print(`
|
|
133
|
+
context.print(` scope ${record.scope}`);
|
|
134
|
+
context.print(` class ${record.cls}`);
|
|
135
|
+
context.print(` summary ${record.summary}`);
|
|
136
|
+
if (record.detail) context.print(` detail ${record.detail}`);
|
|
137
|
+
if (record.tags.length) context.print(` tags ${record.tags.join(', ')}`);
|
|
138
|
+
context.print(` created ${ts}`);
|
|
138
139
|
|
|
139
140
|
if (record.provenance.length) {
|
|
140
|
-
context.print('
|
|
141
|
+
context.print(' origin');
|
|
141
142
|
for (const provenance of record.provenance) {
|
|
142
|
-
|
|
143
|
-
context.print(` ${provenance.kind}: ${provenance.ref}${label}`);
|
|
143
|
+
context.print(` ${formatAgentRecordReference(provenance)}`);
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
const links = memory.linksFor(id);
|
|
148
148
|
if (links.length) {
|
|
149
|
-
context.print('
|
|
149
|
+
context.print(' links');
|
|
150
150
|
for (const link of links) {
|
|
151
151
|
const dir = link.fromId === id ? '->' : '<-';
|
|
152
152
|
const other = link.fromId === id ? link.toId : link.fromId;
|
|
@@ -175,7 +175,12 @@ export async function handleRecallLink(args: string[], context: CommandContext):
|
|
|
175
175
|
context.print('[memory] Link failed — check that both IDs exist.');
|
|
176
176
|
return;
|
|
177
177
|
}
|
|
178
|
-
context.print(
|
|
178
|
+
context.print([
|
|
179
|
+
'[memory] Linked',
|
|
180
|
+
` from ${fromId}`,
|
|
181
|
+
` to ${toId}`,
|
|
182
|
+
` relation ${relation}`,
|
|
183
|
+
].join('\n'));
|
|
179
184
|
}
|
|
180
185
|
|
|
181
186
|
export function handleRecallRemove(args: string[], context: CommandContext): void {
|
|
@@ -195,10 +200,13 @@ export function handleRecallRemove(args: string[], context: CommandContext): voi
|
|
|
195
200
|
}
|
|
196
201
|
const removed = memory.delete(id);
|
|
197
202
|
if (!removed) {
|
|
198
|
-
context.print(`[memory] Record not found
|
|
203
|
+
context.print(`[memory] Record not found ${id}`);
|
|
199
204
|
return;
|
|
200
205
|
}
|
|
201
|
-
context.print(
|
|
206
|
+
context.print([
|
|
207
|
+
'[memory] Deleted',
|
|
208
|
+
` id ${id}`,
|
|
209
|
+
].join('\n'));
|
|
202
210
|
}
|
|
203
211
|
|
|
204
212
|
export function handleRecallList(args: string[], context: CommandContext): void {
|
|
@@ -213,7 +221,7 @@ export function handleRecallList(args: string[], context: CommandContext): void
|
|
|
213
221
|
if (scopeIdx !== -1 && args[scopeIdx + 1]) {
|
|
214
222
|
const scope = args[scopeIdx + 1];
|
|
215
223
|
if (!isValidScope(scope)) {
|
|
216
|
-
context.print(`[memory] Unknown scope "${scope}". Valid
|
|
224
|
+
context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES.join(', ')}.`);
|
|
217
225
|
return;
|
|
218
226
|
}
|
|
219
227
|
filter.scope = scope;
|
|
@@ -232,7 +240,7 @@ export function handleRecallList(args: string[], context: CommandContext): void
|
|
|
232
240
|
}
|
|
233
241
|
|
|
234
242
|
for (const [clsName, group] of Object.entries(grouped)) {
|
|
235
|
-
context.print(`\n[memory] ${clsName.toUpperCase()} (${group.length})
|
|
243
|
+
context.print(`\n[memory] ${clsName.toUpperCase()} (${group.length})`);
|
|
236
244
|
for (const record of group) {
|
|
237
245
|
const tagStr = record.tags.length ? ` [${record.tags.join(', ')}]` : '';
|
|
238
246
|
context.print(` ${record.id} [${record.scope}]${tagStr} ${record.summary}`);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CommandContext } from '../command-registry.ts';
|
|
2
|
+
import { formatAgentRecordReviewState } from '../../agent/record-labels.ts';
|
|
2
3
|
import { VALID_REVIEW_STATES, VALID_SCOPES, isValidReviewState, isValidScope } from './recall-shared.ts';
|
|
3
4
|
import { getMemoryApi } from './recall-query.ts';
|
|
4
5
|
import { requireYesFlag, stripYesFlag } from './confirmation.ts';
|
|
@@ -17,7 +18,7 @@ export function handleRecallQueue(args: string[], context: CommandContext): void
|
|
|
17
18
|
context.print(`[memory] Review queue (${queue.length}):`);
|
|
18
19
|
for (const record of queue) {
|
|
19
20
|
const reason = record.staleReason ? ` — ${record.staleReason}` : '';
|
|
20
|
-
context.print(` ${record.id} [${record.scope}/${record.cls}] ${record.reviewState} ${record.confidence}% ${record.summary}${reason}`);
|
|
21
|
+
context.print(` ${record.id} [${record.scope}/${record.cls}] ${formatAgentRecordReviewState(record.reviewState)} ${record.confidence}% ${record.summary}${reason}`);
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { discoverRoutines, type DiscoveredRoutineRecord } from '../../agent/routine-discovery.ts';
|
|
2
2
|
import { AgentRoutineRegistry, evaluateAgentRoutineReadiness, type AgentRoutineRecord } from '../../agent/routine-registry.ts';
|
|
3
|
+
import { formatAgentRecordOrigin, formatAgentRecordReviewState } from '../../agent/record-labels.ts';
|
|
3
4
|
import { buildAgentSkillRequirements, formatAgentSkillRequirement } from '../../agent/skill-registry.ts';
|
|
4
5
|
import {
|
|
5
6
|
buildRoutineSchedulePreview,
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
promoteRoutineToConnectedSchedule,
|
|
8
|
+
resolveAgentConnectedHostConnection,
|
|
8
9
|
} from '../../agent/routine-schedule-promotion.ts';
|
|
9
10
|
import { parseRoutineSchedulePromotionArgs } from '../../agent/routine-schedule-args.ts';
|
|
10
11
|
import {
|
|
@@ -73,12 +74,23 @@ function requiredFlag(flags: ReadonlyMap<string, string>, key: string): string {
|
|
|
73
74
|
return value;
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
function formatRoutineReceipt(title: string, routine: Pick<AgentRoutineRecord, 'id' | 'name'>, extra: readonly string[] = []): string {
|
|
78
|
+
const enabled = extra.some((line) => line.trim() === 'enabled yes');
|
|
79
|
+
return [
|
|
80
|
+
`${title} ${routine.id}: ${routine.name}${enabled ? ' (enabled)' : ''}`,
|
|
81
|
+
` id ${routine.id}`,
|
|
82
|
+
` name ${routine.name}`,
|
|
83
|
+
...extra,
|
|
84
|
+
].join('\n');
|
|
85
|
+
}
|
|
86
|
+
|
|
76
87
|
function summarizeRoutine(routine: AgentRoutineRecord): string {
|
|
77
88
|
const enabled = routine.enabled ? 'enabled' : 'disabled';
|
|
78
|
-
const tags = routine.tags.length > 0 ? ` tags
|
|
89
|
+
const tags = routine.tags.length > 0 ? ` tags ${routine.tags.join(', ')}` : '';
|
|
79
90
|
const readiness = evaluateAgentRoutineReadiness(routine);
|
|
91
|
+
const review = formatAgentRecordReviewState(routine.reviewState);
|
|
80
92
|
const ready = readiness.ready ? 'ready' : `needs ${readiness.missing.map(formatAgentSkillRequirement).join(',')}`;
|
|
81
|
-
return ` ${routine.id} ${enabled} ${
|
|
93
|
+
return ` ${routine.id} ${enabled} ${review} ${ready} starts ${routine.startCount} ${routine.name} - ${routine.description}${tags}`;
|
|
82
94
|
}
|
|
83
95
|
|
|
84
96
|
function renderList(title: string, registry: AgentRoutineRegistry, routines: readonly AgentRoutineRecord[], emptyMessage?: string): string {
|
|
@@ -86,12 +98,12 @@ function renderList(title: string, registry: AgentRoutineRegistry, routines: rea
|
|
|
86
98
|
if (routines.length === 0) {
|
|
87
99
|
return emptyMessage
|
|
88
100
|
? `${title}\n ${emptyMessage}`
|
|
89
|
-
: `${title}\n No local Agent routines yet. Create one with /routines create --name <name> --description <summary> --steps <steps>.`;
|
|
101
|
+
: `${title}\n No local Agent routines yet.\n No Agent-local routines yet. Create one with /routines create --name <name> --description <summary> --steps <steps>.`;
|
|
90
102
|
}
|
|
91
103
|
return [
|
|
92
104
|
`${title} (${routines.length})`,
|
|
93
|
-
` store
|
|
94
|
-
` enabled
|
|
105
|
+
` store ${snapshot.path}`,
|
|
106
|
+
` enabled ${snapshot.enabledRoutines.length}`,
|
|
95
107
|
...routines.map(summarizeRoutine),
|
|
96
108
|
].join('\n');
|
|
97
109
|
}
|
|
@@ -100,20 +112,19 @@ function renderRoutine(routine: AgentRoutineRecord): string {
|
|
|
100
112
|
const readiness = evaluateAgentRoutineReadiness(routine);
|
|
101
113
|
return [
|
|
102
114
|
`Routine ${routine.name}`,
|
|
103
|
-
` id
|
|
104
|
-
` enabled
|
|
115
|
+
` id ${routine.id}`,
|
|
116
|
+
` enabled ${routine.enabled ? 'yes' : 'no'}`,
|
|
105
117
|
` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
|
|
106
|
-
` requirements
|
|
118
|
+
` requirements ${routine.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
|
|
107
119
|
readiness.missing.length > 0 ? ` missing: ${readiness.missing.map(formatAgentSkillRequirement).join(', ')}` : '',
|
|
108
|
-
` review
|
|
109
|
-
`
|
|
110
|
-
` provenance: ${routine.provenance}`,
|
|
120
|
+
` review ${formatAgentRecordReviewState(routine.reviewState)}`,
|
|
121
|
+
` origin ${formatAgentRecordOrigin(routine.source, routine.provenance)}`,
|
|
111
122
|
` tags: ${routine.tags.join(', ') || '(none)'}`,
|
|
112
123
|
` triggers: ${routine.triggers.join(', ') || '(manual)'}`,
|
|
113
|
-
` started
|
|
114
|
-
` created
|
|
115
|
-
` updated
|
|
116
|
-
routine.staleReason ? ` stale reason
|
|
124
|
+
` started ${routine.startCount}${routine.lastStartedAt ? `; last ${routine.lastStartedAt}` : ''}`,
|
|
125
|
+
` created ${routine.createdAt}`,
|
|
126
|
+
` updated ${routine.updatedAt}`,
|
|
127
|
+
routine.staleReason ? ` stale reason ${routine.staleReason}` : '',
|
|
117
128
|
'',
|
|
118
129
|
routine.description,
|
|
119
130
|
'',
|
|
@@ -123,7 +134,7 @@ function renderRoutine(routine: AgentRoutineRecord): string {
|
|
|
123
134
|
|
|
124
135
|
function summarizeDiscoveredRoutine(routine: DiscoveredRoutineRecord): string {
|
|
125
136
|
const description = routine.description ? ` - ${routine.description}` : '';
|
|
126
|
-
return ` ${routine.name} ${routine.origin}${description}\n path
|
|
137
|
+
return ` ${routine.name} ${routine.origin}${description}\n path ${routine.path}`;
|
|
127
138
|
}
|
|
128
139
|
|
|
129
140
|
function renderDiscoveredRoutines(routines: readonly DiscoveredRoutineRecord[]): string {
|
|
@@ -169,7 +180,10 @@ function frontmatterAnyList(routine: DiscoveredRoutineRecord, keys: readonly str
|
|
|
169
180
|
}
|
|
170
181
|
|
|
171
182
|
function printError(ctx: CommandContext, error: unknown): void {
|
|
172
|
-
ctx.print(
|
|
183
|
+
ctx.print([
|
|
184
|
+
'Error',
|
|
185
|
+
` message ${error instanceof Error ? error.message : String(error)}`,
|
|
186
|
+
].join('\n'));
|
|
173
187
|
}
|
|
174
188
|
|
|
175
189
|
async function importDiscoveredRoutine(args: readonly string[], ctx: CommandContext, routineRegistry: AgentRoutineRegistry): Promise<void> {
|
|
@@ -181,18 +195,18 @@ async function importDiscoveredRoutine(args: readonly string[], ctx: CommandCont
|
|
|
181
195
|
}
|
|
182
196
|
const discovered = findDiscoveredRoutine(await discoverRoutines(requireShellPaths(ctx)), name);
|
|
183
197
|
if (!discovered) {
|
|
184
|
-
ctx.print(`Unknown discovered Agent routine
|
|
198
|
+
ctx.print(`Unknown discovered Agent routine ${name}\nRun /routines discover to inspect available routine files.`);
|
|
185
199
|
return;
|
|
186
200
|
}
|
|
187
201
|
if (!parsed.yes) {
|
|
188
202
|
ctx.print([
|
|
189
203
|
'Agent routine import preview',
|
|
190
|
-
` name
|
|
191
|
-
` origin
|
|
192
|
-
` path
|
|
193
|
-
` description
|
|
194
|
-
` steps characters
|
|
195
|
-
' next
|
|
204
|
+
` name ${discovered.name}`,
|
|
205
|
+
` origin ${discovered.origin}`,
|
|
206
|
+
` path ${discovered.path}`,
|
|
207
|
+
` description ${discovered.description || '(none)'}`,
|
|
208
|
+
` steps characters ${discovered.steps.length}`,
|
|
209
|
+
' next rerun with --yes to import into the Agent-local routine registry',
|
|
196
210
|
].join('\n'));
|
|
197
211
|
return;
|
|
198
212
|
}
|
|
@@ -210,7 +224,7 @@ async function importDiscoveredRoutine(args: readonly string[], ctx: CommandCont
|
|
|
210
224
|
source: 'imported',
|
|
211
225
|
provenance: `discovered:${discovered.origin}:${discovered.path}`,
|
|
212
226
|
});
|
|
213
|
-
ctx.print(
|
|
227
|
+
ctx.print(formatRoutineReceipt('Imported Agent routine', routine, [` enabled ${routine.enabled ? 'yes' : 'no'}`]));
|
|
214
228
|
}
|
|
215
229
|
|
|
216
230
|
async function promoteRoutine(args: readonly string[], routineRegistry: AgentRoutineRegistry, ctx: CommandContext): Promise<void> {
|
|
@@ -233,8 +247,8 @@ async function promoteRoutine(args: readonly string[], routineRegistry: AgentRou
|
|
|
233
247
|
return;
|
|
234
248
|
}
|
|
235
249
|
const shellPaths = requireShellPaths(ctx);
|
|
236
|
-
const connection =
|
|
237
|
-
const result = await
|
|
250
|
+
const connection = resolveAgentConnectedHostConnection(ctx.platform.configManager, shellPaths.homeDirectory);
|
|
251
|
+
const result = await promoteRoutineToConnectedSchedule(connection, preview);
|
|
238
252
|
const receipt = receiptStoreFromContext(ctx).append(connection, preview, result);
|
|
239
253
|
ctx.print(result.ok ? `${formatRoutineScheduleSuccess(result)}\n receipt: ${receipt.id}` : `${formatRoutineScheduleFailure(result)}\n receipt: ${receipt.id}`);
|
|
240
254
|
}
|
|
@@ -254,7 +268,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
|
|
|
254
268
|
}
|
|
255
269
|
if (sub === 'attention' || sub === 'needs-setup') {
|
|
256
270
|
const routines = routineRegistry.list().filter((routine) => !evaluateAgentRoutineReadiness(routine).ready);
|
|
257
|
-
ctx.print(renderList('Agent Routines needing setup', routineRegistry, routines, 'No local
|
|
271
|
+
ctx.print(renderList('Agent Routines needing setup', routineRegistry, routines, 'No Agent-local routines need setup.'));
|
|
258
272
|
return;
|
|
259
273
|
}
|
|
260
274
|
if (sub === 'discover' || sub === 'discovered') {
|
|
@@ -286,7 +300,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
|
|
|
286
300
|
}
|
|
287
301
|
if (sub === 'reconcile' || sub === 'sync' || sub === 'status') {
|
|
288
302
|
const shellPaths = requireShellPaths(ctx);
|
|
289
|
-
const connection =
|
|
303
|
+
const connection = resolveAgentConnectedHostConnection(ctx.platform.configManager, shellPaths.homeDirectory);
|
|
290
304
|
const result = await reconcileRoutineScheduleReceipts(connection, receiptStoreFromContext(ctx).snapshot());
|
|
291
305
|
ctx.print(formatRoutineScheduleCorrelation(result));
|
|
292
306
|
return;
|
|
@@ -298,7 +312,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
|
|
|
298
312
|
return;
|
|
299
313
|
}
|
|
300
314
|
const receipt = receiptStoreFromContext(ctx).get(id);
|
|
301
|
-
ctx.print(receipt ? formatRoutineScheduleReceipt(receipt) : `Unknown routine schedule receipt
|
|
315
|
+
ctx.print(receipt ? formatRoutineScheduleReceipt(receipt) : `Unknown routine schedule receipt ${id}`);
|
|
302
316
|
return;
|
|
303
317
|
}
|
|
304
318
|
if (sub === 'create') {
|
|
@@ -316,9 +330,9 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
|
|
|
316
330
|
}),
|
|
317
331
|
enabled: parsed.flags.get('enabled') === 'true',
|
|
318
332
|
source: 'user',
|
|
319
|
-
provenance: '
|
|
333
|
+
provenance: 'Command',
|
|
320
334
|
});
|
|
321
|
-
ctx.print(
|
|
335
|
+
ctx.print(formatRoutineReceipt('Created Agent routine', routine));
|
|
322
336
|
return;
|
|
323
337
|
}
|
|
324
338
|
if (sub === 'update') {
|
|
@@ -340,9 +354,9 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
|
|
|
340
354
|
commands: splitList(parsed.flags.get('requires-command') ?? parsed.flags.get('requires-commands')),
|
|
341
355
|
})
|
|
342
356
|
: undefined,
|
|
343
|
-
provenance: '
|
|
357
|
+
provenance: 'Command',
|
|
344
358
|
});
|
|
345
|
-
ctx.print(
|
|
359
|
+
ctx.print(formatRoutineReceipt('Updated Agent routine', updated));
|
|
346
360
|
return;
|
|
347
361
|
}
|
|
348
362
|
if (sub === 'enable' || sub === 'disable') {
|
|
@@ -352,7 +366,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
|
|
|
352
366
|
return;
|
|
353
367
|
}
|
|
354
368
|
const routine = routineRegistry.setEnabled(id, sub === 'enable');
|
|
355
|
-
ctx.print(`${sub === 'enable' ? 'Enabled' : 'Disabled'} Agent routine
|
|
369
|
+
ctx.print(formatRoutineReceipt(`${sub === 'enable' ? 'Enabled' : 'Disabled'} Agent routine`, routine));
|
|
356
370
|
return;
|
|
357
371
|
}
|
|
358
372
|
if (sub === 'start' || sub === 'run') {
|
|
@@ -364,9 +378,11 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
|
|
|
364
378
|
const routine = routineRegistry.markStarted(id);
|
|
365
379
|
const readiness = evaluateAgentRoutineReadiness(routine);
|
|
366
380
|
ctx.print([
|
|
367
|
-
`Started Agent routine ${routine.id}
|
|
381
|
+
`Started Agent routine ${routine.id}`,
|
|
382
|
+
` id ${routine.id}`,
|
|
383
|
+
` name ${routine.name}`,
|
|
368
384
|
` readiness: ${readiness.ready ? 'ready' : `needs setup (${readiness.missing.map(formatAgentSkillRequirement).join(', ')})`}`,
|
|
369
|
-
' policy
|
|
385
|
+
' policy same main conversation; no hidden job, runtime mutation, or external side effect was started',
|
|
370
386
|
'',
|
|
371
387
|
routine.steps,
|
|
372
388
|
].join('\n'));
|
|
@@ -379,7 +395,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
|
|
|
379
395
|
return;
|
|
380
396
|
}
|
|
381
397
|
const routine = routineRegistry.markReviewed(id);
|
|
382
|
-
ctx.print(
|
|
398
|
+
ctx.print(formatRoutineReceipt('Reviewed Agent routine', routine));
|
|
383
399
|
return;
|
|
384
400
|
}
|
|
385
401
|
if (sub === 'stale') {
|
|
@@ -389,7 +405,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
|
|
|
389
405
|
return;
|
|
390
406
|
}
|
|
391
407
|
const routine = routineRegistry.markStale(id, args.slice(2).join(' '));
|
|
392
|
-
ctx.print(
|
|
408
|
+
ctx.print(formatRoutineReceipt('Marked Agent routine stale', routine));
|
|
393
409
|
return;
|
|
394
410
|
}
|
|
395
411
|
if (sub === 'promote' || sub === 'schedule' || sub === 'promote-schedule') {
|
|
@@ -408,7 +424,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
|
|
|
408
424
|
return;
|
|
409
425
|
}
|
|
410
426
|
const removed = routineRegistry.deleteRoutine(id);
|
|
411
|
-
ctx.print(
|
|
427
|
+
ctx.print(formatRoutineReceipt('Deleted Agent routine', removed));
|
|
412
428
|
return;
|
|
413
429
|
}
|
|
414
430
|
ctx.print('Usage: /routines [list|enabled|attention|discover|import-discovered|search|show|receipts|reconcile|receipt|create|update|enable|disable|start|review|stale|promote|delete]');
|
|
@@ -421,7 +437,7 @@ export function registerRoutinesRuntimeCommands(registry: CommandRegistry): void
|
|
|
421
437
|
registry.register({
|
|
422
438
|
name: 'routines',
|
|
423
439
|
aliases: ['routine'],
|
|
424
|
-
description: 'Manage local
|
|
440
|
+
description: 'Manage Agent-local routines',
|
|
425
441
|
usage: '[list|enabled|attention|discover|import-discovered <name> --yes|search <query>|show <id>|receipts|reconcile|receipt <id>|create --name <name> --description <summary> --steps <steps> [--requires-env A,B] [--requires-command gh,jq]|update <id> [--name ...] [--description ...] [--steps ...]|enable <id>|disable <id>|start <id>|review <id>|stale <id> <reason...>|promote <id> --cron <expr> [--delivery-channel slack] --yes|delete <id> --yes]',
|
|
426
442
|
handler: runRoutinesRuntimeCommand,
|
|
427
443
|
});
|