@ifc-lite/mcp 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/context.d.ts +13 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +21 -4
- package/dist/server.js.map +1 -1
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/layer-access.d.ts +18 -0
- package/dist/tools/layer-access.d.ts.map +1 -0
- package/dist/tools/layer-access.js +91 -0
- package/dist/tools/layer-access.js.map +1 -0
- package/dist/tools/layer-ops.d.ts +52 -0
- package/dist/tools/layer-ops.d.ts.map +1 -0
- package/dist/tools/layer-ops.js +130 -0
- package/dist/tools/layer-ops.js.map +1 -0
- package/dist/tools/layer-review.d.ts +3 -0
- package/dist/tools/layer-review.d.ts.map +1 -0
- package/dist/tools/layer-review.js +347 -0
- package/dist/tools/layer-review.js.map +1 -0
- package/dist/tools/layer-store.d.ts +96 -0
- package/dist/tools/layer-store.d.ts.map +1 -0
- package/dist/tools/layer-store.js +271 -0
- package/dist/tools/layer-store.js.map +1 -0
- package/dist/tools/layer.d.ts +19 -0
- package/dist/tools/layer.d.ts.map +1 -0
- package/dist/tools/layer.js +257 -0
- package/dist/tools/layer.js.map +1 -0
- package/dist/transport/http.d.ts +11 -1
- package/dist/transport/http.d.ts.map +1 -1
- package/dist/transport/http.js +38 -3
- package/dist/transport/http.js.map +1 -1
- package/package.json +19 -14
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* In-memory draft / layer / review workspace backing the agent draft-layer
|
|
6
|
+
* tool family (docs/architecture/layer-prs/06-agents.md).
|
|
7
|
+
*
|
|
8
|
+
* Drafts are keyed by transport session id (#1030) and disposed with the
|
|
9
|
+
* session; published layers, refs, and reviews are process-shared so
|
|
10
|
+
* other principals' sessions can build on and review them. Tests call
|
|
11
|
+
* `resetLayerWorkspace()` for isolation. A draft is a CRDT session (Y.Doc
|
|
12
|
+
* seeded with the resolved base stack) plus the baseline snapshot
|
|
13
|
+
* `publishLayer` diffs against.
|
|
14
|
+
*/
|
|
15
|
+
import { randomUUID } from 'node:crypto';
|
|
16
|
+
import * as Y from 'yjs';
|
|
17
|
+
import { createCollabDoc, createEntity, deleteAttribute, deleteEntity, hasEntity, removeChild, removeInherit, setAttribute, setChild, setInherit, } from '@ifc-lite/collab';
|
|
18
|
+
import { IFCLITE_ATTR, ATTR, computeStackHash } from '@ifc-lite/ifcx';
|
|
19
|
+
import { ToolErrorCode, ToolExecutionError } from '../errors.js';
|
|
20
|
+
export function createLayerWorkspace() {
|
|
21
|
+
return {
|
|
22
|
+
drafts: new Map(),
|
|
23
|
+
layers: new Map(),
|
|
24
|
+
refs: new Map([['main', []]]),
|
|
25
|
+
reviews: new Map(),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
// Storage model (#1030). Drafts are private CRDT sessions, so they are
|
|
29
|
+
// the per-transport-session state: keyed by session id, disposed with the
|
|
30
|
+
// session. Published layers, refs, and reviews are the collaboration
|
|
31
|
+
// surface — content-addressed immutable layers, shared branch heads, and
|
|
32
|
+
// reviews that *other* principals must be able to act on from their own
|
|
33
|
+
// HTTP sessions (each principal necessarily holds a different session,
|
|
34
|
+
// since the transport rejects scope mismatches) — so they live in one
|
|
35
|
+
// process-wide store, gated by the visibility checks below. stdio /
|
|
36
|
+
// in-process transports carry no session id and use the local draft
|
|
37
|
+
// space — registry-less local mode (10-registry.md); durable,
|
|
38
|
+
// registry-backed persistence stays future work.
|
|
39
|
+
const shared = {
|
|
40
|
+
layers: new Map(),
|
|
41
|
+
refs: new Map([['main', []]]),
|
|
42
|
+
reviews: new Map(),
|
|
43
|
+
};
|
|
44
|
+
const draftSpaces = new Map();
|
|
45
|
+
/** Draft-space key for transports without a session id (stdio, in-process, tests). */
|
|
46
|
+
const LOCAL_WORKSPACE_KEY = 'local';
|
|
47
|
+
export function getLayerWorkspace(sessionId) {
|
|
48
|
+
const key = sessionId ?? LOCAL_WORKSPACE_KEY;
|
|
49
|
+
let drafts = draftSpaces.get(key);
|
|
50
|
+
if (!drafts) {
|
|
51
|
+
drafts = new Map();
|
|
52
|
+
draftSpaces.set(key, drafts);
|
|
53
|
+
}
|
|
54
|
+
return { drafts, layers: shared.layers, refs: shared.refs, reviews: shared.reviews };
|
|
55
|
+
}
|
|
56
|
+
/** Drafts hold live Y.Docs — destroy them or the CRDT state lingers. */
|
|
57
|
+
function destroyDrafts(drafts) {
|
|
58
|
+
for (const draft of drafts.values())
|
|
59
|
+
draft.doc.destroy();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Drop a session's draft space when the transport session ends. Layers,
|
|
63
|
+
* refs, and reviews deliberately survive — they are the published shared
|
|
64
|
+
* record other sessions keep building on.
|
|
65
|
+
*/
|
|
66
|
+
export function disposeLayerWorkspace(sessionId) {
|
|
67
|
+
const drafts = draftSpaces.get(sessionId);
|
|
68
|
+
if (!drafts)
|
|
69
|
+
return;
|
|
70
|
+
destroyDrafts(drafts);
|
|
71
|
+
draftSpaces.delete(sessionId);
|
|
72
|
+
}
|
|
73
|
+
/** Test hook: drop all draft spaces and shared state; return a fresh local workspace. */
|
|
74
|
+
export function resetLayerWorkspace() {
|
|
75
|
+
for (const drafts of draftSpaces.values())
|
|
76
|
+
destroyDrafts(drafts);
|
|
77
|
+
draftSpaces.clear();
|
|
78
|
+
shared.layers.clear();
|
|
79
|
+
shared.reviews.clear();
|
|
80
|
+
shared.refs.clear();
|
|
81
|
+
shared.refs.set('main', []);
|
|
82
|
+
return getLayerWorkspace();
|
|
83
|
+
}
|
|
84
|
+
/** Files for a ref, erroring on dangling layer ids (corrupt workspace). */
|
|
85
|
+
export function refLayerFiles(ws, name) {
|
|
86
|
+
const ids = ws.refs.get(name);
|
|
87
|
+
if (!ids) {
|
|
88
|
+
throw new ToolExecutionError({
|
|
89
|
+
code: ToolErrorCode.ENTITY_NOT_FOUND,
|
|
90
|
+
message: `Unknown ref '${name}'.`,
|
|
91
|
+
details: { refs: Array.from(ws.refs.keys()) },
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return ids.map((id) => {
|
|
95
|
+
const file = ws.layers.get(id);
|
|
96
|
+
if (!file) {
|
|
97
|
+
throw new ToolExecutionError({
|
|
98
|
+
code: ToolErrorCode.INTERNAL_ERROR,
|
|
99
|
+
message: `Ref '${name}' points at unknown layer ${id}.`,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return file;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/** Resolve a base spec (ref name or layer id; absent → no base). */
|
|
106
|
+
export function resolveBase(ws, ref) {
|
|
107
|
+
if (ref === undefined)
|
|
108
|
+
return { base: null, files: [] };
|
|
109
|
+
if (ws.refs.has(ref)) {
|
|
110
|
+
const ids = ws.refs.get(ref) ?? [];
|
|
111
|
+
const files = refLayerFiles(ws, ref);
|
|
112
|
+
return {
|
|
113
|
+
base: ids.length > 0 ? { kind: 'stack', id: computeStackHash(ids) } : null,
|
|
114
|
+
files,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const layer = ws.layers.get(ref);
|
|
118
|
+
if (layer) {
|
|
119
|
+
// Seed from the full ancestor stack when the layer sits inside a ref
|
|
120
|
+
// history — a lone delta would lose all earlier state and put drafts
|
|
121
|
+
// on the wrong baseline for previews and merge planning.
|
|
122
|
+
const base = { kind: 'layer', id: ref };
|
|
123
|
+
const files = resolveAncestorFilesAnyRef(ws, base);
|
|
124
|
+
return { base, files: files.length > 0 ? files : [layer] };
|
|
125
|
+
}
|
|
126
|
+
throw new ToolExecutionError({
|
|
127
|
+
code: ToolErrorCode.ENTITY_NOT_FOUND,
|
|
128
|
+
message: `Unknown base '${ref}' — not a ref name or published layer id.`,
|
|
129
|
+
details: { refs: Array.from(ws.refs.keys()) },
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Resolve a manifest base against a ref's layer ids: a stack base matches
|
|
134
|
+
* a prefix stack hash, a layer base matches a prefix end (or a stored
|
|
135
|
+
* stray layer). Best effort — unknown bases resolve to [].
|
|
136
|
+
*/
|
|
137
|
+
export function resolveAncestorFiles(ws, base, refIds) {
|
|
138
|
+
if (!base)
|
|
139
|
+
return [];
|
|
140
|
+
if (base.kind === 'stack') {
|
|
141
|
+
for (let i = 0; i <= refIds.length; i += 1) {
|
|
142
|
+
if (computeStackHash(refIds.slice(0, i)) === base.id) {
|
|
143
|
+
return refIds.slice(0, i).map((id) => ws.layers.get(id)).filter((f) => f !== undefined);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
const idx = refIds.indexOf(base.id);
|
|
149
|
+
if (idx !== -1) {
|
|
150
|
+
return refIds.slice(0, idx + 1).map((id) => ws.layers.get(id)).filter((f) => f !== undefined);
|
|
151
|
+
}
|
|
152
|
+
const single = ws.layers.get(base.id);
|
|
153
|
+
return single ? [single] : [];
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Resolve a manifest base by searching every ref's layer list — used when
|
|
157
|
+
* a tool gets a published layer without an explicit `into` ref, where an
|
|
158
|
+
* empty ref list could never reconstruct a stack-hash base.
|
|
159
|
+
*/
|
|
160
|
+
export function resolveAncestorFilesAnyRef(ws, base) {
|
|
161
|
+
if (!base)
|
|
162
|
+
return [];
|
|
163
|
+
for (const refIds of ws.refs.values()) {
|
|
164
|
+
const files = resolveAncestorFiles(ws, base, refIds);
|
|
165
|
+
if (files.length > 0)
|
|
166
|
+
return files;
|
|
167
|
+
}
|
|
168
|
+
// Fall back to the lone-layer case resolveAncestorFiles also covers.
|
|
169
|
+
return resolveAncestorFiles(ws, base, []);
|
|
170
|
+
}
|
|
171
|
+
/** Read the IfcClass code off the well-known class attribute, if present. */
|
|
172
|
+
export function ifcClassOfAttributes(attributes) {
|
|
173
|
+
const cls = attributes?.[ATTR.CLASS];
|
|
174
|
+
if (cls && typeof cls === 'object' && 'code' in cls) {
|
|
175
|
+
const code = cls.code;
|
|
176
|
+
if (typeof code === 'string')
|
|
177
|
+
return code;
|
|
178
|
+
}
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Fold an ordered layer stack (weakest first) into a draft Y.Doc.
|
|
183
|
+
*
|
|
184
|
+
* Unlike `seedFromIfcx` (whose `createEntity` is a no-op on existing
|
|
185
|
+
* paths), this applies later layers' opinions on top: nulls remove,
|
|
186
|
+
* tombstones delete, values overwrite.
|
|
187
|
+
*/
|
|
188
|
+
export function seedDraftDoc(doc, files) {
|
|
189
|
+
doc.transact(() => {
|
|
190
|
+
// Composition resolves `ifclite::deleted` like any other attribute —
|
|
191
|
+
// the strongest (latest) opinion wins after ALL layers merge — so
|
|
192
|
+
// deletion cannot run per-layer: base → delete → resurrect must seed
|
|
193
|
+
// the entity with its base state, exactly as composition reveals it.
|
|
194
|
+
const tombstoned = new Map();
|
|
195
|
+
for (const file of files) {
|
|
196
|
+
for (const node of file.data) {
|
|
197
|
+
const opinion = node.attributes?.[IFCLITE_ATTR.DELETED];
|
|
198
|
+
if (typeof opinion === 'boolean')
|
|
199
|
+
tombstoned.set(node.path, opinion);
|
|
200
|
+
applyNode(doc, file, node);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
for (const [path, deleted] of tombstoned) {
|
|
204
|
+
if (deleted)
|
|
205
|
+
deleteEntity(doc, path);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
function applyNode(doc, file, node) {
|
|
210
|
+
if (!hasEntity(doc, node.path)) {
|
|
211
|
+
const ifcClass = ifcClassOfAttributes(node.attributes);
|
|
212
|
+
const inherits = {};
|
|
213
|
+
for (const [role, target] of Object.entries(node.inherits ?? {})) {
|
|
214
|
+
if (typeof target === 'string')
|
|
215
|
+
inherits[role] = target;
|
|
216
|
+
}
|
|
217
|
+
createEntity(doc, node.path, {
|
|
218
|
+
ifcClass,
|
|
219
|
+
inherits,
|
|
220
|
+
meta: {
|
|
221
|
+
ifcClass,
|
|
222
|
+
createdAt: file.header.timestamp,
|
|
223
|
+
createdBy: file.header.author,
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
for (const [key, value] of Object.entries(node.attributes ?? {})) {
|
|
228
|
+
if (key === IFCLITE_ATTR.DELETED)
|
|
229
|
+
continue;
|
|
230
|
+
if (value === null)
|
|
231
|
+
deleteAttribute(doc, node.path, key);
|
|
232
|
+
else
|
|
233
|
+
setAttribute(doc, node.path, key, value);
|
|
234
|
+
}
|
|
235
|
+
for (const [role, child] of Object.entries(node.children ?? {})) {
|
|
236
|
+
if (child === null)
|
|
237
|
+
removeChild(doc, node.path, role);
|
|
238
|
+
else
|
|
239
|
+
setChild(doc, node.path, role, child);
|
|
240
|
+
}
|
|
241
|
+
// Inherits deltas must replay on existing entities too — `createEntity`
|
|
242
|
+
// only applies them on first creation, but later base layers may add,
|
|
243
|
+
// retarget, or null out inheritance opinions.
|
|
244
|
+
for (const [role, target] of Object.entries(node.inherits ?? {})) {
|
|
245
|
+
if (target === null)
|
|
246
|
+
removeInherit(doc, node.path, role);
|
|
247
|
+
else if (typeof target === 'string')
|
|
248
|
+
setInherit(doc, node.path, role, target);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/** Build, seed, baseline, and register a new draft. */
|
|
252
|
+
export function createDraft(ws, init) {
|
|
253
|
+
const doc = createCollabDoc({ gc: false });
|
|
254
|
+
seedDraftDoc(doc, init.baseFiles);
|
|
255
|
+
const draft = {
|
|
256
|
+
id: randomUUID(),
|
|
257
|
+
doc,
|
|
258
|
+
baseline: Y.encodeStateAsUpdate(doc),
|
|
259
|
+
base: init.base,
|
|
260
|
+
baseFiles: init.baseFiles,
|
|
261
|
+
intent: init.intent,
|
|
262
|
+
claims: init.claims,
|
|
263
|
+
rawClaims: init.rawClaims,
|
|
264
|
+
session: init.session ?? randomUUID(),
|
|
265
|
+
owner: init.owner,
|
|
266
|
+
createdAt: new Date().toISOString(),
|
|
267
|
+
};
|
|
268
|
+
ws.drafts.set(draft.id, draft);
|
|
269
|
+
return draft;
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=layer-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer-store.js","sourceRoot":"","sources":["../../src/tools/layer-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent draft-layer lifecycle tools (spec 06-agents.md §6.2/§6.3):
|
|
3
|
+
*
|
|
4
|
+
* create_draft_layer → n × draft_apply_ops → publish_layer
|
|
5
|
+
*
|
|
6
|
+
* Every mutation lands in a draft (a CRDT session bound to a base);
|
|
7
|
+
* publishing freezes it into an immutable, content-addressed,
|
|
8
|
+
* provenance-stamped layer. Scope claims are enforced twice: per op at
|
|
9
|
+
* write time (before the Y.Doc is touched) and re-verified against the
|
|
10
|
+
* frozen layer at publish time (`scope_verified` + `mismatches`).
|
|
11
|
+
*/
|
|
12
|
+
import { publishLayer } from '@ifc-lite/collab';
|
|
13
|
+
import type { Tool } from './types.js';
|
|
14
|
+
import type { ToolContext } from '../context.js';
|
|
15
|
+
import type { DraftLayer } from './layer-store.js';
|
|
16
|
+
/** Freeze a draft via `publishLayer` without registering the result (previews). */
|
|
17
|
+
export declare function publishDraftFile(draft: DraftLayer, ctx: ToolContext): ReturnType<typeof publishLayer>;
|
|
18
|
+
export declare const draftLayerTools: Tool[];
|
|
19
|
+
//# sourceMappingURL=layer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer.d.ts","sourceRoot":"","sources":["../../src/tools/layer.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,OAAO,EAML,YAAY,EAEb,MAAM,kBAAkB,CAAC;AAI1B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AASjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAiNnD,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAarG;AAyCD,eAAO,MAAM,eAAe,EAAE,IAAI,EAAwD,CAAC"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* Agent draft-layer lifecycle tools (spec 06-agents.md §6.2/§6.3):
|
|
6
|
+
*
|
|
7
|
+
* create_draft_layer → n × draft_apply_ops → publish_layer
|
|
8
|
+
*
|
|
9
|
+
* Every mutation lands in a draft (a CRDT session bound to a base);
|
|
10
|
+
* publishing freezes it into an immutable, content-addressed,
|
|
11
|
+
* provenance-stamped layer. Scope claims are enforced twice: per op at
|
|
12
|
+
* write time (before the Y.Doc is touched) and re-verified against the
|
|
13
|
+
* frozen layer at publish time (`scope_verified` + `mismatches`).
|
|
14
|
+
*/
|
|
15
|
+
import { createEntity, deleteEntity, entityToJSON, getEntity, hasEntity, publishLayer, setAttribute, } from '@ifc-lite/collab';
|
|
16
|
+
import { parseScopeClaims } from '@ifc-lite/extensions';
|
|
17
|
+
import { ATTR, isTypedPropertyValue } from '@ifc-lite/ifcx';
|
|
18
|
+
import { okResult, fmtCount } from './util.js';
|
|
19
|
+
import { ToolErrorCode, ToolExecutionError } from '../errors.js';
|
|
20
|
+
import { createDraft, getLayerWorkspace, resolveBase, } from './layer-store.js';
|
|
21
|
+
import { requireOwnedDraft } from './layer-access.js';
|
|
22
|
+
import { assertOpWithinClaims, descriptorForDraftOp, verifyLayerAgainstClaims, } from './layer-ops.js';
|
|
23
|
+
/**
|
|
24
|
+
* Attribute key a `set_property` op writes. Carries the Pset/Qto name so
|
|
25
|
+
* the merge engine groups it under `pset:<name>` and publish-time
|
|
26
|
+
* verification re-derives `model.mutate:<name>` from the key.
|
|
27
|
+
*/
|
|
28
|
+
function psetAttributeKey(pset, prop) {
|
|
29
|
+
return `bsi::ifc::v5a::${pset}::${prop}`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Canonical wire shape for property values (#1031): scalars are wrapped
|
|
33
|
+
* in the typed record the collab snapshot pipeline emits, so equivalent
|
|
34
|
+
* edits hash identically in the merge engine regardless of which writer
|
|
35
|
+
* produced them. Already-typed records pass through; anything else
|
|
36
|
+
* (arrays, foreign objects, null) is written verbatim.
|
|
37
|
+
*/
|
|
38
|
+
function typedPropertyRecord(value) {
|
|
39
|
+
if (isTypedPropertyValue(value))
|
|
40
|
+
return value;
|
|
41
|
+
if (typeof value === 'boolean')
|
|
42
|
+
return { type: 'IfcBoolean', value };
|
|
43
|
+
if (typeof value === 'number') {
|
|
44
|
+
return { type: Number.isInteger(value) ? 'IfcInteger' : 'IfcReal', value };
|
|
45
|
+
}
|
|
46
|
+
if (typeof value === 'string')
|
|
47
|
+
return { type: 'IfcLabel', value };
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
function ifcClassOfEntity(doc, path) {
|
|
51
|
+
const entity = getEntity(doc, path);
|
|
52
|
+
if (!entity)
|
|
53
|
+
return undefined;
|
|
54
|
+
const ifcClass = entityToJSON(entity).meta.ifcClass;
|
|
55
|
+
return typeof ifcClass === 'string' ? ifcClass : undefined;
|
|
56
|
+
}
|
|
57
|
+
function requireField(op, index, field) {
|
|
58
|
+
const value = op[field];
|
|
59
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
60
|
+
throw new ToolExecutionError({
|
|
61
|
+
code: ToolErrorCode.INVALID_INPUT,
|
|
62
|
+
message: `ops[${index}]: '${op.op}' requires '${field}'.`,
|
|
63
|
+
details: { op: { ...op } },
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return value;
|
|
67
|
+
}
|
|
68
|
+
function requireEntity(draft, op, index) {
|
|
69
|
+
if (!hasEntity(draft.doc, op.path)) {
|
|
70
|
+
throw new ToolExecutionError({
|
|
71
|
+
code: ToolErrorCode.ENTITY_NOT_FOUND,
|
|
72
|
+
message: `ops[${index}]: entity '${op.path}' not found in draft ${draft.id}.`,
|
|
73
|
+
details: { op: { ...op } },
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const createDraftLayer = {
|
|
78
|
+
name: 'create_draft_layer',
|
|
79
|
+
description: 'Open a draft layer (CRDT session) bound to a base ref or layer. All writes land in drafts; ' +
|
|
80
|
+
'`scope` is a list of capability scope-claims that bound what the draft may touch.',
|
|
81
|
+
scope: 'mutate',
|
|
82
|
+
inputSchema: {
|
|
83
|
+
type: 'object',
|
|
84
|
+
properties: {
|
|
85
|
+
base: { type: 'string', description: 'Ref name (e.g. "main") or published layer id. Omit for a baseless draft.' },
|
|
86
|
+
intent: { type: 'string', minLength: 1, description: 'Human-readable why — the layer log line.' },
|
|
87
|
+
scope: {
|
|
88
|
+
type: 'array',
|
|
89
|
+
items: { type: 'string' },
|
|
90
|
+
description: 'Scope claims, e.g. "model.mutate:Pset_FireSafety*@IfcWall". Empty/omitted = unrestricted.',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
required: ['intent'],
|
|
94
|
+
additionalProperties: false,
|
|
95
|
+
},
|
|
96
|
+
handler(input, ctx) {
|
|
97
|
+
const ws = getLayerWorkspace(ctx.session?.id);
|
|
98
|
+
const rawClaims = input.scope ?? [];
|
|
99
|
+
const parsed = parseScopeClaims(rawClaims);
|
|
100
|
+
if (!parsed.ok) {
|
|
101
|
+
throw new ToolExecutionError({
|
|
102
|
+
code: ToolErrorCode.INVALID_INPUT,
|
|
103
|
+
message: 'Invalid scope claims.',
|
|
104
|
+
details: { errors: parsed.errors },
|
|
105
|
+
hint: 'Claims follow "scope.action[:target][@IfcType[&key=value]]".',
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
const { base, files } = resolveBase(ws, input.base);
|
|
109
|
+
const draft = createDraft(ws, {
|
|
110
|
+
base,
|
|
111
|
+
baseFiles: files,
|
|
112
|
+
intent: input.intent,
|
|
113
|
+
claims: parsed.value,
|
|
114
|
+
rawClaims,
|
|
115
|
+
owner: ctx.session?.principal,
|
|
116
|
+
});
|
|
117
|
+
return okResult(`Draft ${draft.id} created${base ? ` on ${base.kind} ${base.id}` : ' (no base)'}; ${fmtCount(rawClaims.length, 'scope claim')}.`, { draft_id: draft.id, base, scope: rawClaims });
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
const draftApplyOps = {
|
|
121
|
+
name: 'draft_apply_ops',
|
|
122
|
+
description: 'Apply entity operations to a draft layer. Each op is checked against the draft\'s scope claims ' +
|
|
123
|
+
'before it touches the document; violations return a structured error.',
|
|
124
|
+
scope: 'mutate',
|
|
125
|
+
inputSchema: {
|
|
126
|
+
type: 'object',
|
|
127
|
+
properties: {
|
|
128
|
+
draft_id: { type: 'string' },
|
|
129
|
+
ops: {
|
|
130
|
+
type: 'array',
|
|
131
|
+
minItems: 1,
|
|
132
|
+
items: {
|
|
133
|
+
type: 'object',
|
|
134
|
+
properties: {
|
|
135
|
+
op: { type: 'string', enum: ['create_entity', 'set_attribute', 'set_property', 'delete_entity'] },
|
|
136
|
+
path: { type: 'string', description: 'Entity path, e.g. "site/wall-1".' },
|
|
137
|
+
ifc_type: { type: 'string', minLength: 1, description: 'IFC class — required for create_entity, e.g. "IfcWall".' },
|
|
138
|
+
name: { type: 'string', description: 'Attribute name for set_attribute.' },
|
|
139
|
+
pset: { type: 'string', description: 'Property-set name for set_property.' },
|
|
140
|
+
prop: { type: 'string', description: 'Property name for set_property.' },
|
|
141
|
+
value: { description: 'Value for set_attribute / set_property.' },
|
|
142
|
+
},
|
|
143
|
+
required: ['op', 'path'],
|
|
144
|
+
additionalProperties: false,
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
required: ['draft_id', 'ops'],
|
|
149
|
+
additionalProperties: false,
|
|
150
|
+
},
|
|
151
|
+
handler(input, ctx) {
|
|
152
|
+
const ws = getLayerWorkspace(ctx.session?.id);
|
|
153
|
+
const draft = requireOwnedDraft(ws, input.draft_id, ctx.session?.principal);
|
|
154
|
+
const ops = input.ops;
|
|
155
|
+
// WRITE-TIME ENFORCEMENT — derive and check every capability before a
|
|
156
|
+
// single op lands, so a denied batch leaves the draft untouched.
|
|
157
|
+
// `pendingTypes` lets later ops in the batch see classes of entities
|
|
158
|
+
// an earlier `create_entity` in the same batch will create.
|
|
159
|
+
const pendingTypes = new Map();
|
|
160
|
+
ops.forEach((op, index) => {
|
|
161
|
+
if (op.op === 'set_attribute')
|
|
162
|
+
requireField(op, index, 'name');
|
|
163
|
+
if (op.op === 'set_property') {
|
|
164
|
+
requireField(op, index, 'pset');
|
|
165
|
+
requireField(op, index, 'prop');
|
|
166
|
+
}
|
|
167
|
+
let ifcType;
|
|
168
|
+
if (op.op === 'create_entity') {
|
|
169
|
+
// A typeless entity would publish without bsi::ifc::class, losing
|
|
170
|
+
// the only stable signal type-scoped claims and merge rely on.
|
|
171
|
+
requireField(op, index, 'ifc_type');
|
|
172
|
+
ifcType = op.ifc_type;
|
|
173
|
+
pendingTypes.set(op.path, op.ifc_type);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
ifcType = ifcClassOfEntity(draft.doc, op.path) ?? pendingTypes.get(op.path);
|
|
177
|
+
}
|
|
178
|
+
assertOpWithinClaims(draft.claims, draft.rawClaims, descriptorForDraftOp(op, ifcType), op);
|
|
179
|
+
});
|
|
180
|
+
draft.doc.transact(() => {
|
|
181
|
+
ops.forEach((op, index) => {
|
|
182
|
+
switch (op.op) {
|
|
183
|
+
case 'create_entity':
|
|
184
|
+
createEntity(draft.doc, op.path, {
|
|
185
|
+
ifcClass: op.ifc_type,
|
|
186
|
+
attributes: { [ATTR.CLASS]: { code: op.ifc_type } },
|
|
187
|
+
});
|
|
188
|
+
break;
|
|
189
|
+
case 'set_attribute':
|
|
190
|
+
requireEntity(draft, op, index);
|
|
191
|
+
setAttribute(draft.doc, op.path, op.name, op.value);
|
|
192
|
+
break;
|
|
193
|
+
case 'set_property':
|
|
194
|
+
requireEntity(draft, op, index);
|
|
195
|
+
setAttribute(draft.doc, op.path, psetAttributeKey(op.pset, op.prop), typedPropertyRecord(op.value));
|
|
196
|
+
break;
|
|
197
|
+
case 'delete_entity':
|
|
198
|
+
requireEntity(draft, op, index);
|
|
199
|
+
deleteEntity(draft.doc, op.path);
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
return okResult(`Applied ${fmtCount(ops.length, 'op')} to draft ${draft.id}.`, {
|
|
205
|
+
draft_id: draft.id,
|
|
206
|
+
applied: ops.length,
|
|
207
|
+
});
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
/** Freeze a draft via `publishLayer` without registering the result (previews). */
|
|
211
|
+
export function publishDraftFile(draft, ctx) {
|
|
212
|
+
return publishLayer(draft.doc, {
|
|
213
|
+
intent: draft.intent,
|
|
214
|
+
author: {
|
|
215
|
+
kind: 'agent',
|
|
216
|
+
principal: ctx.scope.user ?? 'mcp-agent',
|
|
217
|
+
tool: '@ifc-lite/mcp',
|
|
218
|
+
session: draft.session,
|
|
219
|
+
},
|
|
220
|
+
baseline: draft.baseline,
|
|
221
|
+
base: draft.base,
|
|
222
|
+
scope_claim: [...draft.rawClaims],
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
const publishLayerTool = {
|
|
226
|
+
name: 'publish_layer',
|
|
227
|
+
description: 'Freeze a draft into an immutable content-addressed layer (blake3 id + provenance manifest). ' +
|
|
228
|
+
'Actual ops are re-verified against the manifest scope claims; mismatches are reported.',
|
|
229
|
+
scope: 'mutate',
|
|
230
|
+
inputSchema: {
|
|
231
|
+
type: 'object',
|
|
232
|
+
properties: {
|
|
233
|
+
draft_id: { type: 'string' },
|
|
234
|
+
},
|
|
235
|
+
required: ['draft_id'],
|
|
236
|
+
additionalProperties: false,
|
|
237
|
+
},
|
|
238
|
+
handler(input, ctx) {
|
|
239
|
+
const ws = getLayerWorkspace(ctx.session?.id);
|
|
240
|
+
const draft = requireOwnedDraft(ws, input.draft_id, ctx.session?.principal);
|
|
241
|
+
const published = publishDraftFile(draft, ctx);
|
|
242
|
+
// PUBLISH-TIME verification: claims vs the ops actually frozen into
|
|
243
|
+
// the layer. Mismatches are surfaced, never silently accepted.
|
|
244
|
+
const verification = verifyLayerAgainstClaims(published.file, draft.baseFiles, draft.rawClaims);
|
|
245
|
+
ws.layers.set(published.layerId, published.file);
|
|
246
|
+
ws.drafts.delete(draft.id);
|
|
247
|
+
return okResult(`Published ${published.layerId} (${fmtCount(published.opCount, 'op')}); scope_verified=${verification.verified}.`, {
|
|
248
|
+
layer_id: published.layerId,
|
|
249
|
+
op_count: published.opCount,
|
|
250
|
+
scope_verified: verification.verified,
|
|
251
|
+
...(verification.mismatches.length > 0 ? { mismatches: verification.mismatches } : {}),
|
|
252
|
+
checks: [],
|
|
253
|
+
});
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
export const draftLayerTools = [createDraftLayer, draftApplyOps, publishLayerTool];
|
|
257
|
+
//# sourceMappingURL=layer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer.js","sourceRoot":"","sources":["../../src/tools/layer.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;GAUG;AAEH,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,SAAS,EACT,YAAY,EACZ,YAAY,GACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAA2B,MAAM,gBAAgB,CAAC;AAIrF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AAGxB;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,IAAY,EAAE,IAAY;IAClD,OAAO,kBAAkB,IAAI,KAAK,IAAI,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;GAMG;AACH,SAAS,mBAAmB,CAAC,KAAc;IACzC,IAAI,oBAAoB,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9C,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAA+B,CAAC;IAClG,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,EAA+B,CAAC;IAC1G,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAA+B,CAAC;IAC/F,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAU,EAAE,IAAY;IAChD,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACpC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC;IACpD,OAAO,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7D,CAAC;AAED,SAAS,YAAY,CAAC,EAAgB,EAAE,KAAa,EAAE,KAA4C;IACjG,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;IACxB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,kBAAkB,CAAC;YAC3B,IAAI,EAAE,aAAa,CAAC,aAAa;YACjC,OAAO,EAAE,OAAO,KAAK,OAAO,EAAE,CAAC,EAAE,eAAe,KAAK,IAAI;YACzD,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;SAC3B,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,aAAa,CAAC,KAAiB,EAAE,EAAgB,EAAE,KAAa;IACvE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,kBAAkB,CAAC;YAC3B,IAAI,EAAE,aAAa,CAAC,gBAAgB;YACpC,OAAO,EAAE,OAAO,KAAK,cAAc,EAAE,CAAC,IAAI,wBAAwB,KAAK,CAAC,EAAE,GAAG;YAC7E,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;SAC3B,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,gBAAgB,GAAS;IAC7B,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,6FAA6F;QAC7F,mFAAmF;IACrF,KAAK,EAAE,QAAQ;IACf,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0EAA0E,EAAE;YACjH,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,0CAA0C,EAAE;YACjG,KAAK,EAAE;gBACL,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,WAAW,EAAE,2FAA2F;aACzG;SACF;QACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;QACpB,oBAAoB,EAAE,KAAK;KAC5B;IACD,OAAO,CAAC,KAAK,EAAE,GAAG;QAChB,MAAM,EAAE,GAAG,iBAAiB,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAI,KAAK,CAAC,KAA8B,IAAI,EAAE,CAAC;QAC9D,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,IAAI,kBAAkB,CAAC;gBAC3B,IAAI,EAAE,aAAa,CAAC,aAAa;gBACjC,OAAO,EAAE,uBAAuB;gBAChC,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;gBAClC,IAAI,EAAE,8DAA8D;aACrE,CAAC,CAAC;QACL,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,EAAE,EAAE,KAAK,CAAC,IAA0B,CAAC,CAAC;QAC1E,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,EAAE;YAC5B,IAAI;YACJ,SAAS,EAAE,KAAK;YAChB,MAAM,EAAE,KAAK,CAAC,MAAgB;YAC9B,MAAM,EAAE,MAAM,CAAC,KAAK;YACpB,SAAS;YACT,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS;SAC9B,CAAC,CAAC;QACH,OAAO,QAAQ,CACb,SAAS,KAAK,CAAC,EAAE,WAAW,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,EAChI,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAC/C,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,MAAM,aAAa,GAAS;IAC1B,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT,iGAAiG;QACjG,uEAAuE;IACzE,KAAK,EAAE,QAAQ;IACf,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC5B,GAAG,EAAE;gBACH,IAAI,EAAE,OAAO;gBACb,QAAQ,EAAE,CAAC;gBACX,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,CAAC,EAAE;wBACjG,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kCAAkC,EAAE;wBACzE,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,yDAAyD,EAAE;wBAClH,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mCAAmC,EAAE;wBAC1E,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,qCAAqC,EAAE;wBAC5E,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iCAAiC,EAAE;wBACxE,KAAK,EAAE,EAAE,WAAW,EAAE,yCAAyC,EAAE;qBAClE;oBACD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC;oBACxB,oBAAoB,EAAE,KAAK;iBAC5B;aACF;SACF;QACD,QAAQ,EAAE,CAAC,UAAU,EAAE,KAAK,CAAC;QAC7B,oBAAoB,EAAE,KAAK;KAC5B;IACD,OAAO,CAAC,KAAK,EAAE,GAAG;QAChB,MAAM,EAAE,GAAG,iBAAiB,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,iBAAiB,CAAC,EAAE,EAAE,KAAK,CAAC,QAAkB,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,KAAK,CAAC,GAAqB,CAAC;QAExC,sEAAsE;QACtE,iEAAiE;QACjE,qEAAqE;QACrE,4DAA4D;QAC5D,MAAM,YAAY,GAAG,IAAI,GAAG,EAA8B,CAAC;QAC3D,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE;YACxB,IAAI,EAAE,CAAC,EAAE,KAAK,eAAe;gBAAE,YAAY,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YAC/D,IAAI,EAAE,CAAC,EAAE,KAAK,cAAc,EAAE,CAAC;gBAC7B,YAAY,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;gBAChC,YAAY,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YAClC,CAAC;YACD,IAAI,OAA2B,CAAC;YAChC,IAAI,EAAE,CAAC,EAAE,KAAK,eAAe,EAAE,CAAC;gBAC9B,kEAAkE;gBAClE,+DAA+D;gBAC/D,YAAY,CAAC,EAAE,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;gBACpC,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC;gBACtB,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;YACzC,CAAC;iBAAM,CAAC;gBACN,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YAC9E,CAAC;YACD,oBAAoB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7F,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE;YACtB,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE;gBACxB,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;oBACd,KAAK,eAAe;wBAClB,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,EAAE;4BAC/B,QAAQ,EAAE,EAAE,CAAC,QAAQ;4BACrB,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,QAAQ,EAAE,EAAE;yBACpD,CAAC,CAAC;wBACH,MAAM;oBACR,KAAK,eAAe;wBAClB,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;wBAChC,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAc,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;wBAC9D,MAAM;oBACR,KAAK,cAAc;wBACjB,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;wBAChC,YAAY,CACV,KAAK,CAAC,GAAG,EACT,EAAE,CAAC,IAAI,EACP,gBAAgB,CAAC,EAAE,CAAC,IAAc,EAAE,EAAE,CAAC,IAAc,CAAC,EACtD,mBAAmB,CAAC,EAAE,CAAC,KAAK,CAAC,CAC9B,CAAC;wBACF,MAAM;oBACR,KAAK,eAAe;wBAClB,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;wBAChC,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;wBACjC,MAAM;gBACV,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC,WAAW,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,KAAK,CAAC,EAAE,GAAG,EAAE;YAC7E,QAAQ,EAAE,KAAK,CAAC,EAAE;YAClB,OAAO,EAAE,GAAG,CAAC,MAAM;SACpB,CAAC,CAAC;IACL,CAAC;CACF,CAAC;AAEF,mFAAmF;AACnF,MAAM,UAAU,gBAAgB,CAAC,KAAiB,EAAE,GAAgB;IAClE,OAAO,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE;QAC7B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE;YACN,IAAI,EAAE,OAAO;YACb,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,WAAW;YACxC,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB;QACD,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;KAClC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,gBAAgB,GAAS;IAC7B,IAAI,EAAE,eAAe;IACrB,WAAW,EACT,8FAA8F;QAC9F,wFAAwF;IAC1F,KAAK,EAAE,QAAQ;IACf,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;SAC7B;QACD,QAAQ,EAAE,CAAC,UAAU,CAAC;QACtB,oBAAoB,EAAE,KAAK;KAC5B;IACD,OAAO,CAAC,KAAK,EAAE,GAAG;QAChB,MAAM,EAAE,GAAG,iBAAiB,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,iBAAiB,CAAC,EAAE,EAAE,KAAK,CAAC,QAAkB,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAEtF,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/C,oEAAoE;QACpE,+DAA+D;QAC/D,MAAM,YAAY,GAAG,wBAAwB,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QAEhG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACjD,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAE3B,OAAO,QAAQ,CACb,aAAa,SAAS,CAAC,OAAO,KAAK,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,qBAAqB,YAAY,CAAC,QAAQ,GAAG,EACjH;YACE,QAAQ,EAAE,SAAS,CAAC,OAAO;YAC3B,QAAQ,EAAE,SAAS,CAAC,OAAO;YAC3B,cAAc,EAAE,YAAY,CAAC,QAAQ;YACrC,GAAG,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtF,MAAM,EAAE,EAAE;SACX,CACF,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAW,CAAC,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,CAAC,CAAC"}
|
package/dist/transport/http.d.ts
CHANGED
|
@@ -27,7 +27,15 @@ export interface HttpAuthenticator {
|
|
|
27
27
|
authenticate(req: IncomingMessage): Promise<AuthScope | null> | AuthScope | null;
|
|
28
28
|
}
|
|
29
29
|
export interface SessionFactory {
|
|
30
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Build a fresh MCPServer for this session. Called on `initialize`.
|
|
32
|
+
*
|
|
33
|
+
* The server MUST be constructed with `sessionId` (i.e.
|
|
34
|
+
* `createMCPServer({ ..., sessionId })`): it keys per-session state —
|
|
35
|
+
* the layer workspace in particular (#1030) — and its disposal on
|
|
36
|
+
* session end. The transport rejects servers built without it rather
|
|
37
|
+
* than letting every HTTP session silently share the local workspace.
|
|
38
|
+
*/
|
|
31
39
|
build(scope: AuthScope, sessionId: string): Promise<MCPServer> | MCPServer;
|
|
32
40
|
}
|
|
33
41
|
export interface HttpTransportOptions {
|
|
@@ -62,6 +70,8 @@ export declare class HttpTransport {
|
|
|
62
70
|
private enforceHostCheck;
|
|
63
71
|
constructor(opts: HttpTransportOptions);
|
|
64
72
|
listen(): Promise<void>;
|
|
73
|
+
/** Actual bound port — differs from `opts.port` when listening on 0. */
|
|
74
|
+
port(): number | undefined;
|
|
65
75
|
close(): Promise<void>;
|
|
66
76
|
private handle;
|
|
67
77
|
private openSse;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transport/http.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAgB,eAAe,EAA0B,MAAM,WAAW,CAAC;AAKlF,OAAO,EAAE,SAAS,EAAuB,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;CAClF;AAED,MAAM,WAAW,cAAc;IAC7B
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transport/http.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAgB,eAAe,EAA0B,MAAM,WAAW,CAAC;AAKlF,OAAO,EAAE,SAAS,EAAuB,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;CAClF;AAED,MAAM,WAAW,cAAc;IAC7B;;;;;;;;OAQG;IACH,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;CAC5E;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,iBAAiB,CAAC;IACjC,cAAc,EAAE,cAAc,CAAC;IAC/B,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAUD,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,IAAI,CAAuB;IACnC,kEAAkE;IAClE,OAAO,CAAC,cAAc,CAAc;IACpC,4DAA4D;IAC5D,OAAO,CAAC,YAAY,CAAc;IAClC;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB,CAAU;gBAEtB,IAAI,EAAE,oBAAoB;IA6BtC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAOvB,wEAAwE;IACxE,IAAI,IAAI,MAAM,GAAG,SAAS;IAK1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAWR,MAAM;IAkJpB,OAAO,CAAC,OAAO;IAcf,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,WAAW;CAUpB;AA0ED,qBAAa,eAAgB,YAAW,iBAAiB;IAC3C,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;IAElD,YAAY,CAAC,GAAG,EAAE,eAAe,GAAG,SAAS,GAAG,IAAI;CAMrD;AAED,4EAA4E;AAC5E,qBAAa,YAAa,YAAW,iBAAiB;IACxC,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,SAAS;IACpC,YAAY,IAAI,SAAS;CAC1B"}
|