actoviq-agent-sdk 0.4.12 → 0.4.13
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 +18 -0
- package/dist/src/config/agentDefinitionMigration.d.ts +125 -0
- package/dist/src/config/agentDefinitionMigration.d.ts.map +1 -0
- package/dist/src/config/agentDefinitionMigration.js +540 -0
- package/dist/src/config/agentDefinitionMigration.js.map +1 -0
- package/dist/src/config/agentProfiles.d.ts +19 -0
- package/dist/src/config/agentProfiles.d.ts.map +1 -1
- package/dist/src/config/agentProfiles.js +65 -13
- package/dist/src/config/agentProfiles.js.map +1 -1
- package/dist/src/config/modelConfigurationCatalog.d.ts +25 -0
- package/dist/src/config/modelConfigurationCatalog.d.ts.map +1 -0
- package/dist/src/config/modelConfigurationCatalog.js +50 -0
- package/dist/src/config/modelConfigurationCatalog.js.map +1 -0
- package/dist/src/gui/agentTargetPicker.d.ts +32 -0
- package/dist/src/gui/agentTargetPicker.d.ts.map +1 -0
- package/dist/src/gui/agentTargetPicker.js +99 -0
- package/dist/src/gui/agentTargetPicker.js.map +1 -0
- package/dist/src/gui/electronMain.js +1 -0
- package/dist/src/gui/electronMain.js.map +1 -1
- package/dist/src/gui/hadamardGui.d.ts +23 -0
- package/dist/src/gui/hadamardGui.d.ts.map +1 -1
- package/dist/src/gui/hadamardGui.js +4120 -931
- package/dist/src/gui/hadamardGui.js.map +1 -1
- package/dist/src/gui/projectWorkbench.d.ts +6 -2
- package/dist/src/gui/projectWorkbench.d.ts.map +1 -1
- package/dist/src/gui/projectWorkbench.js +76 -67
- package/dist/src/gui/projectWorkbench.js.map +1 -1
- package/dist/src/gui/promptTemplates.d.ts +0 -1
- package/dist/src/gui/promptTemplates.d.ts.map +1 -1
- package/dist/src/gui/promptTemplates.js +0 -3
- package/dist/src/gui/promptTemplates.js.map +1 -1
- package/dist/src/gui/transcript/clientBundle.d.ts +6 -1
- package/dist/src/gui/transcript/clientBundle.d.ts.map +1 -1
- package/dist/src/gui/transcript/clientBundle.js +6 -1
- package/dist/src/gui/transcript/clientBundle.js.map +1 -1
- package/dist/src/help/productCapabilities.d.ts +17 -0
- package/dist/src/help/productCapabilities.d.ts.map +1 -0
- package/dist/src/help/productCapabilities.js +146 -0
- package/dist/src/help/productCapabilities.js.map +1 -0
- package/dist/src/index.d.ts +15 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +9 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/issues/issueExecution.d.ts.map +1 -1
- package/dist/src/issues/issueExecution.js +29 -9
- package/dist/src/issues/issueExecution.js.map +1 -1
- package/dist/src/manager/assistantGlobalTools.d.ts +44 -0
- package/dist/src/manager/assistantGlobalTools.d.ts.map +1 -1
- package/dist/src/manager/assistantGlobalTools.js +565 -32
- package/dist/src/manager/assistantGlobalTools.js.map +1 -1
- package/dist/src/manager/assistantProposals.d.ts +87 -0
- package/dist/src/manager/assistantProposals.d.ts.map +1 -0
- package/dist/src/manager/assistantProposals.js +207 -0
- package/dist/src/manager/assistantProposals.js.map +1 -0
- package/dist/src/manager/referenceIndex.d.ts +82 -0
- package/dist/src/manager/referenceIndex.d.ts.map +1 -0
- package/dist/src/manager/referenceIndex.js +167 -0
- package/dist/src/manager/referenceIndex.js.map +1 -0
- package/dist/src/manager/referenceOperations.d.ts +108 -0
- package/dist/src/manager/referenceOperations.d.ts.map +1 -0
- package/dist/src/manager/referenceOperations.js +821 -0
- package/dist/src/manager/referenceOperations.js.map +1 -0
- package/dist/src/manager/resolveTargetRef.d.ts +67 -0
- package/dist/src/manager/resolveTargetRef.d.ts.map +1 -0
- package/dist/src/manager/resolveTargetRef.js +81 -0
- package/dist/src/manager/resolveTargetRef.js.map +1 -0
- package/dist/src/router/modelRouter.d.ts +22 -2
- package/dist/src/router/modelRouter.d.ts.map +1 -1
- package/dist/src/router/modelRouter.js +76 -9
- package/dist/src/router/modelRouter.js.map +1 -1
- package/dist/src/runtime/agentClient.d.ts +18 -0
- package/dist/src/runtime/agentClient.d.ts.map +1 -1
- package/dist/src/runtime/agentClient.js +209 -21
- package/dist/src/runtime/agentClient.js.map +1 -1
- package/dist/src/runtime/agentSession.d.ts +7 -0
- package/dist/src/runtime/agentSession.d.ts.map +1 -1
- package/dist/src/runtime/agentSession.js +10 -0
- package/dist/src/runtime/agentSession.js.map +1 -1
- package/dist/src/runtime/agentTemplates.d.ts +28 -0
- package/dist/src/runtime/agentTemplates.d.ts.map +1 -0
- package/dist/src/runtime/agentTemplates.js +73 -0
- package/dist/src/runtime/agentTemplates.js.map +1 -0
- package/dist/src/runtime/conversationEngine.d.ts +2 -0
- package/dist/src/runtime/conversationEngine.d.ts.map +1 -1
- package/dist/src/runtime/conversationEngine.js +10 -1
- package/dist/src/runtime/conversationEngine.js.map +1 -1
- package/dist/src/runtime/defaultHadamardAgents.d.ts.map +1 -1
- package/dist/src/runtime/defaultHadamardAgents.js +9 -47
- package/dist/src/runtime/defaultHadamardAgents.js.map +1 -1
- package/dist/src/runtime/effectiveAgentRunOptions.d.ts +49 -0
- package/dist/src/runtime/effectiveAgentRunOptions.d.ts.map +1 -0
- package/dist/src/runtime/effectiveAgentRunOptions.js +50 -0
- package/dist/src/runtime/effectiveAgentRunOptions.js.map +1 -0
- package/dist/src/runtime/externalAgentRunner.d.ts +25 -0
- package/dist/src/runtime/externalAgentRunner.d.ts.map +1 -0
- package/dist/src/runtime/externalAgentRunner.js +57 -0
- package/dist/src/runtime/externalAgentRunner.js.map +1 -0
- package/dist/src/runtime/hadamardAgentDefinitions.d.ts +15 -0
- package/dist/src/runtime/hadamardAgentDefinitions.d.ts.map +1 -1
- package/dist/src/runtime/hadamardAgentDefinitions.js +42 -2
- package/dist/src/runtime/hadamardAgentDefinitions.js.map +1 -1
- package/dist/src/runtime/hadamardAgents.d.ts +6 -0
- package/dist/src/runtime/hadamardAgents.d.ts.map +1 -1
- package/dist/src/runtime/hadamardAgents.js +52 -1
- package/dist/src/runtime/hadamardAgents.js.map +1 -1
- package/dist/src/runtime/hadamardPermissions.d.ts +1 -0
- package/dist/src/runtime/hadamardPermissions.d.ts.map +1 -1
- package/dist/src/runtime/hadamardPermissions.js +6 -0
- package/dist/src/runtime/hadamardPermissions.js.map +1 -1
- package/dist/src/runtime/tools.d.ts.map +1 -1
- package/dist/src/runtime/tools.js +2 -0
- package/dist/src/runtime/tools.js.map +1 -1
- package/dist/src/team/executorTarget.d.ts +26 -0
- package/dist/src/team/executorTarget.d.ts.map +1 -0
- package/dist/src/team/executorTarget.js +15 -0
- package/dist/src/team/executorTarget.js.map +1 -0
- package/dist/src/team/modelTeam.d.ts +5 -1
- package/dist/src/team/modelTeam.d.ts.map +1 -1
- package/dist/src/team/modelTeam.js +157 -41
- package/dist/src/team/modelTeam.js.map +1 -1
- package/dist/src/team/teamComposition.d.ts +20 -0
- package/dist/src/team/teamComposition.d.ts.map +1 -0
- package/dist/src/team/teamComposition.js +78 -0
- package/dist/src/team/teamComposition.js.map +1 -0
- package/dist/src/team/teamDefinitions.d.ts +10 -1
- package/dist/src/team/teamDefinitions.d.ts.map +1 -1
- package/dist/src/team/teamDefinitions.js +123 -16
- package/dist/src/team/teamDefinitions.js.map +1 -1
- package/dist/src/team/teamGraph.d.ts +1 -1
- package/dist/src/team/teamGraph.d.ts.map +1 -1
- package/dist/src/team/teamGraph.js +1 -1
- package/dist/src/team/teamGraph.js.map +1 -1
- package/dist/src/team/teamPrompts.d.ts.map +1 -1
- package/dist/src/team/teamPrompts.js +0 -4
- package/dist/src/team/teamPrompts.js.map +1 -1
- package/dist/src/team/teamProposalService.d.ts +9 -1
- package/dist/src/team/teamProposalService.d.ts.map +1 -1
- package/dist/src/team/teamProposalService.js +66 -6
- package/dist/src/team/teamProposalService.js.map +1 -1
- package/dist/src/team/teamPropose.d.ts +3 -1
- package/dist/src/team/teamPropose.d.ts.map +1 -1
- package/dist/src/team/teamPropose.js +16 -10
- package/dist/src/team/teamPropose.js.map +1 -1
- package/dist/src/team/teamRuntime.d.ts +5 -0
- package/dist/src/team/teamRuntime.d.ts.map +1 -1
- package/dist/src/team/teamRuntime.js +23 -5
- package/dist/src/team/teamRuntime.js.map +1 -1
- package/dist/src/team/workflowSquad.d.ts +10 -2
- package/dist/src/team/workflowSquad.d.ts.map +1 -1
- package/dist/src/team/workflowSquad.js +250 -12
- package/dist/src/team/workflowSquad.js.map +1 -1
- package/dist/src/tools/enterWorktree.d.ts.map +1 -1
- package/dist/src/tools/enterWorktree.js +3 -0
- package/dist/src/tools/enterWorktree.js.map +1 -1
- package/dist/src/tools/exaSearch.d.ts +2 -2
- package/dist/src/tools/exitWorktree.d.ts.map +1 -1
- package/dist/src/tools/exitWorktree.js +3 -1
- package/dist/src/tools/exitWorktree.js.map +1 -1
- package/dist/src/tools/hadamardCoreTools.d.ts +5 -14
- package/dist/src/tools/hadamardCoreTools.d.ts.map +1 -1
- package/dist/src/tools/hadamardCoreTools.js +31 -0
- package/dist/src/tools/hadamardCoreTools.js.map +1 -1
- package/dist/src/tools/hadamardFileTools.d.ts.map +1 -1
- package/dist/src/tools/hadamardFileTools.js +116 -38
- package/dist/src/tools/hadamardFileTools.js.map +1 -1
- package/dist/src/tools/planMode/PlanModeTools.js +2 -2
- package/dist/src/tools/planMode/PlanModeTools.js.map +1 -1
- package/dist/src/tui/hadamardTui.d.ts.map +1 -1
- package/dist/src/tui/hadamardTui.js +358 -69
- package/dist/src/tui/hadamardTui.js.map +1 -1
- package/dist/src/tui/pendingInput.d.ts +17 -0
- package/dist/src/tui/pendingInput.d.ts.map +1 -0
- package/dist/src/tui/pendingInput.js +23 -0
- package/dist/src/tui/pendingInput.js.map +1 -0
- package/dist/src/tui/reasoningDisplay.d.ts +13 -0
- package/dist/src/tui/reasoningDisplay.d.ts.map +1 -0
- package/dist/src/tui/reasoningDisplay.js +45 -0
- package/dist/src/tui/reasoningDisplay.js.map +1 -0
- package/dist/src/tui/screen.d.ts +11 -1
- package/dist/src/tui/screen.d.ts.map +1 -1
- package/dist/src/tui/screen.js +64 -34
- package/dist/src/tui/screen.js.map +1 -1
- package/dist/src/types.d.ts +171 -4
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/ui/commandSurface.d.ts +8 -0
- package/dist/src/ui/commandSurface.d.ts.map +1 -1
- package/dist/src/ui/commandSurface.js +71 -7
- package/dist/src/ui/commandSurface.js.map +1 -1
- package/package.json +1 -1
- package/dist/src/gui/projectSettings.d.ts +0 -2
- package/dist/src/gui/projectSettings.d.ts.map +0 -1
- package/dist/src/gui/projectSettings.js +0 -2
- package/dist/src/gui/projectSettings.js.map +0 -1
|
@@ -11,11 +11,11 @@ import { access } from 'node:fs/promises';
|
|
|
11
11
|
import path from 'node:path';
|
|
12
12
|
import { z } from 'zod';
|
|
13
13
|
import { resolveHadamardHome } from '../config/hadamardHome.js';
|
|
14
|
-
import { deleteAgentProfile, listAgentProfiles, listSelectableAgents, upsertAgentProfile, } from '../config/agentProfiles.js';
|
|
14
|
+
import { deleteAgentProfile, validateAgentProfile, listAgentProfiles, listSelectableAgents, upsertAgentProfile, } from '../config/agentProfiles.js';
|
|
15
15
|
import { getHadamardProjectSessionDirectory } from '../config/projectSessionDirectory.js';
|
|
16
16
|
import { listProjectIssues, isIssueStorageMode, } from '../issues/issueStore.js';
|
|
17
17
|
import { addMcpServer, readMcpServerConfig, removeMcpServer } from '../mcp/mcpServerConfig.js';
|
|
18
|
-
import { addBridgeConfig, findBridgeConfig, readBridgeConfigs, } from '../parity/bridgeConfigs.js';
|
|
18
|
+
import { addBridgeConfig, findBridgeConfig, readBridgeConfigs, removeBridgeConfig, } from '../parity/bridgeConfigs.js';
|
|
19
19
|
import { deleteRouterProfile, listRouterProfiles, saveRouterProfile, } from '../router/modelRouter.js';
|
|
20
20
|
import { MANAGED_PLUGIN_IDS, patchManagedPluginSettings, readManagedPluginCatalog, } from '../plugins/managedPluginCatalog.js';
|
|
21
21
|
import { isRecord } from '../runtime/helpers.js';
|
|
@@ -24,8 +24,15 @@ import { listScheduledAutomationTasks, setScheduledAutomationEnabled, upsertSche
|
|
|
24
24
|
import { isProjectStatus, readProjectMeta, writeProjectMeta } from '../gui/projectMeta.js';
|
|
25
25
|
import { readWorkspaceNote, writeWorkspaceNote } from '../gui/workspaceNote.js';
|
|
26
26
|
import { readWorkspaceRegistry } from '../gui/workspaceRegistry.js';
|
|
27
|
-
import { readProgressFile, readProjectPlanFile, } from './projectManager.js';
|
|
27
|
+
import { readManagerConfig, readProgressFile, readProjectPlanFile, } from './projectManager.js';
|
|
28
|
+
import { buildReferenceIndex, findBrokenRefs, findUsages, } from './referenceIndex.js';
|
|
29
|
+
import { renameDefinitionAndReferences, } from './referenceOperations.js';
|
|
30
|
+
import { deleteTeamDefinition, getBuiltInTeamDefinition, listTeamDefinitions, loadTeamDefinition, } from '../team/teamDefinitions.js';
|
|
31
|
+
import { readAllAgentReferenceProfiles, listAgentDefinitionNames, writeAgentDefinitionMarkdown, writeAgentProfileMarkdown, deleteAgentProfileMarkdown, projectAgentDefinitionsDir, } from '../config/agentDefinitionMigration.js';
|
|
32
|
+
import { deleteWorkflow, listWorkflows } from '../workflow/workflowPersistence.js';
|
|
28
33
|
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
34
|
+
import { loadHadamardAgentDefinitions } from '../runtime/hadamardAgentDefinitions.js';
|
|
35
|
+
import { getProductCapability, productCapabilities, searchProductCapabilities, } from '../help/productCapabilities.js';
|
|
29
36
|
export function isAssistantScope(value) {
|
|
30
37
|
return value === 'global' || value === 'project';
|
|
31
38
|
}
|
|
@@ -75,12 +82,19 @@ function redactBridgeConfig(config) {
|
|
|
75
82
|
name: config.name,
|
|
76
83
|
runtime: config.runtime,
|
|
77
84
|
execution: config.execution ?? 'api',
|
|
85
|
+
authSource: config.authSource ?? (config.execution === 'cli' ? 'native' : 'apiKey'),
|
|
86
|
+
credentialProvider: config.credentialProvider,
|
|
87
|
+
trustProjectResources: config.trustProjectResources === true,
|
|
78
88
|
provider: config.provider,
|
|
79
89
|
baseURL: config.baseURL || undefined,
|
|
80
90
|
model: config.model || undefined,
|
|
81
91
|
models: (config.models ?? []).map(model => ({
|
|
82
92
|
name: model.name,
|
|
83
93
|
context1M: model.context1M === true,
|
|
94
|
+
contextWindowTokens: model.contextWindowTokens,
|
|
95
|
+
maxContextWindowTokens: model.maxContextWindowTokens,
|
|
96
|
+
effectiveContextWindowPercent: model.effectiveContextWindowPercent,
|
|
97
|
+
autoCompactTokenLimit: model.autoCompactTokenLimit,
|
|
84
98
|
modality: model.modality ?? 'text',
|
|
85
99
|
})),
|
|
86
100
|
hasApiKey: Boolean(typeof config.apiKey === 'string' && config.apiKey.trim()),
|
|
@@ -100,17 +114,45 @@ function redactRouterProfile(profile) {
|
|
|
100
114
|
name: profile.name,
|
|
101
115
|
description: profile.description,
|
|
102
116
|
routerModel: redactRouterRef(profile.routerModel),
|
|
117
|
+
routerModelTarget: profile.routerModelTarget,
|
|
103
118
|
routes: profile.routes.map(route => ({
|
|
104
119
|
...redactRouterRef(route),
|
|
105
120
|
when: route.when,
|
|
106
121
|
name: route.name,
|
|
107
122
|
role: route.role,
|
|
108
123
|
description: route.description,
|
|
124
|
+
effort: route.effort,
|
|
125
|
+
target: route.target,
|
|
109
126
|
})),
|
|
110
127
|
fallback: profile.fallback ? redactRouterRef(profile.fallback) : undefined,
|
|
128
|
+
fallbackTarget: profile.fallbackTarget,
|
|
111
129
|
classificationPrompt: profile.classificationPrompt,
|
|
112
130
|
};
|
|
113
131
|
}
|
|
132
|
+
function redactEditorContext(context) {
|
|
133
|
+
if (!context)
|
|
134
|
+
return null;
|
|
135
|
+
const redact = (value) => {
|
|
136
|
+
if (Array.isArray(value))
|
|
137
|
+
return value.map(redact);
|
|
138
|
+
if (!isRecord(value))
|
|
139
|
+
return value;
|
|
140
|
+
const out = {};
|
|
141
|
+
for (const [key, item] of Object.entries(value)) {
|
|
142
|
+
if (/^(apiKey|password|secret|accessToken|refreshToken)$/i.test(key)) {
|
|
143
|
+
out[`${key}Configured`] = Boolean(typeof item === 'string' ? item.trim() : item);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
out[key] = redact(item);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
};
|
|
151
|
+
return {
|
|
152
|
+
...context,
|
|
153
|
+
...(context.draft ? { draft: redact(context.draft) } : {}),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
114
156
|
export async function listAssistantProjectBriefs(homeDir, currentWorkDir) {
|
|
115
157
|
const current = path.resolve(currentWorkDir);
|
|
116
158
|
const byPath = new Map();
|
|
@@ -176,6 +218,109 @@ async function assertKnownProject(host, projectPath) {
|
|
|
176
218
|
}
|
|
177
219
|
return resolved;
|
|
178
220
|
}
|
|
221
|
+
/** Reference snapshot used by the P3 reference/delete tools (same edges as /api/references). */
|
|
222
|
+
async function getReferenceSnapshot(host) {
|
|
223
|
+
if (host.getReferenceSnapshot)
|
|
224
|
+
return host.getReferenceSnapshot();
|
|
225
|
+
const bridgeConfigs = readBridgeConfigs(host.homeDir).configs;
|
|
226
|
+
// S3 unified store: profile edges come from the legacy store AND .md
|
|
227
|
+
// definitions in both scopes (incl. bridgeConfig-only definitions).
|
|
228
|
+
const profileByName = new Map(listAgentProfiles(host.homeDir).map(profile => [profile.name, profile]));
|
|
229
|
+
for (const profile of readAllAgentReferenceProfiles(host.homeDir, host.currentWorkDir)) {
|
|
230
|
+
profileByName.set(profile.name, profile);
|
|
231
|
+
}
|
|
232
|
+
const agentProfiles = [...profileByName.values()];
|
|
233
|
+
const routers = listRouterProfiles(host.currentWorkDir, host.homeDir).map(entry => entry.profile);
|
|
234
|
+
const teams = listTeamDefinitions(host.currentWorkDir, host.homeDir).map(entry => entry.definition);
|
|
235
|
+
const automationTasks = await listScheduledAutomationTasks(host.currentWorkDir)
|
|
236
|
+
.catch(() => []);
|
|
237
|
+
const manager = await readManagerConfig(host.currentWorkDir, resolveHadamardHome(host.homeDir))
|
|
238
|
+
.catch(() => undefined);
|
|
239
|
+
const projectMeta = await readProjectMeta(host.currentWorkDir, host.homeDir);
|
|
240
|
+
const issueStorage = isIssueStorageMode(projectMeta.issueStorage)
|
|
241
|
+
? projectMeta.issueStorage
|
|
242
|
+
: 'home';
|
|
243
|
+
const [issues, assistantConfig] = await Promise.all([
|
|
244
|
+
listProjectIssues(host.currentWorkDir, host.homeDir, issueStorage).catch(() => []),
|
|
245
|
+
readAssistantConfig(host.homeDir),
|
|
246
|
+
]);
|
|
247
|
+
const workflows = listWorkflows(host.currentWorkDir, host.homeDir);
|
|
248
|
+
const index = buildReferenceIndex({
|
|
249
|
+
bridgeConfigs,
|
|
250
|
+
agentProfiles,
|
|
251
|
+
routers,
|
|
252
|
+
teams,
|
|
253
|
+
automationTasks,
|
|
254
|
+
teamPreferences: host.readTeamPreferences?.() ?? null,
|
|
255
|
+
managerConfigs: manager
|
|
256
|
+
? [{ name: host.currentWorkDir, bridgeConfig: manager.bridgeConfig }]
|
|
257
|
+
: [],
|
|
258
|
+
issues,
|
|
259
|
+
assistantConfig,
|
|
260
|
+
session: host.getSessionRefState?.() ?? null,
|
|
261
|
+
});
|
|
262
|
+
return {
|
|
263
|
+
index,
|
|
264
|
+
known: {
|
|
265
|
+
configs: bridgeConfigs.map(config => config.name),
|
|
266
|
+
// Selectable agents include ephemeral per-config presets so an active
|
|
267
|
+
// session edge to one of them is not falsely reported as broken; the
|
|
268
|
+
// .md definition names cover unified-store agents in both scopes (S3).
|
|
269
|
+
agents: [
|
|
270
|
+
...listSelectableAgents(host.homeDir).map(agent => agent.name),
|
|
271
|
+
...listAgentDefinitionNames(host.homeDir, host.currentWorkDir),
|
|
272
|
+
],
|
|
273
|
+
teams: teams.map(team => team.name),
|
|
274
|
+
routers: routers.map(router => router.name),
|
|
275
|
+
workflows: workflows.map(workflow => workflow.name),
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
async function resolveReferenceOperationContext(host) {
|
|
280
|
+
if (host.referenceOperationContext)
|
|
281
|
+
return host.referenceOperationContext();
|
|
282
|
+
return {
|
|
283
|
+
projectDir: host.currentWorkDir,
|
|
284
|
+
homeDir: host.homeDir,
|
|
285
|
+
managerProjectPath: host.currentWorkDir,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* P3 delete discipline: zero-reference deletes proceed immediately; when
|
|
290
|
+
* findUsages reports references the definition is NOT deleted — a proposal
|
|
291
|
+
* card with the reference list and fallback strategies is staged instead, and
|
|
292
|
+
* only Apply (GUI endpoint over AssistantProposalStore) executes the delete.
|
|
293
|
+
*/
|
|
294
|
+
async function deleteWithConfirmation(host, kind, name, deleteNow) {
|
|
295
|
+
const { index } = await getReferenceSnapshot(host);
|
|
296
|
+
const usages = findUsages(index, kind, name);
|
|
297
|
+
if (usages.length === 0) {
|
|
298
|
+
await deleteNow();
|
|
299
|
+
return { ok: true, deleted: true, references: [] };
|
|
300
|
+
}
|
|
301
|
+
if (!host.proposals || !host.assistantSessionId) {
|
|
302
|
+
throw new Error(`Refusing to delete ${kind} "${name}": ${usages.length} reference(s) exist and no `
|
|
303
|
+
+ 'confirmation channel is available in this host. References: '
|
|
304
|
+
+ usages.map(edge => `${edge.from.kind} "${edge.from.name}" (${edge.field})`).join('; '));
|
|
305
|
+
}
|
|
306
|
+
const proposal = host.proposals.stageDelete({
|
|
307
|
+
assistantSessionId: host.assistantSessionId,
|
|
308
|
+
kind,
|
|
309
|
+
name,
|
|
310
|
+
references: usages,
|
|
311
|
+
});
|
|
312
|
+
host.onProposal?.(proposal);
|
|
313
|
+
return {
|
|
314
|
+
ok: true,
|
|
315
|
+
deleted: false,
|
|
316
|
+
staged: true,
|
|
317
|
+
proposalId: proposal.id,
|
|
318
|
+
message: `Found ${usages.length} reference(s) — staged a confirmation card. `
|
|
319
|
+
+ `The ${kind} is deleted only after the user applies it.`,
|
|
320
|
+
references: usages,
|
|
321
|
+
strategies: proposal.delete?.strategies ?? [],
|
|
322
|
+
};
|
|
323
|
+
}
|
|
179
324
|
export function buildAssistantGlobalSystemPrompt(currentWorkDir) {
|
|
180
325
|
return [
|
|
181
326
|
'You are the Hadamard desktop Assistant in Global scope.',
|
|
@@ -188,6 +333,13 @@ export function buildAssistantGlobalSystemPrompt(currentWorkDir) {
|
|
|
188
333
|
'- Start with ListProjects when the user asks about workspaces or status across projects.',
|
|
189
334
|
'- Use GetProjectOverview / GetProjectDocument / ListProjectIssues for deeper project inspection; always pass an explicit projectPath from ListProjects.',
|
|
190
335
|
'- Before changing settings, plugins, bridge configs, agents, schedules, or MCP, briefly say what you will change, then call the matching tool.',
|
|
336
|
+
'- Use ListReferences(kind, name) before any rename/delete to show impact, and ListBrokenReferences for proactive health checks.',
|
|
337
|
+
'- Rename tools (RenameBridgeConfig / RenameAgentProfile / RenameRouterProfile / RenameTeam) run one transaction that atomically rewrites every referencing definition.',
|
|
338
|
+
'- Delete-class tools (DeleteBridgeConfig / DeleteAgentProfile / DeleteRouterProfile / DeleteTeam) delete immediately only when nothing references the definition. When references exist they stage a confirmation card with the reference list and fallback strategies; the delete happens only when the user applies that card. Never claim a delete completed while a proposal is pending.',
|
|
339
|
+
'- UpsertTeam and UpsertWorkflow stage proposal cards (Preview/Apply) — they never write to disk directly. DeleteWorkflow removes an unreferenced script workflow directly and refuses while automation tasks still reference it.',
|
|
340
|
+
'- For any question about how to use Hadamard or what a feature does, call SearchProductCapabilities (or List/ReadProductCapability) and ground the answer in its UI location, prerequisites, steps, commands, and limitations. Do not answer product instructions from memory alone.',
|
|
341
|
+
'- Before changing the currently open Agent, Router, Graph, or Workflow, call GetCurrentEditorContext. Preserve its baseDigest when staging a Graph/Workflow proposal so Apply can reject stale drafts.',
|
|
342
|
+
'- ActivateAgent activates a saved profile by default; kind "config" activates a model configuration, kind "router" activates a Router, and kind "team" attaches a Graph or Workflow.',
|
|
191
343
|
'- Never echo API keys or other secrets. Tool results already redact them.',
|
|
192
344
|
'- Coding and file edits belong in the main chat, not here. Prefer OpenProject + telling the user to continue in the main conversation when implementation work is needed.',
|
|
193
345
|
'- Be concise and concrete.',
|
|
@@ -201,6 +353,11 @@ export async function createAssistantGlobalTools(host) {
|
|
|
201
353
|
apiKey: z.string().optional().describe('$ENV_VAR reference; literal secrets are not persisted'),
|
|
202
354
|
maxTokens: z.number().int().positive().optional(),
|
|
203
355
|
});
|
|
356
|
+
const targetRefSchema = z.discriminatedUnion('kind', [
|
|
357
|
+
z.strictObject({ kind: z.literal('model'), config: z.string(), model: z.string() }),
|
|
358
|
+
z.strictObject({ kind: z.literal('agent'), name: z.string() }),
|
|
359
|
+
z.strictObject({ kind: z.literal('team'), name: z.string() }),
|
|
360
|
+
]);
|
|
204
361
|
const ListProjects = tool({
|
|
205
362
|
name: 'ListProjects',
|
|
206
363
|
description: 'List remembered Hadamard workspaces with brief note, status, and issue counts.',
|
|
@@ -302,6 +459,48 @@ export async function createAssistantGlobalTools(host) {
|
|
|
302
459
|
homeDir: host.homeDir,
|
|
303
460
|
...(host.getAppState ? await host.getAppState() : {}),
|
|
304
461
|
}));
|
|
462
|
+
const GetCurrentEditorContext = tool({
|
|
463
|
+
name: 'GetCurrentEditorContext',
|
|
464
|
+
description: 'Read the active GUI page/entity and its unsaved Agent, Router, Graph, or Workflow draft with a stable base digest. Use before proposing editor changes.',
|
|
465
|
+
inputSchema: z.strictObject({}),
|
|
466
|
+
isReadOnly: () => true,
|
|
467
|
+
}, async () => ({
|
|
468
|
+
context: redactEditorContext(host.getEditorContext ? await host.getEditorContext() : null),
|
|
469
|
+
}));
|
|
470
|
+
const ListProductCapabilities = tool({
|
|
471
|
+
name: 'ListProductCapabilities',
|
|
472
|
+
description: 'List the machine-readable Hadamard capability catalog. Use this, SearchProductCapabilities, or ReadProductCapability before answering product how-to questions.',
|
|
473
|
+
inputSchema: z.strictObject({}),
|
|
474
|
+
isReadOnly: () => true,
|
|
475
|
+
}, async () => ({
|
|
476
|
+
capabilities: productCapabilities.map(capability => ({
|
|
477
|
+
id: capability.id,
|
|
478
|
+
title: capability.title,
|
|
479
|
+
summary: capability.summary,
|
|
480
|
+
uiLocations: capability.uiLocations,
|
|
481
|
+
commands: capability.commands,
|
|
482
|
+
})),
|
|
483
|
+
}));
|
|
484
|
+
const SearchProductCapabilities = tool({
|
|
485
|
+
name: 'SearchProductCapabilities',
|
|
486
|
+
description: 'Search grounded product instructions by feature, UI label, command, or user goal.',
|
|
487
|
+
inputSchema: z.strictObject({
|
|
488
|
+
query: z.string(),
|
|
489
|
+
limit: z.number().int().min(1).max(50).optional(),
|
|
490
|
+
}),
|
|
491
|
+
isReadOnly: () => true,
|
|
492
|
+
}, async (input) => ({ capabilities: searchProductCapabilities(input.query, input.limit) }));
|
|
493
|
+
const ReadProductCapability = tool({
|
|
494
|
+
name: 'ReadProductCapability',
|
|
495
|
+
description: 'Read complete current instructions for one capability id returned by List/SearchProductCapabilities.',
|
|
496
|
+
inputSchema: z.strictObject({ id: z.string() }),
|
|
497
|
+
isReadOnly: () => true,
|
|
498
|
+
}, async (input) => {
|
|
499
|
+
const capability = getProductCapability(input.id);
|
|
500
|
+
if (!capability)
|
|
501
|
+
throw new Error(`Unknown product capability: ${input.id}`);
|
|
502
|
+
return { capability };
|
|
503
|
+
});
|
|
305
504
|
const ListBridgeConfigs = tool({
|
|
306
505
|
name: 'ListBridgeConfigs',
|
|
307
506
|
description: 'List saved provider/bridge configs (API keys redacted).',
|
|
@@ -315,17 +514,43 @@ export async function createAssistantGlobalTools(host) {
|
|
|
315
514
|
description: 'List saved agent profiles and selectable auto presets.',
|
|
316
515
|
inputSchema: z.strictObject({}),
|
|
317
516
|
isReadOnly: () => true,
|
|
318
|
-
}, async () =>
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
517
|
+
}, async () => {
|
|
518
|
+
const definitions = await loadHadamardAgentDefinitions({
|
|
519
|
+
homeDir: host.homeDir,
|
|
520
|
+
workDir: host.currentWorkDir,
|
|
521
|
+
});
|
|
522
|
+
return {
|
|
523
|
+
profiles: listAgentProfiles(host.homeDir),
|
|
524
|
+
definitions: definitions.map(definition => ({
|
|
525
|
+
name: definition.name,
|
|
526
|
+
description: definition.description,
|
|
527
|
+
source: definition.source,
|
|
528
|
+
sourcePath: definition.sourcePath,
|
|
529
|
+
bridgeConfig: definition.bridgeConfig,
|
|
530
|
+
model: definition.model,
|
|
531
|
+
inheritSessionModel: !definition.bridgeConfig || !definition.model,
|
|
532
|
+
promptMode: definition.promptMode,
|
|
533
|
+
permissionMode: definition.permissionMode,
|
|
534
|
+
effort: definition.effort,
|
|
535
|
+
maxTokens: definition.maxTokens,
|
|
536
|
+
temperature: definition.temperature,
|
|
537
|
+
topP: definition.topP,
|
|
538
|
+
allowedTools: definition.allowedTools,
|
|
539
|
+
workspaceAccess: definition.workspaceAccess,
|
|
540
|
+
maxIterations: definition.maxToolIterations ?? definition.maxTurns,
|
|
541
|
+
timeoutMs: definition.timeoutMs,
|
|
542
|
+
subagent: definition.subagent !== false,
|
|
543
|
+
})),
|
|
544
|
+
selectable: listSelectableAgents(host.homeDir).map(agent => ({
|
|
545
|
+
name: agent.name,
|
|
546
|
+
source: agent.source,
|
|
547
|
+
bridgeConfig: agent.bridgeConfig,
|
|
548
|
+
model: agent.model,
|
|
549
|
+
effort: agent.effort,
|
|
550
|
+
ephemeral: agent.ephemeral === true,
|
|
551
|
+
})),
|
|
552
|
+
};
|
|
553
|
+
});
|
|
329
554
|
const ListRouterProfilesTool = tool({
|
|
330
555
|
name: 'ListRouterProfiles',
|
|
331
556
|
description: 'List project and personal router profiles with API keys redacted.',
|
|
@@ -446,6 +671,8 @@ export async function createAssistantGlobalTools(host) {
|
|
|
446
671
|
showProviderConfigsInComposer: z.boolean().optional(),
|
|
447
672
|
showAgentProfilesInComposer: z.boolean().optional(),
|
|
448
673
|
showRouterProfilesInComposer: z.boolean().optional(),
|
|
674
|
+
useDefaultModelAsFallback: z.boolean().optional(),
|
|
675
|
+
showBuiltInSubagents: z.boolean().optional(),
|
|
449
676
|
}),
|
|
450
677
|
}, async (input) => {
|
|
451
678
|
if (!host.applySettings)
|
|
@@ -482,6 +709,9 @@ export async function createAssistantGlobalTools(host) {
|
|
|
482
709
|
name: z.string(),
|
|
483
710
|
runtime: z.enum(['hadamard', 'claude', 'codewhale', 'pi', 'codex', 'reasonix', 'crush']),
|
|
484
711
|
execution: z.enum(['api', 'cli']).optional(),
|
|
712
|
+
authSource: z.enum(['native', 'apiKey']).optional(),
|
|
713
|
+
credentialProvider: z.string().optional(),
|
|
714
|
+
trustProjectResources: z.boolean().optional(),
|
|
485
715
|
provider: z.enum(['anthropic', 'openai']).optional(),
|
|
486
716
|
baseURL: z.string().optional(),
|
|
487
717
|
apiKey: z.string().optional(),
|
|
@@ -489,6 +719,10 @@ export async function createAssistantGlobalTools(host) {
|
|
|
489
719
|
models: z.array(z.strictObject({
|
|
490
720
|
name: z.string(),
|
|
491
721
|
context1M: z.boolean().optional(),
|
|
722
|
+
contextWindowTokens: z.number().int().positive().optional(),
|
|
723
|
+
maxContextWindowTokens: z.number().int().positive().optional(),
|
|
724
|
+
effectiveContextWindowPercent: z.number().positive().max(100).optional(),
|
|
725
|
+
autoCompactTokenLimit: z.number().int().positive().optional(),
|
|
492
726
|
modality: z.enum(['text', 'multimodal']).optional(),
|
|
493
727
|
})).optional(),
|
|
494
728
|
}),
|
|
@@ -498,6 +732,9 @@ export async function createAssistantGlobalTools(host) {
|
|
|
498
732
|
name: input.name.trim(),
|
|
499
733
|
runtime: input.runtime,
|
|
500
734
|
execution: input.execution ?? existing?.execution ?? 'api',
|
|
735
|
+
authSource: input.authSource ?? existing?.authSource,
|
|
736
|
+
credentialProvider: input.credentialProvider?.trim() || existing?.credentialProvider,
|
|
737
|
+
trustProjectResources: input.trustProjectResources ?? existing?.trustProjectResources,
|
|
501
738
|
provider: input.provider ?? existing?.provider ?? 'anthropic',
|
|
502
739
|
baseURL: input.baseURL?.trim() || existing?.baseURL,
|
|
503
740
|
apiKey: input.apiKey?.trim() || existing?.apiKey,
|
|
@@ -509,34 +746,83 @@ export async function createAssistantGlobalTools(host) {
|
|
|
509
746
|
});
|
|
510
747
|
const UpsertAgentProfileTool = tool({
|
|
511
748
|
name: 'UpsertAgentProfile',
|
|
512
|
-
description: 'Create or update
|
|
749
|
+
description: 'Create or update an agent (unified .md store, S3). Omit bridgeConfig+model for an inherit-session-model agent; pass scope "project" to save into <workDir>/.hadamard/agents.',
|
|
513
750
|
inputSchema: z.strictObject({
|
|
514
751
|
name: z.string(),
|
|
515
|
-
bridgeConfig: z.string(),
|
|
516
|
-
model: z.string(),
|
|
752
|
+
bridgeConfig: z.string().optional().describe('Omit (with model) for an inherit-session-model agent'),
|
|
753
|
+
model: z.string().optional(),
|
|
517
754
|
description: z.string().optional(),
|
|
518
755
|
permissionMode: z.enum(['default', 'acceptEdits', 'bypassPermissions', 'plan', 'auto']).optional(),
|
|
519
756
|
effort: z.enum(['auto', 'low', 'medium', 'high', 'max']).optional(),
|
|
520
757
|
maxTokens: z.number().int().positive().optional(),
|
|
521
758
|
temperature: z.number().min(0).max(2).optional(),
|
|
522
759
|
topP: z.number().min(0).max(1).optional(),
|
|
760
|
+
allowedTools: z.array(z.string().min(1)).optional(),
|
|
761
|
+
workspaceAccess: z.enum(['workspace', 'full']).optional(),
|
|
762
|
+
maxIterations: z.number().int().positive().optional(),
|
|
763
|
+
timeoutMs: z.number().int().positive().optional(),
|
|
523
764
|
systemPromptAppend: z.string().optional(),
|
|
765
|
+
scope: z.enum(['project', 'personal']).optional().describe('Defaults to personal (~/.hadamard/agents)'),
|
|
766
|
+
promptMode: z.enum(['extend', 'replace']).optional(),
|
|
767
|
+
subagent: z.boolean().optional().describe('Default true: the Agent/Task tool may delegate to this agent'),
|
|
524
768
|
}),
|
|
525
769
|
}, async (input) => {
|
|
770
|
+
const inheritModel = !input.bridgeConfig?.trim() || !input.model?.trim();
|
|
771
|
+
const extras = {
|
|
772
|
+
...(input.promptMode ? { promptMode: input.promptMode } : {}),
|
|
773
|
+
...(typeof input.subagent === 'boolean' ? { subagent: input.subagent } : {}),
|
|
774
|
+
...(input.permissionMode ? { permissionMode: input.permissionMode } : {}),
|
|
775
|
+
...(input.effort ? { effort: input.effort } : {}),
|
|
776
|
+
...(typeof input.maxTokens === 'number' ? { maxTokens: input.maxTokens } : {}),
|
|
777
|
+
...(typeof input.temperature === 'number' ? { temperature: input.temperature } : {}),
|
|
778
|
+
...(typeof input.topP === 'number' ? { topP: input.topP } : {}),
|
|
779
|
+
...(input.allowedTools?.length ? { tools: input.allowedTools } : {}),
|
|
780
|
+
...(input.workspaceAccess ? { workspaceAccess: input.workspaceAccess } : {}),
|
|
781
|
+
...(typeof input.maxIterations === 'number' ? { maxIterations: input.maxIterations } : {}),
|
|
782
|
+
...(typeof input.timeoutMs === 'number' ? { timeoutMs: input.timeoutMs } : {}),
|
|
783
|
+
};
|
|
784
|
+
const scope = input.scope === 'project' ? 'project' : 'personal';
|
|
785
|
+
const unified = inheritModel || scope === 'project' || Object.keys(extras).length > 0;
|
|
526
786
|
const profile = {
|
|
527
787
|
name: input.name.trim(),
|
|
528
|
-
bridgeConfig: input.bridgeConfig
|
|
529
|
-
model: input.model
|
|
788
|
+
bridgeConfig: input.bridgeConfig?.trim() ?? '',
|
|
789
|
+
model: input.model?.trim() ?? '',
|
|
530
790
|
...(input.description ? { description: input.description } : {}),
|
|
531
791
|
...(input.permissionMode ? { permissionMode: input.permissionMode } : {}),
|
|
532
792
|
...(input.effort ? { effort: input.effort } : {}),
|
|
533
793
|
...(typeof input.maxTokens === 'number' ? { maxTokens: input.maxTokens } : {}),
|
|
534
794
|
...(typeof input.temperature === 'number' ? { temperature: input.temperature } : {}),
|
|
535
795
|
...(typeof input.topP === 'number' ? { topP: input.topP } : {}),
|
|
796
|
+
...(input.allowedTools?.length ? { allowedTools: input.allowedTools } : {}),
|
|
797
|
+
...(input.workspaceAccess ? { workspaceAccess: input.workspaceAccess } : {}),
|
|
798
|
+
...(typeof input.maxIterations === 'number' ? { maxIterations: input.maxIterations } : {}),
|
|
799
|
+
...(typeof input.timeoutMs === 'number' ? { timeoutMs: input.timeoutMs } : {}),
|
|
536
800
|
...(input.systemPromptAppend ? { systemPromptAppend: input.systemPromptAppend } : {}),
|
|
801
|
+
...(input.promptMode ? { promptMode: input.promptMode } : {}),
|
|
802
|
+
...(typeof input.subagent === 'boolean' ? { subagent: input.subagent } : {}),
|
|
537
803
|
};
|
|
538
|
-
|
|
539
|
-
|
|
804
|
+
if (!unified) {
|
|
805
|
+
const saved = upsertAgentProfile(profile, host.homeDir);
|
|
806
|
+
return { ok: true, profile: saved.profile, warnings: saved.warnings };
|
|
807
|
+
}
|
|
808
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(profile.name)) {
|
|
809
|
+
throw new Error('Invalid agent name (use letters, digits, . _ -)');
|
|
810
|
+
}
|
|
811
|
+
const directory = scope === 'project' ? projectAgentDefinitionsDir(host.currentWorkDir) : undefined;
|
|
812
|
+
if (inheritModel) {
|
|
813
|
+
const filePath = writeAgentDefinitionMarkdown({
|
|
814
|
+
name: profile.name,
|
|
815
|
+
description: profile.description,
|
|
816
|
+
body: profile.systemPromptAppend,
|
|
817
|
+
extras,
|
|
818
|
+
directory,
|
|
819
|
+
homeDir: host.homeDir,
|
|
820
|
+
});
|
|
821
|
+
return { ok: true, filePath, inheritSessionModel: true };
|
|
822
|
+
}
|
|
823
|
+
const validation = validateAgentProfile(profile, host.homeDir);
|
|
824
|
+
const filePath = writeAgentProfileMarkdown(validation.profile, host.homeDir, { directory, extras });
|
|
825
|
+
return { ok: true, filePath, profile: validation.profile, warnings: validation.warnings };
|
|
540
826
|
});
|
|
541
827
|
const UpsertRouterProfileTool = tool({
|
|
542
828
|
name: 'UpsertRouterProfile',
|
|
@@ -546,6 +832,7 @@ export async function createAssistantGlobalTools(host) {
|
|
|
546
832
|
scope: z.enum(['project', 'personal']).optional(),
|
|
547
833
|
description: z.string().optional(),
|
|
548
834
|
routerModel: routerRefSchema,
|
|
835
|
+
routerModelTarget: targetRefSchema.optional(),
|
|
549
836
|
routes: z.array(z.strictObject({
|
|
550
837
|
model: z.string(),
|
|
551
838
|
provider: z.enum(['anthropic', 'openai']).optional(),
|
|
@@ -556,8 +843,11 @@ export async function createAssistantGlobalTools(host) {
|
|
|
556
843
|
name: z.string().optional(),
|
|
557
844
|
role: z.string().optional(),
|
|
558
845
|
description: z.string().optional(),
|
|
846
|
+
effort: z.enum(['auto', 'low', 'medium', 'high', 'max']).optional(),
|
|
847
|
+
target: targetRefSchema.optional(),
|
|
559
848
|
})).min(1),
|
|
560
849
|
fallback: routerRefSchema.optional(),
|
|
850
|
+
fallbackTarget: targetRefSchema.optional(),
|
|
561
851
|
classificationPrompt: z.string().optional(),
|
|
562
852
|
}),
|
|
563
853
|
}, async (input) => {
|
|
@@ -565,8 +855,10 @@ export async function createAssistantGlobalTools(host) {
|
|
|
565
855
|
name: input.name.trim(),
|
|
566
856
|
...(input.description?.trim() ? { description: input.description.trim() } : {}),
|
|
567
857
|
routerModel: input.routerModel,
|
|
858
|
+
...(input.routerModelTarget ? { routerModelTarget: input.routerModelTarget } : {}),
|
|
568
859
|
routes: input.routes,
|
|
569
860
|
...(input.fallback ? { fallback: input.fallback } : {}),
|
|
861
|
+
...(input.fallbackTarget ? { fallbackTarget: input.fallbackTarget } : {}),
|
|
570
862
|
...(input.classificationPrompt?.trim()
|
|
571
863
|
? { classificationPrompt: input.classificationPrompt.trim() }
|
|
572
864
|
: {}),
|
|
@@ -580,31 +872,110 @@ export async function createAssistantGlobalTools(host) {
|
|
|
580
872
|
});
|
|
581
873
|
const DeleteRouterProfileTool = tool({
|
|
582
874
|
name: 'DeleteRouterProfile',
|
|
583
|
-
description: 'Delete a router profile by name.
|
|
875
|
+
description: 'Delete a router profile by name. Deletes directly when unreferenced; stages a confirmation card when references exist.',
|
|
584
876
|
inputSchema: z.strictObject({
|
|
585
877
|
name: z.string(),
|
|
586
878
|
scope: z.enum(['project', 'personal']).optional(),
|
|
587
879
|
}),
|
|
588
880
|
}, async (input) => {
|
|
589
|
-
const
|
|
590
|
-
return
|
|
881
|
+
const name = input.name.trim();
|
|
882
|
+
return deleteWithConfirmation(host, 'router', name, async () => {
|
|
883
|
+
const deleted = await deleteRouterProfile(name, input.scope === 'personal' ? undefined : host.currentWorkDir, host.homeDir);
|
|
884
|
+
return { deleted };
|
|
885
|
+
});
|
|
591
886
|
});
|
|
592
887
|
const DeleteAgentProfileTool = tool({
|
|
593
888
|
name: 'DeleteAgentProfile',
|
|
594
|
-
description: 'Delete
|
|
889
|
+
description: 'Delete an agent by name (profile or pure .md definition, either scope — S3 unified store). Deletes directly when unreferenced; stages a confirmation card when references exist.',
|
|
890
|
+
inputSchema: z.strictObject({ name: z.string() }),
|
|
891
|
+
}, async (input) => {
|
|
892
|
+
const name = input.name.trim();
|
|
893
|
+
return deleteWithConfirmation(host, 'agent', name, () => {
|
|
894
|
+
deleteAgentProfile(name, host.homeDir);
|
|
895
|
+
// Pure .md agents / project scope are not in the legacy store.
|
|
896
|
+
deleteAgentProfileMarkdown(name, host.homeDir, projectAgentDefinitionsDir(host.currentWorkDir));
|
|
897
|
+
return { deleted: true };
|
|
898
|
+
});
|
|
899
|
+
});
|
|
900
|
+
const DeleteBridgeConfigTool = tool({
|
|
901
|
+
name: 'DeleteBridgeConfig',
|
|
902
|
+
description: 'Delete a provider/bridge config by name. Deletes directly when unreferenced; stages a confirmation card when references exist.',
|
|
595
903
|
inputSchema: z.strictObject({ name: z.string() }),
|
|
596
904
|
}, async (input) => {
|
|
597
|
-
|
|
598
|
-
|
|
905
|
+
const name = input.name.trim();
|
|
906
|
+
if (!findBridgeConfig(name, host.homeDir)) {
|
|
907
|
+
throw new Error(`Bridge config not found: ${name}`);
|
|
908
|
+
}
|
|
909
|
+
return deleteWithConfirmation(host, 'config', name, () => {
|
|
910
|
+
removeBridgeConfig(name, host.homeDir);
|
|
911
|
+
return { deleted: true };
|
|
912
|
+
});
|
|
913
|
+
});
|
|
914
|
+
const DeleteTeamTool = tool({
|
|
915
|
+
name: 'DeleteTeam',
|
|
916
|
+
description: 'Delete a Team definition by name. Built-in Teams cannot be deleted. Deletes directly when unreferenced; stages a confirmation card when references exist.',
|
|
917
|
+
inputSchema: z.strictObject({ name: z.string() }),
|
|
918
|
+
}, async (input) => {
|
|
919
|
+
const name = input.name.trim();
|
|
920
|
+
if (getBuiltInTeamDefinition(name)) {
|
|
921
|
+
throw new Error(`"${name}" is a built-in Team and cannot be deleted. Clone it instead.`);
|
|
922
|
+
}
|
|
923
|
+
const loaded = loadTeamDefinition(name, host.currentWorkDir, host.homeDir);
|
|
924
|
+
if (!loaded)
|
|
925
|
+
throw new Error(`Team not found: ${name}`);
|
|
926
|
+
return deleteWithConfirmation(host, 'team', name, async () => {
|
|
927
|
+
const deleted = await deleteTeamDefinition(name, host.currentWorkDir, host.homeDir);
|
|
928
|
+
if (!deleted)
|
|
929
|
+
throw new Error(`Team not found: ${name}`);
|
|
930
|
+
return { deleted: true };
|
|
931
|
+
});
|
|
599
932
|
});
|
|
600
933
|
const ActivateAgentTool = tool({
|
|
601
934
|
name: 'ActivateAgent',
|
|
602
|
-
description: 'Activate a
|
|
603
|
-
inputSchema: z.strictObject({
|
|
935
|
+
description: 'Activate a saved Agent/profile, provider config, Router, Graph, or Workflow in the current chat.',
|
|
936
|
+
inputSchema: z.strictObject({
|
|
937
|
+
name: z.string(),
|
|
938
|
+
kind: z.enum(['profile', 'config', 'router', 'team']).optional()
|
|
939
|
+
.describe('Defaults to "profile" (saved agent / selectable preset)'),
|
|
940
|
+
}),
|
|
604
941
|
}, async (input) => {
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
942
|
+
const kind = input.kind ?? 'profile';
|
|
943
|
+
if (kind === 'profile') {
|
|
944
|
+
if (!host.activateAgent)
|
|
945
|
+
throw new Error('ActivateAgent is unavailable in this host.');
|
|
946
|
+
return host.activateAgent(input.name.trim());
|
|
947
|
+
}
|
|
948
|
+
if (!host.activateTarget) {
|
|
949
|
+
throw new Error('ActivateAgent router/team activation is unavailable in this host.');
|
|
950
|
+
}
|
|
951
|
+
return host.activateTarget(kind, input.name.trim());
|
|
952
|
+
});
|
|
953
|
+
const UpdateTeamPreferencesTool = tool({
|
|
954
|
+
name: 'UpdateTeamPreferences',
|
|
955
|
+
description: 'Update Agents-page team behavior: automatic invocation, default attached Graph/Workflow, and confirmation before runs.',
|
|
956
|
+
inputSchema: z.strictObject({
|
|
957
|
+
autoInvoke: z.boolean().optional(),
|
|
958
|
+
defaultAttached: z.string().nullable().optional(),
|
|
959
|
+
confirmBeforeRun: z.boolean().optional(),
|
|
960
|
+
}),
|
|
961
|
+
}, async (input) => {
|
|
962
|
+
if (!host.writeTeamPreferences)
|
|
963
|
+
throw new Error('UpdateTeamPreferences is unavailable in this host.');
|
|
964
|
+
const current = host.readTeamPreferences?.() ?? {
|
|
965
|
+
autoInvoke: false,
|
|
966
|
+
defaultAttached: null,
|
|
967
|
+
confirmBeforeRun: true,
|
|
968
|
+
};
|
|
969
|
+
const next = {
|
|
970
|
+
autoInvoke: input.autoInvoke ?? current.autoInvoke,
|
|
971
|
+
defaultAttached: input.defaultAttached === undefined ? current.defaultAttached : input.defaultAttached,
|
|
972
|
+
confirmBeforeRun: input.confirmBeforeRun ?? current.confirmBeforeRun,
|
|
973
|
+
};
|
|
974
|
+
if (next.defaultAttached && !loadTeamDefinition(next.defaultAttached, host.currentWorkDir, host.homeDir)) {
|
|
975
|
+
throw new Error(`Graph/Workflow not found: ${next.defaultAttached}`);
|
|
976
|
+
}
|
|
977
|
+
await host.writeTeamPreferences(next);
|
|
978
|
+
return { ok: true, preferences: next };
|
|
608
979
|
});
|
|
609
980
|
const UpdateManagedPlugin = tool({
|
|
610
981
|
name: 'UpdateManagedPlugin',
|
|
@@ -729,12 +1100,162 @@ export async function createAssistantGlobalTools(host) {
|
|
|
729
1100
|
removeMcpServer(input.name.trim(), host.homeDir);
|
|
730
1101
|
return { ok: true, servers: readMcpServerConfig(host.homeDir).servers };
|
|
731
1102
|
});
|
|
1103
|
+
const ListReferencesTool = tool({
|
|
1104
|
+
name: 'ListReferences',
|
|
1105
|
+
description: 'List every reference to a definition (kind: config|agent|team|router) — impact analysis before rename/delete.',
|
|
1106
|
+
inputSchema: z.strictObject({
|
|
1107
|
+
kind: z.enum(['config', 'agent', 'team', 'router']),
|
|
1108
|
+
name: z.string(),
|
|
1109
|
+
}),
|
|
1110
|
+
isReadOnly: () => true,
|
|
1111
|
+
}, async (input) => {
|
|
1112
|
+
const { index } = await getReferenceSnapshot(host);
|
|
1113
|
+
const references = findUsages(index, input.kind, input.name.trim());
|
|
1114
|
+
return { kind: input.kind, name: input.name.trim(), count: references.length, references };
|
|
1115
|
+
});
|
|
1116
|
+
const ListBrokenReferencesTool = tool({
|
|
1117
|
+
name: 'ListBrokenReferences',
|
|
1118
|
+
description: 'List references whose target no longer exists (proactive health check).',
|
|
1119
|
+
inputSchema: z.strictObject({}),
|
|
1120
|
+
isReadOnly: () => true,
|
|
1121
|
+
}, async () => {
|
|
1122
|
+
const { index, known } = await getReferenceSnapshot(host);
|
|
1123
|
+
const broken = findBrokenRefs(index, known);
|
|
1124
|
+
return { count: broken.length, broken };
|
|
1125
|
+
});
|
|
1126
|
+
const makeRenameTool = (kind, toolName, label) => tool({
|
|
1127
|
+
name: toolName,
|
|
1128
|
+
description: `Rename a ${label} and atomically rewrite every referencing definition (single transaction with rollback).`,
|
|
1129
|
+
inputSchema: z.strictObject({
|
|
1130
|
+
oldName: z.string(),
|
|
1131
|
+
newName: z.string(),
|
|
1132
|
+
}),
|
|
1133
|
+
}, async (input) => {
|
|
1134
|
+
const report = await renameDefinitionAndReferences(kind, input.oldName, input.newName, await resolveReferenceOperationContext(host));
|
|
1135
|
+
return {
|
|
1136
|
+
ok: true,
|
|
1137
|
+
kind,
|
|
1138
|
+
oldName: input.oldName.trim(),
|
|
1139
|
+
newName: input.newName.trim(),
|
|
1140
|
+
rewritten: report.rewritten,
|
|
1141
|
+
};
|
|
1142
|
+
});
|
|
1143
|
+
const RenameBridgeConfigTool = makeRenameTool('config', 'RenameBridgeConfig', 'provider/bridge config');
|
|
1144
|
+
const RenameAgentProfileTool = makeRenameTool('agent', 'RenameAgentProfile', 'agent profile');
|
|
1145
|
+
const RenameRouterProfileTool = makeRenameTool('router', 'RenameRouterProfile', 'router profile');
|
|
1146
|
+
const RenameTeamTool = makeRenameTool('team', 'RenameTeam', 'Team definition');
|
|
1147
|
+
const UpsertTeamTool = tool({
|
|
1148
|
+
name: 'UpsertTeam',
|
|
1149
|
+
description: 'Stage a Team definition create/update as a proposal card (Preview/Apply). Never writes to disk directly; built-in Teams cannot be overwritten.',
|
|
1150
|
+
inputSchema: z.strictObject({
|
|
1151
|
+
projectPath: z.string().optional().describe('Defaults to the current workspace'),
|
|
1152
|
+
definition: z.record(z.string(), z.unknown())
|
|
1153
|
+
.describe('Complete TeamDefinition JSON, preferably graph v3 with stable node ids'),
|
|
1154
|
+
baseDigest: z.string().optional().describe('Digest from GetCurrentEditorContext; required automatically when changing the active unsaved Graph/Workflow draft'),
|
|
1155
|
+
explanation: z.string().optional(),
|
|
1156
|
+
}),
|
|
1157
|
+
}, async (input) => {
|
|
1158
|
+
if (!host.teamProposals || !host.assistantSessionId) {
|
|
1159
|
+
throw new Error('UpsertTeam is unavailable in this host (no Team proposal store).');
|
|
1160
|
+
}
|
|
1161
|
+
const projectPath = input.projectPath?.trim()
|
|
1162
|
+
? await assertKnownProject(host, input.projectPath)
|
|
1163
|
+
: path.resolve(host.currentWorkDir);
|
|
1164
|
+
const editor = host.getEditorContext ? await host.getEditorContext() : null;
|
|
1165
|
+
const definition = input.definition;
|
|
1166
|
+
const editorMatches = editor
|
|
1167
|
+
&& (editor.entityKind === 'graph' || editor.entityKind === 'workflow')
|
|
1168
|
+
&& editor.entityName === definition.name
|
|
1169
|
+
&& editor.draft
|
|
1170
|
+
&& editor.baseDigest;
|
|
1171
|
+
if (editorMatches && input.baseDigest && input.baseDigest !== editor.baseDigest) {
|
|
1172
|
+
throw new Error('The supplied editor base digest is stale. Read GetCurrentEditorContext and propose the change again.');
|
|
1173
|
+
}
|
|
1174
|
+
const proposal = host.teamProposals.stage({
|
|
1175
|
+
assistantSessionId: host.assistantSessionId,
|
|
1176
|
+
projectPath,
|
|
1177
|
+
definition,
|
|
1178
|
+
explanation: input.explanation ?? '',
|
|
1179
|
+
homeDir: host.homeDir,
|
|
1180
|
+
...(editorMatches ? {
|
|
1181
|
+
baseDefinition: editor.draft,
|
|
1182
|
+
editorBaseDigest: editor.baseDigest,
|
|
1183
|
+
} : {}),
|
|
1184
|
+
});
|
|
1185
|
+
host.onTeamProposal?.(proposal);
|
|
1186
|
+
return {
|
|
1187
|
+
kind: 'team.proposal',
|
|
1188
|
+
proposalId: proposal.id,
|
|
1189
|
+
projectPath: proposal.projectPath,
|
|
1190
|
+
teamName: proposal.teamName,
|
|
1191
|
+
explanation: proposal.explanation,
|
|
1192
|
+
problems: proposal.problems,
|
|
1193
|
+
diff: proposal.diff,
|
|
1194
|
+
status: proposal.status,
|
|
1195
|
+
};
|
|
1196
|
+
});
|
|
1197
|
+
const UpsertWorkflowTool = tool({
|
|
1198
|
+
name: 'UpsertWorkflow',
|
|
1199
|
+
description: 'Stage a script workflow create/update as a confirmation card. Apply writes <name>.js into the project or personal workflows directory.',
|
|
1200
|
+
inputSchema: z.strictObject({
|
|
1201
|
+
name: z.string(),
|
|
1202
|
+
script: z.string().describe('Complete workflow script (export const meta = {...} required)'),
|
|
1203
|
+
scope: z.enum(['project', 'personal']).optional().describe('Defaults to project'),
|
|
1204
|
+
description: z.string().optional(),
|
|
1205
|
+
explanation: z.string().optional(),
|
|
1206
|
+
}),
|
|
1207
|
+
}, async (input) => {
|
|
1208
|
+
if (!host.proposals || !host.assistantSessionId) {
|
|
1209
|
+
throw new Error('UpsertWorkflow is unavailable in this host (no proposal store).');
|
|
1210
|
+
}
|
|
1211
|
+
const proposal = host.proposals.stageWorkflowUpsert({
|
|
1212
|
+
assistantSessionId: host.assistantSessionId,
|
|
1213
|
+
name: input.name,
|
|
1214
|
+
script: input.script,
|
|
1215
|
+
scope: input.scope ?? 'project',
|
|
1216
|
+
projectPath: path.resolve(host.currentWorkDir),
|
|
1217
|
+
description: input.description,
|
|
1218
|
+
explanation: input.explanation,
|
|
1219
|
+
});
|
|
1220
|
+
host.onProposal?.(proposal);
|
|
1221
|
+
return {
|
|
1222
|
+
ok: true,
|
|
1223
|
+
staged: true,
|
|
1224
|
+
proposalId: proposal.id,
|
|
1225
|
+
name: proposal.workflow?.name,
|
|
1226
|
+
problems: proposal.workflow?.problems ?? [],
|
|
1227
|
+
message: 'Staged a confirmation card. The workflow file is written only after the user applies it.',
|
|
1228
|
+
};
|
|
1229
|
+
});
|
|
1230
|
+
const DeleteWorkflowTool = tool({
|
|
1231
|
+
name: 'DeleteWorkflow',
|
|
1232
|
+
description: 'Delete a script workflow by name. Refuses while automation tasks still reference it.',
|
|
1233
|
+
inputSchema: z.strictObject({ name: z.string() }),
|
|
1234
|
+
}, async (input) => {
|
|
1235
|
+
const name = input.name.trim();
|
|
1236
|
+
if (!listWorkflows(host.currentWorkDir, host.homeDir).some(workflow => workflow.name === name)) {
|
|
1237
|
+
throw new Error(`Workflow not found: ${name}`);
|
|
1238
|
+
}
|
|
1239
|
+
const tasks = await listScheduledAutomationTasks(host.currentWorkDir)
|
|
1240
|
+
.catch(() => []);
|
|
1241
|
+
const referencing = tasks.filter(task => task.kind === 'workflow' && task.workflowSource !== 'agent' && task.workflowName === name);
|
|
1242
|
+
if (referencing.length) {
|
|
1243
|
+
throw new Error(`Refusing to delete workflow "${name}": referenced by automation task(s): `
|
|
1244
|
+
+ `${referencing.map(task => task.name || task.id).join(', ')}. Delete or re-point those tasks first.`);
|
|
1245
|
+
}
|
|
1246
|
+
const deleted = await deleteWorkflow(name, host.currentWorkDir, host.homeDir);
|
|
1247
|
+
return { ok: true, deleted };
|
|
1248
|
+
});
|
|
732
1249
|
return [
|
|
733
1250
|
ListProjects,
|
|
734
1251
|
GetProjectOverview,
|
|
735
1252
|
GetProjectDocument,
|
|
736
1253
|
ListProjectIssues,
|
|
737
1254
|
GetAppState,
|
|
1255
|
+
GetCurrentEditorContext,
|
|
1256
|
+
ListProductCapabilities,
|
|
1257
|
+
SearchProductCapabilities,
|
|
1258
|
+
ReadProductCapability,
|
|
738
1259
|
ListBridgeConfigs,
|
|
739
1260
|
ListAgentProfiles,
|
|
740
1261
|
ListRouterProfilesTool,
|
|
@@ -752,11 +1273,23 @@ export async function createAssistantGlobalTools(host) {
|
|
|
752
1273
|
UpsertRouterProfileTool,
|
|
753
1274
|
DeleteRouterProfileTool,
|
|
754
1275
|
ActivateAgentTool,
|
|
1276
|
+
UpdateTeamPreferencesTool,
|
|
755
1277
|
UpdateManagedPlugin,
|
|
756
1278
|
UpsertScheduledTask,
|
|
757
1279
|
ToggleScheduledTask,
|
|
758
1280
|
AddMcpServerTool,
|
|
759
1281
|
RemoveMcpServerTool,
|
|
1282
|
+
ListReferencesTool,
|
|
1283
|
+
ListBrokenReferencesTool,
|
|
1284
|
+
RenameBridgeConfigTool,
|
|
1285
|
+
RenameAgentProfileTool,
|
|
1286
|
+
RenameRouterProfileTool,
|
|
1287
|
+
RenameTeamTool,
|
|
1288
|
+
DeleteBridgeConfigTool,
|
|
1289
|
+
DeleteTeamTool,
|
|
1290
|
+
UpsertTeamTool,
|
|
1291
|
+
UpsertWorkflowTool,
|
|
1292
|
+
DeleteWorkflowTool,
|
|
760
1293
|
];
|
|
761
1294
|
}
|
|
762
1295
|
//# sourceMappingURL=assistantGlobalTools.js.map
|