stitchkit 0.76.0 → 0.76.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/dist/agent-runtime-coding-tools.js +1 -2
- package/dist/agent-runtime-harness.js +4 -5
- package/dist/agent-runtime.js +7 -8
- package/dist/application/keyspace.d.ts +37 -0
- package/dist/application/keyspace.d.ts.map +1 -1
- package/dist/application/watch-hub.d.ts +1 -1
- package/dist/application/watch-hub.d.ts.map +1 -1
- package/dist/application.d.ts +1 -1
- package/dist/application.d.ts.map +1 -1
- package/dist/application.js +31 -8
- package/dist/cli.js +6 -7
- package/dist/contract/index.js +1 -2
- package/dist/{index-v5dm4bwq.js → index-58jzmnn4.js} +1 -1
- package/dist/{index-885chjxq.js → index-7qy2ex0m.js} +1 -1
- package/dist/index-a916km3r.js +45 -0
- package/dist/{index-28jsdwt1.js → index-aczggrty.js} +1 -1
- package/dist/{index-65kathdm.js → index-da1aqnhb.js} +4 -6
- package/dist/{index-xgahrwdf.js → index-ezmn6ac6.js} +3 -3
- package/dist/{index-4kp4fxvp.js → index-f6n5n7nz.js} +18 -4
- package/dist/{index-6wr9f6qm.js → index-jqtsc9mj.js} +2 -2
- package/dist/{index-9c5dbr5q.js → index-k2zczx1g.js} +1 -1
- package/dist/{index-v7xjfy10.js → index-m668wzyc.js} +1 -1
- package/dist/{index-e0a57ymn.js → index-nemjkxjp.js} +1 -1
- package/dist/{index-9my2n66s.js → index-s2rchahr.js} +4 -4
- package/dist/{index-k68e5jz0.js → index-s4c8wy8m.js} +2 -2
- package/dist/{index-52400rdd.js → index-t8qyvrvg.js} +3 -3
- package/dist/{index-endzd8sj.js → index-vbf2p6me.js} +1 -1
- package/dist/{index-hsz2mmk0.js → index-vj3vvpaa.js} +17 -1
- package/dist/index.js +1 -2
- package/dist/internal/stable-digest.d.ts +40 -6
- package/dist/internal/stable-digest.d.ts.map +1 -1
- package/dist/live/watch-client.d.ts +52 -5
- package/dist/live/watch-client.d.ts.map +1 -1
- package/dist/live.d.ts +1 -1
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +44 -57
- package/dist/node.js +4 -5
- package/dist/observability/index.js +3 -4
- package/dist/primitives.js +1 -2
- package/dist/remote.js +2 -3
- package/dist/server/index.js +5 -6
- package/dist/testing.js +2 -3
- package/dist/tool-invoker.js +5 -6
- package/dist/tools.js +13 -14
- package/llms-full.txt +37 -5
- package/package.json +1 -1
- package/dist/index-rxfy4cq7.js +0 -17
- package/dist/index-vdvmcy7r.js +0 -22
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A stable identity for a call's arguments — one implementation, two callers.
|
|
3
|
+
*
|
|
4
|
+
* Two callers need the same thing for different reasons. The MCP round keys a
|
|
5
|
+
* tool invocation by `(operation, arguments)` so a retry is recognised as the
|
|
6
|
+
* same round; a watched read keys its shared source by `(operation, arguments)`
|
|
7
|
+
* so two browsers asking the same question are one read on the server. If those
|
|
8
|
+
* two computed the key differently, the same arguments would be the same round
|
|
9
|
+
* and two different watches — and nothing would say so.
|
|
10
|
+
*
|
|
11
|
+
* The stability that matters is key order: `{a:1,b:2}` and `{b:2,a:1}` are the
|
|
12
|
+
* same arguments and `JSON.stringify` disagrees, so a naive key silently splits
|
|
13
|
+
* one shared source into two whenever a caller builds its object in a different
|
|
14
|
+
* order. That is not a hypothetical: object literal order follows the source
|
|
15
|
+
* that wrote it, and two components asking the same question rarely share one.
|
|
16
|
+
*
|
|
17
|
+
* ## Why this is not SHA-256
|
|
18
|
+
*
|
|
19
|
+
* It was, and that made every watched read fail on an ordinary intranet. Web
|
|
20
|
+
* Crypto — `crypto.subtle` — exists only in a **secure context**, so a page
|
|
21
|
+
* served over plain HTTP from a LAN name has no `crypto.subtle` at all and the
|
|
22
|
+
* first digest throws `Cannot read properties of undefined`. `localhost` is
|
|
23
|
+
* secure by definition, which is exactly why nothing caught it until a browser
|
|
24
|
+
* opened the app by its name.
|
|
25
|
+
*
|
|
26
|
+
* The fix is not a fallback, it is admitting what this is for: **identity, not
|
|
27
|
+
* secrecy**. Nothing here resists an adversary — an attacker who can choose your
|
|
28
|
+
* watch arguments can already ask the question directly. So the requirement is
|
|
29
|
+
* distribution and determinism, both ends agreeing, and no ambient capability;
|
|
30
|
+
* a cryptographic hash bought none of that and cost the entire non-secure web.
|
|
31
|
+
*
|
|
32
|
+
* Being synchronous is the second thing it buys. A promise for a key made the
|
|
33
|
+
* first subscription of a question asynchronous, which meant a component could
|
|
34
|
+
* not be handed a retained value in the same turn it subscribed.
|
|
35
|
+
*/
|
|
1
36
|
/**
|
|
2
37
|
* The value with every object's keys sorted, recursively — arrays keep their
|
|
3
38
|
* order, because in an array order *is* the value.
|
|
@@ -7,12 +42,11 @@
|
|
|
7
42
|
*/
|
|
8
43
|
export declare function stableValue(value: unknown): unknown;
|
|
9
44
|
/**
|
|
10
|
-
* A bounded, order-independent
|
|
45
|
+
* A bounded, order-independent identity for a call's arguments.
|
|
11
46
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* large subscription key repeated in every frame.
|
|
47
|
+
* 128 bits as 32 lowercase hex characters. Deterministic across runtimes and
|
|
48
|
+
* across both ends of a socket, synchronous, and dependent on no ambient
|
|
49
|
+
* capability — see the module header for why that last one is the whole point.
|
|
16
50
|
*
|
|
17
51
|
* What it cannot do, stated because the limit is easy to walk into: values
|
|
18
52
|
* `JSON.stringify` drops or transforms — `undefined` members, a `Date`, a `Map`,
|
|
@@ -20,5 +54,5 @@ export declare function stableValue(value: unknown): unknown;
|
|
|
20
54
|
* Contract arguments are parsed JSON, so this is the argument shape by
|
|
21
55
|
* construction; a caller digesting something else has to say what it means.
|
|
22
56
|
*/
|
|
23
|
-
export declare function argumentsDigest(args: Record<string, unknown>):
|
|
57
|
+
export declare function argumentsDigest(args: Record<string, unknown>): string;
|
|
24
58
|
//# sourceMappingURL=stable-digest.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stable-digest.d.ts","sourceRoot":"","sources":["../../src/internal/stable-digest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stable-digest.d.ts","sourceRoot":"","sources":["../../src/internal/stable-digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQnD;AAyCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAGrE"}
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
* sense a rendering component can use.
|
|
45
45
|
*/
|
|
46
46
|
import type { ContractDef, EndpointDef } from '../contract/define.js';
|
|
47
|
-
import { type WatchKey, type WatchStateFrame } from './watch-contract.js';
|
|
47
|
+
import { WATCH_CLOSE, WATCH_OPEN, WATCH_STATE, WATCH_VALUE, type WatchKey, type WatchStateFrame, type WatchValueFrame } from './watch-contract.js';
|
|
48
48
|
export interface WatchListeners<TValue> {
|
|
49
49
|
value(value: TValue): void;
|
|
50
50
|
/** Phase and, when unhealthy, the read's own code and message. */
|
|
@@ -56,11 +56,58 @@ export interface WatchHandle<TValue> {
|
|
|
56
56
|
/** Drops every listener this handle registered and releases the key. */
|
|
57
57
|
close(): void;
|
|
58
58
|
}
|
|
59
|
-
/**
|
|
59
|
+
/** What the server sends a watcher, by event name. */
|
|
60
|
+
export interface WatchInboundEvents {
|
|
61
|
+
[WATCH_VALUE]: WatchValueFrame;
|
|
62
|
+
[WATCH_STATE]: WatchStateFrame;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A realtime client, as much of one as this adapter needs to see.
|
|
66
|
+
*
|
|
67
|
+
* Four members and no types on them, because the point of this shape is that a
|
|
68
|
+
* *typed* client satisfies it: a bound realtime client's `on` is generic over
|
|
69
|
+
* the events of the contract it was bound to, and TypeScript will not relate
|
|
70
|
+
* that signature to any concrete one written here — measured, both with a payload
|
|
71
|
+
* parameter and with the tuple form the realtime handler actually has.
|
|
72
|
+
*/
|
|
73
|
+
export interface RealtimeClientLike {
|
|
74
|
+
on: (...args: never[]) => unknown;
|
|
75
|
+
emit: (...args: never[]) => unknown;
|
|
76
|
+
request: (...args: never[]) => unknown;
|
|
77
|
+
onConnectionChange: (...args: never[]) => unknown;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Hand a bound realtime client to {@link createWatchClient}.
|
|
81
|
+
*
|
|
82
|
+
* The guide used to say "pass a bound realtime client" and the types refused it,
|
|
83
|
+
* which is the worst combination: an instruction that reads as supported and
|
|
84
|
+
* fails at the call site. This is the conversion, once, in the framework —
|
|
85
|
+
* rather than the same cast copied into every application that follows the
|
|
86
|
+
* guide.
|
|
87
|
+
*/
|
|
88
|
+
export declare function watchTransport(client: RealtimeClientLike): WatchTransport;
|
|
89
|
+
/**
|
|
90
|
+
* The transport half a watch client needs — a realtime client bound to a
|
|
91
|
+
* contract that carries `watchContract`.
|
|
92
|
+
*
|
|
93
|
+
* Written in the protocol's own four event names rather than in `string`, so an
|
|
94
|
+
* application bringing its own transport knows exactly what to implement.
|
|
95
|
+
*
|
|
96
|
+
* A **bound realtime client does not satisfy this shape**, and no phrasing of it
|
|
97
|
+
* would fix that: its `on` is generic over the events of the contract it was
|
|
98
|
+
* bound to, and TypeScript will not relate two generic signatures like these.
|
|
99
|
+
* Pass it through {@link watchTransport}, which is that conversion done once
|
|
100
|
+
* here instead of once per application.
|
|
101
|
+
*/
|
|
60
102
|
export interface WatchTransport {
|
|
61
|
-
on(event:
|
|
62
|
-
emit(event:
|
|
63
|
-
|
|
103
|
+
on<TEvent extends keyof WatchInboundEvents>(event: TEvent, handler: (payload: WatchInboundEvents[TEvent]) => void): () => void;
|
|
104
|
+
emit(event: typeof WATCH_CLOSE, payload: {
|
|
105
|
+
key: WatchKey;
|
|
106
|
+
}): unknown;
|
|
107
|
+
request(event: typeof WATCH_OPEN, payload: {
|
|
108
|
+
key: WatchKey;
|
|
109
|
+
args: unknown;
|
|
110
|
+
}, options: {
|
|
64
111
|
timeoutMs: number;
|
|
65
112
|
}): Promise<{
|
|
66
113
|
accepted: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch-client.d.ts","sourceRoot":"","sources":["../../src/live/watch-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEnE,OAAO,
|
|
1
|
+
{"version":3,"file":"watch-client.d.ts","sourceRoot":"","sources":["../../src/live/watch-client.ts"],"names":[],"mappings":"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"}
|
package/dist/live.d.ts
CHANGED
|
@@ -13,6 +13,6 @@
|
|
|
13
13
|
* a watched read live in `stitchkit/application`. → ADR 0150.
|
|
14
14
|
*/
|
|
15
15
|
export { defineEvents, type EventDecision, type EventDeliveryMode, type EventPayloads, type EventsConfig, type EventsDeclaration, type EventTopicDeclaration, type EventTopicRegistry, type EventTopicsOfMode, type EventUndecided, toRealtimeContract, type WireTopic, } from './live/events.js';
|
|
16
|
-
export { createWatchClient, type TypedWatchClient, type WatchClientConfig, type WatchHandle, type WatchListeners, type WatchTransport, } from './live/watch-client.js';
|
|
16
|
+
export { createWatchClient, type RealtimeClientLike, type TypedWatchClient, type WatchClientConfig, type WatchHandle, type WatchInboundEvents, type WatchListeners, type WatchTransport, watchTransport, } from './live/watch-client.js';
|
|
17
17
|
export { WATCH_CLOSE, WATCH_OPEN, WATCH_STATE, WATCH_VALUE, type WatchKey, WatchKeySchema, type WatchStateFrame, WatchStateSchema, type WatchValueFrame, WatchValueSchema, watchContract, watchKeyString, } from './live/watch-contract.js';
|
|
18
18
|
//# sourceMappingURL=live.d.ts.map
|
package/dist/live.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EACL,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,kBAAkB,EAClB,KAAK,SAAS,GACf,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EACL,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,kBAAkB,EAClB,KAAK,SAAS,GACf,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,WAAW,EACX,UAAU,EACV,WAAW,EACX,WAAW,EACX,KAAK,QAAQ,EACb,cAAc,EACd,KAAK,eAAe,EACpB,gBAAgB,EAChB,KAAK,eAAe,EACpB,gBAAgB,EAChB,aAAa,EACb,cAAc,GACf,MAAM,uBAAuB,CAAC"}
|
package/dist/live.js
CHANGED
|
@@ -2,9 +2,6 @@ import {
|
|
|
2
2
|
LiveStatePhaseSchema,
|
|
3
3
|
LiveStateStopReasonSchema
|
|
4
4
|
} from "./index-35z5h2ty.js";
|
|
5
|
-
import {
|
|
6
|
-
bytesToBase64Url
|
|
7
|
-
} from "./index-rxfy4cq7.js";
|
|
8
5
|
|
|
9
6
|
// src/live/events.ts
|
|
10
7
|
import { z } from "zod";
|
|
@@ -68,9 +65,36 @@ function stableValue(value) {
|
|
|
68
65
|
}
|
|
69
66
|
return result;
|
|
70
67
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
function mix128(input) {
|
|
69
|
+
let a = 2654435769;
|
|
70
|
+
let b = 2246822507;
|
|
71
|
+
let c = 3266489909;
|
|
72
|
+
let d = 668265263;
|
|
73
|
+
for (let index = 0;index < input.length; index += 1) {
|
|
74
|
+
const code = input.charCodeAt(index);
|
|
75
|
+
a = Math.imul(a ^ code, 2246822519);
|
|
76
|
+
b = Math.imul(b ^ code, 3266489917);
|
|
77
|
+
c = Math.imul(c ^ code, 668265263);
|
|
78
|
+
d = Math.imul(d ^ code, 374761393);
|
|
79
|
+
a = a << 13 | a >>> 19;
|
|
80
|
+
b = b << 17 | b >>> 15;
|
|
81
|
+
c = c << 7 | c >>> 25;
|
|
82
|
+
d = d << 11 | d >>> 21;
|
|
83
|
+
}
|
|
84
|
+
a ^= b >>> 15;
|
|
85
|
+
b ^= c >>> 13;
|
|
86
|
+
c ^= d >>> 11;
|
|
87
|
+
d ^= a >>> 9;
|
|
88
|
+
return [
|
|
89
|
+
Math.imul(a ^ a >>> 16, 575075507) >>> 0,
|
|
90
|
+
Math.imul(b ^ b >>> 13, 2654435761) >>> 0,
|
|
91
|
+
Math.imul(c ^ c >>> 16, 2246822507) >>> 0,
|
|
92
|
+
Math.imul(d ^ d >>> 15, 3266489909) >>> 0
|
|
93
|
+
];
|
|
94
|
+
}
|
|
95
|
+
function argumentsDigest(args) {
|
|
96
|
+
const lanes = mix128(JSON.stringify(stableValue(args)) ?? "undefined");
|
|
97
|
+
return lanes.map((lane) => lane.toString(16).padStart(8, "0")).join("");
|
|
74
98
|
}
|
|
75
99
|
|
|
76
100
|
// src/live/watch-contract.ts
|
|
@@ -116,9 +140,11 @@ function watchKeyString(key) {
|
|
|
116
140
|
}
|
|
117
141
|
|
|
118
142
|
// src/live/watch-client.ts
|
|
143
|
+
function watchTransport(client) {
|
|
144
|
+
return client;
|
|
145
|
+
}
|
|
119
146
|
function createWatchClient(contract, config) {
|
|
120
147
|
const entries = new Map;
|
|
121
|
-
const digests = new Map;
|
|
122
148
|
const holdMs = config.holdMs ?? 0;
|
|
123
149
|
const openTimeoutMs = config.openTimeoutMs ?? 1e4;
|
|
124
150
|
const service = contract.meta.prefix;
|
|
@@ -165,18 +191,6 @@ function createWatchClient(contract, config) {
|
|
|
165
191
|
open(entry);
|
|
166
192
|
}
|
|
167
193
|
});
|
|
168
|
-
function cachedDigest(action, args) {
|
|
169
|
-
return digests.get(`${service}/${action}/${JSON.stringify(stableValue(args))}`);
|
|
170
|
-
}
|
|
171
|
-
async function resolveDigest(action, args) {
|
|
172
|
-
const cacheKey = `${service}/${action}/${JSON.stringify(stableValue(args))}`;
|
|
173
|
-
const cached = digests.get(cacheKey);
|
|
174
|
-
if (cached !== undefined)
|
|
175
|
-
return cached;
|
|
176
|
-
const digest = await argumentsDigest(args);
|
|
177
|
-
digests.set(cacheKey, digest);
|
|
178
|
-
return digest;
|
|
179
|
-
}
|
|
180
194
|
function entryFor(key, args) {
|
|
181
195
|
const id = watchKeyString(key);
|
|
182
196
|
const existing = entries.get(id);
|
|
@@ -243,55 +257,27 @@ function createWatchClient(contract, config) {
|
|
|
243
257
|
}
|
|
244
258
|
function handleFor(action, args) {
|
|
245
259
|
const mine = new Set;
|
|
246
|
-
|
|
247
|
-
const known = cachedDigest(action, args);
|
|
248
|
-
if (known !== undefined)
|
|
249
|
-
entry = entryFor({ service, action, digest: known }, args);
|
|
250
|
-
const ready = (async () => {
|
|
251
|
-
if (entry)
|
|
252
|
-
return entry;
|
|
253
|
-
const digest = await resolveDigest(action, args);
|
|
254
|
-
entry = entryFor({ service, action, digest }, args);
|
|
255
|
-
return entry;
|
|
256
|
-
})();
|
|
260
|
+
const entry = entryFor({ service, action, digest: argumentsDigest(args) }, args);
|
|
257
261
|
return {
|
|
258
262
|
subscribe(listeners) {
|
|
259
263
|
const registered = listeners;
|
|
260
264
|
mine.add(registered);
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}
|
|
267
|
-
ready.then((target) => {
|
|
268
|
-
if (!mine.has(registered))
|
|
269
|
-
return;
|
|
270
|
-
if (!target.listeners.has(registered)) {
|
|
271
|
-
target.listeners.add(registered);
|
|
272
|
-
if (target.hasValue)
|
|
273
|
-
registered.value(target.value);
|
|
274
|
-
registered.state?.(target.state);
|
|
275
|
-
}
|
|
276
|
-
open(target);
|
|
277
|
-
});
|
|
265
|
+
entry.listeners.add(registered);
|
|
266
|
+
if (entry.hasValue)
|
|
267
|
+
registered.value(entry.value);
|
|
268
|
+
registered.state?.(entry.state);
|
|
269
|
+
open(entry);
|
|
278
270
|
return () => {
|
|
279
271
|
mine.delete(registered);
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
return;
|
|
283
|
-
target.listeners.delete(registered);
|
|
284
|
-
releaseEntry(target);
|
|
272
|
+
entry.listeners.delete(registered);
|
|
273
|
+
releaseEntry(entry);
|
|
285
274
|
};
|
|
286
275
|
},
|
|
287
276
|
close() {
|
|
288
|
-
const target = entry;
|
|
289
|
-
if (!target)
|
|
290
|
-
return;
|
|
291
277
|
for (const listener of mine)
|
|
292
|
-
|
|
278
|
+
entry.listeners.delete(listener);
|
|
293
279
|
mine.clear();
|
|
294
|
-
releaseEntry(
|
|
280
|
+
releaseEntry(entry);
|
|
295
281
|
}
|
|
296
282
|
};
|
|
297
283
|
}
|
|
@@ -302,6 +288,7 @@ function createWatchClient(contract, config) {
|
|
|
302
288
|
return client;
|
|
303
289
|
}
|
|
304
290
|
export {
|
|
291
|
+
watchTransport,
|
|
305
292
|
watchKeyString,
|
|
306
293
|
watchContract,
|
|
307
294
|
toRealtimeContract,
|
package/dist/node.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
createHandler,
|
|
6
6
|
createSocketIOServer,
|
|
7
7
|
createUnixClientTransport
|
|
8
|
-
} from "./index-
|
|
8
|
+
} from "./index-t8qyvrvg.js";
|
|
9
9
|
import {
|
|
10
10
|
createImplement,
|
|
11
11
|
createImplementRegistry,
|
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
createScopedImplementRegistry,
|
|
15
15
|
implement,
|
|
16
16
|
implementRegistry
|
|
17
|
-
} from "./index-
|
|
18
|
-
import"./index-
|
|
17
|
+
} from "./index-vbf2p6me.js";
|
|
18
|
+
import"./index-nemjkxjp.js";
|
|
19
19
|
import"./index-7b188kmz.js";
|
|
20
20
|
import {
|
|
21
21
|
ShutdownOptionsSchema,
|
|
@@ -25,8 +25,7 @@ import {
|
|
|
25
25
|
createServerLifecycle
|
|
26
26
|
} from "./index-3z73fh2c.js";
|
|
27
27
|
import"./index-nt1mp8km.js";
|
|
28
|
-
import"./index-
|
|
29
|
-
import"./index-rxfy4cq7.js";
|
|
28
|
+
import"./index-vj3vvpaa.js";
|
|
30
29
|
import {
|
|
31
30
|
AppError,
|
|
32
31
|
appError,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
redact,
|
|
11
11
|
sanitizePayload,
|
|
12
12
|
truncatePreview
|
|
13
|
-
} from "../index-
|
|
13
|
+
} from "../index-aczggrty.js";
|
|
14
14
|
import {
|
|
15
15
|
getRequestContext,
|
|
16
16
|
getTraceId,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
setRequestError,
|
|
22
22
|
setRequestUser,
|
|
23
23
|
wrapInRequestContext
|
|
24
|
-
} from "../index-
|
|
24
|
+
} from "../index-nemjkxjp.js";
|
|
25
25
|
import {
|
|
26
26
|
childSpan,
|
|
27
27
|
createTraceContext,
|
|
@@ -31,8 +31,7 @@ import {
|
|
|
31
31
|
resolvePropagationContext,
|
|
32
32
|
resolveTraceContext
|
|
33
33
|
} from "../index-nt1mp8km.js";
|
|
34
|
-
import"../index-
|
|
35
|
-
import"../index-rxfy4cq7.js";
|
|
34
|
+
import"../index-vj3vvpaa.js";
|
|
36
35
|
import"../index-0w9abg87.js";
|
|
37
36
|
import {
|
|
38
37
|
isRecord
|
package/dist/primitives.js
CHANGED
package/dist/remote.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ApiError,
|
|
3
3
|
createClient
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-58jzmnn4.js";
|
|
5
5
|
import"./index-1rxswfbv.js";
|
|
6
6
|
import"./index-nt1mp8km.js";
|
|
7
7
|
import {
|
|
8
8
|
mergeMeta
|
|
9
|
-
} from "./index-
|
|
10
|
-
import"./index-rxfy4cq7.js";
|
|
9
|
+
} from "./index-vj3vvpaa.js";
|
|
11
10
|
import {
|
|
12
11
|
AppError
|
|
13
12
|
} from "./index-0w9abg87.js";
|
package/dist/server/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
sseRoute,
|
|
14
14
|
streamingRoute,
|
|
15
15
|
webSocketLane
|
|
16
|
-
} from "../index-
|
|
16
|
+
} from "../index-t8qyvrvg.js";
|
|
17
17
|
import {
|
|
18
18
|
composeAuthHooks,
|
|
19
19
|
createAuthHook,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
signJwt,
|
|
27
27
|
verifyJwt,
|
|
28
28
|
verifyPkce
|
|
29
|
-
} from "../index-
|
|
29
|
+
} from "../index-da1aqnhb.js";
|
|
30
30
|
import {
|
|
31
31
|
DEFAULT_CORS_ALLOW_HEADERS,
|
|
32
32
|
DEFAULT_CORS_EXPOSE_HEADERS,
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
defineMultipartStream,
|
|
41
41
|
implement,
|
|
42
42
|
implementRegistry
|
|
43
|
-
} from "../index-
|
|
43
|
+
} from "../index-vbf2p6me.js";
|
|
44
44
|
import {
|
|
45
45
|
extractIp,
|
|
46
46
|
generateTraceId,
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
isPublicIp,
|
|
50
50
|
resolveSocketIp,
|
|
51
51
|
resolveTraceId
|
|
52
|
-
} from "../index-
|
|
52
|
+
} from "../index-nemjkxjp.js";
|
|
53
53
|
import {
|
|
54
54
|
isWithinDir,
|
|
55
55
|
realPathWithinDir
|
|
@@ -81,8 +81,7 @@ import {
|
|
|
81
81
|
DEFAULT_CONTRACT_STREAM_FRAME_BYTES,
|
|
82
82
|
joinRoutePath,
|
|
83
83
|
parseTrailingWildcard
|
|
84
|
-
} from "../index-
|
|
85
|
-
import"../index-rxfy4cq7.js";
|
|
84
|
+
} from "../index-vj3vvpaa.js";
|
|
86
85
|
import {
|
|
87
86
|
AppError,
|
|
88
87
|
STITCH_ERROR_STATUS,
|
package/dist/testing.js
CHANGED
|
@@ -24,13 +24,12 @@ import {
|
|
|
24
24
|
import {
|
|
25
25
|
createClient,
|
|
26
26
|
createClients
|
|
27
|
-
} from "./index-
|
|
27
|
+
} from "./index-58jzmnn4.js";
|
|
28
28
|
import"./index-1rxswfbv.js";
|
|
29
29
|
import"./index-nt1mp8km.js";
|
|
30
30
|
import {
|
|
31
31
|
joinRoutePath
|
|
32
|
-
} from "./index-
|
|
33
|
-
import"./index-rxfy4cq7.js";
|
|
32
|
+
} from "./index-vj3vvpaa.js";
|
|
34
33
|
import"./index-0w9abg87.js";
|
|
35
34
|
import {
|
|
36
35
|
isRecord
|
package/dist/tool-invoker.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createToolInvoker
|
|
3
|
-
} from "./index-
|
|
4
|
-
import"./index-
|
|
5
|
-
import"./index-
|
|
6
|
-
import"./index-
|
|
3
|
+
} from "./index-jqtsc9mj.js";
|
|
4
|
+
import"./index-7qy2ex0m.js";
|
|
5
|
+
import"./index-s4c8wy8m.js";
|
|
6
|
+
import"./index-nemjkxjp.js";
|
|
7
7
|
import"./index-22by16v6.js";
|
|
8
8
|
import"./index-cby4ar3v.js";
|
|
9
9
|
import"./index-nt1mp8km.js";
|
|
10
|
-
import"./index-
|
|
11
|
-
import"./index-rxfy4cq7.js";
|
|
10
|
+
import"./index-vj3vvpaa.js";
|
|
12
11
|
import"./index-0w9abg87.js";
|
|
13
12
|
import"./index-qyrqwr4c.js";
|
|
14
13
|
import"./index-6k1937bx.js";
|
package/dist/tools.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
redact
|
|
3
|
-
} from "./index-
|
|
3
|
+
} from "./index-aczggrty.js";
|
|
4
4
|
import {
|
|
5
5
|
buildToolManifest,
|
|
6
6
|
mountAgent
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-ezmn6ac6.js";
|
|
8
8
|
import"./index-3xnq72rz.js";
|
|
9
9
|
import {
|
|
10
10
|
argumentsDigest
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-a916km3r.js";
|
|
12
12
|
import {
|
|
13
13
|
signJwt,
|
|
14
14
|
verifyPkce
|
|
15
|
-
} from "./index-
|
|
15
|
+
} from "./index-da1aqnhb.js";
|
|
16
16
|
import {
|
|
17
17
|
DEFAULT_CORS_ALLOW_HEADERS,
|
|
18
18
|
DEFAULT_PROCESS_SIGNALS,
|
|
@@ -20,10 +20,10 @@ import {
|
|
|
20
20
|
defaultSignalSource,
|
|
21
21
|
guardSignalCallback,
|
|
22
22
|
reportSignalError
|
|
23
|
-
} from "./index-
|
|
23
|
+
} from "./index-vbf2p6me.js";
|
|
24
24
|
import {
|
|
25
25
|
createToolInvoker
|
|
26
|
-
} from "./index-
|
|
26
|
+
} from "./index-jqtsc9mj.js";
|
|
27
27
|
import {
|
|
28
28
|
WaitTimeoutError,
|
|
29
29
|
createCli,
|
|
@@ -32,10 +32,10 @@ import {
|
|
|
32
32
|
fetchPinnedDocument,
|
|
33
33
|
readCapped,
|
|
34
34
|
runWaitOperation
|
|
35
|
-
} from "./index-
|
|
35
|
+
} from "./index-s2rchahr.js";
|
|
36
36
|
import {
|
|
37
37
|
collectToolSurface
|
|
38
|
-
} from "./index-
|
|
38
|
+
} from "./index-k2zczx1g.js";
|
|
39
39
|
import {
|
|
40
40
|
createRuntimeToolFactory,
|
|
41
41
|
defineRuntimeTool
|
|
@@ -44,19 +44,19 @@ import {
|
|
|
44
44
|
collectTools,
|
|
45
45
|
createToolRunner,
|
|
46
46
|
formatToolError
|
|
47
|
-
} from "./index-
|
|
47
|
+
} from "./index-7qy2ex0m.js";
|
|
48
48
|
import {
|
|
49
49
|
ToolExecutionControlError,
|
|
50
50
|
coerceJsonArgs,
|
|
51
51
|
executeToolMethod,
|
|
52
52
|
isToolExecutionControlError,
|
|
53
53
|
toolResultFromError
|
|
54
|
-
} from "./index-
|
|
54
|
+
} from "./index-s4c8wy8m.js";
|
|
55
55
|
import {
|
|
56
56
|
getRequestContext,
|
|
57
57
|
getTraceId,
|
|
58
58
|
runWithRequestContext
|
|
59
|
-
} from "./index-
|
|
59
|
+
} from "./index-nemjkxjp.js";
|
|
60
60
|
import {
|
|
61
61
|
ManagedFileError
|
|
62
62
|
} from "./index-bfcpjw20.js";
|
|
@@ -79,8 +79,7 @@ import {
|
|
|
79
79
|
} from "./index-nt1mp8km.js";
|
|
80
80
|
import {
|
|
81
81
|
defineContract
|
|
82
|
-
} from "./index-
|
|
83
|
-
import"./index-rxfy4cq7.js";
|
|
82
|
+
} from "./index-vj3vvpaa.js";
|
|
84
83
|
import {
|
|
85
84
|
AppError,
|
|
86
85
|
STITCH_ERROR_STATUS
|
|
@@ -1146,7 +1145,7 @@ async function resolveMcpRound(options) {
|
|
|
1146
1145
|
});
|
|
1147
1146
|
const requests = policy.inputRequired;
|
|
1148
1147
|
const state = options.context.mcpReq.requestState();
|
|
1149
|
-
const digest =
|
|
1148
|
+
const digest = argumentsDigest(options.rawArgs);
|
|
1150
1149
|
if (!state) {
|
|
1151
1150
|
if (isRecord(options.context.mcpReq.inputResponses)) {
|
|
1152
1151
|
return failedResolution({
|
package/llms-full.txt
CHANGED
|
@@ -7617,9 +7617,17 @@ const hub = createWatchHub({
|
|
|
7617
7617
|
|
|
7618
7618
|
```ts
|
|
7619
7619
|
// browser
|
|
7620
|
-
import { createWatchClient } from 'stitchkit/live';
|
|
7621
|
-
|
|
7622
|
-
|
|
7620
|
+
import { createWatchClient, watchTransport } from 'stitchkit/live';
|
|
7621
|
+
|
|
7622
|
+
// `live` is the bound realtime client. It goes through `watchTransport`, and
|
|
7623
|
+
// that is not ceremony: its `on` is generic over the contract it was bound to,
|
|
7624
|
+
// and TypeScript will not relate that signature to the one a watch client
|
|
7625
|
+
// declares. The conversion lives in the framework so it is written once rather
|
|
7626
|
+
// than in every application.
|
|
7627
|
+
const watch = createWatchClient(notesContract, {
|
|
7628
|
+
transport: watchTransport(live),
|
|
7629
|
+
holdMs: 30_000,
|
|
7630
|
+
});
|
|
7623
7631
|
|
|
7624
7632
|
const handle = watch.list({ folder: 'inbox' });
|
|
7625
7633
|
const stop = handle.subscribe({
|
|
@@ -7649,6 +7657,13 @@ Without that, one address changing wakes every watcher of the operation. Twenty
|
|
|
7649
7657
|
conversations open means twenty reads for one change — nineteen of them publish
|
|
7650
7658
|
nothing, because nothing changed, and the read is paid anyway.
|
|
7651
7659
|
|
|
7660
|
+
The digest is a plain 128-bit hash computed in JavaScript, on purpose. It used
|
|
7661
|
+
to be SHA-256 through Web Crypto, which exists **only in a secure context** — so
|
|
7662
|
+
every watched read threw on a page served over plain HTTP from a LAN name, while
|
|
7663
|
+
`localhost` (secure by definition) and every test kept saying the code was fine.
|
|
7664
|
+
The key identifies a question; it does not protect one, and an attacker who can
|
|
7665
|
+
choose your watch arguments can already ask the question directly.
|
|
7666
|
+
|
|
7652
7667
|
### Who shares with whom
|
|
7653
7668
|
|
|
7654
7669
|
A key is `(service, action, digest of arguments)`, and everyone on that key gets
|
|
@@ -7737,8 +7752,23 @@ point:
|
|
|
7737
7752
|
immediately. An event emitted before the memory update is a wake-up to the old
|
|
7738
7753
|
value.
|
|
7739
7754
|
|
|
7740
|
-
|
|
7741
|
-
|
|
7755
|
+
Where there is no kernel — a server that binds its own signals and closes what
|
|
7756
|
+
it holds in an order it wrote — open it directly instead:
|
|
7757
|
+
|
|
7758
|
+
```ts
|
|
7759
|
+
const opened = await openKeyspace(sessions, { backend });
|
|
7760
|
+
opened.keyspace.get(id); // synchronous, from memory
|
|
7761
|
+
// on shutdown, in the order you chose:
|
|
7762
|
+
opened.stopAdmission();
|
|
7763
|
+
await opened.drain();
|
|
7764
|
+
await opened.close();
|
|
7765
|
+
```
|
|
7766
|
+
|
|
7767
|
+
The resource is a thin wrapper over exactly that, so there is one implementation
|
|
7768
|
+
and two lifecycles, not two keyspaces.
|
|
7769
|
+
|
|
7770
|
+
Where there **is** a kernel it is a **resource**, read with `context.use(...)`,
|
|
7771
|
+
rather than a function you call wherever you need it. The kernel resolves its resource graph in the constructor
|
|
7742
7772
|
and cannot register one afterwards, so a keyspace opened by a bare call inside
|
|
7743
7773
|
another resource's `start` is never drained, never closed, and never ordered
|
|
7744
7774
|
against the things that write to it.
|
|
@@ -13125,6 +13155,7 @@ realtime contract from `stitchkit`, and the server halves live in `stitchkit/app
|
|
|
13125
13155
|
| `EventPayloads` / `EventTopicsOfMode` / `WireTopic` | _types_ | payload map keyed by wire topic, the topics of one mode, and the `prefix.name` a topic is addressed by |
|
|
13126
13156
|
| `createWatchClient` | function | contract-shaped watch client: `watch.action(args)` returns a ref-counted handle sharing one subscription |
|
|
13127
13157
|
| `WatchHandle` / `WatchListeners` / `WatchClientConfig` / `WatchTransport` / `TypedWatchClient` | _types_ | subscribe/close, the value and state listeners, hold window and open deadline, and the bound realtime client it rides |
|
|
13158
|
+
| `watchTransport` / `RealtimeClientLike` / `WatchInboundEvents` | function / _types_ | hands a bound realtime client to a watch client — two generic signatures TypeScript will not relate, converted once here |
|
|
13128
13159
|
| `watchContract` | const | the four-event realtime contract a watched read travels on |
|
|
13129
13160
|
| `WATCH_OPEN` / `WATCH_CLOSE` / `WATCH_VALUE` / `WATCH_STATE` | const | the event names of that contract |
|
|
13130
13161
|
| `WatchKey` / `WatchKeySchema` / `watchKeyString` | type / schema / function | `(service, action, arguments digest)` — the identity both ends compute the same way |
|
|
@@ -13555,6 +13586,7 @@ the function that derives it from a snapshot,
|
|
|
13555
13586
|
| Export | Kind | Summary |
|
|
13556
13587
|
|--------|------|---------|
|
|
13557
13588
|
| `defineKeyspace` / `keyspaceResource` | function | a named record set read synchronously from memory and written through one serialised chain; backend first, then memory, then the change event |
|
|
13589
|
+
| `openKeyspace` / `OpenedKeyspace` | function / type | the same keyspace opened directly, for an application that owns its own lifecycle rather than declaring resources to a kernel |
|
|
13558
13590
|
| `KeyspaceBackend` / `KeyspaceDeclaration` / `KeyspaceChange` / `KeyspaceResourceConfig` / `OpenKeyspace` | _types_ | the four-method durability port, the declaration, the announced change, the resource's options and the published handle |
|
|
13559
13591
|
| `memoryKeyspaceBackend` / `sqliteKeyspaceBackend` / `SqliteKeyspaceBackendConfig` | function / type | a disposable in-process backend, and one table with a key and a JSON payload over a caller-owned database |
|
|
13560
13592
|
| `SqliteDatabase` / `SqliteStatement` / `SqliteValue` | _types_ | the minimal synchronous SQLite boundary the framework types against |
|