@superdoc/sdk 2.26.0-next.1 → 2.26.0-next.16

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.
@@ -5,11 +5,10 @@ import { SdkStateDirectory } from './state-directory.js';
5
5
  import { registerMutationRevision } from './document-evidence.js';
6
6
  import { CONTRACT } from '../generated/contract.js';
7
7
  import { SDK_POLICY } from './sdk-policy.js';
8
- import { DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE, DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE, DOCUMENT_RPC_REPLACE_FILE_FEATURE, DOCUMENT_RPC_SOURCE_SAVE_FEATURE, buildDocumentInvokeParams, buildDocumentOpenParams, canOpenWithDocumentRpc, documentRpcRequestSupportsResponseTimeout, documentRpcEnabled, mapDocumentLifecycleResult, mapDocumentOpenResult, mapDocumentReplaceFileResult, supportsDocumentRpc, } from './document-rpc.js';
9
8
  const HOST_PROTOCOL_VERSION = SDK_POLICY.protocolVersion;
10
9
  const CLI_HOST_REQUIRED_FEATURES = SDK_POLICY.cliRequiredFeatures;
11
10
  export const COLLABORATION_AUTH_PER_OPEN_FEATURE = SDK_POLICY.features.collaborationAuthPerOpen;
12
- const DOCUMENT_HOST_REQUIRED_FEATURES = SDK_POLICY.documentRequiredFeatures;
11
+ const HOST_REQUEST_TIMEOUT_FEATURE = SDK_POLICY.features.requestTimeout;
13
12
  const CHANGE_MODES = ['direct', 'tracked'];
14
13
  const FORWARD_HOST_STDERR = typeof process !== 'undefined' && typeof process.env?.SUPERDOC_DEBUG_TEXT_REWRITE === 'string'
15
14
  ? process.env.SUPERDOC_DEBUG_TEXT_REWRITE === '1'
@@ -36,6 +35,30 @@ export function mapCliInvocationResult(operation, value) {
36
35
  const extracted = value[envelopeKey];
37
36
  return extracted === undefined ? value : extracted;
38
37
  }
