@pellux/goodvibes-agent 1.1.6 → 1.2.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 +176 -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 +132662 -91399
- 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 +56 -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 +114 -45
- package/docs/voice-and-live-tts.md +3 -1
- package/package.json +3 -2
- package/release/release-notes.md +130 -5
- package/release/release-readiness.json +120 -90
- 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 +296 -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-checkpoint.ts +140 -0
- package/src/agent/setup-wizard.ts +447 -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 +262 -30
- package/src/input/agent-workspace-setup-checkpoint-action.ts +127 -0
- package/src/input/agent-workspace-setup-snapshot.ts +198 -0
- package/src/input/agent-workspace-setup.ts +34 -1
- package/src/input/agent-workspace-snapshot.ts +162 -147
- package/src/input/agent-workspace-types.ts +287 -2
- package/src/input/agent-workspace.ts +18 -0
- 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/main.ts +15 -15
- package/src/panels/qr-panel.ts +2 -2
- package/src/renderer/agent-workspace-context-lines.ts +686 -0
- package/src/renderer/agent-workspace.ts +30 -419
- 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 +43 -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 +287 -0
- 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 +267 -10
- 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.ts +703 -0
- package/src/tools/agent-harness-autonomy-intake.ts +785 -0
- package/src/tools/agent-harness-autonomy-live-records.ts +588 -0
- package/src/tools/agent-harness-autonomy-queue-types.ts +88 -0
- package/src/tools/agent-harness-autonomy-queue.ts +560 -0
- package/src/tools/agent-harness-background-processes-types.ts +35 -0
- package/src/tools/agent-harness-background-processes.ts +794 -0
- package/src/tools/agent-harness-browser-cockpit-route.ts +219 -0
- package/src/tools/agent-harness-browser-control.ts +338 -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-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 +382 -0
- package/src/tools/agent-harness-file-recovery.ts +135 -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 +199 -0
- package/src/tools/agent-harness-local-model-cookbook.ts +238 -0
- package/src/tools/agent-harness-local-model-endpoints.ts +673 -0
- package/src/tools/agent-harness-media-posture.ts +208 -2
- package/src/tools/agent-harness-memory-posture.ts +556 -0
- package/src/tools/agent-harness-metadata.ts +100 -168
- package/src/tools/agent-harness-mode-catalog.ts +84 -33
- package/src/tools/agent-harness-model-catalog.ts +162 -0
- package/src/tools/agent-harness-model-provider-health.ts +186 -0
- package/src/tools/agent-harness-model-readiness.ts +406 -0
- package/src/tools/agent-harness-model-routing-types.ts +266 -0
- package/src/tools/agent-harness-model-routing-utils.ts +30 -0
- package/src/tools/agent-harness-model-routing.ts +137 -190
- package/src/tools/agent-harness-operator-methods.ts +115 -133
- package/src/tools/agent-harness-pairing-posture.ts +431 -18
- 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 +204 -0
- package/src/tools/agent-harness-personal-ops-records.ts +732 -0
- package/src/tools/agent-harness-personal-ops-runner.ts +637 -0
- package/src/tools/agent-harness-personal-ops-types.ts +222 -0
- package/src/tools/agent-harness-personal-ops.ts +606 -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-research-briefing.ts +427 -0
- package/src/tools/agent-harness-research-queue.ts +250 -0
- package/src/tools/agent-harness-research-runs.ts +295 -0
- package/src/tools/agent-harness-research-workflow.ts +322 -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 +101 -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 +508 -0
- package/src/tools/agent-harness-sudo-posture.ts +114 -0
- package/src/tools/agent-harness-tool-schema.ts +120 -7
- package/src/tools/agent-harness-tool-types.ts +78 -0
- package/src/tools/agent-harness-tool-utils.ts +43 -0
- package/src/tools/agent-harness-tool.ts +311 -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 +214 -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 +722 -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-runs-tool.ts +434 -0
- package/src/tools/agent-research-sources-tool.ts +443 -0
- package/src/tools/agent-research-tool.ts +687 -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 +110 -89
- 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/tools/tool-execution-safety.ts +41 -0
- package/src/version.ts +1 -1
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import type { RuntimeEventBus, ToolEvent } from '@/runtime/index.ts';
|
|
2
|
+
|
|
3
|
+
export type AgentExecutionStatus = 'running' | 'succeeded' | 'failed' | 'cancelled';
|
|
4
|
+
export type AgentExecutionRouteKind = 'read' | 'write' | 'shell' | 'network' | 'browser' | 'delegation' | 'other';
|
|
5
|
+
|
|
6
|
+
export interface AgentExecutionResultSummary {
|
|
7
|
+
readonly kind: string;
|
|
8
|
+
readonly byteSize: number;
|
|
9
|
+
readonly preview?: string | undefined;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface AgentExecutionRecord {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly callId: string;
|
|
15
|
+
readonly turnId: string;
|
|
16
|
+
readonly tool: string;
|
|
17
|
+
readonly routeKind: AgentExecutionRouteKind;
|
|
18
|
+
readonly status: AgentExecutionStatus;
|
|
19
|
+
readonly phase: ToolEvent['type'];
|
|
20
|
+
readonly receivedAt: number;
|
|
21
|
+
readonly updatedAt: number;
|
|
22
|
+
readonly completedAt?: number | undefined;
|
|
23
|
+
readonly durationMs?: number | undefined;
|
|
24
|
+
readonly permissionApproved?: boolean | undefined;
|
|
25
|
+
readonly argsPreview: string;
|
|
26
|
+
readonly argsKeys: readonly string[];
|
|
27
|
+
readonly commandPreview?: string | undefined;
|
|
28
|
+
readonly targetPreview?: string | undefined;
|
|
29
|
+
readonly resultSummary?: AgentExecutionResultSummary | undefined;
|
|
30
|
+
readonly error?: string | undefined;
|
|
31
|
+
readonly cancelReason?: string | undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface MutableAgentExecutionRecord {
|
|
35
|
+
id: string;
|
|
36
|
+
callId: string;
|
|
37
|
+
turnId: string;
|
|
38
|
+
tool: string;
|
|
39
|
+
routeKind: AgentExecutionRouteKind;
|
|
40
|
+
status: AgentExecutionStatus;
|
|
41
|
+
phase: ToolEvent['type'];
|
|
42
|
+
receivedAt: number;
|
|
43
|
+
updatedAt: number;
|
|
44
|
+
completedAt?: number | undefined;
|
|
45
|
+
durationMs?: number | undefined;
|
|
46
|
+
permissionApproved?: boolean | undefined;
|
|
47
|
+
argsPreview: string;
|
|
48
|
+
argsKeys: readonly string[];
|
|
49
|
+
commandPreview?: string | undefined;
|
|
50
|
+
targetPreview?: string | undefined;
|
|
51
|
+
resultSummary?: AgentExecutionResultSummary | undefined;
|
|
52
|
+
error?: string | undefined;
|
|
53
|
+
cancelReason?: string | undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface AgentExecutionLedgerSnapshot {
|
|
57
|
+
readonly records: readonly AgentExecutionRecord[];
|
|
58
|
+
readonly total: number;
|
|
59
|
+
readonly running: number;
|
|
60
|
+
readonly succeeded: number;
|
|
61
|
+
readonly failed: number;
|
|
62
|
+
readonly cancelled: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const DEFAULT_LIMIT = 500;
|
|
66
|
+
const SECRET_KEY_PATTERN = /(?:api[_-]?key|authorization|bearer|client[_-]?secret|password|secret|token)/i;
|
|
67
|
+
|
|
68
|
+
function truncateText(value: string, max = 220): string {
|
|
69
|
+
const compact = value.replace(/\s+/g, ' ').trim();
|
|
70
|
+
return compact.length > max ? `${compact.slice(0, Math.max(0, max - 1))}...` : compact;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function redactValue(value: unknown, depth = 0): unknown {
|
|
74
|
+
if (depth > 3) return '[truncated]';
|
|
75
|
+
if (typeof value === 'string') return truncateText(value);
|
|
76
|
+
if (typeof value === 'number' || typeof value === 'boolean' || value === null) return value;
|
|
77
|
+
if (Array.isArray(value)) return value.slice(0, 8).map((entry) => redactValue(entry, depth + 1));
|
|
78
|
+
if (!value || typeof value !== 'object') return String(value);
|
|
79
|
+
const entries = Object.entries(value as Record<string, unknown>).slice(0, 16).map(([key, entry]) => (
|
|
80
|
+
[key, SECRET_KEY_PATTERN.test(key) ? '[redacted]' : redactValue(entry, depth + 1)] as const
|
|
81
|
+
));
|
|
82
|
+
return Object.fromEntries(entries);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function argsPreview(args: Record<string, unknown>): string {
|
|
86
|
+
try {
|
|
87
|
+
return truncateText(JSON.stringify(redactValue(args)), 360);
|
|
88
|
+
} catch {
|
|
89
|
+
return '[unserializable args]';
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function stringArg(args: Record<string, unknown>, keys: readonly string[]): string | undefined {
|
|
94
|
+
for (const key of keys) {
|
|
95
|
+
const value = args[key];
|
|
96
|
+
if (typeof value === 'string' && value.trim()) return truncateText(value, 180);
|
|
97
|
+
}
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function routeKindForTool(tool: string, args: Record<string, unknown>): AgentExecutionRouteKind {
|
|
102
|
+
const name = tool.toLowerCase();
|
|
103
|
+
if (name.includes('browser') || name.includes('desktop') || name.includes('screenshot')) return 'browser';
|
|
104
|
+
if (name.includes('delegate') || name.includes('agent')) return 'delegation';
|
|
105
|
+
if (name.includes('exec') || name.includes('shell') || name.includes('bash') || typeof args.command === 'string') return 'shell';
|
|
106
|
+
if (name.includes('write') || name.includes('edit') || name.includes('patch') || name.includes('delete')) return 'write';
|
|
107
|
+
if (name.includes('fetch') || name.includes('web') || name.includes('http') || name.includes('url')) return 'network';
|
|
108
|
+
if (name.includes('read') || name.includes('find') || name.includes('inspect') || name.includes('grep') || name.includes('search')) return 'read';
|
|
109
|
+
return 'other';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function statusForPhase(phase: ToolEvent['type']): AgentExecutionStatus {
|
|
113
|
+
if (phase === 'TOOL_SUCCEEDED') return 'succeeded';
|
|
114
|
+
if (phase === 'TOOL_FAILED') return 'failed';
|
|
115
|
+
if (phase === 'TOOL_CANCELLED') return 'cancelled';
|
|
116
|
+
return 'running';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function resultSummaryFrom(value: Extract<ToolEvent, { type: 'TOOL_SUCCEEDED' | 'TOOL_FAILED' }>['result']): AgentExecutionResultSummary | undefined {
|
|
120
|
+
if (!value) return undefined;
|
|
121
|
+
return {
|
|
122
|
+
kind: value.kind,
|
|
123
|
+
byteSize: value.byteSize,
|
|
124
|
+
...(typeof value.preview === 'string' && value.preview.trim() ? { preview: truncateText(value.preview, 220) } : {}),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function immutable(record: MutableAgentExecutionRecord): AgentExecutionRecord {
|
|
129
|
+
return { ...record };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export class AgentExecutionLedger {
|
|
133
|
+
private readonly records = new Map<string, MutableAgentExecutionRecord>();
|
|
134
|
+
private readonly order: string[] = [];
|
|
135
|
+
private readonly subscribers = new Set<() => void>();
|
|
136
|
+
private readonly unsubscribe: () => void;
|
|
137
|
+
|
|
138
|
+
public constructor(
|
|
139
|
+
runtimeBus: RuntimeEventBus,
|
|
140
|
+
private readonly limit: number = DEFAULT_LIMIT,
|
|
141
|
+
) {
|
|
142
|
+
this.unsubscribe = runtimeBus.onDomain('tools', (envelope) => {
|
|
143
|
+
this.handleToolEvent(envelope.payload as ToolEvent, envelope.ts);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public getSnapshot(): AgentExecutionLedgerSnapshot {
|
|
148
|
+
const records = this.order
|
|
149
|
+
.map((id) => this.records.get(id))
|
|
150
|
+
.filter((record): record is MutableAgentExecutionRecord => record !== undefined)
|
|
151
|
+
.map(immutable)
|
|
152
|
+
.reverse();
|
|
153
|
+
return {
|
|
154
|
+
records,
|
|
155
|
+
total: records.length,
|
|
156
|
+
running: records.filter((record) => record.status === 'running').length,
|
|
157
|
+
succeeded: records.filter((record) => record.status === 'succeeded').length,
|
|
158
|
+
failed: records.filter((record) => record.status === 'failed').length,
|
|
159
|
+
cancelled: records.filter((record) => record.status === 'cancelled').length,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
public subscribe(callback: () => void): () => void {
|
|
164
|
+
this.subscribers.add(callback);
|
|
165
|
+
return () => this.subscribers.delete(callback);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public dispose(): void {
|
|
169
|
+
this.unsubscribe();
|
|
170
|
+
this.subscribers.clear();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private handleToolEvent(event: ToolEvent, timestamp: number): void {
|
|
174
|
+
if (!('callId' in event)) return;
|
|
175
|
+
if (event.type === 'TOOL_RECEIVED') {
|
|
176
|
+
this.recordReceived(event, timestamp);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const existing = this.records.get(event.callId);
|
|
180
|
+
if (!existing) return;
|
|
181
|
+
existing.phase = event.type;
|
|
182
|
+
existing.status = statusForPhase(event.type);
|
|
183
|
+
existing.updatedAt = timestamp;
|
|
184
|
+
if (event.type === 'TOOL_PERMISSIONED') existing.permissionApproved = event.approved;
|
|
185
|
+
if (event.type === 'TOOL_SUCCEEDED') {
|
|
186
|
+
existing.completedAt = timestamp;
|
|
187
|
+
existing.durationMs = event.durationMs;
|
|
188
|
+
existing.resultSummary = resultSummaryFrom(event.result);
|
|
189
|
+
}
|
|
190
|
+
if (event.type === 'TOOL_FAILED') {
|
|
191
|
+
existing.completedAt = timestamp;
|
|
192
|
+
existing.durationMs = event.durationMs;
|
|
193
|
+
existing.error = truncateText(event.error, 220);
|
|
194
|
+
existing.resultSummary = resultSummaryFrom(event.result);
|
|
195
|
+
}
|
|
196
|
+
if (event.type === 'TOOL_CANCELLED') {
|
|
197
|
+
existing.completedAt = timestamp;
|
|
198
|
+
existing.cancelReason = event.reason ? truncateText(event.reason, 220) : undefined;
|
|
199
|
+
}
|
|
200
|
+
this.notify();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
private recordReceived(event: Extract<ToolEvent, { type: 'TOOL_RECEIVED' }>, timestamp: number): void {
|
|
204
|
+
const record: MutableAgentExecutionRecord = {
|
|
205
|
+
id: event.callId,
|
|
206
|
+
callId: event.callId,
|
|
207
|
+
turnId: event.turnId,
|
|
208
|
+
tool: event.tool,
|
|
209
|
+
routeKind: routeKindForTool(event.tool, event.args),
|
|
210
|
+
status: 'running',
|
|
211
|
+
phase: event.type,
|
|
212
|
+
receivedAt: timestamp,
|
|
213
|
+
updatedAt: timestamp,
|
|
214
|
+
argsPreview: argsPreview(event.args),
|
|
215
|
+
argsKeys: Object.keys(event.args).filter((key) => !SECRET_KEY_PATTERN.test(key)).sort(),
|
|
216
|
+
commandPreview: stringArg(event.args, ['command', 'cmd', 'script']),
|
|
217
|
+
targetPreview: stringArg(event.args, ['path', 'file', 'target', 'url', 'query', 'task']),
|
|
218
|
+
};
|
|
219
|
+
this.records.set(record.id, record);
|
|
220
|
+
this.order.push(record.id);
|
|
221
|
+
while (this.order.length > this.limit) {
|
|
222
|
+
const dropped = this.order.shift();
|
|
223
|
+
if (dropped) this.records.delete(dropped);
|
|
224
|
+
}
|
|
225
|
+
this.notify();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
private notify(): void {
|
|
229
|
+
for (const callback of this.subscribers) callback();
|
|
230
|
+
}
|
|
231
|
+
}
|
package/src/runtime/services.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { AutomationDeliveryManager, AutomationManager, AutomationRouteStore } fr
|
|
|
9
9
|
import { ChannelPluginRegistry, ChannelPolicyManager, RouteBindingManager, SurfaceRegistry } from '@pellux/goodvibes-sdk/platform/channels';
|
|
10
10
|
import { ChannelDeliveryRouter } from '@pellux/goodvibes-sdk/platform/channels';
|
|
11
11
|
import { ApprovalBroker, GatewayMethodCatalog, SharedSessionBroker } from '@pellux/goodvibes-sdk/platform/control-plane';
|
|
12
|
+
import type { SharedSessionRoutingIntent } from '@pellux/goodvibes-sdk/platform/control-plane';
|
|
12
13
|
import { WatcherRegistry } from '@pellux/goodvibes-sdk/platform/watchers';
|
|
13
14
|
import { ArtifactStore } from '@pellux/goodvibes-sdk/platform/artifacts';
|
|
14
15
|
import {
|
|
@@ -89,6 +90,7 @@ import {
|
|
|
89
90
|
type WorkflowServices,
|
|
90
91
|
} from '@pellux/goodvibes-sdk/platform/tools';
|
|
91
92
|
import { WorkPlanStore } from '../work-plans/work-plan-store.ts';
|
|
93
|
+
import { AgentExecutionLedger } from './execution-ledger.ts';
|
|
92
94
|
|
|
93
95
|
type WorktreeRegistry = RuntimeShell.WorktreeRegistry;
|
|
94
96
|
type SdkRuntimeServices = RuntimeFoundationClientsOptions['runtimeServices'];
|
|
@@ -130,6 +132,64 @@ function buildFallbackModelDefinition(provider: string, modelId: string): ModelD
|
|
|
130
132
|
};
|
|
131
133
|
}
|
|
132
134
|
|
|
135
|
+
function normalizeSharedSessionModelId(modelId: string | undefined, providerId: string | undefined): string | undefined {
|
|
136
|
+
const trimmedModelId = modelId?.trim();
|
|
137
|
+
if (!trimmedModelId) return undefined;
|
|
138
|
+
const trimmedProviderId = providerId?.trim();
|
|
139
|
+
const separatorIndex = trimmedModelId.indexOf(':');
|
|
140
|
+
if (separatorIndex > 0) return trimmedModelId;
|
|
141
|
+
if (trimmedProviderId) return `${trimmedProviderId}:${trimmedModelId}`;
|
|
142
|
+
return trimmedModelId;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function normalizeSharedSessionFallbackModels(models: readonly string[] | undefined): string[] {
|
|
146
|
+
return (models ?? [])
|
|
147
|
+
.filter((model): model is string => typeof model === 'string' && model.trim().length > 0)
|
|
148
|
+
.map((model) => {
|
|
149
|
+
const trimmed = model.trim();
|
|
150
|
+
const separatorIndex = trimmed.indexOf(':');
|
|
151
|
+
if (separatorIndex <= 0 || separatorIndex === trimmed.length - 1) {
|
|
152
|
+
throw new Error(`Shared-session fallback model '${model}' must be provider-qualified.`);
|
|
153
|
+
}
|
|
154
|
+
return trimmed;
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function buildAgentSpawnRoutingFromSharedSession(
|
|
159
|
+
routing: SharedSessionRoutingIntent | undefined,
|
|
160
|
+
options: { readonly restrictTools?: boolean | undefined } = {},
|
|
161
|
+
): Partial<Parameters<AgentManager['spawn']>[0]> {
|
|
162
|
+
if (!routing) return options.restrictTools ? { restrictTools: true } : {};
|
|
163
|
+
const provider = routing.providerId?.trim();
|
|
164
|
+
const model = normalizeSharedSessionModelId(routing.modelId, provider);
|
|
165
|
+
if (provider && !model) {
|
|
166
|
+
throw new Error('Shared-session provider routing requires a provider-qualified model when provider is supplied.');
|
|
167
|
+
}
|
|
168
|
+
const fallbackModels = normalizeSharedSessionFallbackModels(routing.fallbackModels);
|
|
169
|
+
const providerFailurePolicy = routing.providerFailurePolicy ?? (
|
|
170
|
+
fallbackModels.length ? 'ordered-fallbacks' : 'fail'
|
|
171
|
+
);
|
|
172
|
+
if (providerFailurePolicy === 'ordered-fallbacks' && fallbackModels.length === 0) {
|
|
173
|
+
throw new Error('Shared-session ordered fallback routing requires at least one provider-qualified fallback model.');
|
|
174
|
+
}
|
|
175
|
+
if (providerFailurePolicy === 'fail' && fallbackModels.length > 0) {
|
|
176
|
+
throw new Error('Shared-session fail routing cannot include fallback models; use ordered-fallbacks to enable model failover.');
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
...(model ? { model } : {}),
|
|
180
|
+
...(provider ? { provider } : {}),
|
|
181
|
+
...(routing.tools?.length ? { tools: [...routing.tools] } : {}),
|
|
182
|
+
...(options.restrictTools ? { restrictTools: true } : {}),
|
|
183
|
+
routing: {
|
|
184
|
+
providerSelection: routing.providerSelection ?? (provider ? 'concrete' : 'inherit-current'),
|
|
185
|
+
providerFailurePolicy,
|
|
186
|
+
...(fallbackModels.length ? { fallbackModels } : {}),
|
|
187
|
+
},
|
|
188
|
+
...(routing.executionIntent ? { executionIntent: routing.executionIntent } : {}),
|
|
189
|
+
...(routing.reasoningEffort ? { reasoningEffort: routing.reasoningEffort } : {}),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
133
193
|
class DisabledAgentWorktreeRegistry extends runtimeShell.WorktreeRegistry {
|
|
134
194
|
public override async list(): Promise<Awaited<ReturnType<WorktreeRegistry['list']>>> {
|
|
135
195
|
return [] as Awaited<ReturnType<WorktreeRegistry['list']>>;
|
|
@@ -405,6 +465,7 @@ export interface RuntimeServices extends SdkRuntimeServices {
|
|
|
405
465
|
readonly processManager: ProcessManager;
|
|
406
466
|
readonly modeManager: ModeManager;
|
|
407
467
|
readonly fileUndoManager: FileUndoManager;
|
|
468
|
+
readonly executionLedger: AgentExecutionLedger;
|
|
408
469
|
readonly integrationHelpers: IntegrationHelperService;
|
|
409
470
|
/**
|
|
410
471
|
* Re-root workspace-bound stores to a new working directory.
|
|
@@ -516,6 +577,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
516
577
|
surfaceRoot: GOODVIBES_AGENT_SURFACE_ROOT,
|
|
517
578
|
createWorktree: createDisabledAgentWrfcWorktreeOps,
|
|
518
579
|
}]) as WrfcController;
|
|
580
|
+
agentManager.setWrfcController(wrfcController);
|
|
519
581
|
const hookDispatcher = new HookDispatcher({ toolLLM, projectRoot: workingDirectory }, hookActivityTracker);
|
|
520
582
|
configManager.attachHookDispatcher(hookDispatcher);
|
|
521
583
|
const hookWorkbench = createHookWorkbench({
|
|
@@ -532,11 +594,13 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
532
594
|
messageSender: agentMessageBus,
|
|
533
595
|
});
|
|
534
596
|
sessionBroker.setContinuationRunner(async ({ task, input }) => {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
597
|
+
const record = agentManager.spawn({
|
|
598
|
+
mode: 'spawn',
|
|
599
|
+
task,
|
|
600
|
+
...buildAgentSpawnRoutingFromSharedSession(input.routing, { restrictTools: true }),
|
|
601
|
+
context: `shared-session:${input.sessionId}`,
|
|
602
|
+
});
|
|
603
|
+
return { agentId: record.id };
|
|
540
604
|
});
|
|
541
605
|
const artifactStore = new ArtifactStore({ configManager });
|
|
542
606
|
const memoryEmbeddingRegistry = new MemoryEmbeddingProviderRegistry({ configManager });
|
|
@@ -562,11 +626,23 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
562
626
|
runtimeBus: options.runtimeBus,
|
|
563
627
|
deliveryManager,
|
|
564
628
|
spawnTask: (input) => {
|
|
565
|
-
|
|
566
|
-
'
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
629
|
+
const record = agentManager.spawn({
|
|
630
|
+
mode: 'spawn',
|
|
631
|
+
task: input.prompt,
|
|
632
|
+
...(input.modelId ? { model: input.modelId } : {}),
|
|
633
|
+
...(input.modelProvider ? { provider: input.modelProvider } : {}),
|
|
634
|
+
...(input.fallbackModels ? { fallbackModels: [...input.fallbackModels] } : {}),
|
|
635
|
+
...(input.routing ? { routing: input.routing } : {}),
|
|
636
|
+
...(input.executionIntent ? { executionIntent: input.executionIntent } : {}),
|
|
637
|
+
...(input.template ? { template: input.template } : {}),
|
|
638
|
+
...(input.reasoningEffort ? { reasoningEffort: input.reasoningEffort } : {}),
|
|
639
|
+
...(input.toolAllowlist ? { tools: [...input.toolAllowlist], restrictTools: true } : {}),
|
|
640
|
+
context: [
|
|
641
|
+
'automation-manager:visible-agent',
|
|
642
|
+
input.context,
|
|
643
|
+
].filter((part): part is string => Boolean(part?.trim())).join('\n\n'),
|
|
644
|
+
});
|
|
645
|
+
return record.id;
|
|
570
646
|
},
|
|
571
647
|
});
|
|
572
648
|
const agentKnowledgeStore = new KnowledgeStore({
|
|
@@ -684,6 +760,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
684
760
|
const processManager = new ProcessManager();
|
|
685
761
|
const modeManager = new ModeManager();
|
|
686
762
|
const fileUndoManager = new FileUndoManager();
|
|
763
|
+
const executionLedger = new AgentExecutionLedger(options.runtimeBus);
|
|
687
764
|
const integrationHelpers = new IntegrationHelperService({
|
|
688
765
|
workingDirectory,
|
|
689
766
|
homeDirectory,
|
|
@@ -816,6 +893,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
816
893
|
processManager,
|
|
817
894
|
modeManager,
|
|
818
895
|
fileUndoManager,
|
|
896
|
+
executionLedger,
|
|
819
897
|
integrationHelpers,
|
|
820
898
|
async rerootStores(newWorkingDir: string): Promise<void> {
|
|
821
899
|
await projectIndex.reroot(newWorkingDir);
|