@pellux/goodvibes-agent 1.0.31 → 1.0.33
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 +38 -3
- package/README.md +7 -5
- package/dist/package/main.js +7346 -2349
- package/docs/README.md +2 -2
- package/docs/channels-remote-and-api.md +6 -2
- package/docs/connected-host.md +26 -5
- package/docs/getting-started.md +29 -9
- package/docs/knowledge-artifacts-and-multimodal.md +16 -4
- package/docs/project-planning.md +2 -2
- package/docs/providers-and-routing.md +3 -2
- package/docs/release-and-publishing.md +15 -11
- package/docs/tools-and-commands.md +20 -8
- package/package.json +8 -3
- package/release/live-verification/live-verification.json +148 -0
- package/release/live-verification/live-verification.md +187 -0
- package/release/performance-snapshot.json +57 -0
- package/release/release-notes.md +28 -0
- package/release/release-readiness.json +581 -0
- package/src/cli/agent-knowledge-command.ts +5 -5
- package/src/cli/agent-knowledge-format.ts +11 -0
- package/src/cli/agent-knowledge-runtime.ts +92 -13
- package/src/cli/bundle-command.ts +5 -4
- package/src/cli/entrypoint.ts +5 -2
- package/src/cli/external-runtime.ts +2 -15
- package/src/cli/management.ts +4 -3
- package/src/input/commands/guidance-runtime.ts +1 -1
- package/src/input/commands/knowledge.ts +2 -2
- package/src/runtime/bootstrap.ts +2 -2
- package/src/runtime/connected-host-auth.ts +16 -0
- package/src/tools/agent-channel-send-tool.ts +5 -7
- package/src/tools/agent-harness-channel-metadata.ts +177 -0
- package/src/tools/agent-harness-connected-host-status.ts +1 -1
- package/src/tools/agent-harness-delegation-posture.ts +216 -0
- package/src/tools/agent-harness-keybinding-metadata.ts +57 -22
- package/src/tools/agent-harness-mcp-metadata.ts +246 -0
- package/src/tools/agent-harness-media-posture.ts +282 -0
- package/src/tools/agent-harness-metadata.ts +21 -4
- package/src/tools/agent-harness-model-routing.ts +501 -0
- package/src/tools/agent-harness-notification-metadata.ts +217 -0
- package/src/tools/agent-harness-operator-methods.ts +285 -0
- package/src/tools/agent-harness-pairing-posture.ts +265 -0
- package/src/tools/agent-harness-provider-account-metadata.ts +203 -0
- package/src/tools/agent-harness-release-evidence.ts +364 -0
- package/src/tools/agent-harness-release-readiness.ts +298 -0
- package/src/tools/agent-harness-security-posture.ts +646 -0
- package/src/tools/agent-harness-service-posture.ts +201 -0
- package/src/tools/agent-harness-session-metadata.ts +282 -0
- package/src/tools/agent-harness-setup-posture.ts +295 -0
- package/src/tools/agent-harness-tool-schema.ts +103 -27
- package/src/tools/agent-harness-tool.ts +209 -236
- package/src/tools/agent-harness-ui-surface-metadata.ts +1 -1
- package/src/tools/agent-harness-workspace-actions.ts +232 -0
- package/src/tools/agent-knowledge-ingest-tool.ts +6 -8
- package/src/tools/agent-knowledge-tool.ts +122 -23
- package/src/tools/agent-local-registry-tool.ts +4 -5
- package/src/tools/agent-media-generate-tool.ts +4 -6
- package/src/tools/agent-notify-tool.ts +5 -6
- package/src/tools/agent-operator-action-tool.ts +6 -8
- package/src/tools/agent-operator-briefing-tool.ts +3 -4
- package/src/tools/agent-reminder-schedule-tool.ts +6 -7
- package/src/tools/agent-tool-policy-guard.ts +8 -17
- package/src/tools/agent-work-plan-tool.ts +3 -4
- package/src/version.ts +2 -2
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import type { CommandContext } from '../input/command-registry.ts';
|
|
2
|
+
import { createAgentWorkspaceEditor } from '../input/agent-workspace-activation.ts';
|
|
3
|
+
import { AGENT_WORKSPACE_CATEGORIES } from '../input/agent-workspace-categories.ts';
|
|
4
|
+
import { searchAgentWorkspaceActions } from '../input/agent-workspace-search.ts';
|
|
5
|
+
import { buildAgentWorkspaceRuntimeSnapshot } from '../input/agent-workspace-snapshot.ts';
|
|
6
|
+
import type { AgentWorkspaceAction, AgentWorkspaceCategory, AgentWorkspaceEditorKind, AgentWorkspaceLocalEditor, AgentWorkspaceLocalLibraryItem, AgentWorkspaceRuntimeSnapshot } from '../input/agent-workspace-types.ts';
|
|
7
|
+
import { describeLocalWorkspaceModelExecution } from './agent-harness-local-operations.ts';
|
|
8
|
+
import { describeWorkspaceEditorModelExecution } from './agent-harness-workspace-editor-execution.ts';
|
|
9
|
+
|
|
10
|
+
export { AGENT_WORKSPACE_CATEGORIES };
|
|
11
|
+
|
|
12
|
+
export interface AgentHarnessWorkspaceActionArgs {
|
|
13
|
+
readonly query?: unknown;
|
|
14
|
+
readonly command?: unknown;
|
|
15
|
+
readonly actionId?: unknown;
|
|
16
|
+
readonly recordId?: unknown;
|
|
17
|
+
readonly fields?: unknown;
|
|
18
|
+
readonly target?: unknown;
|
|
19
|
+
readonly category?: unknown;
|
|
20
|
+
readonly categoryId?: unknown;
|
|
21
|
+
readonly includeParameters?: unknown;
|
|
22
|
+
readonly limit?: unknown;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface WorkspaceEditorContext {
|
|
26
|
+
readonly runtimeStarterTemplates: AgentWorkspaceRuntimeSnapshot['runtimeStarterTemplates'];
|
|
27
|
+
readonly selectedRoutine: AgentWorkspaceLocalLibraryItem | null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface WorkspaceActionLookup {
|
|
31
|
+
readonly source: 'actionId' | 'command' | 'target' | 'query';
|
|
32
|
+
readonly input: string;
|
|
33
|
+
readonly resolvedBy: 'id' | 'case-insensitive-id' | 'label' | 'case-insensitive-label' | 'command' | 'search';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type WorkspaceActionResolution =
|
|
37
|
+
| {
|
|
38
|
+
readonly status: 'found';
|
|
39
|
+
readonly category: AgentWorkspaceCategory;
|
|
40
|
+
readonly action: AgentWorkspaceAction;
|
|
41
|
+
readonly lookup: WorkspaceActionLookup;
|
|
42
|
+
}
|
|
43
|
+
| {
|
|
44
|
+
readonly status: 'ambiguous';
|
|
45
|
+
readonly input: string;
|
|
46
|
+
readonly candidates: readonly { readonly actionId: string; readonly categoryId: string; readonly label: string; readonly command?: string }[];
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
function readString(value: unknown): string {
|
|
50
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function readLimit(value: unknown, fallback: number): number {
|
|
54
|
+
const parsed = typeof value === 'string' && value.trim() ? Number(value) : value;
|
|
55
|
+
if (typeof parsed !== 'number' || !Number.isFinite(parsed)) return fallback;
|
|
56
|
+
return Math.max(1, Math.min(500, Math.trunc(parsed)));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function readFieldMap(value: unknown): Readonly<Record<string, string>> {
|
|
60
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) return {};
|
|
61
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, typeof entry === 'string' ? entry : String(entry)]));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function allWorkspaceActions(): ReadonlyArray<{
|
|
65
|
+
readonly category: AgentWorkspaceCategory;
|
|
66
|
+
readonly action: AgentWorkspaceAction;
|
|
67
|
+
}> {
|
|
68
|
+
return AGENT_WORKSPACE_CATEGORIES.flatMap((category) => category.actions.map((action) => ({ category, action })));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function describeWorkspaceCategory(category: AgentWorkspaceCategory): Record<string, unknown> {
|
|
72
|
+
return {
|
|
73
|
+
id: category.id,
|
|
74
|
+
group: category.group,
|
|
75
|
+
label: category.label,
|
|
76
|
+
summary: category.summary,
|
|
77
|
+
detail: category.detail,
|
|
78
|
+
actions: category.actions.length,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function describeWorkspaceEditor(editor: AgentWorkspaceLocalEditor): Record<string, unknown> {
|
|
83
|
+
return {
|
|
84
|
+
kind: editor.kind,
|
|
85
|
+
mode: editor.mode,
|
|
86
|
+
title: editor.title,
|
|
87
|
+
message: editor.message,
|
|
88
|
+
fields: editor.fields.map((field) => ({
|
|
89
|
+
id: field.id,
|
|
90
|
+
label: field.label,
|
|
91
|
+
required: field.required,
|
|
92
|
+
multiline: field.multiline,
|
|
93
|
+
hint: field.hint,
|
|
94
|
+
redact: field.redact === true,
|
|
95
|
+
default: field.redact ? '<redacted>' : field.value,
|
|
96
|
+
})),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function selectedRoutineFromArgs(
|
|
101
|
+
snapshot: AgentWorkspaceRuntimeSnapshot,
|
|
102
|
+
args: AgentHarnessWorkspaceActionArgs,
|
|
103
|
+
): AgentWorkspaceLocalLibraryItem | null {
|
|
104
|
+
const fields = readFieldMap(args.fields);
|
|
105
|
+
const routineId = readString(args.recordId) || readString(fields.routineId) || readString(fields.id);
|
|
106
|
+
if (!routineId) return null;
|
|
107
|
+
return snapshot.localRoutines.find((routine) => routine.id === routineId || routine.name.toLowerCase() === routineId.toLowerCase()) ?? null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function buildWorkspaceEditorContext(context: CommandContext, args: AgentHarnessWorkspaceActionArgs): WorkspaceEditorContext {
|
|
111
|
+
try {
|
|
112
|
+
const snapshot = buildAgentWorkspaceRuntimeSnapshot(context);
|
|
113
|
+
return {
|
|
114
|
+
runtimeStarterTemplates: snapshot.runtimeStarterTemplates,
|
|
115
|
+
selectedRoutine: selectedRoutineFromArgs(snapshot, args),
|
|
116
|
+
};
|
|
117
|
+
} catch {
|
|
118
|
+
return {
|
|
119
|
+
runtimeStarterTemplates: [],
|
|
120
|
+
selectedRoutine: null,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function createWorkspaceEditor(
|
|
126
|
+
editorKind: AgentWorkspaceEditorKind,
|
|
127
|
+
editorContext: WorkspaceEditorContext | null,
|
|
128
|
+
): AgentWorkspaceLocalEditor | null {
|
|
129
|
+
return createAgentWorkspaceEditor(editorKind, {
|
|
130
|
+
runtimeStarterTemplates: editorContext?.runtimeStarterTemplates ?? [],
|
|
131
|
+
selectedRoutine: editorKind === 'routine-schedule' ? editorContext?.selectedRoutine ?? null : null,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function describeWorkspaceAction(
|
|
136
|
+
category: AgentWorkspaceCategory,
|
|
137
|
+
action: AgentWorkspaceAction,
|
|
138
|
+
options: { readonly includeEditor?: boolean; readonly editorContext?: WorkspaceEditorContext | null; readonly lookup?: WorkspaceActionLookup } = {},
|
|
139
|
+
): Record<string, unknown> {
|
|
140
|
+
const editor = options.includeEditor && action.editorKind ? createWorkspaceEditor(action.editorKind, options.editorContext ?? null) : null;
|
|
141
|
+
return {
|
|
142
|
+
id: action.id,
|
|
143
|
+
categoryId: category.id,
|
|
144
|
+
category: category.label,
|
|
145
|
+
group: category.group,
|
|
146
|
+
label: action.label,
|
|
147
|
+
detail: action.detail,
|
|
148
|
+
kind: action.kind,
|
|
149
|
+
safety: action.safety,
|
|
150
|
+
...(action.command ? { command: action.command } : {}),
|
|
151
|
+
...(action.targetCategoryId ? { targetCategoryId: action.targetCategoryId } : {}),
|
|
152
|
+
...(action.editorKind ? { editorKind: action.editorKind } : {}),
|
|
153
|
+
...(action.localKind ? { localKind: action.localKind } : {}),
|
|
154
|
+
...(action.localOperation ? { localOperation: action.localOperation } : {}),
|
|
155
|
+
...(options.lookup ? { lookup: options.lookup } : {}),
|
|
156
|
+
...(editor ? { editor: describeWorkspaceEditor(editor) } : {}),
|
|
157
|
+
...(action.kind === 'local-selection' || action.kind === 'local-operation' ? {
|
|
158
|
+
modelExecution: describeLocalWorkspaceModelExecution(action),
|
|
159
|
+
} : {}),
|
|
160
|
+
...(action.kind === 'editor' && action.editorKind ? {
|
|
161
|
+
modelExecution: describeWorkspaceEditorModelExecution(action.editorKind),
|
|
162
|
+
} : {}),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function listWorkspaceActions(
|
|
167
|
+
context: CommandContext,
|
|
168
|
+
args: AgentHarnessWorkspaceActionArgs,
|
|
169
|
+
): readonly Record<string, unknown>[] {
|
|
170
|
+
const query = readString(args.query);
|
|
171
|
+
const categoryId = readString(args.categoryId || args.category);
|
|
172
|
+
const limit = readLimit(args.limit, 200);
|
|
173
|
+
const includeEditor = args.includeParameters === true;
|
|
174
|
+
const editorContext = includeEditor ? buildWorkspaceEditorContext(context, args) : null;
|
|
175
|
+
const source = query
|
|
176
|
+
? searchAgentWorkspaceActions(AGENT_WORKSPACE_CATEGORIES, query).map((result) => ({ category: result.category, action: result.action }))
|
|
177
|
+
: allWorkspaceActions();
|
|
178
|
+
return source
|
|
179
|
+
.filter((entry) => !categoryId || entry.category.id === categoryId)
|
|
180
|
+
.slice(0, limit)
|
|
181
|
+
.map((entry) => describeWorkspaceAction(entry.category, entry.action, { includeEditor, editorContext }));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function workspaceActionLookupFromArgs(args: AgentHarnessWorkspaceActionArgs): { readonly source: WorkspaceActionLookup['source']; readonly input: string } | null {
|
|
185
|
+
const actionId = readString(args.actionId);
|
|
186
|
+
if (actionId) return { source: 'actionId', input: actionId };
|
|
187
|
+
const command = readString(args.command);
|
|
188
|
+
if (command) return { source: 'command', input: command };
|
|
189
|
+
const target = readString(args.target);
|
|
190
|
+
if (target) return { source: 'target', input: target };
|
|
191
|
+
const query = readString(args.query);
|
|
192
|
+
return query ? { source: 'query', input: query } : null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function describeWorkspaceActionCandidates(
|
|
196
|
+
entries: readonly { readonly category: AgentWorkspaceCategory; readonly action: AgentWorkspaceAction }[],
|
|
197
|
+
): readonly { readonly actionId: string; readonly categoryId: string; readonly label: string; readonly command?: string }[] {
|
|
198
|
+
return entries.slice(0, 8).map((entry) => ({
|
|
199
|
+
actionId: entry.action.id,
|
|
200
|
+
categoryId: entry.category.id,
|
|
201
|
+
label: entry.action.label,
|
|
202
|
+
...(entry.action.command ? { command: entry.action.command } : {}),
|
|
203
|
+
}));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function resolveWorkspaceActionDetail(args: AgentHarnessWorkspaceActionArgs): WorkspaceActionResolution | null {
|
|
207
|
+
const lookup = workspaceActionLookupFromArgs(args);
|
|
208
|
+
const categoryId = readString(args.categoryId || args.category);
|
|
209
|
+
if (!lookup) return null;
|
|
210
|
+
const entries = allWorkspaceActions().filter((entry) => !categoryId || entry.category.id === categoryId);
|
|
211
|
+
const normalized = lookup.input.toLowerCase();
|
|
212
|
+
const commandInput = lookup.source === 'command' ? lookup.input.trim() : '';
|
|
213
|
+
|
|
214
|
+
const exactId = entries.find((entry) => entry.action.id === lookup.input);
|
|
215
|
+
if (exactId) return { status: 'found', ...exactId, lookup: { ...lookup, resolvedBy: 'id' } };
|
|
216
|
+
const exactLabel = entries.find((entry) => entry.action.label === lookup.input);
|
|
217
|
+
if (exactLabel) return { status: 'found', ...exactLabel, lookup: { ...lookup, resolvedBy: 'label' } };
|
|
218
|
+
const exactCommand = commandInput ? entries.find((entry) => entry.action.command === commandInput) : null;
|
|
219
|
+
if (exactCommand) return { status: 'found', ...exactCommand, lookup: { ...lookup, resolvedBy: 'command' } };
|
|
220
|
+
|
|
221
|
+
const insensitiveId = entries.find((entry) => entry.action.id.toLowerCase() === normalized);
|
|
222
|
+
if (insensitiveId) return { status: 'found', ...insensitiveId, lookup: { ...lookup, resolvedBy: 'case-insensitive-id' } };
|
|
223
|
+
const insensitiveLabel = entries.find((entry) => entry.action.label.toLowerCase() === normalized);
|
|
224
|
+
if (insensitiveLabel) return { status: 'found', ...insensitiveLabel, lookup: { ...lookup, resolvedBy: 'case-insensitive-label' } };
|
|
225
|
+
|
|
226
|
+
const searched = searchAgentWorkspaceActions(AGENT_WORKSPACE_CATEGORIES, lookup.input)
|
|
227
|
+
.map((result) => ({ category: result.category, action: result.action }))
|
|
228
|
+
.filter((entry) => !categoryId || entry.category.id === categoryId);
|
|
229
|
+
if (searched.length === 1) return { status: 'found', ...searched[0]!, lookup: { ...lookup, resolvedBy: 'search' } };
|
|
230
|
+
if (searched.length > 1) return { status: 'ambiguous', input: lookup.input, candidates: describeWorkspaceActionCandidates(searched) };
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
@@ -262,11 +262,9 @@ export function createAgentKnowledgeIngestTool(
|
|
|
262
262
|
definition: {
|
|
263
263
|
name: 'agent_knowledge_ingest',
|
|
264
264
|
description: [
|
|
265
|
-
'Ingest
|
|
266
|
-
'Use only
|
|
267
|
-
'
|
|
268
|
-
'It must never call default knowledge, non-Agent knowledge spaces, separate Agent jobs, local schedulers, or delegated review.',
|
|
269
|
-
'Set confirm:true only for an explicit user request. Otherwise return the preview/confirmation error.',
|
|
265
|
+
'Ingest one confirmed source into isolated Agent Knowledge.',
|
|
266
|
+
'Use only for explicit ingest/import requests.',
|
|
267
|
+
'Supports URL, file, bookmark, history, and connector sources.',
|
|
270
268
|
].join(' '),
|
|
271
269
|
parameters: {
|
|
272
270
|
type: 'object',
|
|
@@ -282,7 +280,7 @@ export function createAgentKnowledgeIngestTool(
|
|
|
282
280
|
},
|
|
283
281
|
path: {
|
|
284
282
|
type: 'string',
|
|
285
|
-
description: 'Local file
|
|
283
|
+
description: 'Local file or import path.',
|
|
286
284
|
},
|
|
287
285
|
title: {
|
|
288
286
|
type: 'string',
|
|
@@ -299,7 +297,7 @@ export function createAgentKnowledgeIngestTool(
|
|
|
299
297
|
},
|
|
300
298
|
connectorId: {
|
|
301
299
|
type: 'string',
|
|
302
|
-
description: 'Connector id
|
|
300
|
+
description: 'Connector id.',
|
|
303
301
|
},
|
|
304
302
|
input: {
|
|
305
303
|
description: 'Connector input as JSON-compatible data or a JSON/text string.',
|
|
@@ -340,7 +338,7 @@ export function createAgentKnowledgeIngestTool(
|
|
|
340
338
|
},
|
|
341
339
|
explicitUserRequest: {
|
|
342
340
|
type: 'string',
|
|
343
|
-
description: '
|
|
341
|
+
description: 'User request authorizing this ingest.',
|
|
344
342
|
},
|
|
345
343
|
},
|
|
346
344
|
required: ['confirm', 'explicitUserRequest'],
|
|
@@ -4,29 +4,62 @@ import type { ShellPathService } from '@/runtime/index.ts';
|
|
|
4
4
|
import {
|
|
5
5
|
createAgentSdk,
|
|
6
6
|
classifyKnowledgeError,
|
|
7
|
+
getAgentKnowledgeJson,
|
|
7
8
|
resolveConnectedHostConnection,
|
|
9
|
+
validateAgentKnowledgeData,
|
|
8
10
|
type AgentKnowledgeFailure,
|
|
9
11
|
type AgentKnowledgeConnectionRuntime,
|
|
10
12
|
} from '../cli/agent-knowledge-runtime.ts';
|
|
11
13
|
import { AGENT_KNOWLEDGE_METHODS, type ConnectedHostCallMethod } from '../cli/agent-knowledge-methods.ts';
|
|
12
14
|
import {
|
|
13
15
|
formatAsk,
|
|
16
|
+
formatConnector,
|
|
17
|
+
formatConnectorDoctor,
|
|
18
|
+
formatConnectors,
|
|
19
|
+
formatEntityList,
|
|
14
20
|
formatFailure,
|
|
21
|
+
formatItem,
|
|
22
|
+
formatMap,
|
|
15
23
|
formatSearch,
|
|
16
24
|
formatStatus,
|
|
17
25
|
} from '../cli/agent-knowledge-format.ts';
|
|
18
26
|
|
|
19
|
-
export type AgentKnowledgeToolAction =
|
|
27
|
+
export type AgentKnowledgeToolAction =
|
|
28
|
+
| 'status'
|
|
29
|
+
| 'ask'
|
|
30
|
+
| 'search'
|
|
31
|
+
| 'sources'
|
|
32
|
+
| 'nodes'
|
|
33
|
+
| 'issues'
|
|
34
|
+
| 'item'
|
|
35
|
+
| 'map'
|
|
36
|
+
| 'connectors'
|
|
37
|
+
| 'connector'
|
|
38
|
+
| 'connector_doctor';
|
|
20
39
|
export type AgentKnowledgeAskMode = 'concise' | 'standard' | 'detailed';
|
|
21
40
|
|
|
22
41
|
export interface AgentKnowledgeToolArgs {
|
|
23
42
|
readonly action?: unknown;
|
|
24
43
|
readonly query?: unknown;
|
|
44
|
+
readonly id?: unknown;
|
|
45
|
+
readonly connectorId?: unknown;
|
|
25
46
|
readonly limit?: unknown;
|
|
26
47
|
readonly mode?: unknown;
|
|
27
48
|
}
|
|
28
49
|
|
|
29
|
-
const ACTIONS: readonly AgentKnowledgeToolAction[] = [
|
|
50
|
+
const ACTIONS: readonly AgentKnowledgeToolAction[] = [
|
|
51
|
+
'status',
|
|
52
|
+
'ask',
|
|
53
|
+
'search',
|
|
54
|
+
'sources',
|
|
55
|
+
'nodes',
|
|
56
|
+
'issues',
|
|
57
|
+
'item',
|
|
58
|
+
'map',
|
|
59
|
+
'connectors',
|
|
60
|
+
'connector',
|
|
61
|
+
'connector_doctor',
|
|
62
|
+
];
|
|
30
63
|
const ASK_MODES: readonly AgentKnowledgeAskMode[] = ['concise', 'standard', 'detailed'];
|
|
31
64
|
|
|
32
65
|
function isAction(value: unknown): value is AgentKnowledgeToolAction {
|
|
@@ -37,11 +70,11 @@ function readString(value: unknown): string {
|
|
|
37
70
|
return typeof value === 'string' ? value.trim() : '';
|
|
38
71
|
}
|
|
39
72
|
|
|
40
|
-
function readLimit(value: unknown, fallback: number): number {
|
|
41
|
-
if (typeof value === 'number' && Number.isInteger(value) && value > 0) return Math.min(value,
|
|
73
|
+
function readLimit(value: unknown, fallback: number, max = 25): number {
|
|
74
|
+
if (typeof value === 'number' && Number.isInteger(value) && value > 0) return Math.min(value, max);
|
|
42
75
|
if (typeof value === 'string' && value.trim()) {
|
|
43
76
|
const parsed = Number(value);
|
|
44
|
-
if (Number.isInteger(parsed) && parsed > 0) return Math.min(parsed,
|
|
77
|
+
if (Number.isInteger(parsed) && parsed > 0) return Math.min(parsed, max);
|
|
45
78
|
}
|
|
46
79
|
return fallback;
|
|
47
80
|
}
|
|
@@ -72,6 +105,17 @@ async function classifyToolKnowledgeError(
|
|
|
72
105
|
return toolFailure(formatKnowledgeFailure(await classifyKnowledgeError(error, connection, method.route)));
|
|
73
106
|
}
|
|
74
107
|
|
|
108
|
+
function validatedToolOutput<TData>(
|
|
109
|
+
data: TData,
|
|
110
|
+
connection: ReturnType<typeof resolveConnectedHostConnection>,
|
|
111
|
+
method: ConnectedHostCallMethod,
|
|
112
|
+
format: (validatedData: TData) => string,
|
|
113
|
+
): { readonly success: true; readonly output: string } | { readonly success: false; readonly error: string } {
|
|
114
|
+
const validated = validateAgentKnowledgeData(data, connection, method);
|
|
115
|
+
if (!validated.ok) return toolFailure(formatKnowledgeFailure(validated));
|
|
116
|
+
return toolOutput(format(validated.data));
|
|
117
|
+
}
|
|
118
|
+
|
|
75
119
|
export function createAgentKnowledgeTool(
|
|
76
120
|
shellPaths: ShellPathService,
|
|
77
121
|
configManager: AgentKnowledgeConnectionRuntime['configManager'],
|
|
@@ -80,10 +124,9 @@ export function createAgentKnowledgeTool(
|
|
|
80
124
|
definition: {
|
|
81
125
|
name: 'agent_knowledge',
|
|
82
126
|
description: [
|
|
83
|
-
'Read isolated
|
|
84
|
-
'Use for
|
|
85
|
-
'
|
|
86
|
-
'It is read-only and does not ingest, reindex, mutate, or create background work.',
|
|
127
|
+
'Read isolated Agent Knowledge.',
|
|
128
|
+
'Use for status, ask/search, source/node/issue lists, item lookup, map summary, and connector inspection.',
|
|
129
|
+
'Read-only.',
|
|
87
130
|
].join(' '),
|
|
88
131
|
parameters: {
|
|
89
132
|
type: 'object',
|
|
@@ -95,11 +138,19 @@ export function createAgentKnowledgeTool(
|
|
|
95
138
|
},
|
|
96
139
|
query: {
|
|
97
140
|
type: 'string',
|
|
98
|
-
description: 'Question/query for ask or
|
|
141
|
+
description: 'Question/query for ask, search, or map filtering.',
|
|
142
|
+
},
|
|
143
|
+
id: {
|
|
144
|
+
type: 'string',
|
|
145
|
+
description: 'Agent Knowledge source, node, or issue id for action item.',
|
|
146
|
+
},
|
|
147
|
+
connectorId: {
|
|
148
|
+
type: 'string',
|
|
149
|
+
description: 'Connector id for action connector or connector_doctor. id may also be used.',
|
|
99
150
|
},
|
|
100
151
|
limit: {
|
|
101
152
|
type: 'number',
|
|
102
|
-
description: 'Maximum
|
|
153
|
+
description: 'Maximum result count.',
|
|
103
154
|
},
|
|
104
155
|
mode: {
|
|
105
156
|
type: 'string',
|
|
@@ -125,13 +176,16 @@ export function createAgentKnowledgeTool(
|
|
|
125
176
|
route: '/api/goodvibes-agent/knowledge/*',
|
|
126
177
|
}));
|
|
127
178
|
}
|
|
179
|
+
let method: ConnectedHostCallMethod = AGENT_KNOWLEDGE_METHODS.status;
|
|
128
180
|
try {
|
|
129
181
|
const sdk = createAgentSdk(connection);
|
|
130
182
|
if (args.action === 'status') {
|
|
183
|
+
method = AGENT_KNOWLEDGE_METHODS.status;
|
|
131
184
|
const data = await sdk.knowledge.status();
|
|
132
|
-
return
|
|
185
|
+
return validatedToolOutput(data, connection, method, formatStatus);
|
|
133
186
|
}
|
|
134
187
|
if (args.action === 'ask') {
|
|
188
|
+
method = AGENT_KNOWLEDGE_METHODS.ask;
|
|
135
189
|
const query = readString(args.query);
|
|
136
190
|
if (!query) return toolFailure('query is required for Agent Knowledge ask.');
|
|
137
191
|
const data = await sdk.knowledge.ask({
|
|
@@ -142,19 +196,64 @@ export function createAgentKnowledgeTool(
|
|
|
142
196
|
includeConfidence: true,
|
|
143
197
|
includeLinkedObjects: true,
|
|
144
198
|
});
|
|
145
|
-
return
|
|
199
|
+
return validatedToolOutput(data, connection, method, (validatedData) => formatAsk(validatedData, query));
|
|
200
|
+
}
|
|
201
|
+
if (args.action === 'search') {
|
|
202
|
+
method = AGENT_KNOWLEDGE_METHODS.search;
|
|
203
|
+
const query = readString(args.query);
|
|
204
|
+
if (!query) return toolFailure('query is required for Agent Knowledge search.');
|
|
205
|
+
const data = await sdk.knowledge.search({ query, limit: readLimit(args.limit, 10) });
|
|
206
|
+
return validatedToolOutput(data, connection, method, (validatedData) => formatSearch(validatedData, query));
|
|
207
|
+
}
|
|
208
|
+
if (args.action === 'sources' || args.action === 'nodes' || args.action === 'issues') {
|
|
209
|
+
const kind = args.action;
|
|
210
|
+
const limit = readLimit(args.limit, 25, 500);
|
|
211
|
+
method = kind === 'sources'
|
|
212
|
+
? AGENT_KNOWLEDGE_METHODS.sourcesList
|
|
213
|
+
: kind === 'nodes'
|
|
214
|
+
? AGENT_KNOWLEDGE_METHODS.nodesList
|
|
215
|
+
: AGENT_KNOWLEDGE_METHODS.issuesList;
|
|
216
|
+
const data = await getAgentKnowledgeJson(connection, method.route, { limit });
|
|
217
|
+
return validatedToolOutput(data, connection, method, (validatedData) => formatEntityList(validatedData, kind, limit));
|
|
218
|
+
}
|
|
219
|
+
if (args.action === 'item') {
|
|
220
|
+
method = AGENT_KNOWLEDGE_METHODS.itemGet;
|
|
221
|
+
const id = readString(args.id);
|
|
222
|
+
if (!id) return toolFailure('id is required for Agent Knowledge item lookup.');
|
|
223
|
+
const route = `/api/goodvibes-agent/knowledge/items/${encodeURIComponent(id)}`;
|
|
224
|
+
const data = await getAgentKnowledgeJson(connection, route);
|
|
225
|
+
return validatedToolOutput(data, connection, { ...method, route }, (validatedData) => formatItem(validatedData, id));
|
|
226
|
+
}
|
|
227
|
+
if (args.action === 'map') {
|
|
228
|
+
method = AGENT_KNOWLEDGE_METHODS.map;
|
|
229
|
+
const data = await getAgentKnowledgeJson(connection, method.route, {
|
|
230
|
+
limit: readLimit(args.limit, 50, 500),
|
|
231
|
+
query: readString(args.query),
|
|
232
|
+
});
|
|
233
|
+
return validatedToolOutput(data, connection, method, formatMap);
|
|
234
|
+
}
|
|
235
|
+
if (args.action === 'connectors') {
|
|
236
|
+
method = AGENT_KNOWLEDGE_METHODS.connectorsList;
|
|
237
|
+
const data = await getAgentKnowledgeJson(connection, method.route);
|
|
238
|
+
return validatedToolOutput(data, connection, method, formatConnectors);
|
|
239
|
+
}
|
|
240
|
+
if (args.action === 'connector' || args.action === 'connector_doctor') {
|
|
241
|
+
method = args.action === 'connector'
|
|
242
|
+
? AGENT_KNOWLEDGE_METHODS.connectorGet
|
|
243
|
+
: AGENT_KNOWLEDGE_METHODS.connectorDoctor;
|
|
244
|
+
const connectorId = readString(args.connectorId) || readString(args.id);
|
|
245
|
+
if (!connectorId) return toolFailure('connectorId or id is required for Agent Knowledge connector lookup.');
|
|
246
|
+
const suffix = args.action === 'connector_doctor' ? '/doctor' : '';
|
|
247
|
+
const route = `/api/goodvibes-agent/knowledge/connectors/${encodeURIComponent(connectorId)}${suffix}`;
|
|
248
|
+
const data = await getAgentKnowledgeJson(connection, route);
|
|
249
|
+
return validatedToolOutput(data, connection, { ...method, route }, (validatedData) => (
|
|
250
|
+
args.action === 'connector'
|
|
251
|
+
? formatConnector(validatedData, connectorId)
|
|
252
|
+
: formatConnectorDoctor(validatedData, connectorId)
|
|
253
|
+
));
|
|
146
254
|
}
|
|
147
|
-
|
|
148
|
-
if (!query) return toolFailure('query is required for Agent Knowledge search.');
|
|
149
|
-
const method = AGENT_KNOWLEDGE_METHODS.search;
|
|
150
|
-
const data = await sdk.knowledge.search({ query, limit: readLimit(args.limit, 10) });
|
|
151
|
-
return toolOutput(formatSearch(data, query));
|
|
255
|
+
return toolFailure(`Unknown Agent Knowledge action. Valid values ${ACTIONS.join(', ')}.`);
|
|
152
256
|
} catch (error) {
|
|
153
|
-
const method = args.action === 'status'
|
|
154
|
-
? AGENT_KNOWLEDGE_METHODS.status
|
|
155
|
-
: args.action === 'ask'
|
|
156
|
-
? AGENT_KNOWLEDGE_METHODS.ask
|
|
157
|
-
: AGENT_KNOWLEDGE_METHODS.search;
|
|
158
257
|
return classifyToolKnowledgeError(error, connection, method);
|
|
159
258
|
}
|
|
160
259
|
},
|
|
@@ -736,9 +736,8 @@ export function createAgentLocalRegistryTool(shellPaths: ShellPathService, memor
|
|
|
736
736
|
definition: {
|
|
737
737
|
name: 'agent_local_registry',
|
|
738
738
|
description: [
|
|
739
|
-
'Inspect
|
|
740
|
-
'
|
|
741
|
-
'Destructive record deletion requires confirm:true plus explicitUserRequest. This tool cannot create schedules, mutate connected hosts, send messages, run background jobs, or delegate build work.',
|
|
739
|
+
'Inspect or update Agent-local records: memory, notes, personas, skills, bundles, and routines.',
|
|
740
|
+
'Deletion requires confirm:true plus explicitUserRequest.',
|
|
742
741
|
].join(' '),
|
|
743
742
|
parameters: {
|
|
744
743
|
type: 'object',
|
|
@@ -761,13 +760,13 @@ export function createAgentLocalRegistryTool(shellPaths: ShellPathService, memor
|
|
|
761
760
|
steps: { type: 'string', description: 'Routine steps.' },
|
|
762
761
|
skills: { type: 'array', items: { type: 'string' }, description: 'Skill ids for skill_bundle create/update.' },
|
|
763
762
|
skillIds: { type: 'array', items: { type: 'string' }, description: 'Skill ids for skill_bundle create/update.' },
|
|
764
|
-
requiresEnv: { type: 'array', items: { type: 'string' }, description: '
|
|
763
|
+
requiresEnv: { type: 'array', items: { type: 'string' }, description: 'Required environment variable names.' },
|
|
765
764
|
requiresCommands: { type: 'array', items: { type: 'string' }, description: 'Command names required by a skill or routine.' },
|
|
766
765
|
triggers: { type: 'array', items: { type: 'string' } },
|
|
767
766
|
tags: { type: 'array', items: { type: 'string' } },
|
|
768
767
|
reason: { type: 'string' },
|
|
769
768
|
enabled: { type: 'boolean' },
|
|
770
|
-
activate: { type: 'boolean', description: 'Activate
|
|
769
|
+
activate: { type: 'boolean', description: 'Activate or clear the persona.' },
|
|
771
770
|
provenance: { type: 'string' },
|
|
772
771
|
confirm: { type: 'boolean', description: 'Required true for delete after an explicit user request.' },
|
|
773
772
|
explicitUserRequest: { type: 'string', description: 'Exact user request or faithful short summary authorizing delete.' },
|
|
@@ -53,11 +53,9 @@ export function createAgentMediaGenerateTool(
|
|
|
53
53
|
definition: {
|
|
54
54
|
name: 'agent_media_generate',
|
|
55
55
|
description: [
|
|
56
|
-
'Generate image or video
|
|
57
|
-
'Use only
|
|
58
|
-
'
|
|
59
|
-
'This tool does not use default knowledge, non-Agent knowledge segments, connected-host lifecycle routes, separate Agent jobs, delegated review, channel sends, or arbitrary route invocation.',
|
|
60
|
-
'Set confirm:true only for an explicit user request. Otherwise return the preview/confirmation error.',
|
|
56
|
+
'Generate one confirmed image or video artifact.',
|
|
57
|
+
'Use only for explicit media generation requests.',
|
|
58
|
+
'Returns artifact ids, not inline base64.',
|
|
61
59
|
].join(' '),
|
|
62
60
|
parameters: {
|
|
63
61
|
type: 'object',
|
|
@@ -68,7 +66,7 @@ export function createAgentMediaGenerateTool(
|
|
|
68
66
|
},
|
|
69
67
|
providerId: {
|
|
70
68
|
type: 'string',
|
|
71
|
-
description: 'Optional
|
|
69
|
+
description: 'Optional media provider id.',
|
|
72
70
|
},
|
|
73
71
|
modelId: {
|
|
74
72
|
type: 'string',
|
|
@@ -79,17 +79,16 @@ export function createAgentNotifyTool(
|
|
|
79
79
|
definition: {
|
|
80
80
|
name: 'agent_notify',
|
|
81
81
|
description: [
|
|
82
|
-
'Send one plain-text notification
|
|
83
|
-
'Use only
|
|
84
|
-
'
|
|
85
|
-
'Set confirm:true only for an explicit user request. Otherwise return the preview/confirmation error.',
|
|
82
|
+
'Send one confirmed plain-text notification.',
|
|
83
|
+
'Use only for explicit notify/message/alert requests.',
|
|
84
|
+
'Uses existing targets only.',
|
|
86
85
|
].join(' '),
|
|
87
86
|
parameters: {
|
|
88
87
|
type: 'object',
|
|
89
88
|
properties: {
|
|
90
89
|
message: {
|
|
91
90
|
type: 'string',
|
|
92
|
-
description: 'Plain-text notification body
|
|
91
|
+
description: 'Plain-text notification body.',
|
|
93
92
|
},
|
|
94
93
|
confirm: {
|
|
95
94
|
type: 'boolean',
|
|
@@ -97,7 +96,7 @@ export function createAgentNotifyTool(
|
|
|
97
96
|
},
|
|
98
97
|
explicitUserRequest: {
|
|
99
98
|
type: 'string',
|
|
100
|
-
description: '
|
|
99
|
+
description: 'User request authorizing this notification.',
|
|
101
100
|
},
|
|
102
101
|
},
|
|
103
102
|
required: ['message', 'confirm', 'explicitUserRequest'],
|
|
@@ -36,11 +36,9 @@ export function createAgentOperatorActionTool(
|
|
|
36
36
|
definition: {
|
|
37
37
|
name: 'agent_operator_action',
|
|
38
38
|
description: [
|
|
39
|
-
'
|
|
40
|
-
'
|
|
41
|
-
'
|
|
42
|
-
'This tool never creates, edits, deletes, or discovers automation definitions; never manages connected-host hosting; never uses default knowledge, non-Agent knowledge segments, separate Agent jobs, delegated review, or arbitrary route invocation.',
|
|
43
|
-
'Set confirm:true only for an explicit user request. Otherwise return the preview/confirmation error.',
|
|
39
|
+
'Run one confirmed allowlisted operator action.',
|
|
40
|
+
'Use only for explicit approval, automation, or schedule requests.',
|
|
41
|
+
'No automation definition edits or host lifecycle.',
|
|
44
42
|
].join(' '),
|
|
45
43
|
parameters: {
|
|
46
44
|
type: 'object',
|
|
@@ -52,7 +50,7 @@ export function createAgentOperatorActionTool(
|
|
|
52
50
|
},
|
|
53
51
|
targetId: {
|
|
54
52
|
type: 'string',
|
|
55
|
-
description: 'Generic target id.
|
|
53
|
+
description: 'Generic target id.',
|
|
56
54
|
},
|
|
57
55
|
approvalId: {
|
|
58
56
|
type: 'string',
|
|
@@ -60,7 +58,7 @@ export function createAgentOperatorActionTool(
|
|
|
60
58
|
},
|
|
61
59
|
jobId: {
|
|
62
60
|
type: 'string',
|
|
63
|
-
description: 'Automation job id
|
|
61
|
+
description: 'Automation job id.',
|
|
64
62
|
},
|
|
65
63
|
runId: {
|
|
66
64
|
type: 'string',
|
|
@@ -80,7 +78,7 @@ export function createAgentOperatorActionTool(
|
|
|
80
78
|
},
|
|
81
79
|
confirm: {
|
|
82
80
|
type: 'boolean',
|
|
83
|
-
description: 'Required true
|
|
81
|
+
description: 'Required true for confirmed operator action.',
|
|
84
82
|
},
|
|
85
83
|
explicitUserRequest: {
|
|
86
84
|
type: 'string',
|
|
@@ -176,10 +176,9 @@ export function createAgentOperatorBriefingTool(
|
|
|
176
176
|
definition: {
|
|
177
177
|
name: 'agent_operator_briefing',
|
|
178
178
|
description: [
|
|
179
|
-
'Read connected
|
|
180
|
-
'Use
|
|
181
|
-
'
|
|
182
|
-
'It never uses default knowledge, non-Agent knowledge segments, channel send routes, mutation routes, connected-host lifecycle, separate Agent jobs, or delegated review.',
|
|
179
|
+
'Read connected Agent operator state for a concise briefing.',
|
|
180
|
+
'Use for pending attention, approvals, automation, schedules, or status.',
|
|
181
|
+
'Read-only.',
|
|
183
182
|
].join(' '),
|
|
184
183
|
parameters: {
|
|
185
184
|
type: 'object',
|