@namzu/sdk 13.1.0 → 14.0.1
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 +140 -0
- package/dist/agents/runAgent.d.ts +9 -0
- package/dist/agents/runAgent.d.ts.map +1 -1
- package/dist/agents/runAgent.js.map +1 -1
- package/dist/connector/mcp/__tests__/a-transport-forgets-its-listeners.test.d.ts +2 -0
- package/dist/connector/mcp/__tests__/a-transport-forgets-its-listeners.test.d.ts.map +1 -0
- package/dist/connector/mcp/__tests__/a-transport-forgets-its-listeners.test.js +101 -0
- package/dist/connector/mcp/__tests__/a-transport-forgets-its-listeners.test.js.map +1 -0
- package/dist/connector/mcp/http-sse.d.ts +10 -0
- package/dist/connector/mcp/http-sse.d.ts.map +1 -1
- package/dist/connector/mcp/http-sse.js +16 -0
- package/dist/connector/mcp/http-sse.js.map +1 -1
- package/dist/connector/mcp/stdio.d.ts +12 -0
- package/dist/connector/mcp/stdio.d.ts.map +1 -1
- package/dist/connector/mcp/stdio.js +33 -1
- package/dist/connector/mcp/stdio.js.map +1 -1
- package/dist/connector/mcp/streamable-http.d.ts +2 -0
- package/dist/connector/mcp/streamable-http.d.ts.map +1 -1
- package/dist/connector/mcp/streamable-http.js +13 -1
- package/dist/connector/mcp/streamable-http.js.map +1 -1
- package/dist/contracts/__tests__/an-id-the-sdk-mints-passes-its-own-schema.test.d.ts +2 -0
- package/dist/contracts/__tests__/an-id-the-sdk-mints-passes-its-own-schema.test.d.ts.map +1 -0
- package/dist/contracts/__tests__/an-id-the-sdk-mints-passes-its-own-schema.test.js +73 -0
- package/dist/contracts/__tests__/an-id-the-sdk-mints-passes-its-own-schema.test.js.map +1 -0
- package/dist/contracts/schemas.d.ts +15 -0
- package/dist/contracts/schemas.d.ts.map +1 -1
- package/dist/contracts/schemas.js +18 -1
- package/dist/contracts/schemas.js.map +1 -1
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +6 -4
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/index.d.ts +2 -0
- package/dist/manager/index.d.ts.map +1 -1
- package/dist/manager/index.js +1 -0
- package/dist/manager/index.js.map +1 -1
- package/dist/manager/project/__tests__/a-closed-workspace-takes-no-work.test.d.ts +2 -0
- package/dist/manager/project/__tests__/a-closed-workspace-takes-no-work.test.d.ts.map +1 -0
- package/dist/manager/project/__tests__/a-closed-workspace-takes-no-work.test.js +208 -0
- package/dist/manager/project/__tests__/a-closed-workspace-takes-no-work.test.js.map +1 -0
- package/dist/manager/project/lifecycle.d.ts +66 -0
- package/dist/manager/project/lifecycle.d.ts.map +1 -0
- package/dist/manager/project/lifecycle.js +125 -0
- package/dist/manager/project/lifecycle.js.map +1 -0
- package/dist/public-runtime.d.ts +2 -2
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +12 -1
- package/dist/public-runtime.js.map +1 -1
- package/dist/session/errors.d.ts +71 -1
- package/dist/session/errors.d.ts.map +1 -1
- package/dist/session/errors.js +50 -0
- package/dist/session/errors.js.map +1 -1
- package/dist/session/handoff/broadcast.d.ts.map +1 -1
- package/dist/session/handoff/broadcast.js +4 -5
- package/dist/session/handoff/broadcast.js.map +1 -1
- package/dist/session/handoff/single.d.ts.map +1 -1
- package/dist/session/handoff/single.js +5 -4
- package/dist/session/handoff/single.js.map +1 -1
- package/dist/session/migration/__tests__/a-migrated-project-id-is-an-id.test.d.ts +2 -0
- package/dist/session/migration/__tests__/a-migrated-project-id-is-an-id.test.d.ts.map +1 -0
- package/dist/session/migration/__tests__/a-migrated-project-id-is-an-id.test.js +75 -0
- package/dist/session/migration/__tests__/a-migrated-project-id-is-an-id.test.js.map +1 -0
- package/dist/session/migration/filesystem.d.ts.map +1 -1
- package/dist/session/migration/filesystem.js +24 -0
- package/dist/session/migration/filesystem.js.map +1 -1
- package/dist/store/session/disk.d.ts +3 -1
- package/dist/store/session/disk.d.ts.map +1 -1
- package/dist/store/session/disk.js +64 -1
- package/dist/store/session/disk.js.map +1 -1
- package/dist/store/session/memory.d.ts +3 -1
- package/dist/store/session/memory.d.ts.map +1 -1
- package/dist/store/session/memory.js +39 -1
- package/dist/store/session/memory.js.map +1 -1
- package/dist/types/project/entity.d.ts +17 -0
- package/dist/types/project/entity.d.ts.map +1 -1
- package/dist/types/session/store.d.ts +28 -1
- package/dist/types/session/store.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/agents/runAgent.ts +9 -0
- package/src/connector/mcp/__tests__/a-transport-forgets-its-listeners.test.ts +127 -0
- package/src/connector/mcp/http-sse.ts +17 -0
- package/src/connector/mcp/stdio.ts +34 -1
- package/src/connector/mcp/streamable-http.ts +15 -1
- package/src/contracts/__tests__/an-id-the-sdk-mints-passes-its-own-schema.test.ts +84 -0
- package/src/contracts/schemas.ts +18 -1
- package/src/manager/agent/lifecycle.ts +6 -6
- package/src/manager/index.ts +3 -0
- package/src/manager/project/__tests__/a-closed-workspace-takes-no-work.test.ts +268 -0
- package/src/manager/project/lifecycle.ts +160 -0
- package/src/public-runtime.ts +14 -0
- package/src/session/errors.ts +85 -1
- package/src/session/handoff/broadcast.ts +4 -5
- package/src/session/handoff/single.ts +5 -4
- package/src/session/migration/__tests__/a-migrated-project-id-is-an-id.test.ts +92 -0
- package/src/session/migration/filesystem.ts +28 -0
- package/src/store/session/disk.ts +79 -2
- package/src/store/session/memory.ts +49 -2
- package/src/types/project/entity.ts +18 -0
- package/src/types/session/store.ts +35 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,145 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 14.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 25acd60: `requireOpenProject` is reachable from the package root.
|
|
8
|
+
|
|
9
|
+
It was exported from the manager barrel and never re-exported by the package
|
|
10
|
+
entry point, so `import { requireOpenProject } from '@namzu/sdk'` was
|
|
11
|
+
`undefined` in 14.0.0 — found by running the published tarball rather than the
|
|
12
|
+
working tree.
|
|
13
|
+
|
|
14
|
+
`ProjectManager.requireOpen` always worked and covers the same check, so
|
|
15
|
+
nothing was broken; what was missing is the shape the function exists for. A
|
|
16
|
+
host writing its own ingress path — a custom handoff, a queue consumer that
|
|
17
|
+
creates sessions — should be able to refuse a closed workspace without
|
|
18
|
+
constructing a manager, which is precisely why the SDK's own three gates call a
|
|
19
|
+
function over a store rather than a method on an injected collaborator.
|
|
20
|
+
|
|
21
|
+
## 14.0.0
|
|
22
|
+
|
|
23
|
+
### Major Changes
|
|
24
|
+
|
|
25
|
+
- 589bcfc: A closed workspace takes no new work.
|
|
26
|
+
|
|
27
|
+
Archiving a workspace meant nothing to the code. `Thread` carried a status and
|
|
28
|
+
`ThreadManager.requireOpen`; `Project` — the thing a tenant owns, configures,
|
|
29
|
+
gives an environment, and actually closes — carried neither, so the kernel kept
|
|
30
|
+
spawning agents into a workspace its owner had shut. This moves the archival
|
|
31
|
+
invariant to the level that survives the Thread removal.
|
|
32
|
+
|
|
33
|
+
**`Project` gains `status` and `ownerVersion`.** Breaking for anyone
|
|
34
|
+
implementing `SessionStore` themselves: a `Project` you construct now needs
|
|
35
|
+
both. Existing records on disk read as `open` at version `0`, which is what
|
|
36
|
+
they were — leaving `ownerVersion` undefined would be worse than a wrong
|
|
37
|
+
default, because every compare-and-set against it would fail and an existing
|
|
38
|
+
workspace could never be closed.
|
|
39
|
+
|
|
40
|
+
**New:** `ProjectManager` with `requireOpen`, `archive` and `reopen`;
|
|
41
|
+
`SessionStore.setProjectStatus` and `SessionStore.listSessionsByProject` (both
|
|
42
|
+
optional, so a host's own store keeps compiling); `ProjectClosedError`,
|
|
43
|
+
`ProjectNotEmptyError` and `StaleProjectError`, all three exported — a host
|
|
44
|
+
that closes a workspace has to tell "this workspace is closed" from any other
|
|
45
|
+
spawn failure, and matching on a message string is not a contract.
|
|
46
|
+
|
|
47
|
+
Three decisions worth naming.
|
|
48
|
+
|
|
49
|
+
**The gate is a function over a store, not an injected manager.** The three
|
|
50
|
+
ingress paths — spawn and both handoffs — already hold a `SessionStore`, so
|
|
51
|
+
`requireOpenProject(store, ...)` needed no constructor change anywhere. A gate
|
|
52
|
+
that requires new wiring is a gate somebody forgets to wire. In each path it
|
|
53
|
+
_replaces_ the existing `getProject` + null check rather than adding a
|
|
54
|
+
round-trip, because a gate that costs something is a gate someone eventually
|
|
55
|
+
moves.
|
|
56
|
+
|
|
57
|
+
**Status moves both ways.** A thread was archived forever. A workspace is
|
|
58
|
+
long-lived and a mistaken close should not be permanent, so `reopen` exists.
|
|
59
|
+
|
|
60
|
+
**Archiving refuses rather than cascading.** A workspace with a session in
|
|
61
|
+
`active`, `locked`, `awaiting_merge` or `awaiting_hitl` throws
|
|
62
|
+
`ProjectNotEmptyError` naming what is blocking. A live session is a running
|
|
63
|
+
agent whose owner is still watching; closing its workspace out from under it
|
|
64
|
+
would strand work. Settle the sessions, then close. Re-archiving an already
|
|
65
|
+
closed, already empty workspace is a no-op that does not burn a version, so a
|
|
66
|
+
retry cannot lose a race it is not in.
|
|
67
|
+
|
|
68
|
+
Verified through the front door: the spawn case drives a real `AgentManager`,
|
|
69
|
+
so the assertion cannot pass with the gate call deleted — removing it fails two
|
|
70
|
+
tests. Calling the gate directly would only have proved the function throws.
|
|
71
|
+
|
|
72
|
+
- af9c29d: An id the SDK mints passes the schema the SDK exports.
|
|
73
|
+
|
|
74
|
+
`ProjectIdSchema` was `/^prj_[a-z0-9]+$/`. The v0.2.0 filesystem migration
|
|
75
|
+
mints `prj_legacy_<suffix>`. So the SDK's own exported validator rejected every
|
|
76
|
+
project it had itself written to disk during a migration — a host that
|
|
77
|
+
validated an inbound project id, which is the only reason the schema is
|
|
78
|
+
exported, answered "Invalid project ID format" for its own data, with nothing
|
|
79
|
+
saying the id had come from the SDK.
|
|
80
|
+
|
|
81
|
+
The schema now accepts the two shapes the SDK mints and no others:
|
|
82
|
+
`prj_<12 lowercase alphanumerics>` from `generateProjectId()`, and
|
|
83
|
+
`prj_legacy_<suffix>` from the migration. It is deliberately narrower than the
|
|
84
|
+
`ProjectId` type, which is `prj_${string}`; a host that supplies its own
|
|
85
|
+
`SessionStore` and mints its own ids should validate with its own schema.
|
|
86
|
+
|
|
87
|
+
**Breaking:** the migration now refuses a legacy `thd_*` folder whose name is
|
|
88
|
+
not a thread id, where it previously migrated it. The migration is the one
|
|
89
|
+
place a project id is built from data rather than generated, and a folder named
|
|
90
|
+
`thd_Not An Id` produced `prj_legacy_Not An Id` — structurally a `ProjectId`,
|
|
91
|
+
accepted by no validator, and thereafter a directory name in the new layout.
|
|
92
|
+
`DefaultFilesystemMigrator.migrate` throws `FilesystemMigrationError` with
|
|
93
|
+
`op: 'validate_thread_id'` and the offending path.
|
|
94
|
+
|
|
95
|
+
If your store root holds such a folder, rename it to `thd_` plus lowercase
|
|
96
|
+
alphanumerics before upgrading, or move it aside; the migration is idempotent
|
|
97
|
+
and re-running it after the rename completes normally. Folders created by the
|
|
98
|
+
SDK are always of that shape, so a store the SDK wrote is unaffected.
|
|
99
|
+
|
|
100
|
+
It refuses rather than skipping the folder. Skipping would leave that thread's
|
|
101
|
+
runs on disk and unaddressable, write the completion marker anyway, and return
|
|
102
|
+
`kind: 'migrated'` with the thread absent from the list.
|
|
103
|
+
|
|
104
|
+
Also documented, not changed: a `projectId` that `runAgent` generates names no
|
|
105
|
+
`Project` record — it takes no store and creates nothing. Carrying one into a
|
|
106
|
+
store-backed `AgentManager` is refused at the first delegation with
|
|
107
|
+
`Project <id> not found for tenant <id> — spawn rejected`, which is the
|
|
108
|
+
enforcement site behaving correctly, since delegation limits live on the
|
|
109
|
+
project. A run that has to delegate should be given the id from
|
|
110
|
+
`store.createProject()`. The `AgentIdentity` doc now says so.
|
|
111
|
+
|
|
112
|
+
### Patch Changes
|
|
113
|
+
|
|
114
|
+
- f605059: An MCP transport forgets its listeners when the session closes.
|
|
115
|
+
|
|
116
|
+
`onMessage`, `onClose` and `onError` appended to arrays that nothing ever
|
|
117
|
+
drained. `MCPClient.connect()` calls all three once each, and it is reachable
|
|
118
|
+
again after `disconnect()` — the guard only refuses when the status is already
|
|
119
|
+
`connected`. So every reconnect stacked another set on the last: after n
|
|
120
|
+
cycles one inbound message dispatched to n handlers, n-1 of them closures over
|
|
121
|
+
sessions that had ended. `rejectAllPending` and `emitLifecycle` fired n times
|
|
122
|
+
per close, and each stale closure held its old client state alive for as long
|
|
123
|
+
as the transport object did.
|
|
124
|
+
|
|
125
|
+
All three transports clear their handlers now — **after** notifying, never
|
|
126
|
+
before.
|
|
127
|
+
|
|
128
|
+
The ordering is the whole fix. `HttpSseTransport` and `StreamableHttpTransport`
|
|
129
|
+
call their close handlers inside `close()`, so they clear immediately
|
|
130
|
+
afterwards. `StdioTransport` does not: its close handlers run from the child
|
|
131
|
+
process's own `close` event, which arrives after `close()` has returned.
|
|
132
|
+
Clearing there — the obvious one-line change — would mean nothing tells
|
|
133
|
+
`MCPClient` the session ended, so its status would stay `connected` and the
|
|
134
|
+
next `connect()` would be refused with "already connected". Its handlers are
|
|
135
|
+
dropped after that event fires instead, with the never-spawned case handled
|
|
136
|
+
separately so a retry after a failed spawn does not stack a second set.
|
|
137
|
+
|
|
138
|
+
Not changed, and worth knowing: the two HTTP transports disagree about closing
|
|
139
|
+
a transport that was never connected — streamable returns early and notifies
|
|
140
|
+
nobody, http-sse notifies regardless. Making them agree changes what a host
|
|
141
|
+
observes and deserves its own decision.
|
|
142
|
+
|
|
3
143
|
## 13.1.0
|
|
4
144
|
|
|
5
145
|
### Minor Changes
|
|
@@ -13,6 +13,15 @@ import type { VerificationGateConfig } from '../types/verification/index.js';
|
|
|
13
13
|
* point: auto-generating alone would make each call its own session, which is
|
|
14
14
|
* right for a one-shot and silently wrong for a conversation — the second turn
|
|
15
15
|
* would start with no history and no shared budget, and nothing would say so.
|
|
16
|
+
*
|
|
17
|
+
* **A generated id is a correlation label, not a store handle.** `runAgent`
|
|
18
|
+
* takes no `SessionStore` and creates no records, so a `projectId` it mints
|
|
19
|
+
* names no `Project`. Carrying one into a store-backed `AgentManager` is
|
|
20
|
+
* refused at the first delegation with `Project <id> not found for tenant
|
|
21
|
+
* <id> — spawn rejected`, which is the enforcement site behaving correctly:
|
|
22
|
+
* delegation limits live on the project, and a missing project has no limits
|
|
23
|
+
* to read. A run that has to delegate should be given the id returned by
|
|
24
|
+
* `store.createProject()`.
|
|
16
25
|
*/
|
|
17
26
|
export interface AgentIdentity {
|
|
18
27
|
sessionId?: SessionId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runAgent.d.ts","sourceRoot":"","sources":["../../src/agents/runAgent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC9F,OAAO,KAAK,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAQ5E
|
|
1
|
+
{"version":3,"file":"runAgent.d.ts","sourceRoot":"","sources":["../../src/agents/runAgent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC9F,OAAO,KAAK,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAQ5E;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,aAAa;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,QAAQ,CAAC,EAAE,QAAQ,CAAA;CACnB;AAED,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACrD,gEAAgE;IAChE,QAAQ,EAAE,WAAW,CAAA;IAErB,kEAAkE;IAClE,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CAAA;IAE1B,yBAAyB;IACzB,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB;;;;;;;;OAQG;IACH,KAAK,EAAE,MAAM,CAAA;IAEb,KAAK,CAAC,EAAE,oBAAoB,CAAA;IAE5B;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,KAAK,EAAE,CAAA;IAEhB;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,sBAAsB,CAAA;IAEzC,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAEzB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,MAAM,CAAC,EAAE,eAAe,CAAA;IAExB,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,QAAQ,CAAC,EAAE,gBAAgB,CAAA;CAC3B;AAED,MAAM,WAAW,cAAc;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IAEnC,qEAAqE;IACrE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;IAEjB;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAA;CAC1C;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAA;AACxC,eAAO,MAAM,oBAAoB,SAAU,CAAA;AAC3C,eAAO,MAAM,kBAAkB,SAAU,CAAA;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA6ChF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runAgent.js","sourceRoot":"","sources":["../../src/agents/runAgent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAQtD,OAAO,EACN,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,GAChB,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"runAgent.js","sourceRoot":"","sources":["../../src/agents/runAgent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a-transport-forgets-its-listeners.test.d.ts","sourceRoot":"","sources":["../../../../src/connector/mcp/__tests__/a-transport-forgets-its-listeners.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { HttpSseTransport } from '../http-sse.js';
|
|
3
|
+
import { StreamableHttpTransport } from '../streamable-http.js';
|
|
4
|
+
/**
|
|
5
|
+
* Handler registration was append-only and nothing ever dropped it.
|
|
6
|
+
*
|
|
7
|
+
* `MCPClient.connect()` calls `onMessage`, `onClose` and `onError` once each,
|
|
8
|
+
* and it is reachable again after `disconnect()` — the guard only refuses when
|
|
9
|
+
* the status is already `connected`. So every reconnect stacked another set on
|
|
10
|
+
* the last: after n cycles one inbound message dispatched to n handlers, n-1
|
|
11
|
+
* of them closures over dead sessions. `rejectAllPending` and `emitLifecycle`
|
|
12
|
+
* fired n times per close, and the stale closures held their old client state
|
|
13
|
+
* alive for as long as the transport object did.
|
|
14
|
+
*
|
|
15
|
+
* The two HTTP transports are exercised here because they notify inside
|
|
16
|
+
* `close()`. `StdioTransport` notifies from the child process's own `close`
|
|
17
|
+
* event, so its handlers deliberately outlive the `close()` call and are
|
|
18
|
+
* dropped after that event fires — clearing them earlier would leave the
|
|
19
|
+
* client believing it was still connected, and its next `connect()` would be
|
|
20
|
+
* refused with "already connected". That ordering is the reason the obvious
|
|
21
|
+
* one-line fix is wrong there.
|
|
22
|
+
*/
|
|
23
|
+
const MESSAGE = { jsonrpc: '2.0', method: 'ping' };
|
|
24
|
+
/**
|
|
25
|
+
* `open` puts the transport in the state where `close()` notifies.
|
|
26
|
+
*
|
|
27
|
+
* They differ, and the difference is real rather than a test artefact:
|
|
28
|
+
* `StreamableHttpTransport.close()` returns early when it was never connected,
|
|
29
|
+
* `HttpSseTransport.close()` notifies regardless. Streamable's `connect()`
|
|
30
|
+
* does no I/O — it sets a flag — so opening it here reaches no network. The
|
|
31
|
+
* divergence itself is left alone; making the two agree changes what a host
|
|
32
|
+
* observes and deserves its own decision.
|
|
33
|
+
*/
|
|
34
|
+
const IMPLEMENTATIONS = [
|
|
35
|
+
[
|
|
36
|
+
'http-sse',
|
|
37
|
+
() => new HttpSseTransport({ url: 'http://127.0.0.1:1/mcp' }),
|
|
38
|
+
async () => { },
|
|
39
|
+
],
|
|
40
|
+
[
|
|
41
|
+
'streamable-http',
|
|
42
|
+
() => new StreamableHttpTransport({ url: 'http://127.0.0.1:1/mcp' }),
|
|
43
|
+
async (t) => {
|
|
44
|
+
await t.connect();
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
];
|
|
48
|
+
describe.each(IMPLEMENTATIONS)('a %s transport forgets its listeners on close', (_n, build, open) => {
|
|
49
|
+
it('notifies each close handler exactly once per registration', async () => {
|
|
50
|
+
const transport = build();
|
|
51
|
+
await open(transport);
|
|
52
|
+
let closes = 0;
|
|
53
|
+
transport.onClose(() => {
|
|
54
|
+
closes++;
|
|
55
|
+
});
|
|
56
|
+
await transport.close();
|
|
57
|
+
// A second registration is what a reconnect does. If the first
|
|
58
|
+
// survived the close, this close fires twice.
|
|
59
|
+
await open(transport);
|
|
60
|
+
transport.onClose(() => {
|
|
61
|
+
closes++;
|
|
62
|
+
});
|
|
63
|
+
await transport.close();
|
|
64
|
+
expect(closes).toBe(2);
|
|
65
|
+
});
|
|
66
|
+
it('does not dispatch a message to a handler from a closed session', async () => {
|
|
67
|
+
// The consequence a host actually sees: work done twice, by a
|
|
68
|
+
// closure that belongs to a session that ended.
|
|
69
|
+
const seen = [];
|
|
70
|
+
const transport = build();
|
|
71
|
+
await open(transport);
|
|
72
|
+
transport.onMessage(() => seen.push('first'));
|
|
73
|
+
await transport.close();
|
|
74
|
+
await open(transport);
|
|
75
|
+
transport.onMessage(() => seen.push('second'));
|
|
76
|
+
dispatch(transport, MESSAGE);
|
|
77
|
+
expect(seen).toEqual(['second']);
|
|
78
|
+
});
|
|
79
|
+
it('still notifies the handlers registered for the session being closed', async () => {
|
|
80
|
+
// The failure mode of clearing too eagerly: close arrives, nobody is
|
|
81
|
+
// told, and the client believes it is still connected.
|
|
82
|
+
const transport = build();
|
|
83
|
+
await open(transport);
|
|
84
|
+
const order = [];
|
|
85
|
+
transport.onClose(() => order.push('notified'));
|
|
86
|
+
await transport.close();
|
|
87
|
+
expect(order).toEqual(['notified']);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
/**
|
|
91
|
+
* Reach the private dispatch the way an inbound frame does. Both transports
|
|
92
|
+
* loop `messageHandlers` from their own parse path; there is no public method
|
|
93
|
+
* that pushes a message in, and adding one for a test would be a surface
|
|
94
|
+
* nobody asked for.
|
|
95
|
+
*/
|
|
96
|
+
function dispatch(transport, message) {
|
|
97
|
+
const handlers = transport.messageHandlers;
|
|
98
|
+
for (const handler of handlers)
|
|
99
|
+
handler(message);
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=a-transport-forgets-its-listeners.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a-transport-forgets-its-listeners.test.js","sourceRoot":"","sources":["../../../../src/connector/mcp/__tests__/a-transport-forgets-its-listeners.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,16 @@ export declare class HttpSseTransport implements MCPTransport {
|
|
|
12
12
|
constructor(config: MCPHttpSseTransportConfig);
|
|
13
13
|
connect(): Promise<void>;
|
|
14
14
|
close(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Drop every registered handler.
|
|
17
|
+
*
|
|
18
|
+
* `onMessage`/`onClose`/`onError` append, and `MCPClient.connect()` calls
|
|
19
|
+
* all three every time — and is reachable again after `disconnect()`. So
|
|
20
|
+
* without this each reconnect duplicated the set, and after n cycles one
|
|
21
|
+
* inbound message dispatched to n handlers, n-1 of them closures over dead
|
|
22
|
+
* sessions that kept their old client state alive.
|
|
23
|
+
*/
|
|
24
|
+
private clearHandlers;
|
|
15
25
|
send(message: MCPJsonRpcMessage): Promise<void>;
|
|
16
26
|
onMessage(handler: (message: MCPJsonRpcMessage) => void): void;
|
|
17
27
|
onClose(handler: () => void): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-sse.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/http-sse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,MAAM,gCAAgC,CAAA;AAkBvC,qBAAa,gBAAiB,YAAW,YAAY;IAUxC,OAAO,CAAC,QAAQ,CAAC,MAAM;IATnC,OAAO,CAAC,eAAe,CAAkD;IACzE,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,GAAG,CAAQ;gBAEU,MAAM,EAAE,yBAAyB;IAOxD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IASxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"http-sse.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/http-sse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,yBAAyB,EACzB,iBAAiB,EACjB,YAAY,EACZ,MAAM,gCAAgC,CAAA;AAkBvC,qBAAa,gBAAiB,YAAW,YAAY;IAUxC,OAAO,CAAC,QAAQ,CAAC,MAAM;IATnC,OAAO,CAAC,eAAe,CAAkD;IACzE,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,GAAG,CAAQ;gBAEU,MAAM,EAAE,yBAAyB;IAOxD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IASxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAMf,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAiCrD,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI;IAI9D,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI;IAIlC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI9C,WAAW,IAAI,OAAO;YAIR,QAAQ;YAUR,SAAS;CAsCvB"}
|
|
@@ -44,6 +44,22 @@ export class HttpSseTransport {
|
|
|
44
44
|
this.abortController = null;
|
|
45
45
|
for (const handler of this.closeHandlers)
|
|
46
46
|
handler();
|
|
47
|
+
// After the notification, never before it.
|
|
48
|
+
this.clearHandlers();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Drop every registered handler.
|
|
52
|
+
*
|
|
53
|
+
* `onMessage`/`onClose`/`onError` append, and `MCPClient.connect()` calls
|
|
54
|
+
* all three every time — and is reachable again after `disconnect()`. So
|
|
55
|
+
* without this each reconnect duplicated the set, and after n cycles one
|
|
56
|
+
* inbound message dispatched to n handlers, n-1 of them closures over dead
|
|
57
|
+
* sessions that kept their old client state alive.
|
|
58
|
+
*/
|
|
59
|
+
clearHandlers() {
|
|
60
|
+
this.messageHandlers = [];
|
|
61
|
+
this.closeHandlers = [];
|
|
62
|
+
this.errorHandlers = [];
|
|
47
63
|
}
|
|
48
64
|
async send(message) {
|
|
49
65
|
if (!this.connected) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-sse.js","sourceRoot":"","sources":["../../../src/connector/mcp/http-sse.ts"],"names":[],"mappings":"AAKA,OAAO,EAAe,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAElE;;;;;;GAMG;AACH,SAAS,oBAAoB,CAAC,KAAa;IAC1C,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,CAAA;IACtB,OAAO,GAAG,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QAC1C,GAAG,EAAE,CAAA;IACN,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AAC3B,CAAC;AAED,MAAM,OAAO,gBAAgB;IAUC;IATrB,eAAe,GAAgD,EAAE,CAAA;IACjE,aAAa,GAAsB,EAAE,CAAA;IACrC,aAAa,GAAkC,EAAE,CAAA;IACjD,SAAS,GAAG,KAAK,CAAA;IACjB,eAAe,GAA2B,IAAI,CAAA;IAC9C,MAAM,CAAQ;IACd,OAAO,CAAQ;IACf,GAAG,CAAQ;IAEnB,YAA6B,MAAiC;QAAjC,WAAM,GAAN,MAAM,CAA2B;QAC7D,MAAM,IAAI,GAAG,oBAAoB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC7C,IAAI,CAAC,MAAM,GAAG,GAAG,IAAI,MAAM,CAAA;QAC3B,IAAI,CAAC,OAAO,GAAG,GAAG,IAAI,UAAU,CAAA;QAChC,IAAI,CAAC,GAAG,GAAG,aAAa,EAAE,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAA;IACpE,CAAC;IAED,KAAK,CAAC,OAAO;QACZ,IAAI,IAAI,CAAC,SAAS;YAAE,OAAM;QAE1B,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,EAAE,CAAA;QAC5C,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAA;QACrB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QACrB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,iCAAiC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAA;IAClE,CAAC;IAED,KAAK,CAAC,KAAK;QACV,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;QACtB,IAAI,CAAC,eAAe,EAAE,KAAK,EAAE,CAAA;QAC7B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAA;QAC3B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,aAAa;YAAE,OAAO,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"http-sse.js","sourceRoot":"","sources":["../../../src/connector/mcp/http-sse.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,11 +6,23 @@ export declare class StdioTransport implements MCPTransport {
|
|
|
6
6
|
private closeHandlers;
|
|
7
7
|
private errorHandlers;
|
|
8
8
|
private connected;
|
|
9
|
+
/** True between kill and the process's own `close` event. */
|
|
10
|
+
private exitPending;
|
|
9
11
|
private buffer;
|
|
10
12
|
private log;
|
|
11
13
|
constructor(config: MCPStdioTransportConfig);
|
|
12
14
|
connect(): Promise<void>;
|
|
13
15
|
close(): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Drop every registered handler.
|
|
18
|
+
*
|
|
19
|
+
* `onMessage`/`onClose`/`onError` append, and `MCPClient.connect()` calls
|
|
20
|
+
* all three every time — and is reachable again after `disconnect()`. So
|
|
21
|
+
* without this each reconnect duplicated the set, and after n cycles one
|
|
22
|
+
* inbound message dispatched to n handlers, n-1 of them closures over dead
|
|
23
|
+
* sessions that kept their old client state alive.
|
|
24
|
+
*/
|
|
25
|
+
private clearHandlers;
|
|
14
26
|
send(message: MCPJsonRpcMessage): Promise<void>;
|
|
15
27
|
onMessage(handler: (message: MCPJsonRpcMessage) => void): void;
|
|
16
28
|
onClose(handler: () => void): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/stdio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,MAAM,gCAAgC,CAAA;AAGvC,qBAAa,cAAe,YAAW,YAAY;
|
|
1
|
+
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/stdio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,MAAM,gCAAgC,CAAA;AAGvC,qBAAa,cAAe,YAAW,YAAY;IAWtC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAVnC,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,eAAe,CAAkD;IACzE,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,SAAS,CAAQ;IACzB,6DAA6D;IAC7D,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,GAAG,CAAQ;gBAEU,MAAM,EAAE,uBAAuB;IAItD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAuCxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAMf,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrD,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI;IAI9D,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI;IAIlC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI9C,WAAW,IAAI,OAAO;IAItB,OAAO,CAAC,aAAa;CAerB"}
|
|
@@ -7,6 +7,8 @@ export class StdioTransport {
|
|
|
7
7
|
closeHandlers = [];
|
|
8
8
|
errorHandlers = [];
|
|
9
9
|
connected = false;
|
|
10
|
+
/** True between kill and the process's own `close` event. */
|
|
11
|
+
exitPending = false;
|
|
10
12
|
buffer = '';
|
|
11
13
|
log;
|
|
12
14
|
constructor(config) {
|
|
@@ -33,6 +35,10 @@ export class StdioTransport {
|
|
|
33
35
|
this.log.info(`MCP server process exited with code ${code}`);
|
|
34
36
|
for (const handler of this.closeHandlers)
|
|
35
37
|
handler();
|
|
38
|
+
// After the notification, not before it: this event is what tells
|
|
39
|
+
// `MCPClient` the session ended.
|
|
40
|
+
this.exitPending = false;
|
|
41
|
+
this.clearHandlers();
|
|
36
42
|
});
|
|
37
43
|
this.process.on('error', (err) => {
|
|
38
44
|
this.connected = false;
|
|
@@ -43,12 +49,38 @@ export class StdioTransport {
|
|
|
43
49
|
this.log.info(`StdioTransport connected: ${this.config.command} ${(this.config.args ?? []).join(' ')}`);
|
|
44
50
|
}
|
|
45
51
|
async close() {
|
|
46
|
-
if (!this.process)
|
|
52
|
+
if (!this.process) {
|
|
53
|
+
// Nothing was spawned, or the exit already ran. No `close` event is
|
|
54
|
+
// coming, so this is the only chance to drop what `connect()`
|
|
55
|
+
// registered — and without it a retry after a failed spawn stacks a
|
|
56
|
+
// second set of handlers on the first.
|
|
57
|
+
if (!this.exitPending)
|
|
58
|
+
this.clearHandlers();
|
|
47
59
|
return;
|
|
60
|
+
}
|
|
48
61
|
this.connected = false;
|
|
62
|
+
this.exitPending = true;
|
|
49
63
|
this.process.kill('SIGTERM');
|
|
50
64
|
this.process = null;
|
|
51
65
|
this.buffer = '';
|
|
66
|
+
// The handlers deliberately survive this call. `process.on('close')`
|
|
67
|
+
// fires them when the process actually exits, and dropping them here
|
|
68
|
+
// would leave `MCPClient` believing it is still connected — so its next
|
|
69
|
+
// `connect()` would be refused with "already connected".
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Drop every registered handler.
|
|
73
|
+
*
|
|
74
|
+
* `onMessage`/`onClose`/`onError` append, and `MCPClient.connect()` calls
|
|
75
|
+
* all three every time — and is reachable again after `disconnect()`. So
|
|
76
|
+
* without this each reconnect duplicated the set, and after n cycles one
|
|
77
|
+
* inbound message dispatched to n handlers, n-1 of them closures over dead
|
|
78
|
+
* sessions that kept their old client state alive.
|
|
79
|
+
*/
|
|
80
|
+
clearHandlers() {
|
|
81
|
+
this.messageHandlers = [];
|
|
82
|
+
this.closeHandlers = [];
|
|
83
|
+
this.errorHandlers = [];
|
|
52
84
|
}
|
|
53
85
|
async send(message) {
|
|
54
86
|
if (!this.process?.stdin?.writable) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../../src/connector/mcp/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAM7D,OAAO,EAAe,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAElE,MAAM,OAAO,cAAc;
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../../src/connector/mcp/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAM7D,OAAO,EAAe,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAElE,MAAM,OAAO,cAAc;IAWG;IAVrB,OAAO,GAAwB,IAAI,CAAA;IACnC,eAAe,GAAgD,EAAE,CAAA;IACjE,aAAa,GAAsB,EAAE,CAAA;IACrC,aAAa,GAAkC,EAAE,CAAA;IACjD,SAAS,GAAG,KAAK,CAAA;IACzB,6DAA6D;IACrD,WAAW,GAAG,KAAK,CAAA;IACnB,MAAM,GAAG,EAAE,CAAA;IACX,GAAG,CAAQ;IAEnB,YAA6B,MAA+B;QAA/B,WAAM,GAAN,MAAM,CAAyB;QAC3D,IAAI,CAAC,GAAG,GAAG,aAAa,EAAE,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC,CAAA;IAClE,CAAC;IAED,KAAK,CAAC,OAAO;QACZ,IAAI,IAAI,CAAC,SAAS;YAAE,OAAM;QAE1B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE;YACjE,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;YAC3C,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG;YACpB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAC/B,CAAC,CAAA;QAEF,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACjD,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;YACtC,IAAI,CAAC,aAAa,EAAE,CAAA;QACrB,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACjD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,sBAAsB,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;QACtE,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACjC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;YACtB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,uCAAuC,IAAI,EAAE,CAAC,CAAA;YAC5D,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,aAAa;gBAAE,OAAO,EAAE,CAAA;YACnD,kEAAkE;YAClE,iCAAiC;YACjC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAA;YACxB,IAAI,CAAC,aAAa,EAAE,CAAA;QACrB,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAChC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;YACtB,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,aAAa;gBAAE,OAAO,CAAC,GAAG,CAAC,CAAA;QACvD,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QACrB,IAAI,CAAC,GAAG,CAAC,IAAI,CACZ,6BAA6B,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CACxF,CAAA;IACF,CAAC;IAED,KAAK,CAAC,KAAK;QACV,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YACnB,oEAAoE;YACpE,8DAA8D;YAC9D,oEAAoE;YACpE,uCAAuC;YACvC,IAAI,CAAC,IAAI,CAAC,WAAW;gBAAE,IAAI,CAAC,aAAa,EAAE,CAAA;YAC3C,OAAM;QACP,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;QACtB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAA;QACvB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QACnB,IAAI,CAAC,MAAM,GAAG,EAAE,CAAA;QAChB,qEAAqE;QACrE,qEAAqE;QACrE,wEAAwE;QACxE,yDAAyD;IAC1D,CAAC;IAED;;;;;;;;OAQG;IACK,aAAa;QACpB,IAAI,CAAC,eAAe,GAAG,EAAE,CAAA;QACzB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAA;QACvB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAA0B;QACpC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAA;QACvE,CAAC;QACD,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAA;QAC3C,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC/B,CAAC;IAED,SAAS,CAAC,OAA6C;QACtD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACnC,CAAC;IAED,OAAO,CAAC,OAAmB;QAC1B,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACjC,CAAC;IAED,OAAO,CAAC,OAA+B;QACtC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACjC,CAAC;IAED,WAAW;QACV,OAAO,IAAI,CAAC,SAAS,CAAA;IACtB,CAAC;IAEO,aAAa;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACrC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAA;QAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;YAC3B,IAAI,CAAC,OAAO;gBAAE,SAAQ;YACtB,IAAI,CAAC;gBACJ,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAsB,CAAA;gBACxD,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,eAAe;oBAAE,OAAO,CAAC,OAAO,CAAC,CAAA;YAC7D,CAAC;YAAC,MAAM,CAAC;gBACR,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,6CAA6C,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;YACpF,CAAC;QACF,CAAC;IACF,CAAC;CACD"}
|
|
@@ -10,6 +10,8 @@ export declare class StreamableHttpTransport implements MCPTransport {
|
|
|
10
10
|
constructor(config: MCPStreamableHttpTransportConfig);
|
|
11
11
|
connect(): Promise<void>;
|
|
12
12
|
close(): Promise<void>;
|
|
13
|
+
/** See {@link StdioTransport} — the same append-only handler leak. */
|
|
14
|
+
private clearHandlers;
|
|
13
15
|
send(message: MCPJsonRpcMessage): Promise<void>;
|
|
14
16
|
onMessage(handler: (message: MCPJsonRpcMessage) => void): void;
|
|
15
17
|
onClose(handler: () => void): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamable-http.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/streamable-http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,iBAAiB,EACjB,gCAAgC,EAChC,YAAY,EACZ,MAAM,gCAAgC,CAAA;AAKvC,qBAAa,uBAAwB,YAAW,YAAY;IAQ/C,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPnC,OAAO,CAAC,eAAe,CAAkD;IACzE,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,GAAG,CAAQ;gBAEU,MAAM,EAAE,gCAAgC;IAI/D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"streamable-http.d.ts","sourceRoot":"","sources":["../../../src/connector/mcp/streamable-http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,iBAAiB,EACjB,gCAAgC,EAChC,YAAY,EACZ,MAAM,gCAAgC,CAAA;AAKvC,qBAAa,uBAAwB,YAAW,YAAY;IAQ/C,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPnC,OAAO,CAAC,eAAe,CAAkD;IACzE,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,GAAG,CAAQ;gBAEU,MAAM,EAAE,gCAAgC;IAI/D,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B,sEAAsE;IACtE,OAAO,CAAC,aAAa;IAMf,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCrD,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,GAAG,IAAI;IAI9D,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI;IAIlC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI9C,WAAW,IAAI,OAAO;IAItB,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,gBAAgB;YAQV,wBAAwB;CAatC"}
|
|
@@ -19,11 +19,23 @@ export class StreamableHttpTransport {
|
|
|
19
19
|
this.log.info(`StreamableHttpTransport connected to ${this.config.url}`);
|
|
20
20
|
}
|
|
21
21
|
async close() {
|
|
22
|
-
if (!this.connected)
|
|
22
|
+
if (!this.connected) {
|
|
23
|
+
// Never connected, or already closed: nothing will notify, so this is
|
|
24
|
+
// the only chance to drop what `connect()` registered before it failed.
|
|
25
|
+
this.clearHandlers();
|
|
23
26
|
return;
|
|
27
|
+
}
|
|
24
28
|
this.connected = false;
|
|
25
29
|
for (const handler of this.closeHandlers)
|
|
26
30
|
handler();
|
|
31
|
+
// After the notification, never before it.
|
|
32
|
+
this.clearHandlers();
|
|
33
|
+
}
|
|
34
|
+
/** See {@link StdioTransport} — the same append-only handler leak. */
|
|
35
|
+
clearHandlers() {
|
|
36
|
+
this.messageHandlers = [];
|
|
37
|
+
this.closeHandlers = [];
|
|
38
|
+
this.errorHandlers = [];
|
|
27
39
|
}
|
|
28
40
|
async send(message) {
|
|
29
41
|
if (!this.connected) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamable-http.js","sourceRoot":"","sources":["../../../src/connector/mcp/streamable-http.ts"],"names":[],"mappings":"AAKA,OAAO,EAAe,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAElE,MAAM,kBAAkB,GAAG,MAAM,CAAA;AAEjC,MAAM,OAAO,uBAAuB;IAQN;IAPrB,eAAe,GAAgD,EAAE,CAAA;IACjE,aAAa,GAAsB,EAAE,CAAA;IACrC,aAAa,GAAkC,EAAE,CAAA;IACjD,SAAS,GAAG,KAAK,CAAA;IACjB,SAAS,GAAkB,IAAI,CAAA;IAC/B,GAAG,CAAQ;IAEnB,YAA6B,MAAwC;QAAxC,WAAM,GAAN,MAAM,CAAkC;QACpE,IAAI,CAAC,GAAG,GAAG,aAAa,EAAE,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,yBAAyB,EAAE,CAAC,CAAA;IAC3E,CAAC;IAED,KAAK,CAAC,OAAO;QACZ,IAAI,IAAI,CAAC,SAAS;YAAE,OAAM;QAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QACrB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,wCAAwC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAA;IACzE,CAAC;IAED,KAAK,CAAC,KAAK;QACV,IAAI,CAAC,IAAI,CAAC,SAAS;
|
|
1
|
+
{"version":3,"file":"streamable-http.js","sourceRoot":"","sources":["../../../src/connector/mcp/streamable-http.ts"],"names":[],"mappings":"AAKA,OAAO,EAAe,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAElE,MAAM,kBAAkB,GAAG,MAAM,CAAA;AAEjC,MAAM,OAAO,uBAAuB;IAQN;IAPrB,eAAe,GAAgD,EAAE,CAAA;IACjE,aAAa,GAAsB,EAAE,CAAA;IACrC,aAAa,GAAkC,EAAE,CAAA;IACjD,SAAS,GAAG,KAAK,CAAA;IACjB,SAAS,GAAkB,IAAI,CAAA;IAC/B,GAAG,CAAQ;IAEnB,YAA6B,MAAwC;QAAxC,WAAM,GAAN,MAAM,CAAkC;QACpE,IAAI,CAAC,GAAG,GAAG,aAAa,EAAE,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,yBAAyB,EAAE,CAAC,CAAA;IAC3E,CAAC;IAED,KAAK,CAAC,OAAO;QACZ,IAAI,IAAI,CAAC,SAAS;YAAE,OAAM;QAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QACrB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,wCAAwC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAA;IACzE,CAAC;IAED,KAAK,CAAC,KAAK;QACV,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACrB,sEAAsE;YACtE,wEAAwE;YACxE,IAAI,CAAC,aAAa,EAAE,CAAA;YACpB,OAAM;QACP,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;QACtB,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,aAAa;YAAE,OAAO,EAAE,CAAA;QACnD,2CAA2C;QAC3C,IAAI,CAAC,aAAa,EAAE,CAAA;IACrB,CAAC;IAED,sEAAsE;IAC9D,aAAa;QACpB,IAAI,CAAC,eAAe,GAAG,EAAE,CAAA;QACzB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAA;QACvB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAA0B;QACpC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAA;QAC1D,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;QACxC,MAAM,OAAO,GAAG,UAAU,CACzB,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EACxB,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,kBAAkB,CAC3C,CAAA;QAED,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;gBAC7C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE;gBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;gBAC7B,MAAM,EAAE,UAAU,CAAC,MAAM;aACzB,CAAC,CAAA;YAEF,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAA;YAE/B,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAClB,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;YAC5F,CAAC;YAED,MAAM,IAAI,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAA;QAC9C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;YACjE,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,aAAa;gBAAE,OAAO,CAAC,KAAK,CAAC,CAAA;YACxD,MAAM,KAAK,CAAA;QACZ,CAAC;gBAAS,CAAC;YACV,YAAY,CAAC,OAAO,CAAC,CAAA;QACtB,CAAC;IACF,CAAC;IAED,SAAS,CAAC,OAA6C;QACtD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACnC,CAAC;IAED,OAAO,CAAC,OAAmB;QAC1B,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACjC,CAAC;IAED,OAAO,CAAC,OAA+B;QACtC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACjC,CAAC;IAED,WAAW;QACV,OAAO,IAAI,CAAC,SAAS,CAAA;IACtB,CAAC;IAEO,YAAY;QACnB,MAAM,OAAO,GAA2B;YACvC,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,qCAAqC;YAC7C,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO;SACtB,CAAA;QAED,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,SAAS,CAAA;QAC3C,CAAC;QAED,OAAO,OAAO,CAAA;IACf,CAAC;IAEO,gBAAgB,CAAC,QAAkB;QAC1C,MAAM,SAAS,GACd,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;QACjF,IAAI,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAC3B,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,wBAAwB,CAAC,QAAkB;QACxD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAClC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAAE,OAAM;QAEpC,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAA;QAC9D,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,mBAAmB,CAAC;YACzD,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC;YACxB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAA;QAE1B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAChC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,eAAe;gBAAE,OAAO,CAAC,OAAO,CAAC,CAAA;QAC7D,CAAC;IACF,CAAC;CACD;AAED,SAAS,iBAAiB,CAAC,GAAW;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4C,CAAA;IACzE,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;AACjD,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW;IACpC,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IAC7C,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACxC,MAAM,QAAQ,GAAwB,EAAE,CAAA;IAExC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,KAAK;aACrB,KAAK,CAAC,IAAI,CAAC;aACX,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;aAC1C,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,CAAC,CAAA;QAEvD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,SAAQ;QAEpC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAA;QACxC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,KAAK,QAAQ;YAAE,SAAQ;QAEpD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4C,CAAA;QAC1E,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAA;QACzB,CAAC;aAAM,CAAC;YACP,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACtB,CAAC;IACF,CAAC;IAED,OAAO,QAAQ,CAAA;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"an-id-the-sdk-mints-passes-its-own-schema.test.d.ts","sourceRoot":"","sources":["../../../src/contracts/__tests__/an-id-the-sdk-mints-passes-its-own-schema.test.ts"],"names":[],"mappings":""}
|