@stratusagent/gateway 0.14.8 → 0.14.9
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/agent-source.d.ts +10 -0
- package/dist/agent-source.d.ts.map +1 -0
- package/dist/agent-source.js +7 -0
- package/dist/agent-source.js.map +1 -0
- package/dist/approvals.d.ts +38 -0
- package/dist/approvals.d.ts.map +1 -0
- package/dist/approvals.js +330 -0
- package/dist/approvals.js.map +1 -0
- package/dist/credential-requests.d.ts +24 -0
- package/dist/credential-requests.d.ts.map +1 -0
- package/dist/credential-requests.js +452 -0
- package/dist/credential-requests.js.map +1 -0
- package/dist/dispatch.d.ts +34 -0
- package/dist/dispatch.d.ts.map +1 -0
- package/dist/dispatch.js +461 -0
- package/dist/dispatch.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +368 -2443
- package/dist/index.js.map +1 -1
- package/dist/merge-batch.d.ts +60 -0
- package/dist/merge-batch.d.ts.map +1 -0
- package/dist/merge-batch.js +59 -0
- package/dist/merge-batch.js.map +1 -0
- package/dist/recovery.d.ts +49 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +487 -0
- package/dist/recovery.js.map +1 -0
- package/dist/steering.d.ts +24 -0
- package/dist/steering.d.ts.map +1 -0
- package/dist/steering.js +108 -0
- package/dist/steering.js.map +1 -0
- package/dist/sub-agents.d.ts +20 -0
- package/dist/sub-agents.d.ts.map +1 -0
- package/dist/sub-agents.js +263 -0
- package/dist/sub-agents.js.map +1 -0
- package/dist/turn-dispatch.d.ts +34 -0
- package/dist/turn-dispatch.d.ts.map +1 -0
- package/dist/turn-dispatch.js +179 -0
- package/dist/turn-dispatch.js.map +1 -0
- package/package.json +7 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"steering.js","sourceRoot":"","sources":["../src/steering.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type AgentDefinition, type AgentRegistry, type Executor, type Session, type SteeredMessage, type SubAgentHandle, type ToolRegistry, type UnlistedTools } from '@stratusagent/core';
|
|
2
|
+
import type { ShardedSessionStore } from './sessions.ts';
|
|
3
|
+
import type { DispatchInput, GatewayOptions } from './types.ts';
|
|
4
|
+
import type { ApprovalBroker } from './approvals.ts';
|
|
5
|
+
/** What delegation closes over in `createGateway`. */
|
|
6
|
+
export interface SubAgentsDeps extends Pick<ApprovalBroker, 'liveSubAgentIds' | 'idAtFirstCall' | 'hostIdOf' | 'isHostSubAgent'> {
|
|
7
|
+
options: GatewayOptions;
|
|
8
|
+
store: ShardedSessionStore;
|
|
9
|
+
registry: AgentRegistry;
|
|
10
|
+
unlistedTools: () => UnlistedTools;
|
|
11
|
+
tools: ToolRegistry;
|
|
12
|
+
dispatchInternal: (input: DispatchInput, absorbedKeys?: readonly string[], subAgent?: AgentDefinition, steer?: (turnSignal: AbortSignal) => Promise<SteeredMessage | undefined>) => Promise<Session>;
|
|
13
|
+
onSessionChain: <T>(sessionId: string, work: () => Promise<T>, released?: () => boolean) => Promise<T>;
|
|
14
|
+
}
|
|
15
|
+
export declare const createSubAgents: ({ options, store, registry, unlistedTools, tools, dispatchInternal, onSessionChain, liveSubAgentIds, idAtFirstCall, hostIdOf, isHostSubAgent, }: SubAgentsDeps) => {
|
|
16
|
+
bindToolCalls: (inner: Executor) => Executor;
|
|
17
|
+
subAgents: SubAgentHandle;
|
|
18
|
+
};
|
|
19
|
+
export type SubAgents = ReturnType<typeof createSubAgents>;
|
|
20
|
+
//# sourceMappingURL=sub-agents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sub-agents.d.ts","sourceRoot":"","sources":["../src/sub-agents.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,QAAQ,EAIb,KAAK,OAAO,EAGZ,KAAK,cAAc,EACnB,KAAK,cAAc,EAEnB,KAAK,YAAY,EACjB,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAQ5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAShE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,sDAAsD;AACtD,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,cAAc,EAAE,iBAAiB,GAAG,eAAe,GAAG,UAAU,GAAG,gBAAgB,CAAC;IAC9H,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,QAAQ,EAAE,aAAa,CAAC;IACxB,aAAa,EAAE,MAAM,aAAa,CAAC;IACnC,KAAK,EAAE,YAAY,CAAC;IACpB,gBAAgB,EAAE,CAChB,KAAK,EAAE,aAAa,EACpB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,EAChC,QAAQ,CAAC,EAAE,eAAe,EAC1B,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE,WAAW,KAAK,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,KACrE,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,cAAc,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACxG;AAED,eAAO,MAAM,eAAe,GAAI,iJAY7B,aAAa;2BA0CgB,QAAQ,KAAG,QAAQ;;CAqNlD,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC"}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Delegation: the `agent.delegate` tool, and sub-agents a plugin runs inside
|
|
3
|
+
* a turn (per-turn slots, which tools a slice may carry, the tool calls in
|
|
4
|
+
* flight they are bound to). Moved out of `createGateway` in index.ts as is:
|
|
5
|
+
* the statements are unchanged, inside a factory that takes what they closed
|
|
6
|
+
* over there, and `createGateway` calls it where they were and destructures
|
|
7
|
+
* what it returns. dispatchInternal and onSessionChain are declared later in
|
|
8
|
+
* `createGateway`, so it passes them late-bound.
|
|
9
|
+
*/
|
|
10
|
+
import { randomUUID } from 'node:crypto';
|
|
11
|
+
import { abortErrorFor, matchesToolAllowlist, resolveToolRisk, SENDER_TRUST_METADATA_KEY, sessionTrustOf, sessionWriteTrust, } from '@stratusagent/core';
|
|
12
|
+
import { createDelegateTool, DEFAULT_MAX_DELEGATION_DEPTH, DELEGATED_BY_METADATA_KEY, DELEGATION_DEPTH_METADATA_KEY, ROOT_SESSION_ID_METADATA_KEY, } from '@stratusagent/agents';
|
|
13
|
+
import { DEFAULT_SUB_AGENTS_PER_TURN, isSubAgentSession, SUB_AGENT_METADATA_KEY, SUB_AGENT_SESSION_ID_MARKER, subAgentNeverGets, } from "./session-keys.js";
|
|
14
|
+
import { FALLBACK_ACTIVE_METADATA_KEY } from '@stratusagent/state';
|
|
15
|
+
export const createSubAgents = ({ options, store, registry, unlistedTools, tools, dispatchInternal, onSessionChain, liveSubAgentIds, idAtFirstCall, hostIdOf, isHostSubAgent, }) => {
|
|
16
|
+
tools.register(createDelegateTool({
|
|
17
|
+
registry,
|
|
18
|
+
dispatch: (input) => dispatchInternal({
|
|
19
|
+
sessionId: input.sessionId,
|
|
20
|
+
agentId: input.agent.id,
|
|
21
|
+
userMessage: input.userMessage,
|
|
22
|
+
metadata: input.metadata,
|
|
23
|
+
// A cancelled parent turn cancels its delegated runs too.
|
|
24
|
+
...(input.signal ? { signal: input.signal } : {}),
|
|
25
|
+
}),
|
|
26
|
+
}));
|
|
27
|
+
// ---- sub-agents (roadmap 24) -------------------------------------------
|
|
28
|
+
/**
|
|
29
|
+
* Running sub-agents per parent session, and who waits for a slot. A
|
|
30
|
+
* parent session runs one turn at a time, so this is per turn.
|
|
31
|
+
*/
|
|
32
|
+
const maxSubAgentsPerTurn = options.subAgents?.maxConcurrentPerTurn ?? DEFAULT_SUB_AGENTS_PER_TURN;
|
|
33
|
+
// NaN, 0, a fraction or Infinity would queue every sub-agent forever or
|
|
34
|
+
// defeat the cap, so refuse it here instead of failing later in a turn.
|
|
35
|
+
if (!Number.isInteger(maxSubAgentsPerTurn) || maxSubAgentsPerTurn < 1) {
|
|
36
|
+
throw new Error(`subAgents.maxConcurrentPerTurn must be a whole number of at least 1 (got ${String(maxSubAgentsPerTurn)}).`);
|
|
37
|
+
}
|
|
38
|
+
const subAgentSlots = new Map();
|
|
39
|
+
let subAgentCount = 0;
|
|
40
|
+
/**
|
|
41
|
+
* The session object each in-flight tool call was handed, with that
|
|
42
|
+
* call's turn signal. `subAgents.run` accepts only a parent found here:
|
|
43
|
+
* the session a running tool was given, by identity, never an id, so a
|
|
44
|
+
* plugin cannot start sub-agents of another turn (another agent's
|
|
45
|
+
* included) just because that turn is running. The signal is how the
|
|
46
|
+
* parent's cancel reaches its sub-agents whether or not the plugin
|
|
47
|
+
* passes one.
|
|
48
|
+
*/
|
|
49
|
+
const toolCallsInFlight = new Map();
|
|
50
|
+
const bindToolCalls = (inner) => ({
|
|
51
|
+
async execute(call, tool, session, context) {
|
|
52
|
+
if (!idAtFirstCall.has(session)) {
|
|
53
|
+
idAtFirstCall.set(session, session.id);
|
|
54
|
+
}
|
|
55
|
+
const entry = toolCallsInFlight.get(session) ?? [];
|
|
56
|
+
toolCallsInFlight.set(session, entry);
|
|
57
|
+
const signal = context?.signal;
|
|
58
|
+
entry.push(signal);
|
|
59
|
+
try {
|
|
60
|
+
return await inner.execute(call, tool, session, context);
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
entry.splice(entry.indexOf(signal), 1);
|
|
64
|
+
if (entry.length === 0) {
|
|
65
|
+
toolCallsInFlight.delete(session);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
const subAgentSlot = (parentId, signal) => new Promise((resolve, reject) => {
|
|
71
|
+
const entry = subAgentSlots.get(parentId) ?? { running: 0, waiting: [] };
|
|
72
|
+
subAgentSlots.set(parentId, entry);
|
|
73
|
+
const release = () => {
|
|
74
|
+
entry.running -= 1;
|
|
75
|
+
const next = entry.waiting.shift();
|
|
76
|
+
if (next) {
|
|
77
|
+
next();
|
|
78
|
+
}
|
|
79
|
+
else if (entry.running === 0) {
|
|
80
|
+
subAgentSlots.delete(parentId);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const take = () => {
|
|
84
|
+
entry.running += 1;
|
|
85
|
+
resolve(release);
|
|
86
|
+
};
|
|
87
|
+
if (entry.running < maxSubAgentsPerTurn) {
|
|
88
|
+
take();
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const onAbort = () => {
|
|
92
|
+
const at = entry.waiting.indexOf(waiter);
|
|
93
|
+
if (at >= 0) {
|
|
94
|
+
entry.waiting.splice(at, 1);
|
|
95
|
+
}
|
|
96
|
+
reject(abortErrorFor(signal));
|
|
97
|
+
};
|
|
98
|
+
const waiter = () => {
|
|
99
|
+
signal?.removeEventListener('abort', onAbort);
|
|
100
|
+
take();
|
|
101
|
+
};
|
|
102
|
+
entry.waiting.push(waiter);
|
|
103
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
104
|
+
});
|
|
105
|
+
/** Why this slice cannot be a sub-agent's, or undefined when it can. */
|
|
106
|
+
const subAgentSliceProblem = (parent, requested) => {
|
|
107
|
+
if (!Array.isArray(requested) || requested.some((name) => typeof name !== 'string' || name.length === 0)) {
|
|
108
|
+
return 'A sub-agent\'s tools are a list of tool names.';
|
|
109
|
+
}
|
|
110
|
+
// Read the way the runner reads it for the parent's own calls: the
|
|
111
|
+
// session's copy, else the registered agent's.
|
|
112
|
+
const allowlist = parent.agent.tools ?? registry.get(parent.agent.id)?.tools;
|
|
113
|
+
for (const name of requested) {
|
|
114
|
+
if (/[*?]/.test(name)) {
|
|
115
|
+
return `A sub-agent's tools are exact names, and ${name} is a pattern.`;
|
|
116
|
+
}
|
|
117
|
+
if (subAgentNeverGets(name)) {
|
|
118
|
+
return `${name} is never given to a sub-agent, even by an agent that holds it.`;
|
|
119
|
+
}
|
|
120
|
+
const tool = tools.get(name);
|
|
121
|
+
if (!tool) {
|
|
122
|
+
return `There is no tool named ${name}.`;
|
|
123
|
+
}
|
|
124
|
+
// The parent's allowlist as its running turn holds it: a slice can
|
|
125
|
+
// only narrow what that turn may already do. With no list, that is
|
|
126
|
+
// the tools registered as safe (every tool on a home an older build
|
|
127
|
+
// set up), and the slice is held to the same rule: naming a gated
|
|
128
|
+
// tool must not hand it to the sub-agent.
|
|
129
|
+
if (allowlist === undefined) {
|
|
130
|
+
if (unlistedTools() !== 'every' && resolveToolRisk(tool) !== 'safe') {
|
|
131
|
+
return `${name} is not a safe tool, and ${parent.agent.id}'s soul has no tools: list, so it gets only safe tools and a sub-agent of it cannot have ${name}.`;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
else if (!matchesToolAllowlist(name, allowlist)) {
|
|
135
|
+
return `${name} is not one of ${parent.agent.id}'s tools, so a sub-agent of it cannot have it.`;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return undefined;
|
|
139
|
+
};
|
|
140
|
+
const subAgents = {
|
|
141
|
+
async run(request) {
|
|
142
|
+
// Copied before the first await, and only the copy is read from here
|
|
143
|
+
// on: the plugin keeps its own objects and can change them while this
|
|
144
|
+
// request is checked or waits for a slot, and a slice changed after
|
|
145
|
+
// it was checked must not be the slice the sub-agent runs with.
|
|
146
|
+
const handed = request?.parent;
|
|
147
|
+
const callSignals = handed ? toolCallsInFlight.get(handed) : undefined;
|
|
148
|
+
if (!callSignals) {
|
|
149
|
+
throw new Error('subAgents.run starts sub-agents only for the session your tool was handed, while that call is running. Pass that session object as "parent".');
|
|
150
|
+
}
|
|
151
|
+
// The parent turn's own stop, and the caller's as an extra one: a
|
|
152
|
+
// plugin that passes no signal still has its sub-agents cancelled
|
|
153
|
+
// with the turn.
|
|
154
|
+
const stops = [...callSignals, request.signal].filter((signal) => signal !== undefined);
|
|
155
|
+
const input = {
|
|
156
|
+
parent: { id: hostIdOf(handed) },
|
|
157
|
+
instruction: request?.instruction,
|
|
158
|
+
tools: Array.isArray(request?.tools) ? [...request.tools] : request?.tools,
|
|
159
|
+
model: request?.model,
|
|
160
|
+
signal: stops.length === 0 ? undefined : stops.length === 1 ? stops[0] : AbortSignal.any(stops),
|
|
161
|
+
};
|
|
162
|
+
const parentId = typeof input.parent.id === 'string' ? input.parent.id : '';
|
|
163
|
+
if (!parentId) {
|
|
164
|
+
throw new Error('subAgents.run needs the session of the turn asking.');
|
|
165
|
+
}
|
|
166
|
+
const instruction = typeof input.instruction === 'string' ? input.instruction.trim() : '';
|
|
167
|
+
if (!instruction) {
|
|
168
|
+
throw new Error('subAgents.run needs an instruction.');
|
|
169
|
+
}
|
|
170
|
+
if (input.model !== undefined) {
|
|
171
|
+
throw new Error('A sub-agent\'s model cannot be chosen yet: it runs on its parent\'s. Leave "model" out.');
|
|
172
|
+
}
|
|
173
|
+
const parent = await store.get(parentId);
|
|
174
|
+
if (!parent) {
|
|
175
|
+
throw new Error(`There is no session ${parentId} to start a sub-agent from.`);
|
|
176
|
+
}
|
|
177
|
+
if (isHostSubAgent(handed) || isSubAgentSession(parent)) {
|
|
178
|
+
throw new Error('A sub-agent cannot start sub-agents.');
|
|
179
|
+
}
|
|
180
|
+
if (parent.status !== 'running') {
|
|
181
|
+
throw new Error(`Session ${parentId} is not running a turn, and sub-agents start only from one.`);
|
|
182
|
+
}
|
|
183
|
+
const depth = typeof parent.metadata?.[DELEGATION_DEPTH_METADATA_KEY] === 'number'
|
|
184
|
+
? parent.metadata[DELEGATION_DEPTH_METADATA_KEY]
|
|
185
|
+
: 0;
|
|
186
|
+
if (depth >= DEFAULT_MAX_DELEGATION_DEPTH) {
|
|
187
|
+
throw new Error(`Delegation depth limit reached (${DEFAULT_MAX_DELEGATION_DEPTH}).`);
|
|
188
|
+
}
|
|
189
|
+
const problem = subAgentSliceProblem(parent, input.tools);
|
|
190
|
+
if (problem) {
|
|
191
|
+
throw new Error(problem);
|
|
192
|
+
}
|
|
193
|
+
if (input.signal?.aborted) {
|
|
194
|
+
throw abortErrorFor(input.signal);
|
|
195
|
+
}
|
|
196
|
+
const release = await subAgentSlot(parent.id, input.signal);
|
|
197
|
+
subAgentCount += 1;
|
|
198
|
+
const sessionId = `${parent.id}${SUB_AGENT_SESSION_ID_MARKER}${depth + 1}:${subAgentCount}-${randomUUID().slice(0, 8)}`;
|
|
199
|
+
// The parent agent, narrowed: its id, provider and credentials, the
|
|
200
|
+
// slice for tools, and nothing else — no instructions (the persona),
|
|
201
|
+
// no skills, no delegates.
|
|
202
|
+
const definition = {
|
|
203
|
+
id: parent.agent.id,
|
|
204
|
+
name: parent.agent.name,
|
|
205
|
+
tools: [...new Set(input.tools)],
|
|
206
|
+
skills: [],
|
|
207
|
+
delegates: [],
|
|
208
|
+
...(parent.agent.credentials !== undefined ? { credentials: [...parent.agent.credentials] } : {}),
|
|
209
|
+
};
|
|
210
|
+
let session;
|
|
211
|
+
liveSubAgentIds.add(sessionId);
|
|
212
|
+
try {
|
|
213
|
+
session = await onSessionChain(sessionId, () => dispatchInternal({
|
|
214
|
+
sessionId,
|
|
215
|
+
agentId: parent.agent.id,
|
|
216
|
+
userMessage: instruction,
|
|
217
|
+
metadata: {
|
|
218
|
+
[SUB_AGENT_METADATA_KEY]: true,
|
|
219
|
+
[DELEGATION_DEPTH_METADATA_KEY]: depth + 1,
|
|
220
|
+
[DELEGATED_BY_METADATA_KEY]: parent.agent.id,
|
|
221
|
+
[ROOT_SESSION_ID_METADATA_KEY]: typeof parent.metadata?.[ROOT_SESSION_ID_METADATA_KEY] === 'string'
|
|
222
|
+
? parent.metadata[ROOT_SESSION_ID_METADATA_KEY]
|
|
223
|
+
: parent.id,
|
|
224
|
+
// The instruction is the parent's text, at the parent's label:
|
|
225
|
+
// a tainted parent must not hand a stranger's words to a
|
|
226
|
+
// session that has seen nothing.
|
|
227
|
+
[SENDER_TRUST_METADATA_KEY]: sessionWriteTrust(parent),
|
|
228
|
+
// On the runtime serving the parent's turn: a parent that has
|
|
229
|
+
// switched to its sticky fallback must not have its helpers
|
|
230
|
+
// retry the primary it left.
|
|
231
|
+
...(parent.metadata?.[FALLBACK_ACTIVE_METADATA_KEY] === true ? { [FALLBACK_ACTIVE_METADATA_KEY]: true } : {}),
|
|
232
|
+
},
|
|
233
|
+
...(input.signal ? { signal: input.signal } : {}),
|
|
234
|
+
}, [], definition));
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
if (input.signal?.aborted) {
|
|
238
|
+
throw error;
|
|
239
|
+
}
|
|
240
|
+
// The error text may be the provider quoting what it refused,
|
|
241
|
+
// which is this sub-agent's context: labelled as nobody can vouch.
|
|
242
|
+
return { status: 'error', error: error instanceof Error ? error.message : String(error), sessionId, trust: 'unknown' };
|
|
243
|
+
}
|
|
244
|
+
finally {
|
|
245
|
+
liveSubAgentIds.delete(sessionId);
|
|
246
|
+
release();
|
|
247
|
+
}
|
|
248
|
+
const trust = sessionTrustOf(session);
|
|
249
|
+
if (session.status === 'failed') {
|
|
250
|
+
return { status: 'error', error: session.lastError ?? 'The sub-agent failed.', sessionId, trust: 'unknown' };
|
|
251
|
+
}
|
|
252
|
+
const reply = [...session.messages]
|
|
253
|
+
.reverse()
|
|
254
|
+
.find((message) => message.role === 'assistant' && message.content.trim().length > 0);
|
|
255
|
+
const outcome = reply
|
|
256
|
+
? { status: 'result', text: reply.content, sessionId, trust }
|
|
257
|
+
: { status: 'empty', sessionId, trust };
|
|
258
|
+
return outcome;
|
|
259
|
+
},
|
|
260
|
+
};
|
|
261
|
+
return { bindToolCalls, subAgents };
|
|
262
|
+
};
|
|
263
|
+
//# sourceMappingURL=sub-agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sub-agents.js","sourceRoot":"","sources":["../src/sub-agents.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type AgentDefinition, type AgentRunner, type AgentRuntimeContext, type Executor, type JsonObject, type Session, type SteeredMessage } from '@stratusagent/core';
|
|
2
|
+
import type { AgentSource } from './agent-source.ts';
|
|
3
|
+
import type { ShardedSessionStore } from './sessions.ts';
|
|
4
|
+
import type { DispatchInput, GatewayOptions } from './types.ts';
|
|
5
|
+
import { type RuntimeConfig, type StateEnvironment } from '@stratusagent/state';
|
|
6
|
+
/** What the turn dispatch closes over in `createGateway`. */
|
|
7
|
+
export interface TurnDispatchDeps {
|
|
8
|
+
options: GatewayOptions;
|
|
9
|
+
env: StateEnvironment;
|
|
10
|
+
store: ShardedSessionStore;
|
|
11
|
+
getSelectedExecutor: () => Executor | undefined;
|
|
12
|
+
defaultAgentId: () => Promise<string>;
|
|
13
|
+
refreshAgent: (agentId: string) => Promise<AgentSource>;
|
|
14
|
+
runtimeContextFor: (source: AgentSource, config: RuntimeConfig, onFallback: boolean, metadata: JsonObject | undefined, subAgent?: boolean) => AgentRuntimeContext;
|
|
15
|
+
runnerFor: (config: RuntimeConfig, agentId: string, subAgent?: boolean) => AgentRunner;
|
|
16
|
+
withWatchdog: <T>(sessionId: string, external: AbortSignal | undefined, idleEnabled: boolean, fallbackStreams: boolean, run: (signal: AbortSignal) => Promise<T>) => Promise<T>;
|
|
17
|
+
onTurnRuntime: <T>(sessionId: string, runtime: {
|
|
18
|
+
source: AgentSource;
|
|
19
|
+
config: RuntimeConfig;
|
|
20
|
+
}, work: () => Promise<T>) => Promise<T>;
|
|
21
|
+
runtimeForAgent: (source: AgentSource) => Promise<RuntimeConfig>;
|
|
22
|
+
watchdogStreamsFor: (session: Pick<Session, 'metadata'> | undefined, config: RuntimeConfig) => {
|
|
23
|
+
switchedToFallback: boolean;
|
|
24
|
+
effectiveStreams: boolean;
|
|
25
|
+
fallbackStreams: boolean;
|
|
26
|
+
};
|
|
27
|
+
reachesHarness: (config: RuntimeConfig, switchedToFallback: boolean) => boolean;
|
|
28
|
+
settleLeftForNextStart: (input: DispatchInput, turn: Promise<Session>) => Promise<Session>;
|
|
29
|
+
}
|
|
30
|
+
export declare const createTurnDispatch: ({ options, env, store, getSelectedExecutor, defaultAgentId, refreshAgent, runtimeContextFor, runnerFor, withWatchdog, onTurnRuntime, runtimeForAgent, watchdogStreamsFor, reachesHarness, settleLeftForNextStart, }: TurnDispatchDeps) => {
|
|
31
|
+
dispatchInternal: (input: DispatchInput, absorbedKeys?: readonly string[], subAgent?: AgentDefinition, steer?: (turnSignal: AbortSignal) => Promise<SteeredMessage | undefined>) => Promise<Session>;
|
|
32
|
+
};
|
|
33
|
+
export type TurnDispatch = ReturnType<typeof createTurnDispatch>;
|
|
34
|
+
//# sourceMappingURL=turn-dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turn-dispatch.d.ts","sourceRoot":"","sources":["../src/turn-dispatch.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EAExB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAQhE,OAAO,EAAyB,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvG,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,cAAc,CAAC;IACxB,GAAG,EAAE,gBAAgB,CAAC;IACtB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,mBAAmB,EAAE,MAAM,QAAQ,GAAG,SAAS,CAAC;IAChD,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IACxD,iBAAiB,EAAE,CACjB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,OAAO,EACnB,QAAQ,EAAE,UAAU,GAAG,SAAS,EAChC,QAAQ,CAAC,EAAE,OAAO,KACf,mBAAmB,CAAC;IACzB,SAAS,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,WAAW,CAAC;IACvF,YAAY,EAAE,CAAC,CAAC,EACd,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,WAAW,GAAG,SAAS,EACjC,WAAW,EAAE,OAAO,EACpB,eAAe,EAAE,OAAO,EACxB,GAAG,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,KACrC,OAAO,CAAC,CAAC,CAAC,CAAC;IAChB,aAAa,EAAE,CAAC,CAAC,EACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,EACvD,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KACnB,OAAO,CAAC,CAAC,CAAC,CAAC;IAChB,eAAe,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;IACjE,kBAAkB,EAAE,CAClB,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,SAAS,EAC9C,MAAM,EAAE,aAAa,KAClB;QAAE,kBAAkB,EAAE,OAAO,CAAC;QAAC,gBAAgB,EAAE,OAAO,CAAC;QAAC,eAAe,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1F,cAAc,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,OAAO,KAAK,OAAO,CAAC;IAChF,sBAAsB,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5F;AAED,eAAO,MAAM,kBAAkB,GAAI,qNAehC,gBAAgB;8BAOR,aAAa,iBACN,SAAS,MAAM,EAAE,aACpB,eAAe,UAQlB,CAAC,UAAU,EAAE,WAAW,KAAK,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,KACvE,OAAO,CAAC,OAAO,CAAC;CAoKpB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* One turn on a session, below the queueing `dispatch` does: resolve the
|
|
3
|
+
* agent and its runtime, run it under the watchdog, and save what it left.
|
|
4
|
+
* `dispatchInternal` is what `dispatch`, scheduled firings, tool-call
|
|
5
|
+
* bindings and sub-agents call. Moved out of `createGateway` in index.ts as
|
|
6
|
+
* is: the statement is unchanged, inside a factory that takes what it closed
|
|
7
|
+
* over there, and `createGateway` calls it where it was. The one edit:
|
|
8
|
+
* `selectedExecutor` is a `let` set when plugins start, so it is read through
|
|
9
|
+
* `getSelectedExecutor()`.
|
|
10
|
+
*/
|
|
11
|
+
import { abortErrorFor, CONVERSATION_METADATA_KEY, } from '@stratusagent/core';
|
|
12
|
+
import { isDelegatedSession, withoutDelegation } from '@stratusagent/agents';
|
|
13
|
+
import { crossIdentityError, EXECUTOR_METADATA_KEY, isSubAgentSession, ROLLED_OVER_TO_METADATA_KEY, SUB_AGENT_METADATA_KEY, } from "./session-keys.js";
|
|
14
|
+
import { assertStateCompatible } from '@stratusagent/state';
|
|
15
|
+
export const createTurnDispatch = ({ options, env, store, getSelectedExecutor, defaultAgentId, refreshAgent, runtimeContextFor, runnerFor, withWatchdog, onTurnRuntime, runtimeForAgent, watchdogStreamsFor, reachesHarness, settleLeftForNextStart, }) => {
|
|
16
|
+
/**
|
|
17
|
+
* `subAgent` is the narrowed definition `subAgents.run` built: the turn
|
|
18
|
+
* runs as that, on the parent's resolved provider, with no memory and no
|
|
19
|
+
* soul. Only that path passes it.
|
|
20
|
+
*/
|
|
21
|
+
const dispatchInternal = async (input, absorbedKeys = [], subAgent,
|
|
22
|
+
/**
|
|
23
|
+
* See `RunInput.steer`; passed by `dispatch` for an opted-in caller.
|
|
24
|
+
* Handed the turn's own signal — the one the runner was given, which
|
|
25
|
+
* the watchdog, `abortTurns` and a restart's window abort as well as
|
|
26
|
+
* the callers — so it takes nothing into a turn that is already
|
|
27
|
+
* stopping (card 959).
|
|
28
|
+
*/
|
|
29
|
+
steer) => {
|
|
30
|
+
// Re-read on every turn, not once at start: a newer build that stamps
|
|
31
|
+
// the home while this daemon is serving has formats this build does not
|
|
32
|
+
// understand, and a daemon that kept writing into them would be the
|
|
33
|
+
// downgrade the stamp exists to refuse — from the inside. Inside the
|
|
34
|
+
// session chain, so a turn already accepted is counted by the drain
|
|
35
|
+
// before anything else runs. One small file read per turn.
|
|
36
|
+
assertStateCompatible(env);
|
|
37
|
+
// A dispatch whose signal fired while it queued behind another turn
|
|
38
|
+
// must not touch durable state: without this check, the runner would
|
|
39
|
+
// load the session, append the cancelled user message, and save it as
|
|
40
|
+
// failed — polluting future model history with input never processed.
|
|
41
|
+
if (input.signal?.aborted) {
|
|
42
|
+
throw abortErrorFor(input.signal);
|
|
43
|
+
}
|
|
44
|
+
// A session pins its agent: when the caller names none, an existing
|
|
45
|
+
// conversation keeps the agent it was created with even if the
|
|
46
|
+
// configured default soul has changed since — only a brand-new session
|
|
47
|
+
// takes the current default. (Loaded here, before the watchdog, also
|
|
48
|
+
// because whether this turn streams depends on durable session state.)
|
|
49
|
+
const existing = await store.get(input.sessionId);
|
|
50
|
+
const agentId = input.agentId ?? existing?.agent.id ?? await defaultAgentId();
|
|
51
|
+
const source = await refreshAgent(agentId);
|
|
52
|
+
const agent = subAgent ?? source.definition;
|
|
53
|
+
if (subAgent !== undefined && existing) {
|
|
54
|
+
throw new Error(`Session ${input.sessionId} already exists; a sub-agent's session is new every time.`);
|
|
55
|
+
}
|
|
56
|
+
// An archived transcript is the record of a conversation that has moved
|
|
57
|
+
// on. Continuing it would revive a session the operator deliberately
|
|
58
|
+
// left behind, under an id nothing routes to any more.
|
|
59
|
+
const continuedAs = existing?.metadata?.[ROLLED_OVER_TO_METADATA_KEY];
|
|
60
|
+
if (typeof continuedAs === 'string') {
|
|
61
|
+
throw new Error(`Session ${input.sessionId} was rolled over; it is an archived transcript and the conversation continues as ${continuedAs}.`);
|
|
62
|
+
}
|
|
63
|
+
const config = await runtimeForAgent(source);
|
|
64
|
+
const runner = runnerFor(config, source.definition.id, subAgent !== undefined);
|
|
65
|
+
// Which executor the turn's tool calls run through — the built-in
|
|
66
|
+
// under the name `stratus run` has always recorded, a contributed one
|
|
67
|
+
// under its registered name — so a transcript says where a command
|
|
68
|
+
// ran, not only which model asked for it.
|
|
69
|
+
const executorRecord = getSelectedExecutor() && options.executor !== undefined ? options.executor : 'local-command';
|
|
70
|
+
const metadata = {
|
|
71
|
+
provider: config.provider,
|
|
72
|
+
// A contributed provider may leave the model to its own default, in
|
|
73
|
+
// which case there is none to record.
|
|
74
|
+
...(config.provider !== 'demo' && config.model !== undefined ? { model: config.model } : {}),
|
|
75
|
+
...input.metadata,
|
|
76
|
+
// After the caller's metadata, and reserved besides: a dispatch that
|
|
77
|
+
// could write it could make a transcript claim a sandbox ran what
|
|
78
|
+
// the host ran.
|
|
79
|
+
[EXECUTOR_METADATA_KEY]: executorRecord,
|
|
80
|
+
};
|
|
81
|
+
if (existing && existing.agent.id !== agent.id) {
|
|
82
|
+
throw crossIdentityError(input.sessionId, existing.agent.id, agent.id);
|
|
83
|
+
}
|
|
84
|
+
// A sub-agent's session is new, but may start on its parent's fallback.
|
|
85
|
+
const { switchedToFallback, effectiveStreams, fallbackStreams } = watchdogStreamsFor(existing ?? (subAgent !== undefined ? { metadata } : undefined), config);
|
|
86
|
+
// Recorded with a keyed message so a restart judges the turn by what it
|
|
87
|
+
// could have run on, not by whatever the config resolves to by then.
|
|
88
|
+
// The fallback counts: a turn can switch to it mid-run. Once a session
|
|
89
|
+
// has switched for good, the primary is never called again, and only
|
|
90
|
+
// the fallback counts.
|
|
91
|
+
const hostedLoop = input.idempotencyKey !== undefined && reachesHarness(config, switchedToFallback);
|
|
92
|
+
return settleLeftForNextStart(input, onTurnRuntime(input.sessionId, { source, config }, () => withWatchdog(input.sessionId, input.signal, effectiveStreams, fallbackStreams, async (signal) => {
|
|
93
|
+
// The preflight above (agent refresh, config resolution, session
|
|
94
|
+
// load) awaited filesystem work; the entry check has long passed.
|
|
95
|
+
// Recheck before the runner touches durable state, or a dispatch
|
|
96
|
+
// cancelled mid-preflight would still persist its user message.
|
|
97
|
+
if (signal.aborted) {
|
|
98
|
+
throw abortErrorFor(signal);
|
|
99
|
+
}
|
|
100
|
+
if (existing) {
|
|
101
|
+
// Refresh the stored definition before resuming, so the turn runs
|
|
102
|
+
// with the current instructions, tools, and credentials.
|
|
103
|
+
existing.agent = agent;
|
|
104
|
+
// A sub-session reached here is being continued from outside — a
|
|
105
|
+
// delegation never resumes its own child; its ids are minted once.
|
|
106
|
+
// The delegating turn is over, so the markers come off: what is
|
|
107
|
+
// now an ordinary conversation must not be closed as an orphan if
|
|
108
|
+
// a later turn of it parks and the daemon dies.
|
|
109
|
+
if (isDelegatedSession(existing) && existing.metadata) {
|
|
110
|
+
existing.metadata = withoutDelegation(existing.metadata);
|
|
111
|
+
}
|
|
112
|
+
// The same for a sub-agent's session, continued as the agent itself:
|
|
113
|
+
// the marker that denies its approvals unasked comes off with the
|
|
114
|
+
// delegation markers it carries.
|
|
115
|
+
if (isSubAgentSession(existing) && existing.metadata) {
|
|
116
|
+
const { [SUB_AGENT_METADATA_KEY]: _subAgent, ...rest } = withoutDelegation(existing.metadata);
|
|
117
|
+
existing.metadata = rest;
|
|
118
|
+
}
|
|
119
|
+
// The executor record follows the daemon, not the session's first
|
|
120
|
+
// turn: a restart that selected another executor runs this turn's
|
|
121
|
+
// commands there, and a session from before the record existed
|
|
122
|
+
// gets one now rather than never.
|
|
123
|
+
if (existing.metadata?.[EXECUTOR_METADATA_KEY] !== executorRecord) {
|
|
124
|
+
existing.metadata = { ...existing.metadata, [EXECUTOR_METADATA_KEY]: executorRecord };
|
|
125
|
+
}
|
|
126
|
+
// The room rides on the turn, but two readers have only the
|
|
127
|
+
// session's: a turn parked on approval and recovered after a
|
|
128
|
+
// restart, and a turn that brings no room of its own (a schedule
|
|
129
|
+
// firing into the thread). Both get the latest room this way, not
|
|
130
|
+
// the first turn's, which a channel made public since would make
|
|
131
|
+
// read as more private than it is. A turn from a channel that
|
|
132
|
+
// could not tell the room (its lookup failed) clears it instead:
|
|
133
|
+
// no room is the generic line, and an old one is a claim.
|
|
134
|
+
if (typeof input.metadata?.channel === 'string') {
|
|
135
|
+
const room = input.metadata[CONVERSATION_METADATA_KEY];
|
|
136
|
+
const { [CONVERSATION_METADATA_KEY]: _stale, ...rest } = existing.metadata ?? {};
|
|
137
|
+
existing.metadata = room !== undefined ? { ...rest, [CONVERSATION_METADATA_KEY]: room } : rest;
|
|
138
|
+
}
|
|
139
|
+
await store.save(existing);
|
|
140
|
+
// The turn's metadata rides along for the sender's trust: without
|
|
141
|
+
// it a resumed turn has no way to say who sent it, and a stranger
|
|
142
|
+
// mentioning the agent in a thread the operator opened would
|
|
143
|
+
// inherit the operator's label.
|
|
144
|
+
return runner.resume({
|
|
145
|
+
sessionId: input.sessionId,
|
|
146
|
+
userMessage: input.userMessage,
|
|
147
|
+
...(input.images !== undefined ? { images: input.images } : {}),
|
|
148
|
+
...(input.addressed !== undefined ? { addressed: input.addressed } : {}),
|
|
149
|
+
...(input.replyOptional === true ? { replyOptional: true } : {}),
|
|
150
|
+
...(input.idempotencyKey !== undefined ? { idempotencyKey: input.idempotencyKey } : {}),
|
|
151
|
+
...(absorbedKeys.length > 0 ? { absorbedKeys: [...absorbedKeys] } : {}),
|
|
152
|
+
...(hostedLoop ? { hostedLoop } : {}),
|
|
153
|
+
...(input.metadata ? { metadata: input.metadata } : {}),
|
|
154
|
+
runtime: runtimeContextFor(source, config, switchedToFallback, input.metadata),
|
|
155
|
+
...(steer !== undefined ? { steer: () => steer(signal) } : {}),
|
|
156
|
+
signal,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return runner.run({
|
|
160
|
+
sessionId: input.sessionId,
|
|
161
|
+
agent,
|
|
162
|
+
userMessage: input.userMessage,
|
|
163
|
+
...(input.images !== undefined ? { images: input.images } : {}),
|
|
164
|
+
...(input.addressed !== undefined ? { addressed: input.addressed } : {}),
|
|
165
|
+
...(input.replyOptional === true ? { replyOptional: true } : {}),
|
|
166
|
+
...(input.idempotencyKey !== undefined ? { idempotencyKey: input.idempotencyKey } : {}),
|
|
167
|
+
...(absorbedKeys.length > 0 ? { absorbedKeys: [...absorbedKeys] } : {}),
|
|
168
|
+
...(hostedLoop ? { hostedLoop } : {}),
|
|
169
|
+
...(input.earlier !== undefined && input.earlier.length > 0 ? { earlier: input.earlier } : {}),
|
|
170
|
+
metadata,
|
|
171
|
+
runtime: runtimeContextFor(source, config, switchedToFallback, input.metadata, subAgent !== undefined),
|
|
172
|
+
...(steer !== undefined ? { steer: () => steer(signal) } : {}),
|
|
173
|
+
signal,
|
|
174
|
+
});
|
|
175
|
+
})));
|
|
176
|
+
};
|
|
177
|
+
return { dispatchInternal };
|
|
178
|
+
};
|
|
179
|
+
//# sourceMappingURL=turn-dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turn-dispatch.js","sourceRoot":"","sources":["../src/turn-dispatch.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratusagent/gateway",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -19,16 +19,16 @@
|
|
|
19
19
|
"node": ">=22.16 <23 || >=24"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@stratusagent/agents": "0.14.
|
|
23
|
-
"@stratusagent/core": "0.14.
|
|
24
|
-
"@stratusagent/executor-local": "0.14.
|
|
25
|
-
"@stratusagent/
|
|
26
|
-
"@stratusagent/
|
|
22
|
+
"@stratusagent/agents": "0.14.9",
|
|
23
|
+
"@stratusagent/core": "0.14.9",
|
|
24
|
+
"@stratusagent/executor-local": "0.14.9",
|
|
25
|
+
"@stratusagent/plugins": "0.14.9",
|
|
26
|
+
"@stratusagent/state": "0.14.9"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^24.6.0",
|
|
30
30
|
"typescript": "^5.9.3",
|
|
31
|
-
"@stratusagent/permissions": "0.14.
|
|
31
|
+
"@stratusagent/permissions": "0.14.9"
|
|
32
32
|
},
|
|
33
33
|
"license": "Apache-2.0",
|
|
34
34
|
"repository": {
|