@pellux/goodvibes-agent 1.1.7 → 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 +170 -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 +132577 -91483
- 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 +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.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 +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,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);
|
|
@@ -17,7 +17,25 @@ const READ_TOOL_NAMES = new Set([
|
|
|
17
17
|
'inspect',
|
|
18
18
|
'state',
|
|
19
19
|
'registry',
|
|
20
|
+
'route',
|
|
20
21
|
'goodvibes_context',
|
|
22
|
+
'autonomy',
|
|
23
|
+
'channels',
|
|
24
|
+
'computer',
|
|
25
|
+
'context',
|
|
26
|
+
'delegation',
|
|
27
|
+
'device',
|
|
28
|
+
'execution',
|
|
29
|
+
'host',
|
|
30
|
+
'memory',
|
|
31
|
+
'models',
|
|
32
|
+
'personal_ops',
|
|
33
|
+
'research',
|
|
34
|
+
'security',
|
|
35
|
+
'setup',
|
|
36
|
+
'settings',
|
|
37
|
+
'vibe',
|
|
38
|
+
'workspace',
|
|
21
39
|
'agent_harness',
|
|
22
40
|
'agent_knowledge',
|
|
23
41
|
'agent_operator_briefing',
|
|
@@ -27,12 +45,36 @@ const WRITE_TOOL_NAMES = new Set([
|
|
|
27
45
|
'write',
|
|
28
46
|
'edit',
|
|
29
47
|
'goodvibes_settings',
|
|
48
|
+
'agent_artifacts',
|
|
49
|
+
'agent_documents',
|
|
30
50
|
'agent_knowledge_ingest',
|
|
51
|
+
'agent_learning_consolidation',
|
|
31
52
|
'agent_local_registry',
|
|
53
|
+
'agent_research_runs',
|
|
54
|
+
'agent_research_sources',
|
|
55
|
+
'agent_research_report',
|
|
56
|
+
'agent_review_packet_presets',
|
|
32
57
|
'agent_work_plan',
|
|
33
58
|
]);
|
|
34
59
|
|
|
35
|
-
const EXECUTE_TOOL_NAMES = new Set(['exec', 'repl']);
|
|
60
|
+
const EXECUTE_TOOL_NAMES = new Set(['exec', 'repl', 'terminal', 'process']);
|
|
61
|
+
const READ_ONLY_PROCESS_ACTIONS = new Set(['', 'list', 'status', 'poll', 'log', 'output', 'capabilities', 'doctor', 'parity']);
|
|
62
|
+
const READ_ONLY_SCHEDULE_ACTIONS = new Set(['', 'list', 'status', 'show']);
|
|
63
|
+
const READ_ONLY_SETTINGS_IMPORT_ACTIONS = new Set(['', 'preview', 'inspect', 'show', 'plan']);
|
|
64
|
+
const READ_ONLY_SETTINGS_ACTIONS = new Set(['', 'list', 'status', 'settings', 'catalog', 'search', 'find', 'browse', 'get', 'show', 'inspect', 'read', 'setting', 'get_setting', 'import', 'import_settings', 'settings_import', 'import_goodvibes', 'goodvibes_import', 'preview_import']);
|
|
65
|
+
const READ_ONLY_SETUP_ACTIONS = new Set(['', 'status', 'summary', 'list', 'item', 'show', 'inspect', 'repair', 'fix', 'diagnose_repair', 'host_repair', 'repair_host', 'launch_host', 'checkpoint', 'checkpoint_status']);
|
|
66
|
+
const READ_ONLY_VIBE_ACTIONS = new Set(['', 'status', 'summary', 'list', 'show', 'file', 'source', 'read', 'inspect']);
|
|
67
|
+
const READ_ONLY_PERSONAL_OPS_ACTIONS = new Set(['', 'briefing', 'brief', 'daily', 'daily_brief', 'morning', 'status', 'summary', 'overview', 'map', 'list', 'queue', 'queues', 'review_queue', 'review_queues', 'personal_queue', 'ops_queue', 'intake', 'request', 'route', 'plan', 'triage', 'draft', 'lane', 'inspect', 'show']);
|
|
68
|
+
const READ_ONLY_RESEARCH_ACTIONS = new Set(['', 'briefing', 'brief', 'status', 'dashboard', 'cockpit', 'next', 'plan', 'workflow', 'research', 'runner', 'browser', 'browser_runner', 'browser_backed', 'deep_research', 'runs', 'list_runs', 'run_list', 'run', 'show_run', 'inspect_run', 'sources', 'queue', 'source_queue', 'source', 'show_source', 'inspect_source', 'bundle', 'bundle_sources', 'source_bundle', 'search', 'public_search', 'collect', 'collect_sources', 'source_candidates', 'reports', 'list_reports', 'report_list', 'visual_reports', 'report_artifact', 'show_report', 'inspect_report', 'show_visual_report', 'visual_report_artifact']);
|
|
69
|
+
const READ_ONLY_CHANNELS_ACTIONS = new Set(['', 'status', 'summary', 'list', 'readiness', 'channels', 'channel', 'show', 'inspect', 'setup', 'guide', 'setup_guide', 'channel_setup_guide', 'triage', 'inbox', 'blockers', 'retries', 'channel_triage', 'deliveries', 'delivery', 'receipts', 'history', 'channel_deliveries']);
|
|
70
|
+
const READ_ONLY_MEMORY_ACTIONS = new Set(['', 'status', 'summary', 'posture', 'memory_posture', 'recall', 'providers', 'provider', 'memory_provider', 'embedding', 'external', 'external_provider', 'curator', 'learning', 'learning_curator', 'queue', 'review_queue', 'plan', 'candidate', 'learning_candidate', 'card', 'inspect_candidate', 'list', 'records', 'memories', 'search', 'find', 'lookup', 'get', 'show', 'inspect', 'read']);
|
|
71
|
+
const READ_ONLY_COMPUTER_ACTIONS = new Set(['', 'status', 'summary', 'overview', 'computer', 'computer_use', 'plan', 'route', 'control_plan', 'browser_plan', 'desktop_plan', 'control', 'browser_control', 'desktop', 'desktop_control', 'screenshot', 'screen', 'screen_recording', 'observe', 'browser', 'pwa', 'cockpit', 'browser_cockpit', 'web', 'setup', 'configure', 'browser_desktop_control', 'mcp', 'tools', 'servers', 'mcp_servers']);
|
|
72
|
+
const READ_ONLY_DEVICE_ACTIONS = new Set(['', 'status', 'map', 'capabilities', 'device', 'devices', 'mobile', 'phone', 'pairing', 'capability', 'route', 'pairing_route', 'show', 'inspect', 'browser', 'pwa', 'cockpit', 'browser_cockpit', 'web', 'control', 'browser_control', 'desktop', 'desktop_control', 'computer_use', 'voice', 'media', 'voice_media', 'workflows', 'provider', 'media_provider', 'voice_provider']);
|
|
73
|
+
const READ_ONLY_MODELS_ACTIONS = new Set(['', 'status', 'routing', 'routes', 'models', 'model', 'readiness', 'route_readiness', 'route', 'model_route', 'inspect', 'show', 'candidate', 'endpoint', 'local', 'cookbook', 'local_cookbook', 'recipes', 'recipe', 'ollama', 'llama_cpp', 'llamacpp', 'vllm', 'local_servers', 'providers', 'provider_accounts', 'accounts', 'subscriptions', 'auth', 'logins', 'provider', 'provider_account', 'account', 'subscription', 'auth_status']);
|
|
74
|
+
const READ_ONLY_WORKSPACE_ACTIONS = new Set(['', 'status', 'summary', 'home', 'workspace', 'categories', 'workspace_categories', 'actions', 'list_actions', 'workspace_actions', 'tasks', 'action', 'show', 'inspect', 'workspace_action', 'surfaces', 'ui_surfaces', 'screens', 'views', 'surface', 'ui_surface', 'screen', 'view', 'panels', 'panes', 'panel', 'pane', 'shortcuts', 'shortcut_help', 'help', 'keybindings', 'bindings', 'keys', 'keybinding', 'binding', 'key', 'commands', 'slash_commands', 'command_catalog', 'command', 'slash_command', 'inspect_command', 'cli_commands', 'cli_catalog', 'cli_command', 'inspect_cli_command']);
|
|
75
|
+
const READ_ONLY_AUTONOMY_ACTIONS = new Set(['', 'intake', 'request', 'route', 'plan', 'triage', 'autonomy_intake', 'queue', 'list', 'work', 'ongoing', 'autonomy_queue', 'item', 'card', 'show', 'inspect', 'autonomy_queue_item', 'status', 'summary', 'overview']);
|
|
76
|
+
const READ_ONLY_DELEGATION_ACTIONS = new Set(['', 'status', 'summary', 'overview', 'policy', 'decision', 'decisions', 'delegation_posture', 'routes', 'list', 'catalog', 'posture', 'route', 'item', 'card', 'show', 'inspect', 'delegation_route']);
|
|
77
|
+
const READ_ONLY_EXECUTION_ACTIONS = new Set(['', 'status', 'summary', 'overview', 'routes', 'posture', 'execution_posture', 'route', 'show_route', 'inspect_route', 'execution_route', 'history', 'activity', 'records', 'execution_history', 'record', 'item', 'show', 'inspect', 'execution_history_item', 'processes', 'background', 'backgrounds', 'background_processes', 'capabilities', 'process_capabilities', 'process', 'background_process', 'recovery', 'file_recovery', 'undo_redo']);
|
|
36
78
|
|
|
37
79
|
type MarkedPermissionManager = PermissionManagerLike & { [SAFETY_MARKER]?: true };
|
|
38
80
|
|
|
@@ -47,9 +89,11 @@ export function installPermissionManagerSafetyGuard(manager: PermissionManagerLi
|
|
|
47
89
|
|
|
48
90
|
manager.getCategory = (toolName, args = {}) => {
|
|
49
91
|
try {
|
|
50
|
-
|
|
92
|
+
const category = originalGetCategory(toolName, args);
|
|
93
|
+
const knownCategory = fallbackPermissionCategoryForArgs(toolName, args);
|
|
94
|
+
return category === 'delegate' && knownCategory !== 'delegate' ? knownCategory : category;
|
|
51
95
|
} catch {
|
|
52
|
-
return
|
|
96
|
+
return fallbackPermissionCategoryForArgs(toolName, args);
|
|
53
97
|
}
|
|
54
98
|
};
|
|
55
99
|
|
|
@@ -57,7 +101,7 @@ export function installPermissionManagerSafetyGuard(manager: PermissionManagerLi
|
|
|
57
101
|
try {
|
|
58
102
|
return await originalCheck(toolName, args);
|
|
59
103
|
} catch {
|
|
60
|
-
return
|
|
104
|
+
return fallbackPermissionCategoryForArgs(toolName, args) === 'read';
|
|
61
105
|
}
|
|
62
106
|
};
|
|
63
107
|
|
|
@@ -66,7 +110,7 @@ export function installPermissionManagerSafetyGuard(manager: PermissionManagerLi
|
|
|
66
110
|
try {
|
|
67
111
|
return await originalCheckDetailed(toolName, args);
|
|
68
112
|
} catch (error) {
|
|
69
|
-
const category =
|
|
113
|
+
const category = fallbackPermissionCategoryForArgs(toolName, args);
|
|
70
114
|
const approved = category === 'read';
|
|
71
115
|
return {
|
|
72
116
|
approved,
|
|
@@ -91,3 +135,153 @@ export function fallbackPermissionCategory(toolName: string): PermissionCategory
|
|
|
91
135
|
if (EXECUTE_TOOL_NAMES.has(toolName)) return 'execute';
|
|
92
136
|
return 'delegate';
|
|
93
137
|
}
|
|
138
|
+
|
|
139
|
+
export function fallbackPermissionCategoryForArgs(toolName: string, args: Record<string, unknown>): PermissionCategory {
|
|
140
|
+
if (toolName === 'process') {
|
|
141
|
+
const action = typeof args.action === 'string'
|
|
142
|
+
? args.action.trim().toLowerCase()
|
|
143
|
+
: typeof args.processAction === 'string'
|
|
144
|
+
? args.processAction.trim().toLowerCase()
|
|
145
|
+
: '';
|
|
146
|
+
return READ_ONLY_PROCESS_ACTIONS.has(action) ? 'read' : 'execute';
|
|
147
|
+
}
|
|
148
|
+
if (toolName === 'schedule') {
|
|
149
|
+
const action = typeof args.action === 'string'
|
|
150
|
+
? args.action.trim().toLowerCase()
|
|
151
|
+
: typeof args.mode === 'string'
|
|
152
|
+
? args.mode.trim().toLowerCase()
|
|
153
|
+
: '';
|
|
154
|
+
return READ_ONLY_SCHEDULE_ACTIONS.has(action) ? 'read' : 'execute';
|
|
155
|
+
}
|
|
156
|
+
if (toolName === 'import_goodvibes_settings') {
|
|
157
|
+
const action = typeof args.action === 'string'
|
|
158
|
+
? args.action.trim().toLowerCase()
|
|
159
|
+
: typeof args.mode === 'string'
|
|
160
|
+
? args.mode.trim().toLowerCase()
|
|
161
|
+
: '';
|
|
162
|
+
return READ_ONLY_SETTINGS_IMPORT_ACTIONS.has(action) ? 'read' : 'write';
|
|
163
|
+
}
|
|
164
|
+
if (toolName === 'settings') {
|
|
165
|
+
const action = typeof args.action === 'string'
|
|
166
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
167
|
+
: typeof args.mode === 'string'
|
|
168
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
169
|
+
: '';
|
|
170
|
+
const confirmed = args.confirm === true || (typeof args.confirm === 'string' && ['true', 'yes', 'apply', 'run'].includes(args.confirm.trim().toLowerCase()));
|
|
171
|
+
if ((action === 'import' || action === 'import_settings' || action === 'settings_import' || action === 'import_goodvibes' || action === 'goodvibes_import') && confirmed) return 'write';
|
|
172
|
+
return READ_ONLY_SETTINGS_ACTIONS.has(action) ? 'read' : 'write';
|
|
173
|
+
}
|
|
174
|
+
if (toolName === 'setup') {
|
|
175
|
+
const action = typeof args.action === 'string'
|
|
176
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
177
|
+
: typeof args.mode === 'string'
|
|
178
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
179
|
+
: '';
|
|
180
|
+
return READ_ONLY_SETUP_ACTIONS.has(action) ? 'read' : 'write';
|
|
181
|
+
}
|
|
182
|
+
if (toolName === 'vibe') {
|
|
183
|
+
const action = typeof args.action === 'string'
|
|
184
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
185
|
+
: typeof args.mode === 'string'
|
|
186
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
187
|
+
: '';
|
|
188
|
+
return READ_ONLY_VIBE_ACTIONS.has(action) ? 'read' : 'write';
|
|
189
|
+
}
|
|
190
|
+
if (toolName === 'personal_ops') {
|
|
191
|
+
const action = typeof args.action === 'string'
|
|
192
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
193
|
+
: typeof args.mode === 'string'
|
|
194
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
195
|
+
: '';
|
|
196
|
+
return READ_ONLY_PERSONAL_OPS_ACTIONS.has(action) ? 'read' : 'write';
|
|
197
|
+
}
|
|
198
|
+
if (toolName === 'research') {
|
|
199
|
+
const action = typeof args.action === 'string'
|
|
200
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
201
|
+
: typeof args.mode === 'string'
|
|
202
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
203
|
+
: '';
|
|
204
|
+
return READ_ONLY_RESEARCH_ACTIONS.has(action) ? 'read' : 'write';
|
|
205
|
+
}
|
|
206
|
+
if (toolName === 'channels') {
|
|
207
|
+
const action = typeof args.action === 'string'
|
|
208
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
209
|
+
: typeof args.mode === 'string'
|
|
210
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
211
|
+
: '';
|
|
212
|
+
return READ_ONLY_CHANNELS_ACTIONS.has(action) ? 'read' : 'write';
|
|
213
|
+
}
|
|
214
|
+
if (toolName === 'memory') {
|
|
215
|
+
const action = typeof args.action === 'string'
|
|
216
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
217
|
+
: typeof args.mode === 'string'
|
|
218
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
219
|
+
: '';
|
|
220
|
+
return READ_ONLY_MEMORY_ACTIONS.has(action) ? 'read' : 'write';
|
|
221
|
+
}
|
|
222
|
+
if (toolName === 'computer') {
|
|
223
|
+
const action = typeof args.action === 'string'
|
|
224
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
225
|
+
: typeof args.mode === 'string'
|
|
226
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
227
|
+
: '';
|
|
228
|
+
return READ_ONLY_COMPUTER_ACTIONS.has(action) ? 'read' : 'write';
|
|
229
|
+
}
|
|
230
|
+
if (toolName === 'device') {
|
|
231
|
+
const action = typeof args.action === 'string'
|
|
232
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
233
|
+
: typeof args.mode === 'string'
|
|
234
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
235
|
+
: '';
|
|
236
|
+
return READ_ONLY_DEVICE_ACTIONS.has(action) ? 'read' : 'write';
|
|
237
|
+
}
|
|
238
|
+
if (toolName === 'models') {
|
|
239
|
+
const action = typeof args.action === 'string'
|
|
240
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
241
|
+
: typeof args.mode === 'string'
|
|
242
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
243
|
+
: '';
|
|
244
|
+
return READ_ONLY_MODELS_ACTIONS.has(action) ? 'read' : 'write';
|
|
245
|
+
}
|
|
246
|
+
if (toolName === 'workspace') {
|
|
247
|
+
const action = typeof args.action === 'string'
|
|
248
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
249
|
+
: typeof args.mode === 'string'
|
|
250
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
251
|
+
: '';
|
|
252
|
+
return READ_ONLY_WORKSPACE_ACTIONS.has(action) ? 'read' : 'write';
|
|
253
|
+
}
|
|
254
|
+
if (toolName === 'autonomy') {
|
|
255
|
+
const action = typeof args.action === 'string'
|
|
256
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
257
|
+
: typeof args.mode === 'string'
|
|
258
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
259
|
+
: '';
|
|
260
|
+
return READ_ONLY_AUTONOMY_ACTIONS.has(action) ? 'read' : 'write';
|
|
261
|
+
}
|
|
262
|
+
if (toolName === 'delegation') {
|
|
263
|
+
const action = typeof args.action === 'string'
|
|
264
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
265
|
+
: typeof args.mode === 'string'
|
|
266
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
267
|
+
: '';
|
|
268
|
+
return READ_ONLY_DELEGATION_ACTIONS.has(action) ? 'read' : 'write';
|
|
269
|
+
}
|
|
270
|
+
if (toolName === 'execution') {
|
|
271
|
+
const action = typeof args.action === 'string'
|
|
272
|
+
? args.action.trim().toLowerCase().replace(/-/g, '_')
|
|
273
|
+
: typeof args.mode === 'string'
|
|
274
|
+
? args.mode.trim().toLowerCase().replace(/-/g, '_')
|
|
275
|
+
: '';
|
|
276
|
+
return READ_ONLY_EXECUTION_ACTIONS.has(action) ? 'read' : 'write';
|
|
277
|
+
}
|
|
278
|
+
if (toolName === 'agent_artifacts') {
|
|
279
|
+
const mode = typeof args.mode === 'string' ? args.mode.trim() : '';
|
|
280
|
+
return mode === 'list' || mode === 'show' ? 'read' : 'write';
|
|
281
|
+
}
|
|
282
|
+
if (toolName === 'agent_review_packet_presets') {
|
|
283
|
+
const mode = typeof args.mode === 'string' ? args.mode.trim() : '';
|
|
284
|
+
return mode === 'list' || mode === 'show' || mode === '' ? 'read' : 'write';
|
|
285
|
+
}
|
|
286
|
+
return fallbackPermissionCategory(toolName);
|
|
287
|
+
}
|