@superdoc/sdk 2.9.1-next.2 → 2.10.0-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -0
- package/dist/action-primitives/doc-index.cjs +6 -4
- package/dist/action-primitives/doc-index.js +6 -4
- package/dist/action-primitives/engine.cjs +6 -2
- package/dist/action-primitives/engine.js +6 -2
- package/dist/action-primitives/receipt.d.ts +4 -0
- package/dist/action-primitives/tools/structure-insert.d.ts +1 -1
- package/dist/agent/actions.cjs +384 -373
- package/dist/agent/actions.d.ts +5 -0
- package/dist/agent/actions.js +385 -374
- package/dist/agent/catalog.cjs +15 -0
- package/dist/agent/catalog.js +15 -0
- package/dist/agent/doc-snapshot.cjs +205 -86
- package/dist/agent/doc-snapshot.d.ts +11 -0
- package/dist/agent/doc-snapshot.js +203 -86
- package/dist/agent/execution-context.cjs +385 -0
- package/dist/agent/execution-context.d.ts +97 -0
- package/dist/agent/execution-context.js +376 -0
- package/dist/agent/runtime.cjs +123 -117
- package/dist/agent/runtime.d.ts +3 -0
- package/dist/agent/runtime.js +124 -118
- package/dist/agent/v2-preset-compat.cjs +5 -1
- package/dist/agent/v2-preset-compat.js +4 -1
- package/dist/embedded-tools.generated.cjs +5 -5
- package/dist/embedded-tools.generated.js +5 -5
- package/dist/generated/client.cjs +2 -0
- package/dist/generated/client.d.ts +85 -0
- package/dist/generated/client.js +2 -0
- package/dist/generated/contract.cjs +1796 -1297
- package/dist/generated/contract.js +1797 -1297
- package/dist/index.cjs +23 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +23 -0
- package/dist/presets/core.cjs +1 -1
- package/dist/presets/core.js +1 -1
- package/dist/runtime/document-evidence.cjs +40 -0
- package/dist/runtime/document-evidence.d.ts +13 -0
- package/dist/runtime/document-evidence.js +30 -0
- package/dist/runtime/document-rpc.cjs +27 -0
- package/dist/runtime/document-rpc.d.ts +2 -0
- package/dist/runtime/document-rpc.js +25 -0
- package/dist/runtime/host.cjs +65 -4
- package/dist/runtime/host.d.ts +3 -0
- package/dist/runtime/host.js +66 -5
- package/dist/runtime/process.cjs +38 -0
- package/dist/runtime/process.d.ts +16 -0
- package/dist/runtime/process.js +38 -0
- package/dist/runtime/sdk-version.generated.cjs +1 -1
- package/dist/runtime/sdk-version.generated.d.ts +1 -1
- package/dist/runtime/sdk-version.generated.js +1 -1
- package/package.json +10 -8
- package/tools/catalog.json +89 -0
- package/tools/tools-policy.json +1 -1
- package/tools/tools.anthropic.json +89 -0
- package/tools/tools.generic.json +89 -0
- package/tools/tools.openai.json +89 -0
- package/tools/tools.vercel.json +89 -0
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var documentEvidence = require('./runtime/document-evidence.cjs');
|
|
3
4
|
var client = require('./generated/client.cjs');
|
|
4
5
|
var contract = require('./generated/contract.cjs');
|
|
5
6
|
var process = require('./runtime/process.cjs');
|
|
@@ -37,6 +38,23 @@ class BoundRuntime {
|
|
|
37
38
|
}
|
|
38
39
|
return this.runtime.invoke(operation, { ...params, sessionId: this.sessionId }, options);
|
|
39
40
|
}
|
|
41
|
+
async replaceFile(source, options = {}) {
|
|
42
|
+
if (this.closed) {
|
|
43
|
+
throw new errors.SuperDocCliError('Document handle is closed; cannot replace its file.', {
|
|
44
|
+
code: 'DOCUMENT_CLOSED',
|
|
45
|
+
details: { sessionId: this.sessionId },
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return this.runtime.replaceFile(this.sessionId, source, options);
|
|
49
|
+
}
|
|
50
|
+
supportsDocumentFacts() {
|
|
51
|
+
return !this.closed && this.runtime.supportsDocumentFacts(this.sessionId);
|
|
52
|
+
}
|
|
53
|
+
async readRevision() {
|
|
54
|
+
if (this.closed)
|
|
55
|
+
throw new errors.SuperDocCliError('Document handle is closed; cannot read its revision.', { code: 'DOCUMENT_CLOSED' });
|
|
56
|
+
return this.runtime.readDocumentRevision(this.sessionId);
|
|
57
|
+
}
|
|
40
58
|
markClosed() {
|
|
41
59
|
this.closed = true;
|
|
42
60
|
}
|
|
@@ -61,6 +79,8 @@ class SuperDocDocumentCore {
|
|
|
61
79
|
this._openResult = openResult;
|
|
62
80
|
this.client = client$1;
|
|
63
81
|
attachBoundDocApi(this, client.createBoundDocApi(this.boundRuntime));
|
|
82
|
+
documentEvidence.registerDocumentRevisionReader(this, () => this.boundRuntime.readRevision());
|
|
83
|
+
documentEvidence.registerDocumentFactCapability(this, () => this.boundRuntime.supportsDocumentFacts());
|
|
64
84
|
}
|
|
65
85
|
get sessionId() {
|
|
66
86
|
return this._sessionId;
|
|
@@ -72,6 +92,9 @@ class SuperDocDocumentCore {
|
|
|
72
92
|
async save(params = {}, options = {}) {
|
|
73
93
|
return this.boundRuntime.invoke(contract.CONTRACT.operations['doc.save'], params, options);
|
|
74
94
|
}
|
|
95
|
+
async replaceFile(source, options = {}) {
|
|
96
|
+
return this.boundRuntime.replaceFile(source, options);
|
|
97
|
+
}
|
|
75
98
|
async close(params = {}, options = {}) {
|
|
76
99
|
const result = await this.boundRuntime.invoke(contract.CONTRACT.operations['doc.close'], params, options);
|
|
77
100
|
this.boundRuntime.markClosed();
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type BoundDocApi, type DocCloseBoundParams, type DocCloseResult, type DocFormatApplyBoundParams, type DocFormatApplyResult, type DocOpenParams as GeneratedDocOpenParams, type DocOpenResult, type DocSaveBoundParams, type DocSaveResult } from './generated/client.js';
|
|
2
|
-
import { SuperDocRuntime, type SuperDocClientOptions, type DocOpenOptions, type InvokeOptions, type OperationSpec, type RuntimeInvoker } from './runtime/process.js';
|
|
2
|
+
import { SuperDocRuntime, type SuperDocClientOptions, type DocOpenOptions, type InvokeOptions, type OperationSpec, type ReplaceFileOptions, type ReplaceFileResult, type ReplaceFileSource, type RuntimeInvoker } from './runtime/process.js';
|
|
3
3
|
/**
|
|
4
4
|
* Wraps a raw runtime and injects a fixed sessionId into every invoke call.
|
|
5
5
|
* Implements RuntimeInvoker so generated code can use it directly.
|
|
@@ -12,6 +12,9 @@ declare class BoundRuntime implements RuntimeInvoker {
|
|
|
12
12
|
private closed;
|
|
13
13
|
constructor(runtime: SuperDocRuntime, sessionId: string);
|
|
14
14
|
invoke<TData = unknown>(operation: OperationSpec, params?: Record<string, unknown>, options?: InvokeOptions): Promise<TData>;
|
|
15
|
+
replaceFile(source: ReplaceFileSource, options?: ReplaceFileOptions): Promise<ReplaceFileResult>;
|
|
16
|
+
supportsDocumentFacts(): boolean;
|
|
17
|
+
readRevision(): Promise<string | undefined>;
|
|
15
18
|
markClosed(): void;
|
|
16
19
|
}
|
|
17
20
|
export interface DocFormatRangeBoundParams extends Omit<DocFormatApplyBoundParams, 'inline'> {
|
|
@@ -33,6 +36,7 @@ declare class SuperDocDocumentCore {
|
|
|
33
36
|
/** Read-only snapshot of the initial doc.open response metadata. */
|
|
34
37
|
get openResult(): DocOpenResult;
|
|
35
38
|
save(params?: DocSaveBoundParams, options?: InvokeOptions): Promise<DocSaveResult>;
|
|
39
|
+
replaceFile(source: ReplaceFileSource, options?: ReplaceFileOptions): Promise<ReplaceFileResult>;
|
|
36
40
|
close(params?: DocCloseBoundParams, options?: InvokeOptions): Promise<DocCloseResult>;
|
|
37
41
|
/** @internal */
|
|
38
42
|
markClosed(): void;
|
|
@@ -42,6 +46,7 @@ type SuperDocDocumentInstance = SuperDocDocumentCore & BoundDocApi;
|
|
|
42
46
|
export declare const SuperDocDocument: new (boundRuntime: BoundRuntime, sessionId: string, openResult: DocOpenResult, client: SuperDocClient) => SuperDocDocumentInstance;
|
|
43
47
|
export type SuperDocDocument = SuperDocDocumentInstance;
|
|
44
48
|
export type DocOpenParams = GeneratedDocOpenParams;
|
|
49
|
+
export type { ReplaceFileOptions, ReplaceFileResult, ReplaceFileSource };
|
|
45
50
|
export interface DocDescribeCommandParams {
|
|
46
51
|
operationId: string;
|
|
47
52
|
[key: string]: unknown;
|
|
@@ -89,7 +94,7 @@ export { dispatchIntentTool } from './generated/intent-dispatch.generated.js';
|
|
|
89
94
|
export { wrapV2PresetCompat } from './agent/v2-preset-compat.js';
|
|
90
95
|
export type { BoundDocApi } from './generated/client.js';
|
|
91
96
|
export type { ActionName } from './agent/actions.js';
|
|
92
|
-
export type { AgentReceipt } from './agent/runtime.js';
|
|
97
|
+
export type { AgentReceipt, AgentApplyArgs, AgentVerifyArgs } from './agent/runtime.js';
|
|
93
98
|
export type { GetSystemPromptOptions, GetToolsOptions, GetToolsResult, PresetDescriptor } from './presets.js';
|
|
94
99
|
export { createAgentToolkit } from './tools.js';
|
|
95
100
|
export type { AgentToolkit, CreateAgentToolkitInput } from './tools.js';
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerDocumentRevisionReader, registerDocumentFactCapability } from './runtime/document-evidence.js';
|
|
1
2
|
import { createDocApi, createBoundDocApi, } from './generated/client.js';
|
|
2
3
|
import { CONTRACT } from './generated/contract.js';
|
|
3
4
|
import { SuperDocRuntime, } from './runtime/process.js';
|
|
@@ -29,6 +30,23 @@ class BoundRuntime {
|
|
|
29
30
|
}
|
|
30
31
|
return this.runtime.invoke(operation, { ...params, sessionId: this.sessionId }, options);
|
|
31
32
|
}
|
|
33
|
+
async replaceFile(source, options = {}) {
|
|
34
|
+
if (this.closed) {
|
|
35
|
+
throw new SuperDocCliError('Document handle is closed; cannot replace its file.', {
|
|
36
|
+
code: 'DOCUMENT_CLOSED',
|
|
37
|
+
details: { sessionId: this.sessionId },
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return this.runtime.replaceFile(this.sessionId, source, options);
|
|
41
|
+
}
|
|
42
|
+
supportsDocumentFacts() {
|
|
43
|
+
return !this.closed && this.runtime.supportsDocumentFacts(this.sessionId);
|
|
44
|
+
}
|
|
45
|
+
async readRevision() {
|
|
46
|
+
if (this.closed)
|
|
47
|
+
throw new SuperDocCliError('Document handle is closed; cannot read its revision.', { code: 'DOCUMENT_CLOSED' });
|
|
48
|
+
return this.runtime.readDocumentRevision(this.sessionId);
|
|
49
|
+
}
|
|
32
50
|
markClosed() {
|
|
33
51
|
this.closed = true;
|
|
34
52
|
}
|
|
@@ -53,6 +71,8 @@ class SuperDocDocumentCore {
|
|
|
53
71
|
this._openResult = openResult;
|
|
54
72
|
this.client = client;
|
|
55
73
|
attachBoundDocApi(this, createBoundDocApi(this.boundRuntime));
|
|
74
|
+
registerDocumentRevisionReader(this, () => this.boundRuntime.readRevision());
|
|
75
|
+
registerDocumentFactCapability(this, () => this.boundRuntime.supportsDocumentFacts());
|
|
56
76
|
}
|
|
57
77
|
get sessionId() {
|
|
58
78
|
return this._sessionId;
|
|
@@ -64,6 +84,9 @@ class SuperDocDocumentCore {
|
|
|
64
84
|
async save(params = {}, options = {}) {
|
|
65
85
|
return this.boundRuntime.invoke(CONTRACT.operations['doc.save'], params, options);
|
|
66
86
|
}
|
|
87
|
+
async replaceFile(source, options = {}) {
|
|
88
|
+
return this.boundRuntime.replaceFile(source, options);
|
|
89
|
+
}
|
|
67
90
|
async close(params = {}, options = {}) {
|
|
68
91
|
const result = await this.boundRuntime.invoke(CONTRACT.operations['doc.close'], params, options);
|
|
69
92
|
this.boundRuntime.markClosed();
|
package/dist/presets/core.cjs
CHANGED
|
@@ -245,7 +245,7 @@ function compactAgentReceipt(receipt) {
|
|
|
245
245
|
: {}),
|
|
246
246
|
...(verification
|
|
247
247
|
? {
|
|
248
|
-
verificationPassed: verification.every((entry) => entry.passed),
|
|
248
|
+
verificationPassed: verification.length > 0 && verification.every((entry) => entry.passed),
|
|
249
249
|
verification: verification.map((entry) => ({
|
|
250
250
|
check: pickScalarFields(entry.check, undefined, 6),
|
|
251
251
|
passed: entry.passed,
|
package/dist/presets/core.js
CHANGED
|
@@ -241,7 +241,7 @@ function compactAgentReceipt(receipt) {
|
|
|
241
241
|
: {}),
|
|
242
242
|
...(verification
|
|
243
243
|
? {
|
|
244
|
-
verificationPassed: verification.every((entry) => entry.passed),
|
|
244
|
+
verificationPassed: verification.length > 0 && verification.every((entry) => entry.passed),
|
|
245
245
|
verification: verification.map((entry) => ({
|
|
246
246
|
check: pickScalarFields(entry.check, undefined, 6),
|
|
247
247
|
passed: entry.passed,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const mutationRevisions = new WeakMap();
|
|
4
|
+
function registerMutationRevision(result, revision) {
|
|
5
|
+
if (result && typeof result === 'object')
|
|
6
|
+
mutationRevisions.set(result, revision);
|
|
7
|
+
}
|
|
8
|
+
function getMutationRevision(result) {
|
|
9
|
+
return result && typeof result === 'object' ? mutationRevisions.get(result) : undefined;
|
|
10
|
+
}
|
|
11
|
+
// Keep transport capabilities off the public document API and tied to the live
|
|
12
|
+
// handle. Undefined means unsupported, never a cached or unknown revision.
|
|
13
|
+
const revisionReaders = new WeakMap();
|
|
14
|
+
function registerDocumentRevisionReader(document, reader) {
|
|
15
|
+
revisionReaders.set(document, reader);
|
|
16
|
+
}
|
|
17
|
+
function getDocumentRevisionReader(document) {
|
|
18
|
+
return revisionReaders.get(document);
|
|
19
|
+
}
|
|
20
|
+
const factCapabilities = new WeakMap();
|
|
21
|
+
function registerDocumentFactCapability(document, supported) {
|
|
22
|
+
factCapabilities.set(document, supported);
|
|
23
|
+
}
|
|
24
|
+
function supportsDocumentFacts(document) {
|
|
25
|
+
return factCapabilities.get(document)?.() === true;
|
|
26
|
+
}
|
|
27
|
+
function forwardDocumentEvidence(source, target) {
|
|
28
|
+
const reader = getDocumentRevisionReader(source);
|
|
29
|
+
if (reader)
|
|
30
|
+
registerDocumentRevisionReader(target, reader);
|
|
31
|
+
registerDocumentFactCapability(target, () => supportsDocumentFacts(source));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
exports.forwardDocumentEvidence = forwardDocumentEvidence;
|
|
35
|
+
exports.getDocumentRevisionReader = getDocumentRevisionReader;
|
|
36
|
+
exports.getMutationRevision = getMutationRevision;
|
|
37
|
+
exports.registerDocumentFactCapability = registerDocumentFactCapability;
|
|
38
|
+
exports.registerDocumentRevisionReader = registerDocumentRevisionReader;
|
|
39
|
+
exports.registerMutationRevision = registerMutationRevision;
|
|
40
|
+
exports.supportsDocumentFacts = supportsDocumentFacts;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type RevisionReader = () => Promise<string | undefined>;
|
|
2
|
+
type MutationRevision = {
|
|
3
|
+
before: string;
|
|
4
|
+
after: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function registerMutationRevision(result: unknown, revision: MutationRevision): void;
|
|
7
|
+
export declare function getMutationRevision(result: unknown): MutationRevision | undefined;
|
|
8
|
+
export declare function registerDocumentRevisionReader(document: object, reader: RevisionReader): void;
|
|
9
|
+
export declare function getDocumentRevisionReader(document: object): RevisionReader | undefined;
|
|
10
|
+
export declare function registerDocumentFactCapability(document: object, supported: () => boolean): void;
|
|
11
|
+
export declare function supportsDocumentFacts(document: object): boolean;
|
|
12
|
+
export declare function forwardDocumentEvidence(source: object, target: object): void;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const mutationRevisions = new WeakMap();
|
|
2
|
+
export function registerMutationRevision(result, revision) {
|
|
3
|
+
if (result && typeof result === 'object')
|
|
4
|
+
mutationRevisions.set(result, revision);
|
|
5
|
+
}
|
|
6
|
+
export function getMutationRevision(result) {
|
|
7
|
+
return result && typeof result === 'object' ? mutationRevisions.get(result) : undefined;
|
|
8
|
+
}
|
|
9
|
+
// Keep transport capabilities off the public document API and tied to the live
|
|
10
|
+
// handle. Undefined means unsupported, never a cached or unknown revision.
|
|
11
|
+
const revisionReaders = new WeakMap();
|
|
12
|
+
export function registerDocumentRevisionReader(document, reader) {
|
|
13
|
+
revisionReaders.set(document, reader);
|
|
14
|
+
}
|
|
15
|
+
export function getDocumentRevisionReader(document) {
|
|
16
|
+
return revisionReaders.get(document);
|
|
17
|
+
}
|
|
18
|
+
const factCapabilities = new WeakMap();
|
|
19
|
+
export function registerDocumentFactCapability(document, supported) {
|
|
20
|
+
factCapabilities.set(document, supported);
|
|
21
|
+
}
|
|
22
|
+
export function supportsDocumentFacts(document) {
|
|
23
|
+
return factCapabilities.get(document)?.() === true;
|
|
24
|
+
}
|
|
25
|
+
export function forwardDocumentEvidence(source, target) {
|
|
26
|
+
const reader = getDocumentRevisionReader(source);
|
|
27
|
+
if (reader)
|
|
28
|
+
registerDocumentRevisionReader(target, reader);
|
|
29
|
+
registerDocumentFactCapability(target, () => supportsDocumentFacts(source));
|
|
30
|
+
}
|
|
@@ -5,6 +5,7 @@ var errors = require('./errors.cjs');
|
|
|
5
5
|
var transportCommon = require('./transport-common.cjs');
|
|
6
6
|
|
|
7
7
|
const DOCUMENT_RPC_FEATURES = ['document.open', 'document.invoke', 'document.save', 'document.close'];
|
|
8
|
+
const DOCUMENT_RPC_REPLACE_FILE_FEATURE = 'document.replaceFile';
|
|
8
9
|
const DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE = 'document.open.defaultChangeMode';
|
|
9
10
|
const DOCUMENT_RPC_SOURCE_SAVE_FEATURE = 'document.save.source';
|
|
10
11
|
const DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE = 'host.request.timeoutMs';
|
|
@@ -103,6 +104,30 @@ function mapDocumentOpenResult(response, sessionId, path) {
|
|
|
103
104
|
dirty: false,
|
|
104
105
|
};
|
|
105
106
|
}
|
|
107
|
+
function mapDocumentReplaceFileResult(response, sessionId) {
|
|
108
|
+
if (typeof response !== 'object' || response == null || Array.isArray(response)) {
|
|
109
|
+
throw new errors.SuperDocCliError('Host returned invalid document.replaceFile result.', {
|
|
110
|
+
code: 'HOST_PROTOCOL_ERROR',
|
|
111
|
+
details: { result: response },
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
const record = response;
|
|
115
|
+
if (record.sessionId !== sessionId ||
|
|
116
|
+
record.replaced !== true ||
|
|
117
|
+
typeof record.byteLength !== 'number' ||
|
|
118
|
+
typeof record.revision !== 'string') {
|
|
119
|
+
throw new errors.SuperDocCliError('Host returned invalid document.replaceFile session metadata.', {
|
|
120
|
+
code: 'HOST_PROTOCOL_ERROR',
|
|
121
|
+
details: { expectedSessionId: sessionId, result: response },
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
contextId: sessionId,
|
|
126
|
+
runtime: 'v2',
|
|
127
|
+
replaced: true,
|
|
128
|
+
document: { byteLength: record.byteLength, revision: record.revision },
|
|
129
|
+
};
|
|
130
|
+
}
|
|
106
131
|
function supportsTrackedMode(operation) {
|
|
107
132
|
return operation.supportsTrackedMode === true || operation.supportsConditionalTrackedMode === true;
|
|
108
133
|
}
|
|
@@ -316,6 +341,7 @@ function mapDocumentLifecycleResult(operationId, response, sessionId, expectedIn
|
|
|
316
341
|
|
|
317
342
|
exports.DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE = DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE;
|
|
318
343
|
exports.DOCUMENT_RPC_FEATURES = DOCUMENT_RPC_FEATURES;
|
|
344
|
+
exports.DOCUMENT_RPC_REPLACE_FILE_FEATURE = DOCUMENT_RPC_REPLACE_FILE_FEATURE;
|
|
319
345
|
exports.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE = DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE;
|
|
320
346
|
exports.DOCUMENT_RPC_SOURCE_SAVE_FEATURE = DOCUMENT_RPC_SOURCE_SAVE_FEATURE;
|
|
321
347
|
exports.buildDocumentInvokeParams = buildDocumentInvokeParams;
|
|
@@ -325,4 +351,5 @@ exports.documentRpcEnabled = documentRpcEnabled;
|
|
|
325
351
|
exports.documentRpcRequestSupportsResponseTimeout = documentRpcRequestSupportsResponseTimeout;
|
|
326
352
|
exports.mapDocumentLifecycleResult = mapDocumentLifecycleResult;
|
|
327
353
|
exports.mapDocumentOpenResult = mapDocumentOpenResult;
|
|
354
|
+
exports.mapDocumentReplaceFileResult = mapDocumentReplaceFileResult;
|
|
328
355
|
exports.supportsDocumentRpc = supportsDocumentRpc;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ChangeMode, type InvokeOptions, type OperationSpec, type UserIdentity } from './transport-common.js';
|
|
2
2
|
export declare const DOCUMENT_RPC_FEATURES: readonly ["document.open", "document.invoke", "document.save", "document.close"];
|
|
3
|
+
export declare const DOCUMENT_RPC_REPLACE_FILE_FEATURE = "document.replaceFile";
|
|
3
4
|
export declare const DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE = "document.open.defaultChangeMode";
|
|
4
5
|
export declare const DOCUMENT_RPC_SOURCE_SAVE_FEATURE = "document.save.source";
|
|
5
6
|
export declare const DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE = "host.request.timeoutMs";
|
|
@@ -15,6 +16,7 @@ export declare function buildDocumentOpenParams(params: Record<string, unknown>,
|
|
|
15
16
|
readonly params: Record<string, unknown>;
|
|
16
17
|
};
|
|
17
18
|
export declare function mapDocumentOpenResult(response: unknown, sessionId: string, path: string): Record<string, unknown>;
|
|
19
|
+
export declare function mapDocumentReplaceFileResult(response: unknown, sessionId: string): Record<string, unknown>;
|
|
18
20
|
export declare function buildDocumentInvokeParams(sessionId: string, operation: OperationSpec, params: Record<string, unknown>, options: InvokeOptions, hostFeatures?: ReadonlySet<string>): {
|
|
19
21
|
readonly method: string;
|
|
20
22
|
readonly params: Record<string, unknown>;
|
|
@@ -2,6 +2,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
2
2
|
import { SuperDocCliError } from './errors.js';
|
|
3
3
|
import { applyOperationParamAliases, } from './transport-common.js';
|
|
4
4
|
export const DOCUMENT_RPC_FEATURES = ['document.open', 'document.invoke', 'document.save', 'document.close'];
|
|
5
|
+
export const DOCUMENT_RPC_REPLACE_FILE_FEATURE = 'document.replaceFile';
|
|
5
6
|
export const DOCUMENT_RPC_DEFAULT_CHANGE_MODE_FEATURE = 'document.open.defaultChangeMode';
|
|
6
7
|
export const DOCUMENT_RPC_SOURCE_SAVE_FEATURE = 'document.save.source';
|
|
7
8
|
export const DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE = 'host.request.timeoutMs';
|
|
@@ -100,6 +101,30 @@ export function mapDocumentOpenResult(response, sessionId, path) {
|
|
|
100
101
|
dirty: false,
|
|
101
102
|
};
|
|
102
103
|
}
|
|
104
|
+
export function mapDocumentReplaceFileResult(response, sessionId) {
|
|
105
|
+
if (typeof response !== 'object' || response == null || Array.isArray(response)) {
|
|
106
|
+
throw new SuperDocCliError('Host returned invalid document.replaceFile result.', {
|
|
107
|
+
code: 'HOST_PROTOCOL_ERROR',
|
|
108
|
+
details: { result: response },
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
const record = response;
|
|
112
|
+
if (record.sessionId !== sessionId ||
|
|
113
|
+
record.replaced !== true ||
|
|
114
|
+
typeof record.byteLength !== 'number' ||
|
|
115
|
+
typeof record.revision !== 'string') {
|
|
116
|
+
throw new SuperDocCliError('Host returned invalid document.replaceFile session metadata.', {
|
|
117
|
+
code: 'HOST_PROTOCOL_ERROR',
|
|
118
|
+
details: { expectedSessionId: sessionId, result: response },
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
contextId: sessionId,
|
|
123
|
+
runtime: 'v2',
|
|
124
|
+
replaced: true,
|
|
125
|
+
document: { byteLength: record.byteLength, revision: record.revision },
|
|
126
|
+
};
|
|
127
|
+
}
|
|
103
128
|
function supportsTrackedMode(operation) {
|
|
104
129
|
return operation.supportsTrackedMode === true || operation.supportsConditionalTrackedMode === true;
|
|
105
130
|
}
|
package/dist/runtime/host.cjs
CHANGED
|
@@ -4,6 +4,7 @@ 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 documentEvidence = require('./document-evidence.cjs');
|
|
7
8
|
var documentRpc = require('./document-rpc.cjs');
|
|
8
9
|
|
|
9
10
|
const HOST_PROTOCOL_VERSION = '1.0';
|
|
@@ -130,6 +131,28 @@ class HostTransport {
|
|
|
130
131
|
async connect() {
|
|
131
132
|
await this.runWhileActive(() => this.ensureConnected());
|
|
132
133
|
}
|
|
134
|
+
supportsDocumentFacts(sessionId) {
|
|
135
|
+
return (this.documentRpcSessions.has(sessionId) &&
|
|
136
|
+
this.hostFeatures.has('document.currentRevision') &&
|
|
137
|
+
this.hostFeatures.has('document.executionFacts') &&
|
|
138
|
+
this.hostFeatures.has('document.mutationRevision'));
|
|
139
|
+
}
|
|
140
|
+
async readDocumentRevision(sessionId) {
|
|
141
|
+
return this.runWhileActive(async () => {
|
|
142
|
+
if (!this.documentRpcSessions.has(sessionId) || !this.hostFeatures.has('document.currentRevision')) {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
await this.ensureConnected();
|
|
146
|
+
const revision = await this.sendJsonRpcRequest('document.currentRevision', { sessionId }, this.resolveWatchdogTimeout(undefined), { requestTimeoutMs: this.resolveDocumentRequestTimeout(undefined) });
|
|
147
|
+
if (typeof revision !== 'string' || revision.trim().length === 0 || revision === 'unknown') {
|
|
148
|
+
throw new errors.SuperDocCliError('Document host returned an invalid current revision.', {
|
|
149
|
+
code: 'HOST_PROTOCOL_ERROR',
|
|
150
|
+
details: { sessionId },
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
return revision;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
133
156
|
async dispose() {
|
|
134
157
|
if (this.disposePromise)
|
|
135
158
|
return this.disposePromise;
|
|
@@ -187,6 +210,34 @@ class HostTransport {
|
|
|
187
210
|
async invoke(operation, params = {}, options = {}) {
|
|
188
211
|
return this.runWhileActive(() => this.invokeWhileActive(operation, params, options));
|
|
189
212
|
}
|
|
213
|
+
async replaceFile(sessionId, path, options = {}) {
|
|
214
|
+
return this.runWhileActive(async () => {
|
|
215
|
+
await this.ensureConnected();
|
|
216
|
+
if (!this.hostFeatures.has(documentRpc.DOCUMENT_RPC_REPLACE_FILE_FEATURE)) {
|
|
217
|
+
throw new errors.SuperDocCliError('The connected host does not support document replacement.', {
|
|
218
|
+
code: 'CAPABILITY_UNSUPPORTED',
|
|
219
|
+
details: { feature: documentRpc.DOCUMENT_RPC_REPLACE_FILE_FEATURE },
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
const tracksDirectSession = this.documentRpcSessions.has(sessionId);
|
|
223
|
+
if (tracksDirectSession)
|
|
224
|
+
this.beginDocumentRpcMutation(sessionId);
|
|
225
|
+
try {
|
|
226
|
+
const response = await this.sendJsonRpcRequest(documentRpc.DOCUMENT_RPC_REPLACE_FILE_FEATURE, { sessionId, path }, this.resolveWatchdogTimeout(options.timeoutMs));
|
|
227
|
+
const result = documentRpc.mapDocumentReplaceFileResult(response, sessionId);
|
|
228
|
+
if (tracksDirectSession)
|
|
229
|
+
this.settleDocumentRpcMutation(sessionId, 'applied');
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
if (tracksDirectSession) {
|
|
234
|
+
const indeterminate = error instanceof errors.SuperDocCliError && ['TIMEOUT', 'HOST_TIMEOUT', 'HOST_DISCONNECTED'].includes(error.code);
|
|
235
|
+
this.settleDocumentRpcMutation(sessionId, indeterminate ? 'indeterminate' : 'not-applied');
|
|
236
|
+
}
|
|
237
|
+
throw error;
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
190
241
|
async invokeWhileActive(operation, params, options) {
|
|
191
242
|
const collaborationAuth = options.collaborationAuth === undefined ? undefined : transportCommon.normalizeCollaborationAuth(options.collaborationAuth);
|
|
192
243
|
if (collaborationAuth !== undefined) {
|
|
@@ -240,12 +291,17 @@ class HostTransport {
|
|
|
240
291
|
? request.params.options
|
|
241
292
|
: undefined;
|
|
242
293
|
const tracksMutation = request.method === 'document.invoke' && documentOperation.mutates === true && requestOptions?.dryRun !== true;
|
|
294
|
+
const includeRevision = request.method === 'document.invoke' &&
|
|
295
|
+
documentOperation.mutates === true &&
|
|
296
|
+
this.hostFeatures.has('document.mutationRevision');
|
|
243
297
|
if (tracksMutation)
|
|
244
298
|
this.beginDocumentRpcMutation(sessionId);
|
|
245
299
|
let result;
|
|
246
300
|
try {
|
|
247
|
-
const response = await this.sendJsonRpcRequest(request.method, request.params, this.resolveWatchdogTimeout(options.timeoutMs), { requestTimeoutMs });
|
|
248
|
-
result = documentRpc.mapDocumentLifecycleResult(operation.operationId, response, sessionId, operation.operationId === 'doc.save' ? request.params.path === undefined : undefined);
|
|
301
|
+
const response = await this.sendJsonRpcRequest(request.method, { ...request.params, ...(includeRevision ? { includeRevision: true } : {}) }, this.resolveWatchdogTimeout(options.timeoutMs), { requestTimeoutMs });
|
|
302
|
+
result = documentRpc.mapDocumentLifecycleResult(operation.operationId, includeRevision ? response.result : response, sessionId, operation.operationId === 'doc.save' ? request.params.path === undefined : undefined);
|
|
303
|
+
if (includeRevision)
|
|
304
|
+
documentEvidence.registerMutationRevision(result, response.revision);
|
|
249
305
|
}
|
|
250
306
|
catch (error) {
|
|
251
307
|
if (tracksMutation) {
|
|
@@ -285,8 +341,11 @@ class HostTransport {
|
|
|
285
341
|
details: { operationId: operation.operationId },
|
|
286
342
|
});
|
|
287
343
|
}
|
|
344
|
+
const supportsRequestTimeoutMetadata = this.hostFeatures.has(documentRpc.DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE);
|
|
288
345
|
const cliHostRequestTimeoutMs = this.requestTimeoutMs ?? HOST_DEFAULT_REQUEST_TIMEOUT_MS;
|
|
289
|
-
if (
|
|
346
|
+
if (!supportsRequestTimeoutMetadata &&
|
|
347
|
+
options.timeoutMs !== undefined &&
|
|
348
|
+
options.timeoutMs > cliHostRequestTimeoutMs) {
|
|
290
349
|
throw new errors.SuperDocCliError(`CLI host cannot honor timeoutMs=${options.timeoutMs} above its ${cliHostRequestTimeoutMs}ms request ceiling.`, {
|
|
291
350
|
code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
|
|
292
351
|
details: {
|
|
@@ -304,7 +363,9 @@ class HostTransport {
|
|
|
304
363
|
argv,
|
|
305
364
|
stdinBase64,
|
|
306
365
|
...(collaborationAuth === undefined ? {} : { collaborationAuth }),
|
|
307
|
-
}, watchdogTimeout
|
|
366
|
+
}, watchdogTimeout, {
|
|
367
|
+
requestTimeoutMs: supportsRequestTimeoutMetadata ? options.timeoutMs : undefined,
|
|
368
|
+
});
|
|
308
369
|
if (typeof response !== 'object' || response == null || Array.isArray(response)) {
|
|
309
370
|
throw new errors.SuperDocCliError('Host returned invalid cli.invoke result.', {
|
|
310
371
|
code: 'HOST_PROTOCOL_ERROR',
|
package/dist/runtime/host.d.ts
CHANGED
|
@@ -61,9 +61,12 @@ export declare class HostTransport {
|
|
|
61
61
|
processMode?: 'cli' | 'document';
|
|
62
62
|
} & SuperDocClientOptions);
|
|
63
63
|
connect(): Promise<void>;
|
|
64
|
+
supportsDocumentFacts(sessionId: string): boolean;
|
|
65
|
+
readDocumentRevision(sessionId: string): Promise<string | undefined>;
|
|
64
66
|
dispose(): Promise<void>;
|
|
65
67
|
private disposeAfterActiveCalls;
|
|
66
68
|
invoke<TData = unknown>(operation: OperationSpec, params?: Record<string, unknown>, options?: TransportInvokeOptions): Promise<TData>;
|
|
69
|
+
replaceFile(sessionId: string, path: string, options?: TransportInvokeOptions): Promise<Record<string, unknown>>;
|
|
67
70
|
private invokeWhileActive;
|
|
68
71
|
private runWhileActive;
|
|
69
72
|
private ensureConnected;
|
package/dist/runtime/host.js
CHANGED
|
@@ -2,7 +2,8 @@ import { spawn } from 'node:child_process';
|
|
|
2
2
|
import { createInterface } from 'node:readline';
|
|
3
3
|
import { buildOperationArgv, normalizeCollaborationAuth, resolveInvocation, } from './transport-common.js';
|
|
4
4
|
import { SuperDocCliError } from './errors.js';
|
|
5
|
-
import {
|
|
5
|
+
import { registerMutationRevision } from './document-evidence.js';
|
|
6
|
+
import { DOCUMENT_RPC_FEATURES, 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';
|
|
6
7
|
const HOST_PROTOCOL_VERSION = '1.0';
|
|
7
8
|
const CLI_HOST_REQUIRED_FEATURES = ['cli.invoke', 'host.shutdown'];
|
|
8
9
|
export const COLLABORATION_AUTH_PER_OPEN_FEATURE = 'collaboration.auth.perOpen';
|
|
@@ -127,6 +128,28 @@ export class HostTransport {
|
|
|
127
128
|
async connect() {
|
|
128
129
|
await this.runWhileActive(() => this.ensureConnected());
|
|
129
130
|
}
|
|
131
|
+
supportsDocumentFacts(sessionId) {
|
|
132
|
+
return (this.documentRpcSessions.has(sessionId) &&
|
|
133
|
+
this.hostFeatures.has('document.currentRevision') &&
|
|
134
|
+
this.hostFeatures.has('document.executionFacts') &&
|
|
135
|
+
this.hostFeatures.has('document.mutationRevision'));
|
|
136
|
+
}
|
|
137
|
+
async readDocumentRevision(sessionId) {
|
|
138
|
+
return this.runWhileActive(async () => {
|
|
139
|
+
if (!this.documentRpcSessions.has(sessionId) || !this.hostFeatures.has('document.currentRevision')) {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
await this.ensureConnected();
|
|
143
|
+
const revision = await this.sendJsonRpcRequest('document.currentRevision', { sessionId }, this.resolveWatchdogTimeout(undefined), { requestTimeoutMs: this.resolveDocumentRequestTimeout(undefined) });
|
|
144
|
+
if (typeof revision !== 'string' || revision.trim().length === 0 || revision === 'unknown') {
|
|
145
|
+
throw new SuperDocCliError('Document host returned an invalid current revision.', {
|
|
146
|
+
code: 'HOST_PROTOCOL_ERROR',
|
|
147
|
+
details: { sessionId },
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return revision;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
130
153
|
async dispose() {
|
|
131
154
|
if (this.disposePromise)
|
|
132
155
|
return this.disposePromise;
|
|
@@ -184,6 +207,34 @@ export class HostTransport {
|
|
|
184
207
|
async invoke(operation, params = {}, options = {}) {
|
|
185
208
|
return this.runWhileActive(() => this.invokeWhileActive(operation, params, options));
|
|
186
209
|
}
|
|
210
|
+
async replaceFile(sessionId, path, options = {}) {
|
|
211
|
+
return this.runWhileActive(async () => {
|
|
212
|
+
await this.ensureConnected();
|
|
213
|
+
if (!this.hostFeatures.has(DOCUMENT_RPC_REPLACE_FILE_FEATURE)) {
|
|
214
|
+
throw new SuperDocCliError('The connected host does not support document replacement.', {
|
|
215
|
+
code: 'CAPABILITY_UNSUPPORTED',
|
|
216
|
+
details: { feature: DOCUMENT_RPC_REPLACE_FILE_FEATURE },
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
const tracksDirectSession = this.documentRpcSessions.has(sessionId);
|
|
220
|
+
if (tracksDirectSession)
|
|
221
|
+
this.beginDocumentRpcMutation(sessionId);
|
|
222
|
+
try {
|
|
223
|
+
const response = await this.sendJsonRpcRequest(DOCUMENT_RPC_REPLACE_FILE_FEATURE, { sessionId, path }, this.resolveWatchdogTimeout(options.timeoutMs));
|
|
224
|
+
const result = mapDocumentReplaceFileResult(response, sessionId);
|
|
225
|
+
if (tracksDirectSession)
|
|
226
|
+
this.settleDocumentRpcMutation(sessionId, 'applied');
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
if (tracksDirectSession) {
|
|
231
|
+
const indeterminate = error instanceof SuperDocCliError && ['TIMEOUT', 'HOST_TIMEOUT', 'HOST_DISCONNECTED'].includes(error.code);
|
|
232
|
+
this.settleDocumentRpcMutation(sessionId, indeterminate ? 'indeterminate' : 'not-applied');
|
|
233
|
+
}
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
}
|
|
187
238
|
async invokeWhileActive(operation, params, options) {
|
|
188
239
|
const collaborationAuth = options.collaborationAuth === undefined ? undefined : normalizeCollaborationAuth(options.collaborationAuth);
|
|
189
240
|
if (collaborationAuth !== undefined) {
|
|
@@ -237,12 +288,17 @@ export class HostTransport {
|
|
|
237
288
|
? request.params.options
|
|
238
289
|
: undefined;
|
|
239
290
|
const tracksMutation = request.method === 'document.invoke' && documentOperation.mutates === true && requestOptions?.dryRun !== true;
|
|
291
|
+
const includeRevision = request.method === 'document.invoke' &&
|
|
292
|
+
documentOperation.mutates === true &&
|
|
293
|
+
this.hostFeatures.has('document.mutationRevision');
|
|
240
294
|
if (tracksMutation)
|
|
241
295
|
this.beginDocumentRpcMutation(sessionId);
|
|
242
296
|
let result;
|
|
243
297
|
try {
|
|
244
|
-
const response = await this.sendJsonRpcRequest(request.method, request.params, this.resolveWatchdogTimeout(options.timeoutMs), { requestTimeoutMs });
|
|
245
|
-
result = mapDocumentLifecycleResult(operation.operationId, response, sessionId, operation.operationId === 'doc.save' ? request.params.path === undefined : undefined);
|
|
298
|
+
const response = await this.sendJsonRpcRequest(request.method, { ...request.params, ...(includeRevision ? { includeRevision: true } : {}) }, this.resolveWatchdogTimeout(options.timeoutMs), { requestTimeoutMs });
|
|
299
|
+
result = mapDocumentLifecycleResult(operation.operationId, includeRevision ? response.result : response, sessionId, operation.operationId === 'doc.save' ? request.params.path === undefined : undefined);
|
|
300
|
+
if (includeRevision)
|
|
301
|
+
registerMutationRevision(result, response.revision);
|
|
246
302
|
}
|
|
247
303
|
catch (error) {
|
|
248
304
|
if (tracksMutation) {
|
|
@@ -282,8 +338,11 @@ export class HostTransport {
|
|
|
282
338
|
details: { operationId: operation.operationId },
|
|
283
339
|
});
|
|
284
340
|
}
|
|
341
|
+
const supportsRequestTimeoutMetadata = this.hostFeatures.has(DOCUMENT_RPC_REQUEST_TIMEOUT_FEATURE);
|
|
285
342
|
const cliHostRequestTimeoutMs = this.requestTimeoutMs ?? HOST_DEFAULT_REQUEST_TIMEOUT_MS;
|
|
286
|
-
if (
|
|
343
|
+
if (!supportsRequestTimeoutMetadata &&
|
|
344
|
+
options.timeoutMs !== undefined &&
|
|
345
|
+
options.timeoutMs > cliHostRequestTimeoutMs) {
|
|
287
346
|
throw new SuperDocCliError(`CLI host cannot honor timeoutMs=${options.timeoutMs} above its ${cliHostRequestTimeoutMs}ms request ceiling.`, {
|
|
288
347
|
code: 'DOCUMENT_RPC_INPUT_UNSUPPORTED',
|
|
289
348
|
details: {
|
|
@@ -301,7 +360,9 @@ export class HostTransport {
|
|
|
301
360
|
argv,
|
|
302
361
|
stdinBase64,
|
|
303
362
|
...(collaborationAuth === undefined ? {} : { collaborationAuth }),
|
|
304
|
-
}, watchdogTimeout
|
|
363
|
+
}, watchdogTimeout, {
|
|
364
|
+
requestTimeoutMs: supportsRequestTimeoutMetadata ? options.timeoutMs : undefined,
|
|
365
|
+
});
|
|
305
366
|
if (typeof response !== 'object' || response == null || Array.isArray(response)) {
|
|
306
367
|
throw new SuperDocCliError('Host returned invalid cli.invoke result.', {
|
|
307
368
|
code: 'HOST_PROTOCOL_ERROR',
|