@stratusagent/gateway 0.14.7 → 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 +4 -1290
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +202 -2546
- package/dist/index.js.map +1 -1
- package/dist/lifecycle.d.ts +130 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +147 -0
- package/dist/lifecycle.js.map +1 -0
- 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/session-keys.d.ts +101 -0
- package/dist/session-keys.d.ts.map +1 -0
- package/dist/session-keys.js +148 -0
- package/dist/session-keys.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/dist/types.d.ts +1103 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +7 -7
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ParsedSoul } from '@stratusagent/agents';
|
|
2
|
+
import type { AgentDefinition } from '@stratusagent/core';
|
|
3
|
+
export interface AgentSource {
|
|
4
|
+
definition: AgentDefinition;
|
|
5
|
+
/** Soul file backing this agent; undefined for the built-in default. */
|
|
6
|
+
soulPath?: string;
|
|
7
|
+
/** The parsed soul, carried for its provider/model pins. */
|
|
8
|
+
soul?: ParsedSoul;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=agent-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-source.d.ts","sourceRoot":"","sources":["../src/agent-source.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,eAAe,CAAC;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* One agent as the gateway holds it: its definition, the soul file behind
|
|
3
|
+
* it and the parsed soul. Moved out of index.ts as is so the modules split
|
|
4
|
+
* out of `createGateway` can name it; index.ts does not re-export it.
|
|
5
|
+
*/
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=agent-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-source.js","sourceRoot":"","sources":["../src/agent-source.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ApprovalAnswer, ApprovalResolutionReason, EventBus, Session } from '@stratusagent/core';
|
|
2
|
+
import type { SchedulerRuntime } from './schedules.ts';
|
|
3
|
+
import type { ShardedSessionStore } from './sessions.ts';
|
|
4
|
+
import type { ApprovalRequester, PendingApproval, ResolveApprovalInput } from './types.ts';
|
|
5
|
+
export type SettleApproval = (answer: ApprovalAnswer, reason: ApprovalResolutionReason, actor?: string) => void;
|
|
6
|
+
/**
|
|
7
|
+
* One parked call: how to settle it, and what it is. The summary is kept
|
|
8
|
+
* alongside the settler because a listing needs the request itself, and
|
|
9
|
+
* the map is the only place that knows a request is still outstanding.
|
|
10
|
+
*/
|
|
11
|
+
export interface ParkedCall {
|
|
12
|
+
settle: SettleApproval;
|
|
13
|
+
pending: PendingApproval;
|
|
14
|
+
}
|
|
15
|
+
/** What the approval broker closes over in `createGateway`. */
|
|
16
|
+
export interface ApprovalBrokerDeps {
|
|
17
|
+
warn: (line: string) => void;
|
|
18
|
+
bus: EventBus;
|
|
19
|
+
store: ShardedSessionStore;
|
|
20
|
+
scheduler: SchedulerRuntime;
|
|
21
|
+
effectiveApprovalTimeoutMs: number;
|
|
22
|
+
isStopping: () => boolean;
|
|
23
|
+
}
|
|
24
|
+
export declare const createApprovalBroker: ({ warn, bus, store, scheduler, effectiveApprovalTimeoutMs, isStopping, }: ApprovalBrokerDeps) => {
|
|
25
|
+
pendingApprovals: Map<string, ParkedCall>;
|
|
26
|
+
approvalEmissions: Set<Promise<void>>;
|
|
27
|
+
liveSubAgentIds: Set<string>;
|
|
28
|
+
idAtFirstCall: WeakMap<Session, string>;
|
|
29
|
+
hostIdOf: (session: Session) => string;
|
|
30
|
+
isHostSubAgent: (session: Session) => boolean;
|
|
31
|
+
requestApproval: ApprovalRequester;
|
|
32
|
+
resolveApproval: (input: ResolveApprovalInput) => boolean;
|
|
33
|
+
suspendWatchdog: Map<string, () => void>;
|
|
34
|
+
approvalWaits: Map<string, number>;
|
|
35
|
+
holdApprovalWait: (sessionId: string) => (() => void);
|
|
36
|
+
};
|
|
37
|
+
export type ApprovalBroker = ReturnType<typeof createApprovalBroker>;
|
|
38
|
+
//# sourceMappingURL=approvals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../src/approvals.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,cAAc,EAGd,wBAAwB,EACxB,QAAQ,EACR,OAAO,EACR,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EACV,iBAAiB,EAEjB,eAAe,EACf,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAGpB,MAAM,MAAM,cAAc,GAAG,CAC3B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,wBAAwB,EAChC,KAAK,CAAC,EAAE,MAAM,KACX,IAAI,CAAC;AAEV;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,eAAe,CAAC;CAC1B;AAED,+DAA+D;AAC/D,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,mBAAmB,CAAC;IAC3B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,0BAA0B,EAAE,MAAM,CAAC;IACnC,UAAU,EAAE,MAAM,OAAO,CAAC;CAC3B;AAED,eAAO,MAAM,oBAAoB,GAAI,0EAOlC,kBAAkB;;;;;wBAiEQ,OAAO,KAAG,MAAM;8BAEV,OAAO,KAAG,OAAO;;6BA6MlB,oBAAoB,KAAG,OAAO;uCAkBhB,IAAI;;kCAmBb,MAAM,KAAG,CAAC,MAAM,IAAI,CAAC;CAiC3D,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The gateway's approval broker: parked tool calls waiting on a person, how
|
|
3
|
+
* a request is asked (and refused for a sub-agent or during shutdown), how an
|
|
4
|
+
* answer settles it, and the per-session approval waits the turn watchdog
|
|
5
|
+
* reads. Moved out of `createGateway` in index.ts as is: the statements are
|
|
6
|
+
* unchanged, inside a factory that takes what they closed over there, and
|
|
7
|
+
* `createGateway` calls it where they were and destructures what it returns.
|
|
8
|
+
* The one edit: `stopping` is a `let` declared later in `createGateway`, so
|
|
9
|
+
* the broker reads it through `isStopping()`.
|
|
10
|
+
*/
|
|
11
|
+
import { randomUUID } from 'node:crypto';
|
|
12
|
+
import { isDelegatedSession, ROOT_SESSION_ID_METADATA_KEY } from '@stratusagent/agents';
|
|
13
|
+
import { isSubAgentSession } from "./session-keys.js";
|
|
14
|
+
export const createApprovalBroker = ({ warn, bus, store, scheduler, effectiveApprovalTimeoutMs, isStopping, }) => {
|
|
15
|
+
const pendingApprovals = new Map();
|
|
16
|
+
/**
|
|
17
|
+
* In-flight `tool.approval-resolved` emissions. `EventBus.emit` awaits its
|
|
18
|
+
* subscribers in order, so one async handler ahead of a channel adapter
|
|
19
|
+
* suspends the emission before the adapter ever sees it. Nothing today is
|
|
20
|
+
* async in front of one — which is exactly the problem: the shutdown
|
|
21
|
+
* guarantee below would rest on that staying true, and the first async
|
|
22
|
+
* subscriber anyone adds would silently leave live-looking buttons in a
|
|
23
|
+
* workspace the daemon has left.
|
|
24
|
+
*/
|
|
25
|
+
const approvalEmissions = new Set();
|
|
26
|
+
/**
|
|
27
|
+
* Publishes one parked call and settles when somebody answers it, the
|
|
28
|
+
* request expires, or the turn is cancelled.
|
|
29
|
+
*
|
|
30
|
+
* All three endings run through the same `settle`, which removes the
|
|
31
|
+
* request from the registry BEFORE resolving. That ordering is the whole
|
|
32
|
+
* point: a request that is no longer pending cannot be resolved twice,
|
|
33
|
+
* so a click racing the timeout — or arriving after an abort — is refused
|
|
34
|
+
* rather than executing a tool for a turn that has already moved on.
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* The conversation a delegated sub-session's work was asked from, read
|
|
38
|
+
* from the store rather than from anything the caller wrote: the root
|
|
39
|
+
* session `agent.delegate` recorded, which is where the person waiting
|
|
40
|
+
* on the answer is. Undefined for an ordinary session, or a root that no
|
|
41
|
+
* longer exists — the request is then asked the way it always was.
|
|
42
|
+
*/
|
|
43
|
+
const delegationOriginOf = async (session) => {
|
|
44
|
+
if (!isDelegatedSession(session)) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const rootId = session.metadata?.[ROOT_SESSION_ID_METADATA_KEY];
|
|
48
|
+
if (typeof rootId !== 'string' || rootId === session.id) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
let root;
|
|
52
|
+
try {
|
|
53
|
+
root = await store.get(rootId);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
warn(`${session.id}: could not read the delegating session ${rootId} to route an approval (${error instanceof Error ? error.message : String(error)})`);
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
if (!root) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
return { agentId: root.agent.id, sessionId: root.id, ...(root.metadata ? { metadata: root.metadata } : {}) };
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Which sessions are sub-agents, as the host knows it rather than as the
|
|
66
|
+
* session says (roadmap 24). Every tool in a slice is handed the same
|
|
67
|
+
* mutable Session, so the metadata marker and the id are claims a tool
|
|
68
|
+
* can rewrite. The ids are the ones `subAgents.run` minted, held while
|
|
69
|
+
* the sub-agent runs. A session object's id is read once, by the
|
|
70
|
+
* executor on its first tool call, before any tool has been handed it,
|
|
71
|
+
* so a session a tool renamed is still known by the id it ran under.
|
|
72
|
+
*/
|
|
73
|
+
const liveSubAgentIds = new Set();
|
|
74
|
+
const idAtFirstCall = new WeakMap();
|
|
75
|
+
const hostIdOf = (session) => idAtFirstCall.get(session) ?? session.id;
|
|
76
|
+
const isHostSubAgent = (session) => liveSubAgentIds.has(hostIdOf(session)) || isSubAgentSession(session);
|
|
77
|
+
const requestApproval = async (request) => {
|
|
78
|
+
// A sub-agent asks no one (roadmap 24): its parent turn is the one a
|
|
79
|
+
// person is accountable for, and that turn gets the refusal back as a
|
|
80
|
+
// result and decides what to do. Denied as undeliverable, since nobody
|
|
81
|
+
// was asked, and announced only as a resolution, so no channel renders
|
|
82
|
+
// a question nobody may answer.
|
|
83
|
+
if (isHostSubAgent(request.session)) {
|
|
84
|
+
void bus.emit({
|
|
85
|
+
type: 'tool.approval-resolved',
|
|
86
|
+
sessionId: request.session.id,
|
|
87
|
+
requestId: randomUUID(),
|
|
88
|
+
answer: 'deny',
|
|
89
|
+
reason: 'undeliverable',
|
|
90
|
+
});
|
|
91
|
+
return { answer: 'deny' };
|
|
92
|
+
}
|
|
93
|
+
const delegatedFrom = await delegationOriginOf(request.session);
|
|
94
|
+
return requestApprovalFrom(request, delegatedFrom);
|
|
95
|
+
};
|
|
96
|
+
const requestApprovalFrom = (request, delegatedFrom) => new Promise((resolve) => {
|
|
97
|
+
// A shutdown denies what is parked once, at the top of stop(). Turns
|
|
98
|
+
// already running keep going through the drain, though, and one of them
|
|
99
|
+
// can reach a gated tool AFTER that snapshot — finishing a provider
|
|
100
|
+
// call, or moving to the next call in the same response. Parking it
|
|
101
|
+
// would deadlock the drain against a question nobody is left to answer:
|
|
102
|
+
// stop() waits for the turn, the turn waits for the approval, and the
|
|
103
|
+
// approval waits out its timeout — forever when there is none.
|
|
104
|
+
if (isStopping()) {
|
|
105
|
+
resolve({ answer: 'deny' });
|
|
106
|
+
void bus.emit({
|
|
107
|
+
type: 'tool.approval-resolved',
|
|
108
|
+
sessionId: request.session.id,
|
|
109
|
+
requestId: randomUUID(),
|
|
110
|
+
answer: 'deny',
|
|
111
|
+
reason: 'cancelled',
|
|
112
|
+
});
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const requestId = randomUUID();
|
|
116
|
+
let timer;
|
|
117
|
+
const onAbort = () => settle('deny', 'cancelled');
|
|
118
|
+
/**
|
|
119
|
+
* Settles once the request has finished being announced.
|
|
120
|
+
*
|
|
121
|
+
* Both emissions go through the same subscriber list, in order, and
|
|
122
|
+
* `EventBus.emit` awaits each one — so an async subscriber ahead of a
|
|
123
|
+
* channel can hold the announcement while a timeout or abort fires
|
|
124
|
+
* behind it, and the channel would hear that a request it has never
|
|
125
|
+
* heard of was resolved. It drops that, then renders the announcement
|
|
126
|
+
* when it finally arrives, leaving buttons for a settled request that
|
|
127
|
+
* nothing will ever retract.
|
|
128
|
+
*
|
|
129
|
+
* Chaining is the fix rather than remembering orphaned resolutions in
|
|
130
|
+
* the channel: a resolution that arrives before its request is not
|
|
131
|
+
* something a consumer can act on, so it should not be able to happen.
|
|
132
|
+
* Starts resolved, because a turn already aborted never announces at
|
|
133
|
+
* all and its denial should not wait on an emission that never runs.
|
|
134
|
+
*/
|
|
135
|
+
let announced = Promise.resolve();
|
|
136
|
+
// Read when the request is made, from the scheduler's own records: a
|
|
137
|
+
// live firing of a schedule approved with a destination, nothing else.
|
|
138
|
+
// Delegated work is not included yet; its sub-session is not a firing.
|
|
139
|
+
const scheduleDestination = scheduler.approvalDestinationFor(request.session);
|
|
140
|
+
// Work one agent does for another is allowed one call at a time. The
|
|
141
|
+
// people asked are the delegating conversation's, and a standing grant
|
|
142
|
+
// would widen what the other agent may do on its own work for good —
|
|
143
|
+
// so nothing offers **Always allow** here, and an `always` that
|
|
144
|
+
// arrives anyway (the control API takes all three answers) runs the
|
|
145
|
+
// call once, recorded as exactly that.
|
|
146
|
+
const forAnotherAgent = delegatedFrom !== undefined && delegatedFrom.agentId !== request.session.agent.id;
|
|
147
|
+
const oneShot = request.oneShot === true || forAnotherAgent;
|
|
148
|
+
const always = forAnotherAgent ? undefined : request.always;
|
|
149
|
+
const settle = (given, reason, actor) => {
|
|
150
|
+
const answer = forAnotherAgent && given === 'always' ? 'once' : given;
|
|
151
|
+
// Identity, not presence: a request that already settled is gone from
|
|
152
|
+
// the registry, and comparing against this exact function is what
|
|
153
|
+
// makes every ending — click, timeout, abort, shutdown — idempotent.
|
|
154
|
+
if (pendingApprovals.get(requestId)?.settle !== settle) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
pendingApprovals.delete(requestId);
|
|
158
|
+
if (timer) {
|
|
159
|
+
clearTimeout(timer);
|
|
160
|
+
}
|
|
161
|
+
request.signal?.removeEventListener('abort', onAbort);
|
|
162
|
+
resolve({ answer, ...(actor ? { actor } : {}) });
|
|
163
|
+
const emitted = announced.then(() => bus.emit({
|
|
164
|
+
type: 'tool.approval-resolved',
|
|
165
|
+
sessionId: request.session.id,
|
|
166
|
+
requestId,
|
|
167
|
+
answer,
|
|
168
|
+
reason,
|
|
169
|
+
...(actor ? { actor } : {}),
|
|
170
|
+
}));
|
|
171
|
+
approvalEmissions.add(emitted);
|
|
172
|
+
void emitted.finally(() => approvalEmissions.delete(emitted));
|
|
173
|
+
};
|
|
174
|
+
// What is left of the window, not a fresh one: a re-asked request
|
|
175
|
+
// carries when it originally parked, and the elapsed time counts.
|
|
176
|
+
// Computed before registration because the summary below quotes the
|
|
177
|
+
// deadline, and a listing that disagreed with the announcing event about
|
|
178
|
+
// when a request expires would be worse than one that said nothing.
|
|
179
|
+
const alreadyWaitedMs = request.parkedAt ? Date.now() - Date.parse(request.parkedAt) : 0;
|
|
180
|
+
const remainingTimeoutMs = effectiveApprovalTimeoutMs > 0
|
|
181
|
+
? effectiveApprovalTimeoutMs - (Number.isFinite(alreadyWaitedMs) ? Math.max(0, alreadyWaitedMs) : 0)
|
|
182
|
+
: 0;
|
|
183
|
+
const expiresAt = remainingTimeoutMs > 0
|
|
184
|
+
? new Date(Date.now() + remainingTimeoutMs).toISOString()
|
|
185
|
+
: undefined;
|
|
186
|
+
pendingApprovals.set(requestId, {
|
|
187
|
+
settle,
|
|
188
|
+
pending: {
|
|
189
|
+
requestId,
|
|
190
|
+
sessionId: request.session.id,
|
|
191
|
+
agentId: request.session.agent.id,
|
|
192
|
+
call: request.call,
|
|
193
|
+
risk: request.risk,
|
|
194
|
+
...(request.origin !== undefined ? { origin: request.origin } : {}),
|
|
195
|
+
...(oneShot ? { oneShot: true } : {}),
|
|
196
|
+
...(always !== undefined ? { always } : {}),
|
|
197
|
+
...(request.reviewNote !== undefined ? { reviewNote: request.reviewNote } : {}),
|
|
198
|
+
parkedAt: request.parkedAt ?? new Date().toISOString(),
|
|
199
|
+
...(expiresAt ? { expiresAt } : {}),
|
|
200
|
+
...(request.session.metadata ? { metadata: request.session.metadata } : {}),
|
|
201
|
+
...(delegatedFrom ? { delegatedFrom } : {}),
|
|
202
|
+
...(scheduleDestination ? { scheduleDestination } : {}),
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
if (effectiveApprovalTimeoutMs > 0 && remainingTimeoutMs <= 0) {
|
|
206
|
+
// Nothing left to wait with. Settled here rather than armed with a
|
|
207
|
+
// zero timer, which `setTimeout` would still run a tick later — long
|
|
208
|
+
// enough to announce a request that is already over.
|
|
209
|
+
settle('deny', 'timeout');
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (remainingTimeoutMs > 0) {
|
|
213
|
+
// Deliberately NOT unref'd. A parked turn is real outstanding work,
|
|
214
|
+
// and its timer is the only thing that will ever finish it — letting
|
|
215
|
+
// the process exit out from under one would abandon the turn instead
|
|
216
|
+
// of denying it. Shutdown is handled where it belongs, in stop(),
|
|
217
|
+
// which settles every outstanding request before draining.
|
|
218
|
+
timer = setTimeout(() => settle('deny', 'timeout'), remainingTimeoutMs);
|
|
219
|
+
}
|
|
220
|
+
// The abort listener is attached before the request is announced, so a
|
|
221
|
+
// turn cancelled while the event is still being delivered still ends
|
|
222
|
+
// the request rather than leaving it pending forever.
|
|
223
|
+
if (request.signal) {
|
|
224
|
+
if (request.signal.aborted) {
|
|
225
|
+
settle('deny', 'cancelled');
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
request.signal.addEventListener('abort', onAbort, { once: true });
|
|
229
|
+
}
|
|
230
|
+
// `announced` is assigned BEFORE the emission starts, because emit runs
|
|
231
|
+
// its first subscribers synchronously — one of them settling the
|
|
232
|
+
// request inline would otherwise chain onto the already-resolved
|
|
233
|
+
// placeholder and race the very announcement it is answering.
|
|
234
|
+
let markAnnounced = () => { };
|
|
235
|
+
announced = new Promise((resolveAnnounced) => {
|
|
236
|
+
markAnnounced = resolveAnnounced;
|
|
237
|
+
});
|
|
238
|
+
const announcing = bus.emit({
|
|
239
|
+
type: 'tool.approval-requested',
|
|
240
|
+
sessionId: request.session.id,
|
|
241
|
+
agentId: request.session.agent.id,
|
|
242
|
+
requestId,
|
|
243
|
+
call: request.call,
|
|
244
|
+
risk: request.risk,
|
|
245
|
+
...(request.origin !== undefined ? { origin: request.origin } : {}),
|
|
246
|
+
...(oneShot ? { oneShot: true } : {}),
|
|
247
|
+
...(always !== undefined ? { always } : {}),
|
|
248
|
+
...(request.reviewNote !== undefined ? { reviewNote: request.reviewNote } : {}),
|
|
249
|
+
...(request.session.metadata ? { metadata: request.session.metadata } : {}),
|
|
250
|
+
...(delegatedFrom ? { delegatedFrom } : {}),
|
|
251
|
+
...(scheduleDestination ? { scheduleDestination } : {}),
|
|
252
|
+
...(expiresAt ? { expiresAt } : {}),
|
|
253
|
+
});
|
|
254
|
+
// Drained at shutdown alongside the resolutions: a channel that has not
|
|
255
|
+
// yet been told a request exists cannot be told it was denied either.
|
|
256
|
+
approvalEmissions.add(announcing);
|
|
257
|
+
void announcing.finally(() => {
|
|
258
|
+
approvalEmissions.delete(announcing);
|
|
259
|
+
markAnnounced();
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
const resolveApproval = (input) => {
|
|
263
|
+
const parked = pendingApprovals.get(input.requestId);
|
|
264
|
+
if (!parked) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
parked.settle(input.answer, input.reason ?? 'decided', input.actor);
|
|
268
|
+
return true;
|
|
269
|
+
};
|
|
270
|
+
/**
|
|
271
|
+
* How a turn's watchdog stops its own clock, registered while it runs.
|
|
272
|
+
*
|
|
273
|
+
* Recording that a tool phase is open is not enough on its own: the
|
|
274
|
+
* timer is only re-evaluated when an event arrives, so a phase opened by
|
|
275
|
+
* something that emits nothing — an approval policy handed straight to
|
|
276
|
+
* the gateway — would leave an already-armed timer running to fire
|
|
277
|
+
* mid-wait.
|
|
278
|
+
*/
|
|
279
|
+
const suspendWatchdog = new Map();
|
|
280
|
+
/**
|
|
281
|
+
* Approval waits in progress, per session.
|
|
282
|
+
*
|
|
283
|
+
* Deliberately a balanced counter and not a set of call ids. An earlier
|
|
284
|
+
* shape had the approval wrapper *open* a phase that the watchdog's
|
|
285
|
+
* event observer was expected to close, and that handoff was wrong in
|
|
286
|
+
* every way it could be: the observer does not exist when no watchdog is
|
|
287
|
+
* armed, so nothing closed it; a policy that threw closed nothing; and a
|
|
288
|
+
* stale entry did not merely leak, it suppressed the watchdog for the
|
|
289
|
+
* next turn on that session. Four separate exits, each patched in turn.
|
|
290
|
+
*
|
|
291
|
+
* A counter incremented and decremented in one `finally` cannot have any
|
|
292
|
+
* of those bugs, because the thing that opens the phase is the thing
|
|
293
|
+
* that closes it, in the same scope, on every path out.
|
|
294
|
+
*/
|
|
295
|
+
const approvalWaits = new Map();
|
|
296
|
+
const holdApprovalWait = (sessionId) => {
|
|
297
|
+
approvalWaits.set(sessionId, (approvalWaits.get(sessionId) ?? 0) + 1);
|
|
298
|
+
// Stop any clock already running: this wait produces no events, so
|
|
299
|
+
// nothing else would.
|
|
300
|
+
suspendWatchdog.get(sessionId)?.();
|
|
301
|
+
let released = false;
|
|
302
|
+
return () => {
|
|
303
|
+
if (released) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
released = true;
|
|
307
|
+
const remaining = (approvalWaits.get(sessionId) ?? 1) - 1;
|
|
308
|
+
if (remaining > 0) {
|
|
309
|
+
approvalWaits.set(sessionId, remaining);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
approvalWaits.delete(sessionId);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
};
|
|
316
|
+
return {
|
|
317
|
+
pendingApprovals,
|
|
318
|
+
approvalEmissions,
|
|
319
|
+
liveSubAgentIds,
|
|
320
|
+
idAtFirstCall,
|
|
321
|
+
hostIdOf,
|
|
322
|
+
isHostSubAgent,
|
|
323
|
+
requestApproval,
|
|
324
|
+
resolveApproval,
|
|
325
|
+
suspendWatchdog,
|
|
326
|
+
approvalWaits,
|
|
327
|
+
holdApprovalWait,
|
|
328
|
+
};
|
|
329
|
+
};
|
|
330
|
+
//# sourceMappingURL=approvals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../src/approvals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AASzC,OAAO,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AASxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AA4BtD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,EACnC,IAAI,EACJ,GAAG,EACH,KAAK,EACL,SAAS,EACT,0BAA0B,EAC1B,UAAU,GACS,EAAE,EAAE;IACvB,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAsB,CAAC;IAEvD;;;;;;;;OAQG;IACH,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAiB,CAAC;IAEnD;;;;;;;;;OASG;IACH;;;;;;OAMG;IACH,MAAM,kBAAkB,GAAG,KAAK,EAAE,OAAgB,EAAiD,EAAE;QACnG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;YACjC,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,4BAA4B,CAAC,CAAC;QAChE,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,OAAO,CAAC,EAAE,EAAE,CAAC;YACxD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,IAAI,IAAyB,CAAC;QAC9B,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,GAAG,OAAO,CAAC,EAAE,2CAA2C,MAAM,0BAA0B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxJ,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAC/G,CAAC,CAAC;IAEF;;;;;;;;OAQG;IACH,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;IAE1C,MAAM,aAAa,GAAG,IAAI,OAAO,EAAmB,CAAC;IAErD,MAAM,QAAQ,GAAG,CAAC,OAAgB,EAAU,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,EAAE,CAAC;IAExF,MAAM,cAAc,GAAG,CAAC,OAAgB,EAAW,EAAE,CACnD,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAEvE,MAAM,eAAe,GAAsB,KAAK,EAAE,OAAO,EAAE,EAAE;QAC3D,qEAAqE;QACrE,sEAAsE;QACtE,uEAAuE;QACvE,uEAAuE;QACvE,gCAAgC;QAChC,IAAI,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACpC,KAAK,GAAG,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,wBAAwB;gBAC9B,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC7B,SAAS,EAAE,UAAU,EAAE;gBACvB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,eAAe;aACxB,CAAC,CAAC;YACH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC5B,CAAC;QACD,MAAM,aAAa,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAChE,OAAO,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACrD,CAAC,CAAC;IAEF,MAAM,mBAAmB,GAAG,CAC1B,OAA+B,EAC/B,aAAmD,EACzB,EAAE,CAAC,IAAI,OAAO,CAAkB,CAAC,OAAO,EAAE,EAAE;QACtE,qEAAqE;QACrE,wEAAwE;QACxE,oEAAoE;QACpE,oEAAoE;QACpE,wEAAwE;QACxE,sEAAsE;QACtE,+DAA+D;QAC/D,IAAI,UAAU,EAAE,EAAE,CAAC;YACjB,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YAC5B,KAAK,GAAG,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,wBAAwB;gBAC9B,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC7B,SAAS,EAAE,UAAU,EAAE;gBACvB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,WAAW;aACpB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;QAE/B,IAAI,KAAiC,CAAC;QACtC,MAAM,OAAO,GAAG,GAAS,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAExD;;;;;;;;;;;;;;;;WAgBG;QACH,IAAI,SAAS,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;QAEjD,qEAAqE;QACrE,uEAAuE;QACvE,uEAAuE;QACvE,MAAM,mBAAmB,GAAG,SAAS,CAAC,sBAAsB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAE9E,qEAAqE;QACrE,uEAAuE;QACvE,qEAAqE;QACrE,gEAAgE;QAChE,oEAAoE;QACpE,uCAAuC;QACvC,MAAM,eAAe,GAAG,aAAa,KAAK,SAAS,IAAI,aAAa,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1G,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,KAAK,IAAI,IAAI,eAAe,CAAC;QAC5D,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QAE5D,MAAM,MAAM,GAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;YACtD,MAAM,MAAM,GAAmB,eAAe,IAAI,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;YACtF,sEAAsE;YACtE,kEAAkE;YAClE,qEAAqE;YACrE,IAAI,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;gBACvD,OAAO;YACT,CAAC;YACD,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACnC,IAAI,KAAK,EAAE,CAAC;gBACV,YAAY,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;YACD,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACtD,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC;gBAC5C,IAAI,EAAE,wBAAwB;gBAC9B,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC7B,SAAS;gBACT,MAAM;gBACN,MAAM;gBACN,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5B,CAAC,CAAC,CAAC;YACJ,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC/B,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAChE,CAAC,CAAC;QAEF,kEAAkE;QAClE,kEAAkE;QAClE,oEAAoE;QACpE,yEAAyE;QACzE,oEAAoE;QACpE,MAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzF,MAAM,kBAAkB,GAAG,0BAA0B,GAAG,CAAC;YACvD,CAAC,CAAC,0BAA0B,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpG,CAAC,CAAC,CAAC,CAAC;QACN,MAAM,SAAS,GAAG,kBAAkB,GAAG,CAAC;YACtC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,kBAAkB,CAAC,CAAC,WAAW,EAAE;YACzD,CAAC,CAAC,SAAS,CAAC;QAEd,gBAAgB,CAAC,GAAG,CAAC,SAAS,EAAE;YAC9B,MAAM;YACN,OAAO,EAAE;gBACP,SAAS;gBACT,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC7B,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gBACjC,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrC,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3C,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/E,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACtD,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3E,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3C,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACxD;SACF,CAAC,CAAC;QAEH,IAAI,0BAA0B,GAAG,CAAC,IAAI,kBAAkB,IAAI,CAAC,EAAE,CAAC;YAC9D,mEAAmE;YACnE,qEAAqE;YACrE,qDAAqD;YACrD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YAC1B,OAAO;QACT,CAAC;QAED,IAAI,kBAAkB,GAAG,CAAC,EAAE,CAAC;YAC3B,oEAAoE;YACpE,qEAAqE;YACrE,qEAAqE;YACrE,kEAAkE;YAClE,2DAA2D;YAC3D,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,kBAAkB,CAAC,CAAC;QAC1E,CAAC;QAED,uEAAuE;QACvE,qEAAqE;QACrE,sDAAsD;QACtD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,IAAI,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC3B,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;gBAC5B,OAAO;YACT,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,wEAAwE;QACxE,iEAAiE;QACjE,iEAAiE;QACjE,8DAA8D;QAC9D,IAAI,aAAa,GAAG,GAAS,EAAE,GAAE,CAAC,CAAC;QACnC,SAAS,GAAG,IAAI,OAAO,CAAO,CAAC,gBAAgB,EAAE,EAAE;YACjD,aAAa,GAAG,gBAAgB,CAAC;QACnC,CAAC,CAAC,CAAC;QACH,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC;YAC1B,IAAI,EAAE,yBAAyB;YAC/B,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;YAC7B,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACjC,SAAS;YACT,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrC,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/E,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3E,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvD,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpC,CAAC,CAAC;QACH,wEAAwE;QACxE,sEAAsE;QACtE,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAClC,KAAK,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE;YAC3B,iBAAiB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACrC,aAAa,EAAE,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,CAAC,KAA2B,EAAW,EAAE;QAC/D,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF;;;;;;;;OAQG;IACH,MAAM,eAAe,GAAG,IAAI,GAAG,EAAsB,CAAC;IAEtD;;;;;;;;;;;;;;OAcG;IACH,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEhD,MAAM,gBAAgB,GAAG,CAAC,SAAiB,EAAgB,EAAE;QAC3D,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtE,mEAAmE;QACnE,sBAAsB;QACtB,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;QACnC,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,OAAO,GAAG,EAAE;YACV,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO;YACT,CAAC;YACD,QAAQ,GAAG,IAAI,CAAC;YAChB,MAAM,SAAS,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAC1D,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;gBAClB,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACN,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAClC,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO;QACL,gBAAgB;QAChB,iBAAiB;QACjB,eAAe;QACf,aAAa;QACb,QAAQ;QACR,cAAc;QACd,eAAe;QACf,eAAe;QACf,eAAe;QACf,aAAa;QACb,gBAAgB;KACjB,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type AgentRegistry, type EventBus, type ToolRegistry, type UnlistedTools } from '@stratusagent/core';
|
|
2
|
+
import type { AgentSource } from './agent-source.ts';
|
|
3
|
+
import type { GatewayChannelAdapter, ProvideCredentialInput, ProvideCredentialResult } from './types.ts';
|
|
4
|
+
import { type StateEnvironment } from '@stratusagent/state';
|
|
5
|
+
/** What credential requests close over in `createGateway`. */
|
|
6
|
+
export interface CredentialRequestsDeps {
|
|
7
|
+
env: StateEnvironment;
|
|
8
|
+
warn: (line: string) => void;
|
|
9
|
+
bus: EventBus;
|
|
10
|
+
startedChannels: GatewayChannelAdapter[];
|
|
11
|
+
channelCarrying: (kind: string, agentId: string, capable: (candidate: GatewayChannelAdapter) => boolean) => {
|
|
12
|
+
adapter?: GatewayChannelAdapter;
|
|
13
|
+
carriesOthers: boolean;
|
|
14
|
+
};
|
|
15
|
+
registry: AgentRegistry;
|
|
16
|
+
sources: Map<string, AgentSource>;
|
|
17
|
+
unlistedTools: () => UnlistedTools;
|
|
18
|
+
tools: ToolRegistry;
|
|
19
|
+
}
|
|
20
|
+
export declare const createCredentialRequests: ({ env, warn, bus, startedChannels, channelCarrying, registry, sources, unlistedTools, tools, }: CredentialRequestsDeps) => {
|
|
21
|
+
provideCredential: (input: ProvideCredentialInput) => Promise<ProvideCredentialResult>;
|
|
22
|
+
};
|
|
23
|
+
export type CredentialRequests = ReturnType<typeof createCredentialRequests>;
|
|
24
|
+
//# sourceMappingURL=credential-requests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-requests.d.ts","sourceRoot":"","sources":["../src/credential-requests.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,KAAK,aAAa,EAGlB,KAAK,QAAQ,EAEb,KAAK,YAAY,EACjB,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAM5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACzG,OAAO,EAWL,KAAK,gBAAgB,EAEtB,MAAM,qBAAqB,CAAC;AAuB7B,8DAA8D;AAC9D,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,gBAAgB,CAAC;IACtB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,GAAG,EAAE,QAAQ,CAAC;IACd,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,eAAe,EAAE,CACf,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,SAAS,EAAE,qBAAqB,KAAK,OAAO,KACnD;QAAE,OAAO,CAAC,EAAE,qBAAqB,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAE,CAAC;IACjE,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClC,aAAa,EAAE,MAAM,aAAa,CAAC;IACnC,KAAK,EAAE,YAAY,CAAC;CACrB;AAED,eAAO,MAAM,wBAAwB,GAAI,gGAUtC,sBAAsB;+BAmPiB,sBAAsB,KAAG,OAAO,CAAC,uBAAuB,CAAC;CAiNlG,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
|