@pellux/goodvibes-agent 1.1.7 → 1.3.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 +329 -0
- package/README.md +46 -30
- package/dist/package/{ast-grep-napi.linux-x64-gnu-mkk8xwww.node → ast-grep-napi.linux-x64-gnu-swtppvy9.node} +0 -0
- package/dist/package/{ast-grep-napi.linux-x64-musl-ryqtgdv6.node → ast-grep-napi.linux-x64-musl-ttfcdtap.node} +0 -0
- package/dist/package/main.js +138903 -91477
- package/docs/README.md +14 -7
- package/docs/channels-remote-and-api.md +8 -5
- package/docs/connected-host.md +14 -12
- package/docs/getting-started.md +58 -30
- package/docs/knowledge-artifacts-and-multimodal.md +7 -5
- package/docs/project-planning.md +2 -2
- package/docs/providers-and-routing.md +11 -3
- package/docs/tools-and-commands.md +116 -45
- package/docs/voice-and-live-tts.md +3 -1
- package/package.json +3 -2
- package/release/release-notes.md +142 -5
- package/release/release-readiness.json +124 -94
- package/src/agent/assistant-cockpit.ts +247 -0
- package/src/agent/autonomy-schedule-format.ts +96 -0
- package/src/agent/autonomy-schedule.ts +514 -0
- package/src/agent/channel-delivery-receipts.ts +292 -0
- package/src/agent/competitive-feature-inventory.ts +294 -0
- package/src/agent/document-registry-types.ts +106 -0
- package/src/agent/document-registry.ts +734 -0
- package/src/agent/harness-control.ts +2 -2
- package/src/agent/memory-prompt.ts +2 -2
- package/src/agent/operator-actions.ts +50 -6
- package/src/agent/persona-registry.ts +8 -0
- package/src/agent/project-context-files.ts +273 -0
- package/src/agent/prompt-context-receipts.ts +502 -0
- package/src/agent/reminder-schedule-format.ts +16 -2
- package/src/agent/research-run-registry.ts +582 -0
- package/src/agent/research-source-registry.ts +441 -0
- package/src/agent/routine-registry.ts +19 -3
- package/src/agent/routine-schedule-format.ts +27 -2
- package/src/agent/runtime-profile-starters.ts +7 -0
- package/src/agent/runtime-profile.ts +106 -4
- package/src/agent/schedule-edit-format.ts +129 -0
- package/src/agent/schedule-edit.ts +496 -0
- package/src/agent/schedule-next-routes.ts +42 -0
- package/src/agent/setup-wizard-artifact-receipts.ts +366 -0
- package/src/agent/setup-wizard-checkpoint.ts +140 -0
- package/src/agent/setup-wizard.ts +683 -0
- package/src/agent/skill-registry-types.ts +102 -0
- package/src/agent/skill-registry.ts +81 -107
- package/src/agent/vibe-confirmation-routes.ts +62 -0
- package/src/agent/vibe-file.ts +285 -0
- package/src/cli/agent-knowledge-command.ts +45 -2
- package/src/cli/help.ts +3 -0
- package/src/cli/profiles-command.ts +25 -11
- package/src/config/agent-settings-policy.ts +1 -18
- package/src/input/agent-workspace-activation.ts +53 -0
- package/src/input/agent-workspace-artifact-browser-editor.ts +494 -0
- package/src/input/agent-workspace-artifact-metadata.ts +17 -0
- package/src/input/agent-workspace-basic-command-editors.ts +5 -1
- package/src/input/agent-workspace-categories.ts +153 -155
- package/src/input/agent-workspace-channel-triage.ts +481 -0
- package/src/input/agent-workspace-channels.ts +263 -0
- package/src/input/agent-workspace-command-editor.ts +152 -0
- package/src/input/agent-workspace-context-snapshot.ts +349 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +8 -0
- package/src/input/agent-workspace-document-editor.ts +502 -0
- package/src/input/agent-workspace-document-ops-editor.ts +523 -0
- package/src/input/agent-workspace-host-category.ts +1 -1
- package/src/input/agent-workspace-local-library-snapshot.ts +167 -0
- package/src/input/agent-workspace-model-compare-editor.ts +376 -0
- package/src/input/agent-workspace-model-compare-prompt-submission.ts +552 -0
- package/src/input/agent-workspace-model-compare-types.ts +82 -0
- package/src/input/agent-workspace-model-compare-utils.ts +35 -0
- package/src/input/agent-workspace-onboarding-categories.ts +141 -0
- package/src/input/agent-workspace-operations-command-editor-submission.ts +53 -0
- package/src/input/agent-workspace-operations-command-editors.ts +22 -0
- package/src/input/agent-workspace-research-report-editor.ts +212 -0
- package/src/input/agent-workspace-research-run-editor.ts +144 -0
- package/src/input/agent-workspace-research-source-editor.ts +167 -0
- package/src/input/agent-workspace-review-packet-snapshot.ts +593 -0
- package/src/input/agent-workspace-review-packet-utils.ts +265 -0
- package/src/input/agent-workspace-settings.ts +313 -30
- package/src/input/agent-workspace-setup-checkpoint-action.ts +127 -0
- package/src/input/agent-workspace-setup-snapshot.ts +217 -0
- package/src/input/agent-workspace-setup.ts +61 -1
- package/src/input/agent-workspace-snapshot.ts +184 -149
- package/src/input/agent-workspace-types.ts +287 -2
- package/src/input/agent-workspace.ts +23 -1
- package/src/input/command-registry.ts +9 -2
- package/src/input/commands/agent-runtime-profile-runtime.ts +28 -13
- package/src/input/commands/channels-runtime.ts +102 -114
- package/src/input/commands/delegation-runtime.ts +87 -24
- package/src/input/commands/knowledge-browser-flags.ts +12 -0
- package/src/input/commands/knowledge.ts +28 -14
- package/src/input/commands/operator-actions-runtime.ts +6 -3
- package/src/input/commands/schedule-runtime.ts +71 -14
- package/src/input/commands/session-content.ts +2 -2
- package/src/input/commands/shell-core.ts +2 -0
- package/src/input/commands/vibe-runtime.ts +140 -0
- package/src/input/commands.ts +2 -0
- package/src/input/connected-host-routes.ts +123 -0
- package/src/input/settings-modal-types.ts +14 -0
- package/src/input/setup-wizard-live-receipts.ts +76 -0
- package/src/main.ts +15 -15
- package/src/panels/qr-panel.ts +2 -2
- package/src/renderer/agent-workspace-context-lines.ts +701 -0
- package/src/renderer/agent-workspace.ts +68 -421
- package/src/renderer/settings-modal-helpers.ts +12 -0
- package/src/renderer/settings-modal.ts +12 -0
- package/src/runtime/bootstrap-command-context.ts +11 -1
- package/src/runtime/bootstrap-command-parts.ts +14 -3
- package/src/runtime/bootstrap-core.ts +39 -1
- package/src/runtime/bootstrap-shell.ts +6 -0
- package/src/runtime/bootstrap.ts +113 -30
- package/src/runtime/connected-host-auth.ts +3 -2
- package/src/runtime/execution-ledger.ts +231 -0
- package/src/runtime/services.ts +88 -10
- package/src/runtime/tool-permission-safety.ts +199 -5
- package/src/shell/session-continuity-hints.ts +39 -0
- package/src/tools/agent-artifacts-tool.ts +606 -0
- package/src/tools/agent-audit-tool.ts +155 -0
- package/src/tools/agent-autonomy-schedule-tool.ts +238 -0
- package/src/tools/agent-autonomy-tool.ts +140 -0
- package/src/tools/agent-channel-send-tool.ts +24 -2
- package/src/tools/agent-channels-tool.ts +140 -0
- package/src/tools/agent-computer-tool.ts +168 -0
- package/src/tools/agent-context-policy.ts +137 -7
- package/src/tools/agent-context-tool.ts +143 -0
- package/src/tools/agent-delegation-tool.ts +128 -0
- package/src/tools/agent-device-tool.ts +240 -0
- package/src/tools/agent-documents-tool.ts +684 -0
- package/src/tools/agent-execution-tool.ts +230 -0
- package/src/tools/agent-harness-agent-orchestration-policy.ts +75 -0
- package/src/tools/agent-harness-agent-orchestration.ts +791 -0
- package/src/tools/agent-harness-autonomy-intake.ts +785 -0
- package/src/tools/agent-harness-autonomy-live-records.ts +742 -0
- package/src/tools/agent-harness-autonomy-queue-types.ts +88 -0
- package/src/tools/agent-harness-autonomy-queue.ts +571 -0
- package/src/tools/agent-harness-autonomy-watcher-read-models.ts +509 -0
- package/src/tools/agent-harness-background-processes-types.ts +35 -0
- package/src/tools/agent-harness-background-processes.ts +798 -0
- package/src/tools/agent-harness-browser-cockpit-route.ts +373 -0
- package/src/tools/agent-harness-browser-control.ts +346 -0
- package/src/tools/agent-harness-browser-pwa-read-models.ts +622 -0
- package/src/tools/agent-harness-channel-metadata.ts +168 -10
- package/src/tools/agent-harness-cli-command-policy.ts +110 -0
- package/src/tools/agent-harness-command-catalog.ts +4 -2
- package/src/tools/agent-harness-command-runner.ts +42 -0
- package/src/tools/agent-harness-connected-host-status.ts +7 -4
- package/src/tools/agent-harness-delegation-posture.ts +234 -19
- package/src/tools/agent-harness-device-live-read-models.ts +366 -0
- package/src/tools/agent-harness-document-ops-reviewer-readiness.ts +234 -0
- package/src/tools/agent-harness-document-ops-types.ts +72 -0
- package/src/tools/agent-harness-document-ops.ts +671 -0
- package/src/tools/agent-harness-execution-history.ts +489 -0
- package/src/tools/agent-harness-execution-posture.ts +385 -0
- package/src/tools/agent-harness-file-recovery.ts +135 -0
- package/src/tools/agent-harness-interactive-runtime-records.ts +421 -0
- package/src/tools/agent-harness-keybinding-metadata.ts +16 -12
- package/src/tools/agent-harness-learning-curator-common.ts +102 -0
- package/src/tools/agent-harness-learning-curator-consolidation.ts +295 -0
- package/src/tools/agent-harness-learning-curator-proposals.ts +606 -0
- package/src/tools/agent-harness-learning-curator-types.ts +151 -0
- package/src/tools/agent-harness-learning-curator.ts +417 -0
- package/src/tools/agent-harness-local-model-benchmarks.ts +269 -0
- package/src/tools/agent-harness-local-model-cookbook.ts +238 -0
- package/src/tools/agent-harness-local-model-endpoints.ts +788 -0
- package/src/tools/agent-harness-local-model-smoke.ts +277 -0
- package/src/tools/agent-harness-local-model-url.ts +78 -0
- package/src/tools/agent-harness-media-posture.ts +223 -2
- package/src/tools/agent-harness-memory-external-providers.ts +796 -0
- package/src/tools/agent-harness-memory-posture.ts +672 -0
- package/src/tools/agent-harness-memory-provider-certification.ts +219 -0
- package/src/tools/agent-harness-memory-refinement.ts +340 -0
- package/src/tools/agent-harness-metadata.ts +100 -168
- package/src/tools/agent-harness-mode-catalog.ts +86 -33
- package/src/tools/agent-harness-model-catalog.ts +162 -0
- package/src/tools/agent-harness-model-provider-health.ts +283 -0
- package/src/tools/agent-harness-model-readiness.ts +432 -0
- package/src/tools/agent-harness-model-routing-types.ts +327 -0
- package/src/tools/agent-harness-model-routing-utils.ts +30 -0
- package/src/tools/agent-harness-model-routing.ts +165 -193
- package/src/tools/agent-harness-operator-methods.ts +115 -133
- package/src/tools/agent-harness-pairing-posture.ts +452 -18
- package/src/tools/agent-harness-personal-ops-certification.ts +116 -0
- package/src/tools/agent-harness-personal-ops-discovery.ts +533 -0
- package/src/tools/agent-harness-personal-ops-intake.ts +385 -0
- package/src/tools/agent-harness-personal-ops-lanes.ts +270 -0
- package/src/tools/agent-harness-personal-ops-operations.ts +225 -0
- package/src/tools/agent-harness-personal-ops-provider-records.ts +358 -0
- package/src/tools/agent-harness-personal-ops-provider-task-records.ts +321 -0
- package/src/tools/agent-harness-personal-ops-records.ts +684 -0
- package/src/tools/agent-harness-personal-ops-runner.ts +637 -0
- package/src/tools/agent-harness-personal-ops-types.ts +240 -0
- package/src/tools/agent-harness-personal-ops.ts +613 -0
- package/src/tools/agent-harness-project-context.ts +144 -0
- package/src/tools/agent-harness-prompt-context.ts +589 -0
- package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
- package/src/tools/agent-harness-release-evidence.ts +9 -7
- package/src/tools/agent-harness-release-readiness.ts +9 -7
- package/src/tools/agent-harness-remote-read-models.ts +541 -0
- package/src/tools/agent-harness-research-briefing.ts +446 -0
- package/src/tools/agent-harness-research-live-read-models.ts +500 -0
- package/src/tools/agent-harness-research-queue.ts +250 -0
- package/src/tools/agent-harness-research-runs.ts +307 -0
- package/src/tools/agent-harness-research-workflow.ts +395 -0
- package/src/tools/agent-harness-security-posture.ts +2 -2
- package/src/tools/agent-harness-service-posture.ts +9 -9
- package/src/tools/agent-harness-session-metadata.ts +3 -3
- package/src/tools/agent-harness-setup-connected-host.ts +501 -0
- package/src/tools/agent-harness-setup-describe.ts +557 -0
- package/src/tools/agent-harness-setup-handoffs.ts +502 -0
- package/src/tools/agent-harness-setup-model-helpers.ts +102 -0
- package/src/tools/agent-harness-setup-plan.ts +253 -0
- package/src/tools/agent-harness-setup-posture-types.ts +218 -0
- package/src/tools/agent-harness-setup-posture-utils.ts +173 -0
- package/src/tools/agent-harness-setup-posture.ts +449 -221
- package/src/tools/agent-harness-setup-smoke.ts +533 -0
- package/src/tools/agent-harness-sudo-posture.ts +114 -0
- package/src/tools/agent-harness-tool-schema.ts +142 -7
- package/src/tools/agent-harness-tool-types.ts +83 -0
- package/src/tools/agent-harness-tool-utils.ts +43 -0
- package/src/tools/agent-harness-tool.ts +319 -370
- package/src/tools/agent-harness-ui-surface-metadata.ts +76 -69
- package/src/tools/agent-harness-ui-surface-types.ts +46 -0
- package/src/tools/agent-harness-vibe-health.ts +105 -0
- package/src/tools/agent-harness-workspace-action-runner.ts +149 -0
- package/src/tools/agent-harness-workspace-actions.ts +114 -8
- package/src/tools/agent-harness-workspace-editor-execution.ts +214 -0
- package/src/tools/agent-harness-workspace-editor-runner.ts +755 -0
- package/src/tools/agent-host-tool.ts +159 -0
- package/src/tools/agent-knowledge-ingest-tool.ts +34 -1
- package/src/tools/agent-learning-consolidation-core.ts +327 -0
- package/src/tools/agent-learning-consolidation-tool.ts +758 -0
- package/src/tools/agent-memory-tool.ts +253 -0
- package/src/tools/agent-model-compare-export.ts +315 -0
- package/src/tools/agent-model-compare-handoff.ts +592 -0
- package/src/tools/agent-model-compare-judgment.ts +633 -0
- package/src/tools/agent-model-compare-run.ts +735 -0
- package/src/tools/agent-model-compare-tool.ts +698 -0
- package/src/tools/agent-model-compare-types.ts +191 -0
- package/src/tools/agent-model-compare-utils.ts +93 -0
- package/src/tools/agent-models-tool.ts +208 -0
- package/src/tools/agent-operator-action-tool.ts +1 -1
- package/src/tools/agent-operator-method-tool.ts +643 -0
- package/src/tools/agent-personal-ops-tool.ts +197 -0
- package/src/tools/agent-policy-explanation.ts +415 -0
- package/src/tools/agent-research-report-tool.ts +608 -0
- package/src/tools/agent-research-runner.ts +367 -0
- package/src/tools/agent-research-runs-tool.ts +434 -0
- package/src/tools/agent-research-sources-tool.ts +443 -0
- package/src/tools/agent-research-tool.ts +515 -0
- package/src/tools/agent-review-packet-presets-core.ts +757 -0
- package/src/tools/agent-review-packet-presets-tool.ts +466 -0
- package/src/tools/agent-review-packet-share-tool.ts +305 -0
- package/src/tools/agent-route-planner-candidates-setup.ts +411 -0
- package/src/tools/agent-route-planner-candidates-surfaces.ts +432 -0
- package/src/tools/agent-route-planner-candidates-work.ts +251 -0
- package/src/tools/agent-route-planner-helpers.ts +667 -0
- package/src/tools/agent-route-planner.ts +185 -0
- package/src/tools/agent-route-tool.ts +105 -0
- package/src/tools/agent-schedule-edit-tool.ts +210 -0
- package/src/tools/agent-schedule-tool.ts +282 -0
- package/src/tools/agent-security-tool.ts +145 -0
- package/src/tools/agent-sessions-tool.ts +122 -0
- package/src/tools/agent-settings-import-tool.ts +104 -0
- package/src/tools/agent-settings-tool.ts +176 -0
- package/src/tools/agent-setup-tool.ts +226 -0
- package/src/tools/agent-support-tool.ts +122 -0
- package/src/tools/agent-terminal-process-tools.ts +167 -0
- package/src/tools/agent-tool-policy-guard-types.ts +77 -0
- package/src/tools/agent-tool-policy-guard.ts +106 -85
- package/src/tools/agent-vibe-tool.ts +297 -0
- package/src/tools/agent-work-plan-tool.ts +265 -6
- package/src/tools/agent-workspace-tool.ts +305 -0
- package/src/tools/artifact-archive.ts +169 -0
- package/src/tools/tool-definition-compaction.ts +36 -0
- package/src/version.ts +1 -1
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
|
|
2
|
+
import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
|
|
3
|
+
import type { CommandContext, CommandRegistry } from '../input/command-registry.ts';
|
|
4
|
+
import { createAgentHarnessTool } from './agent-harness-tool.ts';
|
|
5
|
+
|
|
6
|
+
type AgentHostAction =
|
|
7
|
+
| 'status'
|
|
8
|
+
| 'capabilities'
|
|
9
|
+
| 'capability'
|
|
10
|
+
| 'services'
|
|
11
|
+
| 'service'
|
|
12
|
+
| 'methods'
|
|
13
|
+
| 'method';
|
|
14
|
+
|
|
15
|
+
interface AgentHostToolArgs {
|
|
16
|
+
readonly action?: unknown;
|
|
17
|
+
readonly mode?: unknown;
|
|
18
|
+
readonly capabilityId?: unknown;
|
|
19
|
+
readonly endpointId?: unknown;
|
|
20
|
+
readonly methodId?: unknown;
|
|
21
|
+
readonly target?: unknown;
|
|
22
|
+
readonly query?: unknown;
|
|
23
|
+
readonly includeParameters?: unknown;
|
|
24
|
+
readonly limit?: unknown;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface AgentHostToolDeps {
|
|
28
|
+
readonly commandRegistry: CommandRegistry;
|
|
29
|
+
readonly commandContext: CommandContext;
|
|
30
|
+
readonly toolRegistry: ToolRegistry;
|
|
31
|
+
readonly harnessTool?: Tool;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function readString(value: unknown): string {
|
|
35
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function normalizeHostAction(value: unknown): AgentHostAction | null {
|
|
39
|
+
const action = readString(value).toLowerCase().replace(/-/g, '_');
|
|
40
|
+
if (!action) return null;
|
|
41
|
+
if (action === 'status' || action === 'health' || action === 'readiness' || action === 'daemon_status' || action === 'connected_host_status') return 'status';
|
|
42
|
+
if (action === 'capabilities' || action === 'capability_map' || action === 'map' || action === 'inventory' || action === 'connected_host' || action === 'daemon' || action === 'host' || action === 'boundaries') return 'capabilities';
|
|
43
|
+
if (action === 'capability' || action === 'show_capability' || action === 'inspect_capability' || action === 'connected_host_capability') return 'capability';
|
|
44
|
+
if (action === 'services' || action === 'service_posture' || action === 'service_status' || action === 'endpoints' || action === 'endpoint_list') return 'services';
|
|
45
|
+
if (action === 'service' || action === 'endpoint' || action === 'service_endpoint') return 'service';
|
|
46
|
+
if (action === 'methods' || action === 'operator_methods' || action === 'operator_contract' || action === 'operations' || action === 'actions') return 'methods';
|
|
47
|
+
if (action === 'method' || action === 'operator_method' || action === 'operation') return 'method';
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function readAction(args: AgentHostToolArgs): AgentHostAction {
|
|
52
|
+
const explicit = normalizeHostAction(args.action) ?? normalizeHostAction(args.mode);
|
|
53
|
+
if (explicit) return explicit;
|
|
54
|
+
if (readString(args.methodId)) return 'method';
|
|
55
|
+
if (readString(args.endpointId)) return 'service';
|
|
56
|
+
if (readString(args.capabilityId) || readString(args.target) || readString(args.query)) return 'capability';
|
|
57
|
+
return 'status';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function compactArgs(entries: Record<string, unknown>): Record<string, unknown> {
|
|
61
|
+
return Object.fromEntries(Object.entries(entries).filter(([, value]) => value !== undefined && value !== ''));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function createAgentHostTool(deps: AgentHostToolDeps): Tool {
|
|
65
|
+
const harnessTool = deps.harnessTool ?? createAgentHarnessTool({
|
|
66
|
+
commandRegistry: deps.commandRegistry,
|
|
67
|
+
commandContext: deps.commandContext,
|
|
68
|
+
toolRegistry: deps.toolRegistry,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
definition: {
|
|
73
|
+
name: 'host',
|
|
74
|
+
description: 'Inspect GoodVibes host status, services, and methods.',
|
|
75
|
+
parameters: {
|
|
76
|
+
type: 'object',
|
|
77
|
+
properties: {
|
|
78
|
+
action: {
|
|
79
|
+
type: 'string',
|
|
80
|
+
enum: ['status', 'capabilities', 'capability', 'services', 'service', 'methods', 'method'],
|
|
81
|
+
description: 'Read host status, capabilities, services, and method posture.',
|
|
82
|
+
},
|
|
83
|
+
mode: { type: 'string', description: 'Alias for action.' },
|
|
84
|
+
capabilityId: { type: 'string', description: 'Connected-host capability id.' },
|
|
85
|
+
endpointId: { type: 'string', description: 'Service endpoint id.' },
|
|
86
|
+
methodId: { type: 'string', description: 'Daemon operator method id.' },
|
|
87
|
+
target: { type: 'string', description: 'Lookup target for a capability, endpoint, or method.' },
|
|
88
|
+
query: { type: 'string', description: 'Search text for capabilities or methods.' },
|
|
89
|
+
includeParameters: { type: 'boolean', description: 'Include detailed method schemas, route families, probes, or diagnostics.' },
|
|
90
|
+
limit: { type: 'number', description: 'Maximum methods to return for action:methods.' },
|
|
91
|
+
},
|
|
92
|
+
additionalProperties: false,
|
|
93
|
+
},
|
|
94
|
+
sideEffects: [],
|
|
95
|
+
concurrency: 'parallel',
|
|
96
|
+
},
|
|
97
|
+
execute: async (rawArgs: unknown) => {
|
|
98
|
+
const args = (rawArgs && typeof rawArgs === 'object' && !Array.isArray(rawArgs) ? rawArgs : {}) as AgentHostToolArgs;
|
|
99
|
+
const action = readAction(args);
|
|
100
|
+
|
|
101
|
+
if (action === 'status') {
|
|
102
|
+
return harnessTool.execute(compactArgs({
|
|
103
|
+
mode: 'connected_host_status',
|
|
104
|
+
includeParameters: args.includeParameters,
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
if (action === 'capabilities') {
|
|
108
|
+
return harnessTool.execute(compactArgs({
|
|
109
|
+
mode: 'connected_host',
|
|
110
|
+
includeParameters: args.includeParameters,
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
if (action === 'capability') {
|
|
114
|
+
return harnessTool.execute(compactArgs({
|
|
115
|
+
mode: 'connected_host_capability',
|
|
116
|
+
capabilityId: args.capabilityId,
|
|
117
|
+
target: args.target,
|
|
118
|
+
query: args.query,
|
|
119
|
+
}));
|
|
120
|
+
}
|
|
121
|
+
if (action === 'services') {
|
|
122
|
+
return harnessTool.execute(compactArgs({
|
|
123
|
+
mode: 'service_posture',
|
|
124
|
+
includeParameters: args.includeParameters,
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
if (action === 'service') {
|
|
128
|
+
return harnessTool.execute(compactArgs({
|
|
129
|
+
mode: 'service_endpoint',
|
|
130
|
+
endpointId: args.endpointId,
|
|
131
|
+
target: args.target,
|
|
132
|
+
query: args.query,
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
if (action === 'methods') {
|
|
136
|
+
return harnessTool.execute(compactArgs({
|
|
137
|
+
mode: 'operator_methods',
|
|
138
|
+
query: args.query ?? args.target,
|
|
139
|
+
includeParameters: args.includeParameters,
|
|
140
|
+
limit: args.limit,
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
return harnessTool.execute(compactArgs({
|
|
144
|
+
mode: 'operator_method',
|
|
145
|
+
methodId: args.methodId,
|
|
146
|
+
target: args.target,
|
|
147
|
+
query: args.query,
|
|
148
|
+
}));
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function registerAgentHostTool(
|
|
154
|
+
registry: ToolRegistry,
|
|
155
|
+
commandRegistry: CommandRegistry,
|
|
156
|
+
commandContext: CommandContext,
|
|
157
|
+
): void {
|
|
158
|
+
if (!registry.has('host')) registry.register(createAgentHostTool({ commandRegistry, commandContext, toolRegistry: registry }));
|
|
159
|
+
}
|
|
@@ -14,6 +14,7 @@ import { formatBatchIngest, formatFailure, formatIngest } from '../cli/agent-kno
|
|
|
14
14
|
export type AgentKnowledgeIngestSourceKind =
|
|
15
15
|
| 'url'
|
|
16
16
|
| 'file'
|
|
17
|
+
| 'artifact'
|
|
17
18
|
| 'urls_file'
|
|
18
19
|
| 'bookmarks_file'
|
|
19
20
|
| 'browser_history'
|
|
@@ -23,6 +24,7 @@ export interface AgentKnowledgeIngestToolArgs {
|
|
|
23
24
|
readonly sourceKind?: unknown;
|
|
24
25
|
readonly url?: unknown;
|
|
25
26
|
readonly path?: unknown;
|
|
27
|
+
readonly artifactId?: unknown;
|
|
26
28
|
readonly title?: unknown;
|
|
27
29
|
readonly tags?: unknown;
|
|
28
30
|
readonly folderPath?: unknown;
|
|
@@ -44,6 +46,7 @@ type JsonRecord = Record<string, unknown>;
|
|
|
44
46
|
interface AgentKnowledgeIngestRequest {
|
|
45
47
|
readonly method: typeof AGENT_KNOWLEDGE_METHODS[keyof typeof AGENT_KNOWLEDGE_METHODS];
|
|
46
48
|
readonly target: string;
|
|
49
|
+
readonly targetLabel: string;
|
|
47
50
|
readonly label: string;
|
|
48
51
|
readonly payload: JsonRecord;
|
|
49
52
|
readonly batch: boolean;
|
|
@@ -52,6 +55,7 @@ interface AgentKnowledgeIngestRequest {
|
|
|
52
55
|
const SOURCE_KINDS: readonly AgentKnowledgeIngestSourceKind[] = [
|
|
53
56
|
'url',
|
|
54
57
|
'file',
|
|
58
|
+
'artifact',
|
|
55
59
|
'urls_file',
|
|
56
60
|
'bookmarks_file',
|
|
57
61
|
'browser_history',
|
|
@@ -161,6 +165,7 @@ function requestForArgs(args: AgentKnowledgeIngestToolArgs): AgentKnowledgeInges
|
|
|
161
165
|
return {
|
|
162
166
|
method: AGENT_KNOWLEDGE_METHODS.ingestUrl,
|
|
163
167
|
target: url,
|
|
168
|
+
targetLabel: 'url',
|
|
164
169
|
label: 'URL ingest',
|
|
165
170
|
batch: false,
|
|
166
171
|
payload: {
|
|
@@ -180,6 +185,7 @@ function requestForArgs(args: AgentKnowledgeIngestToolArgs): AgentKnowledgeInges
|
|
|
180
185
|
return {
|
|
181
186
|
method: AGENT_KNOWLEDGE_METHODS.ingestArtifact,
|
|
182
187
|
target: path,
|
|
188
|
+
targetLabel: 'file',
|
|
183
189
|
label: 'file ingest',
|
|
184
190
|
batch: false,
|
|
185
191
|
payload: {
|
|
@@ -194,6 +200,26 @@ function requestForArgs(args: AgentKnowledgeIngestToolArgs): AgentKnowledgeInges
|
|
|
194
200
|
};
|
|
195
201
|
}
|
|
196
202
|
|
|
203
|
+
if (sourceKind === 'artifact') {
|
|
204
|
+
const artifactId = readString(args.artifactId);
|
|
205
|
+
if (!artifactId) throw new Error('artifactId is required.');
|
|
206
|
+
return {
|
|
207
|
+
method: AGENT_KNOWLEDGE_METHODS.ingestArtifact,
|
|
208
|
+
target: artifactId,
|
|
209
|
+
targetLabel: 'artifact',
|
|
210
|
+
label: 'artifact ingest',
|
|
211
|
+
batch: false,
|
|
212
|
+
payload: {
|
|
213
|
+
artifactId,
|
|
214
|
+
title,
|
|
215
|
+
tags: [...tags],
|
|
216
|
+
folderPath: readOptionalString(args.folderPath),
|
|
217
|
+
connectorId: readOptionalString(args.connectorId) ?? 'goodvibes-agent-artifact-browser',
|
|
218
|
+
metadata: originMetadata,
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
197
223
|
if (sourceKind === 'urls_file' || sourceKind === 'bookmarks_file') {
|
|
198
224
|
const path = readString(args.path);
|
|
199
225
|
if (!path) throw new Error('path is required.');
|
|
@@ -201,6 +227,7 @@ function requestForArgs(args: AgentKnowledgeIngestToolArgs): AgentKnowledgeInges
|
|
|
201
227
|
return {
|
|
202
228
|
method,
|
|
203
229
|
target: path,
|
|
230
|
+
targetLabel: 'file',
|
|
204
231
|
label: sourceKind === 'urls_file' ? 'URL-list import' : 'bookmarks import',
|
|
205
232
|
batch: true,
|
|
206
233
|
payload: {
|
|
@@ -215,6 +242,7 @@ function requestForArgs(args: AgentKnowledgeIngestToolArgs): AgentKnowledgeInges
|
|
|
215
242
|
return {
|
|
216
243
|
method: AGENT_KNOWLEDGE_METHODS.ingestBrowserHistory,
|
|
217
244
|
target: 'local browser history',
|
|
245
|
+
targetLabel: 'source',
|
|
218
246
|
label: 'browser-history import',
|
|
219
247
|
batch: true,
|
|
220
248
|
payload: {
|
|
@@ -240,6 +268,7 @@ function requestForArgs(args: AgentKnowledgeIngestToolArgs): AgentKnowledgeInges
|
|
|
240
268
|
return {
|
|
241
269
|
method: AGENT_KNOWLEDGE_METHODS.ingestConnector,
|
|
242
270
|
target: connectorId,
|
|
271
|
+
targetLabel: 'connector',
|
|
243
272
|
label: 'connector ingest',
|
|
244
273
|
batch: true,
|
|
245
274
|
payload: {
|
|
@@ -278,6 +307,10 @@ export function createAgentKnowledgeIngestTool(
|
|
|
278
307
|
type: 'string',
|
|
279
308
|
description: 'Local file or import path.',
|
|
280
309
|
},
|
|
310
|
+
artifactId: {
|
|
311
|
+
type: 'string',
|
|
312
|
+
description: 'Saved artifact id when sourceKind is artifact.',
|
|
313
|
+
},
|
|
281
314
|
title: {
|
|
282
315
|
type: 'string',
|
|
283
316
|
description: 'Optional source title for url or file ingest.',
|
|
@@ -381,7 +414,7 @@ export function createAgentKnowledgeIngestTool(
|
|
|
381
414
|
request.target,
|
|
382
415
|
request.label,
|
|
383
416
|
request.method.route,
|
|
384
|
-
request.
|
|
417
|
+
request.targetLabel,
|
|
385
418
|
));
|
|
386
419
|
} catch (error) {
|
|
387
420
|
return failure(formatKnowledgeFailure(await classifyKnowledgeError(error, connection, request.method.route)));
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
|
|
4
|
+
import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
|
|
5
|
+
import type { MemoryBundle, MemoryRecord, MemoryRegistry } from '@pellux/goodvibes-sdk/platform/state';
|
|
6
|
+
import type { ShellPathService } from '@/runtime/index.ts';
|
|
7
|
+
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
8
|
+
import type { CommandContext } from '../input/command-registry.ts';
|
|
9
|
+
import { AgentPersonaRegistry, type AgentPersonaRecord } from '../agent/persona-registry.ts';
|
|
10
|
+
import { AgentRoutineRegistry, type AgentRoutineRecord } from '../agent/routine-registry.ts';
|
|
11
|
+
import { AgentSkillRegistry, type AgentSkillRecord } from '../agent/skill-registry.ts';
|
|
12
|
+
import {
|
|
13
|
+
resolveLearningConsolidationCandidate,
|
|
14
|
+
type LearningCandidate,
|
|
15
|
+
type LearningConsolidationFields,
|
|
16
|
+
} from './agent-harness-learning-curator.ts';
|
|
17
|
+
|
|
18
|
+
export type AgentLearningConsolidationMode = 'preview' | 'merge' | 'stale' | 'delete' | 'rollback' | 'recreate' | 'receipts';
|
|
19
|
+
export type AgentLearningConsolidationDomain = 'memory' | 'persona' | 'skill' | 'routine';
|
|
20
|
+
export type AgentLearningConsolidationWriteMode = 'merge' | 'stale' | 'delete' | 'rollback' | 'recreate';
|
|
21
|
+
|
|
22
|
+
export interface AgentLearningConsolidationToolArgs {
|
|
23
|
+
readonly mode?: unknown;
|
|
24
|
+
readonly candidateId?: unknown;
|
|
25
|
+
readonly query?: unknown;
|
|
26
|
+
readonly receiptId?: unknown;
|
|
27
|
+
readonly limit?: unknown;
|
|
28
|
+
readonly confirm?: unknown;
|
|
29
|
+
readonly explicitUserRequest?: unknown;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface LearningConsolidationReceipt {
|
|
33
|
+
readonly id: string;
|
|
34
|
+
readonly createdAt: string;
|
|
35
|
+
readonly domain: AgentLearningConsolidationDomain;
|
|
36
|
+
readonly candidateId: string;
|
|
37
|
+
readonly phase: AgentLearningConsolidationWriteMode;
|
|
38
|
+
readonly explicitUserRequest: string;
|
|
39
|
+
readonly survivorId: string;
|
|
40
|
+
readonly duplicateIds: readonly string[];
|
|
41
|
+
readonly beforeSurvivor?: Record<string, unknown>;
|
|
42
|
+
readonly beforeDuplicates: readonly Record<string, unknown>[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface LearningConsolidationReceiptFile {
|
|
46
|
+
readonly version: 1;
|
|
47
|
+
readonly receipts: readonly LearningConsolidationReceipt[];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const MODES: readonly AgentLearningConsolidationMode[] = ['preview', 'merge', 'stale', 'delete', 'rollback', 'recreate', 'receipts'];
|
|
51
|
+
export const WRITE_MODES = new Set<AgentLearningConsolidationMode>(['merge', 'stale', 'delete', 'rollback', 'recreate']);
|
|
52
|
+
export const RECEIPT_LIMIT = 100;
|
|
53
|
+
export const MEMORY_CLASSES = new Set(['decision', 'constraint', 'incident', 'pattern', 'fact', 'risk', 'runbook', 'architecture', 'ownership']);
|
|
54
|
+
export const MEMORY_SCOPES = new Set(['session', 'project', 'team']);
|
|
55
|
+
export const MEMORY_REVIEW_STATES = new Set(['fresh', 'reviewed', 'stale', 'contradicted']);
|
|
56
|
+
|
|
57
|
+
export function readString(value: unknown): string {
|
|
58
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function readMode(value: unknown): AgentLearningConsolidationMode {
|
|
62
|
+
return typeof value === 'string' && MODES.includes(value as AgentLearningConsolidationMode)
|
|
63
|
+
? value as AgentLearningConsolidationMode
|
|
64
|
+
: 'preview';
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function readLimit(value: unknown, fallback: number): number {
|
|
68
|
+
const parsed = typeof value === 'string' && value.trim() ? Number(value) : value;
|
|
69
|
+
if (typeof parsed !== 'number' || !Number.isFinite(parsed)) return fallback;
|
|
70
|
+
return Math.max(1, Math.min(RECEIPT_LIMIT, Math.trunc(parsed)));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function slugifyForDomain(value: string, fallback: AgentLearningConsolidationDomain): string {
|
|
74
|
+
const slug = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
|
75
|
+
return slug || fallback;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function nextGeneratedId(name: string, occupiedIds: Set<string>, fallback: AgentLearningConsolidationDomain): string {
|
|
79
|
+
const base = slugifyForDomain(name, fallback);
|
|
80
|
+
if (!occupiedIds.has(base)) return base;
|
|
81
|
+
for (let index = 2; index < 1000; index += 1) {
|
|
82
|
+
const candidate = `${base}-${index}`;
|
|
83
|
+
if (!occupiedIds.has(candidate)) return candidate;
|
|
84
|
+
}
|
|
85
|
+
throw new Error(`Could not allocate ${fallback} id for ${name}.`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function output(value: unknown): { readonly success: true; readonly output: string } {
|
|
89
|
+
return { success: true, output: JSON.stringify(value, null, 2) };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function failure(error: string): { readonly success: false; readonly error: string } {
|
|
93
|
+
return { success: false, error };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function requireConfirmedWrite(args: AgentLearningConsolidationToolArgs, mode: AgentLearningConsolidationWriteMode): string {
|
|
97
|
+
const explicitUserRequest = readString(args.explicitUserRequest);
|
|
98
|
+
if (!explicitUserRequest) throw new Error(`${mode} requires explicitUserRequest with the user's exact request or a short faithful summary.`);
|
|
99
|
+
if (args.confirm !== true) throw new Error(`${mode} requires confirm:true after an explicit user request.`);
|
|
100
|
+
return explicitUserRequest;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function isDomain(value: string): value is AgentLearningConsolidationDomain {
|
|
104
|
+
return value === 'memory' || value === 'persona' || value === 'skill' || value === 'routine';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function receiptPath(shellPaths: ShellPathService): string {
|
|
108
|
+
return shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, 'learning', 'consolidation-receipts.json');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function parseReceipt(value: unknown): LearningConsolidationReceipt | null {
|
|
112
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
|
|
113
|
+
const record = value as Record<string, unknown>;
|
|
114
|
+
const id = readString(record.id);
|
|
115
|
+
const createdAt = readString(record.createdAt);
|
|
116
|
+
const domain = readString(record.domain);
|
|
117
|
+
const candidateId = readString(record.candidateId);
|
|
118
|
+
const phase = readString(record.phase);
|
|
119
|
+
const explicitUserRequest = readString(record.explicitUserRequest);
|
|
120
|
+
const survivorId = readString(record.survivorId);
|
|
121
|
+
const duplicateIds = Array.isArray(record.duplicateIds)
|
|
122
|
+
? record.duplicateIds.filter((entry): entry is string => typeof entry === 'string')
|
|
123
|
+
: [];
|
|
124
|
+
const beforeDuplicates = Array.isArray(record.beforeDuplicates)
|
|
125
|
+
? record.beforeDuplicates.filter((entry): entry is Record<string, unknown> => typeof entry === 'object' && entry !== null && !Array.isArray(entry))
|
|
126
|
+
: [];
|
|
127
|
+
if (
|
|
128
|
+
!id
|
|
129
|
+
|| !createdAt
|
|
130
|
+
|| !isDomain(domain)
|
|
131
|
+
|| !candidateId
|
|
132
|
+
|| !['merge', 'stale', 'delete', 'rollback', 'recreate'].includes(phase)
|
|
133
|
+
|| !explicitUserRequest
|
|
134
|
+
|| !survivorId
|
|
135
|
+
) return null;
|
|
136
|
+
const beforeSurvivor = typeof record.beforeSurvivor === 'object' && record.beforeSurvivor !== null && !Array.isArray(record.beforeSurvivor)
|
|
137
|
+
? record.beforeSurvivor as Record<string, unknown>
|
|
138
|
+
: undefined;
|
|
139
|
+
return {
|
|
140
|
+
id,
|
|
141
|
+
createdAt,
|
|
142
|
+
domain,
|
|
143
|
+
candidateId,
|
|
144
|
+
phase: phase as AgentLearningConsolidationWriteMode,
|
|
145
|
+
explicitUserRequest,
|
|
146
|
+
survivorId,
|
|
147
|
+
duplicateIds,
|
|
148
|
+
...(beforeSurvivor ? { beforeSurvivor } : {}),
|
|
149
|
+
beforeDuplicates,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function readReceiptFile(shellPaths: ShellPathService): LearningConsolidationReceiptFile {
|
|
154
|
+
const path = receiptPath(shellPaths);
|
|
155
|
+
if (!existsSync(path)) return { version: 1, receipts: [] };
|
|
156
|
+
try {
|
|
157
|
+
const parsed: unknown = JSON.parse(readFileSync(path, 'utf-8'));
|
|
158
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return { version: 1, receipts: [] };
|
|
159
|
+
const receipts = Array.isArray((parsed as Record<string, unknown>).receipts)
|
|
160
|
+
? ((parsed as Record<string, unknown>).receipts as unknown[]).map(parseReceipt).filter((entry): entry is LearningConsolidationReceipt => entry !== null)
|
|
161
|
+
: [];
|
|
162
|
+
return { version: 1, receipts };
|
|
163
|
+
} catch {
|
|
164
|
+
return { version: 1, receipts: [] };
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function writeReceipt(shellPaths: ShellPathService, receipt: LearningConsolidationReceipt): void {
|
|
169
|
+
const path = receiptPath(shellPaths);
|
|
170
|
+
const current = readReceiptFile(shellPaths).receipts;
|
|
171
|
+
const next: LearningConsolidationReceiptFile = {
|
|
172
|
+
version: 1,
|
|
173
|
+
receipts: [receipt, ...current.filter((entry) => entry.id !== receipt.id)].slice(0, RECEIPT_LIMIT),
|
|
174
|
+
};
|
|
175
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
176
|
+
const tmpPath = `${path}.tmp`;
|
|
177
|
+
writeFileSync(tmpPath, `${JSON.stringify(next, null, 2)}\n`, 'utf-8');
|
|
178
|
+
renameSync(tmpPath, path);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function receiptId(candidate: LearningCandidate, phase: AgentLearningConsolidationWriteMode): string {
|
|
182
|
+
const slug = candidate.id.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 48) || 'candidate';
|
|
183
|
+
return `lcon-${phase}-${Date.now().toString(36)}-${slug}`;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function receiptIdFromReceipt(receipt: LearningConsolidationReceipt, phase: AgentLearningConsolidationWriteMode): string {
|
|
187
|
+
const slug = receipt.candidateId.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 48) || 'receipt';
|
|
188
|
+
return `lcon-${phase}-${Date.now().toString(36)}-${slug}`;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function minimalContext(shellPaths: ShellPathService, memoryRegistry: MemoryRegistry): CommandContext {
|
|
192
|
+
return {
|
|
193
|
+
workspace: { shellPaths },
|
|
194
|
+
clients: { agentKnowledgeApi: { memory: memoryRegistry } },
|
|
195
|
+
} as unknown as CommandContext;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function resolveCandidate(
|
|
199
|
+
shellPaths: ShellPathService,
|
|
200
|
+
memoryRegistry: MemoryRegistry,
|
|
201
|
+
args: AgentLearningConsolidationToolArgs,
|
|
202
|
+
): LearningCandidate {
|
|
203
|
+
const input = readString(args.candidateId) || readString(args.query);
|
|
204
|
+
const resolved = resolveLearningConsolidationCandidate(minimalContext(shellPaths, memoryRegistry), input);
|
|
205
|
+
if (resolved.status === 'found') return resolved.candidate;
|
|
206
|
+
if (resolved.status === 'ambiguous') {
|
|
207
|
+
throw new Error(`Ambiguous learning consolidation candidate ${resolved.input}. Candidates: ${JSON.stringify(resolved.candidates)}`);
|
|
208
|
+
}
|
|
209
|
+
throw new Error(resolved.usage);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function domainForCandidate(candidate: LearningCandidate): AgentLearningConsolidationDomain {
|
|
213
|
+
const domain = String(candidate.domain);
|
|
214
|
+
if (!isDomain(domain)) throw new Error(`Candidate ${candidate.id} is not an applyable consolidation domain.`);
|
|
215
|
+
return domain;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function cloneRecord(record: unknown): Record<string, unknown> {
|
|
219
|
+
return JSON.parse(JSON.stringify(record)) as Record<string, unknown>;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function getRecord(
|
|
223
|
+
shellPaths: ShellPathService,
|
|
224
|
+
memoryRegistry: MemoryRegistry,
|
|
225
|
+
domain: AgentLearningConsolidationDomain,
|
|
226
|
+
id: string,
|
|
227
|
+
): MemoryRecord | AgentPersonaRecord | AgentSkillRecord | AgentRoutineRecord {
|
|
228
|
+
if (domain === 'memory') {
|
|
229
|
+
const record = memoryRegistry.get(id);
|
|
230
|
+
if (!record) throw new Error(`Unknown Agent-local memory ${id}`);
|
|
231
|
+
return record;
|
|
232
|
+
}
|
|
233
|
+
if (domain === 'persona') {
|
|
234
|
+
const record = AgentPersonaRegistry.fromShellPaths(shellPaths).get(id);
|
|
235
|
+
if (!record) throw new Error(`Unknown Agent-local persona ${id}`);
|
|
236
|
+
return record;
|
|
237
|
+
}
|
|
238
|
+
if (domain === 'skill') {
|
|
239
|
+
const record = AgentSkillRegistry.fromShellPaths(shellPaths).get(id);
|
|
240
|
+
if (!record) throw new Error(`Unknown Agent-local skill ${id}`);
|
|
241
|
+
return record;
|
|
242
|
+
}
|
|
243
|
+
const record = AgentRoutineRegistry.fromShellPaths(shellPaths).get(id);
|
|
244
|
+
if (!record) throw new Error(`Unknown Agent-local routine ${id}`);
|
|
245
|
+
return record;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function updateSurvivor(
|
|
249
|
+
shellPaths: ShellPathService,
|
|
250
|
+
memoryRegistry: MemoryRegistry,
|
|
251
|
+
domain: AgentLearningConsolidationDomain,
|
|
252
|
+
survivorId: string,
|
|
253
|
+
fields: LearningConsolidationFields,
|
|
254
|
+
): Record<string, unknown> {
|
|
255
|
+
if (domain === 'memory') {
|
|
256
|
+
const record = memoryRegistry.update(survivorId, {
|
|
257
|
+
...(fields.detail === undefined ? {} : { detail: fields.detail }),
|
|
258
|
+
...(fields.tags === undefined ? {} : { tags: [...fields.tags] }),
|
|
259
|
+
});
|
|
260
|
+
if (!record) throw new Error(`Unknown Agent-local memory ${survivorId}`);
|
|
261
|
+
return cloneRecord(record);
|
|
262
|
+
}
|
|
263
|
+
if (domain === 'persona') {
|
|
264
|
+
const record = AgentPersonaRegistry.fromShellPaths(shellPaths).update(survivorId, {
|
|
265
|
+
...(fields.description === undefined ? {} : { description: fields.description }),
|
|
266
|
+
...(fields.tags === undefined ? {} : { tags: [...fields.tags] }),
|
|
267
|
+
...(fields.triggers === undefined ? {} : { triggers: [...fields.triggers] }),
|
|
268
|
+
provenance: 'learning-curator-consolidation',
|
|
269
|
+
});
|
|
270
|
+
return cloneRecord(record);
|
|
271
|
+
}
|
|
272
|
+
if (domain === 'skill') {
|
|
273
|
+
const record = AgentSkillRegistry.fromShellPaths(shellPaths).update(survivorId, {
|
|
274
|
+
...(fields.description === undefined ? {} : { description: fields.description }),
|
|
275
|
+
...(fields.tags === undefined ? {} : { tags: [...fields.tags] }),
|
|
276
|
+
...(fields.triggers === undefined ? {} : { triggers: [...fields.triggers] }),
|
|
277
|
+
provenance: 'learning-curator-consolidation',
|
|
278
|
+
});
|
|
279
|
+
return cloneRecord(record);
|
|
280
|
+
}
|
|
281
|
+
const record = AgentRoutineRegistry.fromShellPaths(shellPaths).update(survivorId, {
|
|
282
|
+
...(fields.description === undefined ? {} : { description: fields.description }),
|
|
283
|
+
...(fields.tags === undefined ? {} : { tags: [...fields.tags] }),
|
|
284
|
+
...(fields.triggers === undefined ? {} : { triggers: [...fields.triggers] }),
|
|
285
|
+
provenance: 'learning-curator-consolidation',
|
|
286
|
+
});
|
|
287
|
+
return cloneRecord(record);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export function markDuplicateStale(
|
|
291
|
+
shellPaths: ShellPathService,
|
|
292
|
+
memoryRegistry: MemoryRegistry,
|
|
293
|
+
domain: AgentLearningConsolidationDomain,
|
|
294
|
+
duplicateId: string,
|
|
295
|
+
survivorId: string,
|
|
296
|
+
): Record<string, unknown> {
|
|
297
|
+
const reason = `Duplicate of ${survivorId}; staged by learning curator consolidation.`;
|
|
298
|
+
if (domain === 'memory') {
|
|
299
|
+
const record = memoryRegistry.review(duplicateId, { state: 'stale', staleReason: reason, reviewedBy: 'agent' });
|
|
300
|
+
if (!record) throw new Error(`Unknown Agent-local memory ${duplicateId}`);
|
|
301
|
+
return cloneRecord(record);
|
|
302
|
+
}
|
|
303
|
+
if (domain === 'persona') return cloneRecord(AgentPersonaRegistry.fromShellPaths(shellPaths).markStale(duplicateId, reason));
|
|
304
|
+
if (domain === 'skill') return cloneRecord(AgentSkillRegistry.fromShellPaths(shellPaths).markStale(duplicateId, reason));
|
|
305
|
+
return cloneRecord(AgentRoutineRegistry.fromShellPaths(shellPaths).markStale(duplicateId, reason));
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export function deleteDuplicate(
|
|
309
|
+
shellPaths: ShellPathService,
|
|
310
|
+
memoryRegistry: MemoryRegistry,
|
|
311
|
+
domain: AgentLearningConsolidationDomain,
|
|
312
|
+
duplicateId: string,
|
|
313
|
+
): void {
|
|
314
|
+
if (domain === 'memory') {
|
|
315
|
+
if (!memoryRegistry.delete(duplicateId)) throw new Error(`Unknown Agent-local memory ${duplicateId}`);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (domain === 'persona') {
|
|
319
|
+
AgentPersonaRegistry.fromShellPaths(shellPaths).deletePersona(duplicateId);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
if (domain === 'skill') {
|
|
323
|
+
AgentSkillRegistry.fromShellPaths(shellPaths).deleteSkill(duplicateId);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
AgentRoutineRegistry.fromShellPaths(shellPaths).deleteRoutine(duplicateId);
|
|
327
|
+
}
|