@nylorun/runtime 0.27.0-beta → 0.29.0-beta
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/CHANGELOG.md +67 -0
- package/README.md +1 -1
- package/dist/api/a2a/card.d.ts +4 -3
- package/dist/api/a2a/card.js +3 -3
- package/dist/api/a2a/routes.js +18 -7
- package/dist/api/ag-ui/routes.js +4 -7
- package/dist/api/components.d.ts +5854 -2718
- package/dist/api/components.js +39 -30
- package/dist/api/http/app.js +9 -4
- package/dist/api/http/body.d.ts +2 -0
- package/dist/api/http/body.js +20 -0
- package/dist/api/http/define.d.ts +4 -0
- package/dist/api/http/define.js +20 -9
- package/dist/api/http/routes/agent-manifests.d.ts +10 -0
- package/dist/api/http/routes/agent-manifests.js +135 -0
- package/dist/api/http/routes/agents.d.ts +11 -0
- package/dist/api/http/routes/agents.js +418 -0
- package/dist/api/http/routes/artifacts.js +2 -2
- package/dist/api/http/routes/coverage.d.ts +4 -4
- package/dist/api/http/routes/coverage.js +12 -6
- package/dist/api/http/routes/files.js +1 -1
- package/dist/api/http/routes/mcp.js +2 -2
- package/dist/api/http/routes/me.d.ts +1 -1
- package/dist/api/http/routes/me.js +1 -2
- package/dist/api/http/routes/memories.d.ts +9 -0
- package/dist/api/http/routes/memories.js +152 -0
- package/dist/api/http/routes/reads.d.ts +1 -137
- package/dist/api/http/routes/reads.js +31 -12
- package/dist/api/http/routes/sessions.js +21 -50
- package/dist/api/http/routes/tenant.js +13 -10
- package/dist/api/http/routes/triggers.d.ts +10 -0
- package/dist/api/http/routes/triggers.js +183 -0
- package/dist/api/openapi.js +69 -47
- package/dist/artifacts/disk.d.ts +10 -10
- package/dist/artifacts/disk.js +27 -27
- package/dist/artifacts/quota.d.ts +1 -1
- package/dist/artifacts/quota.js +2 -2
- package/dist/artifacts/service.js +2 -2
- package/dist/core/flow-host.d.ts +0 -1
- package/dist/gates/egress-credentials.js +1 -1
- package/dist/gates/egress.d.ts +5 -5
- package/dist/gates/egress.js +6 -6
- package/dist/gates/http-tool.js +2 -2
- package/dist/gates/meter.js +22 -5
- package/dist/gates/policy.d.ts +8 -3
- package/dist/gates/policy.js +7 -2
- package/dist/gates/tenant-vaults.d.ts +1 -1
- package/dist/harness/pod.d.ts +2 -0
- package/dist/harness/setup.js +17 -6
- package/dist/harness-api/record.js +11 -0
- package/dist/harness-api/server.js +4 -0
- package/dist/harness-api/start.d.ts +11 -7
- package/dist/harness-api/start.js +49 -5
- package/dist/harness-api/workspace.js +2 -2
- package/dist/host/config-for.d.ts +2 -0
- package/dist/host/config-for.js +1 -0
- package/dist/host/http.d.ts +2 -2
- package/dist/host/http.js +5 -2
- package/dist/host/main.js +1 -0
- package/dist/keys/keys.d.ts +15 -4
- package/dist/keys/keys.js +16 -0
- package/dist/keys/webhooks.d.ts +25 -0
- package/dist/keys/webhooks.js +62 -0
- package/dist/management-openapi.json +313 -133
- package/dist/mcp/connect.d.ts +2 -2
- package/dist/mcp/connect.js +3 -3
- package/dist/mcp/preview.js +7 -7
- package/dist/memory/service.d.ts +97 -0
- package/dist/memory/service.js +335 -0
- package/dist/memory/tool.d.ts +36 -0
- package/dist/memory/tool.js +84 -0
- package/dist/model/pi-model.js +7 -0
- package/dist/openapi.json +13120 -9034
- package/dist/reads/types.d.ts +3 -3
- package/dist/record/agent.d.ts +27 -0
- package/dist/record/agent.js +46 -0
- package/dist/record/index.d.ts +1 -1
- package/dist/record/index.js +1 -1
- package/dist/sandbox/join.js +5 -5
- package/dist/sandbox/placement.d.ts +1 -1
- package/dist/sandbox/placement.js +3 -3
- package/dist/sandbox/pods/lifecycle.d.ts +6 -6
- package/dist/sandbox/pods/lifecycle.js +6 -6
- package/dist/sandbox/pods/reconcile.js +10 -2
- package/dist/sandbox/resolve.d.ts +3 -3
- package/dist/sandbox/resolve.js +7 -7
- package/dist/sandbox/setup.d.ts +3 -1
- package/dist/sandbox/setup.js +14 -4
- package/dist/store/postgres/drizzle/0032_agents.sql +54 -0
- package/dist/store/postgres/drizzle/0033_agent_versions.sql +7 -0
- package/dist/store/postgres/drizzle/0034_protocol_17_session_queue.sql +13 -0
- package/dist/store/postgres/drizzle/0035_t4_triggers.sql +41 -0
- package/dist/store/postgres/drizzle/0036_t5_memories.sql +30 -0
- package/dist/store/postgres/drizzle/0037_model_usage_cost_split.sql +4 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +42 -0
- package/dist/store/postgres/reads.js +44 -87
- package/dist/store/postgres/record-writer.d.ts +4 -4
- package/dist/store/postgres/record-writer.js +9 -9
- package/dist/store/postgres/schema.d.ts +1408 -123
- package/dist/store/postgres/schema.js +194 -38
- package/dist/store/postgres/store.js +329 -79
- package/dist/store/postgres/tenant.js +1 -2
- package/dist/store/types.d.ts +155 -50
- package/dist/store/types.js +0 -1
- package/dist/tenant/advance.js +20 -8
- package/dist/tenant/agent-manifests.d.ts +72 -0
- package/dist/tenant/agent-manifests.js +359 -0
- package/dist/tenant/agent-versions.d.ts +126 -0
- package/dist/tenant/agent-versions.js +389 -0
- package/dist/tenant/agents.d.ts +230 -0
- package/dist/tenant/{environments.js → agents.js} +464 -320
- package/dist/tenant/auth.d.ts +1 -1
- package/dist/tenant/auth.js +3 -3
- package/dist/tenant/commands.d.ts +63 -2
- package/dist/tenant/commands.js +240 -83
- package/dist/tenant/context.d.ts +46 -19
- package/dist/tenant/context.js +6 -2
- package/dist/tenant/effects.js +7 -16
- package/dist/tenant/identity-file.d.ts +6 -6
- package/dist/tenant/identity-file.js +12 -10
- package/dist/tenant/issuers.js +3 -3
- package/dist/tenant/limits.d.ts +0 -3
- package/dist/tenant/limits.js +0 -3
- package/dist/tenant/memories.d.ts +38 -0
- package/dist/tenant/memories.js +119 -0
- package/dist/tenant/reset.js +2 -2
- package/dist/tenant/run-grants.d.ts +6 -0
- package/dist/tenant/run-grants.js +4 -0
- package/dist/tenant/runtime.d.ts +1 -1
- package/dist/tenant/runtime.js +8 -0
- package/dist/tenant/sessions.d.ts +28 -45
- package/dist/tenant/sessions.js +85 -208
- package/dist/tenant/status.js +6 -7
- package/dist/tenant/sweep.js +12 -3
- package/dist/tenant/transcript.d.ts +16 -16
- package/dist/tenant/triggers.d.ts +143 -0
- package/dist/tenant/triggers.js +715 -0
- package/dist/tenant/turn-timing.d.ts +11 -1
- package/dist/tenant/turn-timing.js +3 -1
- package/dist/tenant/types.d.ts +5 -0
- package/dist/tenant/worker.d.ts +2 -0
- package/dist/tenant/worker.js +5 -0
- package/dist/traces/map.d.ts +1 -1
- package/dist/traces/map.js +7 -1
- package/dist/tuning.d.ts +7 -0
- package/dist/tuning.js +19 -0
- package/dist/vault/service.d.ts +13 -8
- package/dist/vault/service.js +61 -17
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +13 -12
- package/dist/api/http/routes/environment-manifests.d.ts +0 -9
- package/dist/api/http/routes/environment-manifests.js +0 -118
- package/dist/api/http/routes/environments.d.ts +0 -11
- package/dist/api/http/routes/environments.js +0 -332
- package/dist/record/environment.d.ts +0 -27
- package/dist/record/environment.js +0 -46
- package/dist/tenant/environment-manifests.d.ts +0 -57
- package/dist/tenant/environment-manifests.js +0 -208
- package/dist/tenant/environments.d.ts +0 -172
package/dist/tenant/sessions.js
CHANGED
|
@@ -1,118 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Session
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Session resources: `PUT /v1/sessions/:id` (create, or find an identical one), the session list
|
|
3
|
+
* and the session view. A session runs on one Agent (protocol 16) and pins the manifest version
|
|
4
|
+
* the Agent runs when it opens; each turn takes the version the Agent runs then
|
|
5
|
+
* (`agent-versions.ts`). Reads use the store's typed queries; `PUT /v1/sessions/:id` runs in
|
|
6
|
+
* one transaction with the Agent's checks.
|
|
5
7
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import { hashManifest } from "@nylorun/core/compatibility";
|
|
8
|
-
import { approvalRefusal, codeToolRefusal } from "@nylorun/core/define";
|
|
8
|
+
import {} from "@nylorun/core/contracts";
|
|
9
9
|
import { aggregateWaits, isWorkflowManifest } from "../core/flow-host.js";
|
|
10
10
|
import { canonical } from "../store/canonical.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { harnessOf, } from "./context.js";
|
|
11
|
+
import { readSandboxConfig } from "../sandbox/tenant-config.js";
|
|
12
|
+
import { checkPlacement, requirePods } from "../sandbox/placement.js";
|
|
13
|
+
import { pinOf } from "./agent-versions.js";
|
|
14
|
+
import { openAgent, recordAttachment } from "./agents.js";
|
|
15
|
+
import { harnessOf, reachesAgent, } from "./context.js";
|
|
17
16
|
import { fail } from "./http.js";
|
|
18
17
|
import { definitionFileIssues } from "./definition-files.js";
|
|
19
|
-
import { limitsInForce,
|
|
20
|
-
import { readRuntimeLimits } from "./runtime-limits.js";
|
|
21
|
-
import { httpToolTimeoutIssues } from "../gates/http-tool.js";
|
|
22
|
-
import { requiresIssues } from "./limits.js";
|
|
18
|
+
import { limitsInForce, readTenantLimits } from "./limits.js";
|
|
23
19
|
/** A session's creation identity: everything but the request id. */
|
|
24
20
|
const sessionIdentity = (value) => {
|
|
25
21
|
const { requestId: _requestId, ...body } = value ?? {};
|
|
26
22
|
return canonical(body);
|
|
27
23
|
};
|
|
28
|
-
export async function listDefinitions(ctx) {
|
|
29
|
-
const definitions = await ctx.store.tx((t) => t.listDefinitions());
|
|
30
|
-
return {
|
|
31
|
-
agents: definitions.map((d) => ({
|
|
32
|
-
agentId: d.manifest.id,
|
|
33
|
-
manifest: d.manifest,
|
|
34
|
-
manifestHash: d.manifestHash,
|
|
35
|
-
implementationVersion: d.implementationVersion,
|
|
36
|
-
})),
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* The agents a token caller may see: id, name and description only, never
|
|
41
|
-
* instructions, tools or MCP servers, and only the agents allowed.
|
|
42
|
-
*/
|
|
43
|
-
export async function listAgentsPublic(ctx, agents) {
|
|
44
|
-
const definitions = await ctx.store.tx((t) => t.listDefinitions());
|
|
45
|
-
return {
|
|
46
|
-
agents: definitions
|
|
47
|
-
.filter((d) => agents === "*" || agents.has(d.manifest.id))
|
|
48
|
-
.map((d) => ({
|
|
49
|
-
agentId: d.manifest.id,
|
|
50
|
-
...(typeof d.manifest.name === "string" ? { name: d.manifest.name } : {}),
|
|
51
|
-
...(typeof d.manifest.description === "string"
|
|
52
|
-
? { description: d.manifest.description }
|
|
53
|
-
: {}),
|
|
54
|
-
})),
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
export async function putDefinition(ctx, agentId, body, options = {}) {
|
|
58
|
-
if (body.manifest.id !== agentId)
|
|
59
|
-
fail(400, "Agent id mismatch");
|
|
60
|
-
DefinitionDocumentSchema.parse(body.manifest);
|
|
61
|
-
// The Runtime runs agents from their manifests alone (track R2): no tool may need it.
|
|
62
|
-
const code = codeToolRefusal(body.manifest);
|
|
63
|
-
if (code)
|
|
64
|
-
fail(400, code);
|
|
65
|
-
// Tool approvals are the Tenant's tool policy, decided at the Tool Gate (R5 step 2).
|
|
66
|
-
const approval = approvalRefusal(body.manifest);
|
|
67
|
-
if (approval)
|
|
68
|
-
fail(400, approval);
|
|
69
|
-
const declared = declaredSandboxes(body.manifest);
|
|
70
|
-
if (declared.length > 0)
|
|
71
|
-
fail(400, `${declared.join(", ")} declares a sandbox. Agents no longer declare one: remove .sandbox(), create an Environment with the sandbox (PUT /v1/environments/{id}) and open the session on it, createSession({ environment }). See MIGRATION.md.`);
|
|
72
|
-
const definition = {
|
|
73
|
-
...body,
|
|
74
|
-
manifestHash: hashManifest(body.manifest),
|
|
75
|
-
};
|
|
76
|
-
const files = [...definitionFilesOf(body.manifest)];
|
|
77
|
-
await ctx.store.tx(async (t) => {
|
|
78
|
-
const limits = await readRuntimeLimits(t);
|
|
79
|
-
const issues = [
|
|
80
|
-
...httpToolTimeoutIssues(body.manifest, limits.httpToolTimeoutMs),
|
|
81
|
-
...requiresIssues(body.manifest.requires, limits),
|
|
82
|
-
];
|
|
83
|
-
if (issues.length > 0)
|
|
84
|
-
fail(400, issues.join(" "));
|
|
85
|
-
const { totalBytes } = await readSkillLimits(t);
|
|
86
|
-
const { missing, oversized } = await definitionFileIssues(t, body.manifest, totalBytes);
|
|
87
|
-
if (missing.length > 0)
|
|
88
|
-
fail(400, `The definition names ${missing.length} file(s) the Runtime does not hold; upload each with PUT /v1/files/<sha256> first: ${missing.join(", ")}`, { code: "definition_files_missing", details: { missing } });
|
|
89
|
-
if (oversized.length > 0)
|
|
90
|
-
fail(413, `This Tenant allows a skill's files at most ${totalBytes} bytes together: ${oversized.map((skill) => `'${skill.name}' holds ${skill.bytes}`).join(", ")}`, { code: "limit_exceeded", details: { limitBytes: totalBytes, skills: oversized } });
|
|
91
|
-
if (options.dryRun)
|
|
92
|
-
return;
|
|
93
|
-
await t.put("definitions", agentId, definition);
|
|
94
|
-
await t.insertDefinitionFileUses(agentId, definition.manifestHash, files);
|
|
95
|
-
});
|
|
96
|
-
return {
|
|
97
|
-
agentId,
|
|
98
|
-
manifestHash: definition.manifestHash,
|
|
99
|
-
implementationVersion: body.implementationVersion,
|
|
100
|
-
...(options.dryRun ? { dryRun: true } : {}),
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
24
|
/**
|
|
104
|
-
* `access`, when the request acts for a person, limits the list to that person's sessions
|
|
105
|
-
* the
|
|
25
|
+
* `access`, when the request acts for a person, limits the list to that person's sessions on
|
|
26
|
+
* the Agents they may use.
|
|
106
27
|
*/
|
|
107
28
|
export async function listSessions(ctx, agentId, access) {
|
|
108
29
|
const sessions = await ctx.store.tx((t) => t.listSessions({
|
|
109
30
|
...(agentId === null ? {} : { agentId }),
|
|
110
31
|
...(access === undefined ? {} : { ownerUserId: access.owner }),
|
|
111
32
|
}));
|
|
112
|
-
const allowed = access?.agents;
|
|
113
33
|
return {
|
|
114
34
|
sessions: sessions
|
|
115
|
-
.filter((s) =>
|
|
35
|
+
.filter((s) => reachesAgent(access, s.agentId))
|
|
116
36
|
.map((s) => ({
|
|
117
37
|
id: s.id,
|
|
118
38
|
agentId: s.agentId,
|
|
@@ -123,130 +43,90 @@ export async function listSessions(ctx, agentId, access) {
|
|
|
123
43
|
};
|
|
124
44
|
}
|
|
125
45
|
/**
|
|
126
|
-
* Create a session
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
* another owner.
|
|
46
|
+
* Create a session on an Agent, or find an identical one. `access`, when the request acts for a
|
|
47
|
+
* subject, must be the session's owner: another owner's session id is the 404 of a missing one
|
|
48
|
+
* (not the 409 of a mismatch), and so is an Agent whose owner guard names another owner.
|
|
130
49
|
*
|
|
131
|
-
* The session
|
|
132
|
-
* the session's, with the spec of the
|
|
133
|
-
*
|
|
50
|
+
* The session runs on its Agent for its life: the Agent's sandbox (kinds `virtual` and `pod`) is
|
|
51
|
+
* the session's, with the spec of what the Agent runs pinned now, and the Agent's vault holds the
|
|
52
|
+
* session's credentials. It pins the manifest version the Agent runs (`definition`), as the loop
|
|
53
|
+
* manifest that version's harness section makes, and the harness that section names (`pinOf`);
|
|
54
|
+
* a turn's first segment pins the version the Agent runs then (`repinTurn`).
|
|
134
55
|
*/
|
|
135
56
|
export async function putSession(ctx, id, body, access, options = {}) {
|
|
136
57
|
const opaque = access !== undefined;
|
|
137
58
|
if (opaque && body.ownerUserId !== access.owner)
|
|
138
59
|
fail(403, "ownerUserId must be the subject");
|
|
139
|
-
// An
|
|
140
|
-
if (access
|
|
141
|
-
fail(404, "
|
|
142
|
-
return ctx.store.tx(
|
|
143
|
-
const prior = await t.lockSession(id);
|
|
144
|
-
if (opaque &&
|
|
145
|
-
prior &&
|
|
146
|
-
(prior.ownerUserId !== access.owner ||
|
|
147
|
-
(access.agents !== undefined && !access.agents.has(prior.agentId))))
|
|
148
|
-
fail(404, "Session not found");
|
|
149
|
-
if (prior && options.createOnly) {
|
|
150
|
-
if (prior.ownerUserId !== body.ownerUserId ||
|
|
151
|
-
prior.agentId !== body.agentId)
|
|
152
|
-
fail(404, "Session not found");
|
|
153
|
-
return prior;
|
|
154
|
-
}
|
|
155
|
-
if (prior) {
|
|
156
|
-
if (sessionIdentity(prior.creation) !== sessionIdentity(body))
|
|
157
|
-
fail(409, "Session already exists with different creation parameters");
|
|
158
|
-
return prior;
|
|
159
|
-
}
|
|
160
|
-
const definition = (await t.get("definitions", body.agentId)) ??
|
|
161
|
-
fail(404, "Definition not found");
|
|
162
|
-
const environment = body.environment === undefined
|
|
163
|
-
? undefined
|
|
164
|
-
: await openEnvironment(t, body.environment, {
|
|
165
|
-
...(options.environmentGrants === undefined ? {} : { grants: options.environmentGrants }),
|
|
166
|
-
ownerUserId: body.ownerUserId,
|
|
167
|
-
opaque,
|
|
168
|
-
});
|
|
169
|
-
if (!isWorkflowManifest(definition.manifest))
|
|
170
|
-
await checkRequirements(t, definition.manifest, environment);
|
|
171
|
-
if (environment !== undefined)
|
|
172
|
-
await checkSkillLimit(t, definition.manifest, environment);
|
|
173
|
-
const config = await readSandboxConfig(t);
|
|
174
|
-
// The harness the session runs for its life (R4.1): its Environment's, else ours. A flow
|
|
175
|
-
// runs in core and our engine, whatever its Environment names.
|
|
176
|
-
const harness = isWorkflowManifest(definition.manifest) || environment === undefined
|
|
177
|
-
? HARNESS_ID
|
|
178
|
-
: environment.applied.harness;
|
|
179
|
-
// Placement (D38, D52): where this session's harness may run, decided now and kept.
|
|
180
|
-
checkPlacement(config, environment?.kind, harness);
|
|
181
|
-
if (environment?.kind === "pod")
|
|
182
|
-
await requirePods(ctx.pods, `Environment ${environment.id}`);
|
|
183
|
-
const spec = environment === undefined || environment.kind === "none"
|
|
184
|
-
? undefined
|
|
185
|
-
: sandboxSpecOf(environment.applied, effectiveSandboxConfig(config).limits.idle);
|
|
186
|
-
// The session pins its definition as registered (protocol 15): the sandbox's spec stays on
|
|
187
|
-
// the session, and the harness words the facts and defines the tools.
|
|
188
|
-
const created = {
|
|
189
|
-
id,
|
|
190
|
-
agentId: body.agentId,
|
|
191
|
-
ownerUserId: body.ownerUserId,
|
|
192
|
-
manifest: definition.manifest,
|
|
193
|
-
manifestHash: definition.manifestHash,
|
|
194
|
-
definitionHash: definition.manifestHash,
|
|
195
|
-
implementationVersion: definition.implementationVersion,
|
|
196
|
-
info: body.info,
|
|
197
|
-
status: "idle",
|
|
198
|
-
activeTurnId: null,
|
|
199
|
-
creation: body,
|
|
200
|
-
harness,
|
|
201
|
-
...(environment === undefined
|
|
202
|
-
? {}
|
|
203
|
-
: { environmentId: environment.id, environmentVersion: environment.version }),
|
|
204
|
-
...(spec === undefined ? {} : { sandbox: spec }),
|
|
205
|
-
};
|
|
206
|
-
await t.put("sessions", id, created);
|
|
207
|
-
if (environment !== undefined)
|
|
208
|
-
await recordAttachment(t, id, environment.id);
|
|
209
|
-
return created;
|
|
210
|
-
});
|
|
60
|
+
// An Agent the subject may not use is the 404 of a missing one.
|
|
61
|
+
if (!reachesAgent(access, body.agent))
|
|
62
|
+
fail(404, "Agent not found");
|
|
63
|
+
return ctx.store.tx((t) => openSessionIn(ctx, t, id, body, access, options));
|
|
211
64
|
}
|
|
212
65
|
/**
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
* gap is named in one `409 environment_unsuitable`.
|
|
66
|
+
* `putSession`'s work in transaction `t`: also how a trigger's first run opens the session it
|
|
67
|
+
* names (track T4), in the run's transaction.
|
|
216
68
|
*/
|
|
217
|
-
async function
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
missing.push("pod");
|
|
227
|
-
if (requires.secrets?.length) {
|
|
228
|
-
const vault = environment === undefined ? undefined : await t.vaultOfEnvironment(environment.id);
|
|
229
|
-
const held = new Set(vault ? (await t.credentialsForVault(vault.id)).map((row) => row.name) : []);
|
|
230
|
-
for (const name of requires.secrets)
|
|
231
|
-
if (!held.has(name))
|
|
232
|
-
missing.push(`secret:${name}`);
|
|
69
|
+
export async function openSessionIn(ctx, t, id, body, access, options = {}) {
|
|
70
|
+
const opaque = access !== undefined;
|
|
71
|
+
const prior = await t.lockSession(id);
|
|
72
|
+
if (opaque && prior && (prior.ownerUserId !== access.owner || !reachesAgent(access, prior.agentId)))
|
|
73
|
+
fail(404, "Session not found");
|
|
74
|
+
if (prior && options.createOnly) {
|
|
75
|
+
if (prior.ownerUserId !== body.ownerUserId || prior.agentId !== body.agent)
|
|
76
|
+
fail(404, "Session not found");
|
|
77
|
+
return prior;
|
|
233
78
|
}
|
|
234
|
-
if (
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
79
|
+
if (prior) {
|
|
80
|
+
if (sessionIdentity(prior.creation) !== sessionIdentity(body))
|
|
81
|
+
fail(409, "Session already exists with different creation parameters");
|
|
82
|
+
return prior;
|
|
83
|
+
}
|
|
84
|
+
const agent = await openAgent(t, body.agent, {
|
|
85
|
+
...(options.agentGrants === undefined ? {} : { grants: options.agentGrants }),
|
|
86
|
+
ownerUserId: body.ownerUserId,
|
|
87
|
+
opaque,
|
|
88
|
+
});
|
|
89
|
+
// The version the Agent runs, both sections (T3): its loop manifest, harness and sandbox spec.
|
|
90
|
+
const { pin } = await pinOf(t, agent);
|
|
91
|
+
await checkSkillLimit(t, pin.manifest, agent);
|
|
92
|
+
const config = await readSandboxConfig(t);
|
|
93
|
+
// Placement (D38, D52): where this session's harness may run, decided now and kept.
|
|
94
|
+
checkPlacement(config, agent.kind, pin.harness);
|
|
95
|
+
if (agent.kind === "pod")
|
|
96
|
+
await requirePods(ctx.pods, `Agent ${agent.id}`);
|
|
97
|
+
const created = {
|
|
98
|
+
id,
|
|
99
|
+
agentId: agent.id,
|
|
100
|
+
ownerUserId: body.ownerUserId,
|
|
101
|
+
manifest: pin.manifest,
|
|
102
|
+
manifestHash: pin.manifestHash,
|
|
103
|
+
definition: { ...pin.definition },
|
|
104
|
+
...(pin.loop === undefined ? {} : { loop: pin.loop }),
|
|
105
|
+
info: body.info,
|
|
106
|
+
status: "idle",
|
|
107
|
+
activeTurnId: null,
|
|
108
|
+
creation: body,
|
|
109
|
+
harness: pin.harness,
|
|
110
|
+
environmentId: agent.id,
|
|
111
|
+
environmentVersion: agent.version,
|
|
112
|
+
...(pin.sandbox === undefined ? {} : { sandbox: pin.sandbox }),
|
|
113
|
+
};
|
|
114
|
+
await t.put("sessions", id, created);
|
|
115
|
+
await recordAttachment(t, id, agent.id);
|
|
116
|
+
return created;
|
|
238
117
|
}
|
|
239
118
|
/**
|
|
240
|
-
* Refuses a session whose
|
|
241
|
-
* manifest's `limits.skills.totalBytes`, else the Tenant's, never above the Tenant's
|
|
242
|
-
* `
|
|
119
|
+
* Refuses a session whose Agent's manifest carries a skill larger than the Agent allows now: its
|
|
120
|
+
* manifest's `limits.skills.totalBytes`, else the Tenant's, never above the Tenant's, which may
|
|
121
|
+
* have been lowered since the manifest was saved. `413 limit_exceeded`, with each skill and its
|
|
122
|
+
* size in `details.skills`.
|
|
243
123
|
*/
|
|
244
|
-
async function checkSkillLimit(t, manifest,
|
|
245
|
-
const limitBytes = limitsInForce(await readTenantLimits(t),
|
|
124
|
+
async function checkSkillLimit(t, manifest, agent) {
|
|
125
|
+
const limitBytes = limitsInForce(await readTenantLimits(t), agent.applied.limits).skills.totalBytes;
|
|
246
126
|
const { oversized } = await definitionFileIssues(t, manifest, limitBytes);
|
|
247
127
|
if (oversized.length === 0)
|
|
248
128
|
return;
|
|
249
|
-
fail(
|
|
129
|
+
fail(413, `Agent ${agent.id} allows a skill's files at most ${limitBytes} bytes together, and its manifest carries ${oversized.map((skill) => `'${skill.name}' (${skill.bytes})`).join(", ")}.`, { code: "limit_exceeded", details: { limitBytes, skills: oversized } });
|
|
250
130
|
}
|
|
251
131
|
/** The session resource returned by `GET`/`PUT /v1/sessions/:id`. */
|
|
252
132
|
export async function sessionView(t, s) {
|
|
@@ -270,14 +150,11 @@ export async function sessionView(t, s) {
|
|
|
270
150
|
id: s.id,
|
|
271
151
|
agentId: s.agentId,
|
|
272
152
|
ownerUserId: s.ownerUserId,
|
|
153
|
+
manifest: s.definition ?? null,
|
|
273
154
|
manifestHash: s.manifestHash,
|
|
274
|
-
...(s.definitionHash === undefined ? {} : { definitionHash: s.definitionHash }),
|
|
275
|
-
implementationVersion: s.implementationVersion,
|
|
276
155
|
status: s.status,
|
|
277
156
|
activeTurnId: s.activeTurnId,
|
|
278
|
-
|
|
279
|
-
? null
|
|
280
|
-
: { id: s.environmentId, version: s.environmentVersion ?? 1 },
|
|
157
|
+
queuedMessages: await t.countQueuedMessages(s.id),
|
|
281
158
|
harness: harnessOf(s),
|
|
282
159
|
...(s.closedReason === undefined ? {} : { closedReason: s.closedReason }),
|
|
283
160
|
mcpSnapshot: s.mcpSnapshot ?? null,
|
package/dist/tenant/status.js
CHANGED
|
@@ -47,9 +47,9 @@ async function executionStatus(stuckInvocations) {
|
|
|
47
47
|
/** Build `TenantStatusSchema` with secrets redacted (A14). */
|
|
48
48
|
export async function buildTenantStatus(ctx) {
|
|
49
49
|
const health = await ctx.store.health();
|
|
50
|
-
const { counts,
|
|
50
|
+
const { counts, rows } = await ctx.store.tx(async (t) => ({
|
|
51
51
|
counts: await t.counts(),
|
|
52
|
-
|
|
52
|
+
rows: await t.listEnvironments(),
|
|
53
53
|
}));
|
|
54
54
|
const [modelView, sandboxReport, execution, streams] = await Promise.all([
|
|
55
55
|
ctx.vault.getHostModel(),
|
|
@@ -57,11 +57,10 @@ export async function buildTenantStatus(ctx) {
|
|
|
57
57
|
ctx.stuckInvocations ? executionStatus(ctx.stuckInvocations) : undefined,
|
|
58
58
|
ctx.streamsStatus?.(),
|
|
59
59
|
]);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
]
|
|
60
|
+
// The Tenant's Agents; a pod Agent being deleted is none.
|
|
61
|
+
const agents = rows
|
|
62
|
+
.filter((row) => row.pod?.desired !== "deleted")
|
|
63
|
+
.map((row) => row.id)
|
|
65
64
|
.sort()
|
|
66
65
|
.map((agentId) => ({ agentId }));
|
|
67
66
|
return {
|
package/dist/tenant/sweep.js
CHANGED
|
@@ -33,7 +33,9 @@
|
|
|
33
33
|
* workspaces). Idle MCP connections of the in-process harness are closed. As often as the
|
|
34
34
|
* orphan scan, pod Environments whose change stalled get a reconcile (`reconcileStalePods`).
|
|
35
35
|
* Environments unused for their `lifecycle.deleteAfter` are deleted
|
|
36
|
-
* (`
|
|
36
|
+
* (`sweepUnusedAgents`).
|
|
37
|
+
* Triggers (track T4, `triggers.ts`): on this process's first pass every active trigger's
|
|
38
|
+
* timer is armed, later overdue ones only, and runs past `triggerRunRetentionMs` are deleted.
|
|
37
39
|
* 5. **Control signals.** Signals on the control bus older than `sweep.signalRetentionMs` are
|
|
38
40
|
* deleted: followers read back only the last two minutes (`store/postgres/control.ts`).
|
|
39
41
|
* 6. **Hooks.** Callbacks registered with `ctx.onSweep`.
|
|
@@ -43,10 +45,12 @@
|
|
|
43
45
|
* step does not stop the others; the first error is rethrown at the end so the execution
|
|
44
46
|
* reports it.
|
|
45
47
|
*/
|
|
46
|
-
import {
|
|
48
|
+
import { sweepUnusedAgents } from "./agents.js";
|
|
49
|
+
import { reconcileTriggers } from "./triggers.js";
|
|
47
50
|
import { sweepPendingSeeds } from "../artifacts/disk.js";
|
|
48
51
|
import { pendingAgentEffects, reconcilePendingAgentEffect, } from "../core/flow-host.js";
|
|
49
52
|
import { hostTuning } from "../tuning.js";
|
|
53
|
+
import { sweepStartChecks } from "./agent-versions.js";
|
|
50
54
|
/*
|
|
51
55
|
* The sweep's timings are the Host tuning's `sweep` group (`tuning.ts`):
|
|
52
56
|
* - `outboxGraceMs`: how old an outbox row is before the sweep delivers it, unless its delivery
|
|
@@ -113,7 +117,12 @@ export async function sweep(ctx) {
|
|
|
113
117
|
]
|
|
114
118
|
: []),
|
|
115
119
|
// Environments unused for their `lifecycle.deleteAfter`: one query when none is due.
|
|
116
|
-
["
|
|
120
|
+
["agents", () => sweepUnusedAgents(ctx, now.getTime())],
|
|
121
|
+
// Pods slower than `tenant.upgradeStartMs` to start on a new version go back (track T3).
|
|
122
|
+
["starts", () => sweepStartChecks(ctx, now.getTime())],
|
|
123
|
+
// Triggers (track T4): every active one armed on this process's first pass, overdue ones after;
|
|
124
|
+
// runs past their retention deleted.
|
|
125
|
+
["triggers", () => reconcileTriggers(ctx, first)],
|
|
117
126
|
// Seeds of new volumes whose engine is connected and no process copies (R2d step 3).
|
|
118
127
|
["seeds", () => sweepPendingSeeds(ctx)],
|
|
119
128
|
// A harness elsewhere closes its own idle MCP connections.
|
|
@@ -192,7 +192,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
192
192
|
redacted: number;
|
|
193
193
|
toolName: string;
|
|
194
194
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
195
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
195
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
196
196
|
server?: string | undefined;
|
|
197
197
|
tool?: string | undefined;
|
|
198
198
|
skill?: string | undefined;
|
|
@@ -214,7 +214,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
214
214
|
redacted: number;
|
|
215
215
|
toolName: string;
|
|
216
216
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
217
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
217
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
218
218
|
server?: string | undefined;
|
|
219
219
|
tool?: string | undefined;
|
|
220
220
|
skill?: string | undefined;
|
|
@@ -236,7 +236,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
236
236
|
redacted?: undefined;
|
|
237
237
|
toolName: string;
|
|
238
238
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
239
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
239
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
240
240
|
server?: string | undefined;
|
|
241
241
|
tool?: string | undefined;
|
|
242
242
|
skill?: string | undefined;
|
|
@@ -258,7 +258,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
258
258
|
redacted?: undefined;
|
|
259
259
|
toolName: string;
|
|
260
260
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
261
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
261
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
262
262
|
server?: string | undefined;
|
|
263
263
|
tool?: string | undefined;
|
|
264
264
|
skill?: string | undefined;
|
|
@@ -275,7 +275,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
275
275
|
redacted: number;
|
|
276
276
|
toolName: string;
|
|
277
277
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
278
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
278
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
279
279
|
server?: string | undefined;
|
|
280
280
|
tool?: string | undefined;
|
|
281
281
|
skill?: string | undefined;
|
|
@@ -292,7 +292,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
292
292
|
redacted: number;
|
|
293
293
|
toolName: string;
|
|
294
294
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
295
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
295
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
296
296
|
server?: string | undefined;
|
|
297
297
|
tool?: string | undefined;
|
|
298
298
|
skill?: string | undefined;
|
|
@@ -309,7 +309,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
309
309
|
redacted?: undefined;
|
|
310
310
|
toolName: string;
|
|
311
311
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
312
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
312
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
313
313
|
server?: string | undefined;
|
|
314
314
|
tool?: string | undefined;
|
|
315
315
|
skill?: string | undefined;
|
|
@@ -326,7 +326,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
326
326
|
redacted?: undefined;
|
|
327
327
|
toolName: string;
|
|
328
328
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
329
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
329
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
330
330
|
server?: string | undefined;
|
|
331
331
|
tool?: string | undefined;
|
|
332
332
|
skill?: string | undefined;
|
|
@@ -350,7 +350,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
350
350
|
redacted: number;
|
|
351
351
|
toolName: string;
|
|
352
352
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
353
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
353
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
354
354
|
server?: string | undefined;
|
|
355
355
|
tool?: string | undefined;
|
|
356
356
|
skill?: string | undefined;
|
|
@@ -374,7 +374,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
374
374
|
redacted: number;
|
|
375
375
|
toolName: string;
|
|
376
376
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
377
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
377
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
378
378
|
server?: string | undefined;
|
|
379
379
|
tool?: string | undefined;
|
|
380
380
|
skill?: string | undefined;
|
|
@@ -398,7 +398,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
398
398
|
redacted?: undefined;
|
|
399
399
|
toolName: string;
|
|
400
400
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
401
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
401
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
402
402
|
server?: string | undefined;
|
|
403
403
|
tool?: string | undefined;
|
|
404
404
|
skill?: string | undefined;
|
|
@@ -422,7 +422,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
422
422
|
redacted?: undefined;
|
|
423
423
|
toolName: string;
|
|
424
424
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
425
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
425
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
426
426
|
server?: string | undefined;
|
|
427
427
|
tool?: string | undefined;
|
|
428
428
|
skill?: string | undefined;
|
|
@@ -441,7 +441,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
441
441
|
redacted: number;
|
|
442
442
|
toolName: string;
|
|
443
443
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
444
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
444
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
445
445
|
server?: string | undefined;
|
|
446
446
|
tool?: string | undefined;
|
|
447
447
|
skill?: string | undefined;
|
|
@@ -460,7 +460,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
460
460
|
redacted: number;
|
|
461
461
|
toolName: string;
|
|
462
462
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
463
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
463
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
464
464
|
server?: string | undefined;
|
|
465
465
|
tool?: string | undefined;
|
|
466
466
|
skill?: string | undefined;
|
|
@@ -479,7 +479,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
479
479
|
redacted?: undefined;
|
|
480
480
|
toolName: string;
|
|
481
481
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
482
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
482
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
483
483
|
server?: string | undefined;
|
|
484
484
|
tool?: string | undefined;
|
|
485
485
|
skill?: string | undefined;
|
|
@@ -498,7 +498,7 @@ export declare function toolCompleted(request: HostEffect, value: unknown, facts
|
|
|
498
498
|
redacted?: undefined;
|
|
499
499
|
toolName: string;
|
|
500
500
|
status?: "cancelled" | "completed" | "failed" | undefined;
|
|
501
|
-
kind?: "harness" | "http" | "mcp" | "sandbox" | undefined;
|
|
501
|
+
kind?: "harness" | "http" | "mcp" | "runtime" | "sandbox" | undefined;
|
|
502
502
|
server?: string | undefined;
|
|
503
503
|
tool?: string | undefined;
|
|
504
504
|
skill?: string | undefined;
|