@qvac/harness 0.7.0 → 1.0.0-rc.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/CHANGELOG.md +42 -1
- package/README.md +239 -2
- package/dist-lib/index.d.ts +58 -3
- package/dist-lib/index.js +736 -239
- package/dist-lib/lib/capabilities/completion-engine/abort-polyfill.d.ts +1 -0
- package/dist-lib/lib/capabilities/completion-engine/abort-polyfill.js +10 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/answering.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/answering.js +17 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/approval.d.ts +4 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/approval.js +29 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/direct-search.d.ts +4 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/direct-search.js +73 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/execute.d.ts +41 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/execute.js +49 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/executing.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/executing.js +102 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/execution-plan.d.ts +47 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/execution-plan.js +87 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/finishing.d.ts +2 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/finishing.js +32 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/inspect-preload.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/inspect-preload.js +75 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/inspecting.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/inspecting.js +152 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/loading-skill.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/loading-skill.js +94 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preload-failure.d.ts +9 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preload-failure.js +11 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preloading.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preloading.js +114 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preparing.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preparing.js +198 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/rejecting.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/rejecting.js +71 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/rejection.d.ts +18 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/rejection.js +70 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/resolving.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/resolving.js +60 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/stream.d.ts +21 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/stream.js +48 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/streaming.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/streaming.js +156 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/wrap-up.d.ts +7 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/wrap-up.js +61 -0
- package/dist-lib/lib/capabilities/completion-engine/driver.d.ts +25 -0
- package/dist-lib/lib/capabilities/completion-engine/driver.js +553 -0
- package/dist-lib/lib/capabilities/completion-engine/durable.d.ts +61 -0
- package/dist-lib/lib/capabilities/completion-engine/durable.js +150 -0
- package/dist-lib/lib/capabilities/completion-engine/operations.d.ts +6 -0
- package/dist-lib/lib/capabilities/completion-engine/operations.js +239 -0
- package/dist-lib/lib/capabilities/completion-engine/ports.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/ports.js +267 -0
- package/dist-lib/lib/capabilities/completion-engine/session.d.ts +76 -0
- package/dist-lib/lib/capabilities/completion-engine/session.js +70 -0
- package/dist-lib/lib/capabilities/completion-loop/index.d.ts +80 -0
- package/dist-lib/lib/capabilities/completion-loop/index.js +158 -0
- package/dist-lib/lib/capabilities/completion-loop/metrics.d.ts +5 -0
- package/dist-lib/lib/capabilities/completion-loop/metrics.js +29 -0
- package/dist-lib/lib/capabilities/completion-loop/round.d.ts +33 -0
- package/dist-lib/lib/capabilities/completion-loop/round.js +353 -0
- package/dist-lib/lib/capabilities/completion-loop/tool-execution.d.ts +60 -0
- package/dist-lib/lib/capabilities/completion-loop/tool-execution.js +270 -0
- package/dist-lib/lib/capabilities/completion-loop/turns.d.ts +23 -0
- package/dist-lib/lib/capabilities/completion-loop/turns.js +112 -0
- package/dist-lib/lib/capabilities/completion-runtime.d.ts +46 -0
- package/dist-lib/lib/capabilities/completion-runtime.js +74 -0
- package/dist-lib/lib/capabilities/completion.d.ts +18 -335
- package/dist-lib/lib/capabilities/completion.js +20 -1301
- package/dist-lib/lib/capabilities/download.d.ts +1 -1
- package/dist-lib/lib/capabilities/download.js +7 -2
- package/dist-lib/lib/capabilities/invoke.js +5 -3
- package/dist-lib/lib/capabilities/tool-plan.d.ts +35 -0
- package/dist-lib/lib/capabilities/tool-plan.js +66 -0
- package/dist-lib/lib/capabilities/tool-turns.d.ts +11 -2
- package/dist-lib/lib/capabilities/tool-turns.js +30 -2
- package/dist-lib/lib/capabilities/types.d.ts +287 -0
- package/dist-lib/lib/capabilities/types.js +1 -0
- package/dist-lib/lib/completion-lifecycle.d.ts +14 -0
- package/dist-lib/lib/completion-lifecycle.js +126 -0
- package/dist-lib/lib/connect.d.ts +10 -3
- package/dist-lib/lib/connect.js +329 -23
- package/dist-lib/lib/contract-types.d.ts +19 -2
- package/dist-lib/lib/harness-lifecycle.d.ts +66 -0
- package/dist-lib/lib/harness-lifecycle.js +129 -0
- package/dist-lib/lib/helpers/detach-json.d.ts +1 -0
- package/dist-lib/lib/helpers/detach-json.js +146 -0
- package/dist-lib/lib/helpers/markup-scanner.d.ts +26 -0
- package/dist-lib/lib/helpers/markup-scanner.js +156 -0
- package/dist-lib/lib/helpers/markup-stream-filter.js +138 -35
- package/dist-lib/lib/helpers/race-abort.d.ts +9 -4
- package/dist-lib/lib/helpers/race-abort.js +2 -7
- package/dist-lib/lib/helpers/recovery-required.d.ts +1 -0
- package/dist-lib/lib/helpers/recovery-required.js +1 -0
- package/dist-lib/lib/helpers/run-outcome.d.ts +10 -2
- package/dist-lib/lib/helpers/run-outcome.js +8 -5
- package/dist-lib/lib/helpers/tool-call-markup.d.ts +2 -0
- package/dist-lib/lib/helpers/tool-call-markup.js +197 -82
- package/dist-lib/lib/hooks/built-in/arg-repair.d.ts +1 -0
- package/dist-lib/lib/hooks/built-in/arg-repair.js +1 -0
- package/dist-lib/lib/hooks/built-in/egress.d.ts +1 -0
- package/dist-lib/lib/hooks/built-in/egress.js +2 -1
- package/dist-lib/lib/hooks/built-in/sandbox.d.ts +1 -0
- package/dist-lib/lib/hooks/built-in/sandbox.js +6 -1
- package/dist-lib/lib/hooks/built-in/skill-catalog.d.ts +1 -0
- package/dist-lib/lib/hooks/built-in/skill-catalog.js +2 -1
- package/dist-lib/lib/hooks/pipeline.d.ts +4 -1
- package/dist-lib/lib/hooks/pipeline.js +24 -2
- package/dist-lib/lib/hooks/run.d.ts +2 -1
- package/dist-lib/lib/hooks/run.js +19 -7
- package/dist-lib/lib/hooks/types.d.ts +17 -6
- package/dist-lib/lib/machine/completion/actions/approval.d.ts +3 -0
- package/dist-lib/lib/machine/completion/actions/approval.js +16 -0
- package/dist-lib/lib/machine/completion/actions/completion.d.ts +23 -0
- package/dist-lib/lib/machine/completion/actions/completion.js +142 -0
- package/dist-lib/lib/machine/completion/actions/skills.d.ts +9 -0
- package/dist-lib/lib/machine/completion/actions/skills.js +83 -0
- package/dist-lib/lib/machine/completion/actions/tools.d.ts +16 -0
- package/dist-lib/lib/machine/completion/actions/tools.js +173 -0
- package/dist-lib/lib/machine/completion/context.d.ts +9 -0
- package/dist-lib/lib/machine/completion/context.js +44 -0
- package/dist-lib/lib/machine/completion/contract.d.ts +6 -0
- package/dist-lib/lib/machine/completion/contract.js +1 -0
- package/dist-lib/lib/machine/completion/guards/retry.d.ts +9 -0
- package/dist-lib/lib/machine/completion/guards/retry.js +25 -0
- package/dist-lib/lib/machine/completion/implementations.d.ts +81 -0
- package/dist-lib/lib/machine/completion/implementations.js +152 -0
- package/dist-lib/lib/machine/completion/machine.d.ts +375 -0
- package/dist-lib/lib/machine/completion/machine.js +511 -0
- package/dist-lib/lib/machine/completion/ports.d.ts +65 -0
- package/dist-lib/lib/machine/completion/ports.js +224 -0
- package/dist-lib/lib/machine/completion/rules.d.ts +39 -0
- package/dist-lib/lib/machine/completion/rules.js +115 -0
- package/dist-lib/lib/machine/completion/types.d.ts +493 -0
- package/dist-lib/lib/machine/completion/types.js +1 -0
- package/dist-lib/lib/machine/engine.d.ts +93 -0
- package/dist-lib/lib/machine/engine.js +483 -0
- package/dist-lib/lib/machine/errors.d.ts +44 -0
- package/dist-lib/lib/machine/errors.js +373 -0
- package/dist-lib/lib/machine/guards.d.ts +2 -0
- package/dist-lib/lib/machine/guards.js +6 -0
- package/dist-lib/lib/machine/index.d.ts +20 -0
- package/dist-lib/lib/machine/index.js +11 -0
- package/dist-lib/lib/machine/replay-output.d.ts +24 -0
- package/dist-lib/lib/machine/replay-output.js +50 -0
- package/dist-lib/lib/machine/stable-stringify.d.ts +1 -0
- package/dist-lib/lib/machine/stable-stringify.js +11 -0
- package/dist-lib/lib/models/model-handle.d.ts +5 -1
- package/dist-lib/lib/models/model-handle.js +8 -3
- package/dist-lib/lib/models/model-list.d.ts +5 -3
- package/dist-lib/lib/models/model-pool.d.ts +18 -7
- package/dist-lib/lib/models/model-pool.js +126 -38
- package/dist-lib/lib/run-log/history-codec.d.ts +23 -0
- package/dist-lib/lib/run-log/history-codec.js +973 -0
- package/dist-lib/lib/run-log/patch.d.ts +6 -0
- package/dist-lib/lib/run-log/patch.js +93 -0
- package/dist-lib/lib/run-log/persisted-actor.d.ts +18 -0
- package/dist-lib/lib/run-log/persisted-actor.js +218 -0
- package/dist-lib/lib/run-log/protocol-types.d.ts +153 -0
- package/dist-lib/lib/run-log/protocol-types.js +1 -0
- package/dist-lib/lib/run-log/protocol.d.ts +27 -0
- package/dist-lib/lib/run-log/protocol.js +1056 -0
- package/dist-lib/lib/run-log/replay.d.ts +25 -0
- package/dist-lib/lib/run-log/replay.js +129 -0
- package/dist-lib/lib/run-log/run-journal.d.ts +125 -0
- package/dist-lib/lib/run-log/run-journal.js +783 -0
- package/dist-lib/lib/run-log-inspect.d.ts +25 -0
- package/dist-lib/lib/run-log-inspect.js +627 -0
- package/dist-lib/lib/run-log-protocol.d.ts +2 -0
- package/dist-lib/lib/run-log-protocol.js +1 -0
- package/dist-lib/lib/run-log-redact.d.ts +27 -0
- package/dist-lib/lib/run-log-redact.js +1107 -0
- package/dist-lib/lib/serve.js +308 -12
- package/dist-lib/lib/spawn.js +3 -2
- package/dist-lib/lib/tool-call-display.d.ts +1 -21
- package/dist-lib/lib/tools/exec.d.ts +2 -1
- package/dist-lib/lib/tools/exec.js +57 -2
- package/dist-lib/lib/tools/generate-image.js +1 -1
- package/dist-lib/lib/tools/generate-music.js +1 -1
- package/dist-lib/lib/tools/http-request.d.ts +2 -1
- package/dist-lib/lib/tools/http-request.js +2 -1
- package/dist-lib/lib/tools/mcp-call.js +8 -1
- package/dist-lib/lib/tools/operations/builders.d.ts +1 -0
- package/dist-lib/lib/tools/operations/builders.js +1 -0
- package/dist-lib/lib/tools/operations/compile.js +11 -1
- package/dist-lib/lib/tools/operations/manifest.js +1 -0
- package/dist-lib/lib/tools/outbound-guard.d.ts +8 -6
- package/dist-lib/lib/tools/outbound-guard.js +25 -8
- package/dist-lib/lib/tools/skills/catalog.d.ts +1 -0
- package/dist-lib/lib/tools/skills/catalog.js +35 -0
- package/dist-lib/lib/tools/skills/cli-schema-types.d.ts +1 -0
- package/dist-lib/lib/tools/skills/cli-schema.js +25 -0
- package/dist-lib/lib/wire.d.ts +5 -0
- package/dist-lib/lib/wire.js +128 -5
- package/dist-lib/schema/harness.js +22 -6
- package/dist-lib/spec/hrpc/messages.js +100 -18
- package/dist-lib/spec/hyperschema/index.js +100 -18
- package/dist-lib/spec/hyperschema/schema.json +74 -1
- package/dist-lib/spec/hyperschema/types.d.ts +11 -3
- package/package.json +19 -1
- package/patches/@qvac%2Finference@0.20.0.patch +67 -0
- package/patches/bare-stow@0.1.5.patch +68 -0
- package/patches/hypercore-blob-server@1.15.0.patch +15 -0
- package/patches/localwatch@1.4.3.patch +13 -0
- package/patches/pyodide@314.0.2.patch +144 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { assign, createActor, fromPromise, setup, waitFor } from 'xstate';
|
|
2
|
+
import { errorMessage, isRecord } from './guards.js';
|
|
3
|
+
import { hlog } from './log.js';
|
|
4
|
+
function errorFromEvent(event) {
|
|
5
|
+
return isRecord(event) ? event.error : undefined;
|
|
6
|
+
}
|
|
7
|
+
function requestFromEvent(event) {
|
|
8
|
+
return event.type === 'SUSPEND' || event.type === 'RESUME' || event.type === 'WAKEUP'
|
|
9
|
+
? event.type
|
|
10
|
+
: null;
|
|
11
|
+
}
|
|
12
|
+
export const harnessLifecycle = setup({
|
|
13
|
+
types: {},
|
|
14
|
+
actors: {
|
|
15
|
+
suspend: fromPromise(async () => { }),
|
|
16
|
+
resume: fromPromise(async () => { })
|
|
17
|
+
},
|
|
18
|
+
actions: {
|
|
19
|
+
hold: assign(({ event }) => ({ pending: requestFromEvent(event) })),
|
|
20
|
+
clear: assign({ pending: null }),
|
|
21
|
+
report: ({ event }) => {
|
|
22
|
+
hlog('lifecycle step failed', { err: errorMessage(errorFromEvent(event)) });
|
|
23
|
+
},
|
|
24
|
+
recordError: assign(({ context, event }) => {
|
|
25
|
+
const message = errorMessage(errorFromEvent(event));
|
|
26
|
+
return {
|
|
27
|
+
failureCount: context.failureCount + 1,
|
|
28
|
+
failureMessage: message
|
|
29
|
+
};
|
|
30
|
+
})
|
|
31
|
+
},
|
|
32
|
+
guards: {
|
|
33
|
+
resumeHeld: ({ context }) => context.pending === 'RESUME',
|
|
34
|
+
wakeupHeld: ({ context }) => context.pending === 'WAKEUP',
|
|
35
|
+
suspendHeld: ({ context }) => context.pending === 'SUSPEND'
|
|
36
|
+
}
|
|
37
|
+
}).createMachine({
|
|
38
|
+
id: 'harness',
|
|
39
|
+
context: { pending: null, failureCount: 0, failureMessage: null },
|
|
40
|
+
initial: 'running',
|
|
41
|
+
states: {
|
|
42
|
+
running: {
|
|
43
|
+
always: { guard: 'suspendHeld', target: 'suspending', actions: 'clear' },
|
|
44
|
+
on: { PRESUSPEND: 'presuspended', SUSPEND: 'suspending' }
|
|
45
|
+
},
|
|
46
|
+
presuspended: {
|
|
47
|
+
on: { RESUME: 'running', WAKEUP: 'running', SUSPEND: 'suspending' }
|
|
48
|
+
},
|
|
49
|
+
suspending: {
|
|
50
|
+
tags: ['busy', 'suspended'],
|
|
51
|
+
invoke: {
|
|
52
|
+
src: 'suspend',
|
|
53
|
+
onDone: 'suspended',
|
|
54
|
+
onError: { target: 'suspended', actions: ['report', 'recordError'] }
|
|
55
|
+
},
|
|
56
|
+
on: {
|
|
57
|
+
RESUME: { actions: 'hold' },
|
|
58
|
+
WAKEUP: { actions: 'hold' },
|
|
59
|
+
SUSPEND: { actions: 'clear' },
|
|
60
|
+
CLOSE: { actions: 'clear' }
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
suspended: {
|
|
64
|
+
tags: ['suspended'],
|
|
65
|
+
always: [
|
|
66
|
+
{ guard: 'resumeHeld', target: 'resuming', actions: 'clear' },
|
|
67
|
+
{ guard: 'wakeupHeld', target: 'waking', actions: 'clear' }
|
|
68
|
+
],
|
|
69
|
+
on: { RESUME: 'resuming', WAKEUP: 'waking' }
|
|
70
|
+
},
|
|
71
|
+
resuming: {
|
|
72
|
+
tags: ['busy'],
|
|
73
|
+
invoke: {
|
|
74
|
+
src: 'resume',
|
|
75
|
+
onDone: 'running',
|
|
76
|
+
onError: { target: 'suspended', actions: ['report', 'recordError', 'clear'] }
|
|
77
|
+
},
|
|
78
|
+
on: {
|
|
79
|
+
SUSPEND: { actions: 'hold' },
|
|
80
|
+
RESUME: { actions: 'clear' },
|
|
81
|
+
WAKEUP: { actions: 'clear' },
|
|
82
|
+
CLOSE: { actions: 'clear' }
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
waking: {
|
|
86
|
+
tags: ['busy'],
|
|
87
|
+
invoke: {
|
|
88
|
+
src: 'resume',
|
|
89
|
+
onDone: 'running',
|
|
90
|
+
onError: { target: 'suspended', actions: ['report', 'recordError', 'clear'] }
|
|
91
|
+
},
|
|
92
|
+
on: {
|
|
93
|
+
SUSPEND: { actions: 'hold' },
|
|
94
|
+
RESUME: { actions: 'clear' },
|
|
95
|
+
WAKEUP: { actions: 'clear' },
|
|
96
|
+
CLOSE: { actions: 'clear' }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
export function createHarnessLifecycle(work) {
|
|
102
|
+
const actor = createActor(harnessLifecycle.provide({
|
|
103
|
+
actors: {
|
|
104
|
+
suspend: fromPromise(() => work.suspend()),
|
|
105
|
+
resume: fromPromise(() => work.resume())
|
|
106
|
+
}
|
|
107
|
+
})).start();
|
|
108
|
+
const settled = () => waitFor(actor, (snapshot) => !snapshot.hasTag('busy'));
|
|
109
|
+
return {
|
|
110
|
+
get suspended() {
|
|
111
|
+
return actor.getSnapshot().hasTag('suspended');
|
|
112
|
+
},
|
|
113
|
+
get state() {
|
|
114
|
+
return actor.getSnapshot().value;
|
|
115
|
+
},
|
|
116
|
+
async send(type) {
|
|
117
|
+
const failureCount = actor.getSnapshot().context.failureCount;
|
|
118
|
+
actor.send({ type });
|
|
119
|
+
await settled();
|
|
120
|
+
const { context } = actor.getSnapshot();
|
|
121
|
+
if (context.failureCount !== failureCount) {
|
|
122
|
+
throw new Error(context.failureMessage ?? 'Harness lifecycle step failed');
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
settled,
|
|
126
|
+
cancelPending: () => actor.send({ type: 'CLOSE' }),
|
|
127
|
+
stop: () => actor.stop()
|
|
128
|
+
};
|
|
129
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function detachJson<Value>(value: Value): Value;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
export function detachJson(value) {
|
|
2
|
+
const detached = detachValue(value);
|
|
3
|
+
return detached;
|
|
4
|
+
}
|
|
5
|
+
function detachValue(value) {
|
|
6
|
+
if (!isStructuralJson(value, new WeakSet())) {
|
|
7
|
+
const encoded = JSON.stringify(value);
|
|
8
|
+
if (encoded === undefined) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
return JSON.parse(encoded);
|
|
12
|
+
}
|
|
13
|
+
return cloneStructural(value, { arrayItem: false });
|
|
14
|
+
}
|
|
15
|
+
function isStructuralJson(value, ancestors) {
|
|
16
|
+
if (isJsonPrimitive(value)) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
if (typeof value !== 'object') {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (ancestors.has(value) || hasJsonHook(value)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
ancestors.add(value);
|
|
26
|
+
try {
|
|
27
|
+
if (Array.isArray(value)) {
|
|
28
|
+
return isStructuralArray(value, ancestors);
|
|
29
|
+
}
|
|
30
|
+
if (!isPlainRecord(value)) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return isStructuralRecord(value, ancestors);
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
ancestors.delete(value);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function isJsonPrimitive(value) {
|
|
40
|
+
return (value === null ||
|
|
41
|
+
value === undefined ||
|
|
42
|
+
typeof value === 'string' ||
|
|
43
|
+
typeof value === 'boolean' ||
|
|
44
|
+
typeof value === 'number');
|
|
45
|
+
}
|
|
46
|
+
function isStructuralArray(value, ancestors) {
|
|
47
|
+
if (Object.getPrototypeOf(value) !== Array.prototype) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
for (let index = 0; index < value.length; index++) {
|
|
51
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
52
|
+
if (!descriptor) {
|
|
53
|
+
if (index in value) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (!('value' in descriptor)) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (!isStructuralJson(descriptor.value, ancestors)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
function isStructuralRecord(value, ancestors) {
|
|
68
|
+
for (const key of Object.keys(value)) {
|
|
69
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
70
|
+
if (!descriptor || !('value' in descriptor)) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
if (!isStructuralJson(descriptor.value, ancestors)) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
function cloneStructural(value, position) {
|
|
80
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean') {
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
if (typeof value === 'number') {
|
|
84
|
+
if (!Number.isFinite(value)) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
return Object.is(value, -0) ? 0 : value;
|
|
88
|
+
}
|
|
89
|
+
if (value === undefined) {
|
|
90
|
+
if (position.arrayItem) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
if (Array.isArray(value)) {
|
|
96
|
+
return cloneArray(value);
|
|
97
|
+
}
|
|
98
|
+
if (!isPlainRecord(value)) {
|
|
99
|
+
throw new TypeError('Expected a plain JSON object');
|
|
100
|
+
}
|
|
101
|
+
return cloneRecord(value);
|
|
102
|
+
}
|
|
103
|
+
function cloneArray(value) {
|
|
104
|
+
const output = [];
|
|
105
|
+
for (let index = 0; index < value.length; index++) {
|
|
106
|
+
output.push(cloneStructural(value[index], { arrayItem: true }));
|
|
107
|
+
}
|
|
108
|
+
return output;
|
|
109
|
+
}
|
|
110
|
+
function cloneRecord(value) {
|
|
111
|
+
const output = {};
|
|
112
|
+
for (const key of Object.keys(value)) {
|
|
113
|
+
const child = cloneStructural(value[key], { arrayItem: false });
|
|
114
|
+
if (child !== undefined) {
|
|
115
|
+
Object.defineProperty(output, key, {
|
|
116
|
+
value: child,
|
|
117
|
+
enumerable: true,
|
|
118
|
+
configurable: true,
|
|
119
|
+
writable: true
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return output;
|
|
124
|
+
}
|
|
125
|
+
function isPlainRecord(value) {
|
|
126
|
+
if (!value || typeof value !== 'object') {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
const prototype = Object.getPrototypeOf(value);
|
|
130
|
+
return prototype === Object.prototype || prototype === null;
|
|
131
|
+
}
|
|
132
|
+
function hasJsonHook(value) {
|
|
133
|
+
const own = Object.getOwnPropertyDescriptor(value, 'toJSON');
|
|
134
|
+
if (own) {
|
|
135
|
+
return !('value' in own) || typeof own.value === 'function';
|
|
136
|
+
}
|
|
137
|
+
let prototype = Object.getPrototypeOf(value);
|
|
138
|
+
while (prototype) {
|
|
139
|
+
const inherited = Object.getOwnPropertyDescriptor(prototype, 'toJSON');
|
|
140
|
+
if (inherited) {
|
|
141
|
+
return !('value' in inherited) || typeof inherited.value === 'function';
|
|
142
|
+
}
|
|
143
|
+
prototype = Object.getPrototypeOf(prototype);
|
|
144
|
+
}
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type NamedMarkupTag = 'function' | 'parameter';
|
|
2
|
+
export declare const MAX_MARKUP_NAME_LENGTH = 64;
|
|
3
|
+
export interface NamedMarkupBlock {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly body: string;
|
|
6
|
+
readonly start: number;
|
|
7
|
+
readonly end: number;
|
|
8
|
+
readonly nested: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface NamedMarkupToken {
|
|
11
|
+
readonly kind: 'open' | 'close';
|
|
12
|
+
readonly start: number;
|
|
13
|
+
readonly end: number;
|
|
14
|
+
readonly name?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface NamedMarkupScan {
|
|
17
|
+
readonly token: NamedMarkupToken | null;
|
|
18
|
+
readonly partial: number;
|
|
19
|
+
}
|
|
20
|
+
export interface ScanNamedMarkupOptions {
|
|
21
|
+
readonly from?: number;
|
|
22
|
+
readonly maxNameLength?: number;
|
|
23
|
+
readonly haystack?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function scanNamedMarkup(text: string, tag: NamedMarkupTag, { from, maxNameLength, haystack }?: ScanNamedMarkupOptions): NamedMarkupScan;
|
|
26
|
+
export declare function namedMarkupBlocks(text: string, tag: NamedMarkupTag, maxNameLength?: number): Generator<NamedMarkupBlock>;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
const ASCII_WHITESPACE = new Set([' ', '\t', '\n', '\r', '\f']);
|
|
2
|
+
export const MAX_MARKUP_NAME_LENGTH = 64;
|
|
3
|
+
function lowerAscii(char) {
|
|
4
|
+
return char.toLowerCase();
|
|
5
|
+
}
|
|
6
|
+
function isWhitespace(char) {
|
|
7
|
+
return char !== undefined && ASCII_WHITESPACE.has(char);
|
|
8
|
+
}
|
|
9
|
+
function skipBoundedWhitespace(text, start, bound) {
|
|
10
|
+
let cursor = start;
|
|
11
|
+
while (isWhitespace(text[cursor]) && cursor - start < bound) {
|
|
12
|
+
cursor++;
|
|
13
|
+
}
|
|
14
|
+
return isWhitespace(text[cursor]) ? -1 : cursor;
|
|
15
|
+
}
|
|
16
|
+
function validNameEnd(text, start, maxLength) {
|
|
17
|
+
const limit = Math.min(text.length, start + maxLength + 1);
|
|
18
|
+
for (let index = start; index < limit; index++) {
|
|
19
|
+
const char = text[index];
|
|
20
|
+
if (char === '>') {
|
|
21
|
+
return index === start ? -2 : { nameEnd: index, closerAt: index };
|
|
22
|
+
}
|
|
23
|
+
if (char === '<') {
|
|
24
|
+
return -2;
|
|
25
|
+
}
|
|
26
|
+
if (isWhitespace(char)) {
|
|
27
|
+
if (index === start) {
|
|
28
|
+
return -2;
|
|
29
|
+
}
|
|
30
|
+
const closerAt = skipBoundedWhitespace(text, index, MAX_MARKUP_NAME_LENGTH);
|
|
31
|
+
if (closerAt === -1) {
|
|
32
|
+
return -2;
|
|
33
|
+
}
|
|
34
|
+
if (closerAt === text.length) {
|
|
35
|
+
return -1;
|
|
36
|
+
}
|
|
37
|
+
return text[closerAt] === '>' ? { nameEnd: index, closerAt } : -2;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return -1;
|
|
41
|
+
}
|
|
42
|
+
function partialPrefix(haystack, start, value) {
|
|
43
|
+
const available = haystack.slice(start);
|
|
44
|
+
return available.length < value.length && value.startsWith(available);
|
|
45
|
+
}
|
|
46
|
+
function parseOpen(ctx, start) {
|
|
47
|
+
const prefix = `<${ctx.tag}`;
|
|
48
|
+
if (partialPrefix(ctx.haystack, start, prefix)) {
|
|
49
|
+
return 'partial';
|
|
50
|
+
}
|
|
51
|
+
if (!ctx.haystack.startsWith(prefix, start)) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const cursor = skipBoundedWhitespace(ctx.haystack, start + prefix.length, MAX_MARKUP_NAME_LENGTH);
|
|
55
|
+
if (cursor === -1) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
if (cursor === ctx.text.length) {
|
|
59
|
+
return 'partial';
|
|
60
|
+
}
|
|
61
|
+
if (ctx.haystack[cursor] !== '=') {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
return parseName(ctx, start, cursor + 1);
|
|
65
|
+
}
|
|
66
|
+
function parseName(ctx, start, nameStart) {
|
|
67
|
+
const cursor = skipBoundedWhitespace(ctx.haystack, nameStart, MAX_MARKUP_NAME_LENGTH);
|
|
68
|
+
if (cursor === -1) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
if (cursor === ctx.text.length) {
|
|
72
|
+
return 'partial';
|
|
73
|
+
}
|
|
74
|
+
const end = validNameEnd(ctx.text, cursor, ctx.maxNameLength);
|
|
75
|
+
if (end === -2) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
if (end === -1) {
|
|
79
|
+
return ctx.text.length - cursor <= ctx.maxNameLength ? 'partial' : null;
|
|
80
|
+
}
|
|
81
|
+
return { kind: 'open', start, end: end.closerAt + 1, name: ctx.text.slice(cursor, end.nameEnd) };
|
|
82
|
+
}
|
|
83
|
+
function parseAt(ctx, start) {
|
|
84
|
+
const close = `</${ctx.tag}>`;
|
|
85
|
+
if (ctx.haystack.startsWith(close, start)) {
|
|
86
|
+
return { kind: 'close', start, end: start + close.length };
|
|
87
|
+
}
|
|
88
|
+
if (partialPrefix(ctx.haystack, start, close)) {
|
|
89
|
+
return 'partial';
|
|
90
|
+
}
|
|
91
|
+
return parseOpen(ctx, start);
|
|
92
|
+
}
|
|
93
|
+
function scanNamedMarkupIn(ctx, from = 0) {
|
|
94
|
+
let cursor = from;
|
|
95
|
+
for (;;) {
|
|
96
|
+
const start = ctx.haystack.indexOf('<', cursor);
|
|
97
|
+
if (start === -1) {
|
|
98
|
+
return { token: null, partial: -1 };
|
|
99
|
+
}
|
|
100
|
+
const parsed = parseAt(ctx, start);
|
|
101
|
+
if (parsed === 'partial') {
|
|
102
|
+
return { token: null, partial: start };
|
|
103
|
+
}
|
|
104
|
+
if (parsed) {
|
|
105
|
+
return { token: parsed, partial: -1 };
|
|
106
|
+
}
|
|
107
|
+
cursor = start + 1;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function makeContext(text, tag, { maxNameLength, haystack }) {
|
|
111
|
+
return { text, haystack: haystack ?? text.replace(/[A-Z]/g, lowerAscii), tag, maxNameLength };
|
|
112
|
+
}
|
|
113
|
+
export function scanNamedMarkup(text, tag, { from = 0, maxNameLength = MAX_MARKUP_NAME_LENGTH, haystack } = {}) {
|
|
114
|
+
return scanNamedMarkupIn(makeContext(text, tag, { maxNameLength, haystack }), from);
|
|
115
|
+
}
|
|
116
|
+
function nextBlock(ctx, from) {
|
|
117
|
+
let scan = scanNamedMarkupIn(ctx, from);
|
|
118
|
+
while (scan.token?.kind === 'close') {
|
|
119
|
+
scan = scanNamedMarkupIn(ctx, scan.token.end);
|
|
120
|
+
}
|
|
121
|
+
const open = scan.token;
|
|
122
|
+
if (!open || open.kind !== 'open') {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
let nested = false;
|
|
126
|
+
let cursor = open.end;
|
|
127
|
+
for (;;) {
|
|
128
|
+
const next = scanNamedMarkupIn(ctx, cursor).token;
|
|
129
|
+
if (!next) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
if (next.kind === 'close') {
|
|
133
|
+
return {
|
|
134
|
+
name: open.name ?? '',
|
|
135
|
+
body: ctx.text.slice(open.end, next.start),
|
|
136
|
+
start: open.start,
|
|
137
|
+
end: next.end,
|
|
138
|
+
nested
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
nested = true;
|
|
142
|
+
cursor = next.end;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
export function* namedMarkupBlocks(text, tag, maxNameLength = MAX_MARKUP_NAME_LENGTH) {
|
|
146
|
+
const ctx = makeContext(text, tag, { maxNameLength });
|
|
147
|
+
let cursor = 0;
|
|
148
|
+
for (;;) {
|
|
149
|
+
const block = nextBlock(ctx, cursor);
|
|
150
|
+
if (!block) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
yield block;
|
|
154
|
+
cursor = block.end;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -1,50 +1,122 @@
|
|
|
1
|
-
import { firstMarker } from 'asenion/guards';
|
|
2
1
|
import { holdback } from 'asenion/scan';
|
|
3
2
|
import { createJoinGuard } from './join-guard.js';
|
|
4
|
-
|
|
3
|
+
import { scanNamedMarkup } from './markup-scanner.js';
|
|
4
|
+
const MARKUP_OPENERS = ['<tool_call>', '<tool_response>'];
|
|
5
5
|
const MARKUP_CLOSERS = {
|
|
6
6
|
'<tool_call>': '</tool_call>',
|
|
7
|
-
'<function=': '</function>',
|
|
8
7
|
'<tool_response>': '</tool_response>'
|
|
9
8
|
};
|
|
10
9
|
const MARKUP_MARKERS = [...MARKUP_OPENERS, ...Object.values(MARKUP_CLOSERS)];
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
const FUNCTION_CLOSE = '</function>';
|
|
11
|
+
const JOIN_MARKERS = [...MARKUP_MARKERS, '<function', '</function>', '<FUNCTION', '</FUNCTION>'];
|
|
12
|
+
function initialState() {
|
|
13
|
+
return {
|
|
13
14
|
buffer: '',
|
|
15
|
+
lower: '',
|
|
16
|
+
markerAt: MARKUP_MARKERS.map(() => -1),
|
|
17
|
+
namedFrom: 0,
|
|
14
18
|
closer: null,
|
|
19
|
+
candidate: null,
|
|
20
|
+
candidateTail: '',
|
|
15
21
|
stripNewline: false,
|
|
16
|
-
guard: createJoinGuard(
|
|
22
|
+
guard: createJoinGuard(JOIN_MARKERS)
|
|
17
23
|
};
|
|
24
|
+
}
|
|
25
|
+
function markerHit(state) {
|
|
26
|
+
let hit = null;
|
|
27
|
+
for (let i = 0; i < MARKUP_MARKERS.length; i++) {
|
|
28
|
+
const index = state.markerAt[i];
|
|
29
|
+
if (index !== -1 && (!hit || index < hit.index)) {
|
|
30
|
+
hit = { index, marker: MARKUP_MARKERS[i] };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return hit;
|
|
34
|
+
}
|
|
35
|
+
function appendBuffer(state, token) {
|
|
36
|
+
const oldLength = state.buffer.length;
|
|
37
|
+
state.buffer += token;
|
|
38
|
+
state.lower += token.replace(/[A-Z]/g, (char) => char.toLowerCase());
|
|
39
|
+
state.markerAt = state.markerAt.map((index, i) => index === -1
|
|
40
|
+
? state.buffer.indexOf(MARKUP_MARKERS[i], Math.max(0, oldLength - MARKUP_MARKERS[i].length + 1))
|
|
41
|
+
: index);
|
|
42
|
+
}
|
|
43
|
+
function setBuffer(state, next) {
|
|
44
|
+
const removed = state.buffer.length - next.length;
|
|
45
|
+
state.lower = state.lower.slice(removed);
|
|
46
|
+
state.buffer = next;
|
|
47
|
+
state.namedFrom = Math.max(0, state.namedFrom - removed);
|
|
48
|
+
state.markerAt = state.markerAt.map((index, i) => {
|
|
49
|
+
if (index === -1)
|
|
50
|
+
return -1;
|
|
51
|
+
return index >= removed ? index - removed : next.indexOf(MARKUP_MARKERS[i]);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function drain(state) {
|
|
55
|
+
let out = '';
|
|
56
|
+
for (;;) {
|
|
57
|
+
const step = nextStep(state);
|
|
58
|
+
out += step.out;
|
|
59
|
+
if (step.done) {
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function nextStep(state) {
|
|
65
|
+
if (state.candidate) {
|
|
66
|
+
return consumeCandidate(state);
|
|
67
|
+
}
|
|
68
|
+
return state.closer ? consumeSuppressed(state) : emitUntilOpener(state);
|
|
69
|
+
}
|
|
70
|
+
export function createMarkupStreamFilter() {
|
|
71
|
+
const state = initialState();
|
|
18
72
|
return {
|
|
19
73
|
push(token) {
|
|
20
|
-
state
|
|
21
|
-
|
|
22
|
-
for (;;) {
|
|
23
|
-
const step = state.closer ? consumeSuppressed(state) : emitUntilOpener(state);
|
|
24
|
-
out += step.out;
|
|
25
|
-
if (step.done) {
|
|
26
|
-
return out;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
74
|
+
appendBuffer(state, token);
|
|
75
|
+
return drain(state);
|
|
29
76
|
},
|
|
30
77
|
flush() {
|
|
31
78
|
dropResumeNewline(state);
|
|
32
|
-
const
|
|
33
|
-
state.
|
|
34
|
-
state.
|
|
35
|
-
state
|
|
79
|
+
const candidate = state.candidate ? state.candidate.join('') : '';
|
|
80
|
+
const visible = state.closer ? '' : candidate + state.buffer;
|
|
81
|
+
const rest = state.guard.push(visible) + state.guard.flush();
|
|
82
|
+
resetPending(state);
|
|
36
83
|
return rest;
|
|
37
84
|
}
|
|
38
85
|
};
|
|
39
86
|
}
|
|
87
|
+
function resetPending(state) {
|
|
88
|
+
setBuffer(state, '');
|
|
89
|
+
state.closer = null;
|
|
90
|
+
state.candidate = null;
|
|
91
|
+
state.candidateTail = '';
|
|
92
|
+
state.stripNewline = false;
|
|
93
|
+
}
|
|
94
|
+
function consumeCandidate(state) {
|
|
95
|
+
const lower = state.candidateTail + state.lower;
|
|
96
|
+
const closeAt = lower.indexOf(FUNCTION_CLOSE);
|
|
97
|
+
if (closeAt === -1) {
|
|
98
|
+
state.candidate?.push(state.buffer);
|
|
99
|
+
state.candidateTail = lower.slice(-FUNCTION_CLOSE.length + 1);
|
|
100
|
+
setBuffer(state, '');
|
|
101
|
+
return { out: '', done: true };
|
|
102
|
+
}
|
|
103
|
+
const consumed = closeAt + FUNCTION_CLOSE.length - state.candidateTail.length;
|
|
104
|
+
setBuffer(state, state.buffer.slice(consumed));
|
|
105
|
+
state.candidate = null;
|
|
106
|
+
state.candidateTail = '';
|
|
107
|
+
state.stripNewline = true;
|
|
108
|
+
state.guard.cut();
|
|
109
|
+
return { out: '', done: false };
|
|
110
|
+
}
|
|
40
111
|
function consumeSuppressed(state) {
|
|
41
112
|
const closer = state.closer ?? '';
|
|
42
113
|
const end = state.buffer.indexOf(closer);
|
|
43
114
|
if (end === -1) {
|
|
44
|
-
|
|
115
|
+
const held = holdback(state.buffer, [closer]);
|
|
116
|
+
setBuffer(state, state.buffer.slice(state.buffer.length - held));
|
|
45
117
|
return { out: '', done: true };
|
|
46
118
|
}
|
|
47
|
-
state
|
|
119
|
+
setBuffer(state, state.buffer.slice(end + closer.length));
|
|
48
120
|
state.stripNewline = true;
|
|
49
121
|
state.closer = null;
|
|
50
122
|
return { out: '', done: false };
|
|
@@ -54,25 +126,56 @@ function dropResumeNewline(state) {
|
|
|
54
126
|
return;
|
|
55
127
|
state.stripNewline = false;
|
|
56
128
|
if (state.buffer[0] === '\n') {
|
|
57
|
-
state
|
|
129
|
+
setBuffer(state, state.buffer.slice(1));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function beginFunctionCandidate(state, start, end) {
|
|
133
|
+
const out = state.guard.push(state.buffer.slice(0, start));
|
|
134
|
+
state.candidate = [state.buffer.slice(start, end)];
|
|
135
|
+
setBuffer(state, state.buffer.slice(end));
|
|
136
|
+
state.candidateTail = '';
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
function consumeFixedMarker(state, index, marker) {
|
|
140
|
+
const out = state.guard.push(state.buffer.slice(0, index));
|
|
141
|
+
state.guard.cut();
|
|
142
|
+
setBuffer(state, state.buffer.slice(index + marker.length));
|
|
143
|
+
const closer = MARKUP_CLOSERS[marker];
|
|
144
|
+
state.stripNewline = closer === undefined;
|
|
145
|
+
state.closer = closer ?? null;
|
|
146
|
+
return { out, done: false };
|
|
147
|
+
}
|
|
148
|
+
function scanNamedOpen(buffer, haystack, start) {
|
|
149
|
+
let from = start;
|
|
150
|
+
for (;;) {
|
|
151
|
+
const scan = scanNamedMarkup(buffer, 'function', { from, haystack });
|
|
152
|
+
if (!scan.token || scan.token.kind === 'open') {
|
|
153
|
+
return scan;
|
|
154
|
+
}
|
|
155
|
+
from = scan.token.end;
|
|
58
156
|
}
|
|
59
157
|
}
|
|
60
158
|
function emitUntilOpener(state) {
|
|
61
159
|
dropResumeNewline(state);
|
|
62
|
-
const marker =
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
state.
|
|
72
|
-
|
|
160
|
+
const marker = markerHit(state);
|
|
161
|
+
const scan = scanNamedOpen(state.buffer, state.lower, state.namedFrom);
|
|
162
|
+
const namedIndex = scan.token?.start ?? scan.partial;
|
|
163
|
+
state.namedFrom = namedIndex === -1 ? state.buffer.length : namedIndex;
|
|
164
|
+
const useNamed = namedIndex !== -1 && (!marker || namedIndex < marker.index);
|
|
165
|
+
if (useNamed && scan.token) {
|
|
166
|
+
return { out: beginFunctionCandidate(state, scan.token.start, scan.token.end), done: false };
|
|
167
|
+
}
|
|
168
|
+
if (marker && !useNamed) {
|
|
169
|
+
return consumeFixedMarker(state, marker.index, marker.marker);
|
|
170
|
+
}
|
|
171
|
+
if (useNamed) {
|
|
172
|
+
const out = state.guard.push(state.buffer.slice(0, namedIndex));
|
|
173
|
+
setBuffer(state, state.buffer.slice(namedIndex));
|
|
174
|
+
return { out, done: true };
|
|
73
175
|
}
|
|
74
|
-
const
|
|
176
|
+
const functionHold = scan.partial === -1 ? 0 : state.buffer.length - scan.partial;
|
|
177
|
+
const hold = Math.max(holdback(state.buffer, MARKUP_MARKERS), functionHold);
|
|
75
178
|
const out = state.guard.push(state.buffer.slice(0, state.buffer.length - hold));
|
|
76
|
-
state
|
|
179
|
+
setBuffer(state, state.buffer.slice(state.buffer.length - hold));
|
|
77
180
|
return { out, done: true };
|
|
78
181
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
export
|
|
3
|
-
|
|
1
|
+
import { AbortedError } from '../machine/index.ts';
|
|
2
|
+
export { AbortedError };
|
|
3
|
+
export interface AbortSignalLike {
|
|
4
|
+
readonly aborted: boolean;
|
|
5
|
+
addEventListener(type: 'abort', listener: () => void, options?: {
|
|
6
|
+
once?: boolean;
|
|
7
|
+
}): void;
|
|
8
|
+
removeEventListener(type: 'abort', listener: () => void): void;
|
|
4
9
|
}
|
|
5
|
-
export declare function raceAbort<T>(promise: Promise<T>, signal?:
|
|
10
|
+
export declare function raceAbort<T>(promise: Promise<T>, signal?: AbortSignalLike): Promise<T>;
|