@agentproto/runtime 3.2.0 → 3.4.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/dist/catalog-models.d.ts +15 -5
- package/dist/catalog-models.mjs +12 -3
- package/dist/catalog-models.mjs.map +1 -1
- package/dist/index.d.ts +34 -10
- package/dist/index.mjs +112 -30
- package/dist/index.mjs.map +1 -1
- package/package.json +28 -28
package/dist/index.d.ts
CHANGED
|
@@ -3899,8 +3899,12 @@ type WorktreeGcClass = "reclaim" | "salvage" | "hold";
|
|
|
3899
3899
|
* `orphan` is set on an entry/outcome the orphan scan found — a directory
|
|
3900
3900
|
* physically present under the repo's worktree pool with no `git worktree
|
|
3901
3901
|
* list` entry at all (see `WorktreeGcPlanEntryView.orphan`).
|
|
3902
|
+
* `prunable` is set on an entry/outcome `git worktree list --porcelain`
|
|
3903
|
+
* itself already reported dead — the mirror image of `orphan`: the
|
|
3904
|
+
* registration is still there, but the working directory is gone (see
|
|
3905
|
+
* `WorktreeGcPlanEntryView.prunable`).
|
|
3902
3906
|
*/
|
|
3903
|
-
type WorktreeGcReclaimReason = "dep-bump" | "orphan";
|
|
3907
|
+
type WorktreeGcReclaimReason = "dep-bump" | "orphan" | "prunable";
|
|
3904
3908
|
/**
|
|
3905
3909
|
* One entry of the dry-run plan — a runtime-local projection of a
|
|
3906
3910
|
* `GcPlanEntry`. `tree` / `integration` / `liveness` are flattened to their
|
|
@@ -3912,7 +3916,7 @@ interface WorktreeGcPlanEntryView {
|
|
|
3912
3916
|
branch: string | null;
|
|
3913
3917
|
head: string;
|
|
3914
3918
|
class: WorktreeGcClass;
|
|
3915
|
-
/** Set only when `class === "reclaim"` via the dep-bump exemption or the
|
|
3919
|
+
/** Set only when `class === "reclaim"` via the dep-bump exemption, the orphan scan, or the prunable signal. */
|
|
3916
3920
|
reclaimReason?: WorktreeGcReclaimReason;
|
|
3917
3921
|
/**
|
|
3918
3922
|
* `true` only for an orphan-scan entry: a directory physically present
|
|
@@ -3923,6 +3927,13 @@ interface WorktreeGcPlanEntryView {
|
|
|
3923
3927
|
* literal `"orphan"` placeholder below rather than a fabricated value.
|
|
3924
3928
|
*/
|
|
3925
3929
|
orphan?: boolean;
|
|
3930
|
+
/**
|
|
3931
|
+
* `true` only for a linked worktree `git worktree list --porcelain` itself
|
|
3932
|
+
* already marked `prunable`. Same reasoning as `orphan` above — no
|
|
3933
|
+
* tree/integration/liveness axis was ever read for a working directory
|
|
3934
|
+
* that's gone — projected as the literal `"prunable"` placeholder below.
|
|
3935
|
+
*/
|
|
3936
|
+
prunable?: boolean;
|
|
3926
3937
|
tree: string;
|
|
3927
3938
|
integration: {
|
|
3928
3939
|
state: string;
|
|
@@ -5249,6 +5260,15 @@ interface SessionDescriptor {
|
|
|
5249
5260
|
* posture or a raw `{ harnessModeId }` sourced from the harness's ACP mode
|
|
5250
5261
|
* registry (SPEC §3.4a). */
|
|
5251
5262
|
posture?: Posture;
|
|
5263
|
+
/**
|
|
5264
|
+
* Read-surface echo of the live harness's advertised ACP session modes
|
|
5265
|
+
* (`SessionModeState.availableModes`, #482) — stamped at READ TIME from the
|
|
5266
|
+
* live agent session by `list()`/`get()`, never persisted. A client posture
|
|
5267
|
+
* picker resolves the native (enforced, live-switchable) rows from this;
|
|
5268
|
+
* absent for arms with no native mode registry (print/proprietary) and for a
|
|
5269
|
+
* session whose live runtime handle is gone.
|
|
5270
|
+
*/
|
|
5271
|
+
availableModes?: SessionMode[];
|
|
5252
5272
|
/** Endpoint / gateway rail (SPEC §3.1 axis 4). `baseUrl` is carried only
|
|
5253
5273
|
* for a custom gateway the catalog can't resolve; `access` is downstream
|
|
5254
5274
|
* of this axis (SPEC §1c). */
|
|
@@ -6216,6 +6236,7 @@ interface SessionsRegistry {
|
|
|
6216
6236
|
*/
|
|
6217
6237
|
listSummaries(opts?: {
|
|
6218
6238
|
includeArchived?: boolean;
|
|
6239
|
+
lane?: "agents" | "auto";
|
|
6219
6240
|
limit?: number;
|
|
6220
6241
|
offset?: number;
|
|
6221
6242
|
}): {
|
|
@@ -7522,14 +7543,17 @@ declare function registerBuiltinRoutes(opts?: {
|
|
|
7522
7543
|
* kind-organized catalogs, so NO adapters, NO profiles, NO host wiring.
|
|
7523
7544
|
* `getModelsByProvider` is itself router-aware: OpenRouter's route table is
|
|
7524
7545
|
* spread into `LLM_PRICING_CATALOG` upstream (`llm/catalog.ts`), so an
|
|
7525
|
-
* `openrouter` query returns that full, large list with bare ids; Requesty
|
|
7526
|
-
*
|
|
7527
|
-
*
|
|
7528
|
-
* pricing
|
|
7529
|
-
*
|
|
7530
|
-
*
|
|
7531
|
-
*
|
|
7532
|
-
*
|
|
7546
|
+
* `openrouter` query returns that full, large list with bare ids; Requesty,
|
|
7547
|
+
* HuggingFace and OpenCode's two hosted endpoints (`opencode-go`,
|
|
7548
|
+
* `opencode`) are NOT spread into that catalog — spreading a second router's
|
|
7549
|
+
* bare-id pricing there would repoint direct-vendor ids at router pricing
|
|
7550
|
+
* (`route-identity/index.ts`) — so `getModelsByProvider` instead folds their
|
|
7551
|
+
* generated route tables in directly. The emitted id is whatever the ref
|
|
7552
|
+
* formats to: `vendor/product@route` for the vendor-namespacing routers, and
|
|
7553
|
+
* the bare `opencode-go/glm-5.3` form for the OpenCode endpoints, whose route
|
|
7554
|
+
* IS the id's leading segment. Every provider enumerates through the same
|
|
7555
|
+
* path; the picker paginates client-side. NEVER log the rows: OpenRouter
|
|
7556
|
+
* alone is thousands.
|
|
7533
7557
|
*/
|
|
7534
7558
|
|
|
7535
7559
|
interface CatalogProviderModelsQuery {
|
package/dist/index.mjs
CHANGED
|
@@ -25,7 +25,7 @@ import { inferLegacyModeKind, parseModelSwitchCommand, isModelSwitchAcknowledgem
|
|
|
25
25
|
import { loadSandboxConfig, resolveCommandSandbox, COMMAND_SANDBOX_MODE_ENV } from '@agentproto/command-sandbox';
|
|
26
26
|
import { createBrainManager, parseKnowledgeConfig } from '@agentproto/workspace-brain';
|
|
27
27
|
import { defineHttpDriver } from '@agentproto/driver-http';
|
|
28
|
-
import {
|
|
28
|
+
import { liveSessionApp, makeLiveSessionApp, sessionsPanelApp, agentsOverviewApp, bureauSessionsApp, sessionStoryApp, workBoardApp, makeSessionsPanelApp, makeAgentsOverviewApp, makeBureauSessionsApp, makeSessionStoryPanelApp, makeSessionChatApp, makeWorkBoardApp, SESSION_CHAT_APP_ID, sessionChatApp } from '@agentproto/apps';
|
|
29
29
|
import matter2 from 'gray-matter';
|
|
30
30
|
import { createServer } from 'http';
|
|
31
31
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
@@ -4036,7 +4036,13 @@ function resolveWorktreeIdentity(cwd) {
|
|
|
4036
4036
|
dir = parent;
|
|
4037
4037
|
}
|
|
4038
4038
|
}
|
|
4039
|
-
var WIDENING_ROUTES = [
|
|
4039
|
+
var WIDENING_ROUTES = [
|
|
4040
|
+
"openrouter",
|
|
4041
|
+
"requesty",
|
|
4042
|
+
"huggingface",
|
|
4043
|
+
"opencode-go",
|
|
4044
|
+
"opencode"
|
|
4045
|
+
];
|
|
4040
4046
|
var VENDOR_COMPATIBILITY_ROUTES = {
|
|
4041
4047
|
xai: ["xai", "xai-anthropic"]
|
|
4042
4048
|
};
|
|
@@ -4375,9 +4381,12 @@ function reconcileModelRoute(input) {
|
|
|
4375
4381
|
}
|
|
4376
4382
|
function serviceableModelRoutes(model) {
|
|
4377
4383
|
const routes = /* @__PURE__ */ new Set();
|
|
4378
|
-
const provider = getModelProvider(model);
|
|
4379
|
-
if (provider) routes.add(provider);
|
|
4380
4384
|
const parsed = tryParseModelRef(normalizeRouterPrefixedId(model));
|
|
4385
|
+
const selfRouted = parsed !== void 0 && parsed.route === parsed.vendor && WIDENING_ROUTES.includes(parsed.vendor) && tryResolveLlmModelRoute(`${parsed.vendor}/${parsed.product}`)?.pricing.provider === parsed.vendor;
|
|
4386
|
+
if (!selfRouted) {
|
|
4387
|
+
const provider = getModelProvider(model);
|
|
4388
|
+
if (provider) routes.add(provider);
|
|
4389
|
+
}
|
|
4381
4390
|
if (parsed) {
|
|
4382
4391
|
if (parsed.route !== parsed.vendor) routes.add(parsed.route);
|
|
4383
4392
|
if (resolvePricingExact(parsed.product)?.provider === parsed.vendor) {
|
|
@@ -11091,6 +11100,14 @@ function stampInterrupted(desc) {
|
|
|
11091
11100
|
delete desc.interrupted;
|
|
11092
11101
|
}
|
|
11093
11102
|
}
|
|
11103
|
+
function stampLiveModes(desc, rt) {
|
|
11104
|
+
const modes = rt.agentSession?.availableModes;
|
|
11105
|
+
if (modes && modes.length > 0) {
|
|
11106
|
+
desc.availableModes = [...modes];
|
|
11107
|
+
} else {
|
|
11108
|
+
delete desc.availableModes;
|
|
11109
|
+
}
|
|
11110
|
+
}
|
|
11094
11111
|
function isResumable(desc) {
|
|
11095
11112
|
return desc.kind === "agent-cli" && !!desc.adapterSlug && !!desc.adapterSessionId && !!desc.cwd && !desc.archived;
|
|
11096
11113
|
}
|
|
@@ -11525,6 +11542,7 @@ function createSessionsRegistry(opts) {
|
|
|
11525
11542
|
secondsSinceLastActivity: _secondsSinceLastActivity,
|
|
11526
11543
|
toolCallsThisTurn: _toolCallsThisTurn,
|
|
11527
11544
|
eventsPath: _eventsPath,
|
|
11545
|
+
availableModes: _availableModes,
|
|
11528
11546
|
...rest
|
|
11529
11547
|
} = s.desc;
|
|
11530
11548
|
return rest;
|
|
@@ -13529,6 +13547,7 @@ ${message}`;
|
|
|
13529
13547
|
stampInterrupted(desc);
|
|
13530
13548
|
stampCurrentStatus(rt);
|
|
13531
13549
|
stampWatchers(desc);
|
|
13550
|
+
stampLiveModes(desc, rt);
|
|
13532
13551
|
desc.childrenBusy = childrenBusy.get(desc.id) ?? 0;
|
|
13533
13552
|
desc.queuedPrompts = desc.promptQueue?.length ?? 0;
|
|
13534
13553
|
return desc;
|
|
@@ -13536,10 +13555,30 @@ ${message}`;
|
|
|
13536
13555
|
},
|
|
13537
13556
|
listSummaries(opts2) {
|
|
13538
13557
|
const includeArchived = opts2?.includeArchived ?? false;
|
|
13558
|
+
const lane = opts2?.lane;
|
|
13539
13559
|
const limit = Math.max(1, Math.min(200, opts2?.limit ?? 50));
|
|
13540
13560
|
const offset = Math.max(0, opts2?.offset ?? 0);
|
|
13541
13561
|
const childrenBusy = childrenBusyCounts();
|
|
13542
|
-
const
|
|
13562
|
+
const hasMachineLineage = (rt) => {
|
|
13563
|
+
const ownMachine = (desc) => desc.origin === "cron" || desc.origin === "gate";
|
|
13564
|
+
if (ownMachine(rt.desc)) return true;
|
|
13565
|
+
const seen = /* @__PURE__ */ new Set([rt.desc.id]);
|
|
13566
|
+
let current = rt.desc;
|
|
13567
|
+
while (current.parentSessionId) {
|
|
13568
|
+
const parent = sessions.get(current.parentSessionId)?.desc;
|
|
13569
|
+
if (!parent || seen.has(parent.id)) return true;
|
|
13570
|
+
if (parent.kind === "terminal" || parent.kind === "command") return true;
|
|
13571
|
+
seen.add(parent.id);
|
|
13572
|
+
current = parent;
|
|
13573
|
+
}
|
|
13574
|
+
return ownMachine(current);
|
|
13575
|
+
};
|
|
13576
|
+
const all = Array.from(sessions.values()).filter((rt) => includeArchived || !rt.desc.archived).filter((rt) => {
|
|
13577
|
+
if (!lane) return true;
|
|
13578
|
+
if (rt.desc.kind === "terminal" || rt.desc.kind === "command") return false;
|
|
13579
|
+
const machine = hasMachineLineage(rt);
|
|
13580
|
+
return lane === "auto" ? machine : !machine;
|
|
13581
|
+
}).sort((a, b) => b.desc.startedAt.localeCompare(a.desc.startedAt));
|
|
13543
13582
|
const slice = all.slice(offset, offset + limit);
|
|
13544
13583
|
const summaries = slice.map((rt) => {
|
|
13545
13584
|
const desc = rt.desc;
|
|
@@ -13561,6 +13600,7 @@ ${message}`;
|
|
|
13561
13600
|
stampInterrupted(desc);
|
|
13562
13601
|
stampCurrentStatus(rt);
|
|
13563
13602
|
stampWatchers(desc);
|
|
13603
|
+
stampLiveModes(desc, rt);
|
|
13564
13604
|
desc.childrenBusy = childrenBusyCounts().get(desc.id) ?? 0;
|
|
13565
13605
|
desc.queuedPrompts = desc.promptQueue?.length ?? 0;
|
|
13566
13606
|
}
|
|
@@ -20343,6 +20383,18 @@ var PANEL_APP_HANDLES = [
|
|
|
20343
20383
|
sessionChatApp,
|
|
20344
20384
|
workBoardApp
|
|
20345
20385
|
];
|
|
20386
|
+
function resolveBuiltinPanelUi(appId, httpBaseUrl) {
|
|
20387
|
+
if (appId === liveSessionApp.id) {
|
|
20388
|
+
const app = makeLiveSessionApp({ httpBaseUrl });
|
|
20389
|
+
const html = typeof app.html === "function" ? app.html({ httpBaseUrl }) : app.html;
|
|
20390
|
+
return { html, tools: liveSessionApp.ui?.tools ?? [] };
|
|
20391
|
+
}
|
|
20392
|
+
const handle = [sessionsPanelApp, agentsOverviewApp, bureauSessionsApp, sessionStoryApp, workBoardApp].find(
|
|
20393
|
+
(h) => h.id === appId
|
|
20394
|
+
);
|
|
20395
|
+
if (!handle?.ui) return void 0;
|
|
20396
|
+
return { html: handle.ui.html, tools: handle.ui.tools ?? [] };
|
|
20397
|
+
}
|
|
20346
20398
|
function builtinPanelCatalogEntries() {
|
|
20347
20399
|
const apps = makeBuiltinPanelApps({
|
|
20348
20400
|
listSessions: () => [],
|
|
@@ -21953,12 +22005,7 @@ function notEnabled(tool) {
|
|
|
21953
22005
|
`${tool} is not enabled \u2014 the daemon was started without an adapter resolver. Re-run the daemon with the \`@agentproto/cli\` shim wired (see playground/scripts/gateway.ts).`
|
|
21954
22006
|
);
|
|
21955
22007
|
}
|
|
21956
|
-
async function
|
|
21957
|
-
const installed = appRegistry.getApp(input.appId);
|
|
21958
|
-
if (!installed || !installed.ui) {
|
|
21959
|
-
return errorResult2(`app_tool_call: app "${input.appId}" is not installed or has no UI.`);
|
|
21960
|
-
}
|
|
21961
|
-
const declaredAllowlist = installed.ui.tools ?? [];
|
|
22008
|
+
async function dispatchAllowlistedAppTool(declaredAllowlist, input, deps2) {
|
|
21962
22009
|
const effectiveAllowlist = [...declaredAllowlist, ...APP_UI_DISCOVERY_TOOLS];
|
|
21963
22010
|
if (!effectiveAllowlist.includes(input.tool)) {
|
|
21964
22011
|
return errorResult2(
|
|
@@ -21986,6 +22033,19 @@ async function performAppToolCall(appRegistry, input, deps2) {
|
|
|
21986
22033
|
return errorResult2(`app_tool_call: ${err instanceof Error ? err.message : String(err)}`);
|
|
21987
22034
|
}
|
|
21988
22035
|
}
|
|
22036
|
+
async function performAppToolCall(appRegistry, input, deps2) {
|
|
22037
|
+
const installed = appRegistry.getApp(input.appId);
|
|
22038
|
+
if (!installed || !installed.ui) {
|
|
22039
|
+
return errorResult2(`app_tool_call: app "${input.appId}" is not installed or has no UI.`);
|
|
22040
|
+
}
|
|
22041
|
+
return dispatchAllowlistedAppTool(installed.ui.tools ?? [], input, deps2);
|
|
22042
|
+
}
|
|
22043
|
+
async function performBuiltinPanelToolCall(tools, input, deps2) {
|
|
22044
|
+
if (tools === void 0) {
|
|
22045
|
+
return errorResult2(`app_tool_call: app "${input.appId}" is not installed or has no UI.`);
|
|
22046
|
+
}
|
|
22047
|
+
return dispatchAllowlistedAppTool(tools, input, deps2);
|
|
22048
|
+
}
|
|
21989
22049
|
function refIdOf(ref) {
|
|
21990
22050
|
if (typeof ref === "string") return ref;
|
|
21991
22051
|
return ref.ref ?? ref.file ?? "inline";
|
|
@@ -22871,7 +22931,7 @@ var STANDALONE_REST_BRIDGE_SCRIPT = `<script>
|
|
|
22871
22931
|
return res.json().catch(function () {
|
|
22872
22932
|
throw new Error("tool-call failed: HTTP " + res.status);
|
|
22873
22933
|
}).then(function (body) {
|
|
22874
|
-
if (!res.ok) throw new Error((body && body.error) || ("tool-call failed: HTTP " + res.status));
|
|
22934
|
+
if (!res.ok) throw new Error((body && (body.message || body.error)) || ("tool-call failed: HTTP " + res.status));
|
|
22875
22935
|
return body;
|
|
22876
22936
|
});
|
|
22877
22937
|
});
|
|
@@ -26688,6 +26748,7 @@ var DEFAULT_ALLOWED_ORIGINS = [
|
|
|
26688
26748
|
// matching how guilde.work is trusted. Drop it via `strictOrigins`.
|
|
26689
26749
|
"https://cli.agentproto.sh"
|
|
26690
26750
|
];
|
|
26751
|
+
var DEFAULT_FRAME_ANCESTORS = ["vscode-webview:"];
|
|
26691
26752
|
var PROXY_FORWARDING_HEADERS = [
|
|
26692
26753
|
"x-forwarded-for",
|
|
26693
26754
|
"forwarded",
|
|
@@ -28050,7 +28111,8 @@ async function startHttpServer(opts) {
|
|
|
28050
28111
|
req,
|
|
28051
28112
|
res,
|
|
28052
28113
|
decodeURIComponent(uiMatch[1]),
|
|
28053
|
-
opts.appRegistry
|
|
28114
|
+
opts.appRegistry,
|
|
28115
|
+
[...DEFAULT_FRAME_ANCESTORS, ...opts.frameAncestors ?? []]
|
|
28054
28116
|
);
|
|
28055
28117
|
return;
|
|
28056
28118
|
}
|
|
@@ -28601,7 +28663,9 @@ function parseMcpServersField(raw) {
|
|
|
28601
28663
|
servers.push({
|
|
28602
28664
|
name: o.name,
|
|
28603
28665
|
transport: o.transport,
|
|
28604
|
-
...typeof o.ref === "string" ? { ref: o.ref } : {}
|
|
28666
|
+
...typeof o.ref === "string" ? { ref: o.ref } : {},
|
|
28667
|
+
...isStringRecord(o.headers) ? { headers: o.headers } : {},
|
|
28668
|
+
...typeof o.credentialRef === "string" ? { credentialRef: o.credentialRef } : {}
|
|
28605
28669
|
});
|
|
28606
28670
|
}
|
|
28607
28671
|
return servers;
|
|
@@ -28795,10 +28859,13 @@ async function handleSessions(req, res, path, registry, resolveAgentAdapter, pty
|
|
|
28795
28859
|
const queryString = reqUrl.includes("?") ? reqUrl.slice(reqUrl.indexOf("?") + 1) : "";
|
|
28796
28860
|
const params = new URLSearchParams(queryString);
|
|
28797
28861
|
const includeArchived = params.get("includeArchived") === "true";
|
|
28862
|
+
const laneParam = params.get("lane");
|
|
28863
|
+
const lane = laneParam === "agents" || laneParam === "auto" ? laneParam : void 0;
|
|
28798
28864
|
const limit = Number.parseInt(params.get("limit") ?? "", 10);
|
|
28799
28865
|
const offset = Number.parseInt(params.get("offset") ?? "", 10);
|
|
28800
28866
|
const result = registry.listSummaries({
|
|
28801
28867
|
includeArchived,
|
|
28868
|
+
lane,
|
|
28802
28869
|
limit: Number.isNaN(limit) ? void 0 : limit,
|
|
28803
28870
|
offset: Number.isNaN(offset) ? void 0 : offset
|
|
28804
28871
|
});
|
|
@@ -30749,33 +30816,43 @@ async function handleProviderInbound(req, res, slug, deps2) {
|
|
|
30749
30816
|
res.writeHead(200, { "content-type": "application/json" });
|
|
30750
30817
|
res.end(JSON.stringify(result));
|
|
30751
30818
|
}
|
|
30752
|
-
|
|
30819
|
+
function requestHttpBaseUrl(req) {
|
|
30820
|
+
return `http://${req.headers.host ?? "127.0.0.1"}`;
|
|
30821
|
+
}
|
|
30822
|
+
async function handleAppUiPage(req, res, appId, appRegistry, frameAncestors) {
|
|
30753
30823
|
const app = appRegistry.getApp(appId);
|
|
30754
|
-
|
|
30824
|
+
const builtin = app?.ui ? void 0 : resolveBuiltinPanelUi(appId, requestHttpBaseUrl(req));
|
|
30825
|
+
if (!app?.ui && !builtin) {
|
|
30755
30826
|
res.writeHead(404, { "content-type": "application/json" });
|
|
30756
30827
|
res.end(JSON.stringify({ error: `app "${appId}" is not installed or has no UI.` }));
|
|
30757
30828
|
return;
|
|
30758
30829
|
}
|
|
30759
30830
|
let raw;
|
|
30760
|
-
|
|
30761
|
-
|
|
30762
|
-
|
|
30763
|
-
|
|
30764
|
-
|
|
30765
|
-
|
|
30766
|
-
|
|
30767
|
-
|
|
30768
|
-
|
|
30769
|
-
|
|
30831
|
+
if (app?.ui) {
|
|
30832
|
+
try {
|
|
30833
|
+
raw = await readFile(app.ui.path, "utf8");
|
|
30834
|
+
} catch (err) {
|
|
30835
|
+
res.writeHead(500, { "content-type": "application/json" });
|
|
30836
|
+
res.end(
|
|
30837
|
+
JSON.stringify({
|
|
30838
|
+
error: `could not read app "${appId}"'s ui html at "${app.ui.path}": ${err instanceof Error ? err.message : String(err)}`
|
|
30839
|
+
})
|
|
30840
|
+
);
|
|
30841
|
+
return;
|
|
30842
|
+
}
|
|
30843
|
+
} else {
|
|
30844
|
+
raw = builtin.html;
|
|
30770
30845
|
}
|
|
30771
30846
|
const embedRequested = new URL(req.url ?? "/", "http://localhost").searchParams.get("embed") === "1";
|
|
30772
30847
|
const headers = {
|
|
30773
30848
|
"content-type": "text/html; charset=utf-8",
|
|
30774
30849
|
"cache-control": "no-store"
|
|
30775
30850
|
};
|
|
30776
|
-
if (!(embedRequested && iframeEmbedAllowed(req, app))) {
|
|
30777
|
-
headers["
|
|
30778
|
-
|
|
30851
|
+
if (!(embedRequested && iframeEmbedAllowed(req, app ?? {}))) {
|
|
30852
|
+
headers["content-security-policy"] = `frame-ancestors 'self' ${frameAncestors.join(" ")}`.trimEnd();
|
|
30853
|
+
if (frameAncestors.length === 0) {
|
|
30854
|
+
headers["x-frame-options"] = "SAMEORIGIN";
|
|
30855
|
+
}
|
|
30779
30856
|
}
|
|
30780
30857
|
res.writeHead(200, headers);
|
|
30781
30858
|
res.end(injectStandaloneAppBridge(raw));
|
|
@@ -30911,7 +30988,12 @@ async function handleAppUiToolCall(req, res, appId, appRegistry, deps2) {
|
|
|
30911
30988
|
tool = inner.tool;
|
|
30912
30989
|
args = inner.args && typeof inner.args === "object" && !Array.isArray(inner.args) ? inner.args : {};
|
|
30913
30990
|
}
|
|
30914
|
-
const
|
|
30991
|
+
const installed = appRegistry.getApp(appId);
|
|
30992
|
+
const result = installed?.ui ? await performAppToolCall(appRegistry, { appId, tool, args }, deps2) : await performBuiltinPanelToolCall(
|
|
30993
|
+
resolveBuiltinPanelUi(appId, requestHttpBaseUrl(req))?.tools,
|
|
30994
|
+
{ appId, tool, args },
|
|
30995
|
+
deps2
|
|
30996
|
+
);
|
|
30915
30997
|
res.writeHead(200, { "content-type": "application/json" });
|
|
30916
30998
|
res.end(JSON.stringify(result));
|
|
30917
30999
|
}
|