@agent-native/core 0.147.0 → 0.148.1
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/analytics/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/analytics/DEVELOPING.md +50 -3
- package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +190 -0
- package/corpus/templates/analytics/app/i18n/index.ts +14 -29
- package/corpus/templates/analytics/app/i18n-data.ts +10 -10
- package/corpus/templates/analytics/app/pages/Settings.tsx +5 -21
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -3
- package/corpus/templates/analytics/scripts/first-party-analytics-bigquery-backfill.ts +197 -18
- package/corpus/templates/analytics/server/db/schema.ts +23 -0
- package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +3 -1
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +1 -1
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +113 -13
- package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +140 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-volume.ts +207 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +40 -9
- package/corpus/templates/analytics/server/lib/gcloud.ts +148 -20
- package/corpus/templates/analytics/server/plugins/db.ts +42 -0
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/assets/app/i18n/index.ts +14 -29
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/brain/app/i18n/index.ts +14 -29
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/chat/app/i18n/index.ts +14 -29
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -7
- package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +18 -13
- package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +87 -370
- package/corpus/templates/clips/app/components/settings/slack-section.tsx +59 -101
- package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +136 -213
- package/corpus/templates/clips/app/i18n/en-US.ts +11 -8
- package/corpus/templates/clips/desktop/src/app.tsx +1 -1
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/content/app/i18n/index.ts +14 -29
- package/corpus/templates/crm/app/i18n/index.ts +14 -29
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/design/actions/analyze-brand-assets.ts +15 -15
- package/corpus/templates/design/actions/import-code.ts +2 -43
- package/corpus/templates/design/app/i18n/index.ts +14 -29
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/dispatch/app/i18n-data.ts +1 -1
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/factory/AGENTS.md +40 -49
- package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +66 -0
- package/corpus/templates/factory/actions/evaluate-triage-item.ts +37 -0
- package/corpus/templates/factory/actions/get-slack-feedback-context.ts +20 -0
- package/corpus/templates/factory/actions/get-triage-item.ts +25 -4
- package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +55 -0
- package/corpus/templates/factory/actions/ingest-github-observation.ts +21 -0
- package/corpus/templates/factory/actions/list-factory-audit.ts +118 -0
- package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
- package/corpus/templates/factory/actions/list-triage-items.ts +24 -2
- package/corpus/templates/factory/actions/poll-github-sources.ts +60 -0
- package/corpus/templates/factory/actions/poll-sentry-errors.ts +39 -0
- package/corpus/templates/factory/actions/poll-slack-channel.ts +45 -1
- package/corpus/templates/factory/actions/run-factory-automation.ts +1 -1
- package/corpus/templates/factory/actions/save-factory-automation.ts +2 -2
- package/corpus/templates/factory/actions/start-builder-for-item.ts +51 -0
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +685 -0
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +6 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +25 -0
- package/corpus/templates/factory/app/routes/factory.tsx +95 -42
- package/corpus/templates/factory/server/db/schema.ts +37 -0
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +5 -1
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +29 -0
- package/corpus/templates/factory/server/triage/audit.ts +79 -0
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/forms/app/i18n/index.ts +14 -29
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/macros/app/i18n/index.ts +14 -29
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/mail/app/i18n/index.ts +14 -29
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +7 -7
- package/corpus/templates/plan/app/i18n/index.ts +14 -29
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/slides/actions/analyze-brand-assets.ts +15 -15
- package/corpus/templates/slides/actions/import-code.ts +2 -43
- package/corpus/templates/slides/app/i18n/index.ts +14 -29
- package/corpus/templates/slides/server/routes/api/preview-images.get.ts +4 -1
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/tasks/app/components/layout/HeaderActions.tsx +1 -84
- package/corpus/templates/tasks/app/hooks/use-mobile.tsx +1 -21
- package/corpus/templates/tasks/app/i18n/index.ts +14 -29
- package/dist/agent/engine/ai-sdk-engine.js +2 -1
- package/dist/agent/engine/openai-compatible-endpoint.d.ts +2 -0
- package/dist/agent/engine/openai-compatible-endpoint.js +5 -1
- package/dist/agent/engine/provider-endpoint-validation.d.ts +9 -0
- package/dist/agent/engine/provider-endpoint-validation.js +26 -0
- package/dist/agent/engine/provider-env-vars.d.ts +1 -1
- package/dist/agent/engine/provider-env-vars.js +1 -1
- package/dist/agent/engine/registry.d.ts +8 -6
- package/dist/agent/engine/registry.js +37 -24
- package/dist/agent/tool-search.d.ts +1 -0
- package/dist/agent/tool-search.js +17 -1
- package/dist/automations/service.js +4 -10
- package/dist/brand-kit/brand-signals.d.ts +13 -0
- package/dist/brand-kit/brand-signals.js +15 -0
- package/dist/brand-kit/index.d.ts +2 -2
- package/dist/brand-kit/index.js +1 -1
- package/dist/cli/plan-blocks.d.ts +3 -18
- package/dist/cli/plan-blocks.js +2 -95
- package/dist/cli/plan-publish-store.d.ts +2 -61
- package/dist/cli/plan-publish-store.js +2 -127
- package/dist/cli/skills-content/connection.d.ts +1 -1
- package/dist/cli/skills-content/connection.js +1 -52
- package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
- package/dist/cli/skills-content/visual-recap-skill.js +1 -553
- package/dist/client/agent-engine-key.d.ts +14 -4
- package/dist/client/agent-engine-key.js +51 -5
- package/dist/client/agent-provider-catalog.d.ts +20 -0
- package/dist/client/agent-provider-catalog.js +100 -0
- package/dist/client/blocks/index.d.ts +1 -0
- package/dist/client/blocks/index.js +1 -0
- package/dist/client/blocks/library/diagram.js +1 -1
- package/dist/client/blocks/library/sanitize-html.js +66 -2
- package/dist/client/blocks/library/wireframe-kit.js +69 -0
- package/dist/client/chat/run-recovery.js +4 -48
- package/dist/client/chat-first/apps-rail.d.ts +1 -1
- package/dist/client/chat-first/apps-rail.js +4 -4
- package/dist/client/chat-first/copy.js +1 -0
- package/dist/client/chat-first/types.d.ts +1 -0
- package/dist/client/chat-first.js +4 -3
- package/dist/client/i18n.d.ts +14 -0
- package/dist/client/i18n.js +18 -0
- package/dist/client/settings/ProviderSetupForm.d.ts +21 -0
- package/dist/client/settings/ProviderSetupForm.js +145 -0
- package/dist/client/settings/SettingsPanel.js +52 -49
- package/dist/client/settings/index.d.ts +2 -0
- package/dist/client/settings/index.js +2 -0
- package/dist/coding-tools/run-code.d.ts +5 -0
- package/dist/coding-tools/run-code.js +196 -36
- package/dist/coding-tools/tool-orchestration.d.ts +10 -0
- package/dist/coding-tools/tool-orchestration.js +107 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/jobs/frontmatter.d.ts +9 -0
- package/dist/jobs/frontmatter.js +16 -0
- package/dist/jobs/scheduler.js +8 -8
- package/dist/jobs/tools.d.ts +1 -1
- package/dist/jobs/tools.js +2 -7
- package/dist/localization/default-messages.d.ts +20 -0
- package/dist/localization/default-messages.js +25 -5
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +2 -2
- package/dist/onboarding/app-profile.js +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/scripts/agent-engines/test-agent-engine.js +34 -10
- package/dist/server/agent-chat/run-code-tools.d.ts +1 -1
- package/dist/server/agent-chat/run-code-tools.js +3 -1
- package/dist/server/agent-chat-plugin.js +6 -6
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.js +43 -12
- package/dist/server/agents-bundle.js +2 -1
- package/dist/server/auth.js +21 -5
- package/dist/server/credential-provider.js +1 -0
- package/dist/server/design-token-utils.d.ts +18 -0
- package/dist/server/design-token-utils.js +31 -0
- package/dist/server/onboarding-html.js +22 -2
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/styles/blocks.css +132 -0
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/templates/chat/app/i18n/index.ts +14 -29
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/templates/default/app/i18n/index.ts +14 -29
- package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/triggers/dispatcher.js +1 -8
- package/docs/content/actions.mdx +4 -1
- package/docs/content/agent-surfaces.mdx +8 -6
- package/docs/content/automations.mdx +1 -1
- package/docs/content/database.mdx +6 -1
- package/docs/content/docs-components.mdx +22 -14
- package/docs/content/drop-in-agent.mdx +1 -1
- package/docs/content/environment-variables.mdx +39 -38
- package/docs/content/getting-started-actions.mdx +5 -4
- package/docs/content/getting-started-pages.mdx +7 -6
- package/docs/content/getting-started.mdx +4 -3
- package/docs/content/notifications.mdx +6 -6
- package/docs/content/progress.mdx +5 -5
- package/docs/content/routing.mdx +3 -1
- package/docs/content/server-database.mdx +13 -4
- package/docs/content/server-overview.mdx +9 -9
- package/docs/content/server-plugins.mdx +10 -4
- package/docs/content/server-routes.mdx +7 -2
- package/docs/content/tracking.mdx +4 -4
- package/docs/content/what-is-agent-native.mdx +4 -4
- package/package.json +4 -4
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/src/templates/chat/app/i18n/index.ts +14 -29
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
- package/src/templates/default/app/i18n/index.ts +14 -29
- package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/plan/app/components/plan/wireframe/sanitize-html.ts +0 -343
|
@@ -37,6 +37,9 @@ const DEFAULT_TIMEOUT_MS = 120_000;
|
|
|
37
37
|
const MAX_TIMEOUT_MS = 600_000;
|
|
38
38
|
const DEFAULT_MAX_OUTPUT_CHARS = 50_000;
|
|
39
39
|
const MAX_OUTPUT_CHARS = 200_000;
|
|
40
|
+
const TOOL_ORCHESTRATION_DEFAULT_MAX_CALLS = 32;
|
|
41
|
+
const TOOL_ORCHESTRATION_MAX_CALLS = 128;
|
|
42
|
+
const TOOL_ORCHESTRATION_MAX_PROVIDER_PAGES = 20;
|
|
40
43
|
/** Hard cap on bridge request bodies so sandboxed code can't exhaust parent memory. */
|
|
41
44
|
const BRIDGE_MAX_BODY_BYTES = 10 * 1024 * 1024;
|
|
42
45
|
/** Tools callable via the sandbox bridge by default. */
|
|
@@ -203,8 +206,9 @@ export function createRunCodeEntry(getActions, opts = {}) {
|
|
|
203
206
|
export async function executeSandboxCode(options) {
|
|
204
207
|
const actions = options.getActions();
|
|
205
208
|
const bridgeToken = crypto.randomBytes(32).toString("hex");
|
|
209
|
+
const mode = options.mode ?? "run-code";
|
|
206
210
|
// Start bridge server — resolves once the server is listening.
|
|
207
|
-
const { bridgePort, getUsedTools, cleanup: cleanupBridge, } = await startBridgeServer(bridgeToken, actions, options.context, DEFAULT_BRIDGE_TOOLS, options.extraBridgeTools ?? new Set());
|
|
211
|
+
const { bridgePort, getUsedTools, cleanup: cleanupBridge, } = await startBridgeServer(bridgeToken, actions, options.context, DEFAULT_BRIDGE_TOOLS, options.extraBridgeTools ?? new Set(), mode, options.maxToolCalls);
|
|
208
212
|
try {
|
|
209
213
|
// Build scrubbed env — only safe POSIX vars, no secrets. The adapter
|
|
210
214
|
// points TMPDIR/TEMP/TMP at the sandbox's own temp dir.
|
|
@@ -228,7 +232,7 @@ export async function executeSandboxCode(options) {
|
|
|
228
232
|
// bridge, env scrub, module, and output formatting stay in the parent
|
|
229
233
|
// regardless of adapter.
|
|
230
234
|
const { stdout, stderr, exitCode, timedOut } = await resolveExecutionSandboxAdapter().run({
|
|
231
|
-
moduleSource: buildSandboxModule(options.code, bridgePort, bridgeToken),
|
|
235
|
+
moduleSource: buildSandboxModule(options.code, bridgePort, bridgeToken, mode),
|
|
232
236
|
env: safeEnv,
|
|
233
237
|
timeoutMs: options.timeoutMs,
|
|
234
238
|
bridgePort,
|
|
@@ -457,8 +461,14 @@ export function createGetCodeExecutionEntry() {
|
|
|
457
461
|
},
|
|
458
462
|
};
|
|
459
463
|
}
|
|
460
|
-
async function startBridgeServer(token, actions, context, defaultTools, extraTools) {
|
|
464
|
+
async function startBridgeServer(token, actions, context, defaultTools, extraTools, mode, maxToolCalls) {
|
|
461
465
|
const usedTools = new Set();
|
|
466
|
+
const callBudget = mode === "tool-orchestration"
|
|
467
|
+
? {
|
|
468
|
+
count: 0,
|
|
469
|
+
max: normalizeToolCallBudget(maxToolCalls),
|
|
470
|
+
}
|
|
471
|
+
: undefined;
|
|
462
472
|
const server = http.createServer((req, res) => {
|
|
463
473
|
if (req.method !== "POST" || req.url !== "/tool") {
|
|
464
474
|
res.writeHead(404);
|
|
@@ -489,7 +499,7 @@ async function startBridgeServer(token, actions, context, defaultTools, extraToo
|
|
|
489
499
|
req.on("end", () => {
|
|
490
500
|
if (rejected)
|
|
491
501
|
return;
|
|
492
|
-
handleBridgeRequest(body, actions, context, defaultTools, extraTools, usedTools, res);
|
|
502
|
+
handleBridgeRequest(body, actions, context, defaultTools, extraTools, usedTools, mode, callBudget, res);
|
|
493
503
|
});
|
|
494
504
|
req.on("error", () => {
|
|
495
505
|
res.writeHead(500);
|
|
@@ -515,7 +525,7 @@ async function startBridgeServer(token, actions, context, defaultTools, extraToo
|
|
|
515
525
|
cleanup,
|
|
516
526
|
};
|
|
517
527
|
}
|
|
518
|
-
function handleBridgeRequest(rawBody, actions, context, defaultTools, extraTools, usedTools, res) {
|
|
528
|
+
function handleBridgeRequest(rawBody, actions, context, defaultTools, extraTools, usedTools, mode, callBudget, res) {
|
|
519
529
|
let parsed;
|
|
520
530
|
try {
|
|
521
531
|
parsed = JSON.parse(rawBody);
|
|
@@ -546,7 +556,27 @@ function handleBridgeRequest(rawBody, actions, context, defaultTools, extraTools
|
|
|
546
556
|
const isReadOnlyAction = entry.readOnly === true &&
|
|
547
557
|
entry.agentTool !== false &&
|
|
548
558
|
entry.toolCallable !== false;
|
|
549
|
-
|
|
559
|
+
const toolArgs = parsed.args ?? {};
|
|
560
|
+
const childArgs = mode === "tool-orchestration"
|
|
561
|
+
? boundToolOrchestrationArgs(toolName, toolArgs)
|
|
562
|
+
: toolArgs;
|
|
563
|
+
if (mode === "tool-orchestration") {
|
|
564
|
+
if (callBudget && callBudget.count >= callBudget.max) {
|
|
565
|
+
res.writeHead(429, { "Content-Type": "application/json" });
|
|
566
|
+
res.end(JSON.stringify({
|
|
567
|
+
error: `Tool-orchestration child-call budget exceeded (${callBudget.max}). Aggregate the current results or increase maxToolCalls within its limit.`,
|
|
568
|
+
}));
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
if (!isAllowedToolOrchestrationCall(toolName, childArgs, entry)) {
|
|
572
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
573
|
+
res.end(JSON.stringify({
|
|
574
|
+
error: `Tool "${toolName}" is not permitted by tool-orchestration. Only read-only tools and GET/HEAD provider or web reads without staging or saving files are allowed; call mutating tools directly.`,
|
|
575
|
+
}));
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
else if (!defaultTools.has(toolName) &&
|
|
550
580
|
!extraTools.has(toolName) &&
|
|
551
581
|
!isReadOnlyAction) {
|
|
552
582
|
// A registered, agent-exposed action that isn't read-only is a mutation.
|
|
@@ -563,12 +593,13 @@ function handleBridgeRequest(rawBody, actions, context, defaultTools, extraTools
|
|
|
563
593
|
}));
|
|
564
594
|
return;
|
|
565
595
|
}
|
|
566
|
-
|
|
596
|
+
if (callBudget)
|
|
597
|
+
callBudget.count += 1;
|
|
567
598
|
usedTools.add(toolName);
|
|
568
599
|
// Run the tool with the parent request context so auth/org/owner resolution
|
|
569
600
|
// works exactly as it does in the normal agent loop.
|
|
570
601
|
entry
|
|
571
|
-
.run(
|
|
602
|
+
.run(childArgs, context)
|
|
572
603
|
.then((result) => {
|
|
573
604
|
const body = typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
574
605
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
@@ -580,6 +611,105 @@ function handleBridgeRequest(rawBody, actions, context, defaultTools, extraTools
|
|
|
580
611
|
res.end(JSON.stringify({ error: message }));
|
|
581
612
|
});
|
|
582
613
|
}
|
|
614
|
+
function normalizeToolCallBudget(value) {
|
|
615
|
+
if (!Number.isFinite(value) || !value || value <= 0) {
|
|
616
|
+
return TOOL_ORCHESTRATION_DEFAULT_MAX_CALLS;
|
|
617
|
+
}
|
|
618
|
+
return Math.min(Math.floor(value), TOOL_ORCHESTRATION_MAX_CALLS);
|
|
619
|
+
}
|
|
620
|
+
function isAllowedToolOrchestrationCall(toolName, args, entry) {
|
|
621
|
+
if (toolName === "workspace-files") {
|
|
622
|
+
// This is an internal bridge action by design, so agentTool/toolCallable
|
|
623
|
+
// are intentionally not required here. Its operation enum is the policy
|
|
624
|
+
// boundary for the read-only workspace surface.
|
|
625
|
+
return isCallableWithoutApproval(entry) && isReadOnlyWorkspaceRequest(args);
|
|
626
|
+
}
|
|
627
|
+
if (toolName === "provider-api-request") {
|
|
628
|
+
return isReadOnlyProviderApiRequest(args, entry);
|
|
629
|
+
}
|
|
630
|
+
return isReadOnlyOrchestrationAction(args, entry);
|
|
631
|
+
}
|
|
632
|
+
function isCallableWithoutApproval(entry) {
|
|
633
|
+
// The bridge calls ActionEntry.run directly for child reads. A predicate
|
|
634
|
+
// approval gate must therefore fail closed rather than being silently
|
|
635
|
+
// bypassed by this bounded path.
|
|
636
|
+
return entry.needsApproval === undefined || entry.needsApproval === false;
|
|
637
|
+
}
|
|
638
|
+
function isReadOnlyWorkspaceRequest(args) {
|
|
639
|
+
const action = typeof args.action === "string" ? args.action : "";
|
|
640
|
+
return action === "read" || action === "list" || action === "grep";
|
|
641
|
+
}
|
|
642
|
+
function isReadOnlyProviderApiRequest(args, entry) {
|
|
643
|
+
if (!entry.tool ||
|
|
644
|
+
!isCallableWithoutApproval(entry) ||
|
|
645
|
+
entry.agentTool === false ||
|
|
646
|
+
entry.allowInPlanMode === false) {
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
const method = String(args.method ?? "GET").toUpperCase();
|
|
650
|
+
return ((method === "GET" || method === "HEAD") &&
|
|
651
|
+
args.stageAs == null &&
|
|
652
|
+
args.saveToFile == null);
|
|
653
|
+
}
|
|
654
|
+
function isReadOnlyOrchestrationAction(args, entry) {
|
|
655
|
+
if (!entry.tool ||
|
|
656
|
+
!isCallableWithoutApproval(entry) ||
|
|
657
|
+
entry.agentTool === false ||
|
|
658
|
+
entry.toolCallable === false ||
|
|
659
|
+
entry.allowInPlanMode === false) {
|
|
660
|
+
return false;
|
|
661
|
+
}
|
|
662
|
+
const planMode = entry.planMode;
|
|
663
|
+
if (!planMode)
|
|
664
|
+
return entry.readOnly === true;
|
|
665
|
+
const input = args;
|
|
666
|
+
if (planMode.allowedProperties &&
|
|
667
|
+
Object.keys(args).some((key) => !planMode.allowedProperties.includes(key))) {
|
|
668
|
+
return false;
|
|
669
|
+
}
|
|
670
|
+
if (planMode.omittedProperties?.some((key) => Object.prototype.hasOwnProperty.call(args, key))) {
|
|
671
|
+
return false;
|
|
672
|
+
}
|
|
673
|
+
if (Object.entries(planMode.allowedValues ?? {}).some(([key, allowed]) => {
|
|
674
|
+
const value = args[key];
|
|
675
|
+
return (value !== null &&
|
|
676
|
+
value !== undefined &&
|
|
677
|
+
(typeof value !== "string" || !allowed.includes(value)));
|
|
678
|
+
})) {
|
|
679
|
+
return false;
|
|
680
|
+
}
|
|
681
|
+
try {
|
|
682
|
+
const effect = typeof planMode.effect === "function"
|
|
683
|
+
? planMode.effect(input)
|
|
684
|
+
: planMode.effect;
|
|
685
|
+
return effect === "read";
|
|
686
|
+
}
|
|
687
|
+
catch (error) {
|
|
688
|
+
console.warn("[run-code] tool-orchestration read-only policy classifier failed closed:", error instanceof Error ? error.message : String(error));
|
|
689
|
+
return false;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
function boundToolOrchestrationArgs(toolName, args) {
|
|
693
|
+
if (toolName !== "provider-api-request")
|
|
694
|
+
return args;
|
|
695
|
+
const fetchAllPages = args.fetchAllPages;
|
|
696
|
+
if (!fetchAllPages ||
|
|
697
|
+
typeof fetchAllPages !== "object" ||
|
|
698
|
+
Array.isArray(fetchAllPages)) {
|
|
699
|
+
return args;
|
|
700
|
+
}
|
|
701
|
+
const requestedMaxPages = Number(fetchAllPages.maxPages);
|
|
702
|
+
const maxPages = Number.isInteger(requestedMaxPages) && requestedMaxPages > 0
|
|
703
|
+
? Math.min(Math.floor(requestedMaxPages), TOOL_ORCHESTRATION_MAX_PROVIDER_PAGES)
|
|
704
|
+
: TOOL_ORCHESTRATION_MAX_PROVIDER_PAGES;
|
|
705
|
+
return {
|
|
706
|
+
...args,
|
|
707
|
+
fetchAllPages: {
|
|
708
|
+
...fetchAllPages,
|
|
709
|
+
maxPages,
|
|
710
|
+
},
|
|
711
|
+
};
|
|
712
|
+
}
|
|
583
713
|
// ---------------------------------------------------------------------------
|
|
584
714
|
// Sandbox module template
|
|
585
715
|
// ---------------------------------------------------------------------------
|
|
@@ -589,7 +719,61 @@ function handleBridgeRequest(rawBody, actions, context, defaultTools, extraTools
|
|
|
589
719
|
* `providerSearchAll`, and `webFetch` helpers via the bridge.
|
|
590
720
|
* 2. Runs the user's code as top-level await in an async IIFE.
|
|
591
721
|
*/
|
|
592
|
-
function buildSandboxModule(userCode, bridgePort, bridgeToken) {
|
|
722
|
+
function buildSandboxModule(userCode, bridgePort, bridgeToken, mode = "run-code") {
|
|
723
|
+
const orchestrationHelpers = mode === "tool-orchestration"
|
|
724
|
+
? `
|
|
725
|
+
/**
|
|
726
|
+
* Search the live registry for read-only or conditionally read-only tools, then call one
|
|
727
|
+
* of the returned names with toolCall(). The parent host enforces the same
|
|
728
|
+
* policy again, so this is discovery guidance rather than an authorization
|
|
729
|
+
* boundary.
|
|
730
|
+
*/
|
|
731
|
+
async function toolSearch(query = "", options = {}) {
|
|
732
|
+
const rawResult = await _bridgeCall("tool-search", {
|
|
733
|
+
...(query ? { query } : {}),
|
|
734
|
+
...(options.limit !== undefined ? { limit: options.limit } : {}),
|
|
735
|
+
includeSchemas: true,
|
|
736
|
+
readOnlyOnly: true,
|
|
737
|
+
});
|
|
738
|
+
return _parseBridgeResult(rawResult);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
async function toolCall(name, args = {}) {
|
|
742
|
+
return _parseBridgeResult(await _bridgeCall(name, args));
|
|
743
|
+
}
|
|
744
|
+
`
|
|
745
|
+
: "";
|
|
746
|
+
const workspaceMutationHelpers = mode === "run-code"
|
|
747
|
+
? `
|
|
748
|
+
/**
|
|
749
|
+
* Write (create or overwrite) a workspace file. Use \`scratch/...\` for
|
|
750
|
+
* temporary staging files.
|
|
751
|
+
* \`content\` must be a string. Returns metadata
|
|
752
|
+
* { resourceId, path, contentType, sizeBytes, updatedAt }.
|
|
753
|
+
*/
|
|
754
|
+
async function workspaceWrite(path, content, contentType = "text/plain") {
|
|
755
|
+
const rawResult = await _bridgeCall("workspace-files", {
|
|
756
|
+
action: "write",
|
|
757
|
+
path,
|
|
758
|
+
content: typeof content === "string" ? content : JSON.stringify(content),
|
|
759
|
+
contentType,
|
|
760
|
+
});
|
|
761
|
+
try { return typeof rawResult === "string" ? JSON.parse(rawResult) : rawResult; } catch { return rawResult; }
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Append text to a workspace file (creates if absent).
|
|
766
|
+
*/
|
|
767
|
+
async function workspaceAppend(path, content) {
|
|
768
|
+
const rawResult = await _bridgeCall("workspace-files", {
|
|
769
|
+
action: "append",
|
|
770
|
+
path,
|
|
771
|
+
content: typeof content === "string" ? content : JSON.stringify(content),
|
|
772
|
+
});
|
|
773
|
+
try { return typeof rawResult === "string" ? JSON.parse(rawResult) : rawResult; } catch { return rawResult; }
|
|
774
|
+
}
|
|
775
|
+
`
|
|
776
|
+
: "";
|
|
593
777
|
return `
|
|
594
778
|
import { createRequire } from "node:module";
|
|
595
779
|
const require = createRequire(import.meta.url);
|
|
@@ -646,6 +830,8 @@ async function appAction(name, args = {}) {
|
|
|
646
830
|
return _parseBridgeResult(await _bridgeCall(name, args));
|
|
647
831
|
}
|
|
648
832
|
|
|
833
|
+
${orchestrationHelpers}
|
|
834
|
+
|
|
649
835
|
async function providerRequest(provider, apiPath, init = {}) {
|
|
650
836
|
const method = (init.method || "GET").toUpperCase();
|
|
651
837
|
const rawResult = await _bridgeCall("provider-api-request", {
|
|
@@ -1388,33 +1574,7 @@ async function workspaceReadMeta(path, opts = {}) {
|
|
|
1388
1574
|
return _parseBridgeResult(rawResult);
|
|
1389
1575
|
}
|
|
1390
1576
|
|
|
1391
|
-
|
|
1392
|
-
* Write (create or overwrite) a workspace file. Use \`scratch/...\` for
|
|
1393
|
-
* temporary staging files.
|
|
1394
|
-
* \`content\` must be a string. Returns metadata
|
|
1395
|
-
* { resourceId, path, contentType, sizeBytes, updatedAt }.
|
|
1396
|
-
*/
|
|
1397
|
-
async function workspaceWrite(path, content, contentType = "text/plain") {
|
|
1398
|
-
const rawResult = await _bridgeCall("workspace-files", {
|
|
1399
|
-
action: "write",
|
|
1400
|
-
path,
|
|
1401
|
-
content: typeof content === "string" ? content : JSON.stringify(content),
|
|
1402
|
-
contentType,
|
|
1403
|
-
});
|
|
1404
|
-
try { return typeof rawResult === "string" ? JSON.parse(rawResult) : rawResult; } catch { return rawResult; }
|
|
1405
|
-
}
|
|
1406
|
-
|
|
1407
|
-
/**
|
|
1408
|
-
* Append text to a workspace file (creates if absent).
|
|
1409
|
-
*/
|
|
1410
|
-
async function workspaceAppend(path, content) {
|
|
1411
|
-
const rawResult = await _bridgeCall("workspace-files", {
|
|
1412
|
-
action: "append",
|
|
1413
|
-
path,
|
|
1414
|
-
content: typeof content === "string" ? content : JSON.stringify(content),
|
|
1415
|
-
});
|
|
1416
|
-
try { return typeof rawResult === "string" ? JSON.parse(rawResult) : rawResult; } catch { return rawResult; }
|
|
1417
|
-
}
|
|
1577
|
+
${workspaceMutationHelpers}
|
|
1418
1578
|
|
|
1419
1579
|
/**
|
|
1420
1580
|
* List workspace files, optionally filtered by path prefix.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ActionEntry } from "../agent/production-agent.js";
|
|
2
|
+
/**
|
|
3
|
+
* Create the bounded read-only orchestration tool.
|
|
4
|
+
*
|
|
5
|
+
* This deliberately has a separate registry entry from run-code. The latter
|
|
6
|
+
* retains its existing workspace staging and background-execution contract;
|
|
7
|
+
* this entry is for short fan-out, reduction, and aggregation over tools that
|
|
8
|
+
* the host can prove are read-only for the supplied arguments.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createToolOrchestrationEntry(getActions: () => Record<string, ActionEntry>): ActionEntry;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { executeSandboxCode, } from "./run-code.js";
|
|
2
|
+
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
3
|
+
const MAX_TIMEOUT_MS = 120_000;
|
|
4
|
+
const DEFAULT_MAX_OUTPUT_CHARS = 50_000;
|
|
5
|
+
const MAX_OUTPUT_CHARS = 100_000;
|
|
6
|
+
const DEFAULT_MAX_TOOL_CALLS = 32;
|
|
7
|
+
const MAX_TOOL_CALLS = 128;
|
|
8
|
+
/**
|
|
9
|
+
* Create the bounded read-only orchestration tool.
|
|
10
|
+
*
|
|
11
|
+
* This deliberately has a separate registry entry from run-code. The latter
|
|
12
|
+
* retains its existing workspace staging and background-execution contract;
|
|
13
|
+
* this entry is for short fan-out, reduction, and aggregation over tools that
|
|
14
|
+
* the host can prove are read-only for the supplied arguments.
|
|
15
|
+
*/
|
|
16
|
+
export function createToolOrchestrationEntry(getActions) {
|
|
17
|
+
return {
|
|
18
|
+
readOnly: true,
|
|
19
|
+
allowInPlanMode: false,
|
|
20
|
+
timeoutMs: MAX_TIMEOUT_MS,
|
|
21
|
+
maxResultChars: MAX_OUTPUT_CHARS,
|
|
22
|
+
tool: {
|
|
23
|
+
description: [
|
|
24
|
+
"Run a bounded JavaScript orchestration script in the existing sandbox.",
|
|
25
|
+
"Use toolSearch(query) to discover read-only or conditionally read-only tools, then toolCall(name, args) to fan out, join, filter, and aggregate their results without putting every intermediate payload into chat. The host rechecks conditional policies against each argument object.",
|
|
26
|
+
"The host rechecks every child call: mutating actions, hidden actions, provider writes, non-GET/HEAD web requests, staging, file saves, and workspace writes are rejected. Call mutations directly as native tools.",
|
|
27
|
+
"The orchestration sandbox has no background mode, a strict child-tool-call budget, and a 20-page cap on each provider fetchAllPages call. It is a bounded orchestration path, not a general-purpose replacement for run-code.",
|
|
28
|
+
"Available globals: toolSearch(query?, options?), toolCall(name, args?), providerFetch(provider, path, init?), providerFetchAll(...), providerSearchAll(...), webFetch(url, init?), webRead(url, init?), workspaceRead(path, opts?), workspaceReadMeta(path, opts?), workspaceList(prefix?), and appAction(name, args?) for eligible read-only actions.",
|
|
29
|
+
"Print only the compact result needed by the conversation with console.log().",
|
|
30
|
+
].join(" "),
|
|
31
|
+
parameters: {
|
|
32
|
+
type: "object",
|
|
33
|
+
properties: {
|
|
34
|
+
code: {
|
|
35
|
+
type: "string",
|
|
36
|
+
description: "JavaScript source to execute. ESM syntax and top-level await are supported.",
|
|
37
|
+
},
|
|
38
|
+
timeoutMs: {
|
|
39
|
+
type: "number",
|
|
40
|
+
description: `Execution timeout in milliseconds. Default: ${DEFAULT_TIMEOUT_MS}; max: ${MAX_TIMEOUT_MS}.`,
|
|
41
|
+
},
|
|
42
|
+
maxOutputChars: {
|
|
43
|
+
type: "number",
|
|
44
|
+
description: `Maximum combined stdout+stderr characters. Default: ${DEFAULT_MAX_OUTPUT_CHARS}; max: ${MAX_OUTPUT_CHARS}.`,
|
|
45
|
+
},
|
|
46
|
+
maxToolCalls: {
|
|
47
|
+
type: "number",
|
|
48
|
+
description: `Maximum bridged child-tool calls. Default: ${DEFAULT_MAX_TOOL_CALLS}; max: ${MAX_TOOL_CALLS}.`,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
required: ["code"],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
run: async (args, context) => {
|
|
55
|
+
if (args.background || args.executionId) {
|
|
56
|
+
return "Error: tool-orchestration is foreground-only and does not support background or polling arguments. Use run-code for durable long-running execution.";
|
|
57
|
+
}
|
|
58
|
+
const code = typeof args.code === "string" ? args.code : "";
|
|
59
|
+
if (!code.trim())
|
|
60
|
+
return "Error: code is required.";
|
|
61
|
+
const requestedTimeout = Number(args.timeoutMs);
|
|
62
|
+
const timeoutMs = Number.isFinite(requestedTimeout) && requestedTimeout > 0
|
|
63
|
+
? Math.min(requestedTimeout, MAX_TIMEOUT_MS)
|
|
64
|
+
: DEFAULT_TIMEOUT_MS;
|
|
65
|
+
const requestedOutput = Number(args.maxOutputChars);
|
|
66
|
+
const maxOutputChars = Number.isFinite(requestedOutput) && requestedOutput > 0
|
|
67
|
+
? Math.min(requestedOutput, MAX_OUTPUT_CHARS)
|
|
68
|
+
: DEFAULT_MAX_OUTPUT_CHARS;
|
|
69
|
+
const requestedCalls = Number(args.maxToolCalls);
|
|
70
|
+
const maxToolCalls = Number.isFinite(requestedCalls) && requestedCalls > 0
|
|
71
|
+
? Math.min(Math.floor(requestedCalls), MAX_TOOL_CALLS)
|
|
72
|
+
: DEFAULT_MAX_TOOL_CALLS;
|
|
73
|
+
const result = await executeSandboxCode({
|
|
74
|
+
code,
|
|
75
|
+
timeoutMs,
|
|
76
|
+
getActions,
|
|
77
|
+
mode: "tool-orchestration",
|
|
78
|
+
maxToolCalls,
|
|
79
|
+
context,
|
|
80
|
+
});
|
|
81
|
+
return formatResult(result, timeoutMs, maxOutputChars);
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function formatResult(result, timeoutMs, maxOutputChars) {
|
|
86
|
+
const combined = [
|
|
87
|
+
result.stdout ? `stdout:\n${result.stdout}` : "",
|
|
88
|
+
result.stderr ? `stderr:\n${result.stderr}` : "",
|
|
89
|
+
]
|
|
90
|
+
.filter(Boolean)
|
|
91
|
+
.join("\n\n") || "(no output)";
|
|
92
|
+
const lines = [];
|
|
93
|
+
if (result.timedOut)
|
|
94
|
+
lines.push(`timedOut: true (${timeoutMs}ms)`);
|
|
95
|
+
if (result.exitCode !== 0 && result.exitCode !== null) {
|
|
96
|
+
lines.push(`exitCode: ${result.exitCode}`);
|
|
97
|
+
}
|
|
98
|
+
if (result.bridgeToolsUsed.length) {
|
|
99
|
+
lines.push(`bridgeToolsUsed: ${result.bridgeToolsUsed.join(", ")}`);
|
|
100
|
+
}
|
|
101
|
+
lines.push(combined);
|
|
102
|
+
const full = lines.join("\n\n");
|
|
103
|
+
if (full.length <= maxOutputChars)
|
|
104
|
+
return full;
|
|
105
|
+
const truncated = full.slice(0, maxOutputChars);
|
|
106
|
+
return `${truncated}\n\n...[truncated ${(full.length - maxOutputChars).toLocaleString()} chars]`;
|
|
107
|
+
}
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
ok?: undefined;
|
|
30
29
|
error: string;
|
|
30
|
+
ok?: undefined;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
|
@@ -54,6 +54,15 @@ export interface JobFrontmatter {
|
|
|
54
54
|
*/
|
|
55
55
|
delegatedPolicyId?: string;
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Return whether a scheduler or trigger dispatcher may claim this resource.
|
|
59
|
+
*
|
|
60
|
+
* Personal legacy jobs have no app owner and remain compatible with the
|
|
61
|
+
* shared scheduler. An organization-owned resource without an explicit app
|
|
62
|
+
* owner is ambiguous, though: letting every installed app claim it can run
|
|
63
|
+
* the same job multiple times and with the wrong deployment credentials.
|
|
64
|
+
*/
|
|
65
|
+
export declare function jobBelongsToApp(meta: Pick<JobFrontmatter, "appId" | "orgId">, appId: string | null | undefined): boolean;
|
|
57
66
|
export interface JobResourceClassification {
|
|
58
67
|
kind: "job" | "automation";
|
|
59
68
|
hasExplicitTriggerType: boolean;
|
package/dist/jobs/frontmatter.js
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Return whether a scheduler or trigger dispatcher may claim this resource.
|
|
3
|
+
*
|
|
4
|
+
* Personal legacy jobs have no app owner and remain compatible with the
|
|
5
|
+
* shared scheduler. An organization-owned resource without an explicit app
|
|
6
|
+
* owner is ambiguous, though: letting every installed app claim it can run
|
|
7
|
+
* the same job multiple times and with the wrong deployment credentials.
|
|
8
|
+
*/
|
|
9
|
+
export function jobBelongsToApp(meta, appId) {
|
|
10
|
+
const ownerAppId = meta.appId?.trim();
|
|
11
|
+
if (ownerAppId) {
|
|
12
|
+
const schedulerAppId = appId?.trim();
|
|
13
|
+
return Boolean(schedulerAppId && ownerAppId === schedulerAppId);
|
|
14
|
+
}
|
|
15
|
+
return !meta.orgId?.trim();
|
|
16
|
+
}
|
|
1
17
|
const MAX_JOB_MCP_TOOLS = 64;
|
|
2
18
|
const JOB_MCP_TOOL_NAME_RE = /^mcp__[^\s]+__[^\s]+$/;
|
|
3
19
|
const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n)?([\s\S]*)$/;
|
package/dist/jobs/scheduler.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resourceGetByPath, resourceListAllOwners, resourcePutIfCurrent, } from "../resources/store.js";
|
|
2
2
|
import { backgroundRunCutOffReason, isBackgroundAutomationRunActive, resolveBackgroundAutomationIdentity, runBackgroundAutomation, } from "./background-automation-runner.js";
|
|
3
3
|
import { nextOccurrence, isValidCron, describeCron, effectiveTimezone, } from "./cron.js";
|
|
4
|
-
import { buildJobResourceContent, parseJobResource, } from "./frontmatter.js";
|
|
4
|
+
import { buildJobResourceContent, jobBelongsToApp, parseJobResource, } from "./frontmatter.js";
|
|
5
5
|
import { claimAutomationRun, finishAutomationRun, getAutomationRun, listAutomationRuns, } from "./run-history.js";
|
|
6
6
|
import { acquireAutomationSchedulerLease, recordAutomationSchedulerHealth, releaseAutomationSchedulerLease, renewAutomationSchedulerLease, AUTOMATION_SCHEDULER_LEASE_RENEWAL_MS, } from "./scheduler-health.js";
|
|
7
7
|
// ─── Frontmatter parsing ────────────────────────────────────────────────────
|
|
@@ -18,13 +18,6 @@ const MAX_IDENTITY_PREFLIGHTS_PER_TICK = MAX_CONCURRENT_SCHEDULED_JOBS * 4;
|
|
|
18
18
|
const IDENTITY_FAILURE_RETRY_MS = 5 * 60_000;
|
|
19
19
|
const _activeScheduledJobs = new Set();
|
|
20
20
|
const _preflightingScheduledJobs = new Set();
|
|
21
|
-
function jobBelongsToApp(meta, appId) {
|
|
22
|
-
const ownerAppId = meta.appId?.trim();
|
|
23
|
-
if (!ownerAppId)
|
|
24
|
-
return true;
|
|
25
|
-
const schedulerAppId = appId?.trim();
|
|
26
|
-
return Boolean(schedulerAppId && ownerAppId === schedulerAppId);
|
|
27
|
-
}
|
|
28
21
|
// Skip the DB query on every tick if we recently confirmed no jobs exist.
|
|
29
22
|
// `_hasJobsCache` is invalidated whenever a `jobs/*` resource is written or
|
|
30
23
|
// deleted (subscribed below), and refreshed at most every 5 minutes.
|
|
@@ -429,6 +422,13 @@ async function executeJob(resource, meta, body, deps, now, options = {}) {
|
|
|
429
422
|
requestContext,
|
|
430
423
|
...(options.historyId ? { historyId: options.historyId } : {}),
|
|
431
424
|
actionCaller: "automation",
|
|
425
|
+
actionAutomation: {
|
|
426
|
+
triggerId: resource.id,
|
|
427
|
+
triggerName: jobName,
|
|
428
|
+
...(meta.delegatedPolicyId
|
|
429
|
+
? { policyId: meta.delegatedPolicyId }
|
|
430
|
+
: {}),
|
|
431
|
+
},
|
|
432
432
|
}, deps);
|
|
433
433
|
await recordExecutionOutcome(resource, {
|
|
434
434
|
lastRun: meta.lastRun,
|
package/dist/jobs/tools.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ActionEntry } from "../agent/production-agent.js";
|
|
2
2
|
import { type JobFrontmatter } from "./scheduler.js";
|
|
3
|
-
export
|
|
3
|
+
export { jobBelongsToApp } from "./frontmatter.js";
|
|
4
4
|
/**
|
|
5
5
|
* Authorise a mutation (update / delete) against a job resource. When the
|
|
6
6
|
* job is in the SHARED scope the caller must either be the original
|
package/dist/jobs/tools.js
CHANGED
|
@@ -3,8 +3,9 @@ import { resolveUserSchedulingTimezone } from "../localization/user-timezone.js"
|
|
|
3
3
|
import { resourcePut, resourceGetByPath, resourceList, resourceDelete, organizationIdFromResourceOwner, sharedResourceOwner, SHARED_OWNER, } from "../resources/store.js";
|
|
4
4
|
import { getRequestUserEmail, getRequestOrgId, getIntegrationRequestContext, } from "../server/request-context.js";
|
|
5
5
|
import { isValidCron, nextOccurrence, describeCron, effectiveTimezone, isValidTimezone, } from "./cron.js";
|
|
6
|
-
import { classifyJobResource } from "./frontmatter.js";
|
|
6
|
+
import { classifyJobResource, jobBelongsToApp } from "./frontmatter.js";
|
|
7
7
|
import { parseJobFrontmatter, buildJobContent, normalizeJobMcpTools, } from "./scheduler.js";
|
|
8
|
+
export { jobBelongsToApp } from "./frontmatter.js";
|
|
8
9
|
function getOwner() {
|
|
9
10
|
const email = getRequestUserEmail();
|
|
10
11
|
if (!email)
|
|
@@ -14,12 +15,6 @@ function getOwner() {
|
|
|
14
15
|
function getSharedOwner() {
|
|
15
16
|
return sharedResourceOwner(getRequestOrgId());
|
|
16
17
|
}
|
|
17
|
-
export function jobBelongsToApp(meta, appId) {
|
|
18
|
-
const ownerAppId = meta.appId?.trim();
|
|
19
|
-
if (!ownerAppId)
|
|
20
|
-
return true;
|
|
21
|
-
return ownerAppId === appId?.trim();
|
|
22
|
-
}
|
|
23
18
|
/**
|
|
24
19
|
* Determine if the current request's user is an org owner/admin in the
|
|
25
20
|
* given org. Used to allow privileged users to update or delete shared
|
|
@@ -455,6 +455,26 @@ declare const messages: {
|
|
|
455
455
|
builderModelCredits: string;
|
|
456
456
|
addOwnKeys: string;
|
|
457
457
|
configureProviderKeys: string;
|
|
458
|
+
chooseProvider: string;
|
|
459
|
+
searchProviders: string;
|
|
460
|
+
noProvidersFound: string;
|
|
461
|
+
availableProviders: string;
|
|
462
|
+
configured: string;
|
|
463
|
+
apiKey: string;
|
|
464
|
+
localRuntime: string;
|
|
465
|
+
enterApiKey: string;
|
|
466
|
+
providerSetupFailed: string;
|
|
467
|
+
noApiKeyNeeded: string;
|
|
468
|
+
modelId: string;
|
|
469
|
+
endpointUrl: string;
|
|
470
|
+
optional: string;
|
|
471
|
+
ollamaEndpointHint: string;
|
|
472
|
+
compatibleEndpointHint: string;
|
|
473
|
+
savingProvider: string;
|
|
474
|
+
providerSaved: string;
|
|
475
|
+
useProvider: string;
|
|
476
|
+
saveAndUseProvider: string;
|
|
477
|
+
getApiKey: string;
|
|
458
478
|
checkingAiConnection: string;
|
|
459
479
|
delegatedAgent: {
|
|
460
480
|
asking: string;
|
|
@@ -389,7 +389,7 @@ const messages = {
|
|
|
389
389
|
threadDebugRefreshFailures: "Refresh failed runs",
|
|
390
390
|
threadDebugNoFailures: "No failed runs found.",
|
|
391
391
|
threadDebugCurrentDatabase: "Current Dispatch DB",
|
|
392
|
-
threadDebugSearchPlaceholder: "Search
|
|
392
|
+
threadDebugSearchPlaceholder: "Search threads or email",
|
|
393
393
|
threadDebugSearch: "Search",
|
|
394
394
|
threadDebugLookupPlaceholder: "Paste thread or request/run ID",
|
|
395
395
|
threadDebugInspect: "Inspect",
|
|
@@ -455,12 +455,32 @@ const messages = {
|
|
|
455
455
|
askAgentTitle: "Ask the agent",
|
|
456
456
|
askAgentPlaceholder: "Tell the agent what you want to do…",
|
|
457
457
|
connectAi: "Connect AI",
|
|
458
|
-
builderOrOwnKeys: "
|
|
458
|
+
builderOrOwnKeys: "Choose Builder.io or custom keys.",
|
|
459
459
|
connectBuilderIo: "Connect Builder.io",
|
|
460
460
|
connectingBuilder: "Connecting Builder.io…",
|
|
461
461
|
builderModelCredits: "Free credits for Claude, OpenAI & Gemini",
|
|
462
|
-
addOwnKeys: "
|
|
463
|
-
configureProviderKeys: "
|
|
462
|
+
addOwnKeys: "Custom keys",
|
|
463
|
+
configureProviderKeys: "Choose a provider.",
|
|
464
|
+
chooseProvider: "Choose a provider",
|
|
465
|
+
searchProviders: "Search providers...",
|
|
466
|
+
noProvidersFound: "No providers found.",
|
|
467
|
+
availableProviders: "Available providers",
|
|
468
|
+
configured: "Configured",
|
|
469
|
+
apiKey: "API key",
|
|
470
|
+
localRuntime: "Local",
|
|
471
|
+
enterApiKey: "Enter your {{provider}} API key.",
|
|
472
|
+
providerSetupFailed: "Could not configure this provider.",
|
|
473
|
+
noApiKeyNeeded: "No API key required.",
|
|
474
|
+
modelId: "Model ID",
|
|
475
|
+
endpointUrl: "Endpoint URL",
|
|
476
|
+
optional: "Optional",
|
|
477
|
+
ollamaEndpointHint: "Defaults to Ollama at http://localhost:11434.",
|
|
478
|
+
compatibleEndpointHint: "Use this for LiteLLM or another OpenAI-compatible gateway.",
|
|
479
|
+
savingProvider: "Saving...",
|
|
480
|
+
providerSaved: "Connected",
|
|
481
|
+
useProvider: "Use {{provider}}",
|
|
482
|
+
saveAndUseProvider: "Save and use {{provider}}",
|
|
483
|
+
getApiKey: "Get an API key",
|
|
464
484
|
checkingAiConnection: "Checking AI connection...",
|
|
465
485
|
delegatedAgent: {
|
|
466
486
|
asking: "Asking {{name}}...",
|
|
@@ -475,7 +495,7 @@ const messages = {
|
|
|
475
495
|
setupTitle: "Set up voice mode",
|
|
476
496
|
setupDescription: "Connect Builder.io to use managed voice with free credits, or add your own keys.",
|
|
477
497
|
connectBuilder: "Connect Builder.io",
|
|
478
|
-
useOpenAiKey: "
|
|
498
|
+
useOpenAiKey: "Custom keys",
|
|
479
499
|
startWithOpenAiKey: "Start with OpenAI key",
|
|
480
500
|
start: "Real-time voice",
|
|
481
501
|
keepDictating: "Dictate",
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
* DELETE /_agent-native/notifications/:id — delete
|
|
12
12
|
*/
|
|
13
13
|
export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
|
|
14
|
+
error?: undefined;
|
|
14
15
|
count: number;
|
|
15
16
|
updated?: undefined;
|
|
16
|
-
error?: undefined;
|
|
17
17
|
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
|
+
error?: undefined;
|
|
19
20
|
count?: undefined;
|
|
20
21
|
updated: number;
|
|
21
|
-
error?: undefined;
|
|
22
22
|
ok?: undefined;
|
|
23
23
|
} | {
|
|
24
24
|
count?: undefined;
|
|
@@ -26,8 +26,8 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
|
|
|
26
26
|
error: string;
|
|
27
27
|
ok?: undefined;
|
|
28
28
|
} | {
|
|
29
|
+
error?: undefined;
|
|
29
30
|
count?: undefined;
|
|
30
31
|
updated?: undefined;
|
|
31
|
-
error?: undefined;
|
|
32
32
|
ok: boolean;
|
|
33
33
|
}>>;
|