@agent-native/core 0.144.3 → 0.145.0
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/corpus/README.md +1 -1
- package/corpus/templates/clips/changelog/2026-08-06-desktop-full-screen-recordings-now-normalize-microphone-leve.md +6 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +185 -69
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +47 -4
- package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/slides/server/plugins/agent-chat.ts +1 -1
- package/dist/agent/production-agent.d.ts +6 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/framework-tools.d.ts +126 -0
- package/dist/framework-tools.js +114 -0
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +4 -4
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/server/action-discovery.d.ts +27 -0
- package/dist/server/action-discovery.js +89 -0
- package/dist/server/agent-chat/action-filters-a2a.d.ts +11 -0
- package/dist/server/agent-chat/action-filters-a2a.js +17 -1
- package/dist/server/agent-chat/framework-prompts.d.ts +2 -0
- package/dist/server/agent-chat/plugin-options.d.ts +30 -0
- package/dist/server/agent-chat/prompt-resources.d.ts +4 -1
- package/dist/server/agent-chat/prompt-resources.js +8 -2
- package/dist/server/agent-chat-plugin.js +122 -71
- package/dist/server/prompts/framework-core-compact.d.ts +5 -0
- package/dist/server/prompts/framework-core-compact.js +28 -12
- package/dist/server/prompts/framework-core.d.ts +5 -0
- package/dist/server/prompts/framework-core.js +33 -16
- package/dist/server/prompts/index.d.ts +1 -1
- package/dist/server/prompts/index.js +1 -1
- package/dist/server/prompts/shared-rules.d.ts +12 -4
- package/dist/server/prompts/shared-rules.js +14 -4
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -3
- package/docs/content/deployment.mdx +47 -13
- package/docs/content/key-concepts.mdx +13 -6
- package/package.json +3 -3
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -3
|
@@ -24,6 +24,7 @@ import { adoptThreadScopeIfUnscoped, createThread, forkThread, getThread, regist
|
|
|
24
24
|
import { isCheckpointRestorePath } from "../checkpoints/route-match.js";
|
|
25
25
|
import { createDbAdminAgentTools } from "../db-admin/agent-tools.js";
|
|
26
26
|
import { isTransientDatabaseError } from "../db/client.js";
|
|
27
|
+
import { filterFrameworkToolGroups, resolveFrameworkTools, } from "../framework-tools.js";
|
|
27
28
|
import { verifyInternalToken, extractBearerToken, } from "../integrations/internal-token.js";
|
|
28
29
|
import { RECURRING_JOBS_SWEEP_PATH, RECURRING_JOBS_SWEEP_TOKEN_SUBJECT, } from "../jobs/scheduler-dispatch.js";
|
|
29
30
|
import { McpClientManager, loadMcpConfig, autoDetectMcpConfig, mcpToolsToActionEntries, syncMcpActionEntries, mountMcpServersRoutes, mountMcpHubRoutes, buildMergedConfig, startMcpConfigRefresh, getHubStatus, isHubServeEnabled, } from "../mcp-client/index.js";
|
|
@@ -277,12 +278,19 @@ export function createAgentChatPlugin(options) {
|
|
|
277
278
|
// `canToggle` means "this environment allows toggling" (static); this
|
|
278
279
|
// function means "the user currently has dev mode ON" (live).
|
|
279
280
|
const isDevMode = () => currentDevMode;
|
|
281
|
+
// Resolve the framework's own tool surface once, folding the deprecated
|
|
282
|
+
// `databaseTools` / `extensionTools` into `frameworkTools` so every
|
|
283
|
+
// consumer below reads a single shape. Conflicting old/new values throw
|
|
284
|
+
// here rather than booting with a surface nobody chose.
|
|
285
|
+
const frameworkTools = resolveFrameworkTools(options);
|
|
286
|
+
const disabledFrameworkGroups = frameworkTools.disabledGroups;
|
|
280
287
|
// Build the four assembled system prompt strings. These are static for the
|
|
281
288
|
// lifetime of this plugin instance — examples come from options once at
|
|
282
289
|
// startup, not per-request.
|
|
283
290
|
const { PROD_FRAMEWORK_PROMPT, DEV_FRAMEWORK_PROMPT, PROD_FRAMEWORK_PROMPT_COMPACT, DEV_FRAMEWORK_PROMPT_COMPACT, } = buildFrameworkPrompts(options?.promptExamples, {
|
|
284
|
-
databaseTools:
|
|
285
|
-
extensionTools:
|
|
291
|
+
databaseTools: frameworkTools.database,
|
|
292
|
+
extensionTools: frameworkTools.extensions,
|
|
293
|
+
disabledFrameworkGroups,
|
|
286
294
|
});
|
|
287
295
|
// Route readiness must not wait on settings scans, remote hub fetches, or
|
|
288
296
|
// third-party MCP handshakes. Build the action surface against an empty
|
|
@@ -397,13 +405,23 @@ export function createAgentChatPlugin(options) {
|
|
|
397
405
|
catch {
|
|
398
406
|
// Package action registration is optional.
|
|
399
407
|
}
|
|
400
|
-
// Resource, chat, docs, db, and cross-agent scripts are available in both
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
408
|
+
// Resource, chat, docs, db, and cross-agent scripts are available in both
|
|
409
|
+
// prod and dev modes, unless the app switched the group off through
|
|
410
|
+
// `frameworkTools`. Gating at construction is deliberate: an empty map
|
|
411
|
+
// flows through all thirteen registry composition sites below, whereas a
|
|
412
|
+
// condition at each spread site is the same omission waiting to happen
|
|
413
|
+
// thirteen times. Matching HTTP routes are mounted from `httpActions`,
|
|
414
|
+
// which is built from the ungated sets so the UI keeps working.
|
|
415
|
+
const resourceScripts = frameworkTools.isEnabled("resources")
|
|
416
|
+
? await createResourceScriptEntries()
|
|
417
|
+
: {};
|
|
418
|
+
const docsScripts = frameworkTools.isEnabled("docs")
|
|
419
|
+
? await createDocsScriptEntries()
|
|
420
|
+
: {};
|
|
421
|
+
const databaseToolsMode = normalizeDatabaseToolsMode(frameworkTools.database);
|
|
404
422
|
const databaseToolsEnabled = databaseToolsMode !== "off";
|
|
405
423
|
const databaseWriteToolsEnabled = databaseToolsMode === "write";
|
|
406
|
-
const extensionToolsEnabled =
|
|
424
|
+
const extensionToolsEnabled = frameworkTools.extensions;
|
|
407
425
|
const dbScripts = databaseToolsEnabled
|
|
408
426
|
? await createDbScriptEntries(databaseToolsMode, {
|
|
409
427
|
extensionTools: extensionToolsEnabled,
|
|
@@ -417,12 +435,20 @@ export function createAgentChatPlugin(options) {
|
|
|
417
435
|
const urlTools = createUrlTools();
|
|
418
436
|
const engineScripts = await createAgentEngineScriptEntries(options?.appId);
|
|
419
437
|
const loopSettingsScripts = await createAgentLoopSettingsScriptEntries();
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
438
|
+
// `httpActions` spreads engineScripts/loopSettingsScripts directly, so
|
|
439
|
+
// gating here removes them from the agent's tools without unmounting the
|
|
440
|
+
// routes the settings UI calls.
|
|
441
|
+
const chatScripts = frameworkTools.isEnabled("chat")
|
|
442
|
+
? {
|
|
443
|
+
...(await createChatScriptEntries()),
|
|
444
|
+
...engineScripts,
|
|
445
|
+
...loopSettingsScripts,
|
|
446
|
+
}
|
|
447
|
+
: {};
|
|
448
|
+
// Both `call-agent` and `describe-workspace-apps` come from this factory.
|
|
449
|
+
const callAgentScript = frameworkTools.isEnabled("workspaceApps")
|
|
450
|
+
? await createCallAgentScriptEntry(options?.appId)
|
|
451
|
+
: {};
|
|
426
452
|
let runNowSchedulerDeps = null;
|
|
427
453
|
const browserTools = createBuilderBrowserTool({
|
|
428
454
|
getOrigin: () => getRequestRunContext()?.requestOrigin ?? "http://localhost:3000",
|
|
@@ -582,7 +608,13 @@ export function createAgentChatPlugin(options) {
|
|
|
582
608
|
// surface, prompt, MCP/A2A list, and job/trigger runner below. The full
|
|
583
609
|
// `*All` sets are reserved for `httpActions`, which keeps agent-hidden
|
|
584
610
|
// actions reachable from the frontend / HTTP.
|
|
585
|
-
|
|
611
|
+
//
|
|
612
|
+
// The framework's own action kits (sharing, review, history, flags, …)
|
|
613
|
+
// arrive in this same registry through `autoDiscoverActions`, tagged with
|
|
614
|
+
// `frameworkGroup`. Subtracting disabled groups HERE is what removes them
|
|
615
|
+
// from every downstream agent surface at once; `httpActions` re-merges
|
|
616
|
+
// them ungated, so the share dialog and review threads keep their routes.
|
|
617
|
+
const templateScripts = filterFrameworkToolGroups(filterAgentTools(templateScriptsAll), disabledFrameworkGroups);
|
|
586
618
|
// Compact is the safe default for every app, including generated and
|
|
587
619
|
// third-party apps that have not curated a starter list yet. Keep the
|
|
588
620
|
// app's own action surface immediately callable; framework, provider,
|
|
@@ -592,7 +624,7 @@ export function createAgentChatPlugin(options) {
|
|
|
592
624
|
// (below, after the run-code tools are built) additionally folds in
|
|
593
625
|
// whatever `generateCorpusToolsPrompt` teaches by name for this request.
|
|
594
626
|
const templateInitialToolNames = resolveInitialToolNames(templateScripts, options?.initialToolNames);
|
|
595
|
-
const discoveredActions = filterAgentTools(discoveredActionsAll);
|
|
627
|
+
const discoveredActions = filterFrameworkToolGroups(filterAgentTools(discoveredActionsAll), disabledFrameworkGroups);
|
|
596
628
|
// Per-request owner is read from the AsyncLocalStorage run context
|
|
597
629
|
// (populated by prepareRun). Module-scope `let` would race across
|
|
598
630
|
// concurrent requests on a long-lived Node process — overlapping
|
|
@@ -628,22 +660,29 @@ export function createAgentChatPlugin(options) {
|
|
|
628
660
|
// Automation tools + fetch tool — depend on owner via callback.
|
|
629
661
|
// Each callback short-circuits with a clear error when the run context
|
|
630
662
|
// has no authenticated owner (see SECURITY note on getCurrentRunOwner).
|
|
663
|
+
const automationGroupEnabled = frameworkTools.isEnabled("automation");
|
|
631
664
|
let automationTools = {};
|
|
632
665
|
try {
|
|
633
|
-
|
|
634
|
-
|
|
666
|
+
if (automationGroupEnabled) {
|
|
667
|
+
const { createAutomationToolEntries } = await import("../triggers/actions.js");
|
|
668
|
+
automationTools = createAutomationToolEntries(() => requireCurrentRunOwner("manage automations"));
|
|
669
|
+
}
|
|
635
670
|
}
|
|
636
671
|
catch { }
|
|
637
672
|
let notificationTools = {};
|
|
638
673
|
try {
|
|
639
|
-
|
|
640
|
-
|
|
674
|
+
if (automationGroupEnabled) {
|
|
675
|
+
const { createNotificationToolEntries } = await import("../notifications/actions.js");
|
|
676
|
+
notificationTools = createNotificationToolEntries(() => requireCurrentRunOwner("manage notifications"));
|
|
677
|
+
}
|
|
641
678
|
}
|
|
642
679
|
catch { }
|
|
643
680
|
let progressTools = {};
|
|
644
681
|
try {
|
|
645
|
-
|
|
646
|
-
|
|
682
|
+
if (automationGroupEnabled) {
|
|
683
|
+
const { createProgressToolEntries } = await import("../progress/actions.js");
|
|
684
|
+
progressTools = createProgressToolEntries(() => requireCurrentRunOwner("manage progress"));
|
|
685
|
+
}
|
|
647
686
|
}
|
|
648
687
|
catch { }
|
|
649
688
|
let githubRepoTools = {};
|
|
@@ -661,48 +700,53 @@ export function createAgentChatPlugin(options) {
|
|
|
661
700
|
});
|
|
662
701
|
}
|
|
663
702
|
catch { }
|
|
703
|
+
const webGroupEnabled = frameworkTools.isEnabled("web");
|
|
664
704
|
let fetchTool = {};
|
|
665
705
|
try {
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
const
|
|
686
|
-
|
|
687
|
-
|
|
706
|
+
if (webGroupEnabled) {
|
|
707
|
+
const { createFetchToolEntry } = await import("../extensions/fetch-tool.js");
|
|
708
|
+
// Resolve `${keys.NAME}` through the same request-scope cascade
|
|
709
|
+
// already used by extension fetches (extensions/routes.ts) and
|
|
710
|
+
// automation connector headers (automation/index.ts): user scope
|
|
711
|
+
// first (personal overrides win), then the active org scope (the
|
|
712
|
+
// Dispatch vault syncs workspace secrets here), then workspace
|
|
713
|
+
// scope. Org/workspace vault rows are write-gated (org-admin +
|
|
714
|
+
// Dispatch vault UI), so this is safe to read by default — unlike
|
|
715
|
+
// the opt-in-only user→workspace fallback in resolveKeyReferences
|
|
716
|
+
// (see audit 05 H2 in secrets/substitution.ts), which stays off.
|
|
717
|
+
// Previously this tool only looked at scope "user", so a
|
|
718
|
+
// ${keys.NAME} reference to a key synced into the org/workspace
|
|
719
|
+
// vault could never resolve here even though the same key already
|
|
720
|
+
// worked for extension fetches and automations.
|
|
721
|
+
const { resolveKeyReferencesWithRequestScopes, validateUrlAllowlist, getKeyAllowlist, getResolvedKeyAllowlist, } = await import("../secrets/substitution.js");
|
|
722
|
+
fetchTool = createFetchToolEntry({
|
|
723
|
+
resolveKeys: async (text) => resolveKeyReferencesWithRequestScopes(text, requireCurrentRunOwner("resolve key references")),
|
|
724
|
+
validateUrl: async (url, usedKeys, resolvedKeys) => {
|
|
725
|
+
for (const keyName of usedKeys) {
|
|
726
|
+
const allowlist = await resolveFetchToolKeyAllowlist(keyName, resolvedKeys, requireCurrentRunOwner("validate URL allowlist"), { getKeyAllowlist, getResolvedKeyAllowlist });
|
|
727
|
+
if (allowlist && !validateUrlAllowlist(url, allowlist)) {
|
|
728
|
+
return false;
|
|
729
|
+
}
|
|
688
730
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
}
|
|
692
|
-
}
|
|
731
|
+
return true;
|
|
732
|
+
},
|
|
733
|
+
});
|
|
734
|
+
}
|
|
693
735
|
}
|
|
694
736
|
catch { }
|
|
695
737
|
let webSearchTool = {};
|
|
696
738
|
try {
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
739
|
+
if (webGroupEnabled) {
|
|
740
|
+
const { createWebSearchToolEntry } = await import("../extensions/web-search-tool.js");
|
|
741
|
+
const { getBuilderWebSearchBaseUrl, resolveBuilderCredentials, resolveSecret, } = await import("./credential-provider.js");
|
|
742
|
+
const { getBuilderGatewayRequestHeaders } = await import("../agent/engine/builder-gateway-headers.js");
|
|
743
|
+
webSearchTool = createWebSearchToolEntry({
|
|
744
|
+
resolveSecret,
|
|
745
|
+
resolveBuilderCredentials,
|
|
746
|
+
getBuilderWebSearchBaseUrl,
|
|
747
|
+
getBuilderRequestHeaders: getBuilderGatewayRequestHeaders,
|
|
748
|
+
});
|
|
749
|
+
}
|
|
706
750
|
}
|
|
707
751
|
catch { }
|
|
708
752
|
let workspaceFilesTool = {};
|
|
@@ -752,11 +796,13 @@ export function createAgentChatPlugin(options) {
|
|
|
752
796
|
let coreEmailTools = {};
|
|
753
797
|
let backgroundCoreEmailTools = {};
|
|
754
798
|
try {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
799
|
+
if (frameworkTools.isEnabled("email")) {
|
|
800
|
+
const { createCoreEmailActionEntries } = await import("./email-actions.js");
|
|
801
|
+
coreEmailTools = createCoreEmailActionEntries();
|
|
802
|
+
backgroundCoreEmailTools = createCoreEmailActionEntries({
|
|
803
|
+
unattended: true,
|
|
804
|
+
});
|
|
805
|
+
}
|
|
760
806
|
}
|
|
761
807
|
catch { }
|
|
762
808
|
// Core read-attachment tool — always registered so the agent can page
|
|
@@ -1233,7 +1279,7 @@ export function createAgentChatPlugin(options) {
|
|
|
1233
1279
|
const devActive = isDevMode();
|
|
1234
1280
|
// Build the same system prompt the interactive agent uses
|
|
1235
1281
|
const owner = userEmail;
|
|
1236
|
-
const resources = await loadResourcesForPrompt(owner, lazyContext, options?.appId);
|
|
1282
|
+
const resources = await loadResourcesForPrompt(owner, lazyContext, options?.appId, undefined, { disabledFrameworkGroups });
|
|
1237
1283
|
const schemaBlock = lazyContext
|
|
1238
1284
|
? ""
|
|
1239
1285
|
: await buildSchemaBlock(owner, databaseToolsMode);
|
|
@@ -1701,7 +1747,7 @@ export function createAgentChatPlugin(options) {
|
|
|
1701
1747
|
// catalog on its very first request, undermining the compact MCP
|
|
1702
1748
|
// catalog this surface is supposed to keep external callers on.
|
|
1703
1749
|
const mcpToolSurface = createA2AEngineToolSurface(actionsToEngineTools(mcpActions), effectiveInitialToolNames);
|
|
1704
|
-
const resources = await loadResourcesForPrompt(SHARED_OWNER, lazyContext, options?.appId);
|
|
1750
|
+
const resources = await loadResourcesForPrompt(SHARED_OWNER, lazyContext, options?.appId, undefined, { disabledFrameworkGroups });
|
|
1705
1751
|
const schemaBlock = lazyContext
|
|
1706
1752
|
? ""
|
|
1707
1753
|
: await buildSchemaBlock(SHARED_OWNER, databaseToolsMode);
|
|
@@ -2156,8 +2202,10 @@ export function createAgentChatPlugin(options) {
|
|
|
2156
2202
|
// Job management tool (manage-jobs)
|
|
2157
2203
|
let jobTools = {};
|
|
2158
2204
|
try {
|
|
2159
|
-
|
|
2160
|
-
|
|
2205
|
+
if (automationGroupEnabled) {
|
|
2206
|
+
const { createJobTools } = await import("../jobs/tools.js");
|
|
2207
|
+
jobTools = createJobTools();
|
|
2208
|
+
}
|
|
2161
2209
|
}
|
|
2162
2210
|
catch { }
|
|
2163
2211
|
// Lean mode: only template actions + essential framework tools. Drop
|
|
@@ -2487,7 +2535,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
2487
2535
|
modelOverlay +
|
|
2488
2536
|
runtimeContext);
|
|
2489
2537
|
}
|
|
2490
|
-
const resources = await loadResourcesForPrompt(owner, lazyContext, options?.appId);
|
|
2538
|
+
const resources = await loadResourcesForPrompt(owner, lazyContext, options?.appId, undefined, { disabledFrameworkGroups });
|
|
2491
2539
|
// In lazy context mode, skip embedding the full schema. When database
|
|
2492
2540
|
// tools are enabled the agent can call `db-schema` on demand.
|
|
2493
2541
|
const schemaBlock = lazyContext
|
|
@@ -2720,7 +2768,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
2720
2768
|
});
|
|
2721
2769
|
return setSystemPromptOnContext(leanBasePrompt + extra + modelOverlay + runtimeContext);
|
|
2722
2770
|
}
|
|
2723
|
-
const resources = await loadResourcesForPrompt(owner, lazyContext, options?.appId);
|
|
2771
|
+
const resources = await loadResourcesForPrompt(owner, lazyContext, options?.appId, undefined, { disabledFrameworkGroups });
|
|
2724
2772
|
const schemaBlock = lazyContext || !databaseToolsEnabled
|
|
2725
2773
|
? ""
|
|
2726
2774
|
: await buildSchemaBlock(owner, databaseToolsMode);
|
|
@@ -4696,7 +4744,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
4696
4744
|
const schedulerDeps = {
|
|
4697
4745
|
getActions: getBackgroundActionEntries,
|
|
4698
4746
|
getSystemPrompt: async (owner) => {
|
|
4699
|
-
const resources = await loadResourcesForPrompt(owner, lazyContext, options?.appId);
|
|
4747
|
+
const resources = await loadResourcesForPrompt(owner, lazyContext, options?.appId, undefined, { disabledFrameworkGroups });
|
|
4700
4748
|
const schemaBlock = lazyContext
|
|
4701
4749
|
? ""
|
|
4702
4750
|
: await buildSchemaBlock(owner, databaseToolsMode);
|
|
@@ -4712,8 +4760,11 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
4712
4760
|
// fetchTool/webSearchTool/toolActions catalog every tick.
|
|
4713
4761
|
getInitialToolNames: (job) => [
|
|
4714
4762
|
...effectiveInitialToolNames,
|
|
4715
|
-
|
|
4716
|
-
|
|
4763
|
+
// Only promotable while the group that supplies them is on; with
|
|
4764
|
+
// `automation` off the prompt no longer names them either.
|
|
4765
|
+
...(automationGroupEnabled
|
|
4766
|
+
? ["manage-jobs", "manage-progress"]
|
|
4767
|
+
: []),
|
|
4717
4768
|
...(job?.meta.mcpTools ?? []),
|
|
4718
4769
|
],
|
|
4719
4770
|
apiKey: options?.apiKey,
|
|
@@ -5073,7 +5124,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
5073
5124
|
await initTriggerDispatcher({
|
|
5074
5125
|
getActions: getBackgroundActionEntries,
|
|
5075
5126
|
getSystemPrompt: async (owner) => {
|
|
5076
|
-
const resources = await loadResourcesForPrompt(owner, lazyContext, options?.appId);
|
|
5127
|
+
const resources = await loadResourcesForPrompt(owner, lazyContext, options?.appId, undefined, { disabledFrameworkGroups });
|
|
5077
5128
|
const schemaBlock = lazyContext
|
|
5078
5129
|
? ""
|
|
5079
5130
|
: await buildSchemaBlock(owner, databaseToolsMode);
|
|
@@ -8,11 +8,16 @@
|
|
|
8
8
|
* - Detailed "Parallel Tool Calls" prose (replaced with one-liner)
|
|
9
9
|
* - Detailed "Resources" section (agent uses resources tool)
|
|
10
10
|
*/
|
|
11
|
+
import { type FrameworkToolGroup } from "../../framework-tools.js";
|
|
11
12
|
import { type DatabaseToolsOption } from "../../scripts/db/tool-mode.js";
|
|
12
13
|
import { type PromptExamples } from "./shared-rules.js";
|
|
13
14
|
export interface FrameworkCoreCompactPromptOptions {
|
|
14
15
|
databaseTools?: DatabaseToolsOption;
|
|
15
16
|
extensionTools?: boolean;
|
|
17
|
+
/** Framework tool groups this app switched off. Every block below that names
|
|
18
|
+
* a group's tool by name is gated on this — a prompt naming an absent tool
|
|
19
|
+
* makes the model call it, fail, and often report the capability as missing. */
|
|
20
|
+
disabledFrameworkGroups?: ReadonlySet<FrameworkToolGroup>;
|
|
16
21
|
}
|
|
17
22
|
/**
|
|
18
23
|
* Build the compact FRAMEWORK_CORE prompt string.
|
|
@@ -8,14 +8,37 @@
|
|
|
8
8
|
* - Detailed "Parallel Tool Calls" prose (replaced with one-liner)
|
|
9
9
|
* - Detailed "Resources" section (agent uses resources tool)
|
|
10
10
|
*/
|
|
11
|
+
import { frameworkGroupEnabled, } from "../../framework-tools.js";
|
|
11
12
|
import { hasDatabaseReadTools, hasDatabaseWriteTools, } from "../../scripts/db/tool-mode.js";
|
|
12
|
-
import { sharedRule8, SHARED_RULE_9,
|
|
13
|
+
import { sharedRule8, SHARED_RULE_9, sharedRule14, SHARED_RULE_15, SHARED_RULE_AGENT_WARNINGS, } from "./shared-rules.js";
|
|
13
14
|
/**
|
|
14
15
|
* Build the compact FRAMEWORK_CORE prompt string.
|
|
15
16
|
*
|
|
16
17
|
* @param examples Optional injectable provider/action examples for rule 8.
|
|
17
18
|
*/
|
|
18
19
|
export function buildFrameworkCoreCompact(examples, options) {
|
|
20
|
+
const groupOn = (group) => frameworkGroupEnabled(options?.disabledFrameworkGroups, group);
|
|
21
|
+
const resourcesSection = groupOn("resources")
|
|
22
|
+
? `### Resources
|
|
23
|
+
|
|
24
|
+
Use the \`resources\` tool for persistent notes and context files: \`action: "list"\`, \`"read"\`, \`"effective"\`, \`"write"\`, \`"promote"\`, or \`"delete"\`.
|
|
25
|
+
Resources have three levels: workspace defaults inherited from Dispatch, shared organization/app overrides, and personal overrides. Use \`resources\` with \`action: "effective"\` before editing when you need to explain or inspect which level is active for a path.
|
|
26
|
+
Workspace resources are user-facing by default. If you need temporary working files, write them as agent scratch (\`visibility: "agent_scratch"\`); scratch is hidden from the Workspace view by default and expires. Use \`visibility: "workspace"\` only when the user explicitly asked to save/manage that file, or for durable AGENTS.md, LEARNINGS.md, memory, skills, jobs, or custom agents.
|
|
27
|
+
`
|
|
28
|
+
: "";
|
|
29
|
+
const extendedCapabilityClauses = [
|
|
30
|
+
"inline embeds",
|
|
31
|
+
groupOn("chat") ? "chat history search (`chat-history`)" : "",
|
|
32
|
+
groupOn("automation") ? "recurring jobs (`manage-jobs`)" : "",
|
|
33
|
+
"structured memory (`save-memory`/`delete-memory`)",
|
|
34
|
+
"browser automation (`activate-browser` in production, `set-browser-control` locally)",
|
|
35
|
+
].filter(Boolean);
|
|
36
|
+
const extendedCapabilitiesList = `${extendedCapabilityClauses.slice(0, -1).join(", ")}, and ${extendedCapabilityClauses.at(-1)}`;
|
|
37
|
+
const callAgentSection = groupOn("workspaceApps")
|
|
38
|
+
? `
|
|
39
|
+
For generated media, prefer this app's native generation action; otherwise use \`call-agent\` with agent "assets".
|
|
40
|
+
`
|
|
41
|
+
: "";
|
|
19
42
|
const hasDatabaseTools = hasDatabaseReadTools(options?.databaseTools);
|
|
20
43
|
const hasDatabaseWrites = hasDatabaseWriteTools(options?.databaseTools);
|
|
21
44
|
const dataRule = hasDatabaseWrites
|
|
@@ -56,22 +79,15 @@ ${SHARED_RULE_9}
|
|
|
56
79
|
**Native widgets** — For table/chart/graph/report requests, prefer actions labeled \`Native chat widget\`; use \`render-data-widget\` for already-summarized data (≤50 rows) instead of markdown tables. Above that, give the total plus the top rows — never retype a full result set as widget arguments. Deliver files in chat, never just a path.
|
|
57
80
|
10. **Your tool list is not the whole surface** — Most app actions and connected MCP tools load on demand, so search the live registry with \`tool-search\` before concluding a capability doesn't exist.
|
|
58
81
|
11. **Relative dates use runtime context** — The \`<runtime-context>\` block gives the authoritative current date/time. Resolve "today", "yesterday", "last week", and similar phrases to explicit calendar dates before querying data or creating artifacts.
|
|
59
|
-
${
|
|
82
|
+
${sharedRule14(options)}
|
|
60
83
|
${SHARED_RULE_15}
|
|
61
84
|
${SHARED_RULE_AGENT_WARNINGS}
|
|
62
85
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Use the \`resources\` tool for persistent notes and context files: \`action: "list"\`, \`"read"\`, \`"effective"\`, \`"write"\`, \`"promote"\`, or \`"delete"\`.
|
|
66
|
-
Resources have three levels: workspace defaults inherited from Dispatch, shared organization/app overrides, and personal overrides. Use \`resources\` with \`action: "effective"\` before editing when you need to explain or inspect which level is active for a path.
|
|
67
|
-
Workspace resources are user-facing by default. If you need temporary working files, write them as agent scratch (\`visibility: "agent_scratch"\`); scratch is hidden from the Workspace view by default and expires. Use \`visibility: "workspace"\` only when the user explicitly asked to save/manage that file, or for durable AGENTS.md, LEARNINGS.md, memory, skills, jobs, or custom agents.
|
|
68
|
-
|
|
86
|
+
${resourcesSection}
|
|
69
87
|
### Extended Capabilities
|
|
70
88
|
|
|
71
|
-
You also have tools for
|
|
89
|
+
You also have tools for ${extendedCapabilitiesList}. Call \`get-framework-context\` with the matching key — it lists its own topics — for full instructions when needed.
|
|
72
90
|
|
|
73
91
|
**Agent teams:** default to doing the work yourself. Delegate ONE sub-agent (\`agent-teams\` action "spawn") for self-contained heavy work; fan out to several only for genuinely independent units; never parallelize tightly-coupled work; cap fan-out around 3. Treat "background agent", "sub-agent", "parallel", "batch", "kick off", "run the rest", and "queued items" as delegation intent when the user is asking you to start or continue independent work items. After \`spawn\`, say the task started/running, not completed; use \`status\`/\`read-result\` before claiming the delegated work is done. Give each sub-agent a self-contained brief (objective, the specific context/IDs it needs, output format, boundaries) — it can't see this thread — then read all results and synthesize one integrated answer. Full details: \`get-framework-context\` key \`agent-teams\`.
|
|
74
|
-
|
|
75
|
-
For generated media, prefer this app's native generation action; otherwise use \`call-agent\` with agent "assets".
|
|
76
|
-
`;
|
|
92
|
+
${callAgentSection}`;
|
|
77
93
|
}
|
|
@@ -5,11 +5,16 @@
|
|
|
5
5
|
* Shared rules (8-9, 12-13) are imported from shared-rules.ts so the
|
|
6
6
|
* compact variant uses the same text and the two can never drift.
|
|
7
7
|
*/
|
|
8
|
+
import { type FrameworkToolGroup } from "../../framework-tools.js";
|
|
8
9
|
import { type DatabaseToolsOption } from "../../scripts/db/tool-mode.js";
|
|
9
10
|
import { type PromptExamples } from "./shared-rules.js";
|
|
10
11
|
export interface FrameworkCorePromptOptions {
|
|
11
12
|
databaseTools?: DatabaseToolsOption;
|
|
12
13
|
extensionTools?: boolean;
|
|
14
|
+
/** Framework tool groups this app switched off. Every block below that names
|
|
15
|
+
* a group's tool by name is gated on this — a prompt naming an absent tool
|
|
16
|
+
* makes the model call it, fail, and often report the capability as missing. */
|
|
17
|
+
disabledFrameworkGroups?: ReadonlySet<FrameworkToolGroup>;
|
|
13
18
|
}
|
|
14
19
|
/**
|
|
15
20
|
* Build the full FRAMEWORK_CORE prompt string.
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* Shared rules (8-9, 12-13) are imported from shared-rules.ts so the
|
|
6
6
|
* compact variant uses the same text and the two can never drift.
|
|
7
7
|
*/
|
|
8
|
+
import { frameworkGroupEnabled, } from "../../framework-tools.js";
|
|
8
9
|
import { hasDatabaseReadTools, hasDatabaseWriteTools, } from "../../scripts/db/tool-mode.js";
|
|
9
|
-
import { sharedRule8, SHARED_RULE_9,
|
|
10
|
+
import { sharedRule8, SHARED_RULE_9, sharedRule14, SHARED_RULE_15, SHARED_RULE_AGENT_WARNINGS, } from "./shared-rules.js";
|
|
10
11
|
/**
|
|
11
12
|
* Build the full FRAMEWORK_CORE prompt string.
|
|
12
13
|
*
|
|
@@ -40,6 +41,33 @@ export function buildFrameworkCore(examples, options) {
|
|
|
40
41
|
const actionSurface = options?.extensionTools === true
|
|
41
42
|
? "this app's registered actions, extensions, and connected MCP tools"
|
|
42
43
|
: "this app's registered actions and connected MCP tools";
|
|
44
|
+
const groupOn = (group) => frameworkGroupEnabled(options?.disabledFrameworkGroups, group);
|
|
45
|
+
const resourcesSection = groupOn("resources")
|
|
46
|
+
? `### Resources
|
|
47
|
+
|
|
48
|
+
You have access to a Resources system for persistent notes and context files.
|
|
49
|
+
Use the \`resources\` tool to manage resources: \`action: "list"\`, \`"read"\`, \`"effective"\`, \`"write"\`, \`"promote"\`, or \`"delete"\`.
|
|
50
|
+
Resources can be workspace defaults inherited from Dispatch, shared organization/app overrides, or personal overrides. By default, resources are personal. Workspace-scope resources are read-only from app agents; create shared or personal resources to override or narrow them.
|
|
51
|
+
|
|
52
|
+
When the user gives instructions that should apply to all users/sessions, update the shared "AGENTS.md" resource.
|
|
53
|
+
|
|
54
|
+
Workspace resources are user-facing by default. If you need temporary working files, use the \`resources\` tool with \`visibility: "agent_scratch"\`; scratch resources are hidden from the Workspace view by default and expire automatically. Use \`visibility: "workspace"\` only when the user explicitly asked to save/create/manage that file, or for durable control files such as \`AGENTS.md\`, \`LEARNINGS.md\`, \`memory/\`, \`skills/\`, \`jobs/\`, or \`agents/\`. If a scratch result becomes useful to the user, call \`resources\` with \`action: "promote"\` or rewrite it with \`visibility: "workspace"\`.
|
|
55
|
+
`
|
|
56
|
+
: "";
|
|
57
|
+
const extendedCapabilityClauses = [
|
|
58
|
+
"inline embeds (`embed` fenced code block)",
|
|
59
|
+
groupOn("chat") ? "chat history search (`chat-history`)" : "",
|
|
60
|
+
groupOn("automation") ? "recurring jobs (`manage-jobs`)" : "",
|
|
61
|
+
"connecting Builder.io (`connect-builder`)",
|
|
62
|
+
"browser automation (`set-browser-control`/`activate-browser`)",
|
|
63
|
+
"structured memory (`save-memory`/`delete-memory`)",
|
|
64
|
+
].filter(Boolean);
|
|
65
|
+
const extendedCapabilitiesList = `${extendedCapabilityClauses.slice(0, -1).join(", ")}, and ${extendedCapabilityClauses.at(-1)}`;
|
|
66
|
+
const callAgentSection = groupOn("workspaceApps")
|
|
67
|
+
? `
|
|
68
|
+
**call-agent** messages a DIFFERENT deployed app's agent over A2A — never use it for your own actions or to call yourself. For brand-consistent generated media when this app has no native generation action, call agent "assets".
|
|
69
|
+
`
|
|
70
|
+
: "";
|
|
43
71
|
return `
|
|
44
72
|
### How You Work
|
|
45
73
|
|
|
@@ -78,7 +106,7 @@ ${SHARED_RULE_9}
|
|
|
78
106
|
**Downloadable files** — When the user asks you to create or export a file, deliver it in the same chat turn. For compact tabular results, prefer \`render-data-widget\` so the user gets the native Download CSV action without a second stored copy. For a complete or durable file written through \`workspaceWrite\`, use a normal non-\`scratch/\` path and then call \`show-workspace-file\` with that path so chat renders a direct download card. Never finish by giving filesystem paths or telling the user to navigate elsewhere to find the file.
|
|
79
107
|
10. **Your tool list is not the whole surface** — Most app actions and connected MCP tools load on demand, so search the live registry with \`tool-search\` before concluding a capability doesn't exist.
|
|
80
108
|
11. **Relative dates use runtime context** — The \`<runtime-context>\` block gives the authoritative current date/time. Resolve "today", "yesterday", "last week", and similar phrases to explicit calendar dates before querying data or creating artifacts. When answering factual questions, include the exact date or date range you used.
|
|
81
|
-
${
|
|
109
|
+
${sharedRule14(options)}
|
|
82
110
|
${SHARED_RULE_15}
|
|
83
111
|
${SHARED_RULE_AGENT_WARNINGS}
|
|
84
112
|
|
|
@@ -86,22 +114,11 @@ ${SHARED_RULE_AGENT_WARNINGS}
|
|
|
86
114
|
|
|
87
115
|
Gather context efficiently: when you need several independent read-only lookups (reading state, querying different tables, searching, fetching unrelated records), issue those tool calls together in one batch rather than one at a time. Keep mutating actions ordered and sequential — anything that creates, updates, deletes, sends, or publishes runs one at a time so each can be confirmed before the next, and so writes that depend on each other stay consistent.
|
|
88
116
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
You have access to a Resources system for persistent notes and context files.
|
|
92
|
-
Use the \`resources\` tool to manage resources: \`action: "list"\`, \`"read"\`, \`"effective"\`, \`"write"\`, \`"promote"\`, or \`"delete"\`.
|
|
93
|
-
Resources can be workspace defaults inherited from Dispatch, shared organization/app overrides, or personal overrides. By default, resources are personal. Workspace-scope resources are read-only from app agents; create shared or personal resources to override or narrow them.
|
|
94
|
-
|
|
95
|
-
When the user gives instructions that should apply to all users/sessions, update the shared "AGENTS.md" resource.
|
|
96
|
-
|
|
97
|
-
Workspace resources are user-facing by default. If you need temporary working files, use the \`resources\` tool with \`visibility: "agent_scratch"\`; scratch resources are hidden from the Workspace view by default and expire automatically. Use \`visibility: "workspace"\` only when the user explicitly asked to save/create/manage that file, or for durable control files such as \`AGENTS.md\`, \`LEARNINGS.md\`, \`memory/\`, \`skills/\`, \`jobs/\`, or \`agents/\`. If a scratch result becomes useful to the user, call \`resources\` with \`action: "promote"\` or rewrite it with \`visibility: "workspace"\`.
|
|
98
|
-
|
|
117
|
+
${resourcesSection}
|
|
99
118
|
### Extended Capabilities
|
|
100
119
|
|
|
101
|
-
You also have tools for
|
|
120
|
+
You also have tools for ${extendedCapabilitiesList}. Call \`get-framework-context\` with the matching key — it lists its own topics — for full instructions before non-trivial work in any of these areas.
|
|
102
121
|
|
|
103
122
|
**Agent teams:** default to doing the work yourself in this thread, but treat "background agent", "sub-agent", "parallel", "batch", "kick off", "run the rest", and "queued items" as delegation intent when the user is asking you to start or continue independent work items. Delegate ONE sub-agent for self-contained heavy work (deep research, long multi-step generation, noisy scans); fan out to MULTIPLE only for genuinely independent units; never parallelize tightly-coupled work; cap fan-out around 3. After \`spawn\`, say the task started/running, not completed; use \`status\`/\`read-result\` before claiming delegated work is done. Give every sub-agent a self-contained brief (objective, the specific context/IDs it needs, output format, boundaries), then read all results and synthesize one integrated answer. Full details: \`get-framework-context\` key \`agent-teams\`.
|
|
104
|
-
|
|
105
|
-
**call-agent** messages a DIFFERENT deployed app's agent over A2A — never use it for your own actions or to call yourself. For brand-consistent generated media when this app has no native generation action, call agent "assets".
|
|
106
|
-
`;
|
|
123
|
+
${callAgentSection}`;
|
|
107
124
|
}
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { buildFrameworkCore } from "./framework-core.js";
|
|
6
6
|
export { buildFrameworkCoreCompact } from "./framework-core-compact.js";
|
|
7
|
-
export { sharedRule8, SHARED_RULE_9,
|
|
7
|
+
export { sharedRule8, SHARED_RULE_9, sharedRule14, SHARED_RULE_15, type PromptExamples, type SharedRuleOptions, } from "./shared-rules.js";
|
|
8
8
|
export { getModelFamilyOverlay } from "./model-overlays.js";
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { buildFrameworkCore } from "./framework-core.js";
|
|
6
6
|
export { buildFrameworkCoreCompact } from "./framework-core-compact.js";
|
|
7
|
-
export { sharedRule8, SHARED_RULE_9,
|
|
7
|
+
export { sharedRule8, SHARED_RULE_9, sharedRule14, SHARED_RULE_15, } from "./shared-rules.js";
|
|
8
8
|
export { getModelFamilyOverlay } from "./model-overlays.js";
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* rule) and 12–13 (planning discipline; collaborate through uncertainty) are
|
|
8
8
|
* reproduced verbatim in both prompts — keep them here.
|
|
9
9
|
*/
|
|
10
|
+
import { type FrameworkToolGroup } from "../../framework-tools.js";
|
|
10
11
|
import { type DatabaseToolsOption } from "../../scripts/db/tool-mode.js";
|
|
11
12
|
/**
|
|
12
13
|
* Injectable provider/action examples. Defaults are generic; templates that
|
|
@@ -21,6 +22,9 @@ export interface PromptExamples {
|
|
|
21
22
|
export interface SharedRuleOptions {
|
|
22
23
|
databaseTools?: DatabaseToolsOption;
|
|
23
24
|
extensionTools?: boolean;
|
|
25
|
+
/** Framework tool groups this app switched off. Any rule naming a group's
|
|
26
|
+
* tool must drop that reference — see `frameworkGroupEnabled`. */
|
|
27
|
+
disabledFrameworkGroups?: ReadonlySet<FrameworkToolGroup>;
|
|
24
28
|
}
|
|
25
29
|
/** Rule 8 — db-* tools are internal only (shared between full and compact). */
|
|
26
30
|
export declare function sharedRule8(examples?: PromptExamples, options?: SharedRuleOptions): string;
|
|
@@ -34,14 +38,18 @@ export declare function sharedRule8(examples?: PromptExamples, options?: SharedR
|
|
|
34
38
|
*/
|
|
35
39
|
export declare const SHARED_RULE_9 = "9. **Never fabricate \u2014 verify results, report failures honestly, and recover instead of giving up.**\n - **Never fabricate factual claims or records** \u2014 do not invent numbers, metrics, records, query results, URLs, citations, source attributions, customer names, dates, or success rates. This applies inside generated artifacts too: decks, documents, reports, dashboards, Slack/email replies, and charts. Only state factual numbers/claims the user provided or you retrieved with an action/tool. If a data source is unavailable, returns no rows, is missing credentials, or has a connection error, say so clearly; do not create placeholder rows or fetch unrelated providers to look complete unless the user explicitly asked you to import/sync/backfill. Prefer qualitative wording, placeholders like `[metric TBD]`, or clearly labeled draft assumptions over plausible-looking facts \u2014 presenting made-up data as real is worse than admitting the limitation.\n - **Never fabricate success from tool errors** \u2014 when a tool call returns an error (marked `isError: true`, contains \"Command failed\", \"Error:\", or non-zero exit output), the operation FAILED; do not synthesize a success narrative or describe what it \"would have\" produced. Report the failure verbatim (this applies especially to `bash(command=\"pnpm action ...\")` calls). Before telling the user a mutating action (create/update/delete/send/publish) is done, confirm it actually landed \u2014 check the tool result, or read the refreshed `<current-screen>` / re-query the data; having *called* an action is not proof it worked. If a result is ambiguous, check rather than assume.\n - **Recover instead of giving up** \u2014 treat a failure or ambiguous result as a signal to retry the obvious fix, try an alternate tool or approach, or clearly hand the blocker back with what you tried; never silently give up, and never paper over a failure by claiming success.";
|
|
36
40
|
/**
|
|
37
|
-
* Rule 12 (
|
|
38
|
-
*
|
|
39
|
-
*
|
|
41
|
+
* Rule 12 (name retained as `sharedRule14` for import stability) — Planning and
|
|
42
|
+
* progress. Deliberately states only when to open a progress run; the
|
|
43
|
+
* start/update/complete discipline lives in `manage-progress`'s own tool
|
|
40
44
|
* description (packages/core/src/progress/actions.ts). Re-adding the mechanics
|
|
41
45
|
* here means every turn pays for guidance the model only needs once it has the
|
|
42
46
|
* tool loaded.
|
|
47
|
+
*
|
|
48
|
+
* Drops the `manage-progress` reference when the `automation` group is off, so
|
|
49
|
+
* the rule never names a tool the request does not carry. The planning
|
|
50
|
+
* discipline itself still applies — only the tool call goes away.
|
|
43
51
|
*/
|
|
44
|
-
export declare
|
|
52
|
+
export declare function sharedRule14(options?: SharedRuleOptions): string;
|
|
45
53
|
/**
|
|
46
54
|
* Rule 14 — Relay agent warnings. Named for what it is rather than its number,
|
|
47
55
|
* since the `SHARED_RULE_14`/`15` names above no longer match theirs.
|