@pellux/goodvibes-agent 1.0.34 → 1.0.36
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 +28 -13
- package/README.md +11 -8
- package/dist/package/main.js +1592 -921
- package/docs/README.md +6 -5
- package/docs/channels-remote-and-api.md +3 -3
- package/docs/connected-host.md +3 -3
- package/docs/getting-started.md +20 -12
- package/docs/knowledge-artifacts-and-multimodal.md +9 -4
- package/docs/project-planning.md +3 -3
- package/docs/providers-and-routing.md +2 -2
- package/docs/release-and-publishing.md +8 -8
- package/docs/tools-and-commands.md +34 -17
- package/docs/voice-and-live-tts.md +1 -1
- package/package.json +1 -1
- package/release/live-verification/live-verification.json +15 -15
- package/release/live-verification/live-verification.md +19 -21
- package/release/release-notes.md +6 -6
- package/release/release-readiness.json +64 -64
- package/src/agent/harness-control.ts +35 -9
- package/src/agent/reminder-schedule-format.ts +2 -5
- package/src/agent/reminder-schedule.ts +4 -11
- package/src/agent/routine-schedule-format.ts +3 -6
- package/src/agent/routine-schedule-promotion.ts +5 -14
- package/src/agent/routine-schedule-receipts.ts +4 -9
- package/src/cli/agent-knowledge-command.ts +6 -11
- package/src/cli/agent-knowledge-format.ts +4 -9
- package/src/cli/agent-knowledge-runtime.ts +7 -14
- package/src/cli/external-runtime.ts +3 -46
- package/src/cli/help.ts +2 -2
- package/src/cli/status.ts +6 -7
- package/src/input/agent-workspace-categories.ts +23 -23
- package/src/input/agent-workspace-channels.ts +3 -3
- package/src/input/agent-workspace-operations-command-editors.ts +1 -1
- package/src/input/command-registry.ts +1 -1
- package/src/input/commands/compat-runtime.ts +1 -1
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/runtime-services.ts +1 -1
- package/src/input/mcp-workspace.ts +1 -1
- package/src/input/submission-router.ts +1 -1
- package/src/panels/builtin/shared.ts +1 -1
- package/src/panels/project-planning-panel.ts +4 -4
- package/src/panels/qr-panel.ts +2 -2
- package/src/renderer/conversation-overlays.ts +1 -0
- package/src/runtime/bootstrap-command-parts.ts +1 -1
- package/src/runtime/bootstrap-core.ts +3 -1
- package/src/runtime/bootstrap-hook-bridge.ts +1 -1
- package/src/runtime/bootstrap-shell.ts +1 -1
- package/src/runtime/bootstrap.ts +7 -4
- package/src/runtime/context.ts +2 -2
- package/src/runtime/index.ts +88 -5
- package/src/runtime/store/state.ts +1 -1
- package/src/tools/agent-channel-send-tool.ts +1 -1
- package/src/tools/agent-harness-channel-metadata.ts +36 -25
- package/src/tools/agent-harness-cli-metadata.ts +19 -1
- package/src/tools/agent-harness-command-catalog.ts +15 -4
- package/src/tools/agent-harness-connected-host-status.ts +7 -6
- package/src/tools/agent-harness-delegation-posture.ts +15 -4
- package/src/tools/agent-harness-keybinding-metadata.ts +67 -16
- package/src/tools/agent-harness-mcp-metadata.ts +11 -3
- package/src/tools/agent-harness-media-posture.ts +25 -14
- package/src/tools/agent-harness-metadata.ts +140 -37
- package/src/tools/agent-harness-mode-catalog.ts +258 -0
- package/src/tools/agent-harness-model-routing.ts +18 -3
- package/src/tools/agent-harness-model-tool-catalog.ts +85 -7
- package/src/tools/agent-harness-notification-metadata.ts +30 -19
- package/src/tools/agent-harness-operator-methods.ts +15 -10
- package/src/tools/agent-harness-pairing-posture.ts +17 -5
- package/src/tools/agent-harness-panel-metadata.ts +10 -4
- package/src/tools/agent-harness-provider-account-metadata.ts +46 -35
- package/src/tools/agent-harness-release-evidence.ts +31 -3
- package/src/tools/agent-harness-release-readiness.ts +30 -0
- package/src/tools/agent-harness-security-posture.ts +18 -4
- package/src/tools/agent-harness-service-posture.ts +9 -2
- package/src/tools/agent-harness-session-metadata.ts +24 -8
- package/src/tools/agent-harness-setup-posture.ts +32 -21
- package/src/tools/agent-harness-text.ts +6 -0
- package/src/tools/agent-harness-tool-schema.ts +1 -1
- package/src/tools/agent-harness-tool.ts +38 -36
- package/src/tools/agent-harness-ui-surface-metadata.ts +105 -101
- package/src/tools/agent-harness-workspace-actions.ts +64 -3
- package/src/tools/agent-knowledge-ingest-tool.ts +1 -1
- package/src/tools/agent-knowledge-tool.ts +1 -1
- package/src/tools/agent-media-generate-tool.ts +2 -2
- package/src/tools/agent-notify-tool.ts +1 -1
- package/src/tools/agent-reminder-schedule-tool.ts +1 -1
- package/src/tools/tool-definition-compaction.ts +76 -0
- package/src/version.ts +2 -8
|
@@ -4,6 +4,7 @@ import { GOODVIBES_AGENT_PAIRING_SURFACE } from '../config/surface.ts';
|
|
|
4
4
|
import { resolveRuntimeEndpointBinding } from '../cli/endpoints.ts';
|
|
5
5
|
import { connectedHostOperatorTokenFingerprint, readConnectedHostOperatorToken } from '../runtime/connected-host-auth.ts';
|
|
6
6
|
import { requirePlatform, requireShellPaths } from '../input/commands/runtime-services.ts';
|
|
7
|
+
import { previewHarnessText } from './agent-harness-text.ts';
|
|
7
8
|
|
|
8
9
|
export interface AgentHarnessPairingArgs {
|
|
9
10
|
readonly pairingRouteId?: unknown;
|
|
@@ -101,7 +102,7 @@ function pairingRoutes(): readonly PairingRoute[] {
|
|
|
101
102
|
{
|
|
102
103
|
id: 'connected-host-status',
|
|
103
104
|
label: 'Connected host live posture',
|
|
104
|
-
detail: 'Read-only reachability, token posture,
|
|
105
|
+
detail: 'Read-only reachability, token posture, and route readiness used before companion setup.',
|
|
105
106
|
effect: 'read-only',
|
|
106
107
|
harnessRoute: 'agent_harness mode:"connected_host_status"',
|
|
107
108
|
capabilityIds: ['connected-host-status'],
|
|
@@ -152,6 +153,7 @@ function describeCandidate(route: PairingRoute): Record<string, unknown> {
|
|
|
152
153
|
label: route.label,
|
|
153
154
|
effect: route.effect,
|
|
154
155
|
requiresConfirmation: route.requiresConfirmation === true,
|
|
156
|
+
modelRoute: pairingRouteModelRoute(route),
|
|
155
157
|
};
|
|
156
158
|
}
|
|
157
159
|
|
|
@@ -159,12 +161,15 @@ function describeRoute(route: PairingRoute, options: { readonly includeParameter
|
|
|
159
161
|
return {
|
|
160
162
|
pairingRouteId: route.id,
|
|
161
163
|
label: route.label,
|
|
162
|
-
detail: route.detail,
|
|
164
|
+
...(options.includeParameters ? { detail: route.detail } : { summary: previewHarnessText(route.detail) }),
|
|
163
165
|
effect: route.effect,
|
|
164
|
-
...(route.command ? { command: route.command } : {}),
|
|
165
|
-
...(route.harnessRoute ? { harnessRoute: route.harnessRoute } : {}),
|
|
166
|
-
...(route.capabilityIds ? { capabilityIds: route.capabilityIds } : {}),
|
|
167
166
|
requiresConfirmation: route.requiresConfirmation === true,
|
|
167
|
+
modelRoute: pairingRouteModelRoute(route),
|
|
168
|
+
...(options.includeParameters ? {
|
|
169
|
+
...(route.command ? { command: route.command } : {}),
|
|
170
|
+
...(route.harnessRoute ? { harnessRoute: route.harnessRoute } : {}),
|
|
171
|
+
...(route.capabilityIds ? { capabilityIds: route.capabilityIds } : {}),
|
|
172
|
+
} : {}),
|
|
168
173
|
...(options.lookup ? { lookup: options.lookup } : {}),
|
|
169
174
|
...(options.includeParameters ? {
|
|
170
175
|
policy: {
|
|
@@ -183,6 +188,13 @@ function describeRoute(route: PairingRoute, options: { readonly includeParameter
|
|
|
183
188
|
};
|
|
184
189
|
}
|
|
185
190
|
|
|
191
|
+
function pairingRouteModelRoute(route: PairingRoute): string {
|
|
192
|
+
if (route.command === '/pair') return 'agent_harness mode:"run_command" command:"/pair"';
|
|
193
|
+
if (route.command === '/pair --show-token --yes') return 'agent_harness mode:"run_command" command:"/pair --show-token --yes"';
|
|
194
|
+
if (route.id === 'pairing-ui') return 'agent_harness mode:"workspace_action" target:"pair"';
|
|
195
|
+
return previewHarnessText(route.harnessRoute ?? 'agent_harness mode:"pairing_route"');
|
|
196
|
+
}
|
|
197
|
+
|
|
186
198
|
function pairingState(context: CommandContext): Record<string, unknown> {
|
|
187
199
|
const shellPaths = requireShellPaths(context);
|
|
188
200
|
const configManager = requirePlatform(context).configManager;
|
|
@@ -40,9 +40,9 @@ function readLimit(value: unknown, fallback: number): number {
|
|
|
40
40
|
return Math.max(1, Math.min(500, Math.trunc(parsed)));
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
function previewText(value: string, maxLength =
|
|
43
|
+
function previewText(value: string, maxLength = 56): string {
|
|
44
44
|
const normalized = value.replace(/\s+/g, ' ').trim();
|
|
45
|
-
return normalized.length <= maxLength ? normalized : `${normalized.slice(0, maxLength -
|
|
45
|
+
return normalized.length <= maxLength ? normalized : `${normalized.slice(0, maxLength - 3).trimEnd()}...`;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
function panelManager(context: CommandContext) {
|
|
@@ -77,6 +77,7 @@ function panelCandidate(registration: PanelRegistration): Record<string, unknown
|
|
|
77
77
|
name: registration.name,
|
|
78
78
|
category: registration.category,
|
|
79
79
|
summary: previewText(registration.description),
|
|
80
|
+
modelRoute: panelModelRoute(),
|
|
80
81
|
workspaceRoute: {
|
|
81
82
|
categoryId: agentWorkspaceCategoryForPanel(registration.id),
|
|
82
83
|
command: agentWorkspaceCommandForPanel(registration.id),
|
|
@@ -84,6 +85,10 @@ function panelCandidate(registration: PanelRegistration): Record<string, unknown
|
|
|
84
85
|
};
|
|
85
86
|
}
|
|
86
87
|
|
|
88
|
+
function panelModelRoute(): string {
|
|
89
|
+
return 'agent_harness mode:"open_panel" or mode:"workspace_actions"';
|
|
90
|
+
}
|
|
91
|
+
|
|
87
92
|
function resolveHarnessPanel(context: CommandContext, args: AgentHarnessPanelArgs): PanelResolution | null {
|
|
88
93
|
const manager = panelManager(context);
|
|
89
94
|
const lookup = panelLookupFromArgs(args);
|
|
@@ -131,6 +136,7 @@ function describePanelRegistration(
|
|
|
131
136
|
pane,
|
|
132
137
|
active: activePanel?.id === registration.id,
|
|
133
138
|
focused: activePanel?.id === registration.id,
|
|
139
|
+
modelRoute: panelModelRoute(),
|
|
134
140
|
workspaceRoute: {
|
|
135
141
|
categoryId: agentWorkspaceCategoryForPanel(registration.id),
|
|
136
142
|
command: agentWorkspaceCommandForPanel(registration.id),
|
|
@@ -139,7 +145,7 @@ function describePanelRegistration(
|
|
|
139
145
|
policy: {
|
|
140
146
|
effect: 'ui-navigation',
|
|
141
147
|
confirmation: 'agent_harness mode:"open_panel" requires confirm:true and explicitUserRequest.',
|
|
142
|
-
boundary: 'Panels are Agent/TUI operator views. The model can inspect panel catalog/open state; panel routing uses the existing Agent workspace
|
|
148
|
+
boundary: 'Panels are Agent/TUI operator views. The model can inspect panel catalog/open state; panel routing uses the existing Agent workspace route and does not mutate connected-host lifecycle.',
|
|
143
149
|
},
|
|
144
150
|
} : {}),
|
|
145
151
|
};
|
|
@@ -200,6 +206,6 @@ export function openHarnessPanel(context: CommandContext, args: AgentHarnessPane
|
|
|
200
206
|
status: 'routed',
|
|
201
207
|
panel,
|
|
202
208
|
pane: pane ?? 'default',
|
|
203
|
-
note: 'Panel routing was handed to the current Agent
|
|
209
|
+
note: 'Panel routing was handed to the current Agent operator surface.',
|
|
204
210
|
};
|
|
205
211
|
}
|
|
@@ -2,6 +2,7 @@ import type { CommandContext } from '../input/command-registry.ts';
|
|
|
2
2
|
import type { ProviderAccountRecord, ProviderAccountSnapshot } from '../panels/provider-account-snapshot.ts';
|
|
3
3
|
import { buildProviderAccountSnapshot } from '../panels/provider-account-snapshot.ts';
|
|
4
4
|
import { requireProvider, requireServiceRegistry, requireSubscriptionManager } from '../input/commands/runtime-services.ts';
|
|
5
|
+
import { previewHarnessText } from './agent-harness-text.ts';
|
|
5
6
|
|
|
6
7
|
export interface AgentHarnessProviderAccountArgs {
|
|
7
8
|
readonly providerId?: unknown;
|
|
@@ -74,9 +75,14 @@ function describeCandidate(account: ProviderAccountRecord): Record<string, unkno
|
|
|
74
75
|
authFreshness: account.authFreshness,
|
|
75
76
|
configured: account.configured,
|
|
76
77
|
issues: account.issues.length,
|
|
78
|
+
modelRoute: providerAccountModelRoute(),
|
|
77
79
|
};
|
|
78
80
|
}
|
|
79
81
|
|
|
82
|
+
function providerAccountModelRoute(): string {
|
|
83
|
+
return 'agent_harness mode:"provider_account" or mode:"run_command"';
|
|
84
|
+
}
|
|
85
|
+
|
|
80
86
|
function describeAccount(
|
|
81
87
|
account: ProviderAccountRecord,
|
|
82
88
|
options: { readonly includeParameters?: boolean; readonly lookup?: Record<string, unknown> } = {},
|
|
@@ -99,42 +105,47 @@ function describeAccount(
|
|
|
99
105
|
...(account.tokenType ? { tokenType: account.tokenType } : {}),
|
|
100
106
|
issueCount: account.issues.length,
|
|
101
107
|
recommendedActionCount: account.recommendedActions.length,
|
|
108
|
+
modelRoute: providerAccountModelRoute(),
|
|
102
109
|
...(options.lookup ? { lookup: options.lookup } : {}),
|
|
103
|
-
...(options.includeParameters
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
110
|
+
...(options.includeParameters
|
|
111
|
+
? {
|
|
112
|
+
routeRecords: account.routeRecords.map((route) => ({
|
|
113
|
+
route: route.route,
|
|
114
|
+
usable: route.usable,
|
|
115
|
+
freshness: route.freshness,
|
|
116
|
+
detail: route.detail,
|
|
117
|
+
issues: route.issues,
|
|
118
|
+
})),
|
|
119
|
+
usageWindows: account.usageWindows,
|
|
120
|
+
issues: account.issues,
|
|
121
|
+
notes: account.notes,
|
|
122
|
+
recommendedActions: account.recommendedActions,
|
|
123
|
+
policy: {
|
|
124
|
+
effect: 'read-only',
|
|
125
|
+
values: 'Provider account posture reports route and freshness metadata only; raw tokens, authorization codes, and secret values are never returned.',
|
|
126
|
+
mutation: 'Provider login, logout, subscription bundle export, and account repair actions stay explicit confirmation-gated workspace or slash-command flows.',
|
|
127
|
+
},
|
|
128
|
+
modelAccess: {
|
|
129
|
+
reviewCommand: '/accounts review',
|
|
130
|
+
showCommand: `/accounts show ${account.providerId}`,
|
|
131
|
+
routesCommand: `/accounts routes ${account.providerId}`,
|
|
132
|
+
repairCommand: `/accounts repair ${account.providerId}`,
|
|
133
|
+
subscriptionInspectCommand: `/subscription inspect ${account.providerId}`,
|
|
134
|
+
workspaceActions: [
|
|
135
|
+
'provider-accounts',
|
|
136
|
+
'provider-account-repair',
|
|
137
|
+
'subscription-review',
|
|
138
|
+
'subscription-inspect',
|
|
139
|
+
],
|
|
140
|
+
loginStartCommand: `/subscription login ${account.providerId} start --yes`,
|
|
141
|
+
loginFinishCommand: `/subscription login ${account.providerId} finish <code-or-url> --yes`,
|
|
142
|
+
logoutCommand: `/subscription logout ${account.providerId} --yes`,
|
|
143
|
+
confirmationRequired: true,
|
|
144
|
+
},
|
|
145
|
+
}
|
|
146
|
+
: {
|
|
147
|
+
summary: previewHarnessText(`${account.providerId} ${account.authFreshness}; ${account.issues.length} issue(s)`),
|
|
148
|
+
}),
|
|
138
149
|
};
|
|
139
150
|
}
|
|
140
151
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
+
import { previewHarnessText } from './agent-harness-text.ts';
|
|
3
4
|
|
|
4
5
|
const RELEASE_EVIDENCE_ARTIFACTS = [
|
|
5
6
|
{
|
|
6
7
|
id: 'release-notes',
|
|
7
8
|
path: 'release/release-notes.md',
|
|
8
9
|
kind: 'markdown',
|
|
9
|
-
description: '
|
|
10
|
+
description: 'Shipped release notes included with operator/audit release artifacts.',
|
|
10
11
|
},
|
|
11
12
|
{
|
|
12
13
|
id: 'performance-snapshot',
|
|
@@ -18,7 +19,7 @@ const RELEASE_EVIDENCE_ARTIFACTS = [
|
|
|
18
19
|
id: 'release-readiness',
|
|
19
20
|
path: 'release/release-readiness.json',
|
|
20
21
|
kind: 'json',
|
|
21
|
-
description: 'Release
|
|
22
|
+
description: 'Release inventory with owner, evidence, and quality dimensions.',
|
|
22
23
|
},
|
|
23
24
|
{
|
|
24
25
|
id: 'live-verification-json',
|
|
@@ -120,6 +121,20 @@ function artifactSearchText(artifact: ReleaseEvidenceArtifact): string {
|
|
|
120
121
|
return `${artifact.id}\n${artifact.path}\n${artifact.kind}\n${artifact.description}`.toLowerCase();
|
|
121
122
|
}
|
|
122
123
|
|
|
124
|
+
function releaseEvidenceModelRoute(artifact?: ReleaseEvidenceArtifact): string {
|
|
125
|
+
if (artifact) return 'agent_harness mode:"release_evidence_artifact"';
|
|
126
|
+
return 'agent_harness mode:"release_evidence" or mode:"release_evidence_artifact"';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function releaseEvidencePolicy(): Record<string, unknown> {
|
|
130
|
+
return {
|
|
131
|
+
effect: 'operator-audit-read-only',
|
|
132
|
+
audience: 'release operators and maintainers',
|
|
133
|
+
values: 'Returns packaged release artifacts, summaries, and optional artifact content for release audit.',
|
|
134
|
+
boundary: 'Release artifacts are audit material. They are not visible product routes and do not mutate runtime state.',
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
123
138
|
function evidenceLookupFromArgs(args: ReleaseEvidenceArgs): ReleaseEvidenceLookup | null {
|
|
124
139
|
const artifactId = readString(args.artifactId);
|
|
125
140
|
if (artifactId) return { source: 'artifactId', input: artifactId };
|
|
@@ -243,6 +258,7 @@ function summarizeLoadedArtifact(
|
|
|
243
258
|
kind: loaded.artifact.kind,
|
|
244
259
|
description: loaded.artifact.description,
|
|
245
260
|
status: loaded.status,
|
|
261
|
+
modelRoute: releaseEvidenceModelRoute(loaded.artifact),
|
|
246
262
|
};
|
|
247
263
|
if (loaded.status !== 'available') {
|
|
248
264
|
return { ...base, reason: loaded.reason };
|
|
@@ -255,6 +271,12 @@ function summarizeLoadedArtifact(
|
|
|
255
271
|
...base,
|
|
256
272
|
sizeBytes: loaded.sizeBytes,
|
|
257
273
|
summary,
|
|
274
|
+
policy: releaseEvidencePolicy(),
|
|
275
|
+
modelAccess: {
|
|
276
|
+
listArtifacts: 'agent_harness mode:"release_evidence"',
|
|
277
|
+
inspectArtifact: `agent_harness mode:"release_evidence_artifact" artifactId:"${loaded.artifact.id}"`,
|
|
278
|
+
includeContent: 'Pass includeParameters:true only when release audit requires artifact content.',
|
|
279
|
+
},
|
|
258
280
|
...(options.includeSource
|
|
259
281
|
? loaded.artifact.kind === 'json'
|
|
260
282
|
? { data: loaded.parsed }
|
|
@@ -268,7 +290,8 @@ function releaseEvidenceCandidates(artifacts: readonly ReleaseEvidenceArtifact[]
|
|
|
268
290
|
id: artifact.id,
|
|
269
291
|
path: artifact.path,
|
|
270
292
|
kind: artifact.kind,
|
|
271
|
-
|
|
293
|
+
summary: previewHarnessText(artifact.description),
|
|
294
|
+
modelRoute: releaseEvidenceModelRoute(artifact),
|
|
272
295
|
}));
|
|
273
296
|
}
|
|
274
297
|
|
|
@@ -298,6 +321,11 @@ export function releaseEvidenceSummary(args: ReleaseEvidenceArgs): Record<string
|
|
|
298
321
|
filtered: filtered.length,
|
|
299
322
|
returned: loaded.length,
|
|
300
323
|
artifactsList: loaded.map((artifact) => summarizeLoadedArtifact(artifact, { includeSource: args.includeParameters === true })),
|
|
324
|
+
policy: releaseEvidencePolicy(),
|
|
325
|
+
modelAccess: {
|
|
326
|
+
listArtifacts: 'agent_harness mode:"release_evidence"',
|
|
327
|
+
inspectArtifact: 'agent_harness mode:"release_evidence_artifact" with artifactId, target, or query',
|
|
328
|
+
},
|
|
301
329
|
artifactLookup: 'Use mode:"release_evidence_artifact" with artifactId, target, or query to inspect one release evidence artifact.',
|
|
302
330
|
};
|
|
303
331
|
}
|
|
@@ -103,6 +103,20 @@ function itemSearchText(item: Record<string, unknown>): string {
|
|
|
103
103
|
return fields.join('\n').toLowerCase();
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
function releaseReadinessModelRoute(item?: Record<string, unknown>): string {
|
|
107
|
+
if (item) return 'agent_harness mode:"release_readiness_item"';
|
|
108
|
+
return 'agent_harness mode:"release_readiness" or mode:"release_readiness_item"';
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function releaseReadinessPolicy(): Record<string, unknown> {
|
|
112
|
+
return {
|
|
113
|
+
effect: 'operator-audit-read-only',
|
|
114
|
+
audience: 'release operators and maintainers',
|
|
115
|
+
values: 'Returns release-quality inventory status, evidence, and quality dimensions for audit.',
|
|
116
|
+
boundary: 'Release readiness is audit material. It is not a visible product route and does not mutate runtime state.',
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
106
120
|
function countBy(items: readonly Record<string, unknown>[], key: string): Record<string, number> {
|
|
107
121
|
const counts: Record<string, number> = {};
|
|
108
122
|
for (const item of items) {
|
|
@@ -134,7 +148,15 @@ function summarizeItem(item: Record<string, unknown>, options: { readonly includ
|
|
|
134
148
|
status: item.status,
|
|
135
149
|
evidence: item.evidence,
|
|
136
150
|
action: item.action,
|
|
151
|
+
modelRoute: releaseReadinessModelRoute(item),
|
|
137
152
|
...(options.includeQuality ? { quality: item.quality } : {}),
|
|
153
|
+
...(options.includeQuality ? {
|
|
154
|
+
policy: releaseReadinessPolicy(),
|
|
155
|
+
modelAccess: {
|
|
156
|
+
listItems: 'agent_harness mode:"release_readiness"',
|
|
157
|
+
inspectItem: `agent_harness mode:"release_readiness_item" itemId:"${readString(item.id)}"`,
|
|
158
|
+
},
|
|
159
|
+
} : {}),
|
|
138
160
|
};
|
|
139
161
|
}
|
|
140
162
|
|
|
@@ -153,6 +175,7 @@ function releaseReadinessCandidates(items: readonly Record<string, unknown>[]):
|
|
|
153
175
|
capability: item.capability,
|
|
154
176
|
owner: item.owner,
|
|
155
177
|
status: item.status,
|
|
178
|
+
modelRoute: releaseReadinessModelRoute(item),
|
|
156
179
|
}));
|
|
157
180
|
}
|
|
158
181
|
|
|
@@ -173,6 +196,8 @@ export function releaseReadinessInventoryStatus(): Record<string, unknown> {
|
|
|
173
196
|
checkedAt: loaded.root.checkedAt,
|
|
174
197
|
items: items.length,
|
|
175
198
|
qualityDimensions: QUALITY_DIMENSIONS,
|
|
199
|
+
modelRoute: releaseReadinessModelRoute(),
|
|
200
|
+
policy: releaseReadinessPolicy(),
|
|
176
201
|
};
|
|
177
202
|
}
|
|
178
203
|
|
|
@@ -203,6 +228,11 @@ export function releaseReadinessSummary(args: ReleaseReadinessArgs): Record<stri
|
|
|
203
228
|
schemaVersion: loaded.root.schemaVersion,
|
|
204
229
|
checkedAt: loaded.root.checkedAt,
|
|
205
230
|
policy: loaded.root.policy,
|
|
231
|
+
operatorAuditPolicy: releaseReadinessPolicy(),
|
|
232
|
+
modelAccess: {
|
|
233
|
+
listItems: 'agent_harness mode:"release_readiness"',
|
|
234
|
+
inspectItem: 'agent_harness mode:"release_readiness_item" with itemId, target, or query',
|
|
235
|
+
},
|
|
206
236
|
totals: {
|
|
207
237
|
items: items.length,
|
|
208
238
|
filtered: filtered.length,
|
|
@@ -2,6 +2,7 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
2
2
|
import { buildMcpAttackPathReview } from '@/runtime/index.ts';
|
|
3
3
|
import { listBuiltinSubscriptionProviders } from '@pellux/goodvibes-sdk/platform/config';
|
|
4
4
|
import type { CommandContext } from '../input/command-registry.ts';
|
|
5
|
+
import { previewHarnessText } from './agent-harness-text.ts';
|
|
5
6
|
|
|
6
7
|
export interface AgentHarnessSecurityArgs {
|
|
7
8
|
readonly query?: unknown;
|
|
@@ -153,9 +154,18 @@ function describeFindingCandidate(finding: SecurityFinding): Record<string, unkn
|
|
|
153
154
|
source: finding.source,
|
|
154
155
|
severity: finding.severity,
|
|
155
156
|
title: finding.title,
|
|
157
|
+
modelRoute: securityFindingModelRoute(),
|
|
156
158
|
};
|
|
157
159
|
}
|
|
158
160
|
|
|
161
|
+
function securityFindingModelRoute(): string {
|
|
162
|
+
return 'agent_harness mode:"security_finding" or mode:"run_command"';
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function supportBundleModelRoute(): string {
|
|
166
|
+
return 'agent_harness mode:"support_bundle" or mode:"run_workspace_action"';
|
|
167
|
+
}
|
|
168
|
+
|
|
159
169
|
function describeFinding(finding: SecurityFinding, includeParameters: boolean, lookup?: Record<string, unknown>): Record<string, unknown> {
|
|
160
170
|
return {
|
|
161
171
|
findingId: finding.findingId,
|
|
@@ -164,6 +174,7 @@ function describeFinding(finding: SecurityFinding, includeParameters: boolean, l
|
|
|
164
174
|
title: finding.title,
|
|
165
175
|
summary: finding.summary,
|
|
166
176
|
route: finding.route,
|
|
177
|
+
modelRoute: securityFindingModelRoute(),
|
|
167
178
|
...(lookup ? { lookup } : {}),
|
|
168
179
|
...(includeParameters && finding.detail ? { detail: finding.detail } : {}),
|
|
169
180
|
...(includeParameters ? {
|
|
@@ -537,15 +548,18 @@ export function supportBundleSummary(args: AgentHarnessSecurityArgs): Record<str
|
|
|
537
548
|
bundleType: route.bundleType,
|
|
538
549
|
defaultPath: route.defaultPath,
|
|
539
550
|
inspectCommand: route.inspectCommand,
|
|
540
|
-
|
|
541
|
-
...(route.importCommand ? { importCommand: route.importCommand } : {}),
|
|
542
|
-
workspaceActionIds: route.workspaceActionIds,
|
|
551
|
+
modelRoute: supportBundleModelRoute(),
|
|
543
552
|
...(args.includeParameters === true ? {
|
|
553
|
+
exportCommand: route.exportCommand,
|
|
554
|
+
...(route.importCommand ? { importCommand: route.importCommand } : {}),
|
|
555
|
+
workspaceActionIds: route.workspaceActionIds,
|
|
544
556
|
parameters: {
|
|
545
557
|
bundlePath: 'Workspace-relative path for support_bundle inspection.',
|
|
546
558
|
confirm: 'Required for export/import routes through run_workspace_action or run_command.',
|
|
547
559
|
},
|
|
548
|
-
} : {
|
|
560
|
+
} : {
|
|
561
|
+
summary: previewHarnessText(`${route.bundleType} bundle inspection route`),
|
|
562
|
+
}),
|
|
549
563
|
}));
|
|
550
564
|
return {
|
|
551
565
|
bundles: routes,
|
|
@@ -77,13 +77,14 @@ function describeEndpoint(
|
|
|
77
77
|
bindPosture: endpoint.bindPosture,
|
|
78
78
|
networkFacing: endpoint.networkFacing,
|
|
79
79
|
...(endpoint.reachable !== undefined ? { reachable: endpoint.reachable } : {}),
|
|
80
|
+
modelRoute: serviceEndpointModelRoute(),
|
|
80
81
|
...(options.lookup ? { lookup: options.lookup } : {}),
|
|
81
82
|
...(options.includeParameters ? {
|
|
82
83
|
policy: {
|
|
83
84
|
effect: 'read-only',
|
|
84
85
|
modelOperation: 'Inspect endpoint binding, network-facing posture, and optional reachability only.',
|
|
85
86
|
lifecycle: 'GoodVibes Agent does not start, stop, restart, install, expose, or mutate connected-host listeners.',
|
|
86
|
-
settings: 'Use agent_harness settings
|
|
87
|
+
settings: 'Use agent_harness mode:"settings" or mode:"get_setting" for read-only inspection of endpoint settings; connected-host lifecycle/listener settings stay locked in Agent.',
|
|
87
88
|
},
|
|
88
89
|
} : {}),
|
|
89
90
|
};
|
|
@@ -95,9 +96,14 @@ function describeEndpointCandidate(endpoint: CliServiceEndpointPosture): Record<
|
|
|
95
96
|
label: endpoint.label,
|
|
96
97
|
enabled: endpoint.enabled,
|
|
97
98
|
binding: endpoint.binding,
|
|
99
|
+
modelRoute: serviceEndpointModelRoute(),
|
|
98
100
|
};
|
|
99
101
|
}
|
|
100
102
|
|
|
103
|
+
function serviceEndpointModelRoute(): string {
|
|
104
|
+
return 'agent_harness mode:"service_endpoint" or mode:"settings"';
|
|
105
|
+
}
|
|
106
|
+
|
|
101
107
|
function endpointLookupFromArgs(args: AgentHarnessServicePostureArgs): { readonly source: ServiceEndpointLookupSource; readonly input: string } | null {
|
|
102
108
|
const endpointId = readString(args.endpointId);
|
|
103
109
|
if (endpointId) return { source: 'endpointId', input: endpointId };
|
|
@@ -182,6 +188,7 @@ export async function servicePostureSummary(
|
|
|
182
188
|
ownership: 'external-connected-host',
|
|
183
189
|
readOnly: true,
|
|
184
190
|
lifecycle: 'GoodVibes Agent reports connected-host/service posture but does not start, stop, restart, install, expose, or mutate host listeners.',
|
|
191
|
+
modelRoute: serviceEndpointModelRoute(),
|
|
185
192
|
config: posture.config,
|
|
186
193
|
managed: posture.managed,
|
|
187
194
|
endpoints: posture.endpoints.map((endpoint) => describeEndpoint(endpoint, { includeParameters: includeDetails })),
|
|
@@ -190,7 +197,7 @@ export async function servicePostureSummary(
|
|
|
190
197
|
...(includeDetails ? { modelAccess: {
|
|
191
198
|
endpointLookup: 'Use mode:"service_endpoint" with endpointId, target, or query to inspect one endpoint.',
|
|
192
199
|
settings: 'Use mode:"settings" with includeHidden:true for endpoint setting descriptors. Host-owned listener settings remain read-only.',
|
|
193
|
-
liveHostStatus: 'Use mode:"connected_host_status" for
|
|
200
|
+
liveHostStatus: 'Use mode:"connected_host_status" for token posture and Agent Knowledge route readiness.',
|
|
194
201
|
} } : {}),
|
|
195
202
|
};
|
|
196
203
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CommandContext } from '../input/command-registry.ts';
|
|
2
|
+
import { previewHarnessText } from './agent-harness-text.ts';
|
|
2
3
|
|
|
3
4
|
export interface AgentHarnessSessionArgs {
|
|
4
5
|
readonly sessionId?: unknown;
|
|
@@ -89,9 +90,18 @@ function describeSessionCandidate(session: SessionInfoLike, currentSessionId: st
|
|
|
89
90
|
title: session.title || '(untitled)',
|
|
90
91
|
messageCount: session.messageCount,
|
|
91
92
|
active: session.name === currentSessionId,
|
|
93
|
+
modelRoute: sessionModelRoute(),
|
|
92
94
|
};
|
|
93
95
|
}
|
|
94
96
|
|
|
97
|
+
function sessionModelRoute(): string {
|
|
98
|
+
return 'agent_harness mode:"session" or mode:"run_command"';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function bookmarkModelRoute(): string {
|
|
102
|
+
return 'agent_harness mode:"open_ui_surface" or agent_knowledge_ingest';
|
|
103
|
+
}
|
|
104
|
+
|
|
95
105
|
function describeSession(
|
|
96
106
|
session: SessionInfoLike,
|
|
97
107
|
options: {
|
|
@@ -110,6 +120,8 @@ function describeSession(
|
|
|
110
120
|
model: session.model || null,
|
|
111
121
|
provider: session.provider || null,
|
|
112
122
|
active: session.name === options.currentSessionId,
|
|
123
|
+
modelRoute: sessionModelRoute(),
|
|
124
|
+
...(options.includeParameters ? {} : { summary: previewHarnessText(session.title || session.name) }),
|
|
113
125
|
...(posture ? { returnContext: posture } : {}),
|
|
114
126
|
...(options.search ? {
|
|
115
127
|
search: {
|
|
@@ -164,24 +176,28 @@ function currentSession(context: CommandContext): Record<string, unknown> {
|
|
|
164
176
|
};
|
|
165
177
|
}
|
|
166
178
|
|
|
167
|
-
function bookmarkSummary(context: CommandContext): Record<string, unknown> {
|
|
179
|
+
function bookmarkSummary(context: CommandContext, includeParameters = false): Record<string, unknown> {
|
|
168
180
|
const manager = context.workspace.bookmarkManager;
|
|
169
181
|
if (!manager) {
|
|
170
182
|
return {
|
|
171
183
|
status: 'unavailable',
|
|
172
184
|
bookmarks: 0,
|
|
173
185
|
savedFiles: 0,
|
|
186
|
+
modelRoute: bookmarkModelRoute(),
|
|
174
187
|
};
|
|
175
188
|
}
|
|
176
189
|
return {
|
|
177
190
|
status: 'available',
|
|
178
191
|
bookmarks: manager.list().length,
|
|
179
192
|
savedFiles: manager.listSavedFiles().length,
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
193
|
+
modelRoute: bookmarkModelRoute(),
|
|
194
|
+
...(includeParameters ? {
|
|
195
|
+
modelRoutes: {
|
|
196
|
+
visibleBookmarkPicker: 'agent_harness mode:"open_ui_surface" surfaceId:"bookmarks" confirm:true explicitUserRequest:"..."',
|
|
197
|
+
command: '/bookmarks',
|
|
198
|
+
importIntoKnowledge: 'agent_knowledge_ingest sourceKind:"bookmarks_file" confirm:true explicitUserRequest:"..."',
|
|
199
|
+
},
|
|
200
|
+
} : {}),
|
|
185
201
|
};
|
|
186
202
|
}
|
|
187
203
|
|
|
@@ -206,7 +222,7 @@ export function sessionSummary(context: CommandContext, args: AgentHarnessSessio
|
|
|
206
222
|
returned: 0,
|
|
207
223
|
total: 0,
|
|
208
224
|
current: currentSession(context),
|
|
209
|
-
bookmarks: bookmarkSummary(context),
|
|
225
|
+
bookmarks: bookmarkSummary(context, args.includeParameters === true),
|
|
210
226
|
policy: 'Session runtime or session manager is unavailable in this Agent context.',
|
|
211
227
|
};
|
|
212
228
|
}
|
|
@@ -221,7 +237,7 @@ export function sessionSummary(context: CommandContext, args: AgentHarnessSessio
|
|
|
221
237
|
return {
|
|
222
238
|
status: 'available',
|
|
223
239
|
current: currentSession(context),
|
|
224
|
-
bookmarks: bookmarkSummary(context),
|
|
240
|
+
bookmarks: bookmarkSummary(context, args.includeParameters === true),
|
|
225
241
|
sessions: limited.map((session) => {
|
|
226
242
|
const search = searchByName.get(session.name);
|
|
227
243
|
return describeSession(session, {
|
|
@@ -3,6 +3,7 @@ import { collectOnboardingSnapshot, deriveStep1Capabilities, deriveStep1Capabili
|
|
|
3
3
|
import type { CommandContext } from '../input/command-registry.ts';
|
|
4
4
|
import { buildProviderAccountSnapshot } from '../panels/provider-account-snapshot.ts';
|
|
5
5
|
import { requireLocalUserAuthManager, requirePlatform, requireProvider, requireSecretsManager, requireServiceRegistry, requireShellPaths, requireSubscriptionManager } from '../input/commands/runtime-services.ts';
|
|
6
|
+
import { previewHarnessText } from './agent-harness-text.ts';
|
|
6
7
|
|
|
7
8
|
export interface AgentHarnessSetupArgs {
|
|
8
9
|
readonly setupItemId?: unknown;
|
|
@@ -175,36 +176,46 @@ function describeItem(
|
|
|
175
176
|
setupItemId: item.id,
|
|
176
177
|
label: item.label,
|
|
177
178
|
selected: item.selected,
|
|
178
|
-
|
|
179
|
-
signals: signalsForItem(item, snapshot),
|
|
179
|
+
modelRoute: setupItemModelRoute(),
|
|
180
180
|
...(options.lookup ? { lookup: options.lookup } : {}),
|
|
181
|
-
...(options.includeParameters
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
181
|
+
...(options.includeParameters
|
|
182
|
+
? {
|
|
183
|
+
detail: item.detail,
|
|
184
|
+
signals: signalsForItem(item, snapshot),
|
|
185
|
+
policy: {
|
|
186
|
+
effect: 'read-only',
|
|
187
|
+
values: 'Setup posture returns onboarding readiness, counts, safe setting keys, and route metadata only; secret values and raw provider tokens are never returned.',
|
|
188
|
+
mutation: 'Setup apply, provider auth, local behavior import/create, channel delivery, and starter profile changes stay visible workspace, settings, slash-command, or first-class tool flows.',
|
|
189
|
+
},
|
|
190
|
+
modelAccess: {
|
|
191
|
+
inspectSetup: 'agent_harness mode:"setup_posture"',
|
|
192
|
+
inspectSetupItem: 'agent_harness mode:"setup_item"',
|
|
193
|
+
openOnboarding: 'agent_harness mode:"open_ui_surface" surfaceId:"onboarding" confirm:true explicitUserRequest:"..."',
|
|
194
|
+
setupWorkspace: 'agent_harness mode:"workspace_action" target:"setup"',
|
|
195
|
+
settings: 'agent_harness mode:"settings"; inspect or mutate with get_setting, set_setting, or reset_setting',
|
|
196
|
+
providerRouting: 'agent_harness mode:"model_routing"',
|
|
197
|
+
providerAccounts: 'agent_harness mode:"provider_accounts"',
|
|
198
|
+
channels: 'agent_harness mode:"channels"',
|
|
199
|
+
media: 'agent_harness mode:"media_posture"',
|
|
200
|
+
security: 'agent_harness mode:"security_posture"',
|
|
201
|
+
},
|
|
202
|
+
}
|
|
203
|
+
: {
|
|
204
|
+
summary: previewHarnessText(item.detail),
|
|
205
|
+
}),
|
|
200
206
|
};
|
|
201
207
|
}
|
|
202
208
|
|
|
209
|
+
function setupItemModelRoute(): string {
|
|
210
|
+
return 'agent_harness mode:"setup_item" or mode:"open_ui_surface"';
|
|
211
|
+
}
|
|
212
|
+
|
|
203
213
|
function describeCandidate(item: OnboardingStep1CapabilityItem): Record<string, unknown> {
|
|
204
214
|
return {
|
|
205
215
|
setupItemId: item.id,
|
|
206
216
|
label: item.label,
|
|
207
217
|
selected: item.selected,
|
|
218
|
+
modelRoute: setupItemModelRoute(),
|
|
208
219
|
};
|
|
209
220
|
}
|
|
210
221
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const HARNESS_PREVIEW_LIMIT = 56;
|
|
2
|
+
|
|
3
|
+
export function previewHarnessText(value: string, maxLength = HARNESS_PREVIEW_LIMIT): string {
|
|
4
|
+
const normalized = value.replace(/\s+/g, ' ').trim();
|
|
5
|
+
return normalized.length <= maxLength ? normalized : `${normalized.slice(0, maxLength - 3).trimEnd()}...`;
|
|
6
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const AGENT_HARNESS_MODES = [
|
|
2
|
-
'summary', 'cli_commands', 'cli_command', 'panels', 'panel', 'open_panel',
|
|
2
|
+
'summary', 'modes', 'mode', 'cli_commands', 'cli_command', 'panels', 'panel', 'open_panel',
|
|
3
3
|
'ui_surfaces', 'ui_surface', 'open_ui_surface',
|
|
4
4
|
'shortcuts', 'keybindings', 'keybinding', 'run_keybinding', 'set_keybinding', 'reset_keybinding',
|
|
5
5
|
'commands', 'command', 'run_command', 'channels', 'channel', 'notifications', 'notification_target',
|