@open-mercato/ai-assistant 0.6.2-develop.3406.1.2b403f40da → 0.6.2-develop.3446.1.bd060c6017
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/.turbo/turbo-build.log +1 -1
- package/AGENTS.md +8 -1
- package/build.mjs +1 -0
- package/dist/frontend/components/AiChatButton.js +1 -1
- package/dist/frontend/components/AiChatButton.js.map +2 -2
- package/dist/modules/ai_assistant/__integration__/TC-AI-TOKEN-USAGE-001-005.spec.js +16 -5
- package/dist/modules/ai_assistant/__integration__/TC-AI-TOKEN-USAGE-001-005.spec.js.map +2 -2
- package/dist/modules/ai_assistant/ai-tools/meta-pack.js +58 -1
- package/dist/modules/ai_assistant/ai-tools/meta-pack.js.map +2 -2
- package/dist/modules/ai_assistant/api/ai/agents/route.js +2 -1
- package/dist/modules/ai_assistant/api/ai/agents/route.js.map +2 -2
- package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.js.map +2 -2
- package/dist/modules/ai_assistant/i18n/de.json +7 -1
- package/dist/modules/ai_assistant/i18n/en.json +7 -1
- package/dist/modules/ai_assistant/i18n/es.json +7 -1
- package/dist/modules/ai_assistant/i18n/pl.json +7 -1
- package/dist/modules/ai_assistant/lib/agent-registry.js +26 -6
- package/dist/modules/ai_assistant/lib/agent-registry.js.map +2 -2
- package/dist/modules/ai_assistant/lib/agent-runtime.js +21 -8
- package/dist/modules/ai_assistant/lib/agent-runtime.js.map +3 -3
- package/dist/modules/ai_assistant/lib/ai-agent-definition.js.map +2 -2
- package/dist/modules/ai_assistant/lib/pending-action-types.js.map +2 -2
- package/dist/modules/ai_assistant/lib/prepare-mutation.js +16 -6
- package/dist/modules/ai_assistant/lib/prepare-mutation.js.map +2 -2
- package/dist/modules/ai_assistant/lib/task-plan-labels.js +95 -0
- package/dist/modules/ai_assistant/lib/task-plan-labels.js.map +7 -0
- package/dist/modules/ai_assistant/lib/task-plan-stream.js +349 -0
- package/dist/modules/ai_assistant/lib/task-plan-stream.js.map +7 -0
- package/dist/modules/ai_assistant/lib/tool-test-fixtures.js +3 -0
- package/dist/modules/ai_assistant/lib/tool-test-fixtures.js.map +2 -2
- package/package.json +6 -6
- package/src/frontend/components/AiChatButton.tsx +1 -1
- package/src/modules/ai_assistant/__integration__/TC-AI-TOKEN-USAGE-001-005.spec.ts +20 -8
- package/src/modules/ai_assistant/ai-tools/__tests__/meta-pack.test.ts +60 -4
- package/src/modules/ai_assistant/ai-tools/meta-pack.ts +79 -2
- package/src/modules/ai_assistant/api/ai/agents/route.ts +2 -1
- package/src/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.tsx +1 -0
- package/src/modules/ai_assistant/i18n/de.json +7 -1
- package/src/modules/ai_assistant/i18n/en.json +7 -1
- package/src/modules/ai_assistant/i18n/es.json +7 -1
- package/src/modules/ai_assistant/i18n/pl.json +7 -1
- package/src/modules/ai_assistant/lib/__tests__/agent-registry.test.ts +60 -0
- package/src/modules/ai_assistant/lib/__tests__/ai-agent-definition.test.ts +4 -0
- package/src/modules/ai_assistant/lib/__tests__/prepare-mutation.test.ts +43 -0
- package/src/modules/ai_assistant/lib/__tests__/task-plan-stream.test.ts +375 -0
- package/src/modules/ai_assistant/lib/agent-registry.ts +36 -5
- package/src/modules/ai_assistant/lib/agent-runtime.ts +26 -8
- package/src/modules/ai_assistant/lib/ai-agent-definition.ts +14 -0
- package/src/modules/ai_assistant/lib/pending-action-types.ts +4 -1
- package/src/modules/ai_assistant/lib/prepare-mutation.ts +17 -5
- package/src/modules/ai_assistant/lib/task-plan-labels.ts +112 -0
- package/src/modules/ai_assistant/lib/task-plan-stream.ts +463 -0
- package/src/modules/ai_assistant/lib/tool-test-fixtures.ts +3 -0
- package/src/modules/ai_assistant/lib/types.ts +16 -0
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"ai_assistant.allowlist.save.success": "Liste gespeichert.",
|
|
147
147
|
"ai_assistant.allowlist.subtitle": "Schränke Anbieter und Modelle ein, die für diesen Mandanten verwendet werden dürfen. Die ENV-Liste ist die äußere Beschränkung — die Mandantenauswahl engt sie weiter ein.",
|
|
148
148
|
"ai_assistant.allowlist.title": "Anbieter- & Modell-Allowlist",
|
|
149
|
-
"ai_assistant.chat.agentTasksTitle": "
|
|
149
|
+
"ai_assistant.chat.agentTasksTitle": "Tool-Aufrufe",
|
|
150
150
|
"ai_assistant.chat.assistantRoleLabel": "Assistent",
|
|
151
151
|
"ai_assistant.chat.attachFile": "Attach file",
|
|
152
152
|
"ai_assistant.chat.betaChip": "beta",
|
|
@@ -257,6 +257,12 @@
|
|
|
257
257
|
"ai_assistant.chat.tabs.noSessions": "Keine Sitzungen",
|
|
258
258
|
"ai_assistant.chat.tabs.recentSessions": "Letzte Sitzungen",
|
|
259
259
|
"ai_assistant.chat.tabs.rename": "Umbenennen",
|
|
260
|
+
"ai_assistant.chat.taskDone": "fertig",
|
|
261
|
+
"ai_assistant.chat.taskFailed": "fehlgeschlagen",
|
|
262
|
+
"ai_assistant.chat.taskPending": "ausstehend",
|
|
263
|
+
"ai_assistant.chat.taskPlanTitle": "Plan",
|
|
264
|
+
"ai_assistant.chat.taskRunning": "läuft…",
|
|
265
|
+
"ai_assistant.chat.taskSkipped": "übersprungen",
|
|
260
266
|
"ai_assistant.chat.thinking": "Denkt nach...",
|
|
261
267
|
"ai_assistant.chat.toolDone": "done",
|
|
262
268
|
"ai_assistant.chat.toolError": "failed",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"ai_assistant.allowlist.save.success": "Allowlist saved.",
|
|
147
147
|
"ai_assistant.allowlist.subtitle": "Limit which providers and models the runtime, settings, and chat picker may use for this tenant. The env allowlist is the outer constraint — tenant picks narrow it further.",
|
|
148
148
|
"ai_assistant.allowlist.title": "AI provider & model allowlist",
|
|
149
|
-
"ai_assistant.chat.agentTasksTitle": "
|
|
149
|
+
"ai_assistant.chat.agentTasksTitle": "Tool calls",
|
|
150
150
|
"ai_assistant.chat.assistantRoleLabel": "Assistant",
|
|
151
151
|
"ai_assistant.chat.attachFile": "Attach file",
|
|
152
152
|
"ai_assistant.chat.betaChip": "beta",
|
|
@@ -257,6 +257,12 @@
|
|
|
257
257
|
"ai_assistant.chat.tabs.noSessions": "No sessions",
|
|
258
258
|
"ai_assistant.chat.tabs.recentSessions": "Recent sessions",
|
|
259
259
|
"ai_assistant.chat.tabs.rename": "Rename",
|
|
260
|
+
"ai_assistant.chat.taskDone": "done",
|
|
261
|
+
"ai_assistant.chat.taskFailed": "failed",
|
|
262
|
+
"ai_assistant.chat.taskPending": "pending",
|
|
263
|
+
"ai_assistant.chat.taskPlanTitle": "Plan",
|
|
264
|
+
"ai_assistant.chat.taskRunning": "running…",
|
|
265
|
+
"ai_assistant.chat.taskSkipped": "skipped",
|
|
260
266
|
"ai_assistant.chat.thinking": "Thinking...",
|
|
261
267
|
"ai_assistant.chat.toolDone": "done",
|
|
262
268
|
"ai_assistant.chat.toolError": "failed",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"ai_assistant.allowlist.save.success": "Lista guardada.",
|
|
147
147
|
"ai_assistant.allowlist.subtitle": "Limita los proveedores y modelos que el runtime, los ajustes y el selector de chat pueden usar para este inquilino. La lista ENV es la restricción externa — las elecciones del inquilino la reducen.",
|
|
148
148
|
"ai_assistant.allowlist.title": "Lista de proveedores y modelos AI",
|
|
149
|
-
"ai_assistant.chat.agentTasksTitle": "
|
|
149
|
+
"ai_assistant.chat.agentTasksTitle": "Llamadas a herramientas",
|
|
150
150
|
"ai_assistant.chat.assistantRoleLabel": "Asistente",
|
|
151
151
|
"ai_assistant.chat.attachFile": "Attach file",
|
|
152
152
|
"ai_assistant.chat.betaChip": "beta",
|
|
@@ -257,6 +257,12 @@
|
|
|
257
257
|
"ai_assistant.chat.tabs.noSessions": "Sin sesiones",
|
|
258
258
|
"ai_assistant.chat.tabs.recentSessions": "Sesiones recientes",
|
|
259
259
|
"ai_assistant.chat.tabs.rename": "Renombrar",
|
|
260
|
+
"ai_assistant.chat.taskDone": "hecho",
|
|
261
|
+
"ai_assistant.chat.taskFailed": "fallido",
|
|
262
|
+
"ai_assistant.chat.taskPending": "pendiente",
|
|
263
|
+
"ai_assistant.chat.taskPlanTitle": "Plan",
|
|
264
|
+
"ai_assistant.chat.taskRunning": "en curso…",
|
|
265
|
+
"ai_assistant.chat.taskSkipped": "omitido",
|
|
260
266
|
"ai_assistant.chat.thinking": "Pensando...",
|
|
261
267
|
"ai_assistant.chat.toolDone": "done",
|
|
262
268
|
"ai_assistant.chat.toolError": "failed",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"ai_assistant.allowlist.save.success": "Lista zapisana.",
|
|
147
147
|
"ai_assistant.allowlist.subtitle": "Ogranicz dostawców i modele dostępne dla tego najemcy. Lista ENV jest zewnętrznym ograniczeniem — wybory najemcy je zawężają.",
|
|
148
148
|
"ai_assistant.allowlist.title": "Lista dozwolonych dostawców i modeli AI",
|
|
149
|
-
"ai_assistant.chat.agentTasksTitle": "
|
|
149
|
+
"ai_assistant.chat.agentTasksTitle": "Wywołania narzędzi",
|
|
150
150
|
"ai_assistant.chat.assistantRoleLabel": "Asystent",
|
|
151
151
|
"ai_assistant.chat.attachFile": "Attach file",
|
|
152
152
|
"ai_assistant.chat.betaChip": "beta",
|
|
@@ -257,6 +257,12 @@
|
|
|
257
257
|
"ai_assistant.chat.tabs.noSessions": "Brak sesji",
|
|
258
258
|
"ai_assistant.chat.tabs.recentSessions": "Ostatnie sesje",
|
|
259
259
|
"ai_assistant.chat.tabs.rename": "Zmień nazwę",
|
|
260
|
+
"ai_assistant.chat.taskDone": "ukończono",
|
|
261
|
+
"ai_assistant.chat.taskFailed": "niepowodzenie",
|
|
262
|
+
"ai_assistant.chat.taskPending": "oczekuje",
|
|
263
|
+
"ai_assistant.chat.taskPlanTitle": "Plan",
|
|
264
|
+
"ai_assistant.chat.taskRunning": "w toku…",
|
|
265
|
+
"ai_assistant.chat.taskSkipped": "pominięto",
|
|
260
266
|
"ai_assistant.chat.thinking": "Myślenie...",
|
|
261
267
|
"ai_assistant.chat.toolDone": "done",
|
|
262
268
|
"ai_assistant.chat.toolError": "failed",
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
composeAgentExtensionEntries,
|
|
5
5
|
composeAgentOverrideMap
|
|
6
6
|
} from "./ai-overrides.js";
|
|
7
|
+
import { TASK_PLAN_TOOL_NAME } from "./task-plan-labels.js";
|
|
7
8
|
const agentsById = /* @__PURE__ */ new Map();
|
|
8
9
|
let loaded = false;
|
|
9
10
|
function isStringArray(value) {
|
|
@@ -17,7 +18,7 @@ function isAiAgentSuggestion(value) {
|
|
|
17
18
|
function isAiAgentExtension(value) {
|
|
18
19
|
if (!value || typeof value !== "object") return false;
|
|
19
20
|
const candidate = value;
|
|
20
|
-
return typeof candidate.targetAgentId === "string" && (!("replaceAllowedTools" in candidate) || isStringArray(candidate.replaceAllowedTools)) && (!("deleteAllowedTools" in candidate) || isStringArray(candidate.deleteAllowedTools)) && (!("appendAllowedTools" in candidate) || isStringArray(candidate.appendAllowedTools)) && (!("replaceSystemPrompt" in candidate) || typeof candidate.replaceSystemPrompt === "string") && (!("appendSystemPrompt" in candidate) || typeof candidate.appendSystemPrompt === "string") && (!("replaceSuggestions" in candidate) || Array.isArray(candidate.replaceSuggestions) && candidate.replaceSuggestions.every(isAiAgentSuggestion)) && (!("deleteSuggestions" in candidate) || isStringArray(candidate.deleteSuggestions)) && (!("appendSuggestions" in candidate) || Array.isArray(candidate.appendSuggestions) && candidate.appendSuggestions.every(isAiAgentSuggestion)) && (!("suggestions" in candidate) || Array.isArray(candidate.suggestions) && candidate.suggestions.every(isAiAgentSuggestion));
|
|
21
|
+
return typeof candidate.targetAgentId === "string" && (!("replaceAllowedTools" in candidate) || isStringArray(candidate.replaceAllowedTools)) && (!("deleteAllowedTools" in candidate) || isStringArray(candidate.deleteAllowedTools)) && (!("appendAllowedTools" in candidate) || isStringArray(candidate.appendAllowedTools)) && (!("taskPlan" in candidate) || candidate.taskPlan != null && typeof candidate.taskPlan === "object" && (!("enabled" in candidate.taskPlan) || typeof candidate.taskPlan.enabled === "boolean")) && (!("replaceSystemPrompt" in candidate) || typeof candidate.replaceSystemPrompt === "string") && (!("appendSystemPrompt" in candidate) || typeof candidate.appendSystemPrompt === "string") && (!("replaceSuggestions" in candidate) || Array.isArray(candidate.replaceSuggestions) && candidate.replaceSuggestions.every(isAiAgentSuggestion)) && (!("deleteSuggestions" in candidate) || isStringArray(candidate.deleteSuggestions)) && (!("appendSuggestions" in candidate) || Array.isArray(candidate.appendSuggestions) && candidate.appendSuggestions.every(isAiAgentSuggestion)) && (!("suggestions" in candidate) || Array.isArray(candidate.suggestions) && candidate.suggestions.every(isAiAgentSuggestion));
|
|
21
22
|
}
|
|
22
23
|
function isAiAgentDefinition(value) {
|
|
23
24
|
if (!value || typeof value !== "object") return false;
|
|
@@ -27,6 +28,21 @@ function isAiAgentDefinition(value) {
|
|
|
27
28
|
function uniqueStrings(values) {
|
|
28
29
|
return Array.from(new Set(values.filter((value) => typeof value === "string" && value.length > 0)));
|
|
29
30
|
}
|
|
31
|
+
function isAgentTaskPlanEnabled(agent) {
|
|
32
|
+
return agent.taskPlan?.enabled === true;
|
|
33
|
+
}
|
|
34
|
+
function normalizeTaskPlanTool(agent) {
|
|
35
|
+
const enabled = isAgentTaskPlanEnabled(agent);
|
|
36
|
+
const withoutInternalTool = agent.allowedTools.filter((toolName) => toolName !== TASK_PLAN_TOOL_NAME);
|
|
37
|
+
const allowedTools = enabled ? uniqueStrings([...withoutInternalTool, TASK_PLAN_TOOL_NAME]) : uniqueStrings(withoutInternalTool);
|
|
38
|
+
if (allowedTools.length === agent.allowedTools.length && allowedTools.every((toolName, index) => toolName === agent.allowedTools[index])) {
|
|
39
|
+
return agent;
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
...agent,
|
|
43
|
+
allowedTools
|
|
44
|
+
};
|
|
45
|
+
}
|
|
30
46
|
function applyStringListPatch(current, patch) {
|
|
31
47
|
const deleted = new Set(patch.delete ?? []);
|
|
32
48
|
return uniqueStrings([
|
|
@@ -60,9 +76,10 @@ ${suggestion.prompt}`;
|
|
|
60
76
|
return out;
|
|
61
77
|
}
|
|
62
78
|
function validateAndNormalizeAgent(candidate) {
|
|
79
|
+
const taskPlanNormalized = normalizeTaskPlanTool(candidate);
|
|
63
80
|
const rawProvider = candidate.defaultProvider;
|
|
64
81
|
if (typeof rawProvider !== "string" || rawProvider.trim().length === 0) {
|
|
65
|
-
return
|
|
82
|
+
return taskPlanNormalized;
|
|
66
83
|
}
|
|
67
84
|
const providerHint = rawProvider.trim();
|
|
68
85
|
const registered = llmProviderRegistry.get(providerHint);
|
|
@@ -70,9 +87,9 @@ function validateAndNormalizeAgent(candidate) {
|
|
|
70
87
|
console.warn(
|
|
71
88
|
`[AI Agents] Agent "${candidate.id}" declares defaultProvider "${providerHint}" which is not registered in llmProviderRegistry. The agent will be registered with defaultProvider: undefined so the resolution chain still works. Built-in provider ids: anthropic, google, openai, deepinfra, groq, together, fireworks, azure, litellm, ollama.`
|
|
72
89
|
);
|
|
73
|
-
return { ...
|
|
90
|
+
return { ...taskPlanNormalized, defaultProvider: void 0 };
|
|
74
91
|
}
|
|
75
|
-
return
|
|
92
|
+
return taskPlanNormalized;
|
|
76
93
|
}
|
|
77
94
|
function populateFromAgents(agents) {
|
|
78
95
|
for (const candidate of agents) {
|
|
@@ -130,13 +147,14 @@ function applyExtensionsToRegistry(extensions) {
|
|
|
130
147
|
const replacementSystemPrompt = extension.replaceSystemPrompt?.trim();
|
|
131
148
|
const appendSystemPrompt = extension.appendSystemPrompt?.trim();
|
|
132
149
|
const systemPrompt = replacementSystemPrompt ?? agent.systemPrompt.trim();
|
|
133
|
-
|
|
150
|
+
const patchedAgent = {
|
|
134
151
|
...agent,
|
|
135
152
|
allowedTools: applyStringListPatch(agent.allowedTools, {
|
|
136
153
|
replace: extension.replaceAllowedTools,
|
|
137
154
|
delete: extension.deleteAllowedTools,
|
|
138
155
|
append: extension.appendAllowedTools
|
|
139
156
|
}),
|
|
157
|
+
taskPlan: extension.taskPlan !== void 0 ? extension.taskPlan : agent.taskPlan,
|
|
140
158
|
systemPrompt: appendSystemPrompt ? `${systemPrompt}
|
|
141
159
|
|
|
142
160
|
${appendSystemPrompt}` : systemPrompt,
|
|
@@ -148,7 +166,8 @@ ${appendSystemPrompt}` : systemPrompt,
|
|
|
148
166
|
...extension.suggestions ?? []
|
|
149
167
|
]
|
|
150
168
|
})
|
|
151
|
-
}
|
|
169
|
+
};
|
|
170
|
+
agentsById.set(agent.id, validateAndNormalizeAgent(patchedAgent));
|
|
152
171
|
}
|
|
153
172
|
}
|
|
154
173
|
async function loadAgentRegistry() {
|
|
@@ -202,6 +221,7 @@ export {
|
|
|
202
221
|
applyAgentExtensionEntriesForTests,
|
|
203
222
|
applyAgentOverrideEntriesForTests,
|
|
204
223
|
getAgent,
|
|
224
|
+
isAgentTaskPlanEnabled,
|
|
205
225
|
listAgents,
|
|
206
226
|
listAgentsByModule,
|
|
207
227
|
loadAgentRegistry,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/ai_assistant/lib/agent-registry.ts"],
|
|
4
|
-
"sourcesContent": ["import { llmProviderRegistry } from '@open-mercato/shared/lib/ai/llm-provider-registry'\nimport type { AiAgentDefinition, AiAgentExtension, AiAgentSuggestion } from './ai-agent-definition'\nimport {\n applyAgentOverrideMap,\n composeAgentExtensionEntries,\n composeAgentOverrideMap,\n type AiAgentExtensionConfigEntry,\n type AiAgentOverrideConfigEntry,\n} from './ai-overrides'\n\nconst agentsById = new Map<string, AiAgentDefinition>()\nlet loaded = false\n\nfunction isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((item) => typeof item === 'string')\n}\n\nfunction isAiAgentSuggestion(value: unknown): value is AiAgentSuggestion {\n if (!value || typeof value !== 'object') return false\n const candidate = value as Record<string, unknown>\n return typeof candidate.label === 'string' && typeof candidate.prompt === 'string'\n}\n\nfunction isAiAgentExtension(value: unknown): value is AiAgentExtension {\n if (!value || typeof value !== 'object') return false\n const candidate = value as Record<string, unknown>\n return (\n typeof candidate.targetAgentId === 'string' &&\n (!('replaceAllowedTools' in candidate) || isStringArray(candidate.replaceAllowedTools)) &&\n (!('deleteAllowedTools' in candidate) || isStringArray(candidate.deleteAllowedTools)) &&\n (!('appendAllowedTools' in candidate) || isStringArray(candidate.appendAllowedTools)) &&\n (!('replaceSystemPrompt' in candidate) || typeof candidate.replaceSystemPrompt === 'string') &&\n (!('appendSystemPrompt' in candidate) || typeof candidate.appendSystemPrompt === 'string') &&\n (!('replaceSuggestions' in candidate) ||\n (Array.isArray(candidate.replaceSuggestions) && candidate.replaceSuggestions.every(isAiAgentSuggestion))) &&\n (!('deleteSuggestions' in candidate) || isStringArray(candidate.deleteSuggestions)) &&\n (!('appendSuggestions' in candidate) ||\n (Array.isArray(candidate.appendSuggestions) && candidate.appendSuggestions.every(isAiAgentSuggestion))) &&\n (!('suggestions' in candidate) ||\n (Array.isArray(candidate.suggestions) && candidate.suggestions.every(isAiAgentSuggestion)))\n )\n}\n\nfunction isAiAgentDefinition(value: unknown): value is AiAgentDefinition {\n if (!value || typeof value !== 'object') return false\n const candidate = value as Record<string, unknown>\n return (\n typeof candidate.id === 'string' &&\n typeof candidate.moduleId === 'string' &&\n typeof candidate.label === 'string' &&\n typeof candidate.description === 'string' &&\n typeof candidate.systemPrompt === 'string' &&\n isStringArray(candidate.allowedTools)\n )\n}\n\nfunction uniqueStrings(values: readonly string[]): string[] {\n return Array.from(new Set(values.filter((value) => typeof value === 'string' && value.length > 0)))\n}\n\nfunction applyStringListPatch(\n current: readonly string[],\n patch: {\n replace?: readonly string[]\n delete?: readonly string[]\n append?: readonly string[]\n },\n): string[] {\n const deleted = new Set(patch.delete ?? [])\n return uniqueStrings([\n ...(patch.replace ?? current).filter((value) => !deleted.has(value)),\n ...(patch.append ?? []),\n ])\n}\n\nfunction suggestionDeleteKey(suggestion: AiAgentSuggestion): string[] {\n return [suggestion.label, suggestion.prompt].filter((value) => value.length > 0)\n}\n\nfunction applySuggestionPatch(\n current: readonly AiAgentSuggestion[],\n patch: {\n replace?: readonly AiAgentSuggestion[]\n delete?: readonly string[]\n append?: readonly AiAgentSuggestion[]\n },\n): AiAgentSuggestion[] {\n const deleted = new Set(patch.delete ?? [])\n const base = patch.replace ?? current\n const out: AiAgentSuggestion[] = []\n const seen = new Set<string>()\n for (const suggestion of base) {\n if (suggestionDeleteKey(suggestion).some((key) => deleted.has(key))) continue\n const key = `${suggestion.label}\\n${suggestion.prompt}`\n if (seen.has(key)) continue\n seen.add(key)\n out.push(suggestion)\n }\n for (const suggestion of patch.append ?? []) {\n const key = `${suggestion.label}\\n${suggestion.prompt}`\n if (seen.has(key)) continue\n seen.add(key)\n out.push(suggestion)\n }\n return out\n}\n\nfunction validateAndNormalizeAgent(candidate: AiAgentDefinition): AiAgentDefinition {\n const rawProvider = candidate.defaultProvider\n if (typeof rawProvider !== 'string' || rawProvider.trim().length === 0) {\n return candidate\n }\n const providerHint = rawProvider.trim()\n const registered = llmProviderRegistry.get(providerHint)\n if (!registered) {\n console.warn(\n `[AI Agents] Agent \"${candidate.id}\" declares defaultProvider \"${providerHint}\" which is not registered in llmProviderRegistry. ` +\n `The agent will be registered with defaultProvider: undefined so the resolution chain still works. ` +\n `Built-in provider ids: anthropic, google, openai, deepinfra, groq, together, fireworks, azure, litellm, ollama.`,\n )\n return { ...candidate, defaultProvider: undefined }\n }\n return candidate\n}\n\nfunction populateFromAgents(agents: unknown[]): void {\n for (const candidate of agents) {\n if (!isAiAgentDefinition(candidate)) {\n console.warn('[AI Agents] Skipping malformed agent entry in ai-agents.generated.ts')\n continue\n }\n const existing = agentsById.get(candidate.id)\n if (existing) {\n throw new Error(\n `[AI Agents] Duplicate agent id \"${candidate.id}\" \u2014 already registered by module \"${existing.moduleId}\", conflicts with module \"${candidate.moduleId}\". Export \\`aiAgentOverrides\\` from your module's \\`ai-agents.ts\\` (or set it on the modules.ts entry) to replace an agent across modules.`\n )\n }\n agentsById.set(candidate.id, validateAndNormalizeAgent(candidate))\n }\n}\n\nasync function loadOverrideEntries(): Promise<AiAgentOverrideConfigEntry[]> {\n try {\n const mod = (await import(\n '@/.mercato/generated/ai-agents.generated'\n )) as { aiAgentOverrideEntries?: unknown[] }\n return Array.isArray(mod.aiAgentOverrideEntries)\n ? (mod.aiAgentOverrideEntries as AiAgentOverrideConfigEntry[])\n : []\n } catch {\n // No generated file yet \u2014 pre-generate builds and tests fall through.\n return []\n }\n}\n\nfunction applyOverridesToRegistry(entries: readonly AiAgentOverrideConfigEntry[]): void {\n const overrideMap = composeAgentOverrideMap(entries)\n if (Object.keys(overrideMap).length === 0) return\n const overridden = applyAgentOverrideMap(Array.from(agentsById.values()), overrideMap)\n agentsById.clear()\n for (const agent of overridden) agentsById.set(agent.id, agent)\n for (const [id, value] of Object.entries(overrideMap)) {\n const verb = value === null ? 'disabled' : 'replaced'\n console.info(`[AI Overrides] Agent \"${id}\" ${verb} by override.`)\n }\n}\n\nasync function loadExtensionEntries(): Promise<AiAgentExtension[]> {\n try {\n const mod = (await import(\n '@/.mercato/generated/ai-agents.generated'\n )) as { aiAgentExtensionEntries?: unknown[] }\n const entries = Array.isArray(mod.aiAgentExtensionEntries)\n ? (mod.aiAgentExtensionEntries as AiAgentExtensionConfigEntry[])\n : []\n return composeAgentExtensionEntries(entries).filter(isAiAgentExtension)\n } catch {\n return []\n }\n}\n\nfunction applyExtensionsToRegistry(extensions: readonly AiAgentExtension[]): void {\n if (extensions.length === 0) return\n for (const extension of extensions) {\n const agent = agentsById.get(extension.targetAgentId)\n if (!agent) {\n console.warn(\n `[AI Agents] Skipping extension for unknown agent \"${extension.targetAgentId}\".`,\n )\n continue\n }\n\n const replacementSystemPrompt = extension.replaceSystemPrompt?.trim()\n const appendSystemPrompt = extension.appendSystemPrompt?.trim()\n const systemPrompt = replacementSystemPrompt ?? agent.systemPrompt.trim()\n agentsById.set(agent.id, {\n ...agent,\n allowedTools: applyStringListPatch(agent.allowedTools, {\n replace: extension.replaceAllowedTools,\n delete: extension.deleteAllowedTools,\n append: extension.appendAllowedTools,\n }),\n systemPrompt: appendSystemPrompt\n ? `${systemPrompt}\\n\\n${appendSystemPrompt}`\n : systemPrompt,\n suggestions: applySuggestionPatch(agent.suggestions ?? [], {\n replace: extension.replaceSuggestions,\n delete: extension.deleteSuggestions,\n append: [\n ...(extension.appendSuggestions ?? []),\n ...(extension.suggestions ?? []),\n ],\n }),\n })\n }\n}\n\nexport async function loadAgentRegistry(): Promise<void> {\n if (loaded) return\n try {\n const mod = (await import(\n '@/.mercato/generated/ai-agents.generated'\n )) as { allAiAgents?: unknown[] }\n const agents = Array.isArray(mod.allAiAgents) ? mod.allAiAgents : []\n populateFromAgents(agents)\n } catch (error) {\n console.error(\n '[AI Agents] Could not load ai-agents.generated.ts (agent registry empty):',\n error\n )\n } finally {\n try {\n const overrideEntries = await loadOverrideEntries()\n applyOverridesToRegistry(overrideEntries)\n const extensionEntries = await loadExtensionEntries()\n applyExtensionsToRegistry(extensionEntries)\n } catch (error) {\n console.error('[AI Agents] Failed to apply agent overrides/extensions:', error)\n }\n loaded = true\n }\n}\n\nexport function getAgent(id: string): AiAgentDefinition | undefined {\n return agentsById.get(id)\n}\n\nexport function listAgents(): AiAgentDefinition[] {\n return Array.from(agentsById.values()).sort((a, b) => a.id.localeCompare(b.id))\n}\n\nexport function listAgentsByModule(moduleId: string): AiAgentDefinition[] {\n return listAgents().filter((agent) => agent.moduleId === moduleId)\n}\n\n/**\n * @__internal\n * Test-only hook \u2014 clears the cached registry so `loadAgentRegistry` re-evaluates its source.\n */\nexport function resetAgentRegistryForTests(): void {\n agentsById.clear()\n loaded = false\n}\n\n/**\n * @__internal\n * Test-only hook \u2014 seeds the registry directly from a fixture array without going through\n * the dynamic generated-file import. Used by the registry's own unit tests.\n */\nexport function seedAgentRegistryForTests(agents: unknown[]): void {\n agentsById.clear()\n populateFromAgents(agents)\n loaded = true\n}\n\n/**\n * @__internal\n * Test-only hook \u2014 apply override entries against the seeded registry to\n * exercise the override pipeline without round-tripping through the\n * generated file.\n */\nexport function applyAgentOverrideEntriesForTests(\n entries: readonly AiAgentOverrideConfigEntry[],\n): void {\n applyOverridesToRegistry(entries)\n}\n\n/**\n * @__internal Test-only hook \u2014 apply additive extension entries against the\n * seeded registry without round-tripping through the generated file.\n */\nexport function applyAgentExtensionEntriesForTests(\n entries: readonly AiAgentExtension[],\n): void {\n applyExtensionsToRegistry(entries)\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,2BAA2B;AAEpC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAGK;
|
|
4
|
+
"sourcesContent": ["import { llmProviderRegistry } from '@open-mercato/shared/lib/ai/llm-provider-registry'\nimport type { AiAgentDefinition, AiAgentExtension, AiAgentSuggestion } from './ai-agent-definition'\nimport {\n applyAgentOverrideMap,\n composeAgentExtensionEntries,\n composeAgentOverrideMap,\n type AiAgentExtensionConfigEntry,\n type AiAgentOverrideConfigEntry,\n} from './ai-overrides'\nimport { TASK_PLAN_TOOL_NAME } from './task-plan-labels'\n\nconst agentsById = new Map<string, AiAgentDefinition>()\nlet loaded = false\n\nfunction isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((item) => typeof item === 'string')\n}\n\nfunction isAiAgentSuggestion(value: unknown): value is AiAgentSuggestion {\n if (!value || typeof value !== 'object') return false\n const candidate = value as Record<string, unknown>\n return typeof candidate.label === 'string' && typeof candidate.prompt === 'string'\n}\n\nfunction isAiAgentExtension(value: unknown): value is AiAgentExtension {\n if (!value || typeof value !== 'object') return false\n const candidate = value as Record<string, unknown>\n return (\n typeof candidate.targetAgentId === 'string' &&\n (!('replaceAllowedTools' in candidate) || isStringArray(candidate.replaceAllowedTools)) &&\n (!('deleteAllowedTools' in candidate) || isStringArray(candidate.deleteAllowedTools)) &&\n (!('appendAllowedTools' in candidate) || isStringArray(candidate.appendAllowedTools)) &&\n (!('taskPlan' in candidate) ||\n (candidate.taskPlan != null &&\n typeof candidate.taskPlan === 'object' &&\n (!('enabled' in candidate.taskPlan) ||\n typeof (candidate.taskPlan as { enabled?: unknown }).enabled === 'boolean'))) &&\n (!('replaceSystemPrompt' in candidate) || typeof candidate.replaceSystemPrompt === 'string') &&\n (!('appendSystemPrompt' in candidate) || typeof candidate.appendSystemPrompt === 'string') &&\n (!('replaceSuggestions' in candidate) ||\n (Array.isArray(candidate.replaceSuggestions) && candidate.replaceSuggestions.every(isAiAgentSuggestion))) &&\n (!('deleteSuggestions' in candidate) || isStringArray(candidate.deleteSuggestions)) &&\n (!('appendSuggestions' in candidate) ||\n (Array.isArray(candidate.appendSuggestions) && candidate.appendSuggestions.every(isAiAgentSuggestion))) &&\n (!('suggestions' in candidate) ||\n (Array.isArray(candidate.suggestions) && candidate.suggestions.every(isAiAgentSuggestion)))\n )\n}\n\nfunction isAiAgentDefinition(value: unknown): value is AiAgentDefinition {\n if (!value || typeof value !== 'object') return false\n const candidate = value as Record<string, unknown>\n return (\n typeof candidate.id === 'string' &&\n typeof candidate.moduleId === 'string' &&\n typeof candidate.label === 'string' &&\n typeof candidate.description === 'string' &&\n typeof candidate.systemPrompt === 'string' &&\n isStringArray(candidate.allowedTools)\n )\n}\n\nfunction uniqueStrings(values: readonly string[]): string[] {\n return Array.from(new Set(values.filter((value) => typeof value === 'string' && value.length > 0)))\n}\n\nexport function isAgentTaskPlanEnabled(agent: Pick<AiAgentDefinition, 'taskPlan'>): boolean {\n return agent.taskPlan?.enabled === true\n}\n\nfunction normalizeTaskPlanTool(agent: AiAgentDefinition): AiAgentDefinition {\n const enabled = isAgentTaskPlanEnabled(agent)\n const withoutInternalTool = agent.allowedTools.filter((toolName) => toolName !== TASK_PLAN_TOOL_NAME)\n const allowedTools = enabled\n ? uniqueStrings([...withoutInternalTool, TASK_PLAN_TOOL_NAME])\n : uniqueStrings(withoutInternalTool)\n if (\n allowedTools.length === agent.allowedTools.length &&\n allowedTools.every((toolName, index) => toolName === agent.allowedTools[index])\n ) {\n return agent\n }\n return {\n ...agent,\n allowedTools,\n }\n}\n\nfunction applyStringListPatch(\n current: readonly string[],\n patch: {\n replace?: readonly string[]\n delete?: readonly string[]\n append?: readonly string[]\n },\n): string[] {\n const deleted = new Set(patch.delete ?? [])\n return uniqueStrings([\n ...(patch.replace ?? current).filter((value) => !deleted.has(value)),\n ...(patch.append ?? []),\n ])\n}\n\nfunction suggestionDeleteKey(suggestion: AiAgentSuggestion): string[] {\n return [suggestion.label, suggestion.prompt].filter((value) => value.length > 0)\n}\n\nfunction applySuggestionPatch(\n current: readonly AiAgentSuggestion[],\n patch: {\n replace?: readonly AiAgentSuggestion[]\n delete?: readonly string[]\n append?: readonly AiAgentSuggestion[]\n },\n): AiAgentSuggestion[] {\n const deleted = new Set(patch.delete ?? [])\n const base = patch.replace ?? current\n const out: AiAgentSuggestion[] = []\n const seen = new Set<string>()\n for (const suggestion of base) {\n if (suggestionDeleteKey(suggestion).some((key) => deleted.has(key))) continue\n const key = `${suggestion.label}\\n${suggestion.prompt}`\n if (seen.has(key)) continue\n seen.add(key)\n out.push(suggestion)\n }\n for (const suggestion of patch.append ?? []) {\n const key = `${suggestion.label}\\n${suggestion.prompt}`\n if (seen.has(key)) continue\n seen.add(key)\n out.push(suggestion)\n }\n return out\n}\n\nfunction validateAndNormalizeAgent(candidate: AiAgentDefinition): AiAgentDefinition {\n const taskPlanNormalized = normalizeTaskPlanTool(candidate)\n const rawProvider = candidate.defaultProvider\n if (typeof rawProvider !== 'string' || rawProvider.trim().length === 0) {\n return taskPlanNormalized\n }\n const providerHint = rawProvider.trim()\n const registered = llmProviderRegistry.get(providerHint)\n if (!registered) {\n console.warn(\n `[AI Agents] Agent \"${candidate.id}\" declares defaultProvider \"${providerHint}\" which is not registered in llmProviderRegistry. ` +\n `The agent will be registered with defaultProvider: undefined so the resolution chain still works. ` +\n `Built-in provider ids: anthropic, google, openai, deepinfra, groq, together, fireworks, azure, litellm, ollama.`,\n )\n return { ...taskPlanNormalized, defaultProvider: undefined }\n }\n return taskPlanNormalized\n}\n\nfunction populateFromAgents(agents: unknown[]): void {\n for (const candidate of agents) {\n if (!isAiAgentDefinition(candidate)) {\n console.warn('[AI Agents] Skipping malformed agent entry in ai-agents.generated.ts')\n continue\n }\n const existing = agentsById.get(candidate.id)\n if (existing) {\n throw new Error(\n `[AI Agents] Duplicate agent id \"${candidate.id}\" \u2014 already registered by module \"${existing.moduleId}\", conflicts with module \"${candidate.moduleId}\". Export \\`aiAgentOverrides\\` from your module's \\`ai-agents.ts\\` (or set it on the modules.ts entry) to replace an agent across modules.`\n )\n }\n agentsById.set(candidate.id, validateAndNormalizeAgent(candidate))\n }\n}\n\nasync function loadOverrideEntries(): Promise<AiAgentOverrideConfigEntry[]> {\n try {\n const mod = (await import(\n '@/.mercato/generated/ai-agents.generated'\n )) as { aiAgentOverrideEntries?: unknown[] }\n return Array.isArray(mod.aiAgentOverrideEntries)\n ? (mod.aiAgentOverrideEntries as AiAgentOverrideConfigEntry[])\n : []\n } catch {\n // No generated file yet \u2014 pre-generate builds and tests fall through.\n return []\n }\n}\n\nfunction applyOverridesToRegistry(entries: readonly AiAgentOverrideConfigEntry[]): void {\n const overrideMap = composeAgentOverrideMap(entries)\n if (Object.keys(overrideMap).length === 0) return\n const overridden = applyAgentOverrideMap(Array.from(agentsById.values()), overrideMap)\n agentsById.clear()\n for (const agent of overridden) agentsById.set(agent.id, agent)\n for (const [id, value] of Object.entries(overrideMap)) {\n const verb = value === null ? 'disabled' : 'replaced'\n console.info(`[AI Overrides] Agent \"${id}\" ${verb} by override.`)\n }\n}\n\nasync function loadExtensionEntries(): Promise<AiAgentExtension[]> {\n try {\n const mod = (await import(\n '@/.mercato/generated/ai-agents.generated'\n )) as { aiAgentExtensionEntries?: unknown[] }\n const entries = Array.isArray(mod.aiAgentExtensionEntries)\n ? (mod.aiAgentExtensionEntries as AiAgentExtensionConfigEntry[])\n : []\n return composeAgentExtensionEntries(entries).filter(isAiAgentExtension)\n } catch {\n return []\n }\n}\n\nfunction applyExtensionsToRegistry(extensions: readonly AiAgentExtension[]): void {\n if (extensions.length === 0) return\n for (const extension of extensions) {\n const agent = agentsById.get(extension.targetAgentId)\n if (!agent) {\n console.warn(\n `[AI Agents] Skipping extension for unknown agent \"${extension.targetAgentId}\".`,\n )\n continue\n }\n\n const replacementSystemPrompt = extension.replaceSystemPrompt?.trim()\n const appendSystemPrompt = extension.appendSystemPrompt?.trim()\n const systemPrompt = replacementSystemPrompt ?? agent.systemPrompt.trim()\n const patchedAgent: AiAgentDefinition = {\n ...agent,\n allowedTools: applyStringListPatch(agent.allowedTools, {\n replace: extension.replaceAllowedTools,\n delete: extension.deleteAllowedTools,\n append: extension.appendAllowedTools,\n }),\n taskPlan: extension.taskPlan !== undefined ? extension.taskPlan : agent.taskPlan,\n systemPrompt: appendSystemPrompt\n ? `${systemPrompt}\\n\\n${appendSystemPrompt}`\n : systemPrompt,\n suggestions: applySuggestionPatch(agent.suggestions ?? [], {\n replace: extension.replaceSuggestions,\n delete: extension.deleteSuggestions,\n append: [\n ...(extension.appendSuggestions ?? []),\n ...(extension.suggestions ?? []),\n ],\n }),\n }\n agentsById.set(agent.id, validateAndNormalizeAgent(patchedAgent))\n }\n}\n\nexport async function loadAgentRegistry(): Promise<void> {\n if (loaded) return\n try {\n const mod = (await import(\n '@/.mercato/generated/ai-agents.generated'\n )) as { allAiAgents?: unknown[] }\n const agents = Array.isArray(mod.allAiAgents) ? mod.allAiAgents : []\n populateFromAgents(agents)\n } catch (error) {\n console.error(\n '[AI Agents] Could not load ai-agents.generated.ts (agent registry empty):',\n error\n )\n } finally {\n try {\n const overrideEntries = await loadOverrideEntries()\n applyOverridesToRegistry(overrideEntries)\n const extensionEntries = await loadExtensionEntries()\n applyExtensionsToRegistry(extensionEntries)\n } catch (error) {\n console.error('[AI Agents] Failed to apply agent overrides/extensions:', error)\n }\n loaded = true\n }\n}\n\nexport function getAgent(id: string): AiAgentDefinition | undefined {\n return agentsById.get(id)\n}\n\nexport function listAgents(): AiAgentDefinition[] {\n return Array.from(agentsById.values()).sort((a, b) => a.id.localeCompare(b.id))\n}\n\nexport function listAgentsByModule(moduleId: string): AiAgentDefinition[] {\n return listAgents().filter((agent) => agent.moduleId === moduleId)\n}\n\n/**\n * @__internal\n * Test-only hook \u2014 clears the cached registry so `loadAgentRegistry` re-evaluates its source.\n */\nexport function resetAgentRegistryForTests(): void {\n agentsById.clear()\n loaded = false\n}\n\n/**\n * @__internal\n * Test-only hook \u2014 seeds the registry directly from a fixture array without going through\n * the dynamic generated-file import. Used by the registry's own unit tests.\n */\nexport function seedAgentRegistryForTests(agents: unknown[]): void {\n agentsById.clear()\n populateFromAgents(agents)\n loaded = true\n}\n\n/**\n * @__internal\n * Test-only hook \u2014 apply override entries against the seeded registry to\n * exercise the override pipeline without round-tripping through the\n * generated file.\n */\nexport function applyAgentOverrideEntriesForTests(\n entries: readonly AiAgentOverrideConfigEntry[],\n): void {\n applyOverridesToRegistry(entries)\n}\n\n/**\n * @__internal Test-only hook \u2014 apply additive extension entries against the\n * seeded registry without round-tripping through the generated file.\n */\nexport function applyAgentExtensionEntriesForTests(\n entries: readonly AiAgentExtension[],\n): void {\n applyExtensionsToRegistry(entries)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["key"]
|
|
7
7
|
}
|
|
@@ -28,8 +28,11 @@ import { AiAgentMutationPolicyOverrideRepository } from "../data/repositories/Ai
|
|
|
28
28
|
import { AiAgentRuntimeOverrideRepository } from "../data/repositories/AiAgentRuntimeOverrideRepository.js";
|
|
29
29
|
import { AiTenantModelAllowlistRepository } from "../data/repositories/AiTenantModelAllowlistRepository.js";
|
|
30
30
|
import { composeSystemPromptWithOverride } from "./prompt-override-merge.js";
|
|
31
|
+
import { isAgentTaskPlanEnabled } from "./agent-registry.js";
|
|
31
32
|
import { isKnownMutationPolicy } from "./agent-policy.js";
|
|
32
33
|
import { recordTokenUsage } from "./token-usage-recorder.js";
|
|
34
|
+
import { injectTaskPlanIntoStream } from "./task-plan-stream.js";
|
|
35
|
+
import { TASK_PLAN_RUNTIME_PROMPT_SECTION } from "./task-plan-labels.js";
|
|
33
36
|
import "./llm-bootstrap.js";
|
|
34
37
|
const WRAPPER_DEFAULT_LOOP_CHAT = { maxSteps: 10 };
|
|
35
38
|
const WRAPPER_DEFAULT_LOOP_OBJECT = {};
|
|
@@ -708,6 +711,12 @@ function appendRuntimeMutationPolicy(systemPrompt, agent, mutationPolicyOverride
|
|
|
708
711
|
|
|
709
712
|
${block}`;
|
|
710
713
|
}
|
|
714
|
+
function appendRuntimeTaskPlanPrompt(systemPrompt, agent) {
|
|
715
|
+
if (!isAgentTaskPlanEnabled(agent)) return systemPrompt;
|
|
716
|
+
return `${systemPrompt}
|
|
717
|
+
|
|
718
|
+
${TASK_PLAN_RUNTIME_PROMPT_SECTION}`;
|
|
719
|
+
}
|
|
711
720
|
async function runAiAgentText(input) {
|
|
712
721
|
const [mutationPolicyOverride, tenantRuntimeOverride, tenantAllowlistSnapshot] = await Promise.all([
|
|
713
722
|
resolveMutationPolicyOverride(
|
|
@@ -752,7 +761,7 @@ async function runAiAgentText(input) {
|
|
|
752
761
|
input.authContext.organizationId
|
|
753
762
|
);
|
|
754
763
|
const systemPrompt = appendRuntimeMutationPolicy(
|
|
755
|
-
appendAttachmentSummary(baseSystemPrompt, resolvedAttachments),
|
|
764
|
+
appendRuntimeTaskPlanPrompt(appendAttachmentSummary(baseSystemPrompt, resolvedAttachments), agent),
|
|
756
765
|
agent,
|
|
757
766
|
mutationPolicyOverride
|
|
758
767
|
);
|
|
@@ -851,6 +860,7 @@ async function runAiAgentText(input) {
|
|
|
851
860
|
finalizeLoopTrace: () => loopTraceCollector.finalize(budgetEnforcer.abortReason),
|
|
852
861
|
...builtToolLoopAgent !== void 0 ? { toolLoopAgent: builtToolLoopAgent } : {}
|
|
853
862
|
};
|
|
863
|
+
const taskPlanId = `turn_${turnId}`;
|
|
854
864
|
if (input.generateText) {
|
|
855
865
|
try {
|
|
856
866
|
const callbackResult = await input.generateText(preparedOptions);
|
|
@@ -861,10 +871,11 @@ async function runAiAgentText(input) {
|
|
|
861
871
|
Connection: "keep-alive"
|
|
862
872
|
}
|
|
863
873
|
});
|
|
874
|
+
const withTaskPlan2 = injectTaskPlanIntoStream(baseResponse2, taskPlanId);
|
|
864
875
|
if (input.emitLoopTrace) {
|
|
865
|
-
return appendLoopFinishToStream(
|
|
876
|
+
return appendLoopFinishToStream(withTaskPlan2, preparedOptions.finalizeLoopTrace);
|
|
866
877
|
}
|
|
867
|
-
return
|
|
878
|
+
return withTaskPlan2;
|
|
868
879
|
} finally {
|
|
869
880
|
if (wallClockTimer !== void 0) clearTimeout(wallClockTimer);
|
|
870
881
|
}
|
|
@@ -886,10 +897,11 @@ async function runAiAgentText(input) {
|
|
|
886
897
|
Connection: "keep-alive"
|
|
887
898
|
}
|
|
888
899
|
});
|
|
900
|
+
const withTaskPlan2 = injectTaskPlanIntoStream(baseResponse2, taskPlanId);
|
|
889
901
|
if (input.emitLoopTrace) {
|
|
890
|
-
return appendLoopFinishToStream(
|
|
902
|
+
return appendLoopFinishToStream(withTaskPlan2, preparedOptions.finalizeLoopTrace);
|
|
891
903
|
}
|
|
892
|
-
return
|
|
904
|
+
return withTaskPlan2;
|
|
893
905
|
}
|
|
894
906
|
const result = streamText({
|
|
895
907
|
model,
|
|
@@ -918,10 +930,11 @@ async function runAiAgentText(input) {
|
|
|
918
930
|
Connection: "keep-alive"
|
|
919
931
|
}
|
|
920
932
|
});
|
|
933
|
+
const withTaskPlan = injectTaskPlanIntoStream(baseResponse, taskPlanId);
|
|
921
934
|
if (input.emitLoopTrace) {
|
|
922
|
-
return appendLoopFinishToStream(
|
|
935
|
+
return appendLoopFinishToStream(withTaskPlan, preparedOptions.finalizeLoopTrace);
|
|
923
936
|
}
|
|
924
|
-
return
|
|
937
|
+
return withTaskPlan;
|
|
925
938
|
}
|
|
926
939
|
function normalizeObjectMessages(input) {
|
|
927
940
|
if (typeof input === "string") {
|
|
@@ -1000,7 +1013,7 @@ async function runAiAgentObject(input) {
|
|
|
1000
1013
|
input.authContext.organizationId
|
|
1001
1014
|
);
|
|
1002
1015
|
const systemPrompt = appendRuntimeMutationPolicy(
|
|
1003
|
-
appendAttachmentSummary(baseSystemPrompt, resolvedAttachments),
|
|
1016
|
+
appendRuntimeTaskPlanPrompt(appendAttachmentSummary(baseSystemPrompt, resolvedAttachments), agent),
|
|
1004
1017
|
agent,
|
|
1005
1018
|
mutationPolicyOverride
|
|
1006
1019
|
);
|