@agent-native/core 0.7.12 → 0.7.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/README.md +1 -1
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +26 -8
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/builder-engine.d.ts +19 -0
- package/dist/agent/engine/builder-engine.d.ts.map +1 -0
- package/dist/agent/engine/builder-engine.js +430 -0
- package/dist/agent/engine/builder-engine.js.map +1 -0
- package/dist/agent/engine/builtin.d.ts.map +1 -1
- package/dist/agent/engine/builtin.js +26 -10
- package/dist/agent/engine/builtin.js.map +1 -1
- package/dist/agent/engine/index.d.ts +1 -1
- package/dist/agent/engine/index.d.ts.map +1 -1
- package/dist/agent/engine/index.js +1 -1
- package/dist/agent/engine/index.js.map +1 -1
- package/dist/agent/engine/registry.d.ts +20 -1
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +49 -1
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/engine/types.d.ts +30 -0
- package/dist/agent/engine/types.d.ts.map +1 -1
- package/dist/agent/engine/types.js +19 -1
- package/dist/agent/engine/types.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +65 -7
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +11 -1
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts +4 -0
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +1 -0
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/agent/types.d.ts +8 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/checkpoints/service.d.ts +1 -0
- package/dist/checkpoints/service.d.ts.map +1 -1
- package/dist/checkpoints/service.js +26 -2
- package/dist/checkpoints/service.js.map +1 -1
- package/dist/cli/create.d.ts +30 -0
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +25 -13
- package/dist/cli/create.js.map +1 -1
- package/dist/client/AgentPanel.js +1 -1
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +49 -10
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ConnectBuilderCard.d.ts +1 -7
- package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
- package/dist/client/ConnectBuilderCard.js +30 -132
- package/dist/client/ConnectBuilderCard.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +30 -9
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/analytics.d.ts +5 -8
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +53 -11
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/builder-mark.d.ts +9 -0
- package/dist/client/builder-mark.d.ts.map +1 -0
- package/dist/client/builder-mark.js +10 -0
- package/dist/client/builder-mark.js.map +1 -0
- package/dist/client/components/ui/popover.d.ts +8 -0
- package/dist/client/components/ui/popover.d.ts.map +1 -0
- package/dist/client/components/ui/popover.js +11 -0
- package/dist/client/components/ui/popover.js.map +1 -0
- package/dist/client/composer/ComposerPlusMenu.d.ts +2 -0
- package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -0
- package/dist/client/composer/ComposerPlusMenu.js +244 -0
- package/dist/client/composer/ComposerPlusMenu.js.map +1 -0
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +9 -5
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
- package/dist/client/composer/useVoiceDictation.js +4 -2
- package/dist/client/composer/useVoiceDictation.js.map +1 -1
- package/dist/client/error-format.d.ts +2 -0
- package/dist/client/error-format.d.ts.map +1 -0
- package/dist/client/error-format.js +31 -0
- package/dist/client/error-format.js.map +1 -0
- package/dist/client/index.d.ts +3 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/observability/ObservabilityDashboard.d.ts +5 -0
- package/dist/client/observability/ObservabilityDashboard.d.ts.map +1 -0
- package/dist/client/observability/ObservabilityDashboard.js +169 -0
- package/dist/client/observability/ObservabilityDashboard.js.map +1 -0
- package/dist/client/observability/ThumbsFeedback.d.ts +8 -0
- package/dist/client/observability/ThumbsFeedback.d.ts.map +1 -0
- package/dist/client/observability/ThumbsFeedback.js +64 -0
- package/dist/client/observability/ThumbsFeedback.js.map +1 -0
- package/dist/client/observability/index.d.ts +4 -0
- package/dist/client/observability/index.d.ts.map +1 -0
- package/dist/client/observability/index.js +4 -0
- package/dist/client/observability/index.js.map +1 -0
- package/dist/client/observability/useObservability.d.ts +128 -0
- package/dist/client/observability/useObservability.d.ts.map +1 -0
- package/dist/client/observability/useObservability.js +109 -0
- package/dist/client/observability/useObservability.js.map +1 -0
- package/dist/client/onboarding/OnboardingPanel.d.ts.map +1 -1
- package/dist/client/onboarding/OnboardingPanel.js +34 -92
- package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
- package/dist/client/org/RequireActiveOrg.d.ts +33 -0
- package/dist/client/org/RequireActiveOrg.d.ts.map +1 -0
- package/dist/client/org/RequireActiveOrg.js +63 -0
- package/dist/client/org/RequireActiveOrg.js.map +1 -0
- package/dist/client/org/hooks.d.ts.map +1 -1
- package/dist/client/org/hooks.js +50 -15
- package/dist/client/org/hooks.js.map +1 -1
- package/dist/client/org/index.d.ts +1 -0
- package/dist/client/org/index.d.ts.map +1 -1
- package/dist/client/org/index.js +1 -0
- package/dist/client/org/index.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +3 -3
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/settings/AutomationsSection.js +1 -1
- package/dist/client/settings/AutomationsSection.js.map +1 -1
- package/dist/client/settings/BrowserSection.js +1 -1
- package/dist/client/settings/BrowserSection.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +112 -12
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.js +10 -4
- package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +26 -0
- package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/client/settings/useBuilderStatus.js +128 -4
- package/dist/client/settings/useBuilderStatus.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +2 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +6 -2
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/transcription/BuilderTranscriptionCta.d.ts +9 -0
- package/dist/client/transcription/BuilderTranscriptionCta.d.ts.map +1 -0
- package/dist/client/transcription/BuilderTranscriptionCta.js +18 -0
- package/dist/client/transcription/BuilderTranscriptionCta.js.map +1 -0
- package/dist/client/transcription/use-live-transcription.d.ts +29 -0
- package/dist/client/transcription/use-live-transcription.d.ts.map +1 -0
- package/dist/client/transcription/use-live-transcription.js +156 -0
- package/dist/client/transcription/use-live-transcription.js.map +1 -0
- package/dist/client/use-builder-enabled.d.ts +17 -0
- package/dist/client/use-builder-enabled.d.ts.map +1 -0
- package/dist/client/use-builder-enabled.js +36 -0
- package/dist/client/use-builder-enabled.js.map +1 -0
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +4 -2
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/client/useProductionAgent.d.ts.map +1 -1
- package/dist/client/useProductionAgent.js +3 -1
- package/dist/client/useProductionAgent.js.map +1 -1
- package/dist/db/migrations.d.ts +9 -0
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +75 -10
- package/dist/db/migrations.js.map +1 -1
- package/dist/file-upload/builder.d.ts.map +1 -1
- package/dist/file-upload/builder.js +11 -4
- package/dist/file-upload/builder.js.map +1 -1
- package/dist/jobs/tools.d.ts.map +1 -1
- package/dist/jobs/tools.js +137 -161
- package/dist/jobs/tools.js.map +1 -1
- package/dist/notifications/actions.d.ts +2 -2
- package/dist/notifications/actions.d.ts.map +1 -1
- package/dist/notifications/actions.js +77 -69
- package/dist/notifications/actions.js.map +1 -1
- package/dist/observability/evals.d.ts +22 -0
- package/dist/observability/evals.d.ts.map +1 -0
- package/dist/observability/evals.js +371 -0
- package/dist/observability/evals.js.map +1 -0
- package/dist/observability/experiments.d.ts +24 -0
- package/dist/observability/experiments.d.ts.map +1 -0
- package/dist/observability/experiments.js +274 -0
- package/dist/observability/experiments.js.map +1 -0
- package/dist/observability/feedback.d.ts +14 -0
- package/dist/observability/feedback.d.ts.map +1 -0
- package/dist/observability/feedback.js +256 -0
- package/dist/observability/feedback.js.map +1 -0
- package/dist/observability/index.d.ts +6 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +5 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/plugin.d.ts +2 -0
- package/dist/observability/plugin.d.ts.map +1 -0
- package/dist/observability/plugin.js +12 -0
- package/dist/observability/plugin.js.map +1 -0
- package/dist/observability/routes.d.ts +68 -0
- package/dist/observability/routes.d.ts.map +1 -0
- package/dist/observability/routes.js +301 -0
- package/dist/observability/routes.js.map +1 -0
- package/dist/observability/store.d.ts +77 -0
- package/dist/observability/store.d.ts.map +1 -0
- package/dist/observability/store.js +976 -0
- package/dist/observability/store.js.map +1 -0
- package/dist/observability/traces.d.ts +37 -0
- package/dist/observability/traces.d.ts.map +1 -0
- package/dist/observability/traces.js +182 -0
- package/dist/observability/traces.js.map +1 -0
- package/dist/observability/types.d.ts +159 -0
- package/dist/observability/types.d.ts.map +1 -0
- package/dist/observability/types.js +16 -0
- package/dist/observability/types.js.map +1 -0
- package/dist/onboarding/default-steps.d.ts.map +1 -1
- package/dist/onboarding/default-steps.js +6 -5
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/onboarding/types.d.ts +10 -1
- package/dist/onboarding/types.d.ts.map +1 -1
- package/dist/org/context.d.ts +8 -1
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/context.js +163 -6
- package/dist/org/context.js.map +1 -1
- package/dist/org/handlers.d.ts.map +1 -1
- package/dist/org/handlers.js +49 -30
- package/dist/org/handlers.js.map +1 -1
- package/dist/progress/actions.d.ts +3 -0
- package/dist/progress/actions.d.ts.map +1 -1
- package/dist/progress/actions.js +86 -110
- package/dist/progress/actions.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/progress/routes.js +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/scripts/agent-engines/manage-agent-engine.d.ts +10 -0
- package/dist/scripts/agent-engines/manage-agent-engine.d.ts.map +1 -0
- package/dist/scripts/agent-engines/manage-agent-engine.js +47 -0
- package/dist/scripts/agent-engines/manage-agent-engine.js.map +1 -0
- package/dist/scripts/agent-engines/set-agent-engine.js +2 -2
- package/dist/scripts/agent-engines/set-agent-engine.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +39 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +707 -443
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-teams.js +1 -1
- package/dist/server/agent-teams.js.map +1 -1
- package/dist/server/analytics.d.ts +5 -6
- package/dist/server/analytics.d.ts.map +1 -1
- package/dist/server/analytics.js +6 -14
- package/dist/server/analytics.js.map +1 -1
- package/dist/server/app-name.d.ts +5 -2
- package/dist/server/app-name.d.ts.map +1 -1
- package/dist/server/app-name.js +14 -3
- package/dist/server/app-name.js.map +1 -1
- package/dist/server/app-url.d.ts.map +1 -1
- package/dist/server/app-url.js +10 -1
- package/dist/server/app-url.js.map +1 -1
- package/dist/server/auth.d.ts +2 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +153 -2
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts +2 -0
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +4 -0
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/builder-browser.d.ts +59 -1
- package/dist/server/builder-browser.d.ts.map +1 -1
- package/dist/server/builder-browser.js +127 -11
- package/dist/server/builder-browser.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +208 -6
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/credential-provider.d.ts +7 -0
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +10 -0
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +29 -4
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +46 -5
- package/dist/server/poll.js.map +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +2 -1
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts.map +1 -1
- package/dist/server/transcribe-voice.js +44 -5
- package/dist/server/transcribe-voice.js.map +1 -1
- package/dist/styles/agent-native.css +11 -2
- package/dist/templates/default/.agents/skills/progress/SKILL.md +14 -12
- package/dist/templates/default/app/root.tsx +7 -0
- package/dist/transcription/builder-transcription.d.ts +27 -0
- package/dist/transcription/builder-transcription.d.ts.map +1 -0
- package/dist/transcription/builder-transcription.js +41 -0
- package/dist/transcription/builder-transcription.js.map +1 -0
- package/dist/triggers/actions.d.ts +3 -0
- package/dist/triggers/actions.d.ts.map +1 -1
- package/dist/triggers/actions.js +189 -213
- package/dist/triggers/actions.js.map +1 -1
- package/docs/content/agent-mentions.md +1 -1
- package/docs/content/automations.md +22 -19
- package/docs/content/cloneable-saas.md +2 -2
- package/docs/content/deployment.md +21 -61
- package/docs/content/getting-started.md +1 -1
- package/docs/content/key-concepts.md +1 -1
- package/docs/content/{enterprise-workspace.md → multi-app-workspace.md} +3 -3
- package/docs/content/multi-tenancy.md +1 -1
- package/docs/content/progress.md +11 -11
- package/docs/content/template-dispatch.md +3 -3
- package/docs/content/workspace-management.md +1 -1
- package/package.json +9 -2
- package/src/templates/default/.agents/skills/progress/SKILL.md +14 -12
- package/src/templates/default/app/root.tsx +7 -0
|
@@ -14,7 +14,7 @@ import { createThread, getThread, listThreads, searchThreads, updateThreadData,
|
|
|
14
14
|
import { resourceListAccessible, resourceList, resourceGet, resourceGetByPath, ensurePersonalDefaults, SHARED_OWNER, } from "../resources/store.js";
|
|
15
15
|
import nodePath from "node:path";
|
|
16
16
|
import { readBody } from "./h3-helpers.js";
|
|
17
|
-
import { getBuilderBrowserConnectUrl
|
|
17
|
+
import { getBuilderBrowserConnectUrl } from "./builder-browser.js";
|
|
18
18
|
// Lazy fs — loaded via dynamic import() on first use.
|
|
19
19
|
// This avoids require() which bundlers convert to createRequire(import.meta.url)
|
|
20
20
|
// that crashes on CF Workers where import.meta.url is undefined.
|
|
@@ -74,6 +74,44 @@ function wrapCliScript(tool, cliDefault, opts) {
|
|
|
74
74
|
},
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Creates the `get-framework-context` tool. Returns detailed instructions
|
|
79
|
+
* for framework capabilities that are summarized in the compact prompt.
|
|
80
|
+
* The agent calls this on-demand when it needs specifics about embeds,
|
|
81
|
+
* agent teams, recurring jobs, etc.
|
|
82
|
+
*/
|
|
83
|
+
function createFrameworkContextEntry() {
|
|
84
|
+
const topicList = Object.keys(FRAMEWORK_CONTEXT_SECTIONS).join(", ");
|
|
85
|
+
return {
|
|
86
|
+
"get-framework-context": {
|
|
87
|
+
tool: {
|
|
88
|
+
description: `Read detailed framework instructions for a specific capability. Available topics: ${topicList}. Call with topic="all" to get everything.`,
|
|
89
|
+
parameters: {
|
|
90
|
+
type: "object",
|
|
91
|
+
properties: {
|
|
92
|
+
topic: {
|
|
93
|
+
type: "string",
|
|
94
|
+
description: `Topic to read. One of: ${topicList}, or "all" for everything.`,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
required: ["topic"],
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
run: async (args) => {
|
|
101
|
+
const topic = String(args.topic ?? "all").toLowerCase();
|
|
102
|
+
if (topic === "all") {
|
|
103
|
+
return Object.values(FRAMEWORK_CONTEXT_SECTIONS).join("\n\n");
|
|
104
|
+
}
|
|
105
|
+
const section = FRAMEWORK_CONTEXT_SECTIONS[topic];
|
|
106
|
+
if (!section) {
|
|
107
|
+
return `Unknown topic "${topic}". Available: ${topicList}`;
|
|
108
|
+
}
|
|
109
|
+
return section;
|
|
110
|
+
},
|
|
111
|
+
readOnly: true,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
77
115
|
/**
|
|
78
116
|
* Creates the `refresh-screen` tool. Writes a bump to `application_state`
|
|
79
117
|
* under a well-known key; the client's `useDbSync` watches for this and
|
|
@@ -370,91 +408,87 @@ async function createResourceScriptEntries() {
|
|
|
370
408
|
import("../scripts/resources/save-memory.js"),
|
|
371
409
|
import("../scripts/resources/delete-memory.js"),
|
|
372
410
|
]);
|
|
411
|
+
// Wrap each CLI runner so it captures stdout and converts args properly
|
|
412
|
+
const listEntry = wrapCliScript({
|
|
413
|
+
description: "",
|
|
414
|
+
parameters: { type: "object", properties: {} },
|
|
415
|
+
}, list.default, { readOnly: true });
|
|
416
|
+
const readEntry = wrapCliScript({
|
|
417
|
+
description: "",
|
|
418
|
+
parameters: { type: "object", properties: {} },
|
|
419
|
+
}, read.default, { readOnly: true });
|
|
420
|
+
const writeEntry = wrapCliScript({
|
|
421
|
+
description: "",
|
|
422
|
+
parameters: { type: "object", properties: {} },
|
|
423
|
+
}, write.default);
|
|
424
|
+
const deleteEntry = wrapCliScript({
|
|
425
|
+
description: "",
|
|
426
|
+
parameters: { type: "object", properties: {} },
|
|
427
|
+
}, del.default);
|
|
373
428
|
return {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
required: ["path"],
|
|
412
|
-
},
|
|
413
|
-
}, read.default),
|
|
414
|
-
"resource-write": wrapCliScript({
|
|
415
|
-
description: "Write or update a resource. Creates the resource if it doesn't exist.",
|
|
416
|
-
parameters: {
|
|
417
|
-
type: "object",
|
|
418
|
-
properties: {
|
|
419
|
-
path: {
|
|
420
|
-
type: "string",
|
|
421
|
-
description: "Resource path (e.g. 'LEARNINGS.md', 'notes/ideas.md')",
|
|
422
|
-
},
|
|
423
|
-
content: {
|
|
424
|
-
type: "string",
|
|
425
|
-
description: "The content to write",
|
|
426
|
-
},
|
|
427
|
-
scope: {
|
|
428
|
-
type: "string",
|
|
429
|
-
description: "personal or shared (default: personal)",
|
|
430
|
-
enum: ["personal", "shared"],
|
|
431
|
-
},
|
|
432
|
-
mime: {
|
|
433
|
-
type: "string",
|
|
434
|
-
description: "MIME type (default: inferred from extension)",
|
|
429
|
+
resources: {
|
|
430
|
+
tool: {
|
|
431
|
+
description: 'Manage persistent user files and notes. Actions: "list" (browse), "read" (get contents), "write" (create/update), "delete" (remove).',
|
|
432
|
+
parameters: {
|
|
433
|
+
type: "object",
|
|
434
|
+
properties: {
|
|
435
|
+
action: {
|
|
436
|
+
type: "string",
|
|
437
|
+
description: "The operation to perform",
|
|
438
|
+
enum: ["list", "read", "write", "delete"],
|
|
439
|
+
},
|
|
440
|
+
path: {
|
|
441
|
+
type: "string",
|
|
442
|
+
description: "Resource path (e.g. 'LEARNINGS.md', 'notes/ideas.md'). Required for read/write/delete.",
|
|
443
|
+
},
|
|
444
|
+
content: {
|
|
445
|
+
type: "string",
|
|
446
|
+
description: "Content to write. Required for write.",
|
|
447
|
+
},
|
|
448
|
+
scope: {
|
|
449
|
+
type: "string",
|
|
450
|
+
description: "personal, shared, or all (default varies by action)",
|
|
451
|
+
enum: ["personal", "shared", "all"],
|
|
452
|
+
},
|
|
453
|
+
prefix: {
|
|
454
|
+
type: "string",
|
|
455
|
+
description: "Filter by path prefix when listing (e.g. 'notes/')",
|
|
456
|
+
},
|
|
457
|
+
mime: {
|
|
458
|
+
type: "string",
|
|
459
|
+
description: "MIME type for write (default: inferred from extension)",
|
|
460
|
+
},
|
|
461
|
+
format: {
|
|
462
|
+
type: "string",
|
|
463
|
+
description: 'Output format for list: "json" or "text" (default: text)',
|
|
464
|
+
enum: ["json", "text"],
|
|
465
|
+
},
|
|
435
466
|
},
|
|
467
|
+
required: ["action"],
|
|
436
468
|
},
|
|
437
|
-
required: ["path", "content"],
|
|
438
469
|
},
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
470
|
+
run: async (args) => {
|
|
471
|
+
const { action: a, ...rest } = args;
|
|
472
|
+
if (a === "list")
|
|
473
|
+
return listEntry.run(rest);
|
|
474
|
+
if (a === "read") {
|
|
475
|
+
if (!rest.path)
|
|
476
|
+
return "Error: path is required for read";
|
|
477
|
+
return readEntry.run(rest);
|
|
478
|
+
}
|
|
479
|
+
if (a === "write") {
|
|
480
|
+
if (!rest.path || !rest.content)
|
|
481
|
+
return "Error: path and content are required for write";
|
|
482
|
+
return writeEntry.run(rest);
|
|
483
|
+
}
|
|
484
|
+
if (a === "delete") {
|
|
485
|
+
if (!rest.path)
|
|
486
|
+
return "Error: path is required for delete";
|
|
487
|
+
return deleteEntry.run(rest);
|
|
488
|
+
}
|
|
489
|
+
return `Error: unknown action "${a}". Use: list, read, write, delete`;
|
|
456
490
|
},
|
|
457
|
-
},
|
|
491
|
+
},
|
|
458
492
|
"save-memory": wrapCliScript({
|
|
459
493
|
description: "Save a memory for future conversations. Creates or updates a memory file and its index entry. Use proactively when you learn preferences, corrections, project context, or references.",
|
|
460
494
|
parameters: {
|
|
@@ -502,7 +536,7 @@ async function createResourceScriptEntries() {
|
|
|
502
536
|
}
|
|
503
537
|
}
|
|
504
538
|
/**
|
|
505
|
-
* Creates chat
|
|
539
|
+
* Creates a unified chat-history ActionEntry that dispatches to search or open.
|
|
506
540
|
*/
|
|
507
541
|
async function createChatScriptEntries() {
|
|
508
542
|
try {
|
|
@@ -510,41 +544,80 @@ async function createChatScriptEntries() {
|
|
|
510
544
|
import("../scripts/chat/search-chats.js"),
|
|
511
545
|
import("../scripts/chat/open-chat.js"),
|
|
512
546
|
]);
|
|
513
|
-
|
|
514
|
-
"
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
enum: ["json", "text"],
|
|
531
|
-
},
|
|
547
|
+
const searchEntry = wrapCliScript({
|
|
548
|
+
description: "Search or list past agent chat threads.",
|
|
549
|
+
parameters: {
|
|
550
|
+
type: "object",
|
|
551
|
+
properties: {
|
|
552
|
+
query: {
|
|
553
|
+
type: "string",
|
|
554
|
+
description: "Search term to find chats by title, preview, or content",
|
|
555
|
+
},
|
|
556
|
+
limit: {
|
|
557
|
+
type: "string",
|
|
558
|
+
description: "Max number of results (default: 20)",
|
|
559
|
+
},
|
|
560
|
+
format: {
|
|
561
|
+
type: "string",
|
|
562
|
+
description: "Output format",
|
|
563
|
+
enum: ["json", "text"],
|
|
532
564
|
},
|
|
533
565
|
},
|
|
534
|
-
},
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
566
|
+
},
|
|
567
|
+
}, searchMod.default);
|
|
568
|
+
const openEntry = wrapCliScript({
|
|
569
|
+
description: "Open a chat thread in the UI.",
|
|
570
|
+
parameters: {
|
|
571
|
+
type: "object",
|
|
572
|
+
properties: {
|
|
573
|
+
id: {
|
|
574
|
+
type: "string",
|
|
575
|
+
description: "The chat thread ID to open",
|
|
576
|
+
},
|
|
577
|
+
},
|
|
578
|
+
required: ["id"],
|
|
579
|
+
},
|
|
580
|
+
}, openMod.default);
|
|
581
|
+
return {
|
|
582
|
+
"chat-history": {
|
|
583
|
+
tool: {
|
|
584
|
+
description: "Manage past agent chat threads. Use action 'search' to find previous conversations by keyword, or 'open' to open a thread in the UI.",
|
|
585
|
+
parameters: {
|
|
586
|
+
type: "object",
|
|
587
|
+
properties: {
|
|
588
|
+
action: {
|
|
589
|
+
type: "string",
|
|
590
|
+
description: "The operation to perform",
|
|
591
|
+
enum: ["search", "open"],
|
|
592
|
+
},
|
|
593
|
+
query: {
|
|
594
|
+
type: "string",
|
|
595
|
+
description: "(search) Search term to find chats by title, preview, or content",
|
|
596
|
+
},
|
|
597
|
+
limit: {
|
|
598
|
+
type: "string",
|
|
599
|
+
description: "(search) Max number of results (default: 20)",
|
|
600
|
+
},
|
|
601
|
+
format: {
|
|
602
|
+
type: "string",
|
|
603
|
+
description: "(search) Output format",
|
|
604
|
+
enum: ["json", "text"],
|
|
605
|
+
},
|
|
606
|
+
id: {
|
|
607
|
+
type: "string",
|
|
608
|
+
description: "(open) The chat thread ID to open",
|
|
609
|
+
},
|
|
543
610
|
},
|
|
611
|
+
required: ["action"],
|
|
544
612
|
},
|
|
545
|
-
required: ["id"],
|
|
546
613
|
},
|
|
547
|
-
|
|
614
|
+
run: async (args) => {
|
|
615
|
+
if (args?.action === "open") {
|
|
616
|
+
return openEntry.run(args);
|
|
617
|
+
}
|
|
618
|
+
return searchEntry.run(args);
|
|
619
|
+
},
|
|
620
|
+
},
|
|
548
621
|
};
|
|
549
622
|
}
|
|
550
623
|
catch {
|
|
@@ -552,20 +625,14 @@ async function createChatScriptEntries() {
|
|
|
552
625
|
}
|
|
553
626
|
}
|
|
554
627
|
/**
|
|
555
|
-
* Creates agent
|
|
556
|
-
*
|
|
628
|
+
* Creates the consolidated manage-agent-engine tool (list / set / test).
|
|
629
|
+
* Let the agent inspect and configure the active LLM engine.
|
|
557
630
|
*/
|
|
558
631
|
async function createAgentEngineScriptEntries() {
|
|
559
632
|
try {
|
|
560
|
-
const
|
|
561
|
-
import("../scripts/agent-engines/list-agent-engines.js"),
|
|
562
|
-
import("../scripts/agent-engines/set-agent-engine.js"),
|
|
563
|
-
import("../scripts/agent-engines/test-agent-engine.js"),
|
|
564
|
-
]);
|
|
633
|
+
const mod = await import("../scripts/agent-engines/manage-agent-engine.js");
|
|
565
634
|
return {
|
|
566
|
-
"
|
|
567
|
-
"set-agent-engine": { tool: setMod.tool, run: setMod.run },
|
|
568
|
-
"test-agent-engine": { tool: testMod.tool, run: testMod.run },
|
|
635
|
+
"manage-agent-engine": { tool: mod.tool, run: mod.run },
|
|
569
636
|
};
|
|
570
637
|
}
|
|
571
638
|
catch {
|
|
@@ -611,270 +678,178 @@ function createBuilderBrowserTool(deps) {
|
|
|
611
678
|
return JSON.stringify({
|
|
612
679
|
kind: "connect-builder-card",
|
|
613
680
|
configured,
|
|
614
|
-
builderEnabled: !!process.env.ENABLE_BUILDER,
|
|
615
681
|
connectUrl: getBuilderBrowserConnectUrl(deps.getOrigin()),
|
|
616
682
|
orgName: process.env.BUILDER_ORG_NAME || null,
|
|
617
683
|
prompt,
|
|
618
684
|
});
|
|
619
685
|
},
|
|
620
686
|
},
|
|
621
|
-
"get-browser-connection": {
|
|
622
|
-
tool: {
|
|
623
|
-
description: "Provision a Builder-backed browser session and return browser websocket connection details. If Builder browser access is not configured yet, this returns setup guidance instead.",
|
|
624
|
-
parameters: {
|
|
625
|
-
type: "object",
|
|
626
|
-
properties: {
|
|
627
|
-
sessionId: {
|
|
628
|
-
type: "string",
|
|
629
|
-
description: "Stable browser session identifier. Reuse it to reconnect to the same browser session.",
|
|
630
|
-
},
|
|
631
|
-
projectId: {
|
|
632
|
-
type: "string",
|
|
633
|
-
description: "Optional Builder project or space identifier to scope the session.",
|
|
634
|
-
},
|
|
635
|
-
branchName: {
|
|
636
|
-
type: "string",
|
|
637
|
-
description: "Optional branch name for Builder preview sessions.",
|
|
638
|
-
},
|
|
639
|
-
proxyOrigin: {
|
|
640
|
-
type: "string",
|
|
641
|
-
description: "Optional source origin to proxy from when browsing a local app.",
|
|
642
|
-
},
|
|
643
|
-
proxyDefaultOrigin: {
|
|
644
|
-
type: "string",
|
|
645
|
-
description: "Optional default origin that the browser should use for proxied requests.",
|
|
646
|
-
},
|
|
647
|
-
proxyDestination: {
|
|
648
|
-
type: "string",
|
|
649
|
-
description: "Optional destination origin for proxying local development traffic.",
|
|
650
|
-
},
|
|
651
|
-
},
|
|
652
|
-
required: ["sessionId"],
|
|
653
|
-
},
|
|
654
|
-
},
|
|
655
|
-
run: async (args) => {
|
|
656
|
-
if (!process.env.BUILDER_PRIVATE_KEY ||
|
|
657
|
-
!process.env.BUILDER_PUBLIC_KEY) {
|
|
658
|
-
return JSON.stringify({
|
|
659
|
-
configured: false,
|
|
660
|
-
message: "Builder browser access is not configured. Connect Builder from the workspace Resources panel before requesting a browser session.",
|
|
661
|
-
connectUrl: getBuilderBrowserConnectUrl(deps.getOrigin()),
|
|
662
|
-
});
|
|
663
|
-
}
|
|
664
|
-
const connection = await requestBuilderBrowserConnection({
|
|
665
|
-
sessionId: args.sessionId,
|
|
666
|
-
projectId: args.projectId,
|
|
667
|
-
branchName: args.branchName,
|
|
668
|
-
proxyOrigin: args.proxyOrigin,
|
|
669
|
-
proxyDefaultOrigin: args.proxyDefaultOrigin,
|
|
670
|
-
proxyDestination: args.proxyDestination,
|
|
671
|
-
});
|
|
672
|
-
return JSON.stringify({
|
|
673
|
-
configured: true,
|
|
674
|
-
sessionId: args.sessionId,
|
|
675
|
-
...connection,
|
|
676
|
-
});
|
|
677
|
-
},
|
|
678
|
-
},
|
|
679
687
|
};
|
|
680
688
|
}
|
|
681
689
|
/**
|
|
682
|
-
* Creates agent
|
|
683
|
-
*
|
|
690
|
+
* Creates the unified `agent-teams` tool that consolidates all sub-agent
|
|
691
|
+
* orchestration behind a single tool with an `action` parameter.
|
|
684
692
|
*/
|
|
685
693
|
function createTeamTools(deps) {
|
|
686
694
|
return {
|
|
687
|
-
"
|
|
695
|
+
"agent-teams": {
|
|
688
696
|
tool: {
|
|
689
|
-
description: "
|
|
697
|
+
description: "Manage sub-agent tasks. Use action 'spawn' to start a new sub-agent, 'status' to check progress, 'read-result' to get a finished task's output, 'send' to message a running sub-agent, or 'list' to see all tasks.",
|
|
690
698
|
parameters: {
|
|
691
699
|
type: "object",
|
|
692
700
|
properties: {
|
|
701
|
+
action: {
|
|
702
|
+
type: "string",
|
|
703
|
+
enum: ["spawn", "status", "read-result", "send", "list"],
|
|
704
|
+
description: "The operation to perform",
|
|
705
|
+
},
|
|
693
706
|
task: {
|
|
694
707
|
type: "string",
|
|
695
|
-
description: "Clear description of what the sub-agent should accomplish",
|
|
708
|
+
description: "(spawn) Clear description of what the sub-agent should accomplish",
|
|
696
709
|
},
|
|
697
710
|
instructions: {
|
|
698
711
|
type: "string",
|
|
699
|
-
description: "Optional additional instructions or context for the sub-agent",
|
|
712
|
+
description: "(spawn) Optional additional instructions or context for the sub-agent",
|
|
700
713
|
},
|
|
701
714
|
name: {
|
|
702
715
|
type: "string",
|
|
703
|
-
description: "Short name for the sub-agent tab (e.g. 'Research', 'Draft email'). If omitted, derived from the task.",
|
|
716
|
+
description: "(spawn) Short name for the sub-agent tab (e.g. 'Research', 'Draft email'). If omitted, derived from the task.",
|
|
704
717
|
},
|
|
705
718
|
agent: {
|
|
706
719
|
type: "string",
|
|
707
|
-
description: "Optional custom agent profile from agents/*.md to use for this task.",
|
|
720
|
+
description: "(spawn) Optional custom agent profile from agents/*.md to use for this task.",
|
|
708
721
|
},
|
|
709
|
-
},
|
|
710
|
-
required: ["task"],
|
|
711
|
-
},
|
|
712
|
-
},
|
|
713
|
-
run: async (args) => {
|
|
714
|
-
// Capture the send function NOW (at spawn time) so that
|
|
715
|
-
// concurrent runs don't clobber each other's send reference.
|
|
716
|
-
const capturedSend = deps.getSend();
|
|
717
|
-
const { spawnTask } = await import("./agent-teams.js");
|
|
718
|
-
// Filter out team orchestration tools so sub-agents can't spawn sub-agents
|
|
719
|
-
const teamToolNames = new Set([
|
|
720
|
-
"spawn-task",
|
|
721
|
-
"task-status",
|
|
722
|
-
"read-task-result",
|
|
723
|
-
"send-to-task",
|
|
724
|
-
"list-tasks",
|
|
725
|
-
]);
|
|
726
|
-
const subAgentActions = Object.fromEntries(Object.entries(deps.getActions()).filter(([name]) => !teamToolNames.has(name)));
|
|
727
|
-
let instructions = args.instructions;
|
|
728
|
-
let selectedModel = deps.getModel();
|
|
729
|
-
let selectedName = args.name || "";
|
|
730
|
-
if (args.agent) {
|
|
731
|
-
const { findAccessibleCustomAgent } = await import("../resources/agents.js");
|
|
732
|
-
const profile = await findAccessibleCustomAgent(deps.getOwner(), args.agent);
|
|
733
|
-
if (!profile) {
|
|
734
|
-
throw new Error(`Custom agent not found: ${args.agent}`);
|
|
735
|
-
}
|
|
736
|
-
const profileInstructions = `## Custom Agent Profile: ${profile.name}\n\n` +
|
|
737
|
-
(profile.description ? `${profile.description}\n\n` : "") +
|
|
738
|
-
profile.instructions;
|
|
739
|
-
instructions = instructions
|
|
740
|
-
? `${profileInstructions}\n\n## Extra Task Context\n\n${instructions}`
|
|
741
|
-
: profileInstructions;
|
|
742
|
-
selectedModel = profile.model ?? selectedModel;
|
|
743
|
-
selectedName = selectedName || profile.name;
|
|
744
|
-
}
|
|
745
|
-
const task = await spawnTask({
|
|
746
|
-
description: args.task,
|
|
747
|
-
instructions,
|
|
748
|
-
ownerEmail: deps.getOwner(),
|
|
749
|
-
systemPrompt: deps.getSystemPrompt(),
|
|
750
|
-
actions: subAgentActions,
|
|
751
|
-
engine: deps.getEngine(),
|
|
752
|
-
model: selectedModel,
|
|
753
|
-
parentThreadId: deps.getParentThreadId(),
|
|
754
|
-
parentSend: (event) => {
|
|
755
|
-
if (capturedSend)
|
|
756
|
-
capturedSend(event);
|
|
757
|
-
},
|
|
758
|
-
});
|
|
759
|
-
return JSON.stringify({
|
|
760
|
-
taskId: task.taskId,
|
|
761
|
-
threadId: task.threadId,
|
|
762
|
-
status: task.status,
|
|
763
|
-
description: task.description,
|
|
764
|
-
name: selectedName,
|
|
765
|
-
});
|
|
766
|
-
},
|
|
767
|
-
},
|
|
768
|
-
"task-status": {
|
|
769
|
-
tool: {
|
|
770
|
-
description: "Check the status of a sub-agent task. Returns current status, preview of output, and current step.",
|
|
771
|
-
parameters: {
|
|
772
|
-
type: "object",
|
|
773
|
-
properties: {
|
|
774
722
|
taskId: {
|
|
775
723
|
type: "string",
|
|
776
|
-
description: "The task ID returned by spawn
|
|
724
|
+
description: "(status, read-result, send) The task ID returned by a previous spawn",
|
|
777
725
|
},
|
|
778
|
-
|
|
779
|
-
required: ["taskId"],
|
|
780
|
-
},
|
|
781
|
-
},
|
|
782
|
-
run: async (args) => {
|
|
783
|
-
const { getTask } = await import("./agent-teams.js");
|
|
784
|
-
const task = await getTask(args.taskId);
|
|
785
|
-
if (!task)
|
|
786
|
-
return JSON.stringify({ error: "Task not found" });
|
|
787
|
-
return JSON.stringify({
|
|
788
|
-
taskId: task.taskId,
|
|
789
|
-
threadId: task.threadId,
|
|
790
|
-
status: task.status,
|
|
791
|
-
description: task.description,
|
|
792
|
-
preview: task.preview,
|
|
793
|
-
currentStep: task.currentStep,
|
|
794
|
-
summary: task.summary,
|
|
795
|
-
});
|
|
796
|
-
},
|
|
797
|
-
},
|
|
798
|
-
"read-task-result": {
|
|
799
|
-
tool: {
|
|
800
|
-
description: "Read the result of a completed sub-agent task. Returns the full output summary.",
|
|
801
|
-
parameters: {
|
|
802
|
-
type: "object",
|
|
803
|
-
properties: {
|
|
804
|
-
taskId: {
|
|
726
|
+
message: {
|
|
805
727
|
type: "string",
|
|
806
|
-
description: "
|
|
728
|
+
description: "(send) Message to send to the sub-agent",
|
|
807
729
|
},
|
|
808
730
|
},
|
|
809
|
-
required: ["
|
|
731
|
+
required: ["action"],
|
|
810
732
|
},
|
|
811
733
|
},
|
|
812
734
|
run: async (args) => {
|
|
813
|
-
const
|
|
814
|
-
|
|
815
|
-
if (
|
|
816
|
-
|
|
817
|
-
|
|
735
|
+
const action = args.action;
|
|
736
|
+
// ── spawn ──────────────────────────────────────────────
|
|
737
|
+
if (action === "spawn") {
|
|
738
|
+
if (!args.task)
|
|
739
|
+
throw new Error("'task' is required for spawn");
|
|
740
|
+
// Capture the send function NOW (at spawn time) so that
|
|
741
|
+
// concurrent runs don't clobber each other's send reference.
|
|
742
|
+
const capturedSend = deps.getSend();
|
|
743
|
+
const { spawnTask } = await import("./agent-teams.js");
|
|
744
|
+
// Filter out the team tool so sub-agents can't spawn sub-agents
|
|
745
|
+
const subAgentActions = Object.fromEntries(Object.entries(deps.getActions()).filter(([name]) => name !== "agent-teams"));
|
|
746
|
+
let instructions = args.instructions;
|
|
747
|
+
let selectedModel = deps.getModel();
|
|
748
|
+
let selectedName = args.name || "";
|
|
749
|
+
if (args.agent) {
|
|
750
|
+
const { findAccessibleCustomAgent } = await import("../resources/agents.js");
|
|
751
|
+
const profile = await findAccessibleCustomAgent(deps.getOwner(), args.agent);
|
|
752
|
+
if (!profile) {
|
|
753
|
+
throw new Error(`Custom agent not found: ${args.agent}`);
|
|
754
|
+
}
|
|
755
|
+
const profileInstructions = `## Custom Agent Profile: ${profile.name}\n\n` +
|
|
756
|
+
(profile.description ? `${profile.description}\n\n` : "") +
|
|
757
|
+
profile.instructions;
|
|
758
|
+
instructions = instructions
|
|
759
|
+
? `${profileInstructions}\n\n## Extra Task Context\n\n${instructions}`
|
|
760
|
+
: profileInstructions;
|
|
761
|
+
selectedModel = profile.model ?? selectedModel;
|
|
762
|
+
selectedName = selectedName || profile.name;
|
|
763
|
+
}
|
|
764
|
+
const task = await spawnTask({
|
|
765
|
+
description: args.task,
|
|
766
|
+
instructions,
|
|
767
|
+
ownerEmail: deps.getOwner(),
|
|
768
|
+
systemPrompt: deps.getSystemPrompt(),
|
|
769
|
+
actions: subAgentActions,
|
|
770
|
+
engine: deps.getEngine(),
|
|
771
|
+
model: selectedModel,
|
|
772
|
+
parentThreadId: deps.getParentThreadId(),
|
|
773
|
+
parentSend: (event) => {
|
|
774
|
+
if (capturedSend)
|
|
775
|
+
capturedSend(event);
|
|
776
|
+
},
|
|
777
|
+
});
|
|
818
778
|
return JSON.stringify({
|
|
819
|
-
|
|
779
|
+
taskId: task.taskId,
|
|
780
|
+
threadId: task.threadId,
|
|
781
|
+
status: task.status,
|
|
782
|
+
description: task.description,
|
|
783
|
+
name: selectedName,
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
// ── status ─────────────────────────────────────────────
|
|
787
|
+
if (action === "status") {
|
|
788
|
+
if (!args.taskId)
|
|
789
|
+
throw new Error("'taskId' is required for status");
|
|
790
|
+
const { getTask } = await import("./agent-teams.js");
|
|
791
|
+
const task = await getTask(args.taskId);
|
|
792
|
+
if (!task)
|
|
793
|
+
return JSON.stringify({ error: "Task not found" });
|
|
794
|
+
return JSON.stringify({
|
|
795
|
+
taskId: task.taskId,
|
|
796
|
+
threadId: task.threadId,
|
|
797
|
+
status: task.status,
|
|
798
|
+
description: task.description,
|
|
820
799
|
preview: task.preview,
|
|
821
|
-
|
|
800
|
+
currentStep: task.currentStep,
|
|
801
|
+
summary: task.summary,
|
|
822
802
|
});
|
|
823
803
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
description: t.description,
|
|
874
|
-
status: t.status,
|
|
875
|
-
currentStep: t.currentStep,
|
|
876
|
-
hasResult: t.summary.length > 0,
|
|
877
|
-
})), null, 2);
|
|
804
|
+
// ── read-result ────────────────────────────────────────
|
|
805
|
+
if (action === "read-result") {
|
|
806
|
+
if (!args.taskId)
|
|
807
|
+
throw new Error("'taskId' is required for read-result");
|
|
808
|
+
const { getTask } = await import("./agent-teams.js");
|
|
809
|
+
const task = await getTask(args.taskId);
|
|
810
|
+
if (!task)
|
|
811
|
+
return JSON.stringify({ error: "Task not found" });
|
|
812
|
+
if (task.status === "running") {
|
|
813
|
+
return JSON.stringify({
|
|
814
|
+
status: "running",
|
|
815
|
+
preview: task.preview,
|
|
816
|
+
message: "Task is still running. Check back later.",
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
return JSON.stringify({
|
|
820
|
+
taskId: task.taskId,
|
|
821
|
+
status: task.status,
|
|
822
|
+
summary: task.summary,
|
|
823
|
+
preview: task.preview,
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
// ── send ───────────────────────────────────────────────
|
|
827
|
+
if (action === "send") {
|
|
828
|
+
if (!args.taskId)
|
|
829
|
+
throw new Error("'taskId' is required for send");
|
|
830
|
+
if (!args.message)
|
|
831
|
+
throw new Error("'message' is required for send");
|
|
832
|
+
const { sendToTask } = await import("./agent-teams.js");
|
|
833
|
+
const result = await sendToTask(args.taskId, args.message);
|
|
834
|
+
return JSON.stringify(result);
|
|
835
|
+
}
|
|
836
|
+
// ── list ───────────────────────────────────────────────
|
|
837
|
+
if (action === "list") {
|
|
838
|
+
const { listTasks } = await import("./agent-teams.js");
|
|
839
|
+
const tasks = await listTasks();
|
|
840
|
+
if (tasks.length === 0) {
|
|
841
|
+
return "No sub-agent tasks.";
|
|
842
|
+
}
|
|
843
|
+
return JSON.stringify(tasks.map((t) => ({
|
|
844
|
+
taskId: t.taskId,
|
|
845
|
+
threadId: t.threadId,
|
|
846
|
+
description: t.description,
|
|
847
|
+
status: t.status,
|
|
848
|
+
currentStep: t.currentStep,
|
|
849
|
+
hasResult: t.summary.length > 0,
|
|
850
|
+
})), null, 2);
|
|
851
|
+
}
|
|
852
|
+
throw new Error(`Unknown action '${action}'. Use one of: spawn, status, read-result, send, list`);
|
|
878
853
|
},
|
|
879
854
|
},
|
|
880
855
|
};
|
|
@@ -885,7 +860,157 @@ function createTeamTools(deps) {
|
|
|
885
860
|
* Template AGENTS.md resources only need template-specific content.
|
|
886
861
|
*/
|
|
887
862
|
/**
|
|
888
|
-
*
|
|
863
|
+
* Compact framework instructions for lazy-context mode. Keeps the critical
|
|
864
|
+
* behavioral rules but defers verbose details (chat history, agent teams,
|
|
865
|
+
* recurring jobs, builder.io, browser, A2A, structured memory) behind the
|
|
866
|
+
* `get-framework-context` tool.
|
|
867
|
+
*/
|
|
868
|
+
const FRAMEWORK_CORE_COMPACT = `
|
|
869
|
+
### Core Rules
|
|
870
|
+
|
|
871
|
+
1. **Data lives in SQL** — All app state is in a SQL database. Use the available database tools. Call \`db-schema\` to see the full schema when needed.
|
|
872
|
+
2. **Context awareness** — The user's current screen state is in \`<current-screen>\`, current URL in \`<current-url>\`. Use both to understand what the user is looking at. To change URL state, use \`set-search-params\` or \`set-url-path\`.
|
|
873
|
+
3. **Navigate the UI** — Use the \`navigate\` tool to switch views, open items, or focus elements.
|
|
874
|
+
4. **Application state** — Ephemeral UI state lives in \`application_state\`. Use \`readAppState\`/\`writeAppState\`.
|
|
875
|
+
5. **Screen refresh is automatic** — The framework auto-refreshes after mutating tool calls. Only call \`refresh-screen\` when you mutated data via a path the framework can't detect.
|
|
876
|
+
6. **Memory** — Use \`save-memory\` proactively when you learn preferences, corrections, or project context.
|
|
877
|
+
7. **Security** — Always use parameterized queries. Never \`dangerouslySetInnerHTML\`, \`innerHTML\`, or \`eval()\`.
|
|
878
|
+
|
|
879
|
+
### Resources
|
|
880
|
+
|
|
881
|
+
Use resource-list, resource-read, resource-write, resource-delete for persistent notes and context files.
|
|
882
|
+
Resources are NOT an agent scratchpad — never create executable scripts, task plans, or work-in-progress files.
|
|
883
|
+
|
|
884
|
+
### Navigation Rule
|
|
885
|
+
|
|
886
|
+
When the user says "show me", "go to", "open", etc., ALWAYS use \`navigate\` first.
|
|
887
|
+
|
|
888
|
+
### Extended Capabilities
|
|
889
|
+
|
|
890
|
+
You also have tools for: inline embeds, chat history search, agent teams/sub-agents, recurring jobs, A2A cross-app calls, structured memory, and browser access. Call \`get-framework-context\` to read detailed instructions for any of these when needed.
|
|
891
|
+
`;
|
|
892
|
+
/**
|
|
893
|
+
* Verbose framework sections returned by the `get-framework-context` tool.
|
|
894
|
+
* Keyed by topic so the agent can request specific sections.
|
|
895
|
+
*/
|
|
896
|
+
const FRAMEWORK_CONTEXT_SECTIONS = {
|
|
897
|
+
embeds: `### Inline Embeds
|
|
898
|
+
|
|
899
|
+
You can embed an interactive view inline in your chat reply by writing an \`embed\` fenced code block. The chat renderer swaps the fence for a sandboxed iframe pointing at a route inside this app.
|
|
900
|
+
|
|
901
|
+
Syntax:
|
|
902
|
+
|
|
903
|
+
\`\`\`\`
|
|
904
|
+
\`\`\`embed
|
|
905
|
+
src: /some/path?param=value
|
|
906
|
+
aspect: 16/9
|
|
907
|
+
title: Optional label
|
|
908
|
+
\`\`\`
|
|
909
|
+
\`\`\`\`
|
|
910
|
+
|
|
911
|
+
Keys:
|
|
912
|
+
- \`src\` (required) — **must be a same-origin path starting with \`/\`**. Cross-origin URLs are blocked. No \`javascript:\` or \`data:\` URLs.
|
|
913
|
+
- \`aspect\` (optional) — one of \`16/9\` (default), \`4/3\`, \`3/2\`, \`2/1\`, \`21/9\`, \`1/1\`.
|
|
914
|
+
- \`title\` (optional) — accessible label / hover tooltip.
|
|
915
|
+
- \`height\` (optional) — fixed pixel height when aspect ratio isn't a good fit.
|
|
916
|
+
|
|
917
|
+
Use for charts, visualizations, previews. Don't use for simple text/tables or external sites.`,
|
|
918
|
+
"chat-history": `### Chat History
|
|
919
|
+
|
|
920
|
+
You can search and restore previous chat conversations using \`chat-history\`:
|
|
921
|
+
- \`chat-history\` (action: "search") — Search or list past chat threads by keyword
|
|
922
|
+
- \`chat-history\` (action: "open") — Open a chat thread in the UI as a new tab and focus it
|
|
923
|
+
|
|
924
|
+
When the user asks to find a previous conversation, use \`chat-history\` with action "search" first to find matching threads, then action "open" to restore the one they want.`,
|
|
925
|
+
"agent-teams": `### Agent Teams — Orchestration
|
|
926
|
+
|
|
927
|
+
You are an orchestrator. For complex or multi-step tasks, delegate to sub-agents using the \`agent-teams\` tool:
|
|
928
|
+
- \`agent-teams\` (action: "spawn") — Spawn a sub-agent for a task. It runs in its own thread while you stay available.
|
|
929
|
+
- \`agent-teams\` (action: "status") — Check the progress of a running sub-agent.
|
|
930
|
+
- \`agent-teams\` (action: "read-result") — Read the result when a sub-agent finishes.
|
|
931
|
+
- \`agent-teams\` (action: "send") — Send a message to a running sub-agent.
|
|
932
|
+
- \`agent-teams\` (action: "list") — List all sub-agent tasks.
|
|
933
|
+
|
|
934
|
+
**When to delegate vs do directly:**
|
|
935
|
+
- **Delegate** when the task involves multiple tool calls, research, content generation, or anything that takes more than a few seconds.
|
|
936
|
+
- **Do directly** for quick single-step tasks like navigation, reading state, or answering simple questions.
|
|
937
|
+
- **Spawn multiple sub-agents** when the user asks for multiple independent things — they'll run in parallel.
|
|
938
|
+
|
|
939
|
+
Sub-agents have access to all template tools but **cannot spawn sub-agents themselves**.`,
|
|
940
|
+
"recurring-jobs": `### Recurring Jobs
|
|
941
|
+
|
|
942
|
+
You can create recurring jobs that run on a cron schedule. Jobs are resource files under \`jobs/\`.
|
|
943
|
+
|
|
944
|
+
- \`manage-jobs\` (action: "create") — Create a new recurring job with a cron schedule and instructions
|
|
945
|
+
- \`manage-jobs\` (action: "list") — List all recurring jobs and their status
|
|
946
|
+
- \`manage-jobs\` (action: "update") — Update a job's schedule, instructions, or toggle enabled/disabled
|
|
947
|
+
- Delete a job with \`resource-delete --path jobs/<name>.md\`
|
|
948
|
+
|
|
949
|
+
Convert natural language to 5-field cron format:
|
|
950
|
+
- "every morning" / "daily at 9am" → \`0 9 * * *\`
|
|
951
|
+
- "every weekday at 9am" → \`0 9 * * 1-5\`
|
|
952
|
+
- "every hour" → \`0 * * * *\`
|
|
953
|
+
- "every monday at 9am" → \`0 9 * * 1\``,
|
|
954
|
+
builder: `### Connecting Builder.io
|
|
955
|
+
|
|
956
|
+
When the user asks to connect Builder.io or you hit a "Builder not configured" error, call the \`connect-builder\` tool. It renders a one-click Connect card inline — do NOT write out multi-step setup instructions yourself.`,
|
|
957
|
+
browser: `### Browser Access
|
|
958
|
+
|
|
959
|
+
Use \`connect-builder\` when you need browser access backed by Builder. It renders a Connect card that provisions a browser session.
|
|
960
|
+
|
|
961
|
+
- If Builder is not configured, the card will guide the user through setup.`,
|
|
962
|
+
"call-agent": `### call-agent — External Apps Only
|
|
963
|
+
|
|
964
|
+
The \`call-agent\` tool sends a message to a DIFFERENT, separately-deployed app's agent (A2A protocol). It is **not** for calling actions within the current app.
|
|
965
|
+
|
|
966
|
+
**NEVER use \`call-agent\` to:**
|
|
967
|
+
- Call your own app by name
|
|
968
|
+
- Perform tasks you can accomplish with your own registered tools
|
|
969
|
+
|
|
970
|
+
**ONLY use \`call-agent\` when:**
|
|
971
|
+
- The user explicitly asks you to communicate with a different app
|
|
972
|
+
- You need data that only another deployed app can provide`,
|
|
973
|
+
memory: `### Structured Memory
|
|
974
|
+
|
|
975
|
+
Your memory index (\`memory/MEMORY.md\`) is loaded at the start of every conversation.
|
|
976
|
+
|
|
977
|
+
**Tools:**
|
|
978
|
+
- \`save-memory\` — Create or update a memory (name, type, description, content)
|
|
979
|
+
- \`delete-memory\` — Remove a memory and its index entry
|
|
980
|
+
- \`resource-read --path memory/<name>.md\` — Read the full content of a specific memory
|
|
981
|
+
|
|
982
|
+
**Memory types:** user, feedback, project, reference
|
|
983
|
+
|
|
984
|
+
**When to save (proactively):**
|
|
985
|
+
- User corrects your approach → \`feedback\`
|
|
986
|
+
- User shares preferences → \`user\`
|
|
987
|
+
- Non-obvious pattern or gotcha → \`feedback\`
|
|
988
|
+
- Personal context (contacts, team) → \`user\`
|
|
989
|
+
- Project context to track → \`project\`
|
|
990
|
+
|
|
991
|
+
**Rules:**
|
|
992
|
+
- Don't save things obvious from code or standard framework behavior
|
|
993
|
+
- When updating, read first and merge — don't overwrite
|
|
994
|
+
- Keep descriptions concise
|
|
995
|
+
- One memory per logical topic`,
|
|
996
|
+
"sql-tools": `### SQL Tools
|
|
997
|
+
|
|
998
|
+
- \`db-schema\` — refresh the full schema with indexes and foreign keys
|
|
999
|
+
- \`db-query\` — run a SELECT (read-only; results already filtered to the current user/org)
|
|
1000
|
+
- \`db-exec\` — run INSERT / UPDATE / DELETE (writes already scoped; owner_email and org_id are auto-injected on INSERT)
|
|
1001
|
+
- \`db-patch\` — surgical search-and-replace on a large text column. Use for edits to large fields instead of re-sending multi-kilobyte strings.
|
|
1002
|
+
|
|
1003
|
+
### When to pick which SQL tool
|
|
1004
|
+
- Set a short column outright, update multiple columns, or do computed updates → \`db-exec UPDATE\`
|
|
1005
|
+
- Change a small slice of a large text/JSON column → \`db-patch\`
|
|
1006
|
+
- A template-specific action exists for the table → use that action (it encodes business rules and pushes live Yjs updates)
|
|
1007
|
+
- Read data → \`db-query\`. Never re-add \`WHERE owner_email = ...\` — scoping already applies it.
|
|
1008
|
+
|
|
1009
|
+
### External data sources vs the app database
|
|
1010
|
+
The \`db-*\` tools ONLY query the app's own SQL database. They do NOT reach external data warehouses. If the user asks about tables NOT in the schema, use the appropriate template action instead.`,
|
|
1011
|
+
};
|
|
1012
|
+
/**
|
|
1013
|
+
* Full framework instructions shared across both modes. The mode-specific
|
|
889
1014
|
* preamble is prepended by the prompt composition below.
|
|
890
1015
|
*/
|
|
891
1016
|
const FRAMEWORK_CORE = `
|
|
@@ -902,12 +1027,12 @@ const FRAMEWORK_CORE = `
|
|
|
902
1027
|
### Resources
|
|
903
1028
|
|
|
904
1029
|
You have access to a Resources system for persistent notes and context files.
|
|
905
|
-
Use resource-list, resource-read, resource-write,
|
|
1030
|
+
Use resource-list, resource-read, resource-write, resource-delete to manage resources.
|
|
906
1031
|
Resources can be personal (per-user) or shared (team-wide). By default, resources are personal.
|
|
907
1032
|
|
|
908
1033
|
When the user gives instructions that should apply to all users/sessions, update the shared "AGENTS.md" resource.
|
|
909
1034
|
|
|
910
|
-
**Resources are NOT an agent scratchpad.** Never use \`resource-write\` to store executable scripts, task plans, retry notes, or work-in-progress files you're writing to yourself. Specifically, do NOT create resources under \`scripts/\` or \`tasks/\` unless the user explicitly asked for a file at that path, or a tool (like \`
|
|
1035
|
+
**Resources are NOT an agent scratchpad.** Never use \`resource-write\` to store executable scripts, task plans, retry notes, or work-in-progress files you're writing to yourself. Specifically, do NOT create resources under \`scripts/\` or \`tasks/\` unless the user explicitly asked for a file at that path, or a tool (like \`manage-jobs\` or \`agent-teams\`) writes there as part of its contract. If you can't complete a task with the tools you have, say so — don't improvise by leaving behind \`FINAL-*.md\`, \`EXECUTE-NOW-*.js\`, or similar artifacts. Resources are visible to the user in the workspace sidebar; every file you write is something they'll see and have to clean up.
|
|
911
1036
|
|
|
912
1037
|
### Navigation Rule
|
|
913
1038
|
|
|
@@ -946,18 +1071,20 @@ Which routes are renderable as embeds is template-specific — the app's \`AGENT
|
|
|
946
1071
|
|
|
947
1072
|
### Chat History
|
|
948
1073
|
|
|
949
|
-
You can search and restore previous chat conversations
|
|
950
|
-
- \`
|
|
951
|
-
- \`
|
|
1074
|
+
You can search and restore previous chat conversations using \`chat-history\`:
|
|
1075
|
+
- \`chat-history\` (action: "search") — Search or list past chat threads by keyword
|
|
1076
|
+
- \`chat-history\` (action: "open") — Open a chat thread in the UI as a new tab and focus it
|
|
952
1077
|
|
|
953
|
-
When the user asks to find a previous conversation, use \`
|
|
1078
|
+
When the user asks to find a previous conversation, use \`chat-history\` with action "search" first to find matching threads, then action "open" to restore the one they want.
|
|
954
1079
|
|
|
955
1080
|
### Agent Teams — Orchestration
|
|
956
1081
|
|
|
957
|
-
You are an orchestrator. For complex or multi-step tasks, delegate to sub-agents:
|
|
958
|
-
- \`
|
|
959
|
-
- \`
|
|
960
|
-
- \`read-
|
|
1082
|
+
You are an orchestrator. For complex or multi-step tasks, delegate to sub-agents using the \`agent-teams\` tool:
|
|
1083
|
+
- \`agent-teams\` (action: "spawn") — Spawn a sub-agent for a task. It runs in its own thread while you stay available. A live preview card appears in the chat. You can optionally choose a custom agent profile from \`agents/*.md\`.
|
|
1084
|
+
- \`agent-teams\` (action: "status") — Check the progress of a running sub-agent.
|
|
1085
|
+
- \`agent-teams\` (action: "read-result") — Read the result when a sub-agent finishes.
|
|
1086
|
+
- \`agent-teams\` (action: "send") — Send a message to a running sub-agent.
|
|
1087
|
+
- \`agent-teams\` (action: "list") — List all sub-agent tasks.
|
|
961
1088
|
|
|
962
1089
|
**When to delegate vs do directly:**
|
|
963
1090
|
- **Delegate** when the task involves multiple tool calls, research, content generation, or anything that takes more than a few seconds. Examples: "create a deck about X", "analyze the data and write a report", "look up Y and draft an email about it".
|
|
@@ -968,18 +1095,18 @@ You are an orchestrator. For complex or multi-step tasks, delegate to sub-agents
|
|
|
968
1095
|
1. When the user asks for something complex, spawn a sub-agent with a clear task description.
|
|
969
1096
|
2. Tell the user what you've started ("I'm having a sub-agent research that for you").
|
|
970
1097
|
3. You can keep chatting — sub-agents run independently.
|
|
971
|
-
4. Use \`read-
|
|
1098
|
+
4. Use \`agent-teams\` (action: "read-result") to check results when needed, or the user can see live progress in the card.
|
|
972
1099
|
5. If the user's request has multiple steps, you can spawn one sub-agent per step, or chain them.
|
|
973
1100
|
|
|
974
|
-
Sub-agents have access to all template tools but **cannot spawn sub-agents themselves** — only you (the orchestrator) can do that. Give the sub-agent a specific, actionable task description — it will figure out which tools to use. If a matching custom agent profile exists, pass it via the \`agent\` parameter on \`spawn
|
|
1101
|
+
Sub-agents have access to all template tools but **cannot spawn sub-agents themselves** — only you (the orchestrator) can do that. Give the sub-agent a specific, actionable task description — it will figure out which tools to use. If a matching custom agent profile exists, pass it via the \`agent\` parameter on \`agent-teams\` (action: "spawn").
|
|
975
1102
|
|
|
976
1103
|
### Recurring Jobs
|
|
977
1104
|
|
|
978
1105
|
You can create recurring jobs that run on a cron schedule. Jobs are resource files under \`jobs/\`. Each job has a cron schedule and instructions that the agent executes automatically.
|
|
979
1106
|
|
|
980
|
-
- \`
|
|
981
|
-
- \`
|
|
982
|
-
- \`
|
|
1107
|
+
- \`manage-jobs\` (action: "create") — Create a new recurring job with a cron schedule and instructions
|
|
1108
|
+
- \`manage-jobs\` (action: "list") — List all recurring jobs and their status (schedule, last run, next run, errors)
|
|
1109
|
+
- \`manage-jobs\` (action: "update") — Update a job's schedule, instructions, or toggle enabled/disabled
|
|
983
1110
|
- Delete a job with \`resource-delete --path jobs/<name>.md\`
|
|
984
1111
|
|
|
985
1112
|
When the user asks for something recurring ("every morning", "daily at 9am", "weekly on Mondays"), create a job. Convert natural language to 5-field cron format:
|
|
@@ -998,11 +1125,9 @@ When the user asks to connect Builder.io, needs Builder for LLM access / browser
|
|
|
998
1125
|
|
|
999
1126
|
### Browser Access
|
|
1000
1127
|
|
|
1001
|
-
Use \`
|
|
1128
|
+
Use \`connect-builder\` when you need browser access backed by Builder. It renders a Connect card that provisions a browser session.
|
|
1002
1129
|
|
|
1003
|
-
- If
|
|
1004
|
-
- Reuse a stable \`sessionId\` when you want to reconnect to the same browser session.
|
|
1005
|
-
- Include proxy parameters when you need the browser to reach a local dev server through Builder's browser connection flow.
|
|
1130
|
+
- If Builder is not configured, the card will guide the user through setup.
|
|
1006
1131
|
|
|
1007
1132
|
### call-agent — External Apps Only
|
|
1008
1133
|
|
|
@@ -1068,7 +1193,7 @@ When the user asks you to change the UI, modify code, add a feature, fix a bug i
|
|
|
1068
1193
|
- Do NOT read source files, list directories, or explore the codebase. You have no filesystem tools and don't need to look at code to recommend Builder.
|
|
1069
1194
|
- Do NOT write an implementation plan. Do NOT write code in your response. Do NOT describe which files to create or modify. Builder will figure that out in its sandbox.
|
|
1070
1195
|
- Do NOT save plans, specs, or code to \`resource-write\`. Resources are for app data, not implementation plans the user didn't ask for.
|
|
1071
|
-
- Do NOT spawn sub-agents (\`
|
|
1196
|
+
- Do NOT spawn sub-agents (\`agent-teams\`) to design, plan, or research the feature. The answer is always: call \`connect-builder\`, say one sentence, stop. Sub-agents inherit these same rules and have no code-editing tools either.
|
|
1072
1197
|
- Do NOT say "I don't have a request-code-change tool" or list what tools you lack. Just call \`connect-builder\`.
|
|
1073
1198
|
- Do NOT wait for the user to ask "how" — call \`connect-builder\` the moment a code change is requested.
|
|
1074
1199
|
|
|
@@ -1098,6 +1223,34 @@ When editing code, follow the agent-native architecture:
|
|
|
1098
1223
|
- No Node.js-specific APIs in server routes (must work on Cloudflare Workers, etc.)
|
|
1099
1224
|
- Use shadcn/ui components and Tabler Icons for all UI work
|
|
1100
1225
|
${FRAMEWORK_CORE}`;
|
|
1226
|
+
const PROD_FRAMEWORK_PROMPT_COMPACT = `## Agent-Native Framework — Production Mode
|
|
1227
|
+
|
|
1228
|
+
You are an AI agent in an agent-native application, running in **production mode**.
|
|
1229
|
+
|
|
1230
|
+
The agent and the UI are equal partners — everything the UI can do, you can do via your tools, and vice versa. They share the same SQL database and stay in sync automatically.
|
|
1231
|
+
|
|
1232
|
+
**In production mode, you operate through registered actions exposed as tools.** These are your capabilities — use them to read data, take actions, and help the user. You cannot edit source code or access the filesystem directly. Your tools are the app's API.
|
|
1233
|
+
|
|
1234
|
+
### Code Changes — Call \`connect-builder\`
|
|
1235
|
+
|
|
1236
|
+
When the user asks to change the UI, modify code, add a feature, or fix a bug in the app itself — call \`connect-builder\` immediately, passing the user's request as the \`prompt\`. Do NOT write code, list files, make plans, or spawn sub-agents for code changes. Builder handles it in the cloud. Mention \`npx agent-native create <app-name>\` as an offline fallback.
|
|
1237
|
+
${FRAMEWORK_CORE_COMPACT}`;
|
|
1238
|
+
const DEV_FRAMEWORK_PROMPT_COMPACT = `## Agent-Native Framework — Development Mode
|
|
1239
|
+
|
|
1240
|
+
You are an AI agent in an agent-native application, running in **development mode**.
|
|
1241
|
+
|
|
1242
|
+
The agent and the UI are equal partners — everything the UI can do, you can do via tools/scripts, and vice versa. They share the same SQL database and stay in sync automatically.
|
|
1243
|
+
|
|
1244
|
+
**In development mode, you have UNRESTRICTED access.** You can run any shell command, read/write files, query the database, call external APIs, edit source code, and install packages.
|
|
1245
|
+
|
|
1246
|
+
**Template-specific actions are invoked via shell, NOT as direct tools.** Run them with: \`shell({ command: 'pnpm action <name> --arg value' })\`. See the "Available Actions" section below for CLI syntax.
|
|
1247
|
+
|
|
1248
|
+
When editing code, follow the agent-native architecture:
|
|
1249
|
+
- Every feature needs all four areas: UI + scripts + skills/instructions + application-state sync
|
|
1250
|
+
- All SQL must be dialect-agnostic (works on SQLite and Postgres)
|
|
1251
|
+
- No Node.js-specific APIs in server routes (must work on Cloudflare Workers, etc.)
|
|
1252
|
+
- Use shadcn/ui components and Tabler Icons for all UI work
|
|
1253
|
+
${FRAMEWORK_CORE_COMPACT}`;
|
|
1101
1254
|
const DEFAULT_SYSTEM_PROMPT = PROD_FRAMEWORK_PROMPT;
|
|
1102
1255
|
/**
|
|
1103
1256
|
* Pre-load the agent's context: AGENTS.md (template instructions), the skills
|
|
@@ -1117,7 +1270,7 @@ const DEFAULT_SYSTEM_PROMPT = PROD_FRAMEWORK_PROMPT;
|
|
|
1117
1270
|
* AGENTS.md and restarting the server is all it takes; Vite HMR invalidates
|
|
1118
1271
|
* the bundle in dev so changes land instantly.
|
|
1119
1272
|
*/
|
|
1120
|
-
async function loadResourcesForPrompt(owner) {
|
|
1273
|
+
async function loadResourcesForPrompt(owner, compact = false) {
|
|
1121
1274
|
await ensurePersonalDefaults(owner);
|
|
1122
1275
|
const sections = [];
|
|
1123
1276
|
// 1. Workspace AGENTS.md + skills merged into the template bundle.
|
|
@@ -1128,33 +1281,51 @@ async function loadResourcesForPrompt(owner) {
|
|
|
1128
1281
|
if (bundle.workspaceAgentsMd && bundle.workspaceAgentsMd.trim()) {
|
|
1129
1282
|
sections.push(`<resource name="AGENTS.md" scope="workspace">\n${bundle.workspaceAgentsMd.trim()}\n</resource>`);
|
|
1130
1283
|
}
|
|
1131
|
-
// 2. Template AGENTS.md.
|
|
1284
|
+
// 2. Template AGENTS.md — always included (critical template instructions).
|
|
1132
1285
|
if (bundle.agentsMd.trim()) {
|
|
1133
1286
|
sections.push(`<resource name="AGENTS.md" scope="template">\n${bundle.agentsMd.trim()}\n</resource>`);
|
|
1134
1287
|
}
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1288
|
+
// In compact mode, skip the full skills block — the agent can use
|
|
1289
|
+
// `docs-search` to find skills when it needs them.
|
|
1290
|
+
if (!compact) {
|
|
1291
|
+
const skillsBlock = generateSkillsPromptBlock(bundle);
|
|
1292
|
+
if (skillsBlock)
|
|
1293
|
+
sections.push(skillsBlock);
|
|
1294
|
+
}
|
|
1295
|
+
else if (Object.keys(bundle.skills).length > 0) {
|
|
1296
|
+
const names = Object.values(bundle.skills)
|
|
1297
|
+
.map((s) => s.meta.name)
|
|
1298
|
+
.join(", ");
|
|
1299
|
+
sections.push(`<skills-summary>\nSkills available in .agents/skills/: ${names}. Use \`docs-search\` to read a skill before starting a task it applies to.\n</skills-summary>`);
|
|
1146
1300
|
}
|
|
1147
1301
|
}
|
|
1148
1302
|
catch { }
|
|
1149
|
-
|
|
1150
|
-
|
|
1303
|
+
if (compact) {
|
|
1304
|
+
// In compact mode, skip learnings and memory in the prompt.
|
|
1305
|
+
// The agent can access them via resource-read when needed.
|
|
1306
|
+
// Add a brief pointer so the agent knows they exist.
|
|
1307
|
+
sections.push(`<context-note>Shared learnings (LEARNINGS.md) and your personal memory (memory/MEMORY.md) are available via \`resource-read\`. Check them when making decisions that might benefit from prior context.</context-note>`);
|
|
1308
|
+
}
|
|
1309
|
+
else {
|
|
1310
|
+
// LEARNINGS.md from SQL (template-level instructions are in AGENTS.md above).
|
|
1311
|
+
// 2. Shared SQL scope
|
|
1151
1312
|
try {
|
|
1152
|
-
const
|
|
1153
|
-
if (
|
|
1154
|
-
sections.push(`<resource name="
|
|
1313
|
+
const shared = await resourceGetByPath(SHARED_OWNER, "LEARNINGS.md");
|
|
1314
|
+
if (shared?.content?.trim()) {
|
|
1315
|
+
sections.push(`<resource name="LEARNINGS.md" scope="shared">\n${shared.content.trim()}\n</resource>`);
|
|
1155
1316
|
}
|
|
1156
1317
|
}
|
|
1157
1318
|
catch { }
|
|
1319
|
+
// 3. Personal memory index (skip if owner is the shared sentinel)
|
|
1320
|
+
if (owner !== SHARED_OWNER) {
|
|
1321
|
+
try {
|
|
1322
|
+
const memoryIndex = await resourceGetByPath(owner, "memory/MEMORY.md");
|
|
1323
|
+
if (memoryIndex?.content?.trim()) {
|
|
1324
|
+
sections.push(`<resource name="memory/MEMORY.md" scope="personal">\n${memoryIndex.content.trim()}\n</resource>`);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
catch { }
|
|
1328
|
+
}
|
|
1158
1329
|
}
|
|
1159
1330
|
if (sections.length === 0)
|
|
1160
1331
|
return "";
|
|
@@ -1272,11 +1443,9 @@ ${lines.join("\n")}`;
|
|
|
1272
1443
|
}
|
|
1273
1444
|
return `\n\n## Available Actions
|
|
1274
1445
|
|
|
1275
|
-
**Use these actions directly
|
|
1276
|
-
|
|
1277
|
-
**For external data sources (BigQuery, HubSpot, Jira, GA4, etc.), use the data-source-specific action below — NOT \`db-query\`.** \`db-query\` only reaches the app's own internal database. If the user asks about tables not in the app schema, pick the matching action here.
|
|
1446
|
+
**Use these actions directly as tool calls.** They are your primary tools — they handle database access, validation, and business logic internally. Prefer these over lower-level tools like \`web-request\` or \`db-query\`.
|
|
1278
1447
|
|
|
1279
|
-
Parameter notation: \`name*\` = required, \`name?\` = optional.
|
|
1448
|
+
Parameter notation: \`name*\` = required, \`name?\` = optional. Pass parameters as a JSON object.
|
|
1280
1449
|
|
|
1281
1450
|
${lines.join("\n")}`;
|
|
1282
1451
|
}
|
|
@@ -1467,16 +1636,31 @@ export function createAgentChatPlugin(options) {
|
|
|
1467
1636
|
process.once("SIGTERM", stop);
|
|
1468
1637
|
process.once("SIGINT", stop);
|
|
1469
1638
|
}
|
|
1470
|
-
// Resolve actions — prefer `actions`, fall back to deprecated
|
|
1639
|
+
// Resolve actions — prefer explicit `actions`, fall back to deprecated
|
|
1640
|
+
// `scripts`. When neither is provided, auto-discover from the filesystem
|
|
1641
|
+
// so templates that forget to pass `actions` still work in non-serverless
|
|
1642
|
+
// deployments (serverless bundles need explicit imports).
|
|
1471
1643
|
const rawActions = options?.actions ?? options?.scripts;
|
|
1472
|
-
|
|
1644
|
+
let templateScripts = typeof rawActions === "function"
|
|
1473
1645
|
? await rawActions()
|
|
1474
1646
|
: (rawActions ?? {});
|
|
1647
|
+
if (!rawActions && Object.keys(templateScripts).length === 0) {
|
|
1648
|
+
try {
|
|
1649
|
+
const { autoDiscoverActions } = await import("./action-discovery.js");
|
|
1650
|
+
templateScripts = await autoDiscoverActions(process.cwd());
|
|
1651
|
+
}
|
|
1652
|
+
catch {
|
|
1653
|
+
// Filesystem discovery unavailable (serverless bundle) — skip.
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1475
1656
|
// Resource, chat, docs, db, and cross-agent scripts are available in both prod and dev modes
|
|
1476
1657
|
const resourceScripts = await createResourceScriptEntries();
|
|
1477
1658
|
const docsScripts = await createDocsScriptEntries();
|
|
1478
1659
|
const dbScripts = await createDbScriptEntries();
|
|
1479
1660
|
const refreshScreenTool = createRefreshScreenEntry();
|
|
1661
|
+
const frameworkContextTool = createFrameworkContextEntry();
|
|
1662
|
+
const leanPrompt = options?.leanPrompt === true;
|
|
1663
|
+
const lazyContext = options?.lazyContext !== false && !leanPrompt;
|
|
1480
1664
|
const urlTools = createUrlTools();
|
|
1481
1665
|
const engineScripts = await createAgentEngineScriptEntries();
|
|
1482
1666
|
const chatScripts = {
|
|
@@ -1667,6 +1851,7 @@ export function createAgentChatPlugin(options) {
|
|
|
1667
1851
|
? {
|
|
1668
1852
|
...resourceScripts,
|
|
1669
1853
|
...docsScripts,
|
|
1854
|
+
...(lazyContext ? frameworkContextTool : {}),
|
|
1670
1855
|
...chatScripts,
|
|
1671
1856
|
...callAgentScript,
|
|
1672
1857
|
...automationTools,
|
|
@@ -1683,6 +1868,7 @@ export function createAgentChatPlugin(options) {
|
|
|
1683
1868
|
...docsScripts,
|
|
1684
1869
|
...dbScripts,
|
|
1685
1870
|
...refreshScreenTool,
|
|
1871
|
+
...(lazyContext ? frameworkContextTool : {}),
|
|
1686
1872
|
...urlTools,
|
|
1687
1873
|
...chatScripts,
|
|
1688
1874
|
...callAgentScript,
|
|
@@ -1767,8 +1953,10 @@ export function createAgentChatPlugin(options) {
|
|
|
1767
1953
|
const handler = devActive && devHandler ? devHandler : prodHandler;
|
|
1768
1954
|
// Build the same system prompt the interactive agent uses
|
|
1769
1955
|
const owner = userEmail || "local@localhost";
|
|
1770
|
-
const resources = await loadResourcesForPrompt(owner);
|
|
1771
|
-
const schemaBlock =
|
|
1956
|
+
const resources = await loadResourcesForPrompt(owner, lazyContext);
|
|
1957
|
+
const schemaBlock = lazyContext
|
|
1958
|
+
? ""
|
|
1959
|
+
: await buildSchemaBlock(owner, devActive);
|
|
1772
1960
|
const systemPrompt = devActive
|
|
1773
1961
|
? devPrompt + resources + schemaBlock
|
|
1774
1962
|
: basePrompt + resources + schemaBlock;
|
|
@@ -1782,6 +1970,7 @@ export function createAgentChatPlugin(options) {
|
|
|
1782
1970
|
? {
|
|
1783
1971
|
...resourceScripts,
|
|
1784
1972
|
...docsScripts,
|
|
1973
|
+
...(lazyContext ? frameworkContextTool : {}),
|
|
1785
1974
|
...chatScripts,
|
|
1786
1975
|
...browserTools,
|
|
1787
1976
|
...devScriptsForA2A,
|
|
@@ -1792,6 +1981,7 @@ export function createAgentChatPlugin(options) {
|
|
|
1792
1981
|
...docsScripts,
|
|
1793
1982
|
...dbScripts,
|
|
1794
1983
|
...refreshScreenTool,
|
|
1984
|
+
...(lazyContext ? frameworkContextTool : {}),
|
|
1795
1985
|
...urlTools,
|
|
1796
1986
|
...chatScripts,
|
|
1797
1987
|
...browserTools,
|
|
@@ -1852,11 +2042,26 @@ export function createAgentChatPlugin(options) {
|
|
|
1852
2042
|
// Build system prompts — dynamic functions that pre-load resources per-request.
|
|
1853
2043
|
// Production gets PROD_FRAMEWORK_PROMPT, dev gets DEV_FRAMEWORK_PROMPT.
|
|
1854
2044
|
// Custom systemPrompt from options overrides the framework default entirely.
|
|
1855
|
-
const prodPrompt = (options?.systemPrompt ??
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
2045
|
+
const prodPrompt = (options?.systemPrompt ??
|
|
2046
|
+
(lazyContext
|
|
2047
|
+
? PROD_FRAMEWORK_PROMPT_COMPACT
|
|
2048
|
+
: PROD_FRAMEWORK_PROMPT)) + prodActionsPrompt;
|
|
2049
|
+
// When template actions are registered as native tools in dev (via
|
|
2050
|
+
// `nativeActionsInDev` or `leanPrompt`), the dev prompt's "invoke
|
|
2051
|
+
// template actions via shell" guidance is wrong — use the prod prompt
|
|
2052
|
+
// + tool-format action list instead, same as production.
|
|
2053
|
+
const devNative = options?.nativeActionsInDev === true || leanPrompt;
|
|
2054
|
+
const devPrompt = devNative
|
|
2055
|
+
? prodPrompt
|
|
2056
|
+
: (options?.devSystemPrompt
|
|
2057
|
+
? options.devSystemPrompt +
|
|
2058
|
+
(options?.systemPrompt ??
|
|
2059
|
+
(lazyContext
|
|
2060
|
+
? PROD_FRAMEWORK_PROMPT_COMPACT
|
|
2061
|
+
: PROD_FRAMEWORK_PROMPT))
|
|
2062
|
+
: lazyContext
|
|
2063
|
+
? DEV_FRAMEWORK_PROMPT_COMPACT
|
|
2064
|
+
: DEV_FRAMEWORK_PROMPT) + devActionsPrompt;
|
|
1860
2065
|
// Keep legacy names for the composition below
|
|
1861
2066
|
const basePrompt = prodPrompt;
|
|
1862
2067
|
const devPrefix = options?.devSystemPrompt ?? DEFAULT_DEV_PROMPT;
|
|
@@ -1882,6 +2087,7 @@ export function createAgentChatPlugin(options) {
|
|
|
1882
2087
|
? {
|
|
1883
2088
|
...resourceScripts,
|
|
1884
2089
|
...docsScripts,
|
|
2090
|
+
...(lazyContext ? frameworkContextTool : {}),
|
|
1885
2091
|
...chatScripts,
|
|
1886
2092
|
...devScriptsForA2A,
|
|
1887
2093
|
}
|
|
@@ -1891,14 +2097,29 @@ export function createAgentChatPlugin(options) {
|
|
|
1891
2097
|
...docsScripts,
|
|
1892
2098
|
...dbScripts,
|
|
1893
2099
|
...refreshScreenTool,
|
|
2100
|
+
...(lazyContext ? frameworkContextTool : {}),
|
|
1894
2101
|
...urlTools,
|
|
1895
2102
|
...chatScripts,
|
|
1896
2103
|
};
|
|
1897
2104
|
const mcpTools = actionsToEngineTools(mcpActions);
|
|
1898
|
-
const resources = await loadResourcesForPrompt("local@localhost");
|
|
1899
|
-
const schemaBlock =
|
|
2105
|
+
const resources = await loadResourcesForPrompt("local@localhost", lazyContext);
|
|
2106
|
+
const schemaBlock = lazyContext
|
|
2107
|
+
? ""
|
|
2108
|
+
: await buildSchemaBlock("local@localhost", devActiveMcp);
|
|
2109
|
+
// Build the MCP handler's own prompt — always use the shell-based
|
|
2110
|
+
// dev prompt in dev mode because mcpActions routes template actions
|
|
2111
|
+
// through shell (`devScriptsForA2A`), regardless of `nativeActionsInDev`.
|
|
2112
|
+
const mcpDevPrompt = (options?.devSystemPrompt
|
|
2113
|
+
? options.devSystemPrompt +
|
|
2114
|
+
(options?.systemPrompt ??
|
|
2115
|
+
(lazyContext
|
|
2116
|
+
? PROD_FRAMEWORK_PROMPT_COMPACT
|
|
2117
|
+
: PROD_FRAMEWORK_PROMPT))
|
|
2118
|
+
: lazyContext
|
|
2119
|
+
? DEV_FRAMEWORK_PROMPT_COMPACT
|
|
2120
|
+
: DEV_FRAMEWORK_PROMPT) + devActionsPrompt;
|
|
1900
2121
|
const systemPrompt = devActiveMcp
|
|
1901
|
-
?
|
|
2122
|
+
? mcpDevPrompt + resources + schemaBlock
|
|
1902
2123
|
: basePrompt + resources + schemaBlock;
|
|
1903
2124
|
let accumulatedText = "";
|
|
1904
2125
|
const controller = new AbortController();
|
|
@@ -1931,7 +2152,7 @@ export function createAgentChatPlugin(options) {
|
|
|
1931
2152
|
}
|
|
1932
2153
|
};
|
|
1933
2154
|
// Auto-mount template actions as HTTP endpoints under /_agent-native/actions/
|
|
1934
|
-
// Include engine management
|
|
2155
|
+
// Include engine management script so the UI can call manage-agent-engine.
|
|
1935
2156
|
const httpActions = {
|
|
1936
2157
|
...discoveredActions,
|
|
1937
2158
|
...templateScripts,
|
|
@@ -2041,20 +2262,42 @@ export function createAgentChatPlugin(options) {
|
|
|
2041
2262
|
// Auto-checkpoint in dev mode after file-modifying agent turns
|
|
2042
2263
|
if (isDevMode()) {
|
|
2043
2264
|
try {
|
|
2044
|
-
const { createCheckpoint: gitCheckpoint, isGitRepo, hasUncommittedChanges, } = await import("../checkpoints/service.js");
|
|
2265
|
+
const { createCheckpoint: gitCheckpoint, isGitRepo, hasUncommittedChanges, getChangedFileNames, } = await import("../checkpoints/service.js");
|
|
2045
2266
|
const cwd = process.cwd();
|
|
2046
2267
|
if (isGitRepo(cwd) && hasUncommittedChanges(cwd)) {
|
|
2047
|
-
|
|
2268
|
+
let summary = "";
|
|
2269
|
+
// Try to extract the first sentence of the assistant's text response
|
|
2270
|
+
let assistantText = "";
|
|
2048
2271
|
for (const { event } of run.events ?? []) {
|
|
2049
|
-
if (event.type === "
|
|
2050
|
-
|
|
2051
|
-
|
|
2272
|
+
if (event.type === "text" && typeof event.text === "string") {
|
|
2273
|
+
assistantText += event.text;
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
assistantText = assistantText.trim();
|
|
2277
|
+
if (assistantText) {
|
|
2278
|
+
const firstSentence = assistantText
|
|
2279
|
+
.split(/(?<=[.!?\n])\s/)[0]
|
|
2280
|
+
?.replace(/\n/g, " ")
|
|
2281
|
+
.trim();
|
|
2282
|
+
if (firstSentence && firstSentence.length <= 120) {
|
|
2283
|
+
summary = firstSentence;
|
|
2284
|
+
}
|
|
2285
|
+
else if (firstSentence) {
|
|
2286
|
+
summary = firstSentence.slice(0, 117) + "...";
|
|
2052
2287
|
}
|
|
2053
2288
|
}
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2289
|
+
// Fall back to listing changed files
|
|
2290
|
+
if (!summary) {
|
|
2291
|
+
const files = getChangedFileNames(cwd);
|
|
2292
|
+
if (files.length > 0) {
|
|
2293
|
+
summary = `Update ${files.join(", ")}`;
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
if (!summary)
|
|
2297
|
+
summary = "Agent turn";
|
|
2298
|
+
if (summary.length > 120)
|
|
2299
|
+
summary = summary.slice(0, 117) + "...";
|
|
2300
|
+
const sha = gitCheckpoint(cwd, summary);
|
|
2058
2301
|
if (sha) {
|
|
2059
2302
|
const { insertCheckpoint } = await import("../checkpoints/store.js");
|
|
2060
2303
|
const cpId = `cp-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -2092,6 +2335,7 @@ export function createAgentChatPlugin(options) {
|
|
|
2092
2335
|
// via shell, so omit them from the native tool registry.
|
|
2093
2336
|
...resourceScripts,
|
|
2094
2337
|
...docsScripts,
|
|
2338
|
+
...(lazyContext ? frameworkContextTool : {}),
|
|
2095
2339
|
...chatScripts,
|
|
2096
2340
|
...devScriptsForA2A,
|
|
2097
2341
|
}
|
|
@@ -2101,6 +2345,7 @@ export function createAgentChatPlugin(options) {
|
|
|
2101
2345
|
...docsScripts,
|
|
2102
2346
|
...dbScripts,
|
|
2103
2347
|
...refreshScreenTool,
|
|
2348
|
+
...(lazyContext ? frameworkContextTool : {}),
|
|
2104
2349
|
...urlTools,
|
|
2105
2350
|
...chatScripts,
|
|
2106
2351
|
},
|
|
@@ -2108,7 +2353,7 @@ export function createAgentChatPlugin(options) {
|
|
|
2108
2353
|
createAnthropicEngine({
|
|
2109
2354
|
// Sub-agents must inherit the parent run's resolved key so a
|
|
2110
2355
|
// BYO-key user can't bypass the free-tier check on the parent
|
|
2111
|
-
// run and then have
|
|
2356
|
+
// run and then have agent-teams spawn delegations bill the platform key.
|
|
2112
2357
|
apiKey: _currentRunUserApiKey ??
|
|
2113
2358
|
options?.apiKey ??
|
|
2114
2359
|
process.env.ANTHROPIC_API_KEY,
|
|
@@ -2122,7 +2367,7 @@ export function createAgentChatPlugin(options) {
|
|
|
2122
2367
|
},
|
|
2123
2368
|
});
|
|
2124
2369
|
// Hook into the run lifecycle to set/clear the send reference.
|
|
2125
|
-
// Job management
|
|
2370
|
+
// Job management tool (manage-jobs)
|
|
2126
2371
|
let jobTools = {};
|
|
2127
2372
|
try {
|
|
2128
2373
|
const { createJobTools } = await import("../jobs/tools.js");
|
|
@@ -2135,6 +2380,7 @@ export function createAgentChatPlugin(options) {
|
|
|
2135
2380
|
...docsScripts,
|
|
2136
2381
|
...dbScripts,
|
|
2137
2382
|
...refreshScreenTool,
|
|
2383
|
+
...(lazyContext ? frameworkContextTool : {}),
|
|
2138
2384
|
...urlTools,
|
|
2139
2385
|
...chatScripts,
|
|
2140
2386
|
...callAgentScript,
|
|
@@ -2169,26 +2415,39 @@ export function createAgentChatPlugin(options) {
|
|
|
2169
2415
|
return "";
|
|
2170
2416
|
}
|
|
2171
2417
|
};
|
|
2172
|
-
const leanPrompt = options?.leanPrompt === true;
|
|
2173
2418
|
// Lean mode: use only the template's systemPrompt + actions list.
|
|
2174
|
-
// Skip resource loading
|
|
2175
|
-
//
|
|
2419
|
+
// Skip resource loading and schema block — those add DB round-trips
|
|
2420
|
+
// and tokens that minimal/voice apps don't need.
|
|
2176
2421
|
const leanBasePrompt = (options?.systemPrompt ?? "") + prodActionsPrompt;
|
|
2422
|
+
// Per-request preamble shared by both prod and dev handlers. Resolves
|
|
2423
|
+
// owner + user API key (stashed on the closure so downstream tools can
|
|
2424
|
+
// reach them) and the template-authored `extraContext`. `extraContext`
|
|
2425
|
+
// runs in every prompt variant (lean, lazy, full) — if a template
|
|
2426
|
+
// defined it, they opted in; framework-provided content is what the
|
|
2427
|
+
// token-saving modes strip.
|
|
2428
|
+
const prepareRun = async (event) => {
|
|
2429
|
+
_currentRequestOrigin = getOrigin(event);
|
|
2430
|
+
const owner = await getOwnerFromEvent(event);
|
|
2431
|
+
_currentRunOwner = owner;
|
|
2432
|
+
const { getOwnerActiveApiKey } = await import("../agent/production-agent.js");
|
|
2433
|
+
_currentRunUserApiKey = await getOwnerActiveApiKey(owner);
|
|
2434
|
+
const extra = await resolveExtraContext(event, owner);
|
|
2435
|
+
return { owner, extra };
|
|
2436
|
+
};
|
|
2177
2437
|
const prodHandler = createProductionAgentHandler({
|
|
2178
2438
|
actions: prodActions,
|
|
2179
2439
|
systemPrompt: async (event) => {
|
|
2180
|
-
|
|
2181
|
-
const owner = await getOwnerFromEvent(event);
|
|
2182
|
-
_currentRunOwner = owner;
|
|
2183
|
-
const { getOwnerActiveApiKey } = await import("../agent/production-agent.js");
|
|
2184
|
-
_currentRunUserApiKey = await getOwnerActiveApiKey(owner);
|
|
2440
|
+
const { owner, extra } = await prepareRun(event);
|
|
2185
2441
|
if (leanPrompt) {
|
|
2186
|
-
_currentRunSystemPrompt = leanBasePrompt;
|
|
2442
|
+
_currentRunSystemPrompt = leanBasePrompt + extra;
|
|
2187
2443
|
return _currentRunSystemPrompt;
|
|
2188
2444
|
}
|
|
2189
|
-
const resources = await loadResourcesForPrompt(owner);
|
|
2190
|
-
|
|
2191
|
-
|
|
2445
|
+
const resources = await loadResourcesForPrompt(owner, lazyContext);
|
|
2446
|
+
// In lazy context mode, skip embedding the full schema — the agent
|
|
2447
|
+
// calls `db-schema` on demand. This saves ~1-2K tokens per request.
|
|
2448
|
+
const schemaBlock = lazyContext
|
|
2449
|
+
? ""
|
|
2450
|
+
: await buildSchemaBlock(owner, false);
|
|
2192
2451
|
_currentRunSystemPrompt =
|
|
2193
2452
|
basePrompt + resources + schemaBlock + extra;
|
|
2194
2453
|
return _currentRunSystemPrompt;
|
|
@@ -2224,14 +2483,16 @@ export function createAgentChatPlugin(options) {
|
|
|
2224
2483
|
// how Claude Code works locally and dramatically reduces the rate of
|
|
2225
2484
|
// degenerate empty-object tool calls. The CLI syntax for each action is
|
|
2226
2485
|
// listed in the dev system prompt's "Available Actions" section.
|
|
2227
|
-
// In lean mode
|
|
2228
|
-
// instead of routing through shell
|
|
2229
|
-
//
|
|
2230
|
-
|
|
2486
|
+
// In lean mode — or when `nativeActionsInDev` is set — expose the
|
|
2487
|
+
// template's actions as native tools instead of routing through shell.
|
|
2488
|
+
// Templates with structured-arg actions (objects/arrays) need this to
|
|
2489
|
+
// avoid round-tripping JSON through the CLI parser.
|
|
2490
|
+
const devActions = devNative
|
|
2231
2491
|
? prodActions
|
|
2232
2492
|
: {
|
|
2233
2493
|
...resourceScripts,
|
|
2234
2494
|
...docsScripts,
|
|
2495
|
+
...(lazyContext ? frameworkContextTool : {}),
|
|
2235
2496
|
...chatScripts,
|
|
2236
2497
|
...callAgentScript,
|
|
2237
2498
|
...teamTools,
|
|
@@ -2245,8 +2506,8 @@ export function createAgentChatPlugin(options) {
|
|
|
2245
2506
|
...(await createDevScriptRegistry()),
|
|
2246
2507
|
};
|
|
2247
2508
|
// Keep dev action dict in sync with runtime MCP additions. When
|
|
2248
|
-
//
|
|
2249
|
-
// already covers it.
|
|
2509
|
+
// native-actions mode is on (lean or `nativeActionsInDev`), devActions
|
|
2510
|
+
// === prodActions so the prod listener already covers it.
|
|
2250
2511
|
if (devActions !== prodActions) {
|
|
2251
2512
|
mcpManager.onChange(() => {
|
|
2252
2513
|
syncMcpActionEntries(mcpManager, devActions);
|
|
@@ -2255,18 +2516,15 @@ export function createAgentChatPlugin(options) {
|
|
|
2255
2516
|
devHandler = createProductionAgentHandler({
|
|
2256
2517
|
actions: devActions,
|
|
2257
2518
|
systemPrompt: async (event) => {
|
|
2258
|
-
|
|
2259
|
-
const owner = await getOwnerFromEvent(event);
|
|
2260
|
-
_currentRunOwner = owner;
|
|
2261
|
-
const { getOwnerActiveApiKey } = await import("../agent/production-agent.js");
|
|
2262
|
-
_currentRunUserApiKey = await getOwnerActiveApiKey(owner);
|
|
2519
|
+
const { owner, extra } = await prepareRun(event);
|
|
2263
2520
|
if (leanPrompt) {
|
|
2264
|
-
_currentRunSystemPrompt = leanBasePrompt;
|
|
2521
|
+
_currentRunSystemPrompt = leanBasePrompt + extra;
|
|
2265
2522
|
return _currentRunSystemPrompt;
|
|
2266
2523
|
}
|
|
2267
|
-
const resources = await loadResourcesForPrompt(owner);
|
|
2268
|
-
const schemaBlock =
|
|
2269
|
-
|
|
2524
|
+
const resources = await loadResourcesForPrompt(owner, lazyContext);
|
|
2525
|
+
const schemaBlock = lazyContext
|
|
2526
|
+
? ""
|
|
2527
|
+
: await buildSchemaBlock(owner, true);
|
|
2270
2528
|
_currentRunSystemPrompt =
|
|
2271
2529
|
devPrompt + resources + schemaBlock + extra;
|
|
2272
2530
|
return _currentRunSystemPrompt;
|
|
@@ -3130,6 +3388,7 @@ export function createAgentChatPlugin(options) {
|
|
|
3130
3388
|
...templateScripts,
|
|
3131
3389
|
...resourceScripts,
|
|
3132
3390
|
...docsScripts,
|
|
3391
|
+
...(lazyContext ? frameworkContextTool : {}),
|
|
3133
3392
|
...chatScripts,
|
|
3134
3393
|
...jobTools,
|
|
3135
3394
|
...automationTools,
|
|
@@ -3138,8 +3397,10 @@ export function createAgentChatPlugin(options) {
|
|
|
3138
3397
|
...fetchTool,
|
|
3139
3398
|
}),
|
|
3140
3399
|
getSystemPrompt: async (owner) => {
|
|
3141
|
-
const resources = await loadResourcesForPrompt(owner);
|
|
3142
|
-
const schemaBlock =
|
|
3400
|
+
const resources = await loadResourcesForPrompt(owner, lazyContext);
|
|
3401
|
+
const schemaBlock = lazyContext
|
|
3402
|
+
? ""
|
|
3403
|
+
: await buildSchemaBlock(owner, false);
|
|
3143
3404
|
return basePrompt + resources + schemaBlock;
|
|
3144
3405
|
},
|
|
3145
3406
|
apiKey: options?.apiKey ?? process.env.ANTHROPIC_API_KEY,
|
|
@@ -3167,6 +3428,7 @@ export function createAgentChatPlugin(options) {
|
|
|
3167
3428
|
...templateScripts,
|
|
3168
3429
|
...resourceScripts,
|
|
3169
3430
|
...docsScripts,
|
|
3431
|
+
...(lazyContext ? frameworkContextTool : {}),
|
|
3170
3432
|
...chatScripts,
|
|
3171
3433
|
...jobTools,
|
|
3172
3434
|
...automationTools,
|
|
@@ -3175,8 +3437,10 @@ export function createAgentChatPlugin(options) {
|
|
|
3175
3437
|
...fetchTool,
|
|
3176
3438
|
}),
|
|
3177
3439
|
getSystemPrompt: async (owner) => {
|
|
3178
|
-
const resources = await loadResourcesForPrompt(owner);
|
|
3179
|
-
const schemaBlock =
|
|
3440
|
+
const resources = await loadResourcesForPrompt(owner, lazyContext);
|
|
3441
|
+
const schemaBlock = lazyContext
|
|
3442
|
+
? ""
|
|
3443
|
+
: await buildSchemaBlock(owner, false);
|
|
3180
3444
|
return basePrompt + resources + schemaBlock;
|
|
3181
3445
|
},
|
|
3182
3446
|
apiKey: options?.apiKey ?? process.env.ANTHROPIC_API_KEY,
|