stitchkit 0.103.0 → 0.103.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/dist/agent-runtime/browser-control-contract.d.ts +1118 -0
- package/dist/agent-runtime/browser-control-contract.d.ts.map +1 -0
- package/dist/agent-runtime/browser-controller.d.ts +31 -0
- package/dist/agent-runtime/browser-controller.d.ts.map +1 -0
- package/dist/agent-runtime/harness-control.d.ts.map +1 -1
- package/dist/agent-runtime/harness-realtime.d.ts +25 -0
- package/dist/agent-runtime/harness-realtime.d.ts.map +1 -0
- package/dist/agent-runtime/harness-tools.d.ts +11 -0
- package/dist/agent-runtime/harness-tools.d.ts.map +1 -0
- package/dist/agent-runtime/react.d.ts +4 -0
- package/dist/agent-runtime/react.d.ts.map +1 -0
- package/dist/agent-runtime/run-assertions.d.ts +63 -0
- package/dist/agent-runtime/run-assertions.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime/browser.d.ts +2 -0
- package/dist/entrypoints/agent-runtime/browser.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/browser.js +235 -0
- package/dist/entrypoints/agent-runtime/coding-tools.js +3 -3
- package/dist/entrypoints/agent-runtime/harness-tools.d.ts +2 -0
- package/dist/entrypoints/agent-runtime/harness-tools.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime/harness-tools.js +32 -0
- package/dist/entrypoints/agent-runtime/harness.js +13 -228
- package/dist/entrypoints/agent-runtime/react.d.ts +2 -0
- package/dist/entrypoints/agent-runtime/react.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime/react.js +8 -0
- package/dist/entrypoints/agent-runtime/realtime.d.ts +2 -0
- package/dist/entrypoints/agent-runtime/realtime.d.ts.map +1 -0
- package/dist/entrypoints/agent-runtime/realtime.js +159 -0
- package/dist/entrypoints/agent-runtime/sandbox.js +3 -3
- package/dist/entrypoints/agent-runtime/testing.d.ts +1 -0
- package/dist/entrypoints/agent-runtime/testing.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/testing.js +67 -2
- package/dist/entrypoints/agent-runtime.js +25 -20
- package/dist/entrypoints/cli.js +8 -8
- package/dist/entrypoints/index.js +15 -226
- package/dist/entrypoints/node.js +7 -5
- package/dist/entrypoints/observability.js +2 -2
- package/dist/entrypoints/react.js +2 -2
- package/dist/entrypoints/remote.js +3 -3
- package/dist/entrypoints/server.js +10 -8
- package/dist/entrypoints/testing.js +4 -4
- package/dist/entrypoints/tools/connections.js +2 -2
- package/dist/entrypoints/tools/invoker.js +6 -6
- package/dist/entrypoints/tools.js +25 -36
- package/dist/entrypoints/tracking.js +2 -2
- package/dist/{index-d82d3xg4.js → index-0c419yx7.js} +1 -1
- package/dist/{index-c6aagrbd.js → index-1br6gwhf.js} +4 -4
- package/dist/{index-xkhk5d6g.js → index-1khy8y7n.js} +5 -48
- package/dist/index-20yvtn9a.js +38 -0
- package/dist/{index-a9pd417t.js → index-5vyd0fkb.js} +1 -34
- package/dist/{index-r1z0rd9c.js → index-7n68nmc6.js} +1 -1
- package/dist/{index-zs4ms3th.js → index-90ppdx3q.js} +7 -30
- package/dist/{index-djjhhgjk.js → index-a4ajxwmb.js} +1 -1
- package/dist/index-c9d05kvt.js +11 -0
- package/dist/{index-ewbaywk5.js → index-dnn9z96q.js} +3 -3
- package/dist/index-jn9g8xdt.js +246 -0
- package/dist/index-kmpzj1cq.js +48 -0
- package/dist/{index-dvwj1f43.js → index-m2xqkv55.js} +2 -2
- package/dist/{index-m9fndta6.js → index-n2gre124.js} +3 -3
- package/dist/index-nggfa2yn.js +34 -0
- package/dist/{index-m79yr938.js → index-pw99k9h5.js} +1 -10
- package/dist/index-qapzv4p5.js +54 -0
- package/dist/index-r34mvse1.js +225 -0
- package/dist/{index-n9tyz8z3.js → index-r956rndn.js} +2 -2
- package/dist/index-srs8hj9c.js +10 -0
- package/dist/{index-jzczzcsb.js → index-tgzhq07n.js} +1 -1
- package/dist/index-vgkbcnkc.js +29 -0
- package/dist/{index-7z9ym7t8.js → index-x87j7csh.js} +35 -14
- package/dist/{index-3ct7hhq6.js → index-xwq9j1sf.js} +6 -56
- package/dist/{index-hby4qhax.js → index-yex7eg1v.js} +4 -10
- package/dist/{index-1h6gtdrj.js → index-ygkka6zn.js} +1 -1
- package/dist/index-ze1eph1k.js +20 -0
- package/dist/tools/schema/flatten-join.d.ts +1 -1
- package/dist/tools/schema/flatten-join.d.ts.map +1 -1
- package/dist/tools/schema/flatten.d.ts.map +1 -1
- package/llms/agent-runtime-browser.txt +26 -0
- package/llms/agent-runtime-harness-tools.txt +25 -0
- package/llms/agent-runtime-harness.txt +140 -1
- package/llms/agent-runtime-react.txt +21 -0
- package/llms/agent-runtime-realtime.txt +30 -0
- package/llms/agent-runtime-testing.txt +6 -0
- package/llms/stitchkit.txt +5 -1
- package/llms/tools.3.txt +1 -1
- package/llms/tools.txt +19 -1
- package/llms-full.txt +229 -3
- package/llms.txt +9 -5
- package/package.json +13 -1
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentControlRequestSchema2,
|
|
3
|
+
AgentControlResponseSchema2
|
|
4
|
+
} from "./index-n5yqxd3d.js";
|
|
5
|
+
import {
|
|
6
|
+
createAgentRuntimeEventSink2
|
|
7
|
+
} from "./index-vgkbcnkc.js";
|
|
8
|
+
|
|
9
|
+
// src/agent-runtime/harness-control.ts
|
|
10
|
+
async function runControlledOperation(harness, request) {
|
|
11
|
+
if (request.operation === "interrupt") {
|
|
12
|
+
await harness.interrupt({
|
|
13
|
+
conversationId: request.conversationId,
|
|
14
|
+
runId: request.runId
|
|
15
|
+
});
|
|
16
|
+
return AgentControlResponseSchema2.parse({
|
|
17
|
+
schemaVersion: 1,
|
|
18
|
+
requestId: request.requestId,
|
|
19
|
+
outcome: "ok",
|
|
20
|
+
snapshot: await harness.snapshot(request.conversationId)
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
if (request.operation === "respond-approval") {
|
|
24
|
+
const ticket = await harness.respondToApproval({
|
|
25
|
+
conversationId: request.conversationId,
|
|
26
|
+
approvalId: request.approvalId,
|
|
27
|
+
approved: request.approved,
|
|
28
|
+
...request.reason && { reason: request.reason },
|
|
29
|
+
context: request.context,
|
|
30
|
+
...request.metadata !== undefined && { metadata: request.metadata }
|
|
31
|
+
});
|
|
32
|
+
const admission = await ticket.admission;
|
|
33
|
+
return AgentControlResponseSchema2.parse({
|
|
34
|
+
schemaVersion: 1,
|
|
35
|
+
requestId: request.requestId,
|
|
36
|
+
outcome: "ok",
|
|
37
|
+
runId: admission.runId,
|
|
38
|
+
snapshot: await harness.snapshot(request.conversationId)
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
const ticket = harness.submit({
|
|
42
|
+
conversationId: request.conversationId,
|
|
43
|
+
idempotencyKey: request.idempotencyKey,
|
|
44
|
+
context: request.context,
|
|
45
|
+
parts: request.parts,
|
|
46
|
+
...request.metadata !== undefined && { metadata: request.metadata }
|
|
47
|
+
});
|
|
48
|
+
const admission = await ticket.admission;
|
|
49
|
+
return AgentControlResponseSchema2.parse({
|
|
50
|
+
schemaVersion: 1,
|
|
51
|
+
requestId: request.requestId,
|
|
52
|
+
outcome: "ok",
|
|
53
|
+
runId: admission.runId,
|
|
54
|
+
snapshot: await harness.snapshot(request.conversationId)
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function controlFailure(requestId, code, message) {
|
|
58
|
+
return AgentControlResponseSchema2.parse({
|
|
59
|
+
schemaVersion: 1,
|
|
60
|
+
requestId,
|
|
61
|
+
outcome: "error",
|
|
62
|
+
error: { code, message }
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function attachmentLimit(config) {
|
|
66
|
+
const limit = config.maxPendingAttachments ?? 32;
|
|
67
|
+
if (!Number.isSafeInteger(limit) || limit <= 0)
|
|
68
|
+
throw new TypeError("maxPendingAttachments must be a positive safe integer");
|
|
69
|
+
return limit;
|
|
70
|
+
}
|
|
71
|
+
function connectionState(config, {
|
|
72
|
+
deliver,
|
|
73
|
+
onOverflow
|
|
74
|
+
}, disconnect) {
|
|
75
|
+
const state = {
|
|
76
|
+
attached: new Map,
|
|
77
|
+
pendingAttachments: new Set,
|
|
78
|
+
cancelledAttachments: new Set,
|
|
79
|
+
overflowed: false,
|
|
80
|
+
sink: createAgentRuntimeEventSink2({
|
|
81
|
+
write: (event) => deliver({ schemaVersion: 1, type: "event", event }),
|
|
82
|
+
maxPending: config.maxPendingEvents ?? 128,
|
|
83
|
+
onDrop: ({ event }) => {
|
|
84
|
+
if (state.overflowed)
|
|
85
|
+
return;
|
|
86
|
+
state.overflowed = true;
|
|
87
|
+
onOverflow({
|
|
88
|
+
schemaVersion: 1,
|
|
89
|
+
type: "resync-required",
|
|
90
|
+
conversationId: event.conversationId,
|
|
91
|
+
reason: "overflow"
|
|
92
|
+
});
|
|
93
|
+
disconnect();
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
};
|
|
97
|
+
return state;
|
|
98
|
+
}
|
|
99
|
+
function createAgentHarnessControlServer2(harness, config = {}) {
|
|
100
|
+
const maxPendingAttachments = attachmentLimit(config);
|
|
101
|
+
const connections = new Map;
|
|
102
|
+
const controllers = new Map;
|
|
103
|
+
let pendingAttachments = 0;
|
|
104
|
+
let closed = false;
|
|
105
|
+
const unsubscribe = harness.subscribe((event) => {
|
|
106
|
+
for (const connection of connections.values()) {
|
|
107
|
+
if (connection.attached.has(event.conversationId) && !connection.overflowed) {
|
|
108
|
+
connection.sink.publish(event);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
const detach = (connectionId) => {
|
|
113
|
+
const connection = connections.get(connectionId);
|
|
114
|
+
if (!connection)
|
|
115
|
+
return;
|
|
116
|
+
for (const conversationId of connection.attached.keys()) {
|
|
117
|
+
if (controllers.get(conversationId) === connectionId) {
|
|
118
|
+
controllers.delete(conversationId);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
connection.sink.close();
|
|
122
|
+
connections.delete(connectionId);
|
|
123
|
+
};
|
|
124
|
+
return {
|
|
125
|
+
connect({ id, deliver, onOverflow }) {
|
|
126
|
+
if (closed)
|
|
127
|
+
throw new Error("Agent harness control server is closed");
|
|
128
|
+
if (connections.has(id))
|
|
129
|
+
throw new Error("Agent harness control connection id is duplicate");
|
|
130
|
+
const state = connectionState(config, { deliver, onOverflow }, () => detach(id));
|
|
131
|
+
connections.set(id, state);
|
|
132
|
+
return {
|
|
133
|
+
async request(raw) {
|
|
134
|
+
const request = AgentControlRequestSchema2.parse(raw);
|
|
135
|
+
const fail = (code, message) => controlFailure(request.requestId, code, message);
|
|
136
|
+
if (closed || connections.get(id) !== state)
|
|
137
|
+
return fail("CONNECTION_CLOSED", "Connection is closed");
|
|
138
|
+
try {
|
|
139
|
+
if (request.operation === "attach") {
|
|
140
|
+
if (state.pendingAttachments.has(request.conversationId)) {
|
|
141
|
+
return fail("ATTACH_IN_PROGRESS", "Wait for the current attachment request to settle");
|
|
142
|
+
}
|
|
143
|
+
if (pendingAttachments >= maxPendingAttachments) {
|
|
144
|
+
return fail("ATTACHMENT_CAPACITY", "Too many attachment snapshots are pending on this control server");
|
|
145
|
+
}
|
|
146
|
+
const owner = controllers.get(request.conversationId);
|
|
147
|
+
if (request.access === "control" && owner && owner !== id) {
|
|
148
|
+
return fail("LEASE_CONFLICT", "Conversation already has a controller");
|
|
149
|
+
}
|
|
150
|
+
const previousAccess = state.attached.get(request.conversationId);
|
|
151
|
+
const previousController = controllers.get(request.conversationId);
|
|
152
|
+
pendingAttachments += 1;
|
|
153
|
+
state.pendingAttachments.add(request.conversationId);
|
|
154
|
+
if (!previousAccess)
|
|
155
|
+
state.attached.set(request.conversationId, request.access);
|
|
156
|
+
if (request.access === "control")
|
|
157
|
+
controllers.set(request.conversationId, id);
|
|
158
|
+
let snapshot;
|
|
159
|
+
try {
|
|
160
|
+
snapshot = await harness.snapshot(request.conversationId);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
if (connections.get(id) === state && !state.cancelledAttachments.delete(request.conversationId)) {
|
|
163
|
+
if (previousAccess)
|
|
164
|
+
state.attached.set(request.conversationId, previousAccess);
|
|
165
|
+
else
|
|
166
|
+
state.attached.delete(request.conversationId);
|
|
167
|
+
if (request.access === "control" && controllers.get(request.conversationId) === id && previousController) {
|
|
168
|
+
controllers.set(request.conversationId, previousController);
|
|
169
|
+
} else if (request.access === "control" && controllers.get(request.conversationId) === id) {
|
|
170
|
+
controllers.delete(request.conversationId);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
throw error;
|
|
174
|
+
} finally {
|
|
175
|
+
pendingAttachments -= 1;
|
|
176
|
+
state.pendingAttachments.delete(request.conversationId);
|
|
177
|
+
}
|
|
178
|
+
if (closed || connections.get(id) !== state) {
|
|
179
|
+
return fail("CONNECTION_CLOSED", "Connection is closed");
|
|
180
|
+
}
|
|
181
|
+
if (state.cancelledAttachments.delete(request.conversationId)) {
|
|
182
|
+
return fail("ATTACH_CANCELLED", "Attachment was detached while its snapshot was pending");
|
|
183
|
+
}
|
|
184
|
+
state.attached.set(request.conversationId, request.access);
|
|
185
|
+
if (request.access === "observe" && controllers.get(request.conversationId) === id) {
|
|
186
|
+
controllers.delete(request.conversationId);
|
|
187
|
+
}
|
|
188
|
+
return AgentControlResponseSchema2.parse({
|
|
189
|
+
schemaVersion: 1,
|
|
190
|
+
requestId: request.requestId,
|
|
191
|
+
outcome: "ok",
|
|
192
|
+
snapshot
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
if (request.operation === "detach") {
|
|
196
|
+
if (state.pendingAttachments.has(request.conversationId)) {
|
|
197
|
+
state.cancelledAttachments.add(request.conversationId);
|
|
198
|
+
}
|
|
199
|
+
if (controllers.get(request.conversationId) === id)
|
|
200
|
+
controllers.delete(request.conversationId);
|
|
201
|
+
state.attached.delete(request.conversationId);
|
|
202
|
+
return AgentControlResponseSchema2.parse({
|
|
203
|
+
schemaVersion: 1,
|
|
204
|
+
requestId: request.requestId,
|
|
205
|
+
outcome: "ok"
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
if (state.pendingAttachments.has(request.conversationId)) {
|
|
209
|
+
return fail("ATTACH_IN_PROGRESS", "Wait for the current attachment request to settle");
|
|
210
|
+
}
|
|
211
|
+
if (!state.attached.has(request.conversationId))
|
|
212
|
+
return fail("NOT_ATTACHED", "Attach before requesting conversation state");
|
|
213
|
+
if (request.operation === "snapshot") {
|
|
214
|
+
const snapshot = await harness.snapshot(request.conversationId);
|
|
215
|
+
return AgentControlResponseSchema2.parse({
|
|
216
|
+
schemaVersion: 1,
|
|
217
|
+
requestId: request.requestId,
|
|
218
|
+
outcome: "ok",
|
|
219
|
+
snapshot
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
if (state.attached.get(request.conversationId) !== "control" || controllers.get(request.conversationId) !== id) {
|
|
223
|
+
return fail("LEASE_REQUIRED", "An active controller lease is required");
|
|
224
|
+
}
|
|
225
|
+
return await runControlledOperation(harness, request);
|
|
226
|
+
} catch {
|
|
227
|
+
return fail("REQUEST_REJECTED", "Control request was rejected");
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
close() {
|
|
231
|
+
detach(id);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
},
|
|
235
|
+
close() {
|
|
236
|
+
if (closed)
|
|
237
|
+
return;
|
|
238
|
+
closed = true;
|
|
239
|
+
unsubscribe();
|
|
240
|
+
for (const id of [...connections.keys()])
|
|
241
|
+
detach(id);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export { createAgentHarnessControlServer2 };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
collectToolSurface
|
|
3
|
+
} from "./index-dnn9z96q.js";
|
|
4
|
+
|
|
5
|
+
// src/tools/manifest.ts
|
|
6
|
+
function utf8Length(value) {
|
|
7
|
+
return new TextEncoder().encode(JSON.stringify(value)).byteLength;
|
|
8
|
+
}
|
|
9
|
+
function describeToolCatalog2(config) {
|
|
10
|
+
const deferred = new Set(config.deferredNames ?? []);
|
|
11
|
+
const entries = collectToolSurface({
|
|
12
|
+
surface: config,
|
|
13
|
+
transport: config.transport,
|
|
14
|
+
extend: config.extend,
|
|
15
|
+
flattenUnionInput: config.flattenUnionInput
|
|
16
|
+
}).map(({ kind, service, action, mountable }) => {
|
|
17
|
+
const schemaBytes = utf8Length(mountable.presentationSchema);
|
|
18
|
+
return {
|
|
19
|
+
name: mountable.name,
|
|
20
|
+
description: mountable.method.desc,
|
|
21
|
+
inputSchema: mountable.presentationSchema,
|
|
22
|
+
source: { kind, service, action },
|
|
23
|
+
schemaBytes,
|
|
24
|
+
deferred: deferred.has(mountable.name)
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
if (config.maxSchemaBytes !== undefined) {
|
|
28
|
+
const total = entries.reduce((sum, entry) => sum + entry.schemaBytes, 0);
|
|
29
|
+
if (total > config.maxSchemaBytes) {
|
|
30
|
+
throw new TypeError(`Tool catalog schemas use ${total} bytes, exceeding maxSchemaBytes ${config.maxSchemaBytes}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return entries;
|
|
34
|
+
}
|
|
35
|
+
function buildToolManifest2(config) {
|
|
36
|
+
return collectToolSurface({
|
|
37
|
+
surface: config,
|
|
38
|
+
transport: config.transport,
|
|
39
|
+
extend: config.extend,
|
|
40
|
+
flattenUnionInput: config.flattenUnionInput
|
|
41
|
+
}).map(({ mountable }) => ({
|
|
42
|
+
name: mountable.name,
|
|
43
|
+
description: mountable.method.desc,
|
|
44
|
+
inputSchema: mountable.presentationSchema
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { describeToolCatalog2, buildToolManifest2 };
|
|
@@ -15,11 +15,11 @@ import {
|
|
|
15
15
|
applyToolViewDefaults,
|
|
16
16
|
projectToolView,
|
|
17
17
|
objectShapeKeys
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-x87j7csh.js";
|
|
19
19
|
import {
|
|
20
20
|
runWithRequestContext2,
|
|
21
21
|
getRequestContext2
|
|
22
|
-
} from "./index-
|
|
22
|
+
} from "./index-7n68nmc6.js";
|
|
23
23
|
import {
|
|
24
24
|
formatZodError2
|
|
25
25
|
} from "./index-1eeqpadm.js";
|
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
} from "./index-n53mswt3.js";
|
|
4
4
|
import {
|
|
5
5
|
toolErrorFromResult
|
|
6
|
-
} from "./index-
|
|
6
|
+
} from "./index-m2xqkv55.js";
|
|
7
7
|
import {
|
|
8
8
|
assertUniqueToolName
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-x87j7csh.js";
|
|
10
10
|
import {
|
|
11
11
|
collectTools2,
|
|
12
12
|
createToolRunner
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-r956rndn.js";
|
|
14
14
|
|
|
15
15
|
// src/tools/invoker.ts
|
|
16
16
|
function createToolInvoker2(services, config) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// src/tools/agent-tool-error.ts
|
|
2
|
+
var AGENT_TOOL_ERROR_BRAND = Symbol.for("stitchkit.AgentToolError");
|
|
3
|
+
|
|
4
|
+
class AgentToolError2 extends Error {
|
|
5
|
+
output;
|
|
6
|
+
constructor(output, cause) {
|
|
7
|
+
let message = "Tool execution failed";
|
|
8
|
+
try {
|
|
9
|
+
message = JSON.stringify(output);
|
|
10
|
+
} catch {}
|
|
11
|
+
super(message, cause === undefined ? undefined : { cause });
|
|
12
|
+
this.name = "AgentToolError";
|
|
13
|
+
this.output = output;
|
|
14
|
+
Object.defineProperty(this, AGENT_TOOL_ERROR_BRAND, { value: true });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function isAgentToolError2(value) {
|
|
18
|
+
return typeof value === "object" && value !== null && AGENT_TOOL_ERROR_BRAND in value;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/tools/durability-context.ts
|
|
22
|
+
var contexts = new WeakMap;
|
|
23
|
+
function createToolDurabilityContext(factory) {
|
|
24
|
+
const context = {};
|
|
25
|
+
contexts.set(context, factory);
|
|
26
|
+
return context;
|
|
27
|
+
}
|
|
28
|
+
function resolveToolDurability(context, callId, signal) {
|
|
29
|
+
if (typeof context !== "object" || context === null)
|
|
30
|
+
return;
|
|
31
|
+
return contexts.get(context)?.(callId, signal);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { AgentToolError2, isAgentToolError2, createToolDurabilityContext, resolveToolDurability };
|
|
@@ -312,13 +312,4 @@ function createValidatedRealtimeSocket({
|
|
|
312
312
|
};
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
-
|
|
316
|
-
function isModuleNotFound(error) {
|
|
317
|
-
if (typeof error !== "object" || error === null)
|
|
318
|
-
return false;
|
|
319
|
-
const code = "code" in error ? error.code : undefined;
|
|
320
|
-
const message = "message" in error && typeof error.message === "string" ? error.message : "";
|
|
321
|
-
return code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND" || message.includes("Cannot find module") || message.includes("Cannot find package");
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
export { REALTIME_REJECTION_KEY2, asRealtimeRejection2, parseRealtimeRequestArguments, parseRealtimeRequestAcknowledgement, createValidatedRealtimeSocket, isModuleNotFound };
|
|
315
|
+
export { REALTIME_REJECTION_KEY2, asRealtimeRejection2, parseRealtimeRequestArguments, parseRealtimeRequestAcknowledgement, createValidatedRealtimeSocket };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createValidatedRealtimeSocket
|
|
3
|
+
} from "./index-pw99k9h5.js";
|
|
4
|
+
|
|
5
|
+
// src/server/realtime.ts
|
|
6
|
+
function bindRealtimeServer2(contract, handle, options = {}) {
|
|
7
|
+
const outbound = (target) => createValidatedRealtimeSocket({
|
|
8
|
+
target,
|
|
9
|
+
inbound: {},
|
|
10
|
+
outbound: contract.serverToClient,
|
|
11
|
+
inboundDirection: "server-inbound",
|
|
12
|
+
outboundDirection: "server-outbound",
|
|
13
|
+
onRejected: options.onRejected,
|
|
14
|
+
logger: options.logger
|
|
15
|
+
});
|
|
16
|
+
const broadcast = outbound(handle.io);
|
|
17
|
+
return {
|
|
18
|
+
onConnection: (handler) => {
|
|
19
|
+
const listener = (raw) => {
|
|
20
|
+
const events = createValidatedRealtimeSocket({
|
|
21
|
+
target: raw,
|
|
22
|
+
inbound: contract.clientToServer,
|
|
23
|
+
outbound: contract.serverToClient,
|
|
24
|
+
inboundDirection: "server-inbound",
|
|
25
|
+
outboundDirection: "server-outbound",
|
|
26
|
+
onRejected: options.onRejected,
|
|
27
|
+
logger: options.logger
|
|
28
|
+
});
|
|
29
|
+
const failed = (error) => {
|
|
30
|
+
try {
|
|
31
|
+
raw.disconnect(true);
|
|
32
|
+
} catch {}
|
|
33
|
+
if (options.logger)
|
|
34
|
+
options.logger.error("Realtime connection handler failed", { error });
|
|
35
|
+
else
|
|
36
|
+
console.error("[stitchkit] realtime connection handler failed", error);
|
|
37
|
+
};
|
|
38
|
+
try {
|
|
39
|
+
Promise.resolve(handler({ raw, events, to: (room) => outbound(raw.to(room)) })).catch(failed);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
failed(error);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
handle.io.on("connection", listener);
|
|
45
|
+
return () => {
|
|
46
|
+
handle.io.off("connection", listener);
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
emit: broadcast.emit,
|
|
50
|
+
to: (room) => outbound(handle.io.to(room))
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { bindRealtimeServer2 };
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parseRealtimeRequestArguments,
|
|
3
|
+
parseRealtimeRequestAcknowledgement,
|
|
4
|
+
createValidatedRealtimeSocket
|
|
5
|
+
} from "./index-pw99k9h5.js";
|
|
6
|
+
import {
|
|
7
|
+
randomHex
|
|
8
|
+
} from "./index-c9d05kvt.js";
|
|
9
|
+
|
|
10
|
+
// src/browser/socket-io-trace.ts
|
|
11
|
+
var realtimeRequestTraces = new WeakMap;
|
|
12
|
+
function observeRealtimeRequestPhase(trace, phase) {
|
|
13
|
+
const observation = {
|
|
14
|
+
requestId: trace.requestId,
|
|
15
|
+
event: trace.event,
|
|
16
|
+
phase,
|
|
17
|
+
elapsedMs: performance.now() - trace.startedAt
|
|
18
|
+
};
|
|
19
|
+
const observers = trace.observeRequest && trace.observeRequest !== trace.observeClient ? [trace.observeClient, trace.observeRequest] : [trace.observeClient ?? trace.observeRequest];
|
|
20
|
+
for (const observer of observers) {
|
|
21
|
+
if (!observer)
|
|
22
|
+
continue;
|
|
23
|
+
try {
|
|
24
|
+
const result = observer(observation);
|
|
25
|
+
if (result)
|
|
26
|
+
Promise.resolve(result).catch(() => {
|
|
27
|
+
return;
|
|
28
|
+
});
|
|
29
|
+
} catch {}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function socketIoPacketIdentity(data, expected) {
|
|
33
|
+
if (typeof data !== "string")
|
|
34
|
+
return null;
|
|
35
|
+
const type = data.charAt(0);
|
|
36
|
+
const binary = type === (expected === "event" ? "5" : "6");
|
|
37
|
+
if (type !== (expected === "event" ? "2" : "3") && !binary)
|
|
38
|
+
return null;
|
|
39
|
+
let offset = 1;
|
|
40
|
+
if (binary) {
|
|
41
|
+
const separator = data.indexOf("-", offset);
|
|
42
|
+
if (separator < 0)
|
|
43
|
+
return null;
|
|
44
|
+
for (let index = offset;index < separator; index += 1) {
|
|
45
|
+
const code = data.charCodeAt(index);
|
|
46
|
+
if (code < 48 || code > 57)
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
offset = separator + 1;
|
|
50
|
+
}
|
|
51
|
+
let namespace = "/";
|
|
52
|
+
if (data.charAt(offset) === "/") {
|
|
53
|
+
const separator = data.indexOf(",", offset);
|
|
54
|
+
if (separator < 0)
|
|
55
|
+
return null;
|
|
56
|
+
namespace = data.slice(offset, separator);
|
|
57
|
+
offset = separator + 1;
|
|
58
|
+
}
|
|
59
|
+
const start = offset;
|
|
60
|
+
while (offset < data.length) {
|
|
61
|
+
const code = data.charCodeAt(offset);
|
|
62
|
+
if (code < 48 || code > 57)
|
|
63
|
+
break;
|
|
64
|
+
offset += 1;
|
|
65
|
+
}
|
|
66
|
+
if (offset === start)
|
|
67
|
+
return null;
|
|
68
|
+
return { namespace, id: data.slice(start, offset) };
|
|
69
|
+
}
|
|
70
|
+
function packetIdentityKey(identity) {
|
|
71
|
+
return `${identity.namespace}:${identity.id}`;
|
|
72
|
+
}
|
|
73
|
+
function createRequestTracer(onRequestPhase) {
|
|
74
|
+
const requestTracesByNativeKey = new Map;
|
|
75
|
+
const observedRequestEngines = new WeakSet;
|
|
76
|
+
let startingRequestTrace = null;
|
|
77
|
+
return {
|
|
78
|
+
start(event, onPhase) {
|
|
79
|
+
if (!onRequestPhase && !onPhase)
|
|
80
|
+
return;
|
|
81
|
+
const trace = {
|
|
82
|
+
requestId: randomHex(16),
|
|
83
|
+
event,
|
|
84
|
+
startedAt: performance.now(),
|
|
85
|
+
observeClient: onRequestPhase,
|
|
86
|
+
observeRequest: onPhase,
|
|
87
|
+
closed: false
|
|
88
|
+
};
|
|
89
|
+
return trace;
|
|
90
|
+
},
|
|
91
|
+
close(trace, phase) {
|
|
92
|
+
if (!trace || trace.closed)
|
|
93
|
+
return;
|
|
94
|
+
trace.closed = true;
|
|
95
|
+
if (trace.nativeKey)
|
|
96
|
+
requestTracesByNativeKey.delete(trace.nativeKey);
|
|
97
|
+
observeRealtimeRequestPhase(trace, phase);
|
|
98
|
+
},
|
|
99
|
+
starting(trace, emit) {
|
|
100
|
+
startingRequestTrace = trace ?? null;
|
|
101
|
+
try {
|
|
102
|
+
return emit();
|
|
103
|
+
} finally {
|
|
104
|
+
startingRequestTrace = null;
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
observeEachOpen(target, current) {
|
|
108
|
+
if (!onRequestPhase)
|
|
109
|
+
return;
|
|
110
|
+
target.io.on("open", () => {
|
|
111
|
+
const socket = current();
|
|
112
|
+
if (socket)
|
|
113
|
+
this.observe(socket);
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
observe(target) {
|
|
117
|
+
const engine = target.io.engine;
|
|
118
|
+
if (!engine || observedRequestEngines.has(engine))
|
|
119
|
+
return;
|
|
120
|
+
observedRequestEngines.add(engine);
|
|
121
|
+
engine.on("packetCreate", (packet) => {
|
|
122
|
+
if (!startingRequestTrace || packet.type !== "message")
|
|
123
|
+
return;
|
|
124
|
+
const identity = socketIoPacketIdentity(packet.data, "event");
|
|
125
|
+
if (!identity)
|
|
126
|
+
return;
|
|
127
|
+
const key = packetIdentityKey(identity);
|
|
128
|
+
startingRequestTrace.nativeKey = key;
|
|
129
|
+
requestTracesByNativeKey.set(key, startingRequestTrace);
|
|
130
|
+
observeRealtimeRequestPhase(startingRequestTrace, "engine-handoff");
|
|
131
|
+
});
|
|
132
|
+
engine.on("packet", (packet) => {
|
|
133
|
+
if (packet.type !== "message")
|
|
134
|
+
return;
|
|
135
|
+
const identity = socketIoPacketIdentity(packet.data, "ack");
|
|
136
|
+
if (!identity)
|
|
137
|
+
return;
|
|
138
|
+
const key = packetIdentityKey(identity);
|
|
139
|
+
const trace = requestTracesByNativeKey.get(key);
|
|
140
|
+
if (!trace || trace.closed)
|
|
141
|
+
return;
|
|
142
|
+
observeRealtimeRequestPhase(trace, "engine-ack-received");
|
|
143
|
+
requestTracesByNativeKey.delete(key);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/browser/realtime-client.ts
|
|
150
|
+
function assertRealtimeClientTransport(transport) {
|
|
151
|
+
for (const capability of ["on", "emit", "emitWithAck", "onConnectionChange"]) {
|
|
152
|
+
if (typeof Reflect.get(transport, capability) !== "function") {
|
|
153
|
+
throw new TypeError(`Realtime client transport does not implement ${capability}()`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (typeof transport.connected !== "boolean") {
|
|
157
|
+
throw new TypeError("Realtime client transport does not expose boolean connected");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function bindRealtimeClient2(contract, transport, { onRejected, logger } = {}) {
|
|
161
|
+
assertRealtimeClientTransport(transport);
|
|
162
|
+
const events = createValidatedRealtimeSocket({
|
|
163
|
+
target: transport,
|
|
164
|
+
inbound: contract.serverToClient,
|
|
165
|
+
outbound: contract.clientToServer,
|
|
166
|
+
inboundDirection: "client-inbound",
|
|
167
|
+
outboundDirection: "client-outbound",
|
|
168
|
+
onRejected,
|
|
169
|
+
logger,
|
|
170
|
+
subscribe: (event, handler) => {
|
|
171
|
+
const subscribe = Reflect.get(transport, "on");
|
|
172
|
+
if (typeof subscribe !== "function") {
|
|
173
|
+
throw new Error("Socket.IO client does not implement on()");
|
|
174
|
+
}
|
|
175
|
+
const unsubscribe = Reflect.apply(subscribe, transport, [event, handler]);
|
|
176
|
+
if (typeof unsubscribe !== "function") {
|
|
177
|
+
throw new Error("Socket.IO client on() did not return an unsubscribe function");
|
|
178
|
+
}
|
|
179
|
+
return () => {
|
|
180
|
+
Reflect.apply(unsubscribe, undefined, []);
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
async function request(event, ...args) {
|
|
185
|
+
const options = args.at(-1);
|
|
186
|
+
if (!options || typeof options !== "object" || !("timeoutMs" in options)) {
|
|
187
|
+
throw new TypeError(`Realtime request "${event}" requires { timeoutMs }`);
|
|
188
|
+
}
|
|
189
|
+
const timeoutMs = options.timeoutMs;
|
|
190
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
191
|
+
throw new RangeError(`Realtime request "${event}" timeoutMs must be finite and > 0`);
|
|
192
|
+
}
|
|
193
|
+
const values = args.slice(0, -1);
|
|
194
|
+
const parsedArgs = parseRealtimeRequestArguments(contract.clientToServer, event, "client-outbound", values);
|
|
195
|
+
const definition = contract.clientToServer[event];
|
|
196
|
+
if (!definition?.ack) {
|
|
197
|
+
throw new Error(`Realtime request "${event}" has no acknowledgement schema`);
|
|
198
|
+
}
|
|
199
|
+
const pending = transport.emitWithAck(event, parsedArgs, options);
|
|
200
|
+
const trace = realtimeRequestTraces.get(pending);
|
|
201
|
+
if (trace)
|
|
202
|
+
realtimeRequestTraces.delete(pending);
|
|
203
|
+
const value = await pending;
|
|
204
|
+
let acknowledgement;
|
|
205
|
+
try {
|
|
206
|
+
acknowledgement = parseRealtimeRequestAcknowledgement(definition.ack, event, "client-inbound", value, onRejected, logger);
|
|
207
|
+
} finally {
|
|
208
|
+
if (trace && !trace.closed) {
|
|
209
|
+
trace.closed = true;
|
|
210
|
+
observeRealtimeRequestPhase(trace, "settled");
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return acknowledgement;
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
...events,
|
|
217
|
+
get connected() {
|
|
218
|
+
return transport.connected;
|
|
219
|
+
},
|
|
220
|
+
request,
|
|
221
|
+
onConnectionChange: (listener) => transport.onConnectionChange(listener)
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export { realtimeRequestTraces, createRequestTracer, bindRealtimeClient2 };
|
|
@@ -6,11 +6,11 @@ import {
|
|
|
6
6
|
mergeSchemas,
|
|
7
7
|
assertToolExtensionCompatible,
|
|
8
8
|
projectToolSurface
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-x87j7csh.js";
|
|
10
10
|
import {
|
|
11
11
|
toolErrorFromResult,
|
|
12
12
|
executeToolMethod
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-m2xqkv55.js";
|
|
14
14
|
|
|
15
15
|
// src/tools/mount.ts
|
|
16
16
|
import { z } from "zod";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// src/internal/optional-peer.ts
|
|
2
|
+
function isModuleNotFound(error) {
|
|
3
|
+
if (typeof error !== "object" || error === null)
|
|
4
|
+
return false;
|
|
5
|
+
const code = "code" in error ? error.code : undefined;
|
|
6
|
+
const message = "message" in error && typeof error.message === "string" ? error.message : "";
|
|
7
|
+
return code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND" || message.includes("Cannot find module") || message.includes("Cannot find package");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { isModuleNotFound };
|