@superdoc/sdk 2.5.0 → 2.7.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/agent/actions.cjs +1869 -160
- package/dist/agent/actions.d.ts +77 -10
- package/dist/agent/actions.js +1870 -161
- package/dist/agent/catalog.cjs +102 -9
- package/dist/agent/catalog.d.ts +243 -0
- package/dist/agent/catalog.js +99 -9
- package/dist/agent/doc-snapshot.cjs +200 -2
- package/dist/agent/doc-snapshot.d.ts +91 -0
- package/dist/agent/doc-snapshot.js +199 -2
- package/dist/agent/runtime.cjs +9 -1
- package/dist/agent/runtime.d.ts +8 -0
- package/dist/agent/runtime.js +9 -1
- package/dist/embedded-tools.generated.cjs +5 -5
- package/dist/embedded-tools.generated.js +5 -5
- package/dist/generated/client.cjs +754 -770
- package/dist/generated/client.d.ts +14 -9
- package/dist/generated/client.js +754 -770
- package/dist/generated/contract.cjs +16207 -274
- package/dist/generated/contract.d.ts +38 -0
- package/dist/generated/contract.js +17443 -1503
- package/dist/index.cjs +5 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -4
- package/dist/introspection.cjs +59 -0
- package/dist/introspection.d.ts +3 -0
- package/dist/introspection.js +53 -0
- package/dist/runtime/document-rpc.cjs +328 -0
- package/dist/runtime/document-rpc.d.ts +24 -0
- package/dist/runtime/document-rpc.js +312 -0
- package/dist/runtime/embedded-cli.cjs +5 -68
- package/dist/runtime/embedded-cli.js +5 -67
- package/dist/runtime/embedded-document-host.cjs +28 -0
- package/dist/runtime/embedded-document-host.d.ts +1 -0
- package/dist/runtime/embedded-document-host.js +23 -0
- package/dist/runtime/embedded-platform.cjs +102 -0
- package/dist/runtime/embedded-platform.d.ts +5 -0
- package/dist/runtime/embedded-platform.js +93 -0
- package/dist/runtime/host.cjs +128 -16
- package/dist/runtime/host.d.ts +11 -5
- package/dist/runtime/host.js +126 -16
- package/dist/runtime/process.cjs +34 -5
- package/dist/runtime/process.d.ts +12 -3
- package/dist/runtime/process.js +33 -5
- package/dist/runtime/transport-common.cjs +1 -0
- package/dist/runtime/transport-common.d.ts +28 -10
- package/dist/runtime/transport-common.js +1 -1
- 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
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type SupportedEmbeddedTarget = 'darwin-arm64' | 'darwin-x64' | 'linux-x64' | 'linux-arm64' | 'windows-x64';
|
|
2
|
+
export declare function resolveEmbeddedTarget(platform?: NodeJS.Platform, arch?: NodeJS.Architecture): SupportedEmbeddedTarget | null;
|
|
3
|
+
export declare function embeddedPlatformPackage(target: SupportedEmbeddedTarget): string;
|
|
4
|
+
export declare function resolveEmbeddedPlatformBinary(target: SupportedEmbeddedTarget, binaryName: string): string | null;
|
|
5
|
+
export declare function ensureEmbeddedExecutable(binaryPath: string): void;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { chmodSync, existsSync } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
const TARGET_TO_PACKAGE = {
|
|
7
|
+
'darwin-arm64': '@superdoc/sdk-darwin-arm64',
|
|
8
|
+
'darwin-x64': '@superdoc/sdk-darwin-x64',
|
|
9
|
+
'linux-x64': '@superdoc/sdk-linux-x64',
|
|
10
|
+
'linux-arm64': '@superdoc/sdk-linux-arm64',
|
|
11
|
+
'windows-x64': '@superdoc/sdk-windows-x64',
|
|
12
|
+
};
|
|
13
|
+
const TARGET_TO_DIR = {
|
|
14
|
+
'darwin-arm64': 'sdk-darwin-arm64',
|
|
15
|
+
'darwin-x64': 'sdk-darwin-x64',
|
|
16
|
+
'linux-x64': 'sdk-linux-x64',
|
|
17
|
+
'linux-arm64': 'sdk-linux-arm64',
|
|
18
|
+
'windows-x64': 'sdk-windows-x64',
|
|
19
|
+
};
|
|
20
|
+
export function resolveEmbeddedTarget(platform = process.platform, arch = process.arch) {
|
|
21
|
+
if (platform === 'darwin' && arch === 'arm64')
|
|
22
|
+
return 'darwin-arm64';
|
|
23
|
+
if (platform === 'darwin' && arch === 'x64')
|
|
24
|
+
return 'darwin-x64';
|
|
25
|
+
if (platform === 'linux' && arch === 'x64')
|
|
26
|
+
return 'linux-x64';
|
|
27
|
+
if (platform === 'linux' && arch === 'arm64')
|
|
28
|
+
return 'linux-arm64';
|
|
29
|
+
if (platform === 'win32' && arch === 'x64')
|
|
30
|
+
return 'windows-x64';
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
export function embeddedPlatformPackage(target) {
|
|
34
|
+
return TARGET_TO_PACKAGE[target];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The binary shipped inside this package (`platforms/<target>/bin/`). A build
|
|
38
|
+
* that carries its own host is authoritative — it is the only copy guaranteed
|
|
39
|
+
* to match this SDK's code — so it is tried before any resolver lookup.
|
|
40
|
+
*/
|
|
41
|
+
function resolveFromPackageLocal(target, binaryName) {
|
|
42
|
+
const workspacePath = path.resolve(fileURLToPath(new URL('../../platforms', import.meta.url)), TARGET_TO_DIR[target], 'bin', binaryName);
|
|
43
|
+
return existsSync(workspacePath) ? workspacePath : null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Resolve the platform package through Node, and reject a version that is not
|
|
47
|
+
* this SDK's own.
|
|
48
|
+
*
|
|
49
|
+
* `require.resolve` falls back to NODE_PATH, which package managers set to a
|
|
50
|
+
* flat store directory (pnpm does it for every binary shim). A host binary from
|
|
51
|
+
* an unrelated SDK version installed anywhere in that store then satisfies this
|
|
52
|
+
* lookup, and the SDK silently drives a foreign engine: seen in the wild as an
|
|
53
|
+
* SDK 2.2.1 install executing a hoisted 2.0.0 host, which failed operations the
|
|
54
|
+
* matching host performs correctly. optionalDependencies pin the platform
|
|
55
|
+
* package to an exact version, so a mismatch here is never legitimate.
|
|
56
|
+
*/
|
|
57
|
+
function resolveFromPlatformPackage(target, binaryName) {
|
|
58
|
+
const pkg = TARGET_TO_PACKAGE[target];
|
|
59
|
+
let binaryPath;
|
|
60
|
+
try {
|
|
61
|
+
binaryPath = require.resolve(`${pkg}/bin/${binaryName}`);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const platformVersion = require(require.resolve(`${pkg}/package.json`)).version;
|
|
68
|
+
const ownVersion = require(fileURLToPath(new URL('../../package.json', import.meta.url))).version;
|
|
69
|
+
if (platformVersion !== ownVersion)
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Either manifest being unreadable is itself disqualifying: an unverifiable
|
|
74
|
+
// host is exactly the case this guard exists to reject.
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
return binaryPath;
|
|
78
|
+
}
|
|
79
|
+
export function resolveEmbeddedPlatformBinary(target, binaryName) {
|
|
80
|
+
// Package-local first: a self-contained build must never be overridden by
|
|
81
|
+
// whatever the module resolver happens to find on NODE_PATH.
|
|
82
|
+
return resolveFromPackageLocal(target, binaryName) ?? resolveFromPlatformPackage(target, binaryName);
|
|
83
|
+
}
|
|
84
|
+
export function ensureEmbeddedExecutable(binaryPath) {
|
|
85
|
+
if (process.platform === 'win32')
|
|
86
|
+
return;
|
|
87
|
+
try {
|
|
88
|
+
chmodSync(binaryPath, 0o755);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// Non-fatal: spawn() reports the actionable execution error.
|
|
92
|
+
}
|
|
93
|
+
}
|
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'
|
|
@@ -21,6 +23,21 @@ const HOST_DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
|
|
|
21
23
|
// abort. The buffer absorbs JSON-RPC serialization, stdio drain, and event-
|
|
22
24
|
// loop latency.
|
|
23
25
|
const WATCHDOG_HEADROOM_MS = 5_000;
|
|
26
|
+
function mapCliInvocationResult(operation, value) {
|
|
27
|
+
const envelopeKey = operation.responseEnvelopeKey;
|
|
28
|
+
if (envelopeKey === null || envelopeKey === undefined)
|
|
29
|
+
return value;
|
|
30
|
+
if (typeof envelopeKey !== 'string' || envelopeKey.length === 0) {
|
|
31
|
+
throw new errors.SuperDocCliError('Generated operation has invalid response envelope metadata.', {
|
|
32
|
+
code: 'HOST_PROTOCOL_ERROR',
|
|
33
|
+
details: { operationId: operation.operationId, responseEnvelopeKey: envelopeKey },
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
37
|
+
return value;
|
|
38
|
+
const extracted = value[envelopeKey];
|
|
39
|
+
return extracted === undefined ? value : extracted;
|
|
40
|
+
}
|
|
24
41
|
/**
|
|
25
42
|
* Builds the argv passed to `spawn` for `superdoc host --stdio`. Propagates
|
|
26
43
|
* `requestTimeoutMs` to the host via `--request-timeout-ms`, since the SDK
|
|
@@ -35,6 +52,9 @@ function buildHostSpawnArgs(prefixArgs, options) {
|
|
|
35
52
|
}
|
|
36
53
|
return args;
|
|
37
54
|
}
|
|
55
|
+
function buildDocumentHostSpawnArgs(prefixArgs) {
|
|
56
|
+
return [...prefixArgs];
|
|
57
|
+
}
|
|
38
58
|
/**
|
|
39
59
|
* Computes the JS-side watchdog timeout for a single JSON-RPC request.
|
|
40
60
|
*
|
|
@@ -60,11 +80,10 @@ function resolveJsWatchdogTimeout(watchdogTimeoutMs, requestTimeoutMs, timeoutMs
|
|
|
60
80
|
}
|
|
61
81
|
return Math.max(watchdogTimeoutMs, HOST_DEFAULT_REQUEST_TIMEOUT_MS + WATCHDOG_HEADROOM_MS);
|
|
62
82
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Transport that communicates with a long-lived CLI host process over JSON-RPC stdio.
|
|
65
|
-
*/
|
|
83
|
+
/** Transport for the legacy CLI host or the structured document host. */
|
|
66
84
|
class HostTransport {
|
|
67
|
-
|
|
85
|
+
hostBin;
|
|
86
|
+
processMode;
|
|
68
87
|
env;
|
|
69
88
|
startupTimeoutMs;
|
|
70
89
|
shutdownTimeoutMs;
|
|
@@ -73,14 +92,18 @@ class HostTransport {
|
|
|
73
92
|
maxQueueDepth;
|
|
74
93
|
defaultChangeMode;
|
|
75
94
|
user;
|
|
95
|
+
documentRpcEnabled;
|
|
76
96
|
child = null;
|
|
77
97
|
stdoutReader = null;
|
|
78
98
|
pending = new Map();
|
|
79
99
|
nextRequestId = 1;
|
|
80
100
|
connecting = null;
|
|
81
101
|
stopping = false;
|
|
102
|
+
hostFeatures = new Set();
|
|
103
|
+
documentRpcSessions = new Set();
|
|
82
104
|
constructor(options) {
|
|
83
|
-
this.
|
|
105
|
+
this.hostBin = options.hostBin;
|
|
106
|
+
this.processMode = options.processMode ?? 'cli';
|
|
84
107
|
this.env = options.env;
|
|
85
108
|
this.startupTimeoutMs = options.startupTimeoutMs ?? 5_000;
|
|
86
109
|
this.shutdownTimeoutMs = options.shutdownTimeoutMs ?? 5_000;
|
|
@@ -93,8 +116,9 @@ class HostTransport {
|
|
|
93
116
|
details: { defaultChangeMode: options.defaultChangeMode },
|
|
94
117
|
});
|
|
95
118
|
}
|
|
96
|
-
this.defaultChangeMode = options.defaultChangeMode;
|
|
119
|
+
this.defaultChangeMode = options.defaultChangeMode ?? undefined;
|
|
97
120
|
this.user = options.user;
|
|
121
|
+
this.documentRpcEnabled = this.processMode === 'document' || documentRpc.documentRpcEnabled(options.env);
|
|
98
122
|
}
|
|
99
123
|
async connect() {
|
|
100
124
|
await this.ensureConnected();
|
|
@@ -125,6 +149,53 @@ class HostTransport {
|
|
|
125
149
|
}
|
|
126
150
|
async invoke(operation, params = {}, options = {}) {
|
|
127
151
|
await this.ensureConnected();
|
|
152
|
+
const shouldOpenThroughCliTimeoutFallback = this.processMode === 'cli' &&
|
|
153
|
+
(this.requestTimeoutMs !== undefined ||
|
|
154
|
+
(options.timeoutMs !== undefined && !this.hostFeatures.has(documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE)));
|
|
155
|
+
if (this.documentRpcEnabled &&
|
|
156
|
+
documentRpc.supportsDocumentRpc(this.hostFeatures) &&
|
|
157
|
+
(this.defaultChangeMode === undefined || this.hostFeatures.has(documentRpc.DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE)) &&
|
|
158
|
+
operation.operationId === 'doc.open' &&
|
|
159
|
+
documentRpc.canOpenWithDocumentRpc(params, options) &&
|
|
160
|
+
!shouldOpenThroughCliTimeoutFallback) {
|
|
161
|
+
const opened = documentRpc.buildDocumentOpenParams(params, this.user, this.defaultChangeMode);
|
|
162
|
+
const requestTimeoutMs = this.resolveDocumentRequestTimeout(options.timeoutMs);
|
|
163
|
+
const response = await this.sendJsonRpcRequest('document.open', opened.params, this.resolveWatchdogTimeout(options.timeoutMs), { requestTimeoutMs });
|
|
164
|
+
const result = documentRpc.mapDocumentOpenResult(response, opened.sessionId, params.doc);
|
|
165
|
+
this.documentRpcSessions.add(opened.sessionId);
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
const sessionId = typeof params.sessionId === 'string' ? params.sessionId : undefined;
|
|
169
|
+
if (sessionId !== undefined && this.documentRpcSessions.has(sessionId)) {
|
|
170
|
+
const request = documentRpc.buildDocumentInvokeParams(sessionId, operation, params, options, this.hostFeatures);
|
|
171
|
+
const supportsResponseTimeout = documentRpc.documentRpcRequestSupportsResponseTimeout(operation, request);
|
|
172
|
+
const requestTimeoutMs = supportsResponseTimeout
|
|
173
|
+
? this.resolveDocumentRequestTimeout(options.timeoutMs)
|
|
174
|
+
: undefined;
|
|
175
|
+
const response = await this.sendJsonRpcRequest(request.method, request.params, this.resolveWatchdogTimeout(options.timeoutMs), { requestTimeoutMs });
|
|
176
|
+
const result = documentRpc.mapDocumentLifecycleResult(operation.operationId, response, sessionId, operation.operationId === 'doc.save' ? request.params.path === undefined : undefined);
|
|
177
|
+
if (operation.operationId === 'doc.close')
|
|
178
|
+
this.documentRpcSessions.delete(sessionId);
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
if (this.processMode === 'document') {
|
|
182
|
+
throw new errors.SuperDocCliError(`Standalone document host does not support ${operation.operationId} through structured RPC v0.`, {
|
|
183
|
+
code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
|
|
184
|
+
details: { operationId: operation.operationId },
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
const cliHostRequestTimeoutMs = this.requestTimeoutMs ?? HOST_DEFAULT_REQUEST_TIMEOUT_MS;
|
|
188
|
+
if (options.timeoutMs !== undefined && options.timeoutMs > cliHostRequestTimeoutMs) {
|
|
189
|
+
throw new errors.SuperDocCliError(`CLI host cannot honor timeoutMs=${options.timeoutMs} above its ${cliHostRequestTimeoutMs}ms request ceiling.`, {
|
|
190
|
+
code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
|
|
191
|
+
details: {
|
|
192
|
+
feature: documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE,
|
|
193
|
+
operationId: operation.operationId,
|
|
194
|
+
timeoutMs: options.timeoutMs,
|
|
195
|
+
hostRequestTimeoutMs: cliHostRequestTimeoutMs,
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
}
|
|
128
199
|
const argv = transportCommon.buildOperationArgv(operation, params, options, this.requestTimeoutMs, this.defaultChangeMode, this.user);
|
|
129
200
|
const stdinBase64 = options.stdinBytes ? Buffer.from(options.stdinBytes).toString('base64') : '';
|
|
130
201
|
const watchdogTimeout = this.resolveWatchdogTimeout(options.timeoutMs);
|
|
@@ -139,16 +210,16 @@ class HostTransport {
|
|
|
139
210
|
});
|
|
140
211
|
}
|
|
141
212
|
const resultRecord = response;
|
|
142
|
-
return resultRecord.data;
|
|
213
|
+
return mapCliInvocationResult(operation, resultRecord.data);
|
|
143
214
|
}
|
|
144
215
|
async ensureConnected() {
|
|
145
|
-
if (this.child && !this.child.killed) {
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
216
|
if (this.connecting) {
|
|
149
217
|
await this.connecting;
|
|
150
218
|
return;
|
|
151
219
|
}
|
|
220
|
+
if (this.child && !this.child.killed) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
152
223
|
this.connecting = this.startHostProcess();
|
|
153
224
|
try {
|
|
154
225
|
await this.connecting;
|
|
@@ -158,12 +229,14 @@ class HostTransport {
|
|
|
158
229
|
}
|
|
159
230
|
}
|
|
160
231
|
async startHostProcess() {
|
|
161
|
-
const { command, prefixArgs } = transportCommon.resolveInvocation(this.
|
|
162
|
-
const args =
|
|
232
|
+
const { command, prefixArgs } = transportCommon.resolveInvocation(this.hostBin);
|
|
233
|
+
const args = this.processMode === 'document'
|
|
234
|
+
? buildDocumentHostSpawnArgs(prefixArgs)
|
|
235
|
+
: buildHostSpawnArgs(prefixArgs, { requestTimeoutMs: this.requestTimeoutMs });
|
|
163
236
|
const child = node_child_process.spawn(command, args, {
|
|
164
237
|
env: {
|
|
165
238
|
...process.env,
|
|
166
|
-
...
|
|
239
|
+
...this.env,
|
|
167
240
|
},
|
|
168
241
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
169
242
|
});
|
|
@@ -242,7 +315,14 @@ class HostTransport {
|
|
|
242
315
|
details: { features },
|
|
243
316
|
});
|
|
244
317
|
}
|
|
245
|
-
|
|
318
|
+
const requiredFeatures = this.processMode === 'document'
|
|
319
|
+
? [
|
|
320
|
+
...DOCUMENT_HOST_REQUIRED_FEATURES,
|
|
321
|
+
...(this.defaultChangeMode === undefined ? [] : [documentRpc.DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE]),
|
|
322
|
+
...(this.requestTimeoutMs === undefined ? [] : [documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE]),
|
|
323
|
+
]
|
|
324
|
+
: CLI_HOST_REQUIRED_FEATURES;
|
|
325
|
+
for (const requiredFeature of requiredFeatures) {
|
|
246
326
|
if (!features.includes(requiredFeature)) {
|
|
247
327
|
throw new errors.SuperDocCliError(`Host does not support required feature: ${requiredFeature}`, {
|
|
248
328
|
code: 'HOST_HANDSHAKE_FAILED',
|
|
@@ -250,11 +330,27 @@ class HostTransport {
|
|
|
250
330
|
});
|
|
251
331
|
}
|
|
252
332
|
}
|
|
333
|
+
this.hostFeatures.clear();
|
|
334
|
+
for (const feature of features)
|
|
335
|
+
this.hostFeatures.add(feature);
|
|
253
336
|
}
|
|
254
337
|
resolveWatchdogTimeout(timeoutMsOverride) {
|
|
255
338
|
return resolveJsWatchdogTimeout(this.watchdogTimeoutMs, this.requestTimeoutMs, timeoutMsOverride);
|
|
256
339
|
}
|
|
257
|
-
|
|
340
|
+
resolveDocumentRequestTimeout(timeoutMsOverride) {
|
|
341
|
+
const requestTimeoutMs = timeoutMsOverride ?? this.requestTimeoutMs;
|
|
342
|
+
if (requestTimeoutMs === undefined)
|
|
343
|
+
return undefined;
|
|
344
|
+
if (this.hostFeatures.has(documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE))
|
|
345
|
+
return requestTimeoutMs;
|
|
346
|
+
if (this.processMode === 'cli' && timeoutMsOverride === undefined)
|
|
347
|
+
return undefined;
|
|
348
|
+
throw new errors.SuperDocCliError(`Structured document RPC host does not support ${documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE}.`, {
|
|
349
|
+
code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
|
|
350
|
+
details: { feature: documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE },
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
async sendJsonRpcRequest(method, params, watchdogTimeoutMs, metadata = {}) {
|
|
258
354
|
const child = this.child;
|
|
259
355
|
if (!child || !child.stdin.writable) {
|
|
260
356
|
throw new errors.SuperDocCliError('Host process is not available.', {
|
|
@@ -274,6 +370,7 @@ class HostTransport {
|
|
|
274
370
|
id,
|
|
275
371
|
method,
|
|
276
372
|
params,
|
|
373
|
+
...(metadata.requestTimeoutMs === undefined ? {} : { requestTimeoutMs: metadata.requestTimeoutMs }),
|
|
277
374
|
});
|
|
278
375
|
const promise = new Promise((resolve, reject) => {
|
|
279
376
|
const timer = setTimeout(() => {
|
|
@@ -349,6 +446,7 @@ class HostTransport {
|
|
|
349
446
|
const error = rawError;
|
|
350
447
|
const data = error.data;
|
|
351
448
|
const cliCode = typeof data?.cliCode === 'string' ? data.cliCode : undefined;
|
|
449
|
+
const domainCode = typeof data?.domainCode === 'string' ? data.domainCode : undefined;
|
|
352
450
|
const cliMessage = typeof data?.message === 'string' ? data.message : undefined;
|
|
353
451
|
const exitCode = typeof data?.exitCode === 'number' ? data.exitCode : undefined;
|
|
354
452
|
if (cliCode) {
|
|
@@ -358,6 +456,16 @@ class HostTransport {
|
|
|
358
456
|
exitCode,
|
|
359
457
|
});
|
|
360
458
|
}
|
|
459
|
+
if (domainCode) {
|
|
460
|
+
return new errors.SuperDocCliError(error.message, {
|
|
461
|
+
code: domainCode,
|
|
462
|
+
details: {
|
|
463
|
+
...(data?.details === undefined ? {} : { domainDetails: data.details }),
|
|
464
|
+
...(data?.stage === undefined ? {} : { stage: data.stage }),
|
|
465
|
+
...(data?.byteLength === undefined ? {} : { byteLength: data.byteLength }),
|
|
466
|
+
},
|
|
467
|
+
});
|
|
468
|
+
}
|
|
361
469
|
if (error.code === JSON_RPC_TIMEOUT_CODE) {
|
|
362
470
|
return new errors.SuperDocCliError(error.message, {
|
|
363
471
|
code: 'TIMEOUT',
|
|
@@ -373,6 +481,8 @@ class HostTransport {
|
|
|
373
481
|
this.cleanupProcess(error);
|
|
374
482
|
}
|
|
375
483
|
cleanupProcess(error) {
|
|
484
|
+
this.hostFeatures.clear();
|
|
485
|
+
this.documentRpcSessions.clear();
|
|
376
486
|
const child = this.child;
|
|
377
487
|
if (child) {
|
|
378
488
|
child.removeAllListeners();
|
|
@@ -398,5 +508,7 @@ class HostTransport {
|
|
|
398
508
|
}
|
|
399
509
|
|
|
400
510
|
exports.HostTransport = HostTransport;
|
|
511
|
+
exports.buildDocumentHostSpawnArgs = buildDocumentHostSpawnArgs;
|
|
401
512
|
exports.buildHostSpawnArgs = buildHostSpawnArgs;
|
|
513
|
+
exports.mapCliInvocationResult = mapCliInvocationResult;
|
|
402
514
|
exports.resolveJsWatchdogTimeout = resolveJsWatchdogTimeout;
|
package/dist/runtime/host.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type InvokeOptions, type OperationSpec, type SuperDocClientOptions } from './transport-common.js';
|
|
2
|
+
export declare function mapCliInvocationResult(operation: OperationSpec, value: unknown): unknown;
|
|
2
3
|
/**
|
|
3
4
|
* Builds the argv passed to `spawn` for `superdoc host --stdio`. Propagates
|
|
4
5
|
* `requestTimeoutMs` to the host via `--request-timeout-ms`, since the SDK
|
|
@@ -9,6 +10,7 @@ import { type InvokeOptions, type OperationSpec, type SuperDocClientOptions } fr
|
|
|
9
10
|
export declare function buildHostSpawnArgs(prefixArgs: readonly string[], options: {
|
|
10
11
|
requestTimeoutMs?: number;
|
|
11
12
|
}): string[];
|
|
13
|
+
export declare function buildDocumentHostSpawnArgs(prefixArgs: readonly string[]): string[];
|
|
12
14
|
/**
|
|
13
15
|
* Computes the JS-side watchdog timeout for a single JSON-RPC request.
|
|
14
16
|
*
|
|
@@ -26,11 +28,10 @@ export declare function buildHostSpawnArgs(prefixArgs: readonly string[], option
|
|
|
26
28
|
* Exported for unit testing.
|
|
27
29
|
*/
|
|
28
30
|
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
|
-
*/
|
|
31
|
+
/** Transport for the legacy CLI host or the structured document host. */
|
|
32
32
|
export declare class HostTransport {
|
|
33
|
-
private readonly
|
|
33
|
+
private readonly hostBin;
|
|
34
|
+
private readonly processMode;
|
|
34
35
|
private readonly env?;
|
|
35
36
|
private readonly startupTimeoutMs;
|
|
36
37
|
private readonly shutdownTimeoutMs;
|
|
@@ -39,14 +40,18 @@ export declare class HostTransport {
|
|
|
39
40
|
private readonly maxQueueDepth;
|
|
40
41
|
private readonly defaultChangeMode?;
|
|
41
42
|
private readonly user?;
|
|
43
|
+
private readonly documentRpcEnabled;
|
|
42
44
|
private child;
|
|
43
45
|
private stdoutReader;
|
|
44
46
|
private readonly pending;
|
|
45
47
|
private nextRequestId;
|
|
46
48
|
private connecting;
|
|
47
49
|
private stopping;
|
|
50
|
+
private readonly hostFeatures;
|
|
51
|
+
private readonly documentRpcSessions;
|
|
48
52
|
constructor(options: {
|
|
49
|
-
|
|
53
|
+
hostBin: string;
|
|
54
|
+
processMode?: 'cli' | 'document';
|
|
50
55
|
} & SuperDocClientOptions);
|
|
51
56
|
connect(): Promise<void>;
|
|
52
57
|
dispose(): Promise<void>;
|
|
@@ -55,6 +60,7 @@ export declare class HostTransport {
|
|
|
55
60
|
private startHostProcess;
|
|
56
61
|
private assertCapabilities;
|
|
57
62
|
private resolveWatchdogTimeout;
|
|
63
|
+
private resolveDocumentRequestTimeout;
|
|
58
64
|
private sendJsonRpcRequest;
|
|
59
65
|
private onStdoutLine;
|
|
60
66
|
private mapJsonRpcError;
|