38
+ export function mapDocumentReplaceFileResult(response, sessionId) {
39
+ if (typeof response !== 'object' || response == null || Array.isArray(response)) {
40
+ throw new SuperDocCliError('Host returned invalid document.replaceFile result.', {
41
+ code: 'HOST_PROTOCOL_ERROR',
42
+ details: { result: response },
43
+ });
44
+ }
45
+ const record = response;
46
+ if (record.sessionId !== sessionId ||
47
+ record.replaced !== true ||
48
+ typeof record.byteLength !== 'number' ||
49
+ typeof record.revision !== 'string') {
50
+ throw new SuperDocCliError('Host returned invalid document.replaceFile session metadata.', {
51
+ code: 'HOST_PROTOCOL_ERROR',
52
+ details: { expectedSessionId: sessionId, result: response },
53
+ });
54
+ }
55
+ return {
56
+ contextId: sessionId,
57
+ runtime: 'v2',
58
+ replaced: true,
59
+ document: { byteLength: record.byteLength, revision: record.revision },
60
+ };
61
+ }
39
62
  /**
40
63
  * Builds the argv passed to `spawn` for `superdoc host --stdio`. Propagates
41
64
  * `requestTimeoutMs` to the host via `--request-timeout-ms`, since the SDK
@@ -50,9 +73,6 @@ export function buildHostSpawnArgs(prefixArgs, options) {
50
73
  }
51
74
  return args;
52
75
  }
53
- export function buildDocumentHostSpawnArgs(prefixArgs) {
54
- return [...prefixArgs];
55
- }
56
76
  /**
57
77
  * Computes the JS-side watchdog timeout for a single JSON-RPC request.
58
78
  *
@@ -78,12 +98,10 @@ export function resolveJsWatchdogTimeout(watchdogTimeoutMs, requestTimeoutMs, ti
78
98
  }
79
99
  return Math.max(watchdogTimeoutMs, HOST_DEFAULT_REQUEST_TIMEOUT_MS + WATCHDOG_HEADROOM_MS);
80
100
  }
81
- /** Transport for the legacy CLI host or the structured document host. */
82
101
  export class HostTransport {
83
102
  stateDirectory;
84
103
  stoppedChildren = new Map();
85
104
  hostBin;
86
- processMode;
87
105
  env;
88
106
  startupTimeoutMs;
89
107
  shutdownTimeoutMs;
@@ -92,7 +110,6 @@ export class HostTransport {
92
110
  maxQueueDepth;
93
111
  defaultChangeMode;
94
112
  user;
95
- documentRpcEnabled;
96
113
  child = null;
97
114
  stdoutBuffer = '';
98
115
  stdoutDataListener = null;
@@ -104,15 +121,10 @@ export class HostTransport {
104
121
  stopping = false;
105
122
  activeCalls = new Set();
106
123
  hostFeatures = new Set();
107
- documentRpcSessions = new Set();
108
124
  cliLocalSessions = new Set();
109
- dirtyDocumentRpcSessions = new Set();
110
- documentRpcMutationStates = new Map();
111
- indeterminateDiscardCloses = new Set();
112
125
  constructor(options) {
113
126
  this.stateDirectory = new SdkStateDirectory(options.stateDir);
114
127
  this.hostBin = options.hostBin;
115
- this.processMode = options.processMode ?? 'cli';
116
128
  this.env = options.env;
117
129
  this.startupTimeoutMs = options.startupTimeoutMs ?? 5_000;
118
130
  this.shutdownTimeoutMs = options.shutdownTimeoutMs ?? 5_000;
@@ -127,17 +139,12 @@ export class HostTransport {
127
139
  }
128
140
  this.defaultChangeMode = options.defaultChangeMode ?? undefined;
129
141
  this.user = options.user;
130
- this.documentRpcEnabled = this.processMode === 'document' || documentRpcEnabled(options.env);
131
142
  }
132
143
  async connect() {
133
144
  await this.runWhileActive(() => this.ensureConnected());
134
145
  }
135
146
  supportsDocumentFacts(sessionId) {
136
- return (this.usesCliDocumentFacts(sessionId) ||
137
- (this.documentRpcSessions.has(sessionId) &&
138
- this.hostFeatures.has('document.currentRevision') &&
139
- this.hostFeatures.has('document.executionFacts') &&
140
- this.hostFeatures.has('document.mutationRevision')));
147
+ return this.usesCliDocumentFacts(sessionId);
141
148
  }
142
149
  usesCliDocumentFacts(sessionId) {
143
150
  return this.cliLocalSessions.has(sessionId) && this.hostFeatures.has('cli.invoke.localExecutionFacts');
@@ -155,18 +162,7 @@ export class HostTransport {
155
162
  throw new SuperDocCliError('CLI returned an invalid execution revision.', { code: 'HOST_PROTOCOL_ERROR' });
156
163
  return page.revision;
157
164
  }
158
- if (!this.documentRpcSessions.has(sessionId) || !this.hostFeatures.has('document.currentRevision')) {
159
- return undefined;
160
- }
161
- await this.ensureConnected();
162
- const revision = await this.sendJsonRpcRequest('document.currentRevision', { sessionId }, this.resolveWatchdogTimeout(undefined), { requestTimeoutMs: this.resolveDocumentRequestTimeout(undefined) });
163
- if (typeof revision !== 'string' || revision.trim().length === 0 || revision === 'unknown') {
164
- throw new SuperDocCliError('Document host returned an invalid current revision.', {
165
- code: 'HOST_PROTOCOL_ERROR',
166
- details: { sessionId },
167
- });
168
- }
169
- return revision;
165
+ return undefined;
170
166
  });
171
167
  }
172
168
  async dispose() {
@@ -201,16 +197,6 @@ export class HostTransport {
201
197
  await this.stateDirectory.dispose();
202
198
  return;
203
199
  }
204
- try {
205
- await this.reconcileIndeterminateDiscardCloses();
206
- await this.persistDirtyDocumentRpcSessions();
207
- }
208
- catch (error) {
209
- if (!this.child && error instanceof SuperDocCliError) {
210
- this.terminalDisposalError = error;
211
- }
212
- throw error;
213
- }
214
200
  const child = this.child;
215
201
  try {
216
202
  await this.sendJsonRpcRequest('host.shutdown', {}, this.shutdownTimeoutMs);
@@ -236,29 +222,14 @@ export class HostTransport {
236
222
  async replaceFile(sessionId, path, options = {}) {
237
223
  return this.runWhileActive(async () => {
238
224
  await this.ensureConnected();
239
- if (!this.hostFeatures.has(DOCUMENT_RPC_REPLACE_FILE_FEATURE)) {
225
+ if (!this.hostFeatures.has(SDK_POLICY.features.replaceFile)) {
240
226
  throw new SuperDocCliError('The connected host does not support document replacement.', {
241
227
  code: 'CAPABILITY_UNSUPPORTED',
242
- details: { feature: DOCUMENT_RPC_REPLACE_FILE_FEATURE },
228
+ details: { feature: SDK_POLICY.features.replaceFile },
243
229
  });
244
230
  }
245
- const tracksDirectSession = this.documentRpcSessions.has(sessionId);
246
- if (tracksDirectSession)
247
- this.beginDocumentRpcMutation(sessionId);
248
- try {
249
- const response = await this.sendJsonRpcRequest(DOCUMENT_RPC_REPLACE_FILE_FEATURE, { sessionId, path }, this.resolveWatchdogTimeout(options.timeoutMs));
250
- const result = mapDocumentReplaceFileResult(response, sessionId);
251
- if (tracksDirectSession)
252
- this.settleDocumentRpcMutation(sessionId, 'applied');
253
- return result;
254
- }
255
- catch (error) {
256
- if (tracksDirectSession) {
257
- const indeterminate = error instanceof SuperDocCliError && ['TIMEOUT', 'HOST_TIMEOUT', 'HOST_DISCONNECTED'].includes(error.code);
258
- this.settleDocumentRpcMutation(sessionId, indeterminate ? 'indeterminate' : 'not-applied');
259
- }
260
- throw error;
261
- }
231
+ const response = await this.sendJsonRpcRequest(SDK_POLICY.features.replaceFile, { sessionId, path }, this.resolveWatchdogTimeout(options.timeoutMs));
232
+ return mapDocumentReplaceFileResult(response, sessionId);
262
233
  });
263
234
  }
264
235
  async invokeWhileActive(operation, params, options) {
@@ -269,12 +240,6 @@ export class HostTransport {
269
240
  code: 'INVALID_ARGUMENT',
270
241
  });
271
242
  }
272
- if (this.processMode !== 'cli') {
273
- throw new SuperDocCliError('Per-open collaboration authentication is not supported by the standalone document host.', {
274
- code: 'CAPABILITY_UNSUPPORTED',
275
- details: { feature: COLLABORATION_AUTH_PER_OPEN_FEATURE },
276
- });
277
- }
278
243
  }
279
244
  await this.ensureConnected();
280
245
  if (collaborationAuth !== undefined && !this.hostFeatures.has(COLLABORATION_AUTH_PER_OPEN_FEATURE)) {
@@ -283,88 +248,8 @@ export class HostTransport {
283
248
  details: { feature: COLLABORATION_AUTH_PER_OPEN_FEATURE },
284
249
  });
285
250
  }
286
- const shouldOpenThroughCliTimeoutFallback = this.processMode === 'cli' &&
287
- (this.requestTimeoutMs !== undefined ||
288
- (options.timeoutMs !== undefined && !this.hostFeatures.has(DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE)));
289
- if (this.documentRpcEnabled &&
290
- supportsDocumentRpc(this.hostFeatures) &&
291
- (this.defaultChangeMode === undefined || this.hostFeatures.has(DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE)) &&
292
- operation.operationId === 'doc.open' &&
293
- canOpenWithDocumentRpc(params, options) &&
294
- !shouldOpenThroughCliTimeoutFallback) {
295
- const opened = buildDocumentOpenParams(params, this.user, this.defaultChangeMode);
296
- const requestTimeoutMs = this.resolveDocumentRequestTimeout(options.timeoutMs);
297
- const response = await this.sendJsonRpcRequest('document.open', opened.params, this.resolveWatchdogTimeout(options.timeoutMs), { requestTimeoutMs });
298
- const result = mapDocumentOpenResult(response, opened.sessionId, params.doc);
299
- this.documentRpcSessions.add(opened.sessionId);
300
- this.indeterminateDiscardCloses.delete(opened.sessionId);
301
- return result;
302
- }
303
251
  const sessionId = typeof params.sessionId === 'string' ? params.sessionId : undefined;
304
- if (sessionId !== undefined && this.documentRpcSessions.has(sessionId)) {
305
- const request = buildDocumentInvokeParams(sessionId, operation, params, options, this.hostFeatures);
306
- const supportsResponseTimeout = documentRpcRequestSupportsResponseTimeout(operation, request);
307
- const requestTimeoutMs = supportsResponseTimeout
308
- ? this.resolveDocumentRequestTimeout(options.timeoutMs)
309
- : undefined;
310
- const documentOperation = operation;
311
- const requestOptions = typeof request.params.options === 'object' &&
312
- request.params.options !== null &&
313
- !Array.isArray(request.params.options)
314
- ? request.params.options
315
- : undefined;
316
- const tracksMutation = request.method === 'document.invoke' && documentOperation.mutates === true && requestOptions?.dryRun !== true;
317
- const includeRevision = request.method === 'document.invoke' &&
318
- documentOperation.mutates === true &&
319
- this.hostFeatures.has('document.mutationRevision');
320
- if (tracksMutation)
321
- this.beginDocumentRpcMutation(sessionId);
322
- let result;
323
- try {
324
- const response = await this.sendJsonRpcRequest(request.method, { ...request.params, ...(includeRevision ? { includeRevision: true } : {}) }, this.resolveWatchdogTimeout(options.timeoutMs), { requestTimeoutMs });
325
- result = mapDocumentLifecycleResult(operation.operationId, includeRevision ? response.result : response, sessionId, operation.operationId === 'doc.save' ? request.params.path === undefined : undefined);
326
- if (includeRevision)
327
- registerMutationRevision(result, response.revision);
328
- }
329
- catch (error) {
330
- if (tracksMutation) {
331
- const indeterminate = error instanceof SuperDocCliError && ['TIMEOUT', 'HOST_TIMEOUT', 'HOST_DISCONNECTED'].includes(error.code);
332
- this.settleDocumentRpcMutation(sessionId, indeterminate ? 'indeterminate' : 'not-applied');
333
- }
334
- if (operation.operationId === 'doc.close' &&
335
- request.params.discard === true &&
336
- error instanceof SuperDocCliError &&
337
- error.code === 'TIMEOUT') {
338
- this.indeterminateDiscardCloses.add(sessionId);
339
- }
340
- throw error;
341
- }
342
- if (tracksMutation) {
343
- const failedReceipt = typeof result === 'object' &&
344
- result !== null &&
345
- !Array.isArray(result) &&
346
- result.success === false;
347
- this.settleDocumentRpcMutation(sessionId, failedReceipt ? 'not-applied' : 'applied');
348
- }
349
- if (operation.operationId === 'doc.close') {
350
- this.documentRpcSessions.delete(sessionId);
351
- this.clearDirtyDocumentRpcSession(sessionId);
352
- this.indeterminateDiscardCloses.delete(sessionId);
353
- }
354
- else if (operation.operationId === 'doc.save') {
355
- if (request.params.mode === undefined || request.params.mode === 'review-preserving') {
356
- this.markDocumentRpcSessionSaved(sessionId);
357
- }
358
- }
359
- return result;
360
- }
361
- if (this.processMode === 'document') {
362
- throw new SuperDocCliError(`Standalone document host does not support ${operation.operationId} through structured RPC v0.`, {
363
- code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
364
- details: { operationId: operation.operationId },
365
- });
366
- }
367
- const supportsRequestTimeoutMetadata = this.hostFeatures.has(DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE);
252
+ const supportsRequestTimeoutMetadata = this.hostFeatures.has(HOST_REQUEST_TIMEOUT_FEATURE);
368
253
  const cliHostRequestTimeoutMs = this.requestTimeoutMs ?? HOST_DEFAULT_REQUEST_TIMEOUT_MS;
369
254
  if (!supportsRequestTimeoutMetadata &&
370
255
  options.timeoutMs !== undefined &&
@@ -372,7 +257,7 @@ export class HostTransport {
372
257
  throw new SuperDocCliError(`CLI host cannot honor timeoutMs=${options.timeoutMs} above its ${cliHostRequestTimeoutMs}ms request ceiling.`, {
373
258
  code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
374
259
  details: {
375
- feature: DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE,
260
+ feature: HOST_REQUEST_TIMEOUT_FEATURE,
376
261
  operationId: operation.operationId,
377
262
  timeoutMs: options.timeoutMs,
378
263
  hostRequestTimeoutMs: cliHostRequestTimeoutMs,
@@ -455,9 +340,7 @@ export class HostTransport {
455
340
  }
456
341
  async startHostProcess() {
457
342
  const { command, prefixArgs } = resolveInvocation(this.hostBin);
458
- const args = this.processMode === 'document'
459
- ? buildDocumentHostSpawnArgs(prefixArgs)
460
- : buildHostSpawnArgs(prefixArgs, { requestTimeoutMs: this.requestTimeoutMs });
343
+ const args = buildHostSpawnArgs(prefixArgs, { requestTimeoutMs: this.requestTimeoutMs });
461
344
  await this.waitForStoppedChildren();
462
345
  const env = { ...process.env, ...this.env };
463
346
  env.SUPERDOC_CLI_STATE_DIR = await this.stateDirectory.prepare(env);
@@ -492,7 +375,7 @@ export class HostTransport {
492
375
  child.on('close', (code, signal) => {
493
376
  if (this.child !== child)
494
377
  return;
495
- if (this.stopping && this.dirtyDocumentRpcSessions.size === 0) {
378
+ if (this.stopping) {
496
379
  this.cleanupProcess(null);
497
380
  return;
498
381
  }
@@ -543,13 +426,7 @@ export class HostTransport {
543
426
  details: { features },
544
427
  });
545
428
  }
546
- const requiredFeatures = this.processMode === 'document'
547
- ? [
548
- ...DOCUMENT_HOST_REQUIRED_FEATURES,
549
- ...(this.defaultChangeMode === undefined ? [] : [DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE]),
550
- ...(this.requestTimeoutMs === undefined ? [] : [DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE]),
551
- ]
552
- : CLI_HOST_REQUIRED_FEATURES;
429
+ const requiredFeatures = CLI_HOST_REQUIRED_FEATURES;
553
430
  for (const requiredFeature of requiredFeatures) {
554
431
  if (!features.includes(requiredFeature)) {
555
432
  throw new SuperDocCliError(`Host does not support required feature: ${requiredFeature}`, {
@@ -565,78 +442,6 @@ export class HostTransport {
565
442
  resolveWatchdogTimeout(timeoutMsOverride) {
566
443
  return resolveJsWatchdogTimeout(this.watchdogTimeoutMs, this.requestTimeoutMs, timeoutMsOverride);
567
444
  }
568
- resolveDocumentRequestTimeout(timeoutMsOverride) {
569
- const requestTimeoutMs = timeoutMsOverride ?? this.requestTimeoutMs;
570
- if (requestTimeoutMs === undefined)
571
- return undefined;
572
- if (this.hostFeatures.has(DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE))
573
- return requestTimeoutMs;
574
- if (this.processMode === 'cli' && timeoutMsOverride === undefined)
575
- return undefined;
576
- throw new SuperDocCliError(`Structured document RPC host does not support ${DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE}.`, {
577
- code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
578
- details: { feature: DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE },
579
- });
580
- }
581
- beginDocumentRpcMutation(sessionId) {
582
- const state = this.documentRpcMutationStates.get(sessionId) ?? {
583
- confirmedDirty: this.dirtyDocumentRpcSessions.has(sessionId),
584
- pendingCount: 0,
585
- };
586
- state.pendingCount += 1;
587
- this.documentRpcMutationStates.set(sessionId, state);
588
- this.dirtyDocumentRpcSessions.add(sessionId);
589
- }
590
- settleDocumentRpcMutation(sessionId, outcome) {
591
- const state = this.documentRpcMutationStates.get(sessionId);
592
- if (!state)
593
- return;
594
- state.pendingCount = Math.max(0, state.pendingCount - 1);
595
- if (outcome !== 'not-applied')
596
- state.confirmedDirty = true;
597
- if (state.confirmedDirty || state.pendingCount > 0) {
598
- this.dirtyDocumentRpcSessions.add(sessionId);
599
- return;
600
- }
601
- this.clearDirtyDocumentRpcSession(sessionId);
602
- }
603
- clearDirtyDocumentRpcSession(sessionId) {
604
- this.dirtyDocumentRpcSessions.delete(sessionId);
605
- this.documentRpcMutationStates.delete(sessionId);
606
- }
607
- markDocumentRpcSessionSaved(sessionId) {
608
- const state = this.documentRpcMutationStates.get(sessionId);
609
- if (!state || state.pendingCount === 0) {
610
- this.clearDirtyDocumentRpcSession(sessionId);
611
- return;
612
- }
613
- state.confirmedDirty = false;
614
- this.dirtyDocumentRpcSessions.add(sessionId);
615
- }
616
- async persistDirtyDocumentRpcSessions() {
617
- if (this.dirtyDocumentRpcSessions.size === 0)
618
- return;
619
- if (!this.hostFeatures.has(DOCUMENT_RPC_SOURCE_SAVE_FEATURE)) {
620
- throw new SuperDocCliError('Document host cannot persist dirty sessions during client disposal because it does not support source saves.', {
621
- code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
622
- details: { feature: DOCUMENT_RPC_SOURCE_SAVE_FEATURE },
623
- });
624
- }
625
- for (const sessionId of this.dirtyDocumentRpcSessions) {
626
- const response = await this.sendJsonRpcRequest('document.save', { sessionId }, this.resolveWatchdogTimeout(undefined));
627
- mapDocumentLifecycleResult('doc.save', response, sessionId, true);
628
- this.markDocumentRpcSessionSaved(sessionId);
629
- }
630
- }
631
- async reconcileIndeterminateDiscardCloses() {
632
- for (const sessionId of this.indeterminateDiscardCloses) {
633
- const response = await this.sendJsonRpcRequest('document.close', { sessionId, discard: true }, this.resolveWatchdogTimeout(undefined));
634
- mapDocumentLifecycleResult('doc.close', response, sessionId);
635
- this.documentRpcSessions.delete(sessionId);
636
- this.clearDirtyDocumentRpcSession(sessionId);
637
- this.indeterminateDiscardCloses.delete(sessionId);
638
- }
639
- }
640
445
  async sendJsonRpcRequest(method, params, watchdogTimeoutMs, metadata = {}) {
641
446
  const child = this.child;
642
447
  if (!child || !child.stdin.writable) {
@@ -810,17 +615,7 @@ export class HostTransport {
810
615
  this.cleanupProcess(error);
811
616
  }
812
617
  cleanupProcess(error) {
813
- if (error && this.dirtyDocumentRpcSessions.size > 0 && !this.terminalDisposalError) {
814
- this.terminalDisposalError = new SuperDocCliError('Document host disconnected before dirty sessions could be persisted.', {
815
- code: 'HOST_DISCONNECTED',
816
- details: { causeCode: error.code, causeDetails: error.details },
817
- });
818
- }
819
618
  this.hostFeatures.clear();
820
- this.documentRpcSessions.clear();
821
- this.dirtyDocumentRpcSessions.clear();
822
- this.documentRpcMutationStates.clear();
823
- this.indeterminateDiscardCloses.clear();
824
619
  const child = this.child;
825
620
  if (child) {
826
621
  if (this.stdoutDataListener)
@@ -5,46 +5,20 @@ var os = require('node:os');
5
5
  var path = require('node:path');
6
6
  var host = require('./host.cjs');
7
7
  var embeddedCli = require('./embedded-cli.cjs');
8
- var embeddedDocumentHost = require('./embedded-document-host.cjs');
9
8
  var debugTrace = require('./debug-trace.cjs');
10
9
  var errors = require('./errors.cjs');
11
10
 
12
11
  function resolveRuntimeProcess(options = {}, embedded = {
13
12
  cli: embeddedCli.resolveEmbeddedCliBinary,
14
- documentHost: embeddedDocumentHost.resolveEmbeddedDocumentHostBinary,
15
13
  }) {
16
- const configuredDocumentHostPath = options.documentHostPath;
17
- if (configuredDocumentHostPath !== undefined && configuredDocumentHostPath.trim().length === 0) {
18
- throw new errors.SuperDocCliError('documentHostPath must be a non-empty path.', {
19
- code: 'INVALID_ARGUMENT',
20
- });
21
- }
22
- const configuredDocumentHostBin = options.env?.SUPERDOC_SDK_DOCUMENT_HOST_BIN ?? process.env.SUPERDOC_SDK_DOCUMENT_HOST_BIN;
23
- const documentHostBin = configuredDocumentHostPath ??
24
- (configuredDocumentHostBin === 'embedded' ? embedded.documentHost() : configuredDocumentHostBin);
25
- if (documentHostBin !== undefined && documentHostBin.trim().length === 0) {
26
- throw new errors.SuperDocCliError('SUPERDOC_SDK_DOCUMENT_HOST_BIN must be a non-empty path.', {
27
- code: 'INVALID_ARGUMENT',
28
- });
29
- }
30
- if (documentHostBin !== undefined) {
31
- return { hostBin: documentHostBin, processMode: 'document' };
32
- }
33
14
  return {
34
15
  hostBin: options.env?.SUPERDOC_CLI_BIN ?? process.env.SUPERDOC_CLI_BIN ?? embedded.cli(),
35
- processMode: 'cli',
36
16
  };
37
17
  }
38
18
  function toSafeInvokeTraceOptions(options) {
39
19
  const { collaborationAuth: _collaborationAuth, ...traceOptions } = options;
40
20
  return traceOptions;
41
21
  }
42
- /**
43
- * Internal runtime that delegates operations to a persistent host transport.
44
- *
45
- * Uses the standalone document host when explicitly configured. Otherwise it
46
- * preserves the embedded CLI compatibility path.
47
- */
48
22
  class SuperDocRuntime {
49
23
  transport;
50
24
  constructor(options = {}) {
@@ -1,11 +1,9 @@
1
1
  import type { CollaborationAuth, DocumentRuntimeKind, DocOpenOptions, InvokeOptions, TransportInvokeOptions, OperationParamSpec, OperationSpec, RuntimeInvoker, SuperDocClientOptions } from './transport-common.js';
2
2
  type RuntimeProcessResolution = {
3
3
  hostBin: string;
4
- processMode: 'cli' | 'document';
5
4
  };
6
5
  type EmbeddedRuntimeResolvers = {
7
6
  cli: () => string;
8
- documentHost: () => string;
9
7
  };
10
8
  export type ReplaceFileSource = string | Uint8Array | ArrayBuffer;
11
9
  export interface ReplaceFileOptions {
@@ -22,12 +20,6 @@ export interface ReplaceFileResult {
22
20
  }
23
21
  export declare function resolveRuntimeProcess(options?: SuperDocClientOptions, embedded?: EmbeddedRuntimeResolvers): RuntimeProcessResolution;
24
22
  export declare function toSafeInvokeTraceOptions(options: TransportInvokeOptions): InvokeOptions;
25
- /**
26
- * Internal runtime that delegates operations to a persistent host transport.
27
- *
28
- * Uses the standalone document host when explicitly configured. Otherwise it
29
- * preserves the embedded CLI compatibility path.
30
- */
31
23
  export declare class SuperDocRuntime {
32
24
  private readonly transport;
33
25
  constructor(options?: SuperDocClientOptions);
@@ -3,45 +3,19 @@ import { tmpdir } from 'node:os';
3
3
  import { join } from 'node:path';
4
4
  import { HostTransport } from './host.js';
5
5
  import { resolveEmbeddedCliBinary } from './embedded-cli.js';
6
- import { resolveEmbeddedDocumentHostBinary } from './embedded-document-host.js';
7
6
  import { writeSdkDebugTrace } from './debug-trace.js';
8
7
  import { SuperDocCliError } from './errors.js';
9
8
  export function resolveRuntimeProcess(options = {}, embedded = {
10
9
  cli: resolveEmbeddedCliBinary,
11
- documentHost: resolveEmbeddedDocumentHostBinary,
12
10
  }) {
13
- const configuredDocumentHostPath = options.documentHostPath;
14
- if (configuredDocumentHostPath !== undefined && configuredDocumentHostPath.trim().length === 0) {
15
- throw new SuperDocCliError('documentHostPath must be a non-empty path.', {
16
- code: 'INVALID_ARGUMENT',
17
- });
18
- }
19
- const configuredDocumentHostBin = options.env?.SUPERDOC_SDK_DOCUMENT_HOST_BIN ?? process.env.SUPERDOC_SDK_DOCUMENT_HOST_BIN;
20
- const documentHostBin = configuredDocumentHostPath ??
21
- (configuredDocumentHostBin === 'embedded' ? embedded.documentHost() : configuredDocumentHostBin);
22
- if (documentHostBin !== undefined && documentHostBin.trim().length === 0) {
23
- throw new SuperDocCliError('SUPERDOC_SDK_DOCUMENT_HOST_BIN must be a non-empty path.', {
24
- code: 'INVALID_ARGUMENT',
25
- });
26
- }
27
- if (documentHostBin !== undefined) {
28
- return { hostBin: documentHostBin, processMode: 'document' };
29
- }
30
11
  return {
31
12
  hostBin: options.env?.SUPERDOC_CLI_BIN ?? process.env.SUPERDOC_CLI_BIN ?? embedded.cli(),
32
- processMode: 'cli',
33
13
  };
34
14
  }
35
15
  export function toSafeInvokeTraceOptions(options) {
36
16
  const { collaborationAuth: _collaborationAuth, ...traceOptions } = options;
37
17
  return traceOptions;
38
18
  }
39
- /**
40
- * Internal runtime that delegates operations to a persistent host transport.
41
- *
42
- * Uses the standalone document host when explicitly configured. Otherwise it
43
- * preserves the embedded CLI compatibility path.
44
- */
45
19
  export class SuperDocRuntime {
46
20
  transport;
47
21
  constructor(options = {}) {
@@ -1,21 +1,11 @@
1
1
  export declare const SDK_POLICY: {
2
2
  protocolVersion: string;
3
3
  cliRequiredFeatures: readonly string[];
4
- documentRequiredFeatures: readonly string[];
5
- documentRpcFeatures: readonly string[];
6
4
  features: {
7
5
  replaceFile: string;
8
- defaultChangeMode: string;
9
- sourceSave: string;
10
6
  requestTimeout: string;
11
7
  collaborationAuthPerOpen: string;
12
- documentAuthor: string;
13
- fullPreset?: string;
14
8
  };
15
- documentOpenFields: readonly string[];
16
- documentSaveFields: readonly string[];
17
- documentOptionFields: readonly string[];
18
- revisionPreflightOperations: readonly string[];
19
9
  operationParamAliases: Record<string, Readonly<Record<string, readonly string[]>>>;
20
10
  notifications: readonly string[];
21
11
  hostDefaultRequestTimeoutMs: number;
@@ -3,6 +3,6 @@
3
3
  // AUTO-GENERATED by scripts/embed-version.mjs — DO NOT EDIT.
4
4
  // Source of truth: package.json. Regenerated on every SDK build so the
5
5
  // SDK retains its own version identity when bundled into another package.
6
- const SDK_VERSION = '2.26.0-next.1';
6
+ const SDK_VERSION = '2.26.0-next.16';
7
7
 
8
8
  exports.SDK_VERSION = SDK_VERSION;
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "2.26.0-next.1";
1
+ export declare const SDK_VERSION = "2.26.0-next.16";
@@ -1,4 +1,4 @@
1
1
  // AUTO-GENERATED by scripts/embed-version.mjs — DO NOT EDIT.
2
2
  // Source of truth: package.json. Regenerated on every SDK build so the
3
3
  // SDK retains its own version identity when bundled into another package.
4
- export const SDK_VERSION = '2.26.0-next.1';
4
+ export const SDK_VERSION = '2.26.0-next.16';
@@ -49,14 +49,6 @@ export interface SuperDocClientOptions {
49
49
  /** Writable host state root. Takes precedence over SUPERDOC_CLI_STATE_DIR; persists after disposal. */
50
50
  stateDir?: string;
51
51
  env?: Record<string, string | undefined>;
52
- /**
53
- * Standalone document-host entry to use instead of the embedded CLI.
54
- *
55
- * The host-only path supports local lifecycle methods and generated Document
56
- * API operations through structured RPC. Interface-only conveniences fail
57
- * without CLI fallback.
58
- */
59
- documentHostPath?: string;
60
52
  /**
61
53
  * Default document engine for `client.open(...)`. Explicit `runtime` on an
62
54
  * individual open call takes precedence.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superdoc/sdk",
3
- "version": "2.26.0-next.1",
3
+ "version": "2.26.0-next.16",
4
4
  "description": "Node SDK for SuperDoc, wrapping the SuperDoc CLI to read and edit .docx files from JavaScript and TypeScript.",
5
5
  "private": false,
6
6
  "license": "AGPL-3.0",
@@ -38,11 +38,11 @@
38
38
  "typescript": "^5.9.2"
39
39
  },
40
40
  "optionalDependencies": {
41
- "@superdoc/sdk-darwin-arm64": "2.26.0-next.1",
42
- "@superdoc/sdk-darwin-x64": "2.26.0-next.1",
43
- "@superdoc/sdk-linux-x64": "2.26.0-next.1",
44
- "@superdoc/sdk-linux-arm64": "2.26.0-next.1",
45
- "@superdoc/sdk-windows-x64": "2.26.0-next.1"
41
+ "@superdoc/sdk-darwin-arm64": "2.26.0-next.16",
42
+ "@superdoc/sdk-darwin-x64": "2.26.0-next.16",
43
+ "@superdoc/sdk-linux-x64": "2.26.0-next.16",
44
+ "@superdoc/sdk-linux-arm64": "2.26.0-next.16",
45
+ "@superdoc/sdk-windows-x64": "2.26.0-next.16"
46
46
  },
47
47
  "publishConfig": {
48
48
  "access": "public"
@@ -53,7 +53,7 @@
53
53
  "typecheck": "tsc --noEmit",
54
54
  "typecheck:consumer": "tsc --noEmit --strict --skipLibCheck --target ES2022 --module NodeNext --moduleResolution NodeNext ../../../../tests/consumer-typecheck/src/sdk-per-open-collaboration-auth.mts ../../../../tests/consumer-typecheck/src/sdk-replace-file.mts ../../../../tests/consumer-typecheck/src/sdk-retained-paragraph.mts ../../../../tests/consumer-typecheck/src/sdk-state-directory.mts ../../../../tests/consumer-typecheck/src/sdk-agent-evidence.mts ../../../../tests/consumer-typecheck/src/sdk-custom-actions.mts ../../../../tests/consumer-typecheck/src/sd4807-sdk-inspect.mts ../../../../tests/consumer-typecheck/src/sdk-tracked-only-policy.mts ../../../../tests/consumer-typecheck/src/sdk-tracked-review-route.mts ../../../../tests/consumer-typecheck/src/sd5266-sdk-placeholder-null.mts ../../../../tests/consumer-typecheck/src/sdk-schema-types.mts",
55
55
  "test:agent-actions": "bun test src/__tests__/actions.test.ts src/__tests__/agent-runtime.test.ts src/__tests__/execution-context.test.ts src/__tests__/custom-actions.test.ts src/__tests__/textbox-snapshot.test.ts",
56
- "test:document-host": "bun test src/__tests__/diff-direct-styles.e2e.test.ts src/__tests__/default-cli-optimization.e2e.test.ts src/runtime/__tests__/host-spawn-args.test.ts src/runtime/__tests__/document-rpc.test.ts src/__tests__/tracked-review-route.test.ts src/__tests__/structured-document-rpc.e2e.test.ts src/__tests__/request-timeout-ms.e2e.test.ts src/__tests__/agent-evidence.e2e.test.ts src/__tests__/agent-apply.e2e.test.ts src/__tests__/find-text.e2e.test.ts src/__tests__/custom-actions.e2e.test.ts",
56
+ "test:cli-host": "bun test src/__tests__/diff-direct-styles.e2e.test.ts src/__tests__/default-cli-optimization.e2e.test.ts src/runtime/__tests__/host-spawn-args.test.ts src/runtime/__tests__/cli-host.test.ts src/__tests__/tracked-review-route.test.ts src/__tests__/cli-document-lifecycle.e2e.test.ts src/__tests__/request-timeout-ms.e2e.test.ts src/__tests__/agent-evidence.e2e.test.ts src/__tests__/agent-apply.e2e.test.ts src/__tests__/find-text.e2e.test.ts src/__tests__/custom-actions.e2e.test.ts",
57
57
  "smoke:product-action": "node scripts/product-action-smoke.mjs"
58
58
  }
59
59
  }