@superdoc/sdk 2.26.0-next.2 → 2.26.0-next.9
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 +8 -10
- package/dist/embedded-tools.generated.cjs +5 -5
- package/dist/embedded-tools.generated.js +5 -5
- package/dist/generated/client.d.ts +1728 -0
- package/dist/generated/contract.cjs +1 -1
- package/dist/generated/contract.d.ts +0 -10
- package/dist/generated/contract.js +1 -1
- package/dist/runtime/host.cjs +37 -242
- package/dist/runtime/host.d.ts +1 -16
- package/dist/runtime/host.js +36 -241
- package/dist/runtime/process.cjs +0 -26
- package/dist/runtime/process.d.ts +0 -8
- package/dist/runtime/process.js +0 -26
- package/dist/runtime/sdk-policy.d.ts +0 -10
- package/dist/runtime/sdk-version.generated.cjs +1 -1
- package/dist/runtime/sdk-version.generated.d.ts +1 -1
- package/dist/runtime/sdk-version.generated.js +1 -1
- package/dist/runtime/transport-common.d.ts +0 -8
- package/package.json +7 -7
- package/tools/catalog.json +40 -0
- package/tools/generation-receipt.json +57 -19
- package/tools/tools-policy.json +1 -1
- package/tools/tools.anthropic.json +40 -0
- package/tools/tools.generic.json +40 -0
- package/tools/tools.openai.json +40 -0
- package/tools/tools.vercel.json +40 -0
- package/dist/runtime/document-rpc.cjs +0 -351
- package/dist/runtime/document-rpc.d.ts +0 -26
- package/dist/runtime/document-rpc.js +0 -333
- package/dist/runtime/embedded-document-host.cjs +0 -28
- package/dist/runtime/embedded-document-host.d.ts +0 -1
- package/dist/runtime/embedded-document-host.js +0 -23
package/dist/runtime/host.cjs
CHANGED
|
@@ -7,12 +7,11 @@ var stateDirectory = require('./state-directory.cjs');
|
|
|
7
7
|
var documentEvidence = require('./document-evidence.cjs');
|
|
8
8
|
var contract = require('../generated/contract.cjs');
|
|
9
9
|
var sdkPolicy = require('./sdk-policy.cjs');
|
|
10
|
-
var documentRpc = require('./document-rpc.cjs');
|
|
11
10
|
|
|
12
11
|
const HOST_PROTOCOL_VERSION = sdkPolicy.SDK_POLICY.protocolVersion;
|
|
13
12
|
const CLI_HOST_REQUIRED_FEATURES = sdkPolicy.SDK_POLICY.cliRequiredFeatures;
|
|
14
13
|
const COLLABORATION_AUTH_PER_OPEN_FEATURE = sdkPolicy.SDK_POLICY.features.collaborationAuthPerOpen;
|
|
15
|
-
const
|
|
14
|
+
const HOST_REQUEST_TIMEOUT_FEATURE = sdkPolicy.SDK_POLICY.features.requestTimeout;
|
|
16
15
|
const CHANGE_MODES = ['direct', 'tracked'];
|
|
17
16
|
const FORWARD_HOST_STDERR = typeof process !== 'undefined' && typeof process.env?.SUPERDOC_DEBUG_TEXT_REWRITE === 'string'
|
|
18
17
|
? process.env.SUPERDOC_DEBUG_TEXT_REWRITE === '1'
|
|
@@ -39,6 +38,30 @@ function mapCliInvocationResult(operation, value) {
|
|
|
39
38
|
const extracted = value[envelopeKey];
|
|
40
39
|
return extracted === undefined ? value : extracted;
|
|
41
40
|
}
|
|
41
|
+
function mapDocumentReplaceFileResult(response, sessionId) {
|
|
42
|
+
if (typeof response !== 'object' || response == null || Array.isArray(response)) {
|
|
43
|
+
throw new errors.SuperDocCliError('Host returned invalid document.replaceFile result.', {
|
|
44
|
+
code: 'HOST_PROTOCOL_ERROR',
|
|
45
|
+
details: { result: response },
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const record = response;
|
|
49
|
+
if (record.sessionId !== sessionId ||
|
|
50
|
+
record.replaced !== true ||
|
|
51
|
+
typeof record.byteLength !== 'number' ||
|
|
52
|
+
typeof record.revision !== 'string') {
|
|
53
|
+
throw new errors.SuperDocCliError('Host returned invalid document.replaceFile session metadata.', {
|
|
54
|
+
code: 'HOST_PROTOCOL_ERROR',
|
|
55
|
+
details: { expectedSessionId: sessionId, result: response },
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
contextId: sessionId,
|
|
60
|
+
runtime: 'v2',
|
|
61
|
+
replaced: true,
|
|
62
|
+
document: { byteLength: record.byteLength, revision: record.revision },
|
|
63
|
+
};
|
|
64
|
+
}
|
|
42
65
|
/**
|
|
43
66
|
* Builds the argv passed to `spawn` for `superdoc host --stdio`. Propagates
|
|
44
67
|
* `requestTimeoutMs` to the host via `--request-timeout-ms`, since the SDK
|
|
@@ -53,9 +76,6 @@ function buildHostSpawnArgs(prefixArgs, options) {
|
|
|
53
76
|
}
|
|
54
77
|
return args;
|
|
55
78
|
}
|
|
56
|
-
function buildDocumentHostSpawnArgs(prefixArgs) {
|
|
57
|
-
return [...prefixArgs];
|
|
58
|
-
}
|
|
59
79
|
/**
|
|
60
80
|
* Computes the JS-side watchdog timeout for a single JSON-RPC request.
|
|
61
81
|
*
|
|
@@ -81,12 +101,10 @@ function resolveJsWatchdogTimeout(watchdogTimeoutMs, requestTimeoutMs, timeoutMs
|
|
|
81
101
|
}
|
|
82
102
|
return Math.max(watchdogTimeoutMs, HOST_DEFAULT_REQUEST_TIMEOUT_MS + WATCHDOG_HEADROOM_MS);
|
|
83
103
|
}
|
|
84
|
-
/** Transport for the legacy CLI host or the structured document host. */
|
|
85
104
|
class HostTransport {
|
|
86
105
|
stateDirectory;
|
|
87
106
|
stoppedChildren = new Map();
|
|
88
107
|
hostBin;
|
|
89
|
-
processMode;
|
|
90
108
|
env;
|
|
91
109
|
startupTimeoutMs;
|
|
92
110
|
shutdownTimeoutMs;
|
|
@@ -95,7 +113,6 @@ class HostTransport {
|
|
|
95
113
|
maxQueueDepth;
|
|
96
114
|
defaultChangeMode;
|
|
97
115
|
user;
|
|
98
|
-
documentRpcEnabled;
|
|
99
116
|
child = null;
|
|
100
117
|
stdoutBuffer = '';
|
|
101
118
|
stdoutDataListener = null;
|
|
@@ -107,15 +124,10 @@ class HostTransport {
|
|
|
107
124
|
stopping = false;
|
|
108
125
|
activeCalls = new Set();
|
|
109
126
|
hostFeatures = new Set();
|
|
110
|
-
documentRpcSessions = new Set();
|
|
111
127
|
cliLocalSessions = new Set();
|
|
112
|
-
dirtyDocumentRpcSessions = new Set();
|
|
113
|
-
documentRpcMutationStates = new Map();
|
|
114
|
-
indeterminateDiscardCloses = new Set();
|
|
115
128
|
constructor(options) {
|
|
116
129
|
this.stateDirectory = new stateDirectory.SdkStateDirectory(options.stateDir);
|
|
117
130
|
this.hostBin = options.hostBin;
|
|
118
|
-
this.processMode = options.processMode ?? 'cli';
|
|
119
131
|
this.env = options.env;
|
|
120
132
|
this.startupTimeoutMs = options.startupTimeoutMs ?? 5_000;
|
|
121
133
|
this.shutdownTimeoutMs = options.shutdownTimeoutMs ?? 5_000;
|
|
@@ -130,17 +142,12 @@ class HostTransport {
|
|
|
130
142
|
}
|
|
131
143
|
this.defaultChangeMode = options.defaultChangeMode ?? undefined;
|
|
132
144
|
this.user = options.user;
|
|
133
|
-
this.documentRpcEnabled = this.processMode === 'document' || documentRpc.documentRpcEnabled(options.env);
|
|
134
145
|
}
|
|
135
146
|
async connect() {
|
|
136
147
|
await this.runWhileActive(() => this.ensureConnected());
|
|
137
148
|
}
|
|
138
149
|
supportsDocumentFacts(sessionId) {
|
|
139
|
-
return
|
|
140
|
-
(this.documentRpcSessions.has(sessionId) &&
|
|
141
|
-
this.hostFeatures.has('document.currentRevision') &&
|
|
142
|
-
this.hostFeatures.has('document.executionFacts') &&
|
|
143
|
-
this.hostFeatures.has('document.mutationRevision')));
|
|
150
|
+
return this.usesCliDocumentFacts(sessionId);
|
|
144
151
|
}
|
|
145
152
|
usesCliDocumentFacts(sessionId) {
|
|
146
153
|
return this.cliLocalSessions.has(sessionId) && this.hostFeatures.has('cli.invoke.localExecutionFacts');
|
|
@@ -158,18 +165,7 @@ class HostTransport {
|
|
|
158
165
|
throw new errors.SuperDocCliError('CLI returned an invalid execution revision.', { code: 'HOST_PROTOCOL_ERROR' });
|
|
159
166
|
return page.revision;
|
|
160
167
|
}
|
|
161
|
-
|
|
162
|
-
return undefined;
|
|
163
|
-
}
|
|
164
|
-
await this.ensureConnected();
|
|
165
|
-
const revision = await this.sendJsonRpcRequest('document.currentRevision', { sessionId }, this.resolveWatchdogTimeout(undefined), { requestTimeoutMs: this.resolveDocumentRequestTimeout(undefined) });
|
|
166
|
-
if (typeof revision !== 'string' || revision.trim().length === 0 || revision === 'unknown') {
|
|
167
|
-
throw new errors.SuperDocCliError('Document host returned an invalid current revision.', {
|
|
168
|
-
code: 'HOST_PROTOCOL_ERROR',
|
|
169
|
-
details: { sessionId },
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
return revision;
|
|
168
|
+
return undefined;
|
|
173
169
|
});
|
|
174
170
|
}
|
|
175
171
|
async dispose() {
|
|
@@ -204,16 +200,6 @@ class HostTransport {
|
|
|
204
200
|
await this.stateDirectory.dispose();
|
|
205
201
|
return;
|
|
206
202
|
}
|
|
207
|
-
try {
|
|
208
|
-
await this.reconcileIndeterminateDiscardCloses();
|
|
209
|
-
await this.persistDirtyDocumentRpcSessions();
|
|
210
|
-
}
|
|
211
|
-
catch (error) {
|
|
212
|
-
if (!this.child && error instanceof errors.SuperDocCliError) {
|
|
213
|
-
this.terminalDisposalError = error;
|
|
214
|
-
}
|
|
215
|
-
throw error;
|
|
216
|
-
}
|
|
217
203
|
const child = this.child;
|
|
218
204
|
try {
|
|
219
205
|
await this.sendJsonRpcRequest('host.shutdown', {}, this.shutdownTimeoutMs);
|
|
@@ -239,29 +225,14 @@ class HostTransport {
|
|
|
239
225
|
async replaceFile(sessionId, path, options = {}) {
|
|
240
226
|
return this.runWhileActive(async () => {
|
|
241
227
|
await this.ensureConnected();
|
|
242
|
-
if (!this.hostFeatures.has(
|
|
228
|
+
if (!this.hostFeatures.has(sdkPolicy.SDK_POLICY.features.replaceFile)) {
|
|
243
229
|
throw new errors.SuperDocCliError('The connected host does not support document replacement.', {
|
|
244
230
|
code: 'CAPABILITY_UNSUPPORTED',
|
|
245
|
-
details: { feature:
|
|
231
|
+
details: { feature: sdkPolicy.SDK_POLICY.features.replaceFile },
|
|
246
232
|
});
|
|
247
233
|
}
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
this.beginDocumentRpcMutation(sessionId);
|
|
251
|
-
try {
|
|
252
|
-
const response = await this.sendJsonRpcRequest(documentRpc.DOCUMENT_RPC_REPLACE_FILE_FEATURE, { sessionId, path }, this.resolveWatchdogTimeout(options.timeoutMs));
|
|
253
|
-
const result = documentRpc.mapDocumentReplaceFileResult(response, sessionId);
|
|
254
|
-
if (tracksDirectSession)
|
|
255
|
-
this.settleDocumentRpcMutation(sessionId, 'applied');
|
|
256
|
-
return result;
|
|
257
|
-
}
|
|
258
|
-
catch (error) {
|
|
259
|
-
if (tracksDirectSession) {
|
|
260
|
-
const indeterminate = error instanceof errors.SuperDocCliError && ['TIMEOUT', 'HOST_TIMEOUT', 'HOST_DISCONNECTED'].includes(error.code);
|
|
261
|
-
this.settleDocumentRpcMutation(sessionId, indeterminate ? 'indeterminate' : 'not-applied');
|
|
262
|
-
}
|
|
263
|
-
throw error;
|
|
264
|
-
}
|
|
234
|
+
const response = await this.sendJsonRpcRequest(sdkPolicy.SDK_POLICY.features.replaceFile, { sessionId, path }, this.resolveWatchdogTimeout(options.timeoutMs));
|
|
235
|
+
return mapDocumentReplaceFileResult(response, sessionId);
|
|
265
236
|
});
|
|
266
237
|
}
|
|
267
238
|
async invokeWhileActive(operation, params, options) {
|
|
@@ -272,12 +243,6 @@ class HostTransport {
|
|
|
272
243
|
code: 'INVALID_ARGUMENT',
|
|
273
244
|
});
|
|
274
245
|
}
|
|
275
|
-
if (this.processMode !== 'cli') {
|
|
276
|
-
throw new errors.SuperDocCliError('Per-open collaboration authentication is not supported by the standalone document host.', {
|
|
277
|
-
code: 'CAPABILITY_UNSUPPORTED',
|
|
278
|
-
details: { feature: COLLABORATION_AUTH_PER_OPEN_FEATURE },
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
246
|
}
|
|
282
247
|
await this.ensureConnected();
|
|
283
248
|
if (collaborationAuth !== undefined && !this.hostFeatures.has(COLLABORATION_AUTH_PER_OPEN_FEATURE)) {
|
|
@@ -286,88 +251,8 @@ class HostTransport {
|
|
|
286
251
|
details: { feature: COLLABORATION_AUTH_PER_OPEN_FEATURE },
|
|
287
252
|
});
|
|
288
253
|
}
|
|
289
|
-
const shouldOpenThroughCliTimeoutFallback = this.processMode === 'cli' &&
|
|
290
|
-
(this.requestTimeoutMs !== undefined ||
|
|
291
|
-
(options.timeoutMs !== undefined && !this.hostFeatures.has(documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE)));
|
|
292
|
-
if (this.documentRpcEnabled &&
|
|
293
|
-
documentRpc.supportsDocumentRpc(this.hostFeatures) &&
|
|
294
|
-
(this.defaultChangeMode === undefined || this.hostFeatures.has(documentRpc.DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE)) &&
|
|
295
|
-
operation.operationId === 'doc.open' &&
|
|
296
|
-
documentRpc.canOpenWithDocumentRpc(params, options) &&
|
|
297
|
-
!shouldOpenThroughCliTimeoutFallback) {
|
|
298
|
-
const opened = documentRpc.buildDocumentOpenParams(params, this.user, this.defaultChangeMode);
|
|
299
|
-
const requestTimeoutMs = this.resolveDocumentRequestTimeout(options.timeoutMs);
|
|
300
|
-
const response = await this.sendJsonRpcRequest('document.open', opened.params, this.resolveWatchdogTimeout(options.timeoutMs), { requestTimeoutMs });
|
|
301
|
-
const result = documentRpc.mapDocumentOpenResult(response, opened.sessionId, params.doc);
|
|
302
|
-
this.documentRpcSessions.add(opened.sessionId);
|
|
303
|
-
this.indeterminateDiscardCloses.delete(opened.sessionId);
|
|
304
|
-
return result;
|
|
305
|
-
}
|
|
306
254
|
const sessionId = typeof params.sessionId === 'string' ? params.sessionId : undefined;
|
|
307
|
-
|
|
308
|
-
const request = documentRpc.buildDocumentInvokeParams(sessionId, operation, params, options, this.hostFeatures);
|
|
309
|
-
const supportsResponseTimeout = documentRpc.documentRpcRequestSupportsResponseTimeout(operation, request);
|
|
310
|
-
const requestTimeoutMs = supportsResponseTimeout
|
|
311
|
-
? this.resolveDocumentRequestTimeout(options.timeoutMs)
|
|
312
|
-
: undefined;
|
|
313
|
-
const documentOperation = operation;
|
|
314
|
-
const requestOptions = typeof request.params.options === 'object' &&
|
|
315
|
-
request.params.options !== null &&
|
|
316
|
-
!Array.isArray(request.params.options)
|
|
317
|
-
? request.params.options
|
|
318
|
-
: undefined;
|
|
319
|
-
const tracksMutation = request.method === 'document.invoke' && documentOperation.mutates === true && requestOptions?.dryRun !== true;
|
|
320
|
-
const includeRevision = request.method === 'document.invoke' &&
|
|
321
|
-
documentOperation.mutates === true &&
|
|
322
|
-
this.hostFeatures.has('document.mutationRevision');
|
|
323
|
-
if (tracksMutation)
|
|
324
|
-
this.beginDocumentRpcMutation(sessionId);
|
|
325
|
-
let result;
|
|
326
|
-
try {
|
|
327
|
-
const response = await this.sendJsonRpcRequest(request.method, { ...request.params, ...(includeRevision ? { includeRevision: true } : {}) }, this.resolveWatchdogTimeout(options.timeoutMs), { requestTimeoutMs });
|
|
328
|
-
result = documentRpc.mapDocumentLifecycleResult(operation.operationId, includeRevision ? response.result : response, sessionId, operation.operationId === 'doc.save' ? request.params.path === undefined : undefined);
|
|
329
|
-
if (includeRevision)
|
|
330
|
-
documentEvidence.registerMutationRevision(result, response.revision);
|
|
331
|
-
}
|
|
332
|
-
catch (error) {
|
|
333
|
-
if (tracksMutation) {
|
|
334
|
-
const indeterminate = error instanceof errors.SuperDocCliError && ['TIMEOUT', 'HOST_TIMEOUT', 'HOST_DISCONNECTED'].includes(error.code);
|
|
335
|
-
this.settleDocumentRpcMutation(sessionId, indeterminate ? 'indeterminate' : 'not-applied');
|
|
336
|
-
}
|
|
337
|
-
if (operation.operationId === 'doc.close' &&
|
|
338
|
-
request.params.discard === true &&
|
|
339
|
-
error instanceof errors.SuperDocCliError &&
|
|
340
|
-
error.code === 'TIMEOUT') {
|
|
341
|
-
this.indeterminateDiscardCloses.add(sessionId);
|
|
342
|
-
}
|
|
343
|
-
throw error;
|
|
344
|
-
}
|
|
345
|
-
if (tracksMutation) {
|
|
346
|
-
const failedReceipt = typeof result === 'object' &&
|
|
347
|
-
result !== null &&
|
|
348
|
-
!Array.isArray(result) &&
|
|
349
|
-
result.success === false;
|
|
350
|
-
this.settleDocumentRpcMutation(sessionId, failedReceipt ? 'not-applied' : 'applied');
|
|
351
|
-
}
|
|
352
|
-
if (operation.operationId === 'doc.close') {
|
|
353
|
-
this.documentRpcSessions.delete(sessionId);
|
|
354
|
-
this.clearDirtyDocumentRpcSession(sessionId);
|
|
355
|
-
this.indeterminateDiscardCloses.delete(sessionId);
|
|
356
|
-
}
|
|
357
|
-
else if (operation.operationId === 'doc.save') {
|
|
358
|
-
if (request.params.mode === undefined || request.params.mode === 'review-preserving') {
|
|
359
|
-
this.markDocumentRpcSessionSaved(sessionId);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
return result;
|
|
363
|
-
}
|
|
364
|
-
if (this.processMode === 'document') {
|
|
365
|
-
throw new errors.SuperDocCliError(`Standalone document host does not support ${operation.operationId} through structured RPC v0.`, {
|
|
366
|
-
code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
|
|
367
|
-
details: { operationId: operation.operationId },
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
const supportsRequestTimeoutMetadata = this.hostFeatures.has(documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE);
|
|
255
|
+
const supportsRequestTimeoutMetadata = this.hostFeatures.has(HOST_REQUEST_TIMEOUT_FEATURE);
|
|
371
256
|
const cliHostRequestTimeoutMs = this.requestTimeoutMs ?? HOST_DEFAULT_REQUEST_TIMEOUT_MS;
|
|
372
257
|
if (!supportsRequestTimeoutMetadata &&
|
|
373
258
|
options.timeoutMs !== undefined &&
|
|
@@ -375,7 +260,7 @@ class HostTransport {
|
|
|
375
260
|
throw new errors.SuperDocCliError(`CLI host cannot honor timeoutMs=${options.timeoutMs} above its ${cliHostRequestTimeoutMs}ms request ceiling.`, {
|
|
376
261
|
code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
|
|
377
262
|
details: {
|
|
378
|
-
feature:
|
|
263
|
+
feature: HOST_REQUEST_TIMEOUT_FEATURE,
|
|
379
264
|
operationId: operation.operationId,
|
|
380
265
|
timeoutMs: options.timeoutMs,
|
|
381
266
|
hostRequestTimeoutMs: cliHostRequestTimeoutMs,
|
|
@@ -458,9 +343,7 @@ class HostTransport {
|
|
|
458
343
|
}
|
|
459
344
|
async startHostProcess() {
|
|
460
345
|
const { command, prefixArgs } = transportCommon.resolveInvocation(this.hostBin);
|
|
461
|
-
const args = this.
|
|
462
|
-
? buildDocumentHostSpawnArgs(prefixArgs)
|
|
463
|
-
: buildHostSpawnArgs(prefixArgs, { requestTimeoutMs: this.requestTimeoutMs });
|
|
346
|
+
const args = buildHostSpawnArgs(prefixArgs, { requestTimeoutMs: this.requestTimeoutMs });
|
|
464
347
|
await this.waitForStoppedChildren();
|
|
465
348
|
const env = { ...process.env, ...this.env };
|
|
466
349
|
env.SUPERDOC_CLI_STATE_DIR = await this.stateDirectory.prepare(env);
|
|
@@ -495,7 +378,7 @@ class HostTransport {
|
|
|
495
378
|
child.on('close', (code, signal) => {
|
|
496
379
|
if (this.child !== child)
|
|
497
380
|
return;
|
|
498
|
-
if (this.stopping
|
|
381
|
+
if (this.stopping) {
|
|
499
382
|
this.cleanupProcess(null);
|
|
500
383
|
return;
|
|
501
384
|
}
|
|
@@ -546,13 +429,7 @@ class HostTransport {
|
|
|
546
429
|
details: { features },
|
|
547
430
|
});
|
|
548
431
|
}
|
|
549
|
-
const requiredFeatures =
|
|
550
|
-
? [
|
|
551
|
-
...DOCUMENT_HOST_REQUIRED_FEATURES,
|
|
552
|
-
...(this.defaultChangeMode === undefined ? [] : [documentRpc.DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE]),
|
|
553
|
-
...(this.requestTimeoutMs === undefined ? [] : [documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE]),
|
|
554
|
-
]
|
|
555
|
-
: CLI_HOST_REQUIRED_FEATURES;
|
|
432
|
+
const requiredFeatures = CLI_HOST_REQUIRED_FEATURES;
|
|
556
433
|
for (const requiredFeature of requiredFeatures) {
|
|
557
434
|
if (!features.includes(requiredFeature)) {
|
|
558
435
|
throw new errors.SuperDocCliError(`Host does not support required feature: ${requiredFeature}`, {
|
|
@@ -568,78 +445,6 @@ class HostTransport {
|
|
|
568
445
|
resolveWatchdogTimeout(timeoutMsOverride) {
|
|
569
446
|
return resolveJsWatchdogTimeout(this.watchdogTimeoutMs, this.requestTimeoutMs, timeoutMsOverride);
|
|
570
447
|
}
|
|
571
|
-
resolveDocumentRequestTimeout(timeoutMsOverride) {
|
|
572
|
-
const requestTimeoutMs = timeoutMsOverride ?? this.requestTimeoutMs;
|
|
573
|
-
if (requestTimeoutMs === undefined)
|
|
574
|
-
return undefined;
|
|
575
|
-
if (this.hostFeatures.has(documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE))
|
|
576
|
-
return requestTimeoutMs;
|
|
577
|
-
if (this.processMode === 'cli' && timeoutMsOverride === undefined)
|
|
578
|
-
return undefined;
|
|
579
|
-
throw new errors.SuperDocCliError(`Structured document RPC host does not support ${documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE}.`, {
|
|
580
|
-
code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
|
|
581
|
-
details: { feature: documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE },
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
beginDocumentRpcMutation(sessionId) {
|
|
585
|
-
const state = this.documentRpcMutationStates.get(sessionId) ?? {
|
|
586
|
-
confirmedDirty: this.dirtyDocumentRpcSessions.has(sessionId),
|
|
587
|
-
pendingCount: 0,
|
|
588
|
-
};
|
|
589
|
-
state.pendingCount += 1;
|
|
590
|
-
this.documentRpcMutationStates.set(sessionId, state);
|
|
591
|
-
this.dirtyDocumentRpcSessions.add(sessionId);
|
|
592
|
-
}
|
|
593
|
-
settleDocumentRpcMutation(sessionId, outcome) {
|
|
594
|
-
const state = this.documentRpcMutationStates.get(sessionId);
|
|
595
|
-
if (!state)
|
|
596
|
-
return;
|
|
597
|
-
state.pendingCount = Math.max(0, state.pendingCount - 1);
|
|
598
|
-
if (outcome !== 'not-applied')
|
|
599
|
-
state.confirmedDirty = true;
|
|
600
|
-
if (state.confirmedDirty || state.pendingCount > 0) {
|
|
601
|
-
this.dirtyDocumentRpcSessions.add(sessionId);
|
|
602
|
-
return;
|
|
603
|
-
}
|
|
604
|
-
this.clearDirtyDocumentRpcSession(sessionId);
|
|
605
|
-
}
|
|
606
|
-
clearDirtyDocumentRpcSession(sessionId) {
|
|
607
|
-
this.dirtyDocumentRpcSessions.delete(sessionId);
|
|
608
|
-
this.documentRpcMutationStates.delete(sessionId);
|
|
609
|
-
}
|
|
610
|
-
markDocumentRpcSessionSaved(sessionId) {
|
|
611
|
-
const state = this.documentRpcMutationStates.get(sessionId);
|
|
612
|
-
if (!state || state.pendingCount === 0) {
|
|
613
|
-
this.clearDirtyDocumentRpcSession(sessionId);
|
|
614
|
-
return;
|
|
615
|
-
}
|
|
616
|
-
state.confirmedDirty = false;
|
|
617
|
-
this.dirtyDocumentRpcSessions.add(sessionId);
|
|
618
|
-
}
|
|
619
|
-
async persistDirtyDocumentRpcSessions() {
|
|
620
|
-
if (this.dirtyDocumentRpcSessions.size === 0)
|
|
621
|
-
return;
|
|
622
|
-
if (!this.hostFeatures.has(documentRpc.DOCUMENT_RPC_SOURCE_SAVE_FEATURE)) {
|
|
623
|
-
throw new errors.SuperDocCliError('Document host cannot persist dirty sessions during client disposal because it does not support source saves.', {
|
|
624
|
-
code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
|
|
625
|
-
details: { feature: documentRpc.DOCUMENT_RPC_SOURCE_SAVE_FEATURE },
|
|
626
|
-
});
|
|
627
|
-
}
|
|
628
|
-
for (const sessionId of this.dirtyDocumentRpcSessions) {
|
|
629
|
-
const response = await this.sendJsonRpcRequest('document.save', { sessionId }, this.resolveWatchdogTimeout(undefined));
|
|
630
|
-
documentRpc.mapDocumentLifecycleResult('doc.save', response, sessionId, true);
|
|
631
|
-
this.markDocumentRpcSessionSaved(sessionId);
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
async reconcileIndeterminateDiscardCloses() {
|
|
635
|
-
for (const sessionId of this.indeterminateDiscardCloses) {
|
|
636
|
-
const response = await this.sendJsonRpcRequest('document.close', { sessionId, discard: true }, this.resolveWatchdogTimeout(undefined));
|
|
637
|
-
documentRpc.mapDocumentLifecycleResult('doc.close', response, sessionId);
|
|
638
|
-
this.documentRpcSessions.delete(sessionId);
|
|
639
|
-
this.clearDirtyDocumentRpcSession(sessionId);
|
|
640
|
-
this.indeterminateDiscardCloses.delete(sessionId);
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
448
|
async sendJsonRpcRequest(method, params, watchdogTimeoutMs, metadata = {}) {
|
|
644
449
|
const child = this.child;
|
|
645
450
|
if (!child || !child.stdin.writable) {
|
|
@@ -813,17 +618,7 @@ class HostTransport {
|
|
|
813
618
|
this.cleanupProcess(error);
|
|
814
619
|
}
|
|
815
620
|
cleanupProcess(error) {
|
|
816
|
-
if (error && this.dirtyDocumentRpcSessions.size > 0 && !this.terminalDisposalError) {
|
|
817
|
-
this.terminalDisposalError = new errors.SuperDocCliError('Document host disconnected before dirty sessions could be persisted.', {
|
|
818
|
-
code: 'HOST_DISCONNECTED',
|
|
819
|
-
details: { causeCode: error.code, causeDetails: error.details },
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
621
|
this.hostFeatures.clear();
|
|
823
|
-
this.documentRpcSessions.clear();
|
|
824
|
-
this.dirtyDocumentRpcSessions.clear();
|
|
825
|
-
this.documentRpcMutationStates.clear();
|
|
826
|
-
this.indeterminateDiscardCloses.clear();
|
|
827
622
|
const child = this.child;
|
|
828
623
|
if (child) {
|
|
829
624
|
if (this.stdoutDataListener)
|
|
@@ -849,7 +644,7 @@ class HostTransport {
|
|
|
849
644
|
|
|
850
645
|
exports.COLLABORATION_AUTH_PER_OPEN_FEATURE = COLLABORATION_AUTH_PER_OPEN_FEATURE;
|
|
851
646
|
exports.HostTransport = HostTransport;
|
|
852
|
-
exports.buildDocumentHostSpawnArgs = buildDocumentHostSpawnArgs;
|
|
853
647
|
exports.buildHostSpawnArgs = buildHostSpawnArgs;
|
|
854
648
|
exports.mapCliInvocationResult = mapCliInvocationResult;
|
|
649
|
+
exports.mapDocumentReplaceFileResult = mapDocumentReplaceFileResult;
|
|
855
650
|
exports.resolveJsWatchdogTimeout = resolveJsWatchdogTimeout;
|
package/dist/runtime/host.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type OperationSpec, type SuperDocClientOptions, type TransportInvokeOptions } from './transport-common.js';
|
|
2
2
|
export declare const COLLABORATION_AUTH_PER_OPEN_FEATURE: string;
|
|
3
3
|
export declare function mapCliInvocationResult(operation: OperationSpec, value: unknown): unknown;
|
|
4
|
+
export declare function mapDocumentReplaceFileResult(response: unknown, sessionId: string): Record<string, unknown>;
|
|
4
5
|
/**
|
|
5
6
|
* Builds the argv passed to `spawn` for `superdoc host --stdio`. Propagates
|
|
6
7
|
* `requestTimeoutMs` to the host via `--request-timeout-ms`, since the SDK
|
|
@@ -11,7 +12,6 @@ export declare function mapCliInvocationResult(operation: OperationSpec, value:
|
|
|
11
12
|
export declare function buildHostSpawnArgs(prefixArgs: readonly string[], options: {
|
|
12
13
|
requestTimeoutMs?: number;
|
|
13
14
|
}): string[];
|
|
14
|
-
export declare function buildDocumentHostSpawnArgs(prefixArgs: readonly string[]): string[];
|
|
15
15
|
/**
|
|
16
16
|
* Computes the JS-side watchdog timeout for a single JSON-RPC request.
|
|
17
17
|
*
|
|
@@ -29,12 +29,10 @@ export declare function buildDocumentHostSpawnArgs(prefixArgs: readonly string[]
|
|
|
29
29
|
* Exported for unit testing.
|
|
30
30
|
*/
|
|
31
31
|
export declare function resolveJsWatchdogTimeout(watchdogTimeoutMs: number, requestTimeoutMs: number | undefined, timeoutMsOverride: number | undefined): number;
|
|
32
|
-
/** Transport for the legacy CLI host or the structured document host. */
|
|
33
32
|
export declare class HostTransport {
|
|
34
33
|
private readonly stateDirectory;
|
|
35
34
|
private readonly stoppedChildren;
|
|
36
35
|
private readonly hostBin;
|
|
37
|
-
private readonly processMode;
|
|
38
36
|
private readonly env?;
|
|
39
37
|
private readonly startupTimeoutMs;
|
|
40
38
|
private readonly shutdownTimeoutMs;
|
|
@@ -43,7 +41,6 @@ export declare class HostTransport {
|
|
|
43
41
|
private readonly maxQueueDepth;
|
|
44
42
|
private readonly defaultChangeMode?;
|
|
45
43
|
private readonly user?;
|
|
46
|
-
private readonly documentRpcEnabled;
|
|
47
44
|
private child;
|
|
48
45
|
private stdoutBuffer;
|
|
49
46
|
private stdoutDataListener;
|
|
@@ -55,14 +52,9 @@ export declare class HostTransport {
|
|
|
55
52
|
private stopping;
|
|
56
53
|
private readonly activeCalls;
|
|
57
54
|
private readonly hostFeatures;
|
|
58
|
-
private readonly documentRpcSessions;
|
|
59
55
|
private readonly cliLocalSessions;
|
|
60
|
-
private readonly dirtyDocumentRpcSessions;
|
|
61
|
-
private readonly documentRpcMutationStates;
|
|
62
|
-
private readonly indeterminateDiscardCloses;
|
|
63
56
|
constructor(options: {
|
|
64
57
|
hostBin: string;
|
|
65
|
-
processMode?: 'cli' | 'document';
|
|
66
58
|
} & SuperDocClientOptions);
|
|
67
59
|
connect(): Promise<void>;
|
|
68
60
|
supportsDocumentFacts(sessionId: string): boolean;
|
|
@@ -78,13 +70,6 @@ export declare class HostTransport {
|
|
|
78
70
|
private startHostProcess;
|
|
79
71
|
private assertCapabilities;
|
|
80
72
|
private resolveWatchdogTimeout;
|
|
81
|
-
private resolveDocumentRequestTimeout;
|
|
82
|
-
private beginDocumentRpcMutation;
|
|
83
|
-
private settleDocumentRpcMutation;
|
|
84
|
-
private clearDirtyDocumentRpcSession;
|
|
85
|
-
private markDocumentRpcSessionSaved;
|
|
86
|
-
private persistDirtyDocumentRpcSessions;
|
|
87
|
-
private reconcileIndeterminateDiscardCloses;
|
|
88
73
|
private sendJsonRpcRequest;
|
|
89
74
|
private onStdoutLine;
|
|
90
75
|
private onStdoutChunk;
|