agentfootprint 7.18.0 → 7.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/hosting/agentcore.js +23 -9
- package/dist/adapters/hosting/agentcore.js.map +1 -1
- package/dist/core/Agent.js +6 -0
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/stages/toolCalls.js +13 -0
- package/dist/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/core/durabilityBarrier.js +68 -0
- package/dist/core/durabilityBarrier.js.map +1 -0
- package/dist/esm/adapters/hosting/agentcore.d.ts +4 -4
- package/dist/esm/adapters/hosting/agentcore.js +24 -10
- package/dist/esm/adapters/hosting/agentcore.js.map +1 -1
- package/dist/esm/core/Agent.js +6 -0
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/stages/toolCalls.d.ts +21 -0
- package/dist/esm/core/agent/stages/toolCalls.js +13 -0
- package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/esm/core/durabilityBarrier.d.ts +61 -0
- package/dist/esm/core/durabilityBarrier.js +63 -0
- package/dist/esm/core/durabilityBarrier.js.map +1 -0
- package/dist/esm/hosting/durability.d.ts +92 -0
- package/dist/esm/hosting/durability.js +174 -0
- package/dist/esm/hosting/durability.js.map +1 -0
- package/dist/esm/hosting/envelope.d.ts +75 -14
- package/dist/esm/hosting/envelope.js +141 -16
- package/dist/esm/hosting/envelope.js.map +1 -1
- package/dist/esm/hosting/errors.d.ts +60 -11
- package/dist/esm/hosting/errors.js +92 -18
- package/dist/esm/hosting/errors.js.map +1 -1
- package/dist/esm/hosting/httpHost.d.ts +17 -1
- package/dist/esm/hosting/httpHost.js +42 -6
- package/dist/esm/hosting/httpHost.js.map +1 -1
- package/dist/esm/hosting/index.d.ts +7 -4
- package/dist/esm/hosting/index.js +6 -3
- package/dist/esm/hosting/index.js.map +1 -1
- package/dist/esm/hosting/nodeHost.d.ts +4 -2
- package/dist/esm/hosting/nodeHost.js +14 -3
- package/dist/esm/hosting/nodeHost.js.map +1 -1
- package/dist/esm/hosting/standingAgent.d.ts +22 -7
- package/dist/esm/hosting/standingAgent.js +144 -32
- package/dist/esm/hosting/standingAgent.js.map +1 -1
- package/dist/esm/hosting/types.d.ts +193 -19
- package/dist/hosting/durability.js +178 -0
- package/dist/hosting/durability.js.map +1 -0
- package/dist/hosting/envelope.js +146 -18
- package/dist/hosting/envelope.js.map +1 -1
- package/dist/hosting/errors.js +95 -19
- package/dist/hosting/errors.js.map +1 -1
- package/dist/hosting/httpHost.js +42 -6
- package/dist/hosting/httpHost.js.map +1 -1
- package/dist/hosting/index.js +10 -2
- package/dist/hosting/index.js.map +1 -1
- package/dist/hosting/nodeHost.js +14 -3
- package/dist/hosting/nodeHost.js.map +1 -1
- package/dist/hosting/standingAgent.js +142 -30
- package/dist/hosting/standingAgent.js.map +1 -1
- package/dist/types/adapters/hosting/agentcore.d.ts +4 -4
- package/dist/types/adapters/hosting/agentcore.d.ts.map +1 -1
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/stages/toolCalls.d.ts +21 -0
- package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
- package/dist/types/core/durabilityBarrier.d.ts +62 -0
- package/dist/types/core/durabilityBarrier.d.ts.map +1 -0
- package/dist/types/hosting/durability.d.ts +93 -0
- package/dist/types/hosting/durability.d.ts.map +1 -0
- package/dist/types/hosting/envelope.d.ts +75 -14
- package/dist/types/hosting/envelope.d.ts.map +1 -1
- package/dist/types/hosting/errors.d.ts +60 -11
- package/dist/types/hosting/errors.d.ts.map +1 -1
- package/dist/types/hosting/httpHost.d.ts +17 -1
- package/dist/types/hosting/httpHost.d.ts.map +1 -1
- package/dist/types/hosting/index.d.ts +7 -4
- package/dist/types/hosting/index.d.ts.map +1 -1
- package/dist/types/hosting/nodeHost.d.ts +4 -2
- package/dist/types/hosting/nodeHost.d.ts.map +1 -1
- package/dist/types/hosting/standingAgent.d.ts +22 -7
- package/dist/types/hosting/standingAgent.d.ts.map +1 -1
- package/dist/types/hosting/types.d.ts +193 -19
- package/dist/types/hosting/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -3,12 +3,16 @@
|
|
|
3
3
|
* same words.
|
|
4
4
|
*
|
|
5
5
|
* A refusal that varies by adapter is a refusal nobody can write a test or a
|
|
6
|
-
* runbook against. These
|
|
6
|
+
* runbook against. These five carry a stable `code`, name WHO refused, and say
|
|
7
7
|
* what the caller should do instead. Adapters map the codes onto whatever their
|
|
8
8
|
* transport uses to say "no" — that mapping is the adapter's business and lives
|
|
9
9
|
* in the adapter, never here.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* Note what is NOT here: a run that paused. That is unfinished work rather than
|
|
12
|
+
* a refusal, and it leaves through `reply.awaiting(...)` — its own terminal —
|
|
13
|
+
* not through an error dressed up as one.
|
|
14
|
+
*
|
|
15
|
+
* `requireCapability` is the last refusal and the only one that is a
|
|
12
16
|
* programming mistake rather than a runtime condition, so it throws a plain
|
|
13
17
|
* `Error`: nothing branches on "I forgot to feature-detect", it just needs to
|
|
14
18
|
* say so loudly and name the adapter it is talking about.
|
|
@@ -60,37 +64,107 @@ export class ConcurrentRunError extends Error {
|
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
66
|
/**
|
|
63
|
-
* Raised when a run paused to ask a person something and
|
|
64
|
-
*
|
|
67
|
+
* Raised when a run paused to ask a person something and there is **nowhere to
|
|
68
|
+
* keep it**.
|
|
65
69
|
*
|
|
66
70
|
* **The run did not fail.** A pause is unfinished work: the agent stopped to ask
|
|
67
|
-
* and is waiting for an answer.
|
|
68
|
-
* `'
|
|
69
|
-
*
|
|
70
|
-
* session
|
|
71
|
+
* and is waiting for an answer. Since 7.19 a paused run is stored as
|
|
72
|
+
* `'flowchart-v1'` and continued by a later request carrying a decision — so the
|
|
73
|
+
* one case left where a pause genuinely cannot be carried is a request with no
|
|
74
|
+
* session id. There is no session to store it under, and therefore no later
|
|
75
|
+
* request that could ever answer it.
|
|
76
|
+
*
|
|
77
|
+
* The other half of the old meaning — "the reply cannot carry a pause" — is
|
|
78
|
+
* gone: {@link HostReply.awaiting} carries it now. An adapter that has not
|
|
79
|
+
* implemented that terminal still gets its pause STORED (the store is not the
|
|
80
|
+
* transport's business) and this refusal on the wire, naming the session it can
|
|
81
|
+
* be answered on.
|
|
71
82
|
*/
|
|
72
83
|
export class PauseNotCarriedError extends Error {
|
|
73
84
|
code = 'ERR_PAUSE_NOT_CARRIED';
|
|
74
85
|
/** The tool that asked, when the run recorded which one it was. */
|
|
75
86
|
toolName;
|
|
76
|
-
/** The session
|
|
87
|
+
/** The session the paused run was stored under, when there was one. */
|
|
77
88
|
sessionId;
|
|
78
|
-
|
|
89
|
+
/** Whether the paused run was stored. `false` means it is gone. */
|
|
90
|
+
stored;
|
|
91
|
+
constructor(toolName, sessionId, stored = false) {
|
|
79
92
|
super(`[hosting] the run paused to ask a person about ` +
|
|
80
93
|
(toolName ? `'${toolName}'` : 'a tool') +
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
94
|
+
`. The run did not fail — it is unfinished, waiting on an answer. ` +
|
|
95
|
+
(stored
|
|
96
|
+
? `It IS stored: send another request for session '${String(sessionId)}' carrying ` +
|
|
97
|
+
`a 'decision' to continue it. This reply could not describe the question ` +
|
|
98
|
+
`because the host it arrived on does not implement reply.awaiting(); read the ` +
|
|
99
|
+
`pending ask from the session store, or serve on a host that has it.`
|
|
100
|
+
: `Nothing was written: ` +
|
|
101
|
+
(sessionId === undefined
|
|
102
|
+
? `this request carried no session id, so there is nowhere to store a paused ` +
|
|
103
|
+
`run and no later request that could ever answer it. Send a sessionId, or `
|
|
104
|
+
: `session '${sessionId}' still holds what it held before this request. `) +
|
|
105
|
+
`carry the pause yourself with agent.run() / agent.resume().`));
|
|
89
106
|
this.name = 'PauseNotCarriedError';
|
|
90
107
|
if (toolName !== undefined)
|
|
91
108
|
this.toolName = toolName;
|
|
92
109
|
if (sessionId !== undefined)
|
|
93
110
|
this.sessionId = sessionId;
|
|
111
|
+
this.stored = stored;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Thrown when a new message arrives for a session whose run is waiting on a
|
|
116
|
+
* person's decision.
|
|
117
|
+
*
|
|
118
|
+
* The message is NOT run and the pause is NOT discarded — those are the two ways
|
|
119
|
+
* this could have gone wrong. Answering the message would step over an
|
|
120
|
+
* outstanding consent gate; dropping the paused run to make room for the message
|
|
121
|
+
* would throw away work a person was asked about. So the request is refused, the
|
|
122
|
+
* pending question is named, and the session sits exactly where it was.
|
|
123
|
+
*
|
|
124
|
+
* Answer it by sending the same session a request carrying
|
|
125
|
+
* {@link HostRequest.decision}.
|
|
126
|
+
*/
|
|
127
|
+
export class AwaitingDecisionError extends Error {
|
|
128
|
+
code = 'ERR_AWAITING_DECISION';
|
|
129
|
+
/** The session that is waiting. */
|
|
130
|
+
sessionId;
|
|
131
|
+
/** What it is waiting on — the same payload `reply.awaiting()` delivered. */
|
|
132
|
+
pending;
|
|
133
|
+
constructor(sessionId, pending) {
|
|
134
|
+
const asked = pending.question ?? pending.ask?.question ?? pending.checkIn?.evidence.willDo ?? 'a decision';
|
|
135
|
+
super(`[hosting] session '${sessionId}' is waiting on a person: ` +
|
|
136
|
+
(pending.tool ? `'${pending.tool}' asked "${asked}"` : `"${asked}"`) +
|
|
137
|
+
`. This message was NOT run and the paused run was NOT discarded — answering a ` +
|
|
138
|
+
`new message would step over the question, and dropping the question to answer ` +
|
|
139
|
+
`the message would throw away work somebody was asked to approve. ` +
|
|
140
|
+
`Send this session a request carrying 'decision' (checkInApproved(...) / ` +
|
|
141
|
+
`checkInDeclined(...) for a check-in or a middleware ask) to continue the run.`);
|
|
142
|
+
this.name = 'AwaitingDecisionError';
|
|
143
|
+
this.sessionId = sessionId;
|
|
144
|
+
this.pending = pending;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Thrown when a request carries a decision for a session that is not waiting on
|
|
149
|
+
* one.
|
|
150
|
+
*
|
|
151
|
+
* Usually a duplicate delivery: the run was already continued, or already
|
|
152
|
+
* answered, and the same decision arrived twice. Running it as an ordinary
|
|
153
|
+
* message would put a raw approval into the conversation as if the user had
|
|
154
|
+
* typed it, so it is refused by name instead.
|
|
155
|
+
*/
|
|
156
|
+
export class NoPendingAskError extends Error {
|
|
157
|
+
code = 'ERR_NO_PENDING_ASK';
|
|
158
|
+
/** The session the decision was addressed to. */
|
|
159
|
+
sessionId;
|
|
160
|
+
constructor(sessionId) {
|
|
161
|
+
super(`[hosting] this request carries a 'decision' but session '${sessionId}' is not ` +
|
|
162
|
+
`waiting on one — nothing is paused. The run it answered has most likely already ` +
|
|
163
|
+
`been continued (a duplicate delivery). Refusing rather than treating an approval ` +
|
|
164
|
+
`as if a person had typed it into the conversation. Send it as 'input' if that is ` +
|
|
165
|
+
`genuinely what you meant.`);
|
|
166
|
+
this.name = 'NoPendingAskError';
|
|
167
|
+
this.sessionId = sessionId;
|
|
94
168
|
}
|
|
95
169
|
}
|
|
96
170
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/hosting/errors.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/hosting/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* Pattern: Template method via configuration (Strategy on the wire format).
|
|
29
29
|
* Everything HTTP lives here and in the wires; `types.ts` knows none of it.
|
|
30
30
|
*/
|
|
31
|
-
import type { AgentHost, HostCapability, HostHandle, HostHandler } from './types.js';
|
|
31
|
+
import type { AgentHost, HostCapability, HostHandle, HostHandler, PendingAsk } from './types.js';
|
|
32
32
|
/** Everything a {@link HttpWire} may read when pulling a request apart. */
|
|
33
33
|
export interface HttpRequestFacts {
|
|
34
34
|
/** The parsed JSON body, or `{}` for an empty one. */
|
|
@@ -57,6 +57,12 @@ export interface HttpWire {
|
|
|
57
57
|
readRequest(facts: HttpRequestFacts): {
|
|
58
58
|
readonly input: string;
|
|
59
59
|
readonly sessionId?: string;
|
|
60
|
+
/**
|
|
61
|
+
* A person's answer to an outstanding question, when this request carries
|
|
62
|
+
* one. Its presence is what makes a request a RESUME rather than a new
|
|
63
|
+
* message, so a wire that never returns it can only ever start new turns.
|
|
64
|
+
*/
|
|
65
|
+
readonly decision?: unknown;
|
|
60
66
|
};
|
|
61
67
|
/** Body for a health probe. `uptimeMs` is how long this host has been serving. */
|
|
62
68
|
health(uptimeMs: number): unknown;
|
|
@@ -66,6 +72,16 @@ export interface HttpWire {
|
|
|
66
72
|
failure(message: string, code?: string): unknown;
|
|
67
73
|
/** Body for one streamed piece, when the caller asked for Server-Sent Events. */
|
|
68
74
|
chunk(text: string): unknown;
|
|
75
|
+
/**
|
|
76
|
+
* Body for a reply that is WAITING on a person — the run paused, it is stored,
|
|
77
|
+
* and a later request carrying a decision continues it.
|
|
78
|
+
*
|
|
79
|
+
* Optional so a wire written before this terminal existed keeps compiling and
|
|
80
|
+
* keeps working. A host whose wire has no `awaiting` cannot describe the
|
|
81
|
+
* question, so it reports the named refusal instead — the run is still stored
|
|
82
|
+
* either way.
|
|
83
|
+
*/
|
|
84
|
+
awaiting?(pending: PendingAsk): unknown;
|
|
69
85
|
}
|
|
70
86
|
/** Options for {@link httpHost}. */
|
|
71
87
|
export interface HttpHostOptions {
|
|
@@ -33,17 +33,27 @@ import { HostClosedError } from './errors.js';
|
|
|
33
33
|
/**
|
|
34
34
|
* Status codes mapped by refusal code. Anything else is a 500.
|
|
35
35
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* every dashboard that ever sees it.
|
|
36
|
+
* Not one of them is a 5xx: none of them is the agent breaking. A closed host is
|
|
37
|
+
* shutting down (503); the other four are conflicts with the state the session
|
|
38
|
+
* is already in (409) — a run already going, a question already outstanding, a
|
|
39
|
+
* decision with nothing to decide, a pause this reply cannot describe. A 500
|
|
40
|
+
* would tell every dashboard that ever sees it something untrue.
|
|
41
41
|
*/
|
|
42
42
|
const STATUS_BY_CODE = {
|
|
43
43
|
ERR_HOST_CLOSED: 503,
|
|
44
44
|
ERR_CONCURRENT_RUN: 409,
|
|
45
45
|
ERR_PAUSE_NOT_CARRIED: 409,
|
|
46
|
+
ERR_AWAITING_DECISION: 409,
|
|
47
|
+
ERR_NO_PENDING_ASK: 409,
|
|
46
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* What a run that stopped to ask a person answers with: **202 Accepted.**
|
|
51
|
+
*
|
|
52
|
+
* The request was understood and acted on, and the work is not finished — which
|
|
53
|
+
* is what 202 means and what nothing else in the 2xx range means. Not 200: there
|
|
54
|
+
* is no answer. Not 4xx or 5xx: nothing was refused and nothing broke.
|
|
55
|
+
*/
|
|
56
|
+
const AWAITING_STATUS = 202;
|
|
47
57
|
const DEFAULT_CAPABILITIES = ['streaming'];
|
|
48
58
|
/**
|
|
49
59
|
* An HTTP host for one handler, speaking the dialect you hand it.
|
|
@@ -126,7 +136,7 @@ async function serveOne(req, res, handler, wire) {
|
|
|
126
136
|
}
|
|
127
137
|
const headers = lowerCased(req.headers);
|
|
128
138
|
const query = new URLSearchParams((req.url ?? '').split('?')[1] ?? '');
|
|
129
|
-
const { input, sessionId } = wire.readRequest({ body, headers, query });
|
|
139
|
+
const { input, sessionId, decision } = wire.readRequest({ body, headers, query });
|
|
130
140
|
if (wantsStream) {
|
|
131
141
|
res.writeHead(200, {
|
|
132
142
|
'content-type': 'text/event-stream',
|
|
@@ -161,6 +171,31 @@ async function serveOne(req, res, handler, wire) {
|
|
|
161
171
|
sendJson(res, 200, wire.output(output));
|
|
162
172
|
}
|
|
163
173
|
},
|
|
174
|
+
awaiting(pending) {
|
|
175
|
+
if (settled)
|
|
176
|
+
return;
|
|
177
|
+
// A wire that cannot describe a question must not answer 202 with an
|
|
178
|
+
// empty body — that would look like a completed request. Fall through to
|
|
179
|
+
// the named refusal, which at least says what happened and where the
|
|
180
|
+
// paused run is.
|
|
181
|
+
if (!wire.awaiting) {
|
|
182
|
+
const refusal = new Error(`[hosting] the run is waiting on a person and this host's wire has no ` +
|
|
183
|
+
`awaiting() body shape, so the question cannot be described on the wire. ` +
|
|
184
|
+
`The paused run is stored; read the pending ask from the session store.`);
|
|
185
|
+
refusal.code = 'ERR_PAUSE_NOT_CARRIED';
|
|
186
|
+
reply.fail(refusal);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
settled = true;
|
|
190
|
+
const payload = wire.awaiting(pending);
|
|
191
|
+
if (wantsStream) {
|
|
192
|
+
res.write(encodeSSE('awaiting', payload));
|
|
193
|
+
res.end();
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
sendJson(res, AWAITING_STATUS, payload);
|
|
197
|
+
}
|
|
198
|
+
},
|
|
164
199
|
fail(error) {
|
|
165
200
|
if (settled)
|
|
166
201
|
return;
|
|
@@ -180,6 +215,7 @@ async function serveOne(req, res, handler, wire) {
|
|
|
180
215
|
await handler({
|
|
181
216
|
input,
|
|
182
217
|
...(sessionId !== undefined && { sessionId }),
|
|
218
|
+
...(decision !== undefined && { decision }),
|
|
183
219
|
headers,
|
|
184
220
|
signal: controller.signal,
|
|
185
221
|
}, reply);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpHost.js","sourceRoot":"","sources":["../../../src/hosting/httpHost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"httpHost.js","sourceRoot":"","sources":["../../../src/hosting/httpHost.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,9 +33,12 @@
|
|
|
33
33
|
* another. Two paths and five body shapes are all a second HTTP adapter
|
|
34
34
|
* re-decides.
|
|
35
35
|
* • `memorySessions()` — conversations in a Map, for tests and local dev.
|
|
36
|
-
* • `standingAgent({ agent, sessions, host })` — the composer.
|
|
36
|
+
* • `standingAgent({ agent, sessions, host, durability? })` — the composer.
|
|
37
37
|
* • `toEnvelope` / `readEnvelope` — pack a conversation, and refuse by name to
|
|
38
38
|
* unpack a format this runtime does not know.
|
|
39
|
+
* • `toPausedEnvelope` / `readPausedRun` — the same for a run that stopped to
|
|
40
|
+
* ask a person something (`'flowchart-v1'`). `checkEnvelope` validates
|
|
41
|
+
* either without committing to which half you wanted — what a STORE wants.
|
|
39
42
|
* • `requireCapability` — feature-detection with teeth.
|
|
40
43
|
*
|
|
41
44
|
* @example An agent that stays up and remembers
|
|
@@ -54,7 +57,7 @@ export type { NodeHost, NodeHostHandle, NodeHostOptions } from './nodeHost.js';
|
|
|
54
57
|
export { httpHost, headerValue } from './httpHost.js';
|
|
55
58
|
export type { HttpHost, HttpHostHandle, HttpHostOptions, HttpRequestFacts, HttpWire, } from './httpHost.js';
|
|
56
59
|
export { memorySessions } from './memorySessions.js';
|
|
57
|
-
export { toEnvelope, readEnvelope } from './envelope.js';
|
|
60
|
+
export { toEnvelope, toPausedEnvelope, readEnvelope, readPausedRun, checkEnvelope, } from './envelope.js';
|
|
58
61
|
export { standingAgent } from './standingAgent.js';
|
|
59
|
-
export { requireCapability, HostClosedError, ConcurrentRunError, PauseNotCarriedError, } from './errors.js';
|
|
60
|
-
export type { AgentHost, CheckpointEnvelope, ConcurrentInvokePolicy, HostCapability, HostHandle, HostHandler, HostReply, HostRequest, SessionLifecycle, StandingAgentOptions, WakeReason, } from './types.js';
|
|
62
|
+
export { requireCapability, HostClosedError, ConcurrentRunError, PauseNotCarriedError, AwaitingDecisionError, NoPendingAskError, } from './errors.js';
|
|
63
|
+
export type { AgentHost, CheckpointEnvelope, ConcurrentInvokePolicy, ConversationEnvelope, DurabilityMode, HostCapability, HostHandle, HostHandler, HostReply, HostRequest, PausedRun, PausedRunEnvelope, PendingAsk, SessionLifecycle, StandingAgentOptions, WakeReason, } from './types.js';
|
|
@@ -33,9 +33,12 @@
|
|
|
33
33
|
* another. Two paths and five body shapes are all a second HTTP adapter
|
|
34
34
|
* re-decides.
|
|
35
35
|
* • `memorySessions()` — conversations in a Map, for tests and local dev.
|
|
36
|
-
* • `standingAgent({ agent, sessions, host })` — the composer.
|
|
36
|
+
* • `standingAgent({ agent, sessions, host, durability? })` — the composer.
|
|
37
37
|
* • `toEnvelope` / `readEnvelope` — pack a conversation, and refuse by name to
|
|
38
38
|
* unpack a format this runtime does not know.
|
|
39
|
+
* • `toPausedEnvelope` / `readPausedRun` — the same for a run that stopped to
|
|
40
|
+
* ask a person something (`'flowchart-v1'`). `checkEnvelope` validates
|
|
41
|
+
* either without committing to which half you wanted — what a STORE wants.
|
|
39
42
|
* • `requireCapability` — feature-detection with teeth.
|
|
40
43
|
*
|
|
41
44
|
* @example An agent that stays up and remembers
|
|
@@ -52,7 +55,7 @@
|
|
|
52
55
|
export { nodeHost, jsonWire } from './nodeHost.js';
|
|
53
56
|
export { httpHost, headerValue } from './httpHost.js';
|
|
54
57
|
export { memorySessions } from './memorySessions.js';
|
|
55
|
-
export { toEnvelope, readEnvelope } from './envelope.js';
|
|
58
|
+
export { toEnvelope, toPausedEnvelope, readEnvelope, readPausedRun, checkEnvelope, } from './envelope.js';
|
|
56
59
|
export { standingAgent } from './standingAgent.js';
|
|
57
|
-
export { requireCapability, HostClosedError, ConcurrentRunError, PauseNotCarriedError, } from './errors.js';
|
|
60
|
+
export { requireCapability, HostClosedError, ConcurrentRunError, PauseNotCarriedError, AwaitingDecisionError, NoPendingAskError, } from './errors.js';
|
|
58
61
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/hosting/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/hosting/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAEH,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGnD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAStD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,aAAa,CAAC"}
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
* reply.complete(await answer(request.input));
|
|
8
8
|
* });
|
|
9
9
|
*
|
|
10
|
-
* Two routes: `POST /invoke` takes `{ input, sessionId? }` and
|
|
11
|
-
* `{ output }
|
|
10
|
+
* Two routes: `POST /invoke` takes `{ input, sessionId?, decision? }` and
|
|
11
|
+
* answers `{ output }` — or `{ awaiting }` with a **202** when the run stopped
|
|
12
|
+
* to ask a person something, which a later `POST` carrying `decision` continues;
|
|
13
|
+
* `GET /health` answers `{ status: 'ok' }`. Both paths are
|
|
12
14
|
* options, because the paths are the part most likely to be dictated to you by
|
|
13
15
|
* whatever is in front of the process — a load balancer, a container contract,
|
|
14
16
|
* a colleague's convention. A path is a deployment detail, so it is a knob
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
* reply.complete(await answer(request.input));
|
|
8
8
|
* });
|
|
9
9
|
*
|
|
10
|
-
* Two routes: `POST /invoke` takes `{ input, sessionId? }` and
|
|
11
|
-
* `{ output }
|
|
10
|
+
* Two routes: `POST /invoke` takes `{ input, sessionId?, decision? }` and
|
|
11
|
+
* answers `{ output }` — or `{ awaiting }` with a **202** when the run stopped
|
|
12
|
+
* to ask a person something, which a later `POST` carrying `decision` continues;
|
|
13
|
+
* `GET /health` answers `{ status: 'ok' }`. Both paths are
|
|
12
14
|
* options, because the paths are the part most likely to be dictated to you by
|
|
13
15
|
* whatever is in front of the process — a load balancer, a container contract,
|
|
14
16
|
* a colleague's convention. A path is a deployment detail, so it is a knob
|
|
@@ -44,12 +46,21 @@ export const jsonWire = {
|
|
|
44
46
|
// caller that sets both is not surprised by which one the server preferred.
|
|
45
47
|
const fromBody = typeof facts.body.sessionId === 'string' ? facts.body.sessionId : undefined;
|
|
46
48
|
const sessionId = fromBody ?? facts.headers['x-session-id'];
|
|
47
|
-
|
|
49
|
+
// Read as-is and never coerced: `decision` is a person's answer to whatever
|
|
50
|
+
// a tool asked, and this dialect does not get to decide what that looks
|
|
51
|
+
// like. Its PRESENCE is the whole signal.
|
|
52
|
+
const decision = facts.body.decision;
|
|
53
|
+
return {
|
|
54
|
+
input,
|
|
55
|
+
...(sessionId !== undefined && { sessionId }),
|
|
56
|
+
...(decision !== undefined && { decision }),
|
|
57
|
+
};
|
|
48
58
|
},
|
|
49
59
|
health: (uptimeMs) => ({ status: 'ok', uptimeMs }),
|
|
50
60
|
output: (output) => ({ output }),
|
|
51
61
|
failure: (error, code) => ({ error, ...(code !== undefined && { code }) }),
|
|
52
62
|
chunk: (text) => ({ text }),
|
|
63
|
+
awaiting: (pending) => ({ awaiting: pending }),
|
|
53
64
|
};
|
|
54
65
|
/**
|
|
55
66
|
* An HTTP host for one handler.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeHost.js","sourceRoot":"","sources":["../../../src/hosting/nodeHost.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"nodeHost.js","sourceRoot":"","sources":["../../../src/hosting/nodeHost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,QAAQ,EAAqD,MAAM,eAAe,CAAC;AAwB5F,MAAM,SAAS,GAAG,UAAU,CAAC;AAE7B;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAa;IAChC,WAAW,CAAC,KAAK;QACf,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,wEAAwE;QACxE,4EAA4E;QAC5E,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7F,MAAM,SAAS,GAAG,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAC5D,4EAA4E;QAC5E,wEAAwE;QACxE,0CAA0C;QAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;QACrC,OAAO;YACL,KAAK;YACL,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,CAAC;YAC7C,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,CAAC;SAC5C,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAClD,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAC1E,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;IAC3B,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;CAC/C,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,QAAQ,CAAC,UAA2B,EAAE;IACpD,OAAO,QAAQ,CAAC;QACd,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,QAAQ;QACd,yEAAyE;QACzE,wDAAwD;QACxD,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,SAAS;QAC3C,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,SAAS;QAC3C,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;QACzD,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;KACtE,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -5,17 +5,26 @@
|
|
|
5
5
|
* agent,
|
|
6
6
|
* sessions: memorySessions(),
|
|
7
7
|
* host: nodeHost({ port: 8080 }),
|
|
8
|
+
* durability: 'sync', // optional; 'exit' is the default
|
|
8
9
|
* });
|
|
9
10
|
*
|
|
10
11
|
* One request at a time it does four things: wake and hydrate the session,
|
|
11
|
-
*
|
|
12
|
+
* continue that session or start a fresh one, persist what the run leaves
|
|
12
13
|
* behind, then reply. Everything else is somebody else's job — the host carries
|
|
13
14
|
* bytes, the store keeps them, the agent thinks.
|
|
14
15
|
*
|
|
15
|
-
* ──
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* ── A run has three ends, and this composer honours all three ────────────────
|
|
17
|
+
* It answered, it asked a person something, or it failed. An answer completes
|
|
18
|
+
* the reply and stores a conversation. A QUESTION stores the paused run as
|
|
19
|
+
* `'flowchart-v1'` and leaves through `reply.awaiting(...)` — its own terminal,
|
|
20
|
+
* never `fail`, because a pause is unfinished work and reporting it as a failure
|
|
21
|
+
* tells every dashboard downstream something untrue. A later request for that
|
|
22
|
+
* session carrying `decision` continues the run from exactly where it stopped.
|
|
23
|
+
*
|
|
24
|
+
* ── Resuming a CONVERSATION is a REPLAY, and that has a cost ─────────────────
|
|
25
|
+
* A stored conversation is restored through `agent.resumeOnError(...)`, and this
|
|
26
|
+
* is its caveat, stated here in the words the Agent states it in, because a
|
|
27
|
+
* composition that hides the caveat of the thing it composes is worse than no
|
|
19
28
|
* composition at all:
|
|
20
29
|
*
|
|
21
30
|
* > **Tool re-execution / idempotency**: tool side effects from the FAILED
|
|
@@ -25,6 +34,10 @@
|
|
|
25
34
|
* > emails, DB writes) must be idempotent — key on stable call content, not
|
|
26
35
|
* > `ctx.toolCallId` (a re-issued call gets a new id).
|
|
27
36
|
*
|
|
37
|
+
* `durability` is the dial that bounds how much of that a crash can cost you.
|
|
38
|
+
* Resuming a PAUSED run is different in kind: it is not a replay at all — the
|
|
39
|
+
* engine continues from its own checkpoint, and no earlier tool call re-runs.
|
|
40
|
+
*
|
|
28
41
|
* ── Why one run at a time ───────────────────────────────────────────────────
|
|
29
42
|
* An Agent instance holds per-run state on itself, and this composer shares ONE
|
|
30
43
|
* instance across every session. Two runs overlapping on it do not crash —
|
|
@@ -47,8 +60,9 @@ import type { HostHandle, StandingAgentOptions } from './types.js';
|
|
|
47
60
|
* Serve one agent, with per-session conversation memory, on any
|
|
48
61
|
* {@link AgentHost}.
|
|
49
62
|
*
|
|
50
|
-
* Resolves once the host is live. Closing the returned handle closes the host
|
|
51
|
-
*
|
|
63
|
+
* Resolves once the host is live. Closing the returned handle closes the host,
|
|
64
|
+
* detaches the listeners this composer added to the agent, and removes its
|
|
65
|
+
* durability wiring.
|
|
52
66
|
*
|
|
53
67
|
* @example
|
|
54
68
|
* const handle = await standingAgent({
|
|
@@ -56,6 +70,7 @@ import type { HostHandle, StandingAgentOptions } from './types.js';
|
|
|
56
70
|
* sessions: memorySessions(),
|
|
57
71
|
* host: nodeHost({ port: 0 }),
|
|
58
72
|
* onConcurrentInvoke: 'enqueue',
|
|
73
|
+
* durability: 'sync',
|
|
59
74
|
* });
|
|
60
75
|
* process.on('SIGTERM', () => void handle.close());
|
|
61
76
|
*/
|