@axiom-lattice/core 6.4.0 → 6.4.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/dist/index.d.mts +38 -3
- package/dist/index.d.ts +38 -3
- package/dist/index.js +225 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +224 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -13293,6 +13293,12 @@ function capResult(result, cap) {
|
|
|
13293
13293
|
const serialized = typeof result === "string" ? result : JSON.stringify(result ?? null);
|
|
13294
13294
|
return Buffer.byteLength(serialized, "utf8") <= cap ? result : truncate(serialized, cap);
|
|
13295
13295
|
}
|
|
13296
|
+
function handlerResultText(result) {
|
|
13297
|
+
const value = result.result;
|
|
13298
|
+
if (typeof value === "string") return value;
|
|
13299
|
+
if (value === void 0) return (result.stdout ?? "").trim();
|
|
13300
|
+
return JSON.stringify(value);
|
|
13301
|
+
}
|
|
13296
13302
|
function errorFromStdout(stdout) {
|
|
13297
13303
|
let text = stdout;
|
|
13298
13304
|
try {
|
|
@@ -14224,7 +14230,7 @@ function compileSandboxPlugin(args) {
|
|
|
14224
14230
|
maxResultBytes: t.maxResultBytes
|
|
14225
14231
|
});
|
|
14226
14232
|
if (!result.ok) return result.error ?? "sandbox plugin execution failed";
|
|
14227
|
-
const text =
|
|
14233
|
+
const text = handlerResultText(result);
|
|
14228
14234
|
const ref = t.ui ? { kind: "plugin", pluginType: manifest.type, resource: t.ui.resource, displayMode: t.ui.displayMode ?? "inline" } : null;
|
|
14229
14235
|
return ref ? appendUiFence(text, ref) : text;
|
|
14230
14236
|
},
|
|
@@ -14620,7 +14626,7 @@ var TenantPluginCatalog = class {
|
|
|
14620
14626
|
// src/sandbox_plugin/sandboxPluginRuntime.ts
|
|
14621
14627
|
var catalog = null;
|
|
14622
14628
|
function buildResidentRouting() {
|
|
14623
|
-
const baseUrl = process.env.
|
|
14629
|
+
const baseUrl = process.env.MICROSANDBOX_SERVICE_BASE_URL;
|
|
14624
14630
|
if (!baseUrl) return void 0;
|
|
14625
14631
|
return {
|
|
14626
14632
|
getDeployment: async (tenantId2, pluginType) => await getPluginDeploymentService()?.getDeployment(tenantId2, pluginType) ?? void 0,
|
|
@@ -33447,7 +33453,9 @@ var MicrosandboxServiceClient = class {
|
|
|
33447
33453
|
}
|
|
33448
33454
|
} catch {
|
|
33449
33455
|
}
|
|
33450
|
-
|
|
33456
|
+
const error = new Error(`Microsandbox service request failed: ${detail}`);
|
|
33457
|
+
error.statusCode = response.status;
|
|
33458
|
+
throw error;
|
|
33451
33459
|
}
|
|
33452
33460
|
const payload = await response.json();
|
|
33453
33461
|
if (payload?.success === false) {
|
|
@@ -36896,6 +36904,7 @@ var OutboxPoller = class {
|
|
|
36896
36904
|
};
|
|
36897
36905
|
|
|
36898
36906
|
// src/services/ProjectMutationMutex.ts
|
|
36907
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
36899
36908
|
import { snapshotExactRecord as snapshotExactRecord4 } from "@axiom-lattice/protocols";
|
|
36900
36909
|
|
|
36901
36910
|
// src/services/coordinationLease.ts
|
|
@@ -36965,16 +36974,24 @@ var ProjectMutationMutex = class {
|
|
|
36965
36974
|
constructor() {
|
|
36966
36975
|
this.queues = /* @__PURE__ */ new Map();
|
|
36967
36976
|
this.active = /* @__PURE__ */ new Set();
|
|
36977
|
+
/** Project keys already held by the current async context (reentrancy). */
|
|
36978
|
+
this.held = new AsyncLocalStorage2();
|
|
36968
36979
|
}
|
|
36969
36980
|
/** Runs one mutation after all earlier mutations for the same Tenant and Project. */
|
|
36970
36981
|
async runExclusive(scope, operation, signal) {
|
|
36971
36982
|
const key5 = projectKey(scope);
|
|
36983
|
+
const inherited = this.held.getStore();
|
|
36984
|
+
if (inherited?.has(key5)) return operation();
|
|
36972
36985
|
const leaseKey = `project-mutation:${encodeURIComponent(scope.tenantId)}:${encodeURIComponent(scope.projectId)}`;
|
|
36973
36986
|
await this.acquire(key5, signal);
|
|
36987
|
+
const held = new Set(inherited);
|
|
36988
|
+
held.add(key5);
|
|
36974
36989
|
try {
|
|
36975
|
-
|
|
36976
|
-
|
|
36977
|
-
|
|
36990
|
+
return await this.held.run(held, async () => {
|
|
36991
|
+
const store = getCoordinationLeaseStore();
|
|
36992
|
+
if (!store) return await operation();
|
|
36993
|
+
return await withLease(store, leaseKey, getReplicaId(), operation, MUTATION_LEASE_OPTIONS);
|
|
36994
|
+
});
|
|
36978
36995
|
} finally {
|
|
36979
36996
|
this.release(key5);
|
|
36980
36997
|
}
|
|
@@ -37048,6 +37065,7 @@ var INPUT_KEYS = [
|
|
|
37048
37065
|
];
|
|
37049
37066
|
var REPLY_INPUT_KEYS = ["tenantId", "membershipId", "text", "sourceRoomMessageId", "inputMessageId", "sourceId", "idempotencyKey"];
|
|
37050
37067
|
var INTERRUPT_INPUT_KEYS = ["tenantId", "membershipId", "text", "sourceRoomMessageId", "inputMessageId"];
|
|
37068
|
+
var CORRELATED_INTERRUPT_INPUT_KEYS = ["tenantId", "membershipId", "correlationKey", "text"];
|
|
37051
37069
|
var RoomAgentMessageService = class {
|
|
37052
37070
|
/**
|
|
37053
37071
|
* Creates a room writer over the durable membership and message stores.
|
|
@@ -37095,6 +37113,50 @@ var RoomAgentMessageService = class {
|
|
|
37095
37113
|
idempotencyKey: `room-interrupt:${snapshot.sourceRoomMessageId}:${snapshot.membershipId}:${sourceId}`
|
|
37096
37114
|
});
|
|
37097
37115
|
}
|
|
37116
|
+
/**
|
|
37117
|
+
* Persists a correlated HITL interrupt that has no human source message.
|
|
37118
|
+
*
|
|
37119
|
+
* @param input Explicit tenant, active membership, caller-supplied correlation key, and text.
|
|
37120
|
+
* @returns A deep clone of the canonical idempotent room message.
|
|
37121
|
+
* @remarks Business-agnostic: the caller owns the correlation key. Scope is
|
|
37122
|
+
* validated against the durable membership; no source message is required.
|
|
37123
|
+
*/
|
|
37124
|
+
postCorrelatedInterrupt(input) {
|
|
37125
|
+
const snapshot = exactStringRecord(input, CORRELATED_INTERRUPT_INPUT_KEYS, "Invalid project room interrupt input");
|
|
37126
|
+
return this.persistScoped({
|
|
37127
|
+
tenantId: snapshot.tenantId,
|
|
37128
|
+
membershipId: snapshot.membershipId,
|
|
37129
|
+
text: snapshot.text,
|
|
37130
|
+
sourceId: `interrupt:${snapshot.correlationKey}`,
|
|
37131
|
+
idempotencyKey: `room-interrupt:${snapshot.membershipId}:${snapshot.correlationKey}`
|
|
37132
|
+
});
|
|
37133
|
+
}
|
|
37134
|
+
async persistScoped(input) {
|
|
37135
|
+
const text = input.text.trim();
|
|
37136
|
+
if (text.length < 1 || text.length > 2e4) throw new Error("Invalid project room message text");
|
|
37137
|
+
const member = snapshotMembership(await this.deps.memberships.findById(input.tenantId, input.membershipId));
|
|
37138
|
+
if (!member || member.id !== input.membershipId || member.status !== "active" || member.tenantId !== input.tenantId) {
|
|
37139
|
+
throw new Error("Invalid project room membership");
|
|
37140
|
+
}
|
|
37141
|
+
const candidate = {
|
|
37142
|
+
id: (this.deps.idFactory ?? randomUUID10)(),
|
|
37143
|
+
tenantId: member.tenantId,
|
|
37144
|
+
workspaceId: member.workspaceId,
|
|
37145
|
+
projectId: member.projectId,
|
|
37146
|
+
roomId: member.roomId,
|
|
37147
|
+
author: { type: "bot", membershipId: member.id, assistantId: member.assistantId },
|
|
37148
|
+
content: { type: "text", text },
|
|
37149
|
+
mentions: [],
|
|
37150
|
+
source: "agent",
|
|
37151
|
+
sourceId: input.sourceId,
|
|
37152
|
+
idempotencyKey: input.idempotencyKey
|
|
37153
|
+
};
|
|
37154
|
+
const canonical = snapshotCanonicalScoped(await this.deps.messages.createIdempotent(candidate), candidate);
|
|
37155
|
+
if (!canonical) throw new Error("Invalid canonical project room message");
|
|
37156
|
+
const result = structuredClone(canonical);
|
|
37157
|
+
this.notifyCommitted(result);
|
|
37158
|
+
return result;
|
|
37159
|
+
}
|
|
37098
37160
|
async persistDerived(input) {
|
|
37099
37161
|
const source = snapshotSource(await this.deps.messages.findById(input.tenantId, input.sourceRoomMessageId));
|
|
37100
37162
|
if (!source || source.id !== input.sourceRoomMessageId || source.tenantId !== input.tenantId) throw new Error("Invalid project room message");
|
|
@@ -37250,6 +37312,27 @@ function snapshotCanonical(value, expected) {
|
|
|
37250
37312
|
createdAt
|
|
37251
37313
|
};
|
|
37252
37314
|
}
|
|
37315
|
+
function snapshotCanonicalScoped(value, expected) {
|
|
37316
|
+
const values = exactValues(value, ["id", "tenantId", "workspaceId", "projectId", "roomId", "author", "content", "mentions", "source", "sourceId", "idempotencyKey", "createdAt"], ["replyToMessageId"]);
|
|
37317
|
+
const author = exactValues(values?.author, ["type", "membershipId", "assistantId"]);
|
|
37318
|
+
const content = exactValues(values?.content, ["type", "text"]);
|
|
37319
|
+
const createdAt = date(values?.createdAt);
|
|
37320
|
+
if (!values || !createdAt || typeof values.id !== "string" || values.id.length === 0 || snapshotExactArray(values.mentions)?.length !== 0 || author?.type !== "bot" || expected.author.type !== "bot" || author.membershipId !== expected.author.membershipId || author.assistantId !== expected.author.assistantId || content?.type !== "text" || content.text !== expected.content.text || values.tenantId !== expected.tenantId || values.workspaceId !== expected.workspaceId || values.projectId !== expected.projectId || values.roomId !== expected.roomId || values.source !== "agent" || values.sourceId !== expected.sourceId || values.idempotencyKey !== expected.idempotencyKey) return void 0;
|
|
37321
|
+
return {
|
|
37322
|
+
id: values.id,
|
|
37323
|
+
tenantId: expected.tenantId,
|
|
37324
|
+
workspaceId: expected.workspaceId,
|
|
37325
|
+
projectId: expected.projectId,
|
|
37326
|
+
roomId: expected.roomId,
|
|
37327
|
+
author: { type: "bot", membershipId: expected.author.membershipId, assistantId: expected.author.assistantId },
|
|
37328
|
+
content: { type: "text", text: expected.content.text },
|
|
37329
|
+
mentions: [],
|
|
37330
|
+
source: "agent",
|
|
37331
|
+
sourceId: expected.sourceId,
|
|
37332
|
+
idempotencyKey: expected.idempotencyKey,
|
|
37333
|
+
createdAt
|
|
37334
|
+
};
|
|
37335
|
+
}
|
|
37253
37336
|
|
|
37254
37337
|
// src/services/ProjectTaskOwnerPolicy.ts
|
|
37255
37338
|
import { snapshotExactRecord as snapshotExactRecord6 } from "@axiom-lattice/protocols";
|
|
@@ -47129,6 +47212,18 @@ On top of that, add any of three combinable classes:
|
|
|
47129
47212
|
## Combinations
|
|
47130
47213
|
A plugin is the SET of classes it needs, e.g. \`connection + tools + skills\` or \`UI + connection\`.
|
|
47131
47214
|
|
|
47215
|
+
## Scenarios \u2192 skills
|
|
47216
|
+
| Scenario | Read |
|
|
47217
|
+
|---|---|
|
|
47218
|
+
| Tool that returns/transforms data | \`sandbox-plugins-manifest\` + \`sandbox-plugins-handlers\` |
|
|
47219
|
+
| Skills-only (procedural knowledge, no tools) | \`sandbox-plugins-authoring\` (skills) |
|
|
47220
|
+
| Tool needs credentials / resource discovery | \`sandbox-plugins-connection\` |
|
|
47221
|
+
| Tool shows an interactive panel | \`sandbox-plugins-ui\` |
|
|
47222
|
+
| Tool orchestrates platform tools/agents | \`sandbox-plugins-consume-open\` |
|
|
47223
|
+
| Tool callable by external MCP clients | \`sandbox-plugins-expose\` |
|
|
47224
|
+
| Run as a long-lived resident service | \`sandbox-plugins-deploy\` |
|
|
47225
|
+
| Validate / test / debug | \`sandbox-plugins-testing\` |
|
|
47226
|
+
|
|
47132
47227
|
## Agents (not a supported authoring path)
|
|
47133
47228
|
The manifest schema accepts an \`agents\` block and tenant plugin agents are
|
|
47134
47229
|
registered, but building agents this way is not supported or designed for tenant
|
|
@@ -47339,10 +47434,38 @@ lifecycle handshake:
|
|
|
47339
47434
|
- \`ui/notifications/tool-result\` \u2192 a \`CallToolResult\` \`{ content: [{ type: "text", text }] }\` (the tool output text, with any \`mcp_app\` fence stripped).
|
|
47340
47435
|
|
|
47341
47436
|
Register the \`message\` listener **before** \`ui/initialize\` so nothing is missed.
|
|
47342
|
-
|
|
47343
|
-
|
|
47344
|
-
|
|
47345
|
-
|
|
47437
|
+
Read the payload from \`params.content[0].text\` \u2014 the notification is a
|
|
47438
|
+
\`CallToolResult\`, **not** your handler payload at the top level. The result
|
|
47439
|
+
carries **TEXT content only** \u2014 no \`structuredContent\` or \`artifact\`; parse the
|
|
47440
|
+
JSON yourself if the tool emitted JSON (it is the handler's \`result\`, so the
|
|
47441
|
+
handler must wrap it under \`result\`). To re-query or refresh, call \`tools/call\`
|
|
47442
|
+
from the View and render its response (the host does not re-push \`tool-result\`
|
|
47443
|
+
for your own calls).
|
|
47444
|
+
|
|
47445
|
+
When you call \`tools/call\` from the View, the JSON-RPC response \`result\` is the
|
|
47446
|
+
handler's own \`result\` value **directly** \u2014 it is **not wrapped in a**
|
|
47447
|
+
\`CallToolResult\` \`{ content: [...] }\` (that wrapper is only used for the host's
|
|
47448
|
+
\`tool-result\` push). Parse it as your tool's data.
|
|
47449
|
+
|
|
47450
|
+
## Push vs re-execute (key for debugging)
|
|
47451
|
+
The host pushes \`tool-result\` from the tool result **recorded when the agent ran** \u2014
|
|
47452
|
+
it does **not** re-execute the handler. The push therefore always reflects that
|
|
47453
|
+
run's output (and the handler's \`result\` at that time). A \`tools/call\` from the
|
|
47454
|
+
View, by contrast, **re-executes** the handler live every time.
|
|
47455
|
+
|
|
47456
|
+
So if the push looks stale/wrong but a fresh \`tools/call\` returns the right data,
|
|
47457
|
+
the recorded run predates your change \u2014 re-run the tool (a new agent call) to get
|
|
47458
|
+
a fresh push. Do not assume the push re-reads the handler.
|
|
47459
|
+
|
|
47460
|
+
## Self-check / debug
|
|
47461
|
+
- Log the raw frame: \`console.log(JSON.stringify(ev.data))\` in the \`message\`
|
|
47462
|
+
listener, and open the browser console inside the sandboxed frame.
|
|
47463
|
+
- If the pushed text looks like the raw handler envelope (e.g. it starts with
|
|
47464
|
+
\`{"ok":true,...\`), the handler omitted the \`result\` wrapper \u2014 the host falls
|
|
47465
|
+
back to the raw stdout instead of your payload. Fix the handler (see
|
|
47466
|
+
\`sandbox-plugins-handlers\`).
|
|
47467
|
+
- The push only happens after \`ui/initialize\` **and**
|
|
47468
|
+
\`ui/notifications/initialized\`; a listener registered later misses it.
|
|
47346
47469
|
|
|
47347
47470
|
\`templates/ui.html\` implements all of this in vanilla JS and renders both payloads
|
|
47348
47471
|
into a \`#data\` element.
|
|
@@ -47462,6 +47585,76 @@ Templates: see \`sandbox-plugins-manifest\` for the exact \`tools[]\` fields; th
|
|
|
47462
47585
|
\`templates/plugin.json\` already includes \`"expose": true\` (the tool is grantable via
|
|
47463
47586
|
an API key but not callable until a key grants it). Remove it for tools that should
|
|
47464
47587
|
not be externally grantable at all.
|
|
47588
|
+
`,
|
|
47589
|
+
resources: {}
|
|
47590
|
+
},
|
|
47591
|
+
"sandbox-plugins-consume-open": {
|
|
47592
|
+
version: "1.0.0",
|
|
47593
|
+
content: `---
|
|
47594
|
+
name: sandbox-plugins-consume-open
|
|
47595
|
+
description: Call the platform's Open MCP surface from a tenant plugin handler (discover and invoke other tools/agents). Trigger: a plugin tool must orchestrate platform capabilities, call another tool or agent, or reuse an existing capability instead of re-implementing it.
|
|
47596
|
+
---
|
|
47597
|
+
|
|
47598
|
+
# Calling the platform from a handler (Open MCP)
|
|
47599
|
+
|
|
47600
|
+
A plugin handler can call **the platform's own tools and agents** through the Open
|
|
47601
|
+
MCP endpoint. Reach for this when a tool should orchestrate existing capabilities
|
|
47602
|
+
(read the knowledge base, create a task, invoke an agent) instead of
|
|
47603
|
+
re-implementing them.
|
|
47604
|
+
|
|
47605
|
+
## What the handler gets
|
|
47606
|
+
When the gateway injects the credential, each handler process starts with:
|
|
47607
|
+
- \`API_GATEWAY_URL\` \u2014 the gateway base URL.
|
|
47608
|
+
- \`OPEN_API_TOKEN\` \u2014 a short-lived bearer **scoped to this tenant's plugin callers**.
|
|
47609
|
+
|
|
47610
|
+
If the deployment does not inject them (no \`PUBLIC_GATEWAY_URL\`), the variables are
|
|
47611
|
+
**absent** \u2014 detect that and degrade gracefully (report "platform tools
|
|
47612
|
+
unavailable") rather than crashing.
|
|
47613
|
+
|
|
47614
|
+
## Discover, then call
|
|
47615
|
+
Never hardcode the tool list: the callable set is **reflected per tenant** and
|
|
47616
|
+
changes as plugins are exposed. Call \`listTools()\` at runtime.
|
|
47617
|
+
\`\`\`js
|
|
47618
|
+
const { OpenMcpClient } = require("@axiom-lattice/open-mcp-client");
|
|
47619
|
+
// or require("/root/.agents/sdk/open-mcp-client/index.js") when provisioned there
|
|
47620
|
+
|
|
47621
|
+
async function main() {
|
|
47622
|
+
const input = process.env.PLUGIN_INPUT_FILE
|
|
47623
|
+
? JSON.parse(require("fs").readFileSync(process.env.PLUGIN_INPUT_FILE, "utf8"))
|
|
47624
|
+
: JSON.parse(process.env.PLUGIN_INPUT || "{}");
|
|
47625
|
+
|
|
47626
|
+
const client = OpenMcpClient.fromEnv(); // API_GATEWAY_URL + OPEN_API_TOKEN
|
|
47627
|
+
const tools = await client.listTools(); // exactly what this handler may call
|
|
47628
|
+
const kb = await client.callTool("kb_search", { collection: "docs", query: input.q });
|
|
47629
|
+
|
|
47630
|
+
process.stdout.write(JSON.stringify({ ok: true, result: kb }));
|
|
47631
|
+
}
|
|
47632
|
+
main().catch((err) => {
|
|
47633
|
+
process.stdout.write(JSON.stringify({ ok: false, error: String(err && err.message ? err.message : err) }));
|
|
47634
|
+
});
|
|
47635
|
+
\`\`\`
|
|
47636
|
+
|
|
47637
|
+
- Tool names are \`{domain}_{action}\` (e.g. \`kb_search\`, \`task_manage_task\`).
|
|
47638
|
+
- Args follow the tool's \`inputSchema\`; \`listTools()\` returns name/description.
|
|
47639
|
+
- Return the result through the normal handler envelope (\`{ ok: true, result }\`)
|
|
47640
|
+
so it becomes this tool's output \u2014 see \`sandbox-plugins-handlers\`.
|
|
47641
|
+
|
|
47642
|
+
## What the handler may call
|
|
47643
|
+
The token carries the conservative sandbox defaults (\`sandbox_*\`, \`kb_search\`)
|
|
47644
|
+
**plus the tenant's grantable Open catalog**: every exposed tenant/global plugin
|
|
47645
|
+
tool and the tenant's agents. A call outside that set fails (tool-not-found or
|
|
47646
|
+
\`GRANT_DENIED\`); retrying will not help.
|
|
47647
|
+
|
|
47648
|
+
## Client availability
|
|
47649
|
+
The zero-dependency \`@axiom-lattice/open-mcp-client\` must be present in the
|
|
47650
|
+
sandbox: preinstalled in the image, at \`/root/.agents/sdk/open-mcp-client\`, or
|
|
47651
|
+
installed in this run (\`npm install @axiom-lattice/open-mcp-client\`). The CLI is
|
|
47652
|
+
also available: \`npx @axiom-lattice/open-mcp-client tools list --json\`.
|
|
47653
|
+
|
|
47654
|
+
## Limits
|
|
47655
|
+
- Nested sandbox orchestration is depth-limited (5); past the cap no token is
|
|
47656
|
+
re-issued, so deep recursion fails fast.
|
|
47657
|
+
- Only call what \`listTools()\` returns, and handle a missing tool gracefully.
|
|
47465
47658
|
`,
|
|
47466
47659
|
resources: {}
|
|
47467
47660
|
},
|
|
@@ -47502,10 +47695,23 @@ for the single/first connection, or \`data.connections\` (entries of
|
|
|
47502
47695
|
\`{ key, config }\`) when the plugin selects multiple connections.
|
|
47503
47696
|
|
|
47504
47697
|
## Writing output
|
|
47505
|
-
|
|
47698
|
+
Every tool handler must print **one** JSON envelope to stdout, with your payload
|
|
47699
|
+
under \`result\`:
|
|
47506
47700
|
\`\`\`js
|
|
47507
|
-
process.stdout.write(JSON.stringify({ ok: true, result:
|
|
47701
|
+
process.stdout.write(JSON.stringify({ ok: true, result: <payload> }));
|
|
47508
47702
|
\`\`\`
|
|
47703
|
+
|
|
47704
|
+
> **The payload MUST go under \`result\`.** \`result\` may be any JSON value
|
|
47705
|
+
> (object, array, string, number).
|
|
47706
|
+
> \`\`\`js
|
|
47707
|
+
> // \u2705 correct \u2014 data under \`result\`
|
|
47708
|
+
> process.stdout.write(JSON.stringify({ ok: true, result: { tasks, count } }));
|
|
47709
|
+
>
|
|
47710
|
+
> // \u274C wrong \u2014 \`result\` missing; the host surfaces the raw stdout (this
|
|
47711
|
+
> // envelope), so callers and MCP App UIs never see \`tasks\`
|
|
47712
|
+
> process.stdout.write(JSON.stringify({ ok: true, tasks, count }));
|
|
47713
|
+
> \`\`\`
|
|
47714
|
+
|
|
47509
47715
|
Non-JSON stdout is treated as a plain-text result. To fail, either print
|
|
47510
47716
|
\`{ ok: false, error }\` or exit non-zero (stderr is not required; stdout is
|
|
47511
47717
|
captured).
|
|
@@ -47691,6 +47897,8 @@ Follow the authoring skill's "Decide first" steps to confirm the goal
|
|
|
47691
47897
|
(inputs/outputs). If the UI class applies, load "sandbox-plugins-ui" before
|
|
47692
47898
|
authoring it. If the tool must be callable by external MCP clients via an API key,
|
|
47693
47899
|
load "sandbox-plugins-expose" and follow it (\`expose: true\` + key grants).
|
|
47900
|
+
If a tool must call the platform's own tools/agents from its handler, load
|
|
47901
|
+
"sandbox-plugins-consume-open".
|
|
47694
47902
|
|
|
47695
47903
|
Plan with persistent Tasks: MANDATORY until you load "task-tracking" with the
|
|
47696
47904
|
\`skill\` tool, call neither \`manage_task\` nor any other task operation. Use
|
|
@@ -47897,7 +48105,6 @@ var SANDBOX_PLUGINS_UI_REF = {
|
|
|
47897
48105
|
resource: SANDBOX_PLUGINS_UI_RESOURCE,
|
|
47898
48106
|
displayMode: "inline"
|
|
47899
48107
|
};
|
|
47900
|
-
var PLUGIN_BUILDER_SKILLS = [...Object.keys(SANDBOX_PLUGIN_SKILLS), "task-tracking"];
|
|
47901
48108
|
function tenantIdFrom(exeConfig) {
|
|
47902
48109
|
const c = exeConfig;
|
|
47903
48110
|
return c?.configurable?.runConfig?.tenantId ?? "default";
|
|
@@ -48013,9 +48220,9 @@ var sandboxPluginsPlugin = {
|
|
|
48013
48220
|
id: "skill",
|
|
48014
48221
|
type: "skill",
|
|
48015
48222
|
name: "Skill",
|
|
48016
|
-
description: "Load the sandbox-plugins authoring, patterns, manifest, handler, connection, UI, and testing skills",
|
|
48223
|
+
description: "Load any available skill, including the sandbox-plugins authoring, patterns, manifest, handler, connection, UI, and testing skills",
|
|
48017
48224
|
enabled: true,
|
|
48018
|
-
config: { readAll:
|
|
48225
|
+
config: { readAll: true }
|
|
48019
48226
|
},
|
|
48020
48227
|
{
|
|
48021
48228
|
id: "task",
|
|
@@ -48196,7 +48403,7 @@ var sandboxPluginsPlugin = {
|
|
|
48196
48403
|
assistantId: typeof runCfg.assistant_id === "string" ? runCfg.assistant_id : void 0
|
|
48197
48404
|
}
|
|
48198
48405
|
});
|
|
48199
|
-
return
|
|
48406
|
+
return handlerResultText(redactSecretValues(result, secrets));
|
|
48200
48407
|
} catch (err) {
|
|
48201
48408
|
return JSON.stringify(redactSecretValues({ ok: false, error: errorText(err) }, secrets));
|
|
48202
48409
|
}
|
|
@@ -49573,6 +49780,7 @@ export {
|
|
|
49573
49780
|
globSearchFiles,
|
|
49574
49781
|
grepMatchesFromFiles,
|
|
49575
49782
|
grepSearchFiles,
|
|
49783
|
+
handlerResultText,
|
|
49576
49784
|
hasChunkBuffer,
|
|
49577
49785
|
hasDelegatedWorkerToken,
|
|
49578
49786
|
hasRuntimeCapabilityPolicy,
|