@superdoc/sdk 2.7.0 → 2.9.0-next.1
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 +21 -0
- package/dist/generated/client.d.ts +1 -0
- package/dist/generated/contract.cjs +9 -0
- package/dist/generated/contract.js +10 -0
- package/dist/index.cjs +22 -12
- package/dist/index.d.ts +4 -3
- package/dist/index.js +22 -12
- package/dist/presets/core.cjs +62 -10
- package/dist/presets/core.js +62 -10
- package/dist/runtime/embedded-platform.cjs +18 -12
- package/dist/runtime/embedded-platform.js +18 -12
- package/dist/runtime/host.cjs +192 -7
- package/dist/runtime/host.d.ts +18 -2
- package/dist/runtime/host.js +193 -9
- package/dist/runtime/process.cjs +6 -1
- package/dist/runtime/process.d.ts +4 -3
- package/dist/runtime/process.js +5 -1
- package/dist/runtime/sdk-version.generated.cjs +8 -0
- package/dist/runtime/sdk-version.generated.d.ts +1 -0
- package/dist/runtime/sdk-version.generated.js +4 -0
- package/dist/runtime/transport-common.cjs +22 -0
- package/dist/runtime/transport-common.d.ts +11 -0
- package/dist/runtime/transport-common.js +21 -0
- package/package.json +8 -7
- package/tools/__pycache__/__init__.cpython-311.pyc +0 -0
- package/tools/__pycache__/intent_dispatch_generated.cpython-311.pyc +0 -0
package/README.md
CHANGED
|
@@ -25,6 +25,27 @@ await document.close();
|
|
|
25
25
|
await client.dispose();
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
For token-authenticated Hocuspocus or y-websocket rooms, pass the credential as
|
|
29
|
+
an option on that document's open request:
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
const document = await client.open(
|
|
33
|
+
{
|
|
34
|
+
doc: './contract.docx',
|
|
35
|
+
collaboration: {
|
|
36
|
+
providerType: 'hocuspocus',
|
|
37
|
+
url: 'wss://collaboration.example.com',
|
|
38
|
+
documentId: 'contract-123',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
{ collaborationAuth: { type: 'token', token: userToken } },
|
|
42
|
+
);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The credential applies only to that open request. It is not part of the
|
|
46
|
+
collaboration profile or command-line arguments. Per-open token authentication
|
|
47
|
+
is not supported for Liveblocks or the standalone document host.
|
|
48
|
+
|
|
28
49
|
See the [Node.js SDK guide](https://docs.superdoc.dev/agents/automation/node-sdk) for a complete workflow.
|
|
29
50
|
|
|
30
51
|
## License
|
|
@@ -29333,6 +29333,7 @@ export interface DocOpenParams {
|
|
|
29333
29333
|
url: string;
|
|
29334
29334
|
documentId?: string;
|
|
29335
29335
|
tokenEnv?: string;
|
|
29336
|
+
headersEnv?: string;
|
|
29336
29337
|
params?: Record<string, unknown>;
|
|
29337
29338
|
syncTimeoutMs?: number;
|
|
29338
29339
|
roomMode?: "join" | "create";
|
|
@@ -17,6 +17,7 @@ const CONTRACT = {
|
|
|
17
17
|
"protocolVersion": "1.0",
|
|
18
18
|
"features": [
|
|
19
19
|
"cli.invoke",
|
|
20
|
+
"collaboration.auth.perOpen",
|
|
20
21
|
"document.open",
|
|
21
22
|
"document.open.defaultChangeMode",
|
|
22
23
|
"document.currentRevision",
|
|
@@ -296902,6 +296903,10 @@ const CONTRACT = {
|
|
|
296902
296903
|
"type": "string",
|
|
296903
296904
|
"description": "Environment variable name containing the auth token."
|
|
296904
296905
|
},
|
|
296906
|
+
"headersEnv": {
|
|
296907
|
+
"type": "string",
|
|
296908
|
+
"description": "Environment variable name containing JSON WebSocket headers. Supported by y-websocket."
|
|
296909
|
+
},
|
|
296905
296910
|
"params": {
|
|
296906
296911
|
"type": "object",
|
|
296907
296912
|
"description": "Custom query parameters appended to the WebSocket URL. Values must be strings. Reserved keys: token.",
|
|
@@ -297149,6 +297154,10 @@ const CONTRACT = {
|
|
|
297149
297154
|
"type": "string",
|
|
297150
297155
|
"description": "Environment variable name containing the auth token."
|
|
297151
297156
|
},
|
|
297157
|
+
"headersEnv": {
|
|
297158
|
+
"type": "string",
|
|
297159
|
+
"description": "Environment variable name containing JSON WebSocket headers. Supported by y-websocket."
|
|
297160
|
+
},
|
|
297152
297161
|
"params": {
|
|
297153
297162
|
"type": "object",
|
|
297154
297163
|
"description": "Custom query parameters appended to the WebSocket URL. Values must be strings. Reserved keys: token.",
|
|
@@ -2901,6 +2901,7 @@ export const CONTRACT = {
|
|
|
2901
2901
|
"transport": "stdio",
|
|
2902
2902
|
"features": [
|
|
2903
2903
|
"cli.invoke",
|
|
2904
|
+
"collaboration.auth.perOpen",
|
|
2904
2905
|
"document.open",
|
|
2905
2906
|
"document.open.defaultChangeMode",
|
|
2906
2907
|
"document.currentRevision",
|
|
@@ -2931,6 +2932,7 @@ export const CONTRACT = {
|
|
|
2931
2932
|
"protocolVersion": "1.0",
|
|
2932
2933
|
"features": [
|
|
2933
2934
|
"cli.invoke",
|
|
2935
|
+
"collaboration.auth.perOpen",
|
|
2934
2936
|
"document.open",
|
|
2935
2937
|
"document.open.defaultChangeMode",
|
|
2936
2938
|
"document.currentRevision",
|
|
@@ -299816,6 +299818,10 @@ export const CONTRACT = {
|
|
|
299816
299818
|
"type": "string",
|
|
299817
299819
|
"description": "Environment variable name containing the auth token."
|
|
299818
299820
|
},
|
|
299821
|
+
"headersEnv": {
|
|
299822
|
+
"type": "string",
|
|
299823
|
+
"description": "Environment variable name containing JSON WebSocket headers. Supported by y-websocket."
|
|
299824
|
+
},
|
|
299819
299825
|
"params": {
|
|
299820
299826
|
"type": "object",
|
|
299821
299827
|
"description": "Custom query parameters appended to the WebSocket URL. Values must be strings. Reserved keys: token.",
|
|
@@ -300063,6 +300069,10 @@ export const CONTRACT = {
|
|
|
300063
300069
|
"type": "string",
|
|
300064
300070
|
"description": "Environment variable name containing the auth token."
|
|
300065
300071
|
},
|
|
300072
|
+
"headersEnv": {
|
|
300073
|
+
"type": "string",
|
|
300074
|
+
"description": "Environment variable name containing JSON WebSocket headers. Supported by y-websocket."
|
|
300075
|
+
},
|
|
300066
300076
|
"params": {
|
|
300067
300077
|
"type": "object",
|
|
300068
300078
|
"description": "Custom query parameters appended to the WebSocket URL. Values must be strings. Reserved keys: token.",
|
package/dist/index.cjs
CHANGED
|
@@ -113,6 +113,7 @@ class SuperDocClient {
|
|
|
113
113
|
rawApi;
|
|
114
114
|
defaultDocumentRuntime;
|
|
115
115
|
handles = new Map();
|
|
116
|
+
pendingSessionIds = new Set();
|
|
116
117
|
constructor(options = {}) {
|
|
117
118
|
this.defaultDocumentRuntime = options.runtime;
|
|
118
119
|
this.runtime = new process.SuperDocRuntime(options);
|
|
@@ -133,18 +134,27 @@ class SuperDocClient {
|
|
|
133
134
|
? { ...params, runtime: this.defaultDocumentRuntime }
|
|
134
135
|
: params;
|
|
135
136
|
const explicitSessionId = openParams.sessionId;
|
|
136
|
-
if (typeof explicitSessionId === 'string'
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
137
|
+
if (typeof explicitSessionId === 'string') {
|
|
138
|
+
if (this.handles.has(explicitSessionId) || this.pendingSessionIds.has(explicitSessionId)) {
|
|
139
|
+
throw new errors.SuperDocCliError(`Session id already open in this client: ${explicitSessionId}`, {
|
|
140
|
+
code: 'SESSION_ALREADY_OPEN',
|
|
141
|
+
details: { sessionId: explicitSessionId },
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
this.pendingSessionIds.add(explicitSessionId);
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
const result = (await this.rawApi.open(openParams, options));
|
|
148
|
+
const contextId = result.contextId;
|
|
149
|
+
const boundRuntime = new BoundRuntime(this.runtime, contextId);
|
|
150
|
+
const handle = new SuperDocDocument(boundRuntime, contextId, result, this);
|
|
151
|
+
this.handles.set(contextId, handle);
|
|
152
|
+
return handle;
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
if (typeof explicitSessionId === 'string')
|
|
156
|
+
this.pendingSessionIds.delete(explicitSessionId);
|
|
141
157
|
}
|
|
142
|
-
const result = (await this.rawApi.open(openParams, options));
|
|
143
|
-
const contextId = result.contextId;
|
|
144
|
-
const boundRuntime = new BoundRuntime(this.runtime, contextId);
|
|
145
|
-
const handle = new SuperDocDocument(boundRuntime, contextId, result, this);
|
|
146
|
-
this.handles.set(contextId, handle);
|
|
147
|
-
return handle;
|
|
148
158
|
}
|
|
149
159
|
async describe(_params = {}, _options) {
|
|
150
160
|
return introspection.describeContract();
|
|
@@ -153,11 +163,11 @@ class SuperDocClient {
|
|
|
153
163
|
return introspection.describeContractOperation(params);
|
|
154
164
|
}
|
|
155
165
|
async dispose() {
|
|
166
|
+
await this.runtime.dispose();
|
|
156
167
|
for (const handle of this.handles.values()) {
|
|
157
168
|
handle.markClosed();
|
|
158
169
|
}
|
|
159
170
|
this.handles.clear();
|
|
160
|
-
await this.runtime.dispose();
|
|
161
171
|
}
|
|
162
172
|
/** @internal */
|
|
163
173
|
removeHandle(sessionId) {
|
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 InvokeOptions, type OperationSpec, type RuntimeInvoker } from './runtime/process.js';
|
|
2
|
+
import { SuperDocRuntime, type SuperDocClientOptions, type DocOpenOptions, type InvokeOptions, type OperationSpec, 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.
|
|
@@ -64,6 +64,7 @@ export declare class SuperDocClient {
|
|
|
64
64
|
private readonly rawApi;
|
|
65
65
|
private readonly defaultDocumentRuntime;
|
|
66
66
|
private readonly handles;
|
|
67
|
+
private readonly pendingSessionIds;
|
|
67
68
|
constructor(options?: SuperDocClientOptions);
|
|
68
69
|
connect(): Promise<void>;
|
|
69
70
|
/**
|
|
@@ -73,7 +74,7 @@ export declare class SuperDocClient {
|
|
|
73
74
|
* automatically. The same file can be opened multiple times with
|
|
74
75
|
* different session ids (useful for diff workflows).
|
|
75
76
|
*/
|
|
76
|
-
open(params: DocOpenParams, options?:
|
|
77
|
+
open(params: DocOpenParams, options?: DocOpenOptions): Promise<SuperDocDocument>;
|
|
77
78
|
describe(_params?: Record<string, unknown>, _options?: InvokeOptions): Promise<unknown>;
|
|
78
79
|
describeCommand(params: DocDescribeCommandParams, _options?: InvokeOptions): Promise<unknown>;
|
|
79
80
|
dispose(): Promise<void>;
|
|
@@ -93,5 +94,5 @@ export type { GetSystemPromptOptions, GetToolsOptions, GetToolsResult, PresetDes
|
|
|
93
94
|
export { createAgentToolkit } from './tools.js';
|
|
94
95
|
export type { AgentToolkit, CreateAgentToolkitInput } from './tools.js';
|
|
95
96
|
export { SuperDocCliError } from './runtime/errors.js';
|
|
96
|
-
export type { InvokeOptions, OperationSpec, OperationParamSpec, RuntimeInvoker, SuperDocClientOptions, } from './runtime/process.js';
|
|
97
|
+
export type { CollaborationAuth, DocOpenOptions, InvokeOptions, OperationSpec, OperationParamSpec, RuntimeInvoker, SuperDocClientOptions, } from './runtime/process.js';
|
|
97
98
|
export type { DocOpenResult } from './generated/client.js';
|
package/dist/index.js
CHANGED
|
@@ -105,6 +105,7 @@ export class SuperDocClient {
|
|
|
105
105
|
rawApi;
|
|
106
106
|
defaultDocumentRuntime;
|
|
107
107
|
handles = new Map();
|
|
108
|
+
pendingSessionIds = new Set();
|
|
108
109
|
constructor(options = {}) {
|
|
109
110
|
this.defaultDocumentRuntime = options.runtime;
|
|
110
111
|
this.runtime = new SuperDocRuntime(options);
|
|
@@ -125,18 +126,27 @@ export class SuperDocClient {
|
|
|
125
126
|
? { ...params, runtime: this.defaultDocumentRuntime }
|
|
126
127
|
: params;
|
|
127
128
|
const explicitSessionId = openParams.sessionId;
|
|
128
|
-
if (typeof explicitSessionId === 'string'
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
if (typeof explicitSessionId === 'string') {
|
|
130
|
+
if (this.handles.has(explicitSessionId) || this.pendingSessionIds.has(explicitSessionId)) {
|
|
131
|
+
throw new SuperDocCliError(`Session id already open in this client: ${explicitSessionId}`, {
|
|
132
|
+
code: 'SESSION_ALREADY_OPEN',
|
|
133
|
+
details: { sessionId: explicitSessionId },
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
this.pendingSessionIds.add(explicitSessionId);
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const result = (await this.rawApi.open(openParams, options));
|
|
140
|
+
const contextId = result.contextId;
|
|
141
|
+
const boundRuntime = new BoundRuntime(this.runtime, contextId);
|
|
142
|
+
const handle = new SuperDocDocument(boundRuntime, contextId, result, this);
|
|
143
|
+
this.handles.set(contextId, handle);
|
|
144
|
+
return handle;
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
if (typeof explicitSessionId === 'string')
|
|
148
|
+
this.pendingSessionIds.delete(explicitSessionId);
|
|
133
149
|
}
|
|
134
|
-
const result = (await this.rawApi.open(openParams, options));
|
|
135
|
-
const contextId = result.contextId;
|
|
136
|
-
const boundRuntime = new BoundRuntime(this.runtime, contextId);
|
|
137
|
-
const handle = new SuperDocDocument(boundRuntime, contextId, result, this);
|
|
138
|
-
this.handles.set(contextId, handle);
|
|
139
|
-
return handle;
|
|
140
150
|
}
|
|
141
151
|
async describe(_params = {}, _options) {
|
|
142
152
|
return describeContract();
|
|
@@ -145,11 +155,11 @@ export class SuperDocClient {
|
|
|
145
155
|
return describeContractOperation(params);
|
|
146
156
|
}
|
|
147
157
|
async dispose() {
|
|
158
|
+
await this.runtime.dispose();
|
|
148
159
|
for (const handle of this.handles.values()) {
|
|
149
160
|
handle.markClosed();
|
|
150
161
|
}
|
|
151
162
|
this.handles.clear();
|
|
152
|
-
await this.runtime.dispose();
|
|
153
163
|
}
|
|
154
164
|
/** @internal */
|
|
155
165
|
removeHandle(sessionId) {
|
package/dist/presets/core.cjs
CHANGED
|
@@ -392,26 +392,78 @@ async function coreGetCatalog() {
|
|
|
392
392
|
};
|
|
393
393
|
}
|
|
394
394
|
/**
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
395
|
+
* Sentence boundary: terminal punctuation, whitespace, then something that
|
|
396
|
+
* plausibly opens a sentence — including lowercase, because prompt sentences
|
|
397
|
+
* regularly start with an action name ("comment_paragraphs applies ...").
|
|
398
|
+
* The lookbehind guards keep "e.g."/"i.e." from splitting mid-sentence; a
|
|
399
|
+
* false split is still safe because kept fragments are rejoined with their
|
|
400
|
+
* original whitespace, and erring toward MORE splits only narrows what a
|
|
401
|
+
* mention takes down with it.
|
|
402
|
+
*/
|
|
403
|
+
const SENTENCE_BOUNDARY = /((?<![ei]\.[ge]\.)(?<=[.!?])\s+(?=[A-Za-z"(]))/;
|
|
404
|
+
function mentionsAnyAction(text, excludedActions) {
|
|
405
|
+
for (const name of excludedActions) {
|
|
406
|
+
if (new RegExp(`\\b${name}\\b`).test(text))
|
|
407
|
+
return true;
|
|
408
|
+
}
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Drop the sentences of one prompt line that mention an excluded action.
|
|
413
|
+
* Returns null when nothing usable is left, so the caller drops the line.
|
|
414
|
+
*/
|
|
415
|
+
function stripExcludedActionSentences(line, excludedActions) {
|
|
416
|
+
if (!mentionsAnyAction(line, excludedActions))
|
|
417
|
+
return line;
|
|
418
|
+
// split() with a capturing group keeps the inter-sentence whitespace as
|
|
419
|
+
// separate array elements: even indexes are sentences, odd their separators.
|
|
420
|
+
const parts = line.split(SENTENCE_BOUNDARY);
|
|
421
|
+
const kept = [];
|
|
422
|
+
for (let i = 0; i < parts.length; i += 2) {
|
|
423
|
+
if (mentionsAnyAction(parts[i], excludedActions))
|
|
424
|
+
continue;
|
|
425
|
+
kept.push(parts[i]);
|
|
426
|
+
if (i + 1 < parts.length)
|
|
427
|
+
kept.push(parts[i + 1]);
|
|
428
|
+
}
|
|
429
|
+
let result = kept.join('').trimEnd();
|
|
430
|
+
// Losing the first sentence must not lose the bullet marker with it.
|
|
431
|
+
if (result && /^- /.test(line) && !/^- /.test(result))
|
|
432
|
+
result = `- ${result}`;
|
|
433
|
+
// Nothing left beyond the marker means the whole line was about excluded
|
|
434
|
+
// actions — drop it entirely rather than leaving an empty bullet.
|
|
435
|
+
return /[a-zA-Z0-9]/.test(result.replace(/^- /, '')) ? result : null;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Remove excluded actions from the prompt: drop their per-action
|
|
439
|
+
* documentation lines (entries render as single "- name: ..." lines — the
|
|
440
|
+
* drift-guard test enforces the format), then drop any remaining sentence
|
|
441
|
+
* that still mentions one. Guidance prose ("use move_range to relocate a
|
|
442
|
+
* section") is instruction, not a passing cross-reference: leaving it coaches
|
|
443
|
+
* the model into calls the schema forbids and dispatch rejects.
|
|
400
444
|
*/
|
|
401
445
|
function stripExcludedActionLines(prompt, excludedActions) {
|
|
402
446
|
if (excludedActions.size === 0)
|
|
403
447
|
return prompt;
|
|
404
448
|
return prompt
|
|
405
449
|
.split('\n')
|
|
406
|
-
.
|
|
450
|
+
.map((line) => {
|
|
407
451
|
const match = /^- ([a-z_]+)(?: \/ ([a-z_]+))?:/.exec(line);
|
|
408
452
|
if (!match)
|
|
409
|
-
return
|
|
453
|
+
return line;
|
|
410
454
|
const names = [match[1], match[2]].filter((n) => Boolean(n));
|
|
411
|
-
|
|
412
|
-
//
|
|
413
|
-
|
|
455
|
+
const callable = names.filter((name) => !excludedActions.has(name));
|
|
456
|
+
// Drop the line only when EVERY action it documents is excluded; a
|
|
457
|
+
// paired accept/reject line survives if one side remains callable, but
|
|
458
|
+
// its header keeps only the callable name.
|
|
459
|
+
if (callable.length === 0)
|
|
460
|
+
return null;
|
|
461
|
+
if (callable.length === names.length)
|
|
462
|
+
return line;
|
|
463
|
+
return `- ${callable.join(' / ')}:${line.slice(match[0].length)}`;
|
|
414
464
|
})
|
|
465
|
+
.map((line) => (line === null ? null : stripExcludedActionSentences(line, excludedActions)))
|
|
466
|
+
.filter((line) => line !== null)
|
|
415
467
|
.join('\n');
|
|
416
468
|
}
|
|
417
469
|
async function coreGetSystemPrompt(options) {
|
package/dist/presets/core.js
CHANGED
|
@@ -388,26 +388,78 @@ async function coreGetCatalog() {
|
|
|
388
388
|
};
|
|
389
389
|
}
|
|
390
390
|
/**
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
391
|
+
* Sentence boundary: terminal punctuation, whitespace, then something that
|
|
392
|
+
* plausibly opens a sentence — including lowercase, because prompt sentences
|
|
393
|
+
* regularly start with an action name ("comment_paragraphs applies ...").
|
|
394
|
+
* The lookbehind guards keep "e.g."/"i.e." from splitting mid-sentence; a
|
|
395
|
+
* false split is still safe because kept fragments are rejoined with their
|
|
396
|
+
* original whitespace, and erring toward MORE splits only narrows what a
|
|
397
|
+
* mention takes down with it.
|
|
398
|
+
*/
|
|
399
|
+
const SENTENCE_BOUNDARY = /((?<![ei]\.[ge]\.)(?<=[.!?])\s+(?=[A-Za-z"(]))/;
|
|
400
|
+
function mentionsAnyAction(text, excludedActions) {
|
|
401
|
+
for (const name of excludedActions) {
|
|
402
|
+
if (new RegExp(`\\b${name}\\b`).test(text))
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Drop the sentences of one prompt line that mention an excluded action.
|
|
409
|
+
* Returns null when nothing usable is left, so the caller drops the line.
|
|
410
|
+
*/
|
|
411
|
+
function stripExcludedActionSentences(line, excludedActions) {
|
|
412
|
+
if (!mentionsAnyAction(line, excludedActions))
|
|
413
|
+
return line;
|
|
414
|
+
// split() with a capturing group keeps the inter-sentence whitespace as
|
|
415
|
+
// separate array elements: even indexes are sentences, odd their separators.
|
|
416
|
+
const parts = line.split(SENTENCE_BOUNDARY);
|
|
417
|
+
const kept = [];
|
|
418
|
+
for (let i = 0; i < parts.length; i += 2) {
|
|
419
|
+
if (mentionsAnyAction(parts[i], excludedActions))
|
|
420
|
+
continue;
|
|
421
|
+
kept.push(parts[i]);
|
|
422
|
+
if (i + 1 < parts.length)
|
|
423
|
+
kept.push(parts[i + 1]);
|
|
424
|
+
}
|
|
425
|
+
let result = kept.join('').trimEnd();
|
|
426
|
+
// Losing the first sentence must not lose the bullet marker with it.
|
|
427
|
+
if (result && /^- /.test(line) && !/^- /.test(result))
|
|
428
|
+
result = `- ${result}`;
|
|
429
|
+
// Nothing left beyond the marker means the whole line was about excluded
|
|
430
|
+
// actions — drop it entirely rather than leaving an empty bullet.
|
|
431
|
+
return /[a-zA-Z0-9]/.test(result.replace(/^- /, '')) ? result : null;
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Remove excluded actions from the prompt: drop their per-action
|
|
435
|
+
* documentation lines (entries render as single "- name: ..." lines — the
|
|
436
|
+
* drift-guard test enforces the format), then drop any remaining sentence
|
|
437
|
+
* that still mentions one. Guidance prose ("use move_range to relocate a
|
|
438
|
+
* section") is instruction, not a passing cross-reference: leaving it coaches
|
|
439
|
+
* the model into calls the schema forbids and dispatch rejects.
|
|
396
440
|
*/
|
|
397
441
|
function stripExcludedActionLines(prompt, excludedActions) {
|
|
398
442
|
if (excludedActions.size === 0)
|
|
399
443
|
return prompt;
|
|
400
444
|
return prompt
|
|
401
445
|
.split('\n')
|
|
402
|
-
.
|
|
446
|
+
.map((line) => {
|
|
403
447
|
const match = /^- ([a-z_]+)(?: \/ ([a-z_]+))?:/.exec(line);
|
|
404
448
|
if (!match)
|
|
405
|
-
return
|
|
449
|
+
return line;
|
|
406
450
|
const names = [match[1], match[2]].filter((n) => Boolean(n));
|
|
407
|
-
|
|
408
|
-
//
|
|
409
|
-
|
|
451
|
+
const callable = names.filter((name) => !excludedActions.has(name));
|
|
452
|
+
// Drop the line only when EVERY action it documents is excluded; a
|
|
453
|
+
// paired accept/reject line survives if one side remains callable, but
|
|
454
|
+
// its header keeps only the callable name.
|
|
455
|
+
if (callable.length === 0)
|
|
456
|
+
return null;
|
|
457
|
+
if (callable.length === names.length)
|
|
458
|
+
return line;
|
|
459
|
+
return `- ${callable.join(' / ')}:${line.slice(match[0].length)}`;
|
|
410
460
|
})
|
|
461
|
+
.map((line) => (line === null ? null : stripExcludedActionSentences(line, excludedActions)))
|
|
462
|
+
.filter((line) => line !== null)
|
|
411
463
|
.join('\n');
|
|
412
464
|
}
|
|
413
465
|
async function coreGetSystemPrompt(options) {
|
|
@@ -4,6 +4,7 @@ var node_fs = require('node:fs');
|
|
|
4
4
|
var node_module = require('node:module');
|
|
5
5
|
var path = require('node:path');
|
|
6
6
|
var node_url = require('node:url');
|
|
7
|
+
var sdkVersion_generated = require('./sdk-version.generated.cjs');
|
|
7
8
|
|
|
8
9
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
9
10
|
const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('runtime/embedded-platform.cjs', document.baseURI).href)));
|
|
@@ -50,31 +51,36 @@ function resolveFromPackageLocal(target, binaryName) {
|
|
|
50
51
|
* Resolve the platform package through Node, and reject a version that is not
|
|
51
52
|
* this SDK's own.
|
|
52
53
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* package to an exact version, so a mismatch here is never legitimate.
|
|
54
|
+
* Resolution starts from the installed SDK so pnpm's isolated optional
|
|
55
|
+
* dependency remains visible after the SDK itself is bundled. `require.resolve`
|
|
56
|
+
* can also fall back to NODE_PATH, so the version check prevents a host binary
|
|
57
|
+
* from an unrelated SDK version in a flat store from satisfying this lookup.
|
|
58
|
+
* optionalDependencies pin the platform package to an exact version, so a
|
|
59
|
+
* mismatch here is never legitimate.
|
|
60
60
|
*/
|
|
61
61
|
function resolveFromPlatformPackage(target, binaryName) {
|
|
62
62
|
const pkg = TARGET_TO_PACKAGE[target];
|
|
63
|
+
let sdkRequire;
|
|
64
|
+
try {
|
|
65
|
+
sdkRequire = node_module.createRequire(require$1.resolve('@superdoc/sdk'));
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
sdkRequire = require$1;
|
|
69
|
+
}
|
|
63
70
|
let binaryPath;
|
|
64
71
|
try {
|
|
65
|
-
binaryPath =
|
|
72
|
+
binaryPath = sdkRequire.resolve(`${pkg}/bin/${binaryName}`);
|
|
66
73
|
}
|
|
67
74
|
catch {
|
|
68
75
|
return null;
|
|
69
76
|
}
|
|
70
77
|
try {
|
|
71
|
-
const platformVersion =
|
|
72
|
-
|
|
73
|
-
if (platformVersion !== ownVersion)
|
|
78
|
+
const platformVersion = sdkRequire(sdkRequire.resolve(`${pkg}/package.json`)).version;
|
|
79
|
+
if (platformVersion !== sdkVersion_generated.SDK_VERSION)
|
|
74
80
|
return null;
|
|
75
81
|
}
|
|
76
82
|
catch {
|
|
77
|
-
//
|
|
83
|
+
// An unreadable platform manifest is itself disqualifying: an unverifiable
|
|
78
84
|
// host is exactly the case this guard exists to reject.
|
|
79
85
|
return null;
|
|
80
86
|
}
|
|
@@ -2,6 +2,7 @@ import { chmodSync, existsSync } from 'node:fs';
|
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { SDK_VERSION } from './sdk-version.generated.js';
|
|
5
6
|
const require = createRequire(import.meta.url);
|
|
6
7
|
const TARGET_TO_PACKAGE = {
|
|
7
8
|
'darwin-arm64': '@superdoc/sdk-darwin-arm64',
|
|
@@ -46,31 +47,36 @@ function resolveFromPackageLocal(target, binaryName) {
|
|
|
46
47
|
* Resolve the platform package through Node, and reject a version that is not
|
|
47
48
|
* this SDK's own.
|
|
48
49
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* package to an exact version, so a mismatch here is never legitimate.
|
|
50
|
+
* Resolution starts from the installed SDK so pnpm's isolated optional
|
|
51
|
+
* dependency remains visible after the SDK itself is bundled. `require.resolve`
|
|
52
|
+
* can also fall back to NODE_PATH, so the version check prevents a host binary
|
|
53
|
+
* from an unrelated SDK version in a flat store from satisfying this lookup.
|
|
54
|
+
* optionalDependencies pin the platform package to an exact version, so a
|
|
55
|
+
* mismatch here is never legitimate.
|
|
56
56
|
*/
|
|
57
57
|
function resolveFromPlatformPackage(target, binaryName) {
|
|
58
58
|
const pkg = TARGET_TO_PACKAGE[target];
|
|
59
|
+
let sdkRequire;
|
|
60
|
+
try {
|
|
61
|
+
sdkRequire = createRequire(require.resolve('@superdoc/sdk'));
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
sdkRequire = require;
|
|
65
|
+
}
|
|
59
66
|
let binaryPath;
|
|
60
67
|
try {
|
|
61
|
-
binaryPath =
|
|
68
|
+
binaryPath = sdkRequire.resolve(`${pkg}/bin/${binaryName}`);
|
|
62
69
|
}
|
|
63
70
|
catch {
|
|
64
71
|
return null;
|
|
65
72
|
}
|
|
66
73
|
try {
|
|
67
|
-
const platformVersion =
|
|
68
|
-
|
|
69
|
-
if (platformVersion !== ownVersion)
|
|
74
|
+
const platformVersion = sdkRequire(sdkRequire.resolve(`${pkg}/package.json`)).version;
|
|
75
|
+
if (platformVersion !== SDK_VERSION)
|
|
70
76
|
return null;
|
|
71
77
|
}
|
|
72
78
|
catch {
|
|
73
|
-
//
|
|
79
|
+
// An unreadable platform manifest is itself disqualifying: an unverifiable
|
|
74
80
|
// host is exactly the case this guard exists to reject.
|
|
75
81
|
return null;
|
|
76
82
|
}
|