@superdoc/sdk 2.5.0 → 2.6.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/dist/embedded-tools.generated.cjs +5 -5
- package/dist/embedded-tools.generated.js +5 -5
- package/dist/generated/client.d.ts +5 -0
- package/dist/generated/contract.cjs +38 -3
- package/dist/generated/contract.js +42 -3
- package/dist/runtime/document-rpc.cjs +189 -0
- package/dist/runtime/document-rpc.d.ts +15 -0
- package/dist/runtime/document-rpc.js +177 -0
- package/dist/runtime/host.cjs +73 -12
- package/dist/runtime/host.d.ts +9 -5
- package/dist/runtime/host.js +72 -12
- package/dist/runtime/process.cjs +13 -5
- package/dist/runtime/process.d.ts +3 -3
- package/dist/runtime/process.js +13 -5
- package/package.json +7 -6
- package/tools/__pycache__/__init__.cpython-311.pyc +0 -0
- package/tools/__pycache__/intent_dispatch_generated.cpython-311.pyc +0 -0
- package/tools/catalog.json +2 -2
- package/tools/tools-policy.json +1 -1
- package/tools/tools.anthropic.json +2 -2
- package/tools/tools.generic.json +2 -2
- package/tools/tools.openai.json +2 -2
- package/tools/tools.vercel.json +2 -2
package/dist/runtime/host.cjs
CHANGED
|
@@ -4,9 +4,11 @@ var node_child_process = require('node:child_process');
|
|
|
4
4
|
var node_readline = require('node:readline');
|
|
5
5
|
var transportCommon = require('./transport-common.cjs');
|
|
6
6
|
var errors = require('./errors.cjs');
|
|
7
|
+
var documentRpc = require('./document-rpc.cjs');
|
|
7
8
|
|
|
8
9
|
const HOST_PROTOCOL_VERSION = '1.0';
|
|
9
|
-
const
|
|
10
|
+
const CLI_HOST_REQUIRED_FEATURES = ['cli.invoke', 'host.shutdown'];
|
|
11
|
+
const DOCUMENT_HOST_REQUIRED_FEATURES = [...documentRpc.DOCUMENT_RPC_FEATURES, 'host.shutdown'];
|
|
10
12
|
const CHANGE_MODES = ['direct', 'tracked'];
|
|
11
13
|
const FORWARD_HOST_STDERR = typeof process !== 'undefined' && typeof process.env?.SUPERDOC_DEBUG_TEXT_REWRITE === 'string'
|
|
12
14
|
? process.env.SUPERDOC_DEBUG_TEXT_REWRITE === '1'
|
|
@@ -35,6 +37,9 @@ function buildHostSpawnArgs(prefixArgs, options) {
|
|
|
35
37
|
}
|
|
36
38
|
return args;
|
|
37
39
|
}
|
|
40
|
+
function buildDocumentHostSpawnArgs(prefixArgs) {
|
|
41
|
+
return [...prefixArgs];
|
|
42
|
+
}
|
|
38
43
|
/**
|
|
39
44
|
* Computes the JS-side watchdog timeout for a single JSON-RPC request.
|
|
40
45
|
*
|
|
@@ -60,11 +65,10 @@ function resolveJsWatchdogTimeout(watchdogTimeoutMs, requestTimeoutMs, timeoutMs
|
|
|
60
65
|
}
|
|
61
66
|
return Math.max(watchdogTimeoutMs, HOST_DEFAULT_REQUEST_TIMEOUT_MS + WATCHDOG_HEADROOM_MS);
|
|
62
67
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Transport that communicates with a long-lived CLI host process over JSON-RPC stdio.
|
|
65
|
-
*/
|
|
68
|
+
/** Transport for the legacy CLI host or the structured document host. */
|
|
66
69
|
class HostTransport {
|
|
67
|
-
|
|
70
|
+
hostBin;
|
|
71
|
+
processMode;
|
|
68
72
|
env;
|
|
69
73
|
startupTimeoutMs;
|
|
70
74
|
shutdownTimeoutMs;
|
|
@@ -73,14 +77,18 @@ class HostTransport {
|
|
|
73
77
|
maxQueueDepth;
|
|
74
78
|
defaultChangeMode;
|
|
75
79
|
user;
|
|
80
|
+
documentRpcEnabled;
|
|
76
81
|
child = null;
|
|
77
82
|
stdoutReader = null;
|
|
78
83
|
pending = new Map();
|
|
79
84
|
nextRequestId = 1;
|
|
80
85
|
connecting = null;
|
|
81
86
|
stopping = false;
|
|
87
|
+
hostFeatures = new Set();
|
|
88
|
+
documentRpcSessions = new Set();
|
|
82
89
|
constructor(options) {
|
|
83
|
-
this.
|
|
90
|
+
this.hostBin = options.hostBin;
|
|
91
|
+
this.processMode = options.processMode ?? 'cli';
|
|
84
92
|
this.env = options.env;
|
|
85
93
|
this.startupTimeoutMs = options.startupTimeoutMs ?? 5_000;
|
|
86
94
|
this.shutdownTimeoutMs = options.shutdownTimeoutMs ?? 5_000;
|
|
@@ -95,6 +103,12 @@ class HostTransport {
|
|
|
95
103
|
}
|
|
96
104
|
this.defaultChangeMode = options.defaultChangeMode;
|
|
97
105
|
this.user = options.user;
|
|
106
|
+
this.documentRpcEnabled = documentRpc.documentRpcEnabled(options.env);
|
|
107
|
+
if (this.processMode === 'document' && !this.documentRpcEnabled) {
|
|
108
|
+
throw new errors.SuperDocCliError('SUPERDOC_SDK_DOCUMENT_HOST_BIN requires SUPERDOC_SDK_DOCUMENT_RPC=1.', {
|
|
109
|
+
code: 'INVALID_ARGUMENT',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
98
112
|
}
|
|
99
113
|
async connect() {
|
|
100
114
|
await this.ensureConnected();
|
|
@@ -125,6 +139,33 @@ class HostTransport {
|
|
|
125
139
|
}
|
|
126
140
|
async invoke(operation, params = {}, options = {}) {
|
|
127
141
|
await this.ensureConnected();
|
|
142
|
+
if (this.documentRpcEnabled &&
|
|
143
|
+
documentRpc.supportsDocumentRpc(this.hostFeatures) &&
|
|
144
|
+
this.defaultChangeMode === undefined &&
|
|
145
|
+
this.user === undefined &&
|
|
146
|
+
operation.operationId === 'doc.open' &&
|
|
147
|
+
documentRpc.canOpenWithDocumentRpc(params, options)) {
|
|
148
|
+
const opened = documentRpc.buildDocumentOpenParams(params);
|
|
149
|
+
const response = await this.sendJsonRpcRequest('document.open', opened.params, this.resolveWatchdogTimeout(options.timeoutMs));
|
|
150
|
+
const result = documentRpc.mapDocumentOpenResult(response, opened.sessionId, params.doc);
|
|
151
|
+
this.documentRpcSessions.add(opened.sessionId);
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
const sessionId = typeof params.sessionId === 'string' ? params.sessionId : undefined;
|
|
155
|
+
if (sessionId !== undefined && this.documentRpcSessions.has(sessionId)) {
|
|
156
|
+
const request = documentRpc.buildDocumentInvokeParams(sessionId, operation, params, options);
|
|
157
|
+
const response = await this.sendJsonRpcRequest(request.method, request.params, this.resolveWatchdogTimeout(options.timeoutMs));
|
|
158
|
+
const result = documentRpc.mapDocumentLifecycleResult(operation.operationId, response, sessionId);
|
|
159
|
+
if (operation.operationId === 'doc.close')
|
|
160
|
+
this.documentRpcSessions.delete(sessionId);
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
if (this.processMode === 'document') {
|
|
164
|
+
throw new errors.SuperDocCliError(`Standalone document host does not support ${operation.operationId} through structured RPC v0.`, {
|
|
165
|
+
code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
|
|
166
|
+
details: { operationId: operation.operationId },
|
|
167
|
+
});
|
|
168
|
+
}
|
|
128
169
|
const argv = transportCommon.buildOperationArgv(operation, params, options, this.requestTimeoutMs, this.defaultChangeMode, this.user);
|
|
129
170
|
const stdinBase64 = options.stdinBytes ? Buffer.from(options.stdinBytes).toString('base64') : '';
|
|
130
171
|
const watchdogTimeout = this.resolveWatchdogTimeout(options.timeoutMs);
|
|
@@ -142,13 +183,13 @@ class HostTransport {
|
|
|
142
183
|
return resultRecord.data;
|
|
143
184
|
}
|
|
144
185
|
async ensureConnected() {
|
|
145
|
-
if (this.child && !this.child.killed) {
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
186
|
if (this.connecting) {
|
|
149
187
|
await this.connecting;
|
|
150
188
|
return;
|
|
151
189
|
}
|
|
190
|
+
if (this.child && !this.child.killed) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
152
193
|
this.connecting = this.startHostProcess();
|
|
153
194
|
try {
|
|
154
195
|
await this.connecting;
|
|
@@ -158,8 +199,10 @@ class HostTransport {
|
|
|
158
199
|
}
|
|
159
200
|
}
|
|
160
201
|
async startHostProcess() {
|
|
161
|
-
const { command, prefixArgs } = transportCommon.resolveInvocation(this.
|
|
162
|
-
const args =
|
|
202
|
+
const { command, prefixArgs } = transportCommon.resolveInvocation(this.hostBin);
|
|
203
|
+
const args = this.processMode === 'document'
|
|
204
|
+
? buildDocumentHostSpawnArgs(prefixArgs)
|
|
205
|
+
: buildHostSpawnArgs(prefixArgs, { requestTimeoutMs: this.requestTimeoutMs });
|
|
163
206
|
const child = node_child_process.spawn(command, args, {
|
|
164
207
|
env: {
|
|
165
208
|
...process.env,
|
|
@@ -242,7 +285,8 @@ class HostTransport {
|
|
|
242
285
|
details: { features },
|
|
243
286
|
});
|
|
244
287
|
}
|
|
245
|
-
|
|
288
|
+
const requiredFeatures = this.processMode === 'document' ? DOCUMENT_HOST_REQUIRED_FEATURES : CLI_HOST_REQUIRED_FEATURES;
|
|
289
|
+
for (const requiredFeature of requiredFeatures) {
|
|
246
290
|
if (!features.includes(requiredFeature)) {
|
|
247
291
|
throw new errors.SuperDocCliError(`Host does not support required feature: ${requiredFeature}`, {
|
|
248
292
|
code: 'HOST_HANDSHAKE_FAILED',
|
|
@@ -250,6 +294,9 @@ class HostTransport {
|
|
|
250
294
|
});
|
|
251
295
|
}
|
|
252
296
|
}
|
|
297
|
+
this.hostFeatures.clear();
|
|
298
|
+
for (const feature of features)
|
|
299
|
+
this.hostFeatures.add(feature);
|
|
253
300
|
}
|
|
254
301
|
resolveWatchdogTimeout(timeoutMsOverride) {
|
|
255
302
|
return resolveJsWatchdogTimeout(this.watchdogTimeoutMs, this.requestTimeoutMs, timeoutMsOverride);
|
|
@@ -349,6 +396,7 @@ class HostTransport {
|
|
|
349
396
|
const error = rawError;
|
|
350
397
|
const data = error.data;
|
|
351
398
|
const cliCode = typeof data?.cliCode === 'string' ? data.cliCode : undefined;
|
|
399
|
+
const domainCode = typeof data?.domainCode === 'string' ? data.domainCode : undefined;
|
|
352
400
|
const cliMessage = typeof data?.message === 'string' ? data.message : undefined;
|
|
353
401
|
const exitCode = typeof data?.exitCode === 'number' ? data.exitCode : undefined;
|
|
354
402
|
if (cliCode) {
|
|
@@ -358,6 +406,16 @@ class HostTransport {
|
|
|
358
406
|
exitCode,
|
|
359
407
|
});
|
|
360
408
|
}
|
|
409
|
+
if (domainCode) {
|
|
410
|
+
return new errors.SuperDocCliError(error.message, {
|
|
411
|
+
code: domainCode,
|
|
412
|
+
details: {
|
|
413
|
+
...(data?.details === undefined ? {} : { domainDetails: data.details }),
|
|
414
|
+
...(data?.stage === undefined ? {} : { stage: data.stage }),
|
|
415
|
+
...(data?.byteLength === undefined ? {} : { byteLength: data.byteLength }),
|
|
416
|
+
},
|
|
417
|
+
});
|
|
418
|
+
}
|
|
361
419
|
if (error.code === JSON_RPC_TIMEOUT_CODE) {
|
|
362
420
|
return new errors.SuperDocCliError(error.message, {
|
|
363
421
|
code: 'TIMEOUT',
|
|
@@ -373,6 +431,8 @@ class HostTransport {
|
|
|
373
431
|
this.cleanupProcess(error);
|
|
374
432
|
}
|
|
375
433
|
cleanupProcess(error) {
|
|
434
|
+
this.hostFeatures.clear();
|
|
435
|
+
this.documentRpcSessions.clear();
|
|
376
436
|
const child = this.child;
|
|
377
437
|
if (child) {
|
|
378
438
|
child.removeAllListeners();
|
|
@@ -398,5 +458,6 @@ class HostTransport {
|
|
|
398
458
|
}
|
|
399
459
|
|
|
400
460
|
exports.HostTransport = HostTransport;
|
|
461
|
+
exports.buildDocumentHostSpawnArgs = buildDocumentHostSpawnArgs;
|
|
401
462
|
exports.buildHostSpawnArgs = buildHostSpawnArgs;
|
|
402
463
|
exports.resolveJsWatchdogTimeout = resolveJsWatchdogTimeout;
|
package/dist/runtime/host.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { type InvokeOptions, type OperationSpec, type SuperDocClientOptions } fr
|
|
|
9
9
|
export declare function buildHostSpawnArgs(prefixArgs: readonly string[], options: {
|
|
10
10
|
requestTimeoutMs?: number;
|
|
11
11
|
}): string[];
|
|
12
|
+
export declare function buildDocumentHostSpawnArgs(prefixArgs: readonly string[]): string[];
|
|
12
13
|
/**
|
|
13
14
|
* Computes the JS-side watchdog timeout for a single JSON-RPC request.
|
|
14
15
|
*
|
|
@@ -26,11 +27,10 @@ export declare function buildHostSpawnArgs(prefixArgs: readonly string[], option
|
|
|
26
27
|
* Exported for unit testing.
|
|
27
28
|
*/
|
|
28
29
|
export declare function resolveJsWatchdogTimeout(watchdogTimeoutMs: number, requestTimeoutMs: number | undefined, timeoutMsOverride: number | undefined): number;
|
|
29
|
-
/**
|
|
30
|
-
* Transport that communicates with a long-lived CLI host process over JSON-RPC stdio.
|
|
31
|
-
*/
|
|
30
|
+
/** Transport for the legacy CLI host or the structured document host. */
|
|
32
31
|
export declare class HostTransport {
|
|
33
|
-
private readonly
|
|
32
|
+
private readonly hostBin;
|
|
33
|
+
private readonly processMode;
|
|
34
34
|
private readonly env?;
|
|
35
35
|
private readonly startupTimeoutMs;
|
|
36
36
|
private readonly shutdownTimeoutMs;
|
|
@@ -39,14 +39,18 @@ export declare class HostTransport {
|
|
|
39
39
|
private readonly maxQueueDepth;
|
|
40
40
|
private readonly defaultChangeMode?;
|
|
41
41
|
private readonly user?;
|
|
42
|
+
private readonly documentRpcEnabled;
|
|
42
43
|
private child;
|
|
43
44
|
private stdoutReader;
|
|
44
45
|
private readonly pending;
|
|
45
46
|
private nextRequestId;
|
|
46
47
|
private connecting;
|
|
47
48
|
private stopping;
|
|
49
|
+
private readonly hostFeatures;
|
|
50
|
+
private readonly documentRpcSessions;
|
|
48
51
|
constructor(options: {
|
|
49
|
-
|
|
52
|
+
hostBin: string;
|
|
53
|
+
processMode?: 'cli' | 'document';
|
|
50
54
|
} & SuperDocClientOptions);
|
|
51
55
|
connect(): Promise<void>;
|
|
52
56
|
dispose(): Promise<void>;
|
package/dist/runtime/host.js
CHANGED
|
@@ -2,8 +2,10 @@ import { spawn } from 'node:child_process';
|
|
|
2
2
|
import { createInterface } from 'node:readline';
|
|
3
3
|
import { buildOperationArgv, resolveInvocation, } from './transport-common.js';
|
|
4
4
|
import { SuperDocCliError } from './errors.js';
|
|
5
|
+
import { DOCUMENT_RPC_FEATURES, buildDocumentInvokeParams, buildDocumentOpenParams, canOpenWithDocumentRpc, documentRpcEnabled, mapDocumentLifecycleResult, mapDocumentOpenResult, supportsDocumentRpc, } from './document-rpc.js';
|
|
5
6
|
const HOST_PROTOCOL_VERSION = '1.0';
|
|
6
|
-
const
|
|
7
|
+
const CLI_HOST_REQUIRED_FEATURES = ['cli.invoke', 'host.shutdown'];
|
|
8
|
+
const DOCUMENT_HOST_REQUIRED_FEATURES = [...DOCUMENT_RPC_FEATURES, 'host.shutdown'];
|
|
7
9
|
const CHANGE_MODES = ['direct', 'tracked'];
|
|
8
10
|
const FORWARD_HOST_STDERR = typeof process !== 'undefined' && typeof process.env?.SUPERDOC_DEBUG_TEXT_REWRITE === 'string'
|
|
9
11
|
? process.env.SUPERDOC_DEBUG_TEXT_REWRITE === '1'
|
|
@@ -32,6 +34,9 @@ export function buildHostSpawnArgs(prefixArgs, options) {
|
|
|
32
34
|
}
|
|
33
35
|
return args;
|
|
34
36
|
}
|
|
37
|
+
export function buildDocumentHostSpawnArgs(prefixArgs) {
|
|
38
|
+
return [...prefixArgs];
|
|
39
|
+
}
|
|
35
40
|
/**
|
|
36
41
|
* Computes the JS-side watchdog timeout for a single JSON-RPC request.
|
|
37
42
|
*
|
|
@@ -57,11 +62,10 @@ export function resolveJsWatchdogTimeout(watchdogTimeoutMs, requestTimeoutMs, ti
|
|
|
57
62
|
}
|
|
58
63
|
return Math.max(watchdogTimeoutMs, HOST_DEFAULT_REQUEST_TIMEOUT_MS + WATCHDOG_HEADROOM_MS);
|
|
59
64
|
}
|
|
60
|
-
/**
|
|
61
|
-
* Transport that communicates with a long-lived CLI host process over JSON-RPC stdio.
|
|
62
|
-
*/
|
|
65
|
+
/** Transport for the legacy CLI host or the structured document host. */
|
|
63
66
|
export class HostTransport {
|
|
64
|
-
|
|
67
|
+
hostBin;
|
|
68
|
+
processMode;
|
|
65
69
|
env;
|
|
66
70
|
startupTimeoutMs;
|
|
67
71
|
shutdownTimeoutMs;
|
|
@@ -70,14 +74,18 @@ export class HostTransport {
|
|
|
70
74
|
maxQueueDepth;
|
|
71
75
|
defaultChangeMode;
|
|
72
76
|
user;
|
|
77
|
+
documentRpcEnabled;
|
|
73
78
|
child = null;
|
|
74
79
|
stdoutReader = null;
|
|
75
80
|
pending = new Map();
|
|
76
81
|
nextRequestId = 1;
|
|
77
82
|
connecting = null;
|
|
78
83
|
stopping = false;
|
|
84
|
+
hostFeatures = new Set();
|
|
85
|
+
documentRpcSessions = new Set();
|
|
79
86
|
constructor(options) {
|
|
80
|
-
this.
|
|
87
|
+
this.hostBin = options.hostBin;
|
|
88
|
+
this.processMode = options.processMode ?? 'cli';
|
|
81
89
|
this.env = options.env;
|
|
82
90
|
this.startupTimeoutMs = options.startupTimeoutMs ?? 5_000;
|
|
83
91
|
this.shutdownTimeoutMs = options.shutdownTimeoutMs ?? 5_000;
|
|
@@ -92,6 +100,12 @@ export class HostTransport {
|
|
|
92
100
|
}
|
|
93
101
|
this.defaultChangeMode = options.defaultChangeMode;
|
|
94
102
|
this.user = options.user;
|
|
103
|
+
this.documentRpcEnabled = documentRpcEnabled(options.env);
|
|
104
|
+
if (this.processMode === 'document' && !this.documentRpcEnabled) {
|
|
105
|
+
throw new SuperDocCliError('SUPERDOC_SDK_DOCUMENT_HOST_BIN requires SUPERDOC_SDK_DOCUMENT_RPC=1.', {
|
|
106
|
+
code: 'INVALID_ARGUMENT',
|
|
107
|
+
});
|
|
108
|
+
}
|
|
95
109
|
}
|
|
96
110
|
async connect() {
|
|
97
111
|
await this.ensureConnected();
|
|
@@ -122,6 +136,33 @@ export class HostTransport {
|
|
|
122
136
|
}
|
|
123
137
|
async invoke(operation, params = {}, options = {}) {
|
|
124
138
|
await this.ensureConnected();
|
|
139
|
+
if (this.documentRpcEnabled &&
|
|
140
|
+
supportsDocumentRpc(this.hostFeatures) &&
|
|
141
|
+
this.defaultChangeMode === undefined &&
|
|
142
|
+
this.user === undefined &&
|
|
143
|
+
operation.operationId === 'doc.open' &&
|
|
144
|
+
canOpenWithDocumentRpc(params, options)) {
|
|
145
|
+
const opened = buildDocumentOpenParams(params);
|
|
146
|
+
const response = await this.sendJsonRpcRequest('document.open', opened.params, this.resolveWatchdogTimeout(options.timeoutMs));
|
|
147
|
+
const result = mapDocumentOpenResult(response, opened.sessionId, params.doc);
|
|
148
|
+
this.documentRpcSessions.add(opened.sessionId);
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
151
|
+
const sessionId = typeof params.sessionId === 'string' ? params.sessionId : undefined;
|
|
152
|
+
if (sessionId !== undefined && this.documentRpcSessions.has(sessionId)) {
|
|
153
|
+
const request = buildDocumentInvokeParams(sessionId, operation, params, options);
|
|
154
|
+
const response = await this.sendJsonRpcRequest(request.method, request.params, this.resolveWatchdogTimeout(options.timeoutMs));
|
|
155
|
+
const result = mapDocumentLifecycleResult(operation.operationId, response, sessionId);
|
|
156
|
+
if (operation.operationId === 'doc.close')
|
|
157
|
+
this.documentRpcSessions.delete(sessionId);
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
if (this.processMode === 'document') {
|
|
161
|
+
throw new SuperDocCliError(`Standalone document host does not support ${operation.operationId} through structured RPC v0.`, {
|
|
162
|
+
code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
|
|
163
|
+
details: { operationId: operation.operationId },
|
|
164
|
+
});
|
|
165
|
+
}
|
|
125
166
|
const argv = buildOperationArgv(operation, params, options, this.requestTimeoutMs, this.defaultChangeMode, this.user);
|
|
126
167
|
const stdinBase64 = options.stdinBytes ? Buffer.from(options.stdinBytes).toString('base64') : '';
|
|
127
168
|
const watchdogTimeout = this.resolveWatchdogTimeout(options.timeoutMs);
|
|
@@ -139,13 +180,13 @@ export class HostTransport {
|
|
|
139
180
|
return resultRecord.data;
|
|
140
181
|
}
|
|
141
182
|
async ensureConnected() {
|
|
142
|
-
if (this.child && !this.child.killed) {
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
183
|
if (this.connecting) {
|
|
146
184
|
await this.connecting;
|
|
147
185
|
return;
|
|
148
186
|
}
|
|
187
|
+
if (this.child && !this.child.killed) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
149
190
|
this.connecting = this.startHostProcess();
|
|
150
191
|
try {
|
|
151
192
|
await this.connecting;
|
|
@@ -155,8 +196,10 @@ export class HostTransport {
|
|
|
155
196
|
}
|
|
156
197
|
}
|
|
157
198
|
async startHostProcess() {
|
|
158
|
-
const { command, prefixArgs } = resolveInvocation(this.
|
|
159
|
-
const args =
|
|
199
|
+
const { command, prefixArgs } = resolveInvocation(this.hostBin);
|
|
200
|
+
const args = this.processMode === 'document'
|
|
201
|
+
? buildDocumentHostSpawnArgs(prefixArgs)
|
|
202
|
+
: buildHostSpawnArgs(prefixArgs, { requestTimeoutMs: this.requestTimeoutMs });
|
|
160
203
|
const child = spawn(command, args, {
|
|
161
204
|
env: {
|
|
162
205
|
...process.env,
|
|
@@ -239,7 +282,8 @@ export class HostTransport {
|
|
|
239
282
|
details: { features },
|
|
240
283
|
});
|
|
241
284
|
}
|
|
242
|
-
|
|
285
|
+
const requiredFeatures = this.processMode === 'document' ? DOCUMENT_HOST_REQUIRED_FEATURES : CLI_HOST_REQUIRED_FEATURES;
|
|
286
|
+
for (const requiredFeature of requiredFeatures) {
|
|
243
287
|
if (!features.includes(requiredFeature)) {
|
|
244
288
|
throw new SuperDocCliError(`Host does not support required feature: ${requiredFeature}`, {
|
|
245
289
|
code: 'HOST_HANDSHAKE_FAILED',
|
|
@@ -247,6 +291,9 @@ export class HostTransport {
|
|
|
247
291
|
});
|
|
248
292
|
}
|
|
249
293
|
}
|
|
294
|
+
this.hostFeatures.clear();
|
|
295
|
+
for (const feature of features)
|
|
296
|
+
this.hostFeatures.add(feature);
|
|
250
297
|
}
|
|
251
298
|
resolveWatchdogTimeout(timeoutMsOverride) {
|
|
252
299
|
return resolveJsWatchdogTimeout(this.watchdogTimeoutMs, this.requestTimeoutMs, timeoutMsOverride);
|
|
@@ -346,6 +393,7 @@ export class HostTransport {
|
|
|
346
393
|
const error = rawError;
|
|
347
394
|
const data = error.data;
|
|
348
395
|
const cliCode = typeof data?.cliCode === 'string' ? data.cliCode : undefined;
|
|
396
|
+
const domainCode = typeof data?.domainCode === 'string' ? data.domainCode : undefined;
|
|
349
397
|
const cliMessage = typeof data?.message === 'string' ? data.message : undefined;
|
|
350
398
|
const exitCode = typeof data?.exitCode === 'number' ? data.exitCode : undefined;
|
|
351
399
|
if (cliCode) {
|
|
@@ -355,6 +403,16 @@ export class HostTransport {
|
|
|
355
403
|
exitCode,
|
|
356
404
|
});
|
|
357
405
|
}
|
|
406
|
+
if (domainCode) {
|
|
407
|
+
return new SuperDocCliError(error.message, {
|
|
408
|
+
code: domainCode,
|
|
409
|
+
details: {
|
|
410
|
+
...(data?.details === undefined ? {} : { domainDetails: data.details }),
|
|
411
|
+
...(data?.stage === undefined ? {} : { stage: data.stage }),
|
|
412
|
+
...(data?.byteLength === undefined ? {} : { byteLength: data.byteLength }),
|
|
413
|
+
},
|
|
414
|
+
});
|
|
415
|
+
}
|
|
358
416
|
if (error.code === JSON_RPC_TIMEOUT_CODE) {
|
|
359
417
|
return new SuperDocCliError(error.message, {
|
|
360
418
|
code: 'TIMEOUT',
|
|
@@ -370,6 +428,8 @@ export class HostTransport {
|
|
|
370
428
|
this.cleanupProcess(error);
|
|
371
429
|
}
|
|
372
430
|
cleanupProcess(error) {
|
|
431
|
+
this.hostFeatures.clear();
|
|
432
|
+
this.documentRpcSessions.clear();
|
|
373
433
|
const child = this.child;
|
|
374
434
|
if (child) {
|
|
375
435
|
child.removeAllListeners();
|
package/dist/runtime/process.cjs
CHANGED
|
@@ -3,20 +3,28 @@
|
|
|
3
3
|
var host = require('./host.cjs');
|
|
4
4
|
var embeddedCli = require('./embedded-cli.cjs');
|
|
5
5
|
var debugTrace = require('./debug-trace.cjs');
|
|
6
|
+
var errors = require('./errors.cjs');
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
* Internal runtime that delegates
|
|
9
|
+
* Internal runtime that delegates operations to a persistent host transport.
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
11
|
+
* Uses the standalone document host when explicitly configured. Otherwise it
|
|
12
|
+
* preserves the embedded CLI compatibility path.
|
|
12
13
|
*/
|
|
13
14
|
class SuperDocRuntime {
|
|
14
15
|
transport;
|
|
15
16
|
constructor(options = {}) {
|
|
16
|
-
const
|
|
17
|
+
const documentHostBin = options.env?.SUPERDOC_SDK_DOCUMENT_HOST_BIN ?? process.env.SUPERDOC_SDK_DOCUMENT_HOST_BIN;
|
|
18
|
+
if (documentHostBin !== undefined && documentHostBin.trim().length === 0) {
|
|
19
|
+
throw new errors.SuperDocCliError('SUPERDOC_SDK_DOCUMENT_HOST_BIN must be a non-empty path.', {
|
|
20
|
+
code: 'INVALID_ARGUMENT',
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const hostBin = documentHostBin ?? options.env?.SUPERDOC_CLI_BIN ?? process.env.SUPERDOC_CLI_BIN ?? embeddedCli.resolveEmbeddedCliBinary();
|
|
17
24
|
this.transport = new host.HostTransport({
|
|
18
|
-
cliBin,
|
|
19
25
|
...options,
|
|
26
|
+
hostBin,
|
|
27
|
+
processMode: documentHostBin === undefined ? 'cli' : 'document',
|
|
20
28
|
});
|
|
21
29
|
}
|
|
22
30
|
async connect() {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { DocumentRuntimeKind, InvokeOptions, OperationParamSpec, OperationSpec, RuntimeInvoker, SuperDocClientOptions } from './transport-common.js';
|
|
2
2
|
/**
|
|
3
|
-
* Internal runtime that delegates
|
|
3
|
+
* Internal runtime that delegates operations to a persistent host transport.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Uses the standalone document host when explicitly configured. Otherwise it
|
|
6
|
+
* preserves the embedded CLI compatibility path.
|
|
7
7
|
*/
|
|
8
8
|
export declare class SuperDocRuntime {
|
|
9
9
|
private readonly transport;
|
package/dist/runtime/process.js
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
import { HostTransport } from './host.js';
|
|
2
2
|
import { resolveEmbeddedCliBinary } from './embedded-cli.js';
|
|
3
3
|
import { writeSdkDebugTrace } from './debug-trace.js';
|
|
4
|
+
import { SuperDocCliError } from './errors.js';
|
|
4
5
|
/**
|
|
5
|
-
* Internal runtime that delegates
|
|
6
|
+
* Internal runtime that delegates operations to a persistent host transport.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
8
|
+
* Uses the standalone document host when explicitly configured. Otherwise it
|
|
9
|
+
* preserves the embedded CLI compatibility path.
|
|
9
10
|
*/
|
|
10
11
|
export class SuperDocRuntime {
|
|
11
12
|
transport;
|
|
12
13
|
constructor(options = {}) {
|
|
13
|
-
const
|
|
14
|
+
const documentHostBin = options.env?.SUPERDOC_SDK_DOCUMENT_HOST_BIN ?? process.env.SUPERDOC_SDK_DOCUMENT_HOST_BIN;
|
|
15
|
+
if (documentHostBin !== undefined && documentHostBin.trim().length === 0) {
|
|
16
|
+
throw new SuperDocCliError('SUPERDOC_SDK_DOCUMENT_HOST_BIN must be a non-empty path.', {
|
|
17
|
+
code: 'INVALID_ARGUMENT',
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
const hostBin = documentHostBin ?? options.env?.SUPERDOC_CLI_BIN ?? process.env.SUPERDOC_CLI_BIN ?? resolveEmbeddedCliBinary();
|
|
14
21
|
this.transport = new HostTransport({
|
|
15
|
-
cliBin,
|
|
16
22
|
...options,
|
|
23
|
+
hostBin,
|
|
24
|
+
processMode: documentHostBin === undefined ? 'cli' : 'document',
|
|
17
25
|
});
|
|
18
26
|
}
|
|
19
27
|
async connect() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superdoc/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
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",
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
"typescript": "^5.9.2"
|
|
38
38
|
},
|
|
39
39
|
"optionalDependencies": {
|
|
40
|
-
"@superdoc/sdk-darwin-arm64": "2.
|
|
41
|
-
"@superdoc/sdk-linux-x64": "2.
|
|
42
|
-
"@superdoc/sdk-
|
|
43
|
-
"@superdoc/sdk-
|
|
44
|
-
"@superdoc/sdk-windows-x64": "2.
|
|
40
|
+
"@superdoc/sdk-darwin-arm64": "2.6.0",
|
|
41
|
+
"@superdoc/sdk-linux-x64": "2.6.0",
|
|
42
|
+
"@superdoc/sdk-darwin-x64": "2.6.0",
|
|
43
|
+
"@superdoc/sdk-linux-arm64": "2.6.0",
|
|
44
|
+
"@superdoc/sdk-windows-x64": "2.6.0"
|
|
45
45
|
},
|
|
46
46
|
"publishConfig": {
|
|
47
47
|
"access": "public"
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"build": "rm -rf dist && node scripts/embed-prompts.mjs && node scripts/embed-tools.mjs && tsc && rollup -c rollup.cjs.config.mjs && rm -rf dist/prompts && mkdir -p dist/prompts && cp src/prompts/*.md dist/prompts/ && pnpm run audit:publish",
|
|
51
51
|
"audit:publish": "node ../../../../scripts/audit-publish-artifact.mjs dist --label sdk-node-dist",
|
|
52
52
|
"typecheck": "tsc --noEmit",
|
|
53
|
+
"test:document-host": "bun test src/runtime/__tests__/host-spawn-args.test.ts src/runtime/__tests__/document-rpc.test.ts src/__tests__/structured-document-rpc.e2e.test.ts src/__tests__/request-timeout-ms.e2e.test.ts",
|
|
53
54
|
"smoke:product-action": "node scripts/product-action-smoke.mjs"
|
|
54
55
|
}
|
|
55
56
|
}
|
|
Binary file
|
|
Binary file
|
package/tools/catalog.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"tools": [
|
|
6
6
|
{
|
|
7
7
|
"toolName": "superdoc_get_content",
|
|
8
|
-
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \"blocks\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \"blocks\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \"text\", \"markdown\", and \"html\" return compact strings. Actions \"markdown_projection\" and \"html_projection\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \"info\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \"blocks\" action supports pagination via \"offset\" and \"limit\",
|
|
8
|
+
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \"blocks\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \"blocks\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \"text\", \"markdown\", and \"html\" return compact strings. Actions \"markdown_projection\" and \"html_projection\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \"info\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \"blocks\" action supports pagination via \"offset\" and \"limit\", filtering via \"nodeTypes\", and numbering projection via \"reviewMode\". Other actions ignore pagination and filtering parameters. This tool never modifies the document. Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.\n\nEXAMPLES:\n 1. {\"action\":\"blocks\"}\n 2. {\"action\":\"blocks\",\"includeText\":true,\"offset\":0,\"limit\":20,\"reviewMode\":\"final\"}\n 3. {\"action\":\"blocks\",\"offset\":0,\"limit\":20,\"nodeTypes\":[\"heading\",\"paragraph\"]}\n 4. {\"action\":\"text\"}\n 5. {\"action\":\"info\"}\n 6. {\"action\":\"html_projection\",\"reviewMode\":\"redline\",\"includeSourceMap\":true}\n 7. {\"action\":\"markdown_projection\",\"reviewMode\":\"original\",\"scope\":{\"kind\":\"block\",\"nodeType\":\"paragraph\",\"nodeId\":\"paragraph-id\"},\"includeSourceMap\":true}",
|
|
9
9
|
"inputSchema": {
|
|
10
10
|
"type": "object",
|
|
11
11
|
"properties": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"reviewMode": {
|
|
35
35
|
"$ref": "#/$defs/SDProjectionReviewMode",
|
|
36
|
-
"description": "Only for actions 'markdown_projection', 'html_projection'. Omit for other actions."
|
|
36
|
+
"description": "Only for actions 'markdown_projection', 'html_projection', 'blocks'. Omit for other actions."
|
|
37
37
|
},
|
|
38
38
|
"scope": {
|
|
39
39
|
"$ref": "#/$defs/SDProjectionScope",
|
package/tools/tools-policy.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"tools": [
|
|
4
4
|
{
|
|
5
5
|
"name": "superdoc_get_content",
|
|
6
|
-
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \"blocks\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \"blocks\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \"text\", \"markdown\", and \"html\" return compact strings. Actions \"markdown_projection\" and \"html_projection\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \"info\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \"blocks\" action supports pagination via \"offset\" and \"limit\",
|
|
6
|
+
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \"blocks\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \"blocks\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \"text\", \"markdown\", and \"html\" return compact strings. Actions \"markdown_projection\" and \"html_projection\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \"info\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \"blocks\" action supports pagination via \"offset\" and \"limit\", filtering via \"nodeTypes\", and numbering projection via \"reviewMode\". Other actions ignore pagination and filtering parameters. This tool never modifies the document. Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.\n\nEXAMPLES:\n 1. {\"action\":\"blocks\"}\n 2. {\"action\":\"blocks\",\"includeText\":true,\"offset\":0,\"limit\":20,\"reviewMode\":\"final\"}\n 3. {\"action\":\"blocks\",\"offset\":0,\"limit\":20,\"nodeTypes\":[\"heading\",\"paragraph\"]}\n 4. {\"action\":\"text\"}\n 5. {\"action\":\"info\"}\n 6. {\"action\":\"html_projection\",\"reviewMode\":\"redline\",\"includeSourceMap\":true}\n 7. {\"action\":\"markdown_projection\",\"reviewMode\":\"original\",\"scope\":{\"kind\":\"block\",\"nodeType\":\"paragraph\",\"nodeId\":\"paragraph-id\"},\"includeSourceMap\":true}",
|
|
7
7
|
"input_schema": {
|
|
8
8
|
"type": "object",
|
|
9
9
|
"properties": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"reviewMode": {
|
|
33
33
|
"$ref": "#/$defs/SDProjectionReviewMode",
|
|
34
|
-
"description": "Only for actions 'markdown_projection', 'html_projection'. Omit for other actions."
|
|
34
|
+
"description": "Only for actions 'markdown_projection', 'html_projection', 'blocks'. Omit for other actions."
|
|
35
35
|
},
|
|
36
36
|
"scope": {
|
|
37
37
|
"$ref": "#/$defs/SDProjectionScope",
|
package/tools/tools.generic.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"tools": [
|
|
4
4
|
{
|
|
5
5
|
"name": "superdoc_get_content",
|
|
6
|
-
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \"blocks\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \"blocks\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \"text\", \"markdown\", and \"html\" return compact strings. Actions \"markdown_projection\" and \"html_projection\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \"info\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \"blocks\" action supports pagination via \"offset\" and \"limit\",
|
|
6
|
+
"description": "Read document content in various formats. Call this first in any workflow to understand document structure before making edits. Action \"blocks\" returns structured block data with nodeId, nodeType, textPreview, optional full text when includeText:true, formatting properties (fontFamily, fontSize, color, bold, underline, alignment), and ref handles for immediate use with superdoc_edit or superdoc_format. Its optional reviewMode selects final, original, or redline numbering metadata without filtering blocks. When you need to evaluate or rewrite existing paragraphs or clauses, prefer action \"blocks\" with includeText:true so you can identify the correct block and then target it by nodeId. Actions \"text\", \"markdown\", and \"html\" return compact strings. Actions \"markdown_projection\" and \"html_projection\" return detailed async projections with review modes, scopes, diagnostics, annotations, block maps, and optional source maps. Projection source targets use tracked coordinates and are valid only at evaluatedRevision; after any mutation, reproject before using them. Treat omitted or partially emitted annotations according to their status instead of guessing an anchor from rendered text. Action \"info\" returns document metadata: word count, paragraph count, page count, outline, available styles, and capability flags. The \"blocks\" action supports pagination via \"offset\" and \"limit\", filtering via \"nodeTypes\", and numbering projection via \"reviewMode\". Other actions ignore pagination and filtering parameters. This tool never modifies the document. Do NOT call superdoc_edit or superdoc_format without first reading blocks to get valid refs and formatting reference values.\n\nEXAMPLES:\n 1. {\"action\":\"blocks\"}\n 2. {\"action\":\"blocks\",\"includeText\":true,\"offset\":0,\"limit\":20,\"reviewMode\":\"final\"}\n 3. {\"action\":\"blocks\",\"offset\":0,\"limit\":20,\"nodeTypes\":[\"heading\",\"paragraph\"]}\n 4. {\"action\":\"text\"}\n 5. {\"action\":\"info\"}\n 6. {\"action\":\"html_projection\",\"reviewMode\":\"redline\",\"includeSourceMap\":true}\n 7. {\"action\":\"markdown_projection\",\"reviewMode\":\"original\",\"scope\":{\"kind\":\"block\",\"nodeType\":\"paragraph\",\"nodeId\":\"paragraph-id\"},\"includeSourceMap\":true}",
|
|
7
7
|
"parameters": {
|
|
8
8
|
"type": "object",
|
|
9
9
|
"properties": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"reviewMode": {
|
|
33
33
|
"$ref": "#/$defs/SDProjectionReviewMode",
|
|
34
|
-
"description": "Only for actions 'markdown_projection', 'html_projection'. Omit for other actions."
|
|
34
|
+
"description": "Only for actions 'markdown_projection', 'html_projection', 'blocks'. Omit for other actions."
|
|
35
35
|
},
|
|
36
36
|
"scope": {
|
|
37
37
|
"$ref": "#/$defs/SDProjectionScope",
|