@pellux/goodvibes-agent 1.0.33 → 1.0.35
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 +35 -4
- package/README.md +73 -59
- 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 +49347 -50698
- package/docs/README.md +25 -21
- package/docs/channels-remote-and-api.md +2 -2
- package/docs/connected-host.md +3 -3
- package/docs/getting-started.md +89 -85
- package/docs/providers-and-routing.md +3 -3
- package/docs/release-and-publishing.md +3 -3
- package/docs/tools-and-commands.md +152 -138
- package/docs/voice-and-live-tts.md +1 -1
- package/package.json +1 -1
- package/release/live-verification/live-verification.json +13 -13
- package/release/live-verification/live-verification.md +17 -17
- package/release/release-notes.md +6 -15
- package/release/release-readiness.json +35 -35
- package/src/agent/harness-control.ts +42 -3
- package/src/runtime/bootstrap-core.ts +2 -0
- package/src/runtime/bootstrap.ts +12 -18
- package/src/tools/agent-analysis-registry-policy.ts +2 -9
- package/src/tools/agent-channel-send-tool.ts +1 -5
- package/src/tools/agent-context-policy.ts +1 -5
- package/src/tools/agent-find-policy.ts +1 -4
- package/src/tools/agent-harness-channel-metadata.ts +23 -23
- package/src/tools/agent-harness-cli-metadata.ts +4 -1
- package/src/tools/agent-harness-command-catalog.ts +10 -3
- package/src/tools/agent-harness-connected-host-status.ts +8 -2
- package/src/tools/agent-harness-delegation-posture.ts +5 -5
- package/src/tools/agent-harness-mcp-metadata.ts +30 -28
- package/src/tools/agent-harness-media-posture.ts +10 -10
- package/src/tools/agent-harness-metadata.ts +65 -35
- package/src/tools/agent-harness-mode-catalog.ts +205 -0
- package/src/tools/agent-harness-model-routing.ts +14 -14
- package/src/tools/agent-harness-model-tool-catalog.ts +7 -2
- package/src/tools/agent-harness-notification-metadata.ts +17 -17
- package/src/tools/agent-harness-operator-methods.ts +2 -2
- package/src/tools/agent-harness-pairing-posture.ts +7 -7
- package/src/tools/agent-harness-panel-metadata.ts +26 -12
- package/src/tools/agent-harness-provider-account-metadata.ts +33 -31
- package/src/tools/agent-harness-security-posture.ts +9 -7
- package/src/tools/agent-harness-service-posture.ts +22 -16
- package/src/tools/agent-harness-session-metadata.ts +9 -7
- package/src/tools/agent-harness-setup-posture.ts +7 -7
- package/src/tools/agent-harness-tool-schema.ts +2 -1
- package/src/tools/agent-harness-tool.ts +91 -38
- package/src/tools/agent-harness-ui-surface-metadata.ts +40 -28
- package/src/tools/agent-harness-workspace-actions.ts +29 -1
- package/src/tools/agent-knowledge-ingest-tool.ts +1 -5
- package/src/tools/agent-knowledge-tool.ts +1 -5
- package/src/tools/agent-local-registry-tool.ts +1 -4
- package/src/tools/agent-media-generate-tool.ts +1 -5
- package/src/tools/agent-notify-tool.ts +1 -5
- package/src/tools/agent-operator-action-tool.ts +1 -5
- package/src/tools/agent-operator-briefing-tool.ts +1 -5
- package/src/tools/agent-read-policy.ts +1 -4
- package/src/tools/agent-reminder-schedule-tool.ts +1 -5
- package/src/tools/agent-tool-policy-guard.ts +7 -34
- package/src/tools/agent-web-search-policy.ts +1 -4
- package/src/tools/agent-work-plan-tool.ts +1 -5
- package/src/tools/tool-definition-compaction.ts +49 -0
- package/src/version.ts +1 -1
|
@@ -13,6 +13,10 @@ export type ConnectedHostCapabilityResolution =
|
|
|
13
13
|
| { readonly status: 'found'; readonly detail: Record<string, unknown> }
|
|
14
14
|
| { readonly status: 'ambiguous'; readonly input: string; readonly candidates: readonly Record<string, unknown>[] };
|
|
15
15
|
|
|
16
|
+
function agentHarnessModes(...modes: readonly string[]): string {
|
|
17
|
+
return `agent_harness ${modes.map((mode) => `mode:"${mode}"`).join(', ')}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
export function describeCommandPolicy(commandName: string): CommandExecutionPolicy {
|
|
17
21
|
const root = commandName.replace(/^\//, '').trim().toLowerCase();
|
|
18
22
|
const confirmation = 'agent_harness mode:"run_command" requires confirm:true and explicitUserRequest for every slash command invocation.';
|
|
@@ -20,7 +24,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
20
24
|
return {
|
|
21
25
|
effect: 'ui-navigation',
|
|
22
26
|
confirmation,
|
|
23
|
-
preferredModelTool: '
|
|
27
|
+
preferredModelTool: agentHarnessModes('workspace', 'workspace_categories', 'workspace_actions', 'workspace_action', 'run_workspace_action'),
|
|
24
28
|
boundary: 'Agent workspace navigation is visible shell routing. Use workspace action modes for concrete model-readable operation.',
|
|
25
29
|
};
|
|
26
30
|
}
|
|
@@ -28,7 +32,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
28
32
|
return {
|
|
29
33
|
effect: 'ui-navigation',
|
|
30
34
|
confirmation,
|
|
31
|
-
preferredModelTool: '
|
|
35
|
+
preferredModelTool: agentHarnessModes('workspace_actions', 'workspace_action', 'open_ui_surface'),
|
|
32
36
|
boundary: 'Setup opens the visible Agent onboarding or setup workspace. Model-side changes should use setting modes or workspace actions.',
|
|
33
37
|
};
|
|
34
38
|
}
|
|
@@ -36,7 +40,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
36
40
|
return {
|
|
37
41
|
effect: 'ui-navigation',
|
|
38
42
|
confirmation,
|
|
39
|
-
preferredModelTool: root === 'shortcuts' ? '
|
|
43
|
+
preferredModelTool: root === 'shortcuts' ? agentHarnessModes('shortcuts', 'keybindings', 'keybinding') : agentHarnessModes('commands', 'command'),
|
|
40
44
|
boundary: 'Discovery commands open visible help surfaces. The model should inspect the matching harness catalog directly before invoking commands.',
|
|
41
45
|
};
|
|
42
46
|
}
|
|
@@ -44,7 +48,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
44
48
|
return {
|
|
45
49
|
effect: 'read-only',
|
|
46
50
|
confirmation,
|
|
47
|
-
preferredModelTool: '
|
|
51
|
+
preferredModelTool: agentHarnessModes('shortcuts', 'keybindings', 'keybinding', 'run_keybinding', 'set_keybinding', 'reset_keybinding'),
|
|
48
52
|
boundary: 'Keybinding inspection is read-only. Keybinding execution or edits require explicit confirmation through agent_harness keybinding modes.',
|
|
49
53
|
};
|
|
50
54
|
}
|
|
@@ -52,7 +56,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
52
56
|
return {
|
|
53
57
|
effect: 'mixed',
|
|
54
58
|
confirmation,
|
|
55
|
-
preferredModelTool: '
|
|
59
|
+
preferredModelTool: agentHarnessModes('settings', 'get_setting', 'set_setting', 'reset_setting'),
|
|
56
60
|
boundary: 'Model-writable settings can be changed through agent_harness. Connected-host lifecycle/listener settings remain read-only.',
|
|
57
61
|
};
|
|
58
62
|
}
|
|
@@ -60,7 +64,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
60
64
|
return {
|
|
61
65
|
effect: 'mixed',
|
|
62
66
|
confirmation,
|
|
63
|
-
preferredModelTool: '
|
|
67
|
+
preferredModelTool: agentHarnessModes('settings', 'get_setting', 'set_setting', 'open_ui_surface'),
|
|
64
68
|
boundary: 'Model and reasoning-effort changes affect the current Agent chat route. Prefer settings modes for concrete values and UI surface routing for visible pickers.',
|
|
65
69
|
};
|
|
66
70
|
}
|
|
@@ -68,7 +72,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
68
72
|
return {
|
|
69
73
|
effect: 'mixed',
|
|
70
74
|
confirmation,
|
|
71
|
-
preferredModelTool: '
|
|
75
|
+
preferredModelTool: agentHarnessModes('settings', 'get_setting', 'set_setting', 'open_ui_surface'),
|
|
72
76
|
boundary: 'Provider selection and custom provider files belong to Agent provider configuration. Adding, removing, or switching providers requires explicit user intent.',
|
|
73
77
|
};
|
|
74
78
|
}
|
|
@@ -76,7 +80,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
76
80
|
return {
|
|
77
81
|
effect: 'external-network',
|
|
78
82
|
confirmation,
|
|
79
|
-
preferredModelTool: '
|
|
83
|
+
preferredModelTool: agentHarnessModes('settings', 'tools'),
|
|
80
84
|
boundary: 'Model catalog refresh may call provider discovery routes and update local provider metadata. Do not run it without explicit user request.',
|
|
81
85
|
};
|
|
82
86
|
}
|
|
@@ -84,7 +88,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
84
88
|
return {
|
|
85
89
|
effect: 'local-state',
|
|
86
90
|
confirmation,
|
|
87
|
-
preferredModelTool: '
|
|
91
|
+
preferredModelTool: agentHarnessModes('run_command'),
|
|
88
92
|
boundary: 'Pinned model changes mutate local Agent provider preferences only and require an explicit model id.',
|
|
89
93
|
};
|
|
90
94
|
}
|
|
@@ -92,7 +96,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
92
96
|
return {
|
|
93
97
|
effect: 'local-state',
|
|
94
98
|
confirmation,
|
|
95
|
-
preferredModelTool: '
|
|
99
|
+
preferredModelTool: agentHarnessModes('settings', 'get_setting', 'set_setting'),
|
|
96
100
|
boundary: 'Interaction-mode changes affect the current Agent operator notification posture and should be explicit.',
|
|
97
101
|
};
|
|
98
102
|
}
|
|
@@ -108,7 +112,9 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
108
112
|
return {
|
|
109
113
|
effect: 'read-only',
|
|
110
114
|
confirmation,
|
|
111
|
-
preferredModelTool: root === 'compat'
|
|
115
|
+
preferredModelTool: root === 'compat'
|
|
116
|
+
? agentHarnessModes('service_posture', 'service_endpoint', 'connected_host_status')
|
|
117
|
+
: agentHarnessModes('service_posture', 'service_endpoint', 'connected_host_status', 'settings', 'tools', 'open_ui_surface'),
|
|
112
118
|
boundary: 'Diagnostics and review commands inspect Agent, provider, MCP, security, and connected-host readiness without taking lifecycle ownership.',
|
|
113
119
|
};
|
|
114
120
|
}
|
|
@@ -116,7 +122,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
116
122
|
return {
|
|
117
123
|
effect: 'mixed',
|
|
118
124
|
confirmation,
|
|
119
|
-
preferredModelTool: '
|
|
125
|
+
preferredModelTool: agentHarnessModes('run_command'),
|
|
120
126
|
boundary: 'Review subcommands are read-only; bundle export/import or auth/trust bundle export writes local files and requires explicit confirmation.',
|
|
121
127
|
};
|
|
122
128
|
}
|
|
@@ -124,7 +130,9 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
124
130
|
return {
|
|
125
131
|
effect: 'mixed',
|
|
126
132
|
confirmation,
|
|
127
|
-
preferredModelTool: root === 'secrets' || root === 'secret'
|
|
133
|
+
preferredModelTool: root === 'secrets' || root === 'secret'
|
|
134
|
+
? agentHarnessModes('settings', 'get_setting', 'set_setting', 'reset_setting')
|
|
135
|
+
: agentHarnessModes('workspace_actions', 'settings', 'open_ui_surface'),
|
|
128
136
|
boundary: 'Harness-owned configuration, secret, voice, subscription, and MCP commands can expose credentials or external account state. Mutations require explicit user intent and should prefer secret refs over raw values.',
|
|
129
137
|
};
|
|
130
138
|
}
|
|
@@ -150,7 +158,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
150
158
|
return {
|
|
151
159
|
effect: 'ui-navigation',
|
|
152
160
|
confirmation,
|
|
153
|
-
preferredModelTool: '
|
|
161
|
+
preferredModelTool: `${agentHarnessModes('workspace_actions', 'workspace_action', 'run_workspace_action')} or agent_local_registry`,
|
|
154
162
|
boundary: 'Notes workspace routing is visible navigation; note record mutations should use Agent-local registry or workspace action modes.',
|
|
155
163
|
};
|
|
156
164
|
}
|
|
@@ -198,7 +206,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
198
206
|
return {
|
|
199
207
|
effect: 'external-network',
|
|
200
208
|
confirmation,
|
|
201
|
-
preferredModelTool: '
|
|
209
|
+
preferredModelTool: agentHarnessModes('open_ui_surface'),
|
|
202
210
|
boundary: 'Image attachment reads a local image and submits a model turn with image content. Use only for explicit user-supplied files.',
|
|
203
211
|
};
|
|
204
212
|
}
|
|
@@ -206,7 +214,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
206
214
|
return {
|
|
207
215
|
effect: 'external-network',
|
|
208
216
|
confirmation,
|
|
209
|
-
preferredModelTool: '
|
|
217
|
+
preferredModelTool: agentHarnessModes('settings', 'open_ui_surface'),
|
|
210
218
|
boundary: 'Live TTS submits a normal prompt and may call model and speech providers; stopping playback is local runtime control.',
|
|
211
219
|
};
|
|
212
220
|
}
|
|
@@ -222,7 +230,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
222
230
|
return {
|
|
223
231
|
effect: 'delegated-work',
|
|
224
232
|
confirmation,
|
|
225
|
-
preferredModelTool: '
|
|
233
|
+
preferredModelTool: agentHarnessModes('workspace_actions', 'workspace_action', 'run_workspace_action'),
|
|
226
234
|
boundary: 'Delegation is explicit user-directed work only; no hidden background review or separate Agent job should be created implicitly.',
|
|
227
235
|
};
|
|
228
236
|
}
|
|
@@ -245,7 +253,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
245
253
|
return {
|
|
246
254
|
effect: 'session-lifecycle',
|
|
247
255
|
confirmation,
|
|
248
|
-
preferredModelTool: '
|
|
256
|
+
preferredModelTool: agentHarnessModes('commands', 'command', 'run_command'),
|
|
249
257
|
boundary: 'Session and conversation commands operate on the visible harness session lifecycle.',
|
|
250
258
|
};
|
|
251
259
|
}
|
|
@@ -253,7 +261,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
253
261
|
return {
|
|
254
262
|
effect: 'local-state',
|
|
255
263
|
confirmation,
|
|
256
|
-
preferredModelTool: '
|
|
264
|
+
preferredModelTool: `${agentHarnessModes('workspace_actions', 'workspace_action', 'run_workspace_action')} or ${agentHarnessModes('run_command')}`,
|
|
257
265
|
boundary: 'Conversation export writes a local workspace file and requires an explicit output intent.',
|
|
258
266
|
};
|
|
259
267
|
}
|
|
@@ -261,7 +269,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
261
269
|
return {
|
|
262
270
|
effect: 'ui-navigation',
|
|
263
271
|
confirmation,
|
|
264
|
-
preferredModelTool: root === 'bookmarks' ? '
|
|
272
|
+
preferredModelTool: root === 'bookmarks' ? agentHarnessModes('open_ui_surface') : agentHarnessModes('run_command'),
|
|
265
273
|
boundary: 'Conversation display navigation mutates only the visible transcript view or scroll position.',
|
|
266
274
|
};
|
|
267
275
|
}
|
|
@@ -269,7 +277,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
269
277
|
return {
|
|
270
278
|
effect: 'local-state',
|
|
271
279
|
confirmation,
|
|
272
|
-
preferredModelTool: '
|
|
280
|
+
preferredModelTool: agentHarnessModes('run_keybinding'),
|
|
273
281
|
boundary: 'Paste reads the local clipboard and mutates the visible prompt or image attachment state.',
|
|
274
282
|
};
|
|
275
283
|
}
|
|
@@ -277,7 +285,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
277
285
|
return {
|
|
278
286
|
effect: 'mixed',
|
|
279
287
|
confirmation,
|
|
280
|
-
preferredModelTool: '
|
|
288
|
+
preferredModelTool: agentHarnessModes('workspace_actions', 'workspace_action', 'run_workspace_action'),
|
|
281
289
|
boundary: 'Agent profile commands manage isolated Agent runtime profiles and starter templates. Mutations require explicit confirmation.',
|
|
282
290
|
};
|
|
283
291
|
}
|
|
@@ -285,7 +293,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
285
293
|
return {
|
|
286
294
|
effect: 'read-only',
|
|
287
295
|
confirmation,
|
|
288
|
-
preferredModelTool: '
|
|
296
|
+
preferredModelTool: agentHarnessModes('run_command'),
|
|
289
297
|
boundary: 'Pairing details are displayed for explicit operator use; the Agent does not manage connected-host listener lifecycle.',
|
|
290
298
|
};
|
|
291
299
|
}
|
|
@@ -330,7 +338,9 @@ export function describeCliCommandPolicy(commandName: string): CommandExecutionP
|
|
|
330
338
|
return {
|
|
331
339
|
effect: root === 'tui' || root === 'onboarding' ? 'ui-navigation' : 'read-only',
|
|
332
340
|
confirmation,
|
|
333
|
-
preferredModelTool: root === 'onboarding' || root === 'tui'
|
|
341
|
+
preferredModelTool: root === 'onboarding' || root === 'tui'
|
|
342
|
+
? agentHarnessModes('workspace', 'workspace_actions', 'workspace_action', 'run_workspace_action')
|
|
343
|
+
: agentHarnessModes('cli_commands', 'cli_command'),
|
|
334
344
|
boundary: 'Top-level CLI launch, setup, help, version, and completion commands are package entrypoint surfaces; use in-process workspace and slash-command bridges from the model when operating inside the TUI.',
|
|
335
345
|
};
|
|
336
346
|
}
|
|
@@ -346,7 +356,7 @@ export function describeCliCommandPolicy(commandName: string): CommandExecutionP
|
|
|
346
356
|
return {
|
|
347
357
|
effect: 'read-only',
|
|
348
358
|
confirmation,
|
|
349
|
-
preferredModelTool: root === 'tasks' ? 'agent_operator_briefing' : '
|
|
359
|
+
preferredModelTool: root === 'tasks' ? 'agent_operator_briefing' : agentHarnessModes('service_posture', 'service_endpoint', 'connected_host_status', 'connected_host', 'settings', 'tools'),
|
|
350
360
|
boundary: 'Diagnostics and posture commands are readable from Agent-owned settings, provider, model, and connected-host capability surfaces without taking connected-host lifecycle ownership.',
|
|
351
361
|
};
|
|
352
362
|
}
|
|
@@ -354,7 +364,7 @@ export function describeCliCommandPolicy(commandName: string): CommandExecutionP
|
|
|
354
364
|
return {
|
|
355
365
|
effect: 'local-state',
|
|
356
366
|
confirmation,
|
|
357
|
-
preferredModelTool: root === 'profiles' ? '
|
|
367
|
+
preferredModelTool: root === 'profiles' ? agentHarnessModes('workspace_actions', 'workspace_action', 'run_workspace_action') : 'agent_local_registry',
|
|
358
368
|
boundary: 'Local library/profile/session/bundle CLI commands operate on Agent-local data. Mutations require explicit user intent and should use first-class Agent-local tools where available.',
|
|
359
369
|
};
|
|
360
370
|
}
|
|
@@ -370,7 +380,7 @@ export function describeCliCommandPolicy(commandName: string): CommandExecutionP
|
|
|
370
380
|
return {
|
|
371
381
|
effect: 'delegated-work',
|
|
372
382
|
confirmation,
|
|
373
|
-
preferredModelTool: '
|
|
383
|
+
preferredModelTool: agentHarnessModes('workspace_actions', 'workspace_action', 'run_workspace_action'),
|
|
374
384
|
boundary: 'Delegation is explicit user-directed work only; no hidden background review or separate Agent job should be created implicitly.',
|
|
375
385
|
};
|
|
376
386
|
}
|
|
@@ -378,7 +388,9 @@ export function describeCliCommandPolicy(commandName: string): CommandExecutionP
|
|
|
378
388
|
return {
|
|
379
389
|
effect: root === 'pair' ? 'external-network' : 'mixed',
|
|
380
390
|
confirmation,
|
|
381
|
-
preferredModelTool: root === 'pair'
|
|
391
|
+
preferredModelTool: root === 'pair'
|
|
392
|
+
? agentHarnessModes('workspace_actions', 'workspace_action', 'run_workspace_action')
|
|
393
|
+
: `${agentHarnessModes('settings', 'get_setting', 'set_setting', 'reset_setting')} or ${agentHarnessModes('workspace_actions')}`,
|
|
382
394
|
boundary: 'Provider subscription, secret, and pairing flows can expose credentials or external account state. Use only explicit user-directed flows and prefer secret refs over raw values.',
|
|
383
395
|
};
|
|
384
396
|
}
|
|
@@ -618,22 +630,40 @@ export function describeConnectedHostCapability(
|
|
|
618
630
|
return null;
|
|
619
631
|
}
|
|
620
632
|
|
|
621
|
-
export function connectedHostSummary(
|
|
633
|
+
export function connectedHostSummary(
|
|
634
|
+
context: CommandContext,
|
|
635
|
+
toolRegistry: ToolRegistry,
|
|
636
|
+
options: { readonly includeParameters?: boolean } = {},
|
|
637
|
+
): Record<string, unknown> {
|
|
622
638
|
const shellPaths = context.workspace.shellPaths;
|
|
623
639
|
const homeDirectory = shellPaths?.homeDirectory ?? context.platform.configManager.getHomeDirectory() ?? '';
|
|
624
640
|
const connection = resolveAgentConnectedHostConnection(context.platform.configManager, homeDirectory);
|
|
641
|
+
const routeFamilies = connectedHostRouteFamilies();
|
|
642
|
+
const capabilities = connectedHostCapabilityMap(toolRegistry);
|
|
643
|
+
const blockedCapabilities = blockedConnectedHostCapabilities();
|
|
625
644
|
return {
|
|
626
645
|
baseUrl: connection.baseUrl,
|
|
627
646
|
operatorToken: connection.token ? 'configured' : 'missing',
|
|
628
647
|
tokenPath: connection.tokenPath,
|
|
629
648
|
ownership: 'external-connected-host',
|
|
630
649
|
lifecycle: 'GoodVibes Agent can use public connected-host operator routes, but does not start, stop, restart, install, expose, or mutate the host listener.',
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
650
|
+
modes: {
|
|
651
|
+
servicePosture: agentHarnessModes('service_posture', 'service_endpoint'),
|
|
652
|
+
operatorMethods: agentHarnessModes('operator_methods', 'operator_method'),
|
|
653
|
+
liveStatus: agentHarnessModes('connected_host_status'),
|
|
654
|
+
capabilityDetail: agentHarnessModes('connected_host_capability'),
|
|
655
|
+
},
|
|
656
|
+
counts: {
|
|
657
|
+
routeFamilies: routeFamilies.length,
|
|
658
|
+
allowedCapabilities: capabilities.length,
|
|
659
|
+
availableCapabilities: capabilities.filter((capability) => capability.available === true).length,
|
|
660
|
+
blockedCapabilities: blockedCapabilities.length,
|
|
661
|
+
},
|
|
662
|
+
...(options.includeParameters === true ? {
|
|
663
|
+
routeFamilies,
|
|
664
|
+
capabilities,
|
|
665
|
+
blockedCapabilities,
|
|
666
|
+
} : {}),
|
|
637
667
|
};
|
|
638
668
|
}
|
|
639
669
|
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { AGENT_HARNESS_MODES } from './agent-harness-tool-schema.ts';
|
|
2
|
+
|
|
3
|
+
export type AgentHarnessMode = typeof AGENT_HARNESS_MODES[number];
|
|
4
|
+
|
|
5
|
+
type HarnessModeKind = 'summary' | 'discover' | 'inspect' | 'effect' | 'alias';
|
|
6
|
+
|
|
7
|
+
interface HarnessModeDescriptor {
|
|
8
|
+
readonly id: AgentHarnessMode;
|
|
9
|
+
readonly kind: HarnessModeKind;
|
|
10
|
+
readonly family: string;
|
|
11
|
+
readonly summary: string;
|
|
12
|
+
readonly next?: string;
|
|
13
|
+
readonly requiresConfirmation?: boolean;
|
|
14
|
+
readonly aliases?: readonly AgentHarnessMode[];
|
|
15
|
+
readonly parameters?: readonly string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface HarnessModeCatalogArgs {
|
|
19
|
+
readonly query?: unknown;
|
|
20
|
+
readonly target?: unknown;
|
|
21
|
+
readonly includeParameters?: unknown;
|
|
22
|
+
readonly limit?: unknown;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type HarnessModeResolution =
|
|
26
|
+
| { readonly status: 'found'; readonly mode: Record<string, unknown> }
|
|
27
|
+
| { readonly status: 'ambiguous'; readonly input: string; readonly candidates: readonly Record<string, unknown>[] }
|
|
28
|
+
| { readonly status: 'missing_lookup'; readonly usage: string };
|
|
29
|
+
|
|
30
|
+
export const HARNESS_MODE_DESCRIPTORS: readonly HarnessModeDescriptor[] = [
|
|
31
|
+
{ id: 'summary', kind: 'summary', family: 'start', summary: 'Compact harness map, counts, posture, and mode guide.', next: 'Use modes or a plural catalog mode to drill in.', parameters: ['includeParameters'] },
|
|
32
|
+
{ id: 'modes', kind: 'discover', family: 'start', summary: 'Search all agent_harness modes by task, family, effect, or id.', next: 'Use mode for one exact mode contract.', parameters: ['query', 'target', 'limit', 'includeParameters'] },
|
|
33
|
+
{ id: 'mode', kind: 'inspect', family: 'start', summary: 'Inspect one agent_harness mode contract and common next step.', next: 'Use target or query with a mode id or task phrase.', parameters: ['target', 'query'] },
|
|
34
|
+
{ id: 'cli_commands', kind: 'discover', family: 'cli', summary: 'List top-level package CLI mirrors for discovery only.', next: 'Use cli_command for one command.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
35
|
+
{ id: 'cli_command', kind: 'inspect', family: 'cli', summary: 'Inspect one top-level CLI command, parser result, policy, aliases, and safe model route.', parameters: ['cliCommand', 'command', 'commandName', 'target', 'query'] },
|
|
36
|
+
{ id: 'panels', kind: 'discover', family: 'ui', summary: 'List built-in panel catalog state and workspace routes.', next: 'Use panel or open_panel.', parameters: ['query', 'category', 'limit', 'includeParameters'] },
|
|
37
|
+
{ id: 'panel', kind: 'inspect', family: 'ui', summary: 'Inspect one built-in panel, open state, workspace route, and navigation policy.', parameters: ['panelId', 'target', 'query'] },
|
|
38
|
+
{ id: 'open_panel', kind: 'effect', family: 'ui', summary: 'Route the visible shell to one built-in panel.', requiresConfirmation: true, parameters: ['panelId', 'target', 'query', 'pane', 'confirm', 'explicitUserRequest'] },
|
|
39
|
+
{ id: 'ui_surfaces', kind: 'discover', family: 'ui', summary: 'List modal, picker, and visible UI surfaces the model can request.', next: 'Use ui_surface or open_ui_surface.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
40
|
+
{ id: 'ui_surface', kind: 'inspect', family: 'ui', summary: 'Inspect one visible modal or picker surface and route contract.', parameters: ['surfaceId', 'target', 'query'] },
|
|
41
|
+
{ id: 'open_ui_surface', kind: 'effect', family: 'ui', summary: 'Open one visible modal or picker through the shell bridge.', requiresConfirmation: true, parameters: ['surfaceId', 'target', 'query', 'confirm', 'explicitUserRequest'] },
|
|
42
|
+
{ id: 'shortcuts', kind: 'discover', family: 'keyboard', summary: 'List fixed shortcuts and keybinding overview.', next: 'Use keybindings or keybinding for configurable actions.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
43
|
+
{ id: 'keybindings', kind: 'discover', family: 'keyboard', summary: 'List configurable keybinding actions and current/default combos.', next: 'Use keybinding, run_keybinding, set_keybinding, or reset_keybinding.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
44
|
+
{ id: 'keybinding', kind: 'inspect', family: 'keyboard', summary: 'Inspect one keybinding action, route, current combos, defaults, and policy.', parameters: ['actionId', 'key', 'target', 'query'] },
|
|
45
|
+
{ id: 'run_keybinding', kind: 'effect', family: 'keyboard', summary: 'Run one supported keybinding action through the shell bridge.', requiresConfirmation: true, parameters: ['actionId', 'key', 'target', 'query', 'confirm', 'explicitUserRequest'] },
|
|
46
|
+
{ id: 'set_keybinding', kind: 'effect', family: 'keyboard', summary: 'Set one configurable keybinding action.', requiresConfirmation: true, parameters: ['actionId', 'combo', 'combos', 'confirm', 'explicitUserRequest'] },
|
|
47
|
+
{ id: 'reset_keybinding', kind: 'effect', family: 'keyboard', summary: 'Reset one configurable keybinding action to defaults.', requiresConfirmation: true, parameters: ['actionId', 'confirm', 'explicitUserRequest'] },
|
|
48
|
+
{ id: 'commands', kind: 'discover', family: 'slash', summary: 'List registered slash commands and compact policies.', next: 'Use command or run_command.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
49
|
+
{ id: 'command', kind: 'inspect', family: 'slash', summary: 'Inspect one slash command, parsed args, policy, aliases, and preferred model route.', parameters: ['command', 'commandName', 'target', 'query'] },
|
|
50
|
+
{ id: 'run_command', kind: 'effect', family: 'slash', summary: 'Run one slash command through shared command dispatch.', requiresConfirmation: true, parameters: ['command', 'commandName', 'args', 'target', 'query', 'confirm', 'explicitUserRequest'] },
|
|
51
|
+
{ id: 'channels', kind: 'discover', family: 'delivery', summary: 'List channel readiness, accounts, delivery posture, and safe setup keys.', next: 'Use channel or agent_channel_send.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
52
|
+
{ id: 'channel', kind: 'inspect', family: 'delivery', summary: 'Inspect one channel readiness entry and delivery policy.', parameters: ['channelId', 'target', 'query'] },
|
|
53
|
+
{ id: 'notifications', kind: 'discover', family: 'delivery', summary: 'List notification target posture with webhook values redacted.', next: 'Use notification_target or agent_notify.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
54
|
+
{ id: 'notification_target', kind: 'inspect', family: 'delivery', summary: 'Inspect one notification target and safe routing policy.', parameters: ['notificationTargetId', 'target', 'query'] },
|
|
55
|
+
{ id: 'provider_accounts', kind: 'discover', family: 'providers', summary: 'List provider auth, subscription, usage-window, and repair posture.', next: 'Use provider_account.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
56
|
+
{ id: 'provider_account', kind: 'inspect', family: 'providers', summary: 'Inspect one provider account/auth posture without token leakage.', parameters: ['providerId', 'target', 'query'] },
|
|
57
|
+
{ id: 'mcp_servers', kind: 'discover', family: 'tools', summary: 'List MCP server/tool/security posture without exposing env or secrets.', next: 'Use mcp_server.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
58
|
+
{ id: 'mcp_server', kind: 'inspect', family: 'tools', summary: 'Inspect one MCP server, tools, schemas, auth, and trust posture.', parameters: ['mcpServerId', 'target', 'query'] },
|
|
59
|
+
{ id: 'setup_posture', kind: 'discover', family: 'setup', summary: 'Inspect first-run/setup capability posture and derived readiness flags.', next: 'Use setup_item.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
60
|
+
{ id: 'setup_item', kind: 'inspect', family: 'setup', summary: 'Inspect one setup/onboarding posture item and visible remediation route.', parameters: ['setupItemId', 'target', 'query'] },
|
|
61
|
+
{ id: 'model_routing', kind: 'discover', family: 'providers', summary: 'List current model/provider route, available models, pins, and safe route settings.', next: 'Use model_route.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
62
|
+
{ id: 'model_route', kind: 'inspect', family: 'providers', summary: 'Inspect one model route or model candidate and visible selection paths.', parameters: ['modelRouteId', 'target', 'query'] },
|
|
63
|
+
{ id: 'pairing_posture', kind: 'discover', family: 'companion', summary: 'List companion pairing routes, token posture, and connected-host readiness without raw token output.', next: 'Use pairing_route.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
64
|
+
{ id: 'pairing_route', kind: 'inspect', family: 'companion', summary: 'Inspect one companion pairing route and safe visible handoff.', parameters: ['pairingRouteId', 'target', 'query'] },
|
|
65
|
+
{ id: 'delegation_posture', kind: 'discover', family: 'delegation', summary: 'List explicit build/fix/review delegation routes and boundaries.', next: 'Use delegation_route.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
66
|
+
{ id: 'delegation_route', kind: 'inspect', family: 'delegation', summary: 'Inspect one delegation route and exact visible submission contract.', parameters: ['delegationRouteId', 'target', 'query'] },
|
|
67
|
+
{ id: 'security_posture', kind: 'discover', family: 'security', summary: 'List security posture findings without exposing secrets or raw config.', next: 'Use security_finding.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
68
|
+
{ id: 'security_finding', kind: 'inspect', family: 'security', summary: 'Inspect one security posture finding and safe remediation route.', parameters: ['findingId', 'target', 'query'] },
|
|
69
|
+
{ id: 'support_bundles', kind: 'discover', family: 'support', summary: 'List support bundle artifacts and redacted export/import posture.', next: 'Use support_bundle.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
70
|
+
{ id: 'support_bundle', kind: 'inspect', family: 'support', summary: 'Inspect one support bundle artifact and redaction posture.', parameters: ['bundlePath', 'target', 'query'] },
|
|
71
|
+
{ id: 'media_posture', kind: 'discover', family: 'media', summary: 'List voice/media provider readiness, browser posture, and artifact routes.', next: 'Use media_provider or agent_media_generate.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
72
|
+
{ id: 'media_provider', kind: 'inspect', family: 'media', summary: 'Inspect one voice or media provider readiness entry.', parameters: ['mediaProviderId', 'target', 'query'] },
|
|
73
|
+
{ id: 'sessions', kind: 'discover', family: 'sessions', summary: 'List saved sessions, bookmarks, exports, and pending approvals posture.', next: 'Use session.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
74
|
+
{ id: 'session', kind: 'inspect', family: 'sessions', summary: 'Inspect one saved session or bookmark entry.', parameters: ['sessionId', 'target', 'query'] },
|
|
75
|
+
{ id: 'settings', kind: 'discover', family: 'settings', summary: 'Search Agent settings compactly by category, prefix, or query.', next: 'Use get_setting, set_setting, or reset_setting.', parameters: ['category', 'prefix', 'query', 'includeHidden', 'limit', 'includeParameters'] },
|
|
76
|
+
{ id: 'get_setting', kind: 'inspect', family: 'settings', summary: 'Inspect one Agent setting descriptor, current value, default, and policy.', parameters: ['key', 'target', 'query'] },
|
|
77
|
+
{ id: 'set_setting', kind: 'effect', family: 'settings', summary: 'Set one Agent-owned setting through config/secret managers.', requiresConfirmation: true, parameters: ['key', 'target', 'query', 'value', 'confirm', 'explicitUserRequest'] },
|
|
78
|
+
{ id: 'reset_setting', kind: 'effect', family: 'settings', summary: 'Reset one Agent-owned setting and delete secret refs when needed.', requiresConfirmation: true, parameters: ['key', 'target', 'query', 'confirm', 'explicitUserRequest'] },
|
|
79
|
+
{ id: 'workspace', kind: 'discover', family: 'workspace', summary: 'List Agent workspace categories and action counts.', next: 'Use workspace_actions or workspace_action.' },
|
|
80
|
+
{ id: 'workspace_categories', kind: 'discover', family: 'workspace', summary: 'Alias of workspace for category discovery.', next: 'Use workspace_actions or workspace_action.', aliases: ['workspace'] },
|
|
81
|
+
{ id: 'workspace_actions', kind: 'discover', family: 'workspace', summary: 'Search all user-facing Agent workspace actions and compact model routes.', next: 'Use workspace_action or run_workspace_action.', parameters: ['categoryId', 'query', 'limit', 'includeParameters'] },
|
|
82
|
+
{ id: 'workspace_action', kind: 'inspect', family: 'workspace', summary: 'Inspect one workspace action, editor schema, route bridge, and safety policy.', parameters: ['actionId', 'command', 'target', 'query', 'recordId'] },
|
|
83
|
+
{ id: 'run_workspace_action', kind: 'effect', family: 'workspace', summary: 'Run one supported workspace action or return its concrete model execution handoff.', requiresConfirmation: true, parameters: ['actionId', 'command', 'target', 'query', 'recordId', 'fields', 'confirm', 'explicitUserRequest'] },
|
|
84
|
+
{ id: 'tools', kind: 'discover', family: 'tools', summary: 'List first-class model tool definitions compactly.', next: 'Use tool for full schema.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
85
|
+
{ id: 'tool', kind: 'inspect', family: 'tools', summary: 'Inspect one first-class model tool definition and JSON schema.', parameters: ['toolName', 'target', 'query'] },
|
|
86
|
+
{ id: 'release_evidence', kind: 'discover', family: 'release', summary: 'List packaged release evidence artifacts compactly.', next: 'Use release_evidence_artifact.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
87
|
+
{ id: 'release_evidence_artifact', kind: 'inspect', family: 'release', summary: 'Inspect one release evidence artifact and optional content.', parameters: ['artifactId', 'target', 'query'] },
|
|
88
|
+
{ id: 'release_readiness', kind: 'discover', family: 'release', summary: 'Search the release-quality readiness inventory.', next: 'Use release_readiness_item.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
89
|
+
{ id: 'release_readiness_item', kind: 'inspect', family: 'release', summary: 'Inspect one release-quality readiness inventory item.', parameters: ['itemId', 'target', 'query'] },
|
|
90
|
+
{ id: 'operator_methods', kind: 'discover', family: 'operator', summary: 'List allowlisted public operator/Agent Knowledge methods and owning tools.', next: 'Use operator_method.', parameters: ['query', 'limit', 'includeParameters'] },
|
|
91
|
+
{ id: 'operator_method', kind: 'inspect', family: 'operator', summary: 'Inspect one allowlisted operator method and preferred first-class model tool.', parameters: ['methodId', 'target', 'query'] },
|
|
92
|
+
{ id: 'service_posture', kind: 'discover', family: 'connected-host', summary: 'Inspect connected service endpoint posture, binding, issues, and optional probes.', next: 'Use service_endpoint.', parameters: ['includeParameters'] },
|
|
93
|
+
{ id: 'service_endpoint', kind: 'inspect', family: 'connected-host', summary: 'Inspect one connected service endpoint binding and lifecycle boundary.', parameters: ['endpointId', 'target', 'query'] },
|
|
94
|
+
{ id: 'connected_host', kind: 'discover', family: 'connected-host', summary: 'Map connected-host capabilities, boundaries, and model tool availability.', next: 'Use connected_host_capability or connected_host_status.', parameters: ['includeParameters'] },
|
|
95
|
+
{ id: 'connected_host_status', kind: 'inspect', family: 'connected-host', summary: 'Run live read-only connected-host readiness checks.', parameters: ['includeParameters'] },
|
|
96
|
+
{ id: 'connected_host_capability', kind: 'inspect', family: 'connected-host', summary: 'Inspect one connected-host capability and blocked lifecycle/non-Agent surfaces.', parameters: ['capabilityId', 'target', 'query'] },
|
|
97
|
+
{ id: 'daemon', kind: 'alias', family: 'connected-host', summary: 'Alias for connected_host posture. Does not expose lifecycle control.', next: 'Use connected_host for canonical naming.', aliases: ['connected_host'], parameters: ['includeParameters'] },
|
|
98
|
+
{ id: 'daemon_status', kind: 'alias', family: 'connected-host', summary: 'Alias for connected_host_status live readiness. Does not expose lifecycle control.', next: 'Use connected_host_status for canonical naming.', aliases: ['connected_host_status'], parameters: ['includeParameters'] },
|
|
99
|
+
] as const;
|
|
100
|
+
|
|
101
|
+
function readString(value: unknown): string {
|
|
102
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function readLimit(value: unknown, fallback: number): number {
|
|
106
|
+
const parsed = typeof value === 'string' && value.trim() ? Number(value) : value;
|
|
107
|
+
if (typeof parsed !== 'number' || !Number.isFinite(parsed)) return fallback;
|
|
108
|
+
return Math.max(1, Math.min(500, Math.trunc(parsed)));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function describeHarnessModeDescriptor(
|
|
112
|
+
descriptor: HarnessModeDescriptor,
|
|
113
|
+
options: { readonly includeParameters?: boolean; readonly lookup?: Record<string, unknown> } = {},
|
|
114
|
+
): Record<string, unknown> {
|
|
115
|
+
return {
|
|
116
|
+
id: descriptor.id,
|
|
117
|
+
kind: descriptor.kind,
|
|
118
|
+
family: descriptor.family,
|
|
119
|
+
summary: descriptor.summary,
|
|
120
|
+
...(descriptor.next ? { next: descriptor.next } : {}),
|
|
121
|
+
...(descriptor.requiresConfirmation ? { requiresConfirmation: true } : {}),
|
|
122
|
+
...(descriptor.aliases ? { aliases: descriptor.aliases } : {}),
|
|
123
|
+
...(options.lookup ? { lookup: options.lookup } : {}),
|
|
124
|
+
...(options.includeParameters ? {
|
|
125
|
+
parameters: descriptor.parameters ?? [],
|
|
126
|
+
route: `agent_harness mode:"${descriptor.id}"`,
|
|
127
|
+
} : {}),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function harnessModeSearchText(descriptor: HarnessModeDescriptor): string {
|
|
132
|
+
return [
|
|
133
|
+
descriptor.id,
|
|
134
|
+
descriptor.id.replace(/_/g, ' '),
|
|
135
|
+
descriptor.kind,
|
|
136
|
+
descriptor.family,
|
|
137
|
+
descriptor.summary,
|
|
138
|
+
descriptor.next,
|
|
139
|
+
...(descriptor.aliases ?? []),
|
|
140
|
+
...(descriptor.parameters ?? []),
|
|
141
|
+
].filter(Boolean).join('\n').toLowerCase();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function harnessModeMatchesSearch(descriptor: HarnessModeDescriptor, input: string): boolean {
|
|
145
|
+
const text = harnessModeSearchText(descriptor);
|
|
146
|
+
const normalized = input.toLowerCase().trim();
|
|
147
|
+
if (normalized.length === 0) return true;
|
|
148
|
+
if (text.includes(normalized)) return true;
|
|
149
|
+
const tokens = normalized.split(/[^a-z0-9]+/).filter((token) => token.length > 0);
|
|
150
|
+
return tokens.length > 0 && tokens.every((token) => text.includes(token));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function modeLookupInput(args: HarnessModeCatalogArgs): { readonly source: 'target' | 'query'; readonly input: string } | null {
|
|
154
|
+
const target = readString(args.target);
|
|
155
|
+
if (target) return { source: 'target', input: target };
|
|
156
|
+
const query = readString(args.query);
|
|
157
|
+
return query ? { source: 'query', input: query } : null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function listHarnessModes(args: HarnessModeCatalogArgs): Record<string, unknown> {
|
|
161
|
+
const lookup = modeLookupInput(args);
|
|
162
|
+
const limit = readLimit(args.limit, 120);
|
|
163
|
+
const normalized = lookup?.input.toLowerCase() ?? '';
|
|
164
|
+
const modes = HARNESS_MODE_DESCRIPTORS
|
|
165
|
+
.filter((descriptor) => harnessModeMatchesSearch(descriptor, normalized))
|
|
166
|
+
.map((descriptor) => describeHarnessModeDescriptor(descriptor, { includeParameters: args.includeParameters === true }))
|
|
167
|
+
.slice(0, limit);
|
|
168
|
+
return {
|
|
169
|
+
modes,
|
|
170
|
+
returned: modes.length,
|
|
171
|
+
total: HARNESS_MODE_DESCRIPTORS.length,
|
|
172
|
+
families: Array.from(new Set(HARNESS_MODE_DESCRIPTORS.map((descriptor) => descriptor.family))).sort(),
|
|
173
|
+
policy: 'Mode discovery is read-only. Effect modes still require confirm:true and explicitUserRequest.',
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function describeHarnessMode(args: HarnessModeCatalogArgs): HarnessModeResolution {
|
|
178
|
+
const lookup = modeLookupInput(args);
|
|
179
|
+
if (!lookup) {
|
|
180
|
+
return {
|
|
181
|
+
status: 'missing_lookup',
|
|
182
|
+
usage: 'mode inspection requires target or query. Use mode:"modes" to search available harness modes.',
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const normalized = lookup.input.toLowerCase();
|
|
186
|
+
const exact = HARNESS_MODE_DESCRIPTORS.find((descriptor) => descriptor.id === lookup.input);
|
|
187
|
+
if (exact) return { status: 'found', mode: describeHarnessModeDescriptor(exact, { includeParameters: true, lookup: { ...lookup, resolvedBy: 'id' } }) };
|
|
188
|
+
const insensitive = HARNESS_MODE_DESCRIPTORS.find((descriptor) => descriptor.id.toLowerCase() === normalized);
|
|
189
|
+
if (insensitive) return { status: 'found', mode: describeHarnessModeDescriptor(insensitive, { includeParameters: true, lookup: { ...lookup, resolvedBy: 'case-insensitive-id' } }) };
|
|
190
|
+
const searched = HARNESS_MODE_DESCRIPTORS.filter((descriptor) => harnessModeMatchesSearch(descriptor, normalized));
|
|
191
|
+
if (searched.length === 1) {
|
|
192
|
+
return { status: 'found', mode: describeHarnessModeDescriptor(searched[0]!, { includeParameters: true, lookup: { ...lookup, resolvedBy: 'search' } }) };
|
|
193
|
+
}
|
|
194
|
+
if (searched.length > 1) {
|
|
195
|
+
return {
|
|
196
|
+
status: 'ambiguous',
|
|
197
|
+
input: lookup.input,
|
|
198
|
+
candidates: searched.slice(0, 12).map((descriptor) => describeHarnessModeDescriptor(descriptor)),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
status: 'missing_lookup',
|
|
203
|
+
usage: `Unknown harness mode ${lookup.input}. Use mode:"modes" to inspect available modes.`,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
@@ -320,19 +320,19 @@ function describeRoute(route: RouteCandidate, options: { readonly includeParamet
|
|
|
320
320
|
commands: route.commands,
|
|
321
321
|
uiSurfaces: route.uiSurfaces,
|
|
322
322
|
...(options.lookup ? { lookup: options.lookup } : {}),
|
|
323
|
-
policy: {
|
|
324
|
-
effect: 'read-only',
|
|
325
|
-
values: 'Model routing posture returns model ids, provider ids, route state, capabilities, and safe setting keys only; provider credentials are never returned.',
|
|
326
|
-
mutation: 'Model/provider selection, catalog refresh, favorites, custom provider edits, and route setting changes stay explicit user-facing picker, settings, workspace, or slash-command flows.',
|
|
327
|
-
},
|
|
328
323
|
...(options.includeParameters ? {
|
|
324
|
+
policy: {
|
|
325
|
+
effect: 'read-only',
|
|
326
|
+
values: 'Model routing posture returns model ids, provider ids, route state, capabilities, and safe setting keys only; provider credentials are never returned.',
|
|
327
|
+
mutation: 'Model/provider selection, catalog refresh, favorites, custom provider edits, and route setting changes stay explicit user-facing picker, settings, workspace, or slash-command flows.',
|
|
328
|
+
},
|
|
329
329
|
modelAccess: {
|
|
330
330
|
inspectRouting: 'agent_harness mode:"model_routing"',
|
|
331
331
|
inspectRoute: 'agent_harness mode:"model_route"',
|
|
332
332
|
settingRead: 'agent_harness mode:"get_setting"',
|
|
333
333
|
settingMutation: 'agent_harness mode:"set_setting" confirm:true explicitUserRequest:"..."',
|
|
334
|
-
openModelPicker: 'agent_harness mode:"open_ui_surface" surfaceId:"model-picker" confirm:true',
|
|
335
|
-
openProviderPicker: 'agent_harness mode:"open_ui_surface" surfaceId:"provider-picker" confirm:true',
|
|
334
|
+
openModelPicker: 'agent_harness mode:"open_ui_surface" surfaceId:"model-picker" confirm:true explicitUserRequest:"..."',
|
|
335
|
+
openProviderPicker: 'agent_harness mode:"open_ui_surface" surfaceId:"provider-picker" confirm:true explicitUserRequest:"..."',
|
|
336
336
|
},
|
|
337
337
|
} : {}),
|
|
338
338
|
};
|
|
@@ -350,19 +350,19 @@ function describeModel(model: ModelCandidate, options: { readonly includeParamet
|
|
|
350
350
|
pinned: model.pinned,
|
|
351
351
|
contextWindow: model.contextWindow,
|
|
352
352
|
reasoningEffort: model.reasoningEffort,
|
|
353
|
-
capabilities: model.capabilities,
|
|
354
353
|
...(options.lookup ? { lookup: options.lookup } : {}),
|
|
355
|
-
policy: {
|
|
356
|
-
effect: 'read-only',
|
|
357
|
-
mutation: 'Selecting this model stays a visible picker, settings, workspace, or slash-command flow with explicit user request.',
|
|
358
|
-
},
|
|
359
354
|
...(options.includeParameters ? {
|
|
355
|
+
capabilities: model.capabilities,
|
|
356
|
+
policy: {
|
|
357
|
+
effect: 'read-only',
|
|
358
|
+
mutation: 'Selecting this model stays a visible picker, settings, workspace, or slash-command flow with explicit user request.',
|
|
359
|
+
},
|
|
360
360
|
modelAccess: {
|
|
361
361
|
selectModelCommand: `/model ${model.registryKey}`,
|
|
362
362
|
selectProviderCommand: `/provider ${model.providerId}`,
|
|
363
363
|
pinCommand: `/pin ${model.registryKey}`,
|
|
364
364
|
unpinCommand: `/unpin ${model.registryKey}`,
|
|
365
|
-
setMainModel: `agent_harness mode:"set_setting" key:"provider.model" value:"${model.registryKey}" confirm:true`,
|
|
365
|
+
setMainModel: `agent_harness mode:"set_setting" key:"provider.model" value:"${model.registryKey}" confirm:true explicitUserRequest:"..."`,
|
|
366
366
|
},
|
|
367
367
|
} : {}),
|
|
368
368
|
};
|
|
@@ -433,7 +433,7 @@ export async function modelRoutingSummary(context: CommandContext, args: AgentHa
|
|
|
433
433
|
reasoningEffort: modelReasoning(currentModel),
|
|
434
434
|
capabilities: modelCapabilities(currentModel),
|
|
435
435
|
pinned: false,
|
|
436
|
-
}) : null,
|
|
436
|
+
}, { includeParameters }) : null,
|
|
437
437
|
},
|
|
438
438
|
providers: providerIds,
|
|
439
439
|
routes: filteredRoutes.slice(0, limit).map((route) => describeRoute(route, { includeParameters })),
|
|
@@ -25,6 +25,11 @@ function readLimit(value: unknown, fallback: number): number {
|
|
|
25
25
|
return Math.max(1, Math.min(500, Math.trunc(parsed)));
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
function previewText(value: string, maxLength = 120): string {
|
|
29
|
+
const normalized = value.replace(/\s+/g, ' ').trim();
|
|
30
|
+
return normalized.length <= maxLength ? normalized : `${normalized.slice(0, maxLength - 1).trimEnd()}...`;
|
|
31
|
+
}
|
|
32
|
+
|
|
28
33
|
function modelToolSearchText(tool: HarnessModelToolDefinition): string {
|
|
29
34
|
return [
|
|
30
35
|
tool.name,
|
|
@@ -45,7 +50,7 @@ function modelToolLookupFromArgs(args: AgentHarnessModelToolCatalogArgs): { read
|
|
|
45
50
|
function describeModelTool(tool: HarnessModelToolDefinition, options: { readonly includeParameters?: boolean; readonly lookup?: Record<string, unknown> } = {}): Record<string, unknown> {
|
|
46
51
|
return {
|
|
47
52
|
name: tool.name,
|
|
48
|
-
description: tool.description,
|
|
53
|
+
...(options.includeParameters ? { description: tool.description } : { summary: previewText(tool.description) }),
|
|
49
54
|
sideEffects: tool.sideEffects ?? [],
|
|
50
55
|
concurrency: tool.concurrency ?? 'parallel',
|
|
51
56
|
supportsProgress: tool.supportsProgress ?? false,
|
|
@@ -58,7 +63,7 @@ function describeModelTool(tool: HarnessModelToolDefinition, options: { readonly
|
|
|
58
63
|
function describeModelToolCandidates(tools: readonly HarnessModelToolDefinition[]): readonly Record<string, unknown>[] {
|
|
59
64
|
return tools.slice(0, 8).map((tool) => ({
|
|
60
65
|
toolName: tool.name,
|
|
61
|
-
|
|
66
|
+
summary: previewText(tool.description),
|
|
62
67
|
sideEffects: tool.sideEffects ?? [],
|
|
63
68
|
}));
|
|
64
69
|
}
|