@12ui/design 0.2.76 → 0.2.77
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/SKILL.md +1 -1
- package/dist/cli-codex-readiness.d.ts +6 -0
- package/dist/cli-codex-readiness.d.ts.map +1 -1
- package/dist/cli-codex-readiness.js +12 -12
- package/dist/cli-codex-readiness.js.map +1 -1
- package/dist/cli-help/design.d.ts +2 -2
- package/dist/cli-help/design.d.ts.map +1 -1
- package/dist/cli-help/design.js +2 -0
- package/dist/cli-help/design.js.map +1 -1
- package/dist/cli-help/index.d.ts +2 -2
- package/dist/cli-review-command.d.ts.map +1 -1
- package/dist/cli-review-command.js +2 -0
- package/dist/cli-review-command.js.map +1 -1
- package/dist/cli-run.d.ts.map +1 -1
- package/dist/cli-run.js +6 -0
- package/dist/cli-run.js.map +1 -1
- package/dist/cli-workspace-draw.d.ts +1 -11
- package/dist/cli-workspace-draw.d.ts.map +1 -1
- package/dist/cli-workspace-draw.js +17 -18
- package/dist/cli-workspace-draw.js.map +1 -1
- package/dist/cli-workspace-runner.d.ts +30 -0
- package/dist/cli-workspace-runner.d.ts.map +1 -0
- package/dist/cli-workspace-runner.js +105 -0
- package/dist/cli-workspace-runner.js.map +1 -0
- package/dist/mcp-slate-image.js +1 -1
- package/dist/mcp-slate-image.js.map +1 -1
- package/dist/mcp-slate-tool-defs.js +1 -1
- package/dist/mcp-slate-tool-defs.js.map +1 -1
- package/dist/mcp-slate-ui-copy.d.ts +403 -33
- package/dist/mcp-slate-ui-copy.d.ts.map +1 -1
- package/dist/mcp-slate-ui-copy.js +247 -57
- package/dist/mcp-slate-ui-copy.js.map +1 -1
- package/dist/mcp-slate-ui-icu.d.ts +47 -0
- package/dist/mcp-slate-ui-icu.d.ts.map +1 -0
- package/dist/mcp-slate-ui-icu.js +229 -0
- package/dist/mcp-slate-ui-icu.js.map +1 -0
- package/dist/mcp-slate-ui-locale-match.d.ts +12 -0
- package/dist/mcp-slate-ui-locale-match.d.ts.map +1 -0
- package/dist/mcp-slate-ui-locale-match.js +34 -0
- package/dist/mcp-slate-ui-locale-match.js.map +1 -0
- package/dist/mcp-slate-ui-locales/de-DE.d.ts +9 -0
- package/dist/mcp-slate-ui-locales/de-DE.d.ts.map +1 -0
- package/dist/mcp-slate-ui-locales/de-DE.js +217 -0
- package/dist/mcp-slate-ui-locales/de-DE.js.map +1 -0
- package/dist/mcp-slate-ui-locales/es-419.d.ts +9 -0
- package/dist/mcp-slate-ui-locales/es-419.d.ts.map +1 -0
- package/dist/mcp-slate-ui-locales/es-419.js +217 -0
- package/dist/mcp-slate-ui-locales/es-419.js.map +1 -0
- package/dist/mcp-slate-ui-locales/es-ES.d.ts +9 -0
- package/dist/mcp-slate-ui-locales/es-ES.d.ts.map +1 -0
- package/dist/mcp-slate-ui-locales/es-ES.js +217 -0
- package/dist/mcp-slate-ui-locales/es-ES.js.map +1 -0
- package/dist/mcp-slate-ui-locales/fr-FR.d.ts +9 -0
- package/dist/mcp-slate-ui-locales/fr-FR.d.ts.map +1 -0
- package/dist/mcp-slate-ui-locales/fr-FR.js +217 -0
- package/dist/mcp-slate-ui-locales/fr-FR.js.map +1 -0
- package/dist/mcp-slate-ui-locales/hi-IN.d.ts +9 -0
- package/dist/mcp-slate-ui-locales/hi-IN.d.ts.map +1 -0
- package/dist/mcp-slate-ui-locales/hi-IN.js +217 -0
- package/dist/mcp-slate-ui-locales/hi-IN.js.map +1 -0
- package/dist/mcp-slate-ui-locales/index.d.ts +11 -0
- package/dist/mcp-slate-ui-locales/index.d.ts.map +1 -0
- package/dist/mcp-slate-ui-locales/index.js +34 -0
- package/dist/mcp-slate-ui-locales/index.js.map +1 -0
- package/dist/mcp-slate-ui-locales/it-IT.d.ts +9 -0
- package/dist/mcp-slate-ui-locales/it-IT.d.ts.map +1 -0
- package/dist/mcp-slate-ui-locales/it-IT.js +217 -0
- package/dist/mcp-slate-ui-locales/it-IT.js.map +1 -0
- package/dist/mcp-slate-ui-locales/ja-JP.d.ts +9 -0
- package/dist/mcp-slate-ui-locales/ja-JP.d.ts.map +1 -0
- package/dist/mcp-slate-ui-locales/ja-JP.js +217 -0
- package/dist/mcp-slate-ui-locales/ja-JP.js.map +1 -0
- package/dist/mcp-slate-ui-locales/ko-KR.d.ts +9 -0
- package/dist/mcp-slate-ui-locales/ko-KR.d.ts.map +1 -0
- package/dist/mcp-slate-ui-locales/ko-KR.js +217 -0
- package/dist/mcp-slate-ui-locales/ko-KR.js.map +1 -0
- package/dist/mcp-slate-ui-locales/pt-BR.d.ts +9 -0
- package/dist/mcp-slate-ui-locales/pt-BR.d.ts.map +1 -0
- package/dist/mcp-slate-ui-locales/pt-BR.js +217 -0
- package/dist/mcp-slate-ui-locales/pt-BR.js.map +1 -0
- package/dist/mcp-slate-ui-locales/zh-CN.d.ts +9 -0
- package/dist/mcp-slate-ui-locales/zh-CN.d.ts.map +1 -0
- package/dist/mcp-slate-ui-locales/zh-CN.js +217 -0
- package/dist/mcp-slate-ui-locales/zh-CN.js.map +1 -0
- package/dist/mcp-slate-ui-locales/zh-TW.d.ts +9 -0
- package/dist/mcp-slate-ui-locales/zh-TW.d.ts.map +1 -0
- package/dist/mcp-slate-ui-locales/zh-TW.js +217 -0
- package/dist/mcp-slate-ui-locales/zh-TW.js.map +1 -0
- package/dist/mcp-slate-ui-script-bridge.d.ts.map +1 -1
- package/dist/mcp-slate-ui-script-bridge.js +8 -9
- package/dist/mcp-slate-ui-script-bridge.js.map +1 -1
- package/dist/mcp-slate-ui-script-dialog.d.ts.map +1 -1
- package/dist/mcp-slate-ui-script-dialog.js +60 -30
- package/dist/mcp-slate-ui-script-dialog.js.map +1 -1
- package/dist/mcp-slate-ui-script-inline.d.ts +9 -6
- package/dist/mcp-slate-ui-script-inline.d.ts.map +1 -1
- package/dist/mcp-slate-ui-script-inline.js +91 -46
- package/dist/mcp-slate-ui-script-inline.js.map +1 -1
- package/dist/mcp-slate-ui-script-inspiration-collage.d.ts +20 -0
- package/dist/mcp-slate-ui-script-inspiration-collage.d.ts.map +1 -0
- package/dist/mcp-slate-ui-script-inspiration-collage.js +68 -0
- package/dist/mcp-slate-ui-script-inspiration-collage.js.map +1 -0
- package/dist/mcp-slate-ui-script-inspiration-grid.d.ts +26 -0
- package/dist/mcp-slate-ui-script-inspiration-grid.d.ts.map +1 -0
- package/dist/mcp-slate-ui-script-inspiration-grid.js +246 -0
- package/dist/mcp-slate-ui-script-inspiration-grid.js.map +1 -0
- package/dist/mcp-slate-ui-script-inspiration.d.ts +10 -9
- package/dist/mcp-slate-ui-script-inspiration.d.ts.map +1 -1
- package/dist/mcp-slate-ui-script-inspiration.js +161 -120
- package/dist/mcp-slate-ui-script-inspiration.js.map +1 -1
- package/dist/mcp-slate-ui-script-l10n.d.ts +29 -0
- package/dist/mcp-slate-ui-script-l10n.d.ts.map +1 -0
- package/dist/mcp-slate-ui-script-l10n.js +135 -0
- package/dist/mcp-slate-ui-script-l10n.js.map +1 -0
- package/dist/mcp-slate-ui-script-more.d.ts +3 -2
- package/dist/mcp-slate-ui-script-more.d.ts.map +1 -1
- package/dist/mcp-slate-ui-script-more.js +19 -18
- package/dist/mcp-slate-ui-script-more.js.map +1 -1
- package/dist/mcp-slate-ui-script-pause.d.ts +33 -0
- package/dist/mcp-slate-ui-script-pause.d.ts.map +1 -0
- package/dist/mcp-slate-ui-script-pause.js +217 -0
- package/dist/mcp-slate-ui-script-pause.js.map +1 -0
- package/dist/mcp-slate-ui-script-remote.d.ts +2 -0
- package/dist/mcp-slate-ui-script-remote.d.ts.map +1 -1
- package/dist/mcp-slate-ui-script-remote.js +39 -6
- package/dist/mcp-slate-ui-script-remote.js.map +1 -1
- package/dist/mcp-slate-ui-script-scribble.js +1 -1
- package/dist/mcp-slate-ui-script-select.js +6 -6
- package/dist/mcp-slate-ui-script-stage.d.ts +3 -2
- package/dist/mcp-slate-ui-script-stage.d.ts.map +1 -1
- package/dist/mcp-slate-ui-script-stage.js +31 -19
- package/dist/mcp-slate-ui-script-stage.js.map +1 -1
- package/dist/mcp-slate-ui-script-state.d.ts.map +1 -1
- package/dist/mcp-slate-ui-script-state.js +77 -57
- package/dist/mcp-slate-ui-script-state.js.map +1 -1
- package/dist/mcp-slate-ui-script.d.ts +2 -2
- package/dist/mcp-slate-ui-script.d.ts.map +1 -1
- package/dist/mcp-slate-ui-script.js +21 -7
- package/dist/mcp-slate-ui-script.js.map +1 -1
- package/dist/mcp-slate-ui-styles-dialog.d.ts +6 -7
- package/dist/mcp-slate-ui-styles-dialog.d.ts.map +1 -1
- package/dist/mcp-slate-ui-styles-dialog.js +13 -29
- package/dist/mcp-slate-ui-styles-dialog.js.map +1 -1
- package/dist/mcp-slate-ui-styles-inspiration.d.ts +18 -0
- package/dist/mcp-slate-ui-styles-inspiration.d.ts.map +1 -0
- package/dist/mcp-slate-ui-styles-inspiration.js +43 -0
- package/dist/mcp-slate-ui-styles-inspiration.js.map +1 -0
- package/dist/mcp-slate-ui-styles-pause.d.ts +10 -0
- package/dist/mcp-slate-ui-styles-pause.d.ts.map +1 -0
- package/dist/mcp-slate-ui-styles-pause.js +25 -0
- package/dist/mcp-slate-ui-styles-pause.js.map +1 -0
- package/dist/mcp-slate-ui-styles-stage.d.ts +10 -6
- package/dist/mcp-slate-ui-styles-stage.d.ts.map +1 -1
- package/dist/mcp-slate-ui-styles-stage.js +24 -16
- package/dist/mcp-slate-ui-styles-stage.js.map +1 -1
- package/dist/mcp-slate-ui-styles.d.ts +12 -5
- package/dist/mcp-slate-ui-styles.d.ts.map +1 -1
- package/dist/mcp-slate-ui-styles.js +38 -21
- package/dist/mcp-slate-ui-styles.js.map +1 -1
- package/dist/mcp-slate-ui.d.ts +11 -3
- package/dist/mcp-slate-ui.d.ts.map +1 -1
- package/dist/mcp-slate-ui.js +24 -16
- package/dist/mcp-slate-ui.js.map +1 -1
- package/dist/mosaic-bands.d.ts +44 -0
- package/dist/mosaic-bands.d.ts.map +1 -0
- package/dist/mosaic-bands.js +153 -0
- package/dist/mosaic-bands.js.map +1 -0
- package/dist/review-discovery.d.ts.map +1 -1
- package/dist/review-discovery.js +36 -54
- package/dist/review-discovery.js.map +1 -1
- package/dist/review-page.d.ts.map +1 -1
- package/dist/review-page.js +2 -1
- package/dist/review-page.js.map +1 -1
- package/dist/review-run-roots.d.ts +40 -0
- package/dist/review-run-roots.d.ts.map +1 -0
- package/dist/review-run-roots.js +94 -0
- package/dist/review-run-roots.js.map +1 -0
- package/dist/review-server.d.ts +2 -0
- package/dist/review-server.d.ts.map +1 -1
- package/dist/review-server.js +2 -0
- package/dist/review-server.js.map +1 -1
- package/dist/review-types.d.ts +10 -0
- package/dist/review-types.d.ts.map +1 -1
- package/dist/slate-actions.d.ts +3 -3
- package/dist/slate-actions.d.ts.map +1 -1
- package/dist/slate-actions.js +9 -8
- package/dist/slate-actions.js.map +1 -1
- package/dist/slate-browser-host-script.d.ts +4 -0
- package/dist/slate-browser-host-script.d.ts.map +1 -1
- package/dist/slate-browser-host-script.js +25 -6
- package/dist/slate-browser-host-script.js.map +1 -1
- package/dist/slate-browser-host.d.ts +2 -1
- package/dist/slate-browser-host.d.ts.map +1 -1
- package/dist/slate-browser-host.js +18 -5
- package/dist/slate-browser-host.js.map +1 -1
- package/dist/slate-commit.js +7 -7
- package/dist/slate-commit.js.map +1 -1
- package/dist/slate-corpus.d.ts.map +1 -1
- package/dist/slate-corpus.js +3 -2
- package/dist/slate-corpus.js.map +1 -1
- package/dist/slate-edit-runner.d.ts.map +1 -1
- package/dist/slate-edit-runner.js +5 -4
- package/dist/slate-edit-runner.js.map +1 -1
- package/dist/slate-editability.d.ts +2 -0
- package/dist/slate-editability.d.ts.map +1 -1
- package/dist/slate-editability.js +1 -1
- package/dist/slate-editability.js.map +1 -1
- package/dist/slate-errors.d.ts +7 -1
- package/dist/slate-errors.d.ts.map +1 -1
- package/dist/slate-errors.js +3 -2
- package/dist/slate-errors.js.map +1 -1
- package/dist/slate-handoff-options.d.ts +2 -1
- package/dist/slate-handoff-options.d.ts.map +1 -1
- package/dist/slate-handoff-options.js +2 -2
- package/dist/slate-handoff-options.js.map +1 -1
- package/dist/slate-handoff.js +1 -1
- package/dist/slate-handoff.js.map +1 -1
- package/dist/slate-image-executor.d.ts +18 -1
- package/dist/slate-image-executor.d.ts.map +1 -1
- package/dist/slate-image-executor.js +1 -0
- package/dist/slate-image-executor.js.map +1 -1
- package/dist/slate-inspiration.js +2 -2
- package/dist/slate-inspiration.js.map +1 -1
- package/dist/slate-local-image.d.ts.map +1 -1
- package/dist/slate-local-image.js +4 -1
- package/dist/slate-local-image.js.map +1 -1
- package/dist/slate-lock.js +1 -1
- package/dist/slate-lock.js.map +1 -1
- package/dist/slate-resume.js +6 -6
- package/dist/slate-resume.js.map +1 -1
- package/dist/slate-round-params.d.ts +3 -0
- package/dist/slate-round-params.d.ts.map +1 -1
- package/dist/slate-round-params.js +5 -0
- package/dist/slate-round-params.js.map +1 -1
- package/dist/slate-round-queries.d.ts +18 -0
- package/dist/slate-round-queries.d.ts.map +1 -0
- package/dist/slate-round-queries.js +29 -0
- package/dist/slate-round-queries.js.map +1 -0
- package/dist/slate-round-runner.d.ts.map +1 -1
- package/dist/slate-round-runner.js +12 -9
- package/dist/slate-round-runner.js.map +1 -1
- package/dist/slate-round-search.js +5 -5
- package/dist/slate-round-search.js.map +1 -1
- package/dist/slate-run-action.d.ts.map +1 -1
- package/dist/slate-run-action.js +2 -1
- package/dist/slate-run-action.js.map +1 -1
- package/dist/slate-runner-context.d.ts +3 -1
- package/dist/slate-runner-context.d.ts.map +1 -1
- package/dist/slate-runner-context.js +4 -3
- package/dist/slate-runner-context.js.map +1 -1
- package/dist/slate-runner-failure.d.ts +7 -1
- package/dist/slate-runner-failure.d.ts.map +1 -1
- package/dist/slate-runner-failure.js +6 -5
- package/dist/slate-runner-failure.js.map +1 -1
- package/dist/slate-runtime.d.ts.map +1 -1
- package/dist/slate-runtime.js +1 -0
- package/dist/slate-runtime.js.map +1 -1
- package/dist/slate-versions.js +3 -3
- package/dist/slate-versions.js.map +1 -1
- package/dist/slate-view-contract.d.ts +62 -1
- package/dist/slate-view-contract.d.ts.map +1 -1
- package/dist/slate-view-contract.js +30 -0
- package/dist/slate-view-contract.js.map +1 -1
- package/dist/slate-view.d.ts.map +1 -1
- package/dist/slate-view.js +19 -3
- package/dist/slate-view.js.map +1 -1
- package/dist/slate-workspace-parse.d.ts.map +1 -1
- package/dist/slate-workspace-parse.js +22 -0
- package/dist/slate-workspace-parse.js.map +1 -1
- package/dist/slate-workspace-types.d.ts +2 -0
- package/dist/slate-workspace-types.d.ts.map +1 -1
- package/dist/workspace-draw-client.d.ts +42 -1
- package/dist/workspace-draw-client.d.ts.map +1 -1
- package/dist/workspace-draw-client.js +56 -7
- package/dist/workspace-draw-client.js.map +1 -1
- package/dist/workspace-draw-codex.d.ts +9 -4
- package/dist/workspace-draw-codex.d.ts.map +1 -1
- package/dist/workspace-draw-codex.js +17 -3
- package/dist/workspace-draw-codex.js.map +1 -1
- package/dist/workspace-draw-messages.d.ts +24 -0
- package/dist/workspace-draw-messages.d.ts.map +1 -1
- package/dist/workspace-draw-messages.js +25 -0
- package/dist/workspace-draw-messages.js.map +1 -1
- package/dist/workspace-draw-run.d.ts +19 -1
- package/dist/workspace-draw-run.d.ts.map +1 -1
- package/dist/workspace-draw-run.js +76 -3
- package/dist/workspace-draw-run.js.map +1 -1
- package/dist/workspace-draw-store.d.ts +2 -0
- package/dist/workspace-draw-store.d.ts.map +1 -1
- package/dist/workspace-draw-store.js +3 -1
- package/dist/workspace-draw-store.js.map +1 -1
- package/dist/workspace-draw-types.d.ts +1 -0
- package/dist/workspace-draw-types.d.ts.map +1 -1
- package/dist/workspace-draw-types.js +1 -0
- package/dist/workspace-draw-types.js.map +1 -1
- package/dist/workspace-origin.d.ts +15 -0
- package/dist/workspace-origin.d.ts.map +1 -0
- package/dist/workspace-origin.js +36 -0
- package/dist/workspace-origin.js.map +1 -0
- package/dist/workspace-runner-children.d.ts +28 -0
- package/dist/workspace-runner-children.d.ts.map +1 -0
- package/dist/workspace-runner-children.js +112 -0
- package/dist/workspace-runner-children.js.map +1 -0
- package/dist/workspace-runner-client.d.ts +41 -0
- package/dist/workspace-runner-client.d.ts.map +1 -0
- package/dist/workspace-runner-client.js +63 -0
- package/dist/workspace-runner-client.js.map +1 -0
- package/dist/workspace-runner-main.d.ts +56 -0
- package/dist/workspace-runner-main.d.ts.map +1 -0
- package/dist/workspace-runner-main.js +350 -0
- package/dist/workspace-runner-main.js.map +1 -0
- package/dist/workspace-runner-policy.d.ts +40 -0
- package/dist/workspace-runner-policy.d.ts.map +1 -0
- package/dist/workspace-runner-policy.js +47 -0
- package/dist/workspace-runner-policy.js.map +1 -0
- package/dist/workspace-runner-spawn.d.ts +42 -0
- package/dist/workspace-runner-spawn.d.ts.map +1 -0
- package/dist/workspace-runner-spawn.js +60 -0
- package/dist/workspace-runner-spawn.js.map +1 -0
- package/dist/workspace-runner-stop.d.ts +25 -0
- package/dist/workspace-runner-stop.d.ts.map +1 -0
- package/dist/workspace-runner-stop.js +44 -0
- package/dist/workspace-runner-stop.js.map +1 -0
- package/dist/workspace-runner-store.d.ts +26 -0
- package/dist/workspace-runner-store.d.ts.map +1 -0
- package/dist/workspace-runner-store.js +114 -0
- package/dist/workspace-runner-store.js.map +1 -0
- package/open-design.json +2 -2
- package/package.json +1 -1
- package/runtime/codex-conversion/src/images/native-invoke.mjs +24 -5
- package/runtime/codex-conversion/src/images/native.mjs +3 -2
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { CLI_HEADER, DrawHttpError, DrawTransportError, errorCodeOf, PUSH_HEADER, readBody, retryAfterOf, } from './workspace-draw-client.js';
|
|
2
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;
|
|
4
|
+
/** The heartbeat answer checked before the runner acts on it: an answer this CLI cannot read is never guessed at. */
|
|
5
|
+
export const validateHeartbeat = (value) => {
|
|
6
|
+
const fail = (what) => { throw new DrawTransportError('malformed', `The heartbeat answer is not one this command can read: ${what}.`); };
|
|
7
|
+
if (!isRecord(value) || value.ok !== true)
|
|
8
|
+
return fail('not ok');
|
|
9
|
+
if (typeof value.workspace !== 'string' || typeof value.rev !== 'number')
|
|
10
|
+
return fail('no workspace');
|
|
11
|
+
if (!Array.isArray(value.ops))
|
|
12
|
+
return fail('no ops');
|
|
13
|
+
const ops = [];
|
|
14
|
+
for (const op of value.ops) {
|
|
15
|
+
if (!isRecord(op) || typeof op.opId !== 'string' || !UUID.test(op.opId))
|
|
16
|
+
return fail('an op has no id');
|
|
17
|
+
if (op.kind !== 'round' && op.kind !== 'edit')
|
|
18
|
+
return fail(`op ${op.opId} has kind ${JSON.stringify(op.kind)}`);
|
|
19
|
+
if (op.drawer !== null && typeof op.drawer !== 'string')
|
|
20
|
+
return fail(`op ${op.opId} has a drawer that is not an id`);
|
|
21
|
+
ops.push({ opId: op.opId, kind: op.kind, drawer: op.drawer });
|
|
22
|
+
}
|
|
23
|
+
const runner = value.runner;
|
|
24
|
+
if (runner !== null && (!isRecord(runner) || typeof runner.runnerId !== 'string' || typeof runner.leaseUntilMs !== 'number'))
|
|
25
|
+
return fail('a runner that is not a lease');
|
|
26
|
+
return {
|
|
27
|
+
workspace: value.workspace,
|
|
28
|
+
rev: value.rev,
|
|
29
|
+
runner: runner === null ? null : { runnerId: runner.runnerId, leaseUntilMs: runner.leaseUntilMs },
|
|
30
|
+
ops,
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export const createRunnerClient = (args) => {
|
|
34
|
+
const fetcher = args.fetch ?? ((url, init) => fetch(url, init));
|
|
35
|
+
const post = async (pathname, body) => {
|
|
36
|
+
const url = `${args.origin}${pathname}`;
|
|
37
|
+
let response;
|
|
38
|
+
try {
|
|
39
|
+
response = await fetcher(url, {
|
|
40
|
+
method: 'POST',
|
|
41
|
+
headers: { [PUSH_HEADER]: await args.token(), [CLI_HEADER]: args.cliVersion, 'content-type': 'application/json' },
|
|
42
|
+
body: JSON.stringify(body),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
catch (cause) {
|
|
46
|
+
throw new DrawTransportError('unreachable', `${new URL(url).host} could not be reached`, { cause });
|
|
47
|
+
}
|
|
48
|
+
const parsed = await readBody(response);
|
|
49
|
+
if (!response.ok)
|
|
50
|
+
throw new DrawHttpError(response.status, errorCodeOf(parsed) ?? `http_${response.status}`, retryAfterOf(response, parsed), parsed);
|
|
51
|
+
return parsed;
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
heartbeat: async (body) => (validateHeartbeat(await post('/api/v1/slate/runner', { ...body, cliVersion: args.cliVersion }))),
|
|
55
|
+
claim: async (opId, runnerId) => {
|
|
56
|
+
const answer = await post(`/api/v1/slate/ops/${encodeURIComponent(opId)}/claim`, { runnerId });
|
|
57
|
+
if (!isRecord(answer) || answer.ok !== true || answer.op !== opId)
|
|
58
|
+
throw new DrawTransportError('malformed', `The claim of ${opId} answered something else`);
|
|
59
|
+
return { replayed: answer.replayed === true };
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=workspace-runner-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-runner-client.js","sourceRoot":"","sources":["../src/workspace-runner-client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,WAAW,EACX,QAAQ,EACR,YAAY,GAEb,MAAM,4BAA4B,CAAC;AAkBpC,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAE5I,MAAM,IAAI,GAAG,wEAAwE,CAAC;AAEtF,qHAAqH;AACrH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAc,EAAmB,EAAE;IACnE,MAAM,IAAI,GAAG,CAAC,IAAY,EAAS,EAAE,GAAG,MAAM,IAAI,kBAAkB,CAAC,WAAW,EAAE,0DAA0D,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxJ,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjE,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC;IACtG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrD,MAAM,GAAG,GAAqB,EAAE,CAAC;IACjC,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,GAAgB,EAAE,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACxG,IAAI,EAAE,CAAC,IAAI,KAAK,OAAO,IAAI,EAAE,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,aAAa,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChH,IAAI,EAAE,CAAC,MAAM,KAAK,IAAI,IAAI,OAAO,EAAE,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,iCAAiC,CAAC,CAAC;QACrH,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,MAAuB,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC1K,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAkB,EAAE,YAAY,EAAE,MAAM,CAAC,YAAsB,EAAE;QACrH,GAAG;KACJ,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,IAMlC,EAAE,EAAE;IACH,MAAM,OAAO,GAAc,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAE3E,MAAM,IAAI,GAAG,KAAK,EAAE,QAAgB,EAAE,IAAa,EAAoB,EAAE;QACvE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;QACxC,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;gBAC5B,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBACjH,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,kBAAkB,CAAC,aAAa,EAAE,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,uBAAuB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACtG,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,MAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,IAAI,QAAQ,QAAQ,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;QACrJ,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,OAAO;QACL,SAAS,EAAE,KAAK,EAAE,IAAiE,EAA4B,EAAE,CAAC,CAChH,iBAAiB,CAAC,MAAM,IAAI,CAAC,sBAAsB,EAAE,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAChG;QACD,KAAK,EAAE,KAAK,EAAE,IAAY,EAAE,QAAgB,EAAkC,EAAE;YAC9E,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,qBAAqB,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC/F,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,EAAE,KAAK,IAAI,IAAI,MAAM,CAAC,EAAE,KAAK,IAAI;gBAAE,MAAM,IAAI,kBAAkB,CAAC,WAAW,EAAE,gBAAgB,IAAI,0BAA0B,CAAC,CAAC;YAC7J,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAChD,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type DrawFetch } from './workspace-draw-client.js';
|
|
2
|
+
import { type DrawArguments, type DrawDependencies, type DrawResult } from './workspace-draw-run.js';
|
|
3
|
+
import { RUNNER_POLICY } from './workspace-runner-policy.js';
|
|
4
|
+
/**
|
|
5
|
+
* The workspace runner (docs/slate-remote.md, "The workspace runner"): the one detached process per workspace that
|
|
6
|
+
* `12ui workspace draw` leaves on the user's Mac, so the person's later clicks (Generate more, Edit) are drawn
|
|
7
|
+
* without a turn in the agent's thread.
|
|
8
|
+
*
|
|
9
|
+
* It holds the per-workspace lock (single instance on this Mac) and the server's lease (single instance anywhere),
|
|
10
|
+
* heartbeats with the workspace's upload token, and for every running request nobody holds it claims the request
|
|
11
|
+
* and draws it with the draw command's own run, in this process: the same plan, call ids, op lock and run record as
|
|
12
|
+
* the agent's command, so a request is never drawn twice and a rerun repeats no image call. It leaves alone a request
|
|
13
|
+
* whose op lock a live run holds (the agent's own command). It stops when the workspace has been idle for
|
|
14
|
+
* `RUNNER_POLICY.idleMs`, when its token stops working or its token file is older than the token's 12-hour life, when
|
|
15
|
+
* Codex cannot draw here, or on SIGTERM; it then lets the lease go, so the screen tells the agent again.
|
|
16
|
+
*
|
|
17
|
+
* On SIGTERM or SIGINT it claims nothing new and keeps its lease while the draws in hand finish: their Codex calls do
|
|
18
|
+
* not stop with the signal (`interruptOnSignal: false`), so their options land. What is still drawing at
|
|
19
|
+
* `RUNNER_POLICY.stopDeadlineMs` is given back to the agent with the goodbye, its calls stopped, and never pushed as
|
|
20
|
+
* failed. A call Codex itself was stopped in (macOS signals every process at logout and kills them seconds later) is
|
|
21
|
+
* not pushed either: the request goes back to the agent, whose command settles it.
|
|
22
|
+
*
|
|
23
|
+
* Every Codex call is recorded by process group while it runs, so a runner killed outright leaves its calls findable:
|
|
24
|
+
* the next runner of the workspace stops them when it starts. On every exit that still holds the lock it deletes the
|
|
25
|
+
* token file before letting the lock go.
|
|
26
|
+
*/
|
|
27
|
+
export type RunnerStop = 'already_running' | 'idle' | 'token_missing' | 'token_invalid' | 'token_expired' | 'cli_outdated' | 'workspace_mismatch' | 'no_engine' | 'lock_lost' | 'signal' | 'fault';
|
|
28
|
+
export type RunnerDependencies = {
|
|
29
|
+
env?: NodeJS.ProcessEnv;
|
|
30
|
+
dataRoot?: string;
|
|
31
|
+
cliVersion?: string;
|
|
32
|
+
fetch?: DrawFetch;
|
|
33
|
+
/** Draws one request; the default is the draw command's own run. */
|
|
34
|
+
draw?: (args: DrawArguments, deps: DrawDependencies) => Promise<DrawResult>;
|
|
35
|
+
/** Extra dependencies for each draw (tests hand in the executor and the readiness probe). */
|
|
36
|
+
drawDeps?: Partial<DrawDependencies>;
|
|
37
|
+
now?: () => number;
|
|
38
|
+
sleep?: (milliseconds: number, signal: AbortSignal) => Promise<void>;
|
|
39
|
+
policy?: Partial<typeof RUNNER_POLICY>;
|
|
40
|
+
/** Aborting it stops the runner as a signal would. */
|
|
41
|
+
stop?: AbortSignal;
|
|
42
|
+
runnerId?: string;
|
|
43
|
+
};
|
|
44
|
+
/** `handedBack`: requests still drawing at the stop deadline, given back to the agent (the process must then exit). */
|
|
45
|
+
export type RunnerOutcome = {
|
|
46
|
+
stop: RunnerStop;
|
|
47
|
+
runnerId: string;
|
|
48
|
+
drawn: string[];
|
|
49
|
+
handedBack: string[];
|
|
50
|
+
};
|
|
51
|
+
export declare const runWorkspaceRunner: (args: {
|
|
52
|
+
origin: string;
|
|
53
|
+
workspace: string;
|
|
54
|
+
deps?: RunnerDependencies;
|
|
55
|
+
}) => Promise<RunnerOutcome>;
|
|
56
|
+
//# sourceMappingURL=workspace-runner-main.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-runner-main.d.ts","sourceRoot":"","sources":["../src/workspace-runner-main.ts"],"names":[],"mappings":"AAMA,OAAO,EAAqC,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC/F,OAAO,EAAoB,KAAK,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAIvH,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAY7D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,MAAM,UAAU,GAClB,iBAAiB,GACjB,MAAM,GACN,eAAe,GACf,eAAe,GACf,eAAe,GACf,cAAc,GACd,oBAAoB,GACpB,WAAW,GACX,WAAW,GACX,QAAQ,GACR,OAAO,CAAC;AAEZ,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,oEAAoE;IACpE,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,gBAAgB,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5E,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACrC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,aAAa,CAAC,CAAC;IACvC,sDAAsD;IACtD,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,uHAAuH;AACvH,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AA4B1G,eAAO,MAAM,kBAAkB,GAAU,MAAM;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,kBAAkB,CAAC;CAC3B,KAAG,OAAO,CAAC,aAAa,CAgQxB,CAAC"}
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { packageIdentity } from './client-version.js';
|
|
4
|
+
import { SlateError } from './slate-errors.js';
|
|
5
|
+
import { acquireLock, parseHolder, RUNNER_HEARTBEAT_INTERVAL_MS, staleWhenHeartbeatLapsed } from './slate-lock.js';
|
|
6
|
+
import { DrawHttpError, DrawTransportError } from './workspace-draw-client.js';
|
|
7
|
+
import { runWorkspaceDraw } from './workspace-draw-run.js';
|
|
8
|
+
import { defaultDataRoot, opLockIsLive, opRootOf } from './workspace-draw-store.js';
|
|
9
|
+
import { createRunnerClient } from './workspace-runner-client.js';
|
|
10
|
+
import { codexChildRecorder, reapCodexChildren } from './workspace-runner-children.js';
|
|
11
|
+
import { RUNNER_POLICY } from './workspace-runner-policy.js';
|
|
12
|
+
import { createRunnerLog, ensureRunnerDir, readRunnerToken, removeRunnerToken, runnerDirOf, runnerLockFile, runnerTokenWrittenAtMs, } from './workspace-runner-store.js';
|
|
13
|
+
/** The stops after which the token cannot speak to the server: no goodbye, and no lease kept while finishing. */
|
|
14
|
+
const SILENT_STOPS = new Set(['token_missing', 'token_invalid', 'token_expired']);
|
|
15
|
+
const interruptibleSleep = (milliseconds, signal) => new Promise((resolve) => {
|
|
16
|
+
if (signal.aborted) {
|
|
17
|
+
resolve();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const done = () => { clearTimeout(timer); signal.removeEventListener('abort', done); resolve(); };
|
|
21
|
+
const timer = setTimeout(done, milliseconds);
|
|
22
|
+
signal.addEventListener('abort', done, { once: true });
|
|
23
|
+
});
|
|
24
|
+
/** What one draw's outcome means for the runner: done with the request, retry it later, or stop altogether. */
|
|
25
|
+
const verdictOf = (result) => {
|
|
26
|
+
switch (result.output.code) {
|
|
27
|
+
case 'done':
|
|
28
|
+
case 'replayed':
|
|
29
|
+
case 'partial':
|
|
30
|
+
case 'failed':
|
|
31
|
+
case 'unknown_op':
|
|
32
|
+
return { kind: 'done' };
|
|
33
|
+
// Another run holds the request (this Mac's agent command, or a runner whose claim is in flight): not this one's.
|
|
34
|
+
case 'op_in_progress':
|
|
35
|
+
case 'op_in_flight':
|
|
36
|
+
case 'needs_escalation':
|
|
37
|
+
return { kind: 'retry' };
|
|
38
|
+
case 'token_invalid': return { kind: 'stop', stop: 'token_invalid' };
|
|
39
|
+
case 'cli_outdated': return { kind: 'stop', stop: 'cli_outdated' };
|
|
40
|
+
// Codex cannot draw here (or stopped being able to): the agent's command will say why.
|
|
41
|
+
case 'no_engine': return { kind: 'stop', stop: 'no_engine' };
|
|
42
|
+
default: return { kind: 'stop', stop: 'fault' };
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
export const runWorkspaceRunner = async (args) => {
|
|
46
|
+
const deps = args.deps ?? {};
|
|
47
|
+
const env = deps.env ?? process.env;
|
|
48
|
+
const policy = { ...RUNNER_POLICY, ...deps.policy };
|
|
49
|
+
const now = deps.now ?? Date.now;
|
|
50
|
+
const sleep = deps.sleep ?? interruptibleSleep;
|
|
51
|
+
const dataRoot = deps.dataRoot ?? defaultDataRoot(env);
|
|
52
|
+
const cliVersion = deps.cliVersion ?? packageIdentity().version;
|
|
53
|
+
const runnerId = deps.runnerId ?? randomUUID();
|
|
54
|
+
const draw = deps.draw ?? runWorkspaceDraw;
|
|
55
|
+
const dir = runnerDirOf(dataRoot, args.origin, args.workspace);
|
|
56
|
+
await ensureRunnerDir(dir);
|
|
57
|
+
const log = createRunnerLog(dir, () => new Date(now()));
|
|
58
|
+
let lock;
|
|
59
|
+
try {
|
|
60
|
+
lock = await acquireLock({ file: runnerLockFile(dir), policy: staleWhenHeartbeatLapsed, waitMs: 0 });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof SlateError && error.code === 'workspace_busy')
|
|
64
|
+
return { stop: 'already_running', runnerId, drawn: [], handedBack: [] };
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
const halt = new AbortController();
|
|
68
|
+
let stop = null;
|
|
69
|
+
const stopWith = (reason) => {
|
|
70
|
+
stop ??= reason;
|
|
71
|
+
halt.abort();
|
|
72
|
+
};
|
|
73
|
+
const onExternalStop = () => { stopWith('signal'); };
|
|
74
|
+
deps.stop?.addEventListener('abort', onExternalStop, { once: true });
|
|
75
|
+
if (deps.stop?.aborted)
|
|
76
|
+
stopWith('signal');
|
|
77
|
+
// The lock's heartbeat, and the check that it is still ours (a run after a long sleep may have taken it over).
|
|
78
|
+
const keepLock = setInterval(() => {
|
|
79
|
+
void (async () => {
|
|
80
|
+
const raw = await readFile(lock.file, 'utf8').catch(() => '');
|
|
81
|
+
if (parseHolder(raw)?.nonce !== lock.holder.nonce) {
|
|
82
|
+
stopWith('lock_lost');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
await lock.touch().catch(() => undefined);
|
|
86
|
+
})();
|
|
87
|
+
}, policy.lockTouchMs ?? RUNNER_HEARTBEAT_INTERVAL_MS);
|
|
88
|
+
keepLock.unref?.();
|
|
89
|
+
let token = '';
|
|
90
|
+
const client = createRunnerClient({
|
|
91
|
+
origin: args.origin,
|
|
92
|
+
cliVersion,
|
|
93
|
+
token: async () => token,
|
|
94
|
+
...(deps.fetch ? { fetch: deps.fetch } : {}),
|
|
95
|
+
});
|
|
96
|
+
const children = codexChildRecorder(dir, runnerId);
|
|
97
|
+
// Each call runs to its own end on a signal, and is recorded while it runs.
|
|
98
|
+
const processOptions = { interruptOnSignal: false, ...children };
|
|
99
|
+
const active = new Map();
|
|
100
|
+
const attempts = new Map();
|
|
101
|
+
const givenUp = new Set();
|
|
102
|
+
const drawn = [];
|
|
103
|
+
let lastActivity = now();
|
|
104
|
+
let failures = 0;
|
|
105
|
+
await log({ event: 'started', runnerId, origin: args.origin, workspace: args.workspace, cliVersion });
|
|
106
|
+
const drawOne = (opId) => {
|
|
107
|
+
const work = (async () => {
|
|
108
|
+
await log({ event: 'draw_started', opId });
|
|
109
|
+
let result;
|
|
110
|
+
try {
|
|
111
|
+
result = await draw({ opId, token, origin: args.origin, engine: 'auto', dryRun: false, runnerId }, { processOptions, ...deps.drawDeps, env, dataRoot, cliVersion, progress: (line) => { void log({ event: 'progress', opId, line }); } });
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
await log({ event: 'draw_fault', opId, message: error instanceof Error ? error.message : String(error) });
|
|
115
|
+
stopWith('fault');
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const verdict = verdictOf(result);
|
|
119
|
+
await log({ event: 'draw_finished', opId, code: result.output.code, exitCode: result.exitCode, message: result.output.message, record: result.output.record });
|
|
120
|
+
if (verdict.kind === 'done')
|
|
121
|
+
drawn.push(opId);
|
|
122
|
+
if (verdict.kind === 'retry') {
|
|
123
|
+
const tries = (attempts.get(opId) ?? 0) + 1;
|
|
124
|
+
attempts.set(opId, tries);
|
|
125
|
+
// A request the runner cannot get through is the agent's: the next heartbeat leaves it out, so it is released.
|
|
126
|
+
if (tries >= policy.attemptsPerOp)
|
|
127
|
+
givenUp.add(opId);
|
|
128
|
+
}
|
|
129
|
+
if (verdict.kind === 'stop')
|
|
130
|
+
stopWith(verdict.stop);
|
|
131
|
+
})().finally(() => {
|
|
132
|
+
active.delete(opId);
|
|
133
|
+
lastActivity = now();
|
|
134
|
+
});
|
|
135
|
+
active.set(opId, work);
|
|
136
|
+
};
|
|
137
|
+
/** Takes back a claim on a request this runner is still drawing; no second draw starts. */
|
|
138
|
+
const reclaim = async (opId) => {
|
|
139
|
+
try {
|
|
140
|
+
await client.claim(opId, runnerId);
|
|
141
|
+
await log({ event: 'reclaimed', opId });
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
if (error instanceof DrawHttpError && error.code === 'token_invalid') {
|
|
145
|
+
stopWith('token_invalid');
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
await log({ event: 'reclaim_refused', opId, code: error instanceof DrawHttpError ? error.code : 'transport' });
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
const claimAndDraw = async (beat) => {
|
|
152
|
+
for (const op of beat.ops) {
|
|
153
|
+
if (stop)
|
|
154
|
+
return;
|
|
155
|
+
if (givenUp.has(op.opId))
|
|
156
|
+
continue;
|
|
157
|
+
// Drawing it already. Its claim outlives a lapsed lease (in flight on the server until its quiet window ends), so
|
|
158
|
+
// a long sleep leaves nothing to take back; a request whose window ended is the agent's and is not listed. One
|
|
159
|
+
// listed unheld while this runner still lists it as drawing was let go by someone else's goodbye in its name:
|
|
160
|
+
// take it back, inside its window, and keep drawing (a refused take-back leaves the draw to finish or be given up).
|
|
161
|
+
if (active.has(op.opId)) {
|
|
162
|
+
if (op.drawer === null)
|
|
163
|
+
await reclaim(op.opId);
|
|
164
|
+
if (stop)
|
|
165
|
+
return;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (active.size >= policy.maxActive)
|
|
169
|
+
continue;
|
|
170
|
+
if (op.drawer !== null && op.drawer !== runnerId)
|
|
171
|
+
continue;
|
|
172
|
+
// The agent's own command is drawing it on this Mac: it is that run's.
|
|
173
|
+
if (await opLockIsLive(opRootOf(dataRoot, op.opId)))
|
|
174
|
+
continue;
|
|
175
|
+
try {
|
|
176
|
+
await client.claim(op.opId, runnerId);
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
if (error instanceof DrawHttpError && error.code === 'token_invalid') {
|
|
180
|
+
stopWith('token_invalid');
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
await log({ event: 'claim_refused', opId: op.opId, code: error instanceof DrawHttpError ? error.code : 'transport' });
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
await log({ event: 'claimed', opId: op.opId, kind: op.kind });
|
|
187
|
+
drawOne(op.opId);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* A dead runner's calls are stopped (reaped above), so its claims are over: its goodbye, sent for it, frees its
|
|
192
|
+
* requests at once, instead of leaving them in flight until their quiet window ends (on this Mac that is proven; a
|
|
193
|
+
* runner on another Mac cannot know it, so the server keeps them in flight).
|
|
194
|
+
*/
|
|
195
|
+
const releaseDeadRunners = async (reaped) => {
|
|
196
|
+
const dead = [...new Set(reaped.flatMap((entry) => (entry.runnerId && entry.runnerId !== runnerId ? [entry.runnerId] : [])))];
|
|
197
|
+
if (dead.length === 0)
|
|
198
|
+
return;
|
|
199
|
+
const fresh = await readRunnerToken(dir);
|
|
200
|
+
if (!fresh)
|
|
201
|
+
return;
|
|
202
|
+
token = fresh;
|
|
203
|
+
for (const deadId of dead) {
|
|
204
|
+
try {
|
|
205
|
+
await client.heartbeat({ runnerId: deadId, drawing: [], stopping: true });
|
|
206
|
+
await log({ event: 'released_dead_runner', runnerId: deadId });
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
await log({ event: 'release_dead_runner_failed', runnerId: deadId, code: error instanceof DrawHttpError ? error.code : 'transport' });
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
const goodbye = async () => {
|
|
214
|
+
// Before the first token is read there is nothing to say it with, and nothing was ever claimed.
|
|
215
|
+
if (token === '') {
|
|
216
|
+
await log({ event: 'goodbye_skipped', reason: 'no_token' });
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
try {
|
|
220
|
+
return await client.heartbeat({ runnerId, drawing: [], stopping: true });
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
await log({ event: 'goodbye_failed', code: error instanceof DrawHttpError ? error.code : 'transport' });
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
/**
|
|
228
|
+
* Stopping: claim nothing more, keep the lease (a heartbeat listing what is drawing) while the draws in hand finish,
|
|
229
|
+
* up to the stop deadline. Returns what is still drawing then, after stopping its Codex calls: the goodbye gives
|
|
230
|
+
* those requests back to the agent, and nothing is pushed for them.
|
|
231
|
+
*/
|
|
232
|
+
const finishDrawsInHand = async () => {
|
|
233
|
+
if (active.size === 0)
|
|
234
|
+
return [];
|
|
235
|
+
const deadline = now() + policy.stopDeadlineMs;
|
|
236
|
+
const settled = Promise.allSettled([...active.values()]);
|
|
237
|
+
const keepLease = !SILENT_STOPS.has(stop);
|
|
238
|
+
const never = new AbortController().signal;
|
|
239
|
+
await log({ event: 'finishing', stop, drawing: [...active.keys()], deadlineMs: policy.stopDeadlineMs });
|
|
240
|
+
while (active.size > 0 && now() < deadline) {
|
|
241
|
+
if (keepLease)
|
|
242
|
+
await client.heartbeat({ runnerId, drawing: [...active.keys()].filter((opId) => !givenUp.has(opId)) }).catch(() => null);
|
|
243
|
+
await Promise.race([settled, sleep(Math.max(1, Math.min(policy.pollMs, deadline - now())), never)]);
|
|
244
|
+
}
|
|
245
|
+
const left = [...active.keys()];
|
|
246
|
+
if (left.length > 0) {
|
|
247
|
+
const reaped = await reapCodexChildren(dir, { alsoOf: process.pid }).catch(() => []);
|
|
248
|
+
await log({ event: 'handed_back', opIds: left, codex: reaped.map((entry) => entry.pgid) });
|
|
249
|
+
}
|
|
250
|
+
return left;
|
|
251
|
+
};
|
|
252
|
+
try {
|
|
253
|
+
// A runner of this workspace killed outright may have left Codex calls running: they are nobody's now.
|
|
254
|
+
const reaped = await reapCodexChildren(dir).catch(() => []);
|
|
255
|
+
if (reaped.length > 0)
|
|
256
|
+
await log({ event: 'reaped', codex: reaped });
|
|
257
|
+
await releaseDeadRunners(reaped);
|
|
258
|
+
while (!stop) {
|
|
259
|
+
const fresh = await readRunnerToken(dir);
|
|
260
|
+
const writtenAtMs = fresh ? await runnerTokenWrittenAtMs(dir) : null;
|
|
261
|
+
if (!fresh || writtenAtMs === null) {
|
|
262
|
+
stopWith('token_missing');
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
// The token file is rewritten by every draw command; one older than the token's life holds a dead token.
|
|
266
|
+
if (now() - writtenAtMs >= policy.tokenLifetimeMs) {
|
|
267
|
+
stopWith('token_expired');
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
token = fresh;
|
|
271
|
+
let beat;
|
|
272
|
+
try {
|
|
273
|
+
beat = await client.heartbeat({ runnerId, drawing: [...active.keys()].filter((opId) => !givenUp.has(opId)) });
|
|
274
|
+
failures = 0;
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
if (error instanceof DrawHttpError) {
|
|
278
|
+
if (error.code === 'token_invalid') {
|
|
279
|
+
stopWith('token_invalid');
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
if (error.status === 426 || error.code === 'cli_outdated') {
|
|
283
|
+
stopWith('cli_outdated');
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
if (error.code === 'runner_busy' || error.status === 429) {
|
|
287
|
+
// Another runner's lease (a dead one lapses within one lease), or the edge limit: wait what it names.
|
|
288
|
+
await log({ event: 'wait', code: error.code, seconds: error.retryAfterSeconds });
|
|
289
|
+
if (active.size === 0 && now() - lastActivity >= policy.idleMs) {
|
|
290
|
+
stopWith('idle');
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
await sleep(Math.min(policy.leaseWaitMaxMs, Math.max(1, error.retryAfterSeconds ?? 5) * 1000), halt.signal);
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (error instanceof DrawTransportError && error.kind === 'malformed') {
|
|
298
|
+
stopWith('fault');
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
// Unreachable or a server fault: back off and try again; idle time keeps counting.
|
|
302
|
+
failures += 1;
|
|
303
|
+
await log({ event: 'heartbeat_failed', code: error instanceof DrawHttpError ? error.code : 'unreachable', failures });
|
|
304
|
+
if (active.size === 0 && now() - lastActivity >= policy.idleMs) {
|
|
305
|
+
stopWith('idle');
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
await sleep(Math.min(policy.backoffMaxMs, policy.pollMs * 2 ** Math.min(failures, 6)), halt.signal);
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
if (beat.workspace !== args.workspace) {
|
|
312
|
+
stopWith('workspace_mismatch');
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
const open = beat.ops.filter((op) => !givenUp.has(op.opId));
|
|
316
|
+
if (open.length > 0 || active.size > 0)
|
|
317
|
+
lastActivity = now();
|
|
318
|
+
await claimAndDraw(beat);
|
|
319
|
+
if (stop)
|
|
320
|
+
break;
|
|
321
|
+
if (active.size === 0 && open.length === 0 && now() - lastActivity >= policy.idleMs) {
|
|
322
|
+
// Let the lease go; a click that raced the goodbye keeps the runner on.
|
|
323
|
+
const last = await goodbye();
|
|
324
|
+
if (last && last.ops.some((op) => op.drawer === null && !givenUp.has(op.opId))) {
|
|
325
|
+
lastActivity = now();
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
stop = 'idle';
|
|
329
|
+
await log({ event: 'stopped', stop, drawn });
|
|
330
|
+
return { stop, runnerId, drawn, handedBack: [] };
|
|
331
|
+
}
|
|
332
|
+
await sleep(policy.pollMs, halt.signal);
|
|
333
|
+
}
|
|
334
|
+
const handedBack = await finishDrawsInHand();
|
|
335
|
+
if (!SILENT_STOPS.has(stop))
|
|
336
|
+
await goodbye();
|
|
337
|
+
await log({ event: 'stopped', stop, drawn, ...(handedBack.length > 0 ? { handedBack } : {}) });
|
|
338
|
+
return { stop: stop ?? 'fault', runnerId, drawn, handedBack };
|
|
339
|
+
}
|
|
340
|
+
finally {
|
|
341
|
+
clearInterval(keepLock);
|
|
342
|
+
deps.stop?.removeEventListener('abort', onExternalStop);
|
|
343
|
+
// The token goes with the runner, unless another runner has taken the lock over (it is that runner's token now).
|
|
344
|
+
const holder = parseHolder(await readFile(lock.file, 'utf8').catch(() => ''));
|
|
345
|
+
if (holder?.nonce === lock.holder.nonce)
|
|
346
|
+
await removeRunnerToken(dir).catch(() => undefined);
|
|
347
|
+
await lock.release();
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
//# sourceMappingURL=workspace-runner-main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-runner-main.js","sourceRoot":"","sources":["../src/workspace-runner-main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The workspace runner's numbers and launch rule, in one module (CLAUDE.md item 9). The server's lease
|
|
3
|
+
* (`SLATE_RUNNER.leaseMs`, 60 s, renewed below 30 s) is what decides whether the screen tells the agent; these only
|
|
4
|
+
* pace and bound the runner itself.
|
|
5
|
+
*/
|
|
6
|
+
export declare const RUNNER_POLICY: Readonly<{
|
|
7
|
+
/** One heartbeat (which is also the poll for new clicks) every 5 s: a click starts drawing within about 5 s. */
|
|
8
|
+
pollMs: 5000;
|
|
9
|
+
/** An idle workspace lets its runner go after 30 minutes; the next click then goes to the agent, which starts one. */
|
|
10
|
+
idleMs: number;
|
|
11
|
+
/** The server allows at most three running requests per workspace; the runner draws at most that many at once. */
|
|
12
|
+
maxActive: 3;
|
|
13
|
+
/** A request the runner could not get through this many times (server unreachable mid-draw) is left to the agent. */
|
|
14
|
+
attemptsPerOp: 3;
|
|
15
|
+
/** Backoff ceiling while design.12ui.com cannot be reached. */
|
|
16
|
+
backoffMaxMs: 60000;
|
|
17
|
+
/** The longest single wait for another runner's lease to lapse (one lease). */
|
|
18
|
+
leaseWaitMaxMs: 60000;
|
|
19
|
+
/** The lock file's own heartbeat (its mtime); `null` keeps the lock module's default. */
|
|
20
|
+
lockTouchMs: number | null;
|
|
21
|
+
/**
|
|
22
|
+
* After SIGTERM or SIGINT the runner claims nothing new, keeps its lease, and lets the draws in hand finish: their
|
|
23
|
+
* Codex calls are not stopped by the signal (each is bounded by its own timeout), so their options land. This is the
|
|
24
|
+
* longest it waits: one image call's own timeout plus a minute for its pushes. What is still drawing then is given
|
|
25
|
+
* back to the agent, never marked failed.
|
|
26
|
+
*/
|
|
27
|
+
stopDeadlineMs: number;
|
|
28
|
+
/**
|
|
29
|
+
* The upload token lives 12 hours (the server's `SLATE_TIME.pushTokenTtlMs`). Every `12ui workspace draw` rewrites
|
|
30
|
+
* the token file, so a file older than this holds a dead token: the runner stops then on its own, whatever its
|
|
31
|
+
* server answers.
|
|
32
|
+
*/
|
|
33
|
+
tokenLifetimeMs: number;
|
|
34
|
+
}>;
|
|
35
|
+
/** Set to 1 and `12ui workspace draw` leaves no runner behind: every click then messages the agent, as before. */
|
|
36
|
+
export declare const RUNNER_OPT_OUT_ENV = "TWELVE_UI_NO_RUNNER";
|
|
37
|
+
export type RunnerLaunchRefusal = 'opted_out' | 'origin';
|
|
38
|
+
/** Why no runner may be left behind for this origin and environment, or null when one may. */
|
|
39
|
+
export declare const runnerLaunchRefusal: (origin: string, env: NodeJS.ProcessEnv) => RunnerLaunchRefusal | null;
|
|
40
|
+
//# sourceMappingURL=workspace-runner-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-runner-policy.d.ts","sourceRoot":"","sources":["../src/workspace-runner-policy.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,eAAO,MAAM,aAAa;IACxB,gHAAgH;;IAEhH,sHAAsH;;IAEtH,kHAAkH;;IAElH,qHAAqH;;IAErH,+DAA+D;;IAE/D,+EAA+E;;IAE/E,yFAAyF;iBACpE,MAAM,GAAG,IAAI;IAClC;;;;;OAKG;;IAEH;;;;OAIG;;EAEH,CAAC;AAEH,kHAAkH;AAClH,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AAExD,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEzD,8FAA8F;AAC9F,eAAO,MAAM,mBAAmB,GAAI,QAAQ,MAAM,EAAE,KAAK,MAAM,CAAC,UAAU,KAAG,mBAAmB,GAAG,IAIlG,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { IMAGE_CALL_TIMEOUT_MS } from './slate-image-executor.js';
|
|
2
|
+
import { runnerOriginAllowed } from './workspace-origin.js';
|
|
3
|
+
/**
|
|
4
|
+
* The workspace runner's numbers and launch rule, in one module (CLAUDE.md item 9). The server's lease
|
|
5
|
+
* (`SLATE_RUNNER.leaseMs`, 60 s, renewed below 30 s) is what decides whether the screen tells the agent; these only
|
|
6
|
+
* pace and bound the runner itself.
|
|
7
|
+
*/
|
|
8
|
+
export const RUNNER_POLICY = Object.freeze({
|
|
9
|
+
/** One heartbeat (which is also the poll for new clicks) every 5 s: a click starts drawing within about 5 s. */
|
|
10
|
+
pollMs: 5_000,
|
|
11
|
+
/** An idle workspace lets its runner go after 30 minutes; the next click then goes to the agent, which starts one. */
|
|
12
|
+
idleMs: 30 * 60_000,
|
|
13
|
+
/** The server allows at most three running requests per workspace; the runner draws at most that many at once. */
|
|
14
|
+
maxActive: 3,
|
|
15
|
+
/** A request the runner could not get through this many times (server unreachable mid-draw) is left to the agent. */
|
|
16
|
+
attemptsPerOp: 3,
|
|
17
|
+
/** Backoff ceiling while design.12ui.com cannot be reached. */
|
|
18
|
+
backoffMaxMs: 60_000,
|
|
19
|
+
/** The longest single wait for another runner's lease to lapse (one lease). */
|
|
20
|
+
leaseWaitMaxMs: 60_000,
|
|
21
|
+
/** The lock file's own heartbeat (its mtime); `null` keeps the lock module's default. */
|
|
22
|
+
lockTouchMs: null,
|
|
23
|
+
/**
|
|
24
|
+
* After SIGTERM or SIGINT the runner claims nothing new, keeps its lease, and lets the draws in hand finish: their
|
|
25
|
+
* Codex calls are not stopped by the signal (each is bounded by its own timeout), so their options land. This is the
|
|
26
|
+
* longest it waits: one image call's own timeout plus a minute for its pushes. What is still drawing then is given
|
|
27
|
+
* back to the agent, never marked failed.
|
|
28
|
+
*/
|
|
29
|
+
stopDeadlineMs: IMAGE_CALL_TIMEOUT_MS + 60_000,
|
|
30
|
+
/**
|
|
31
|
+
* The upload token lives 12 hours (the server's `SLATE_TIME.pushTokenTtlMs`). Every `12ui workspace draw` rewrites
|
|
32
|
+
* the token file, so a file older than this holds a dead token: the runner stops then on its own, whatever its
|
|
33
|
+
* server answers.
|
|
34
|
+
*/
|
|
35
|
+
tokenLifetimeMs: 12 * 60 * 60_000,
|
|
36
|
+
});
|
|
37
|
+
/** Set to 1 and `12ui workspace draw` leaves no runner behind: every click then messages the agent, as before. */
|
|
38
|
+
export const RUNNER_OPT_OUT_ENV = 'TWELVE_UI_NO_RUNNER';
|
|
39
|
+
/** Why no runner may be left behind for this origin and environment, or null when one may. */
|
|
40
|
+
export const runnerLaunchRefusal = (origin, env) => {
|
|
41
|
+
if ((env[RUNNER_OPT_OUT_ENV] ?? '').trim() === '1')
|
|
42
|
+
return 'opted_out';
|
|
43
|
+
if (!runnerOriginAllowed(origin))
|
|
44
|
+
return 'origin';
|
|
45
|
+
return null;
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=workspace-runner-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-runner-policy.js","sourceRoot":"","sources":["../src/workspace-runner-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC;IACzC,gHAAgH;IAChH,MAAM,EAAE,KAAK;IACb,sHAAsH;IACtH,MAAM,EAAE,EAAE,GAAG,MAAM;IACnB,kHAAkH;IAClH,SAAS,EAAE,CAAC;IACZ,qHAAqH;IACrH,aAAa,EAAE,CAAC;IAChB,+DAA+D;IAC/D,YAAY,EAAE,MAAM;IACpB,+EAA+E;IAC/E,cAAc,EAAE,MAAM;IACtB,yFAAyF;IACzF,WAAW,EAAE,IAAqB;IAClC;;;;;OAKG;IACH,cAAc,EAAE,qBAAqB,GAAG,MAAM;IAC9C;;;;OAIG;IACH,eAAe,EAAE,EAAE,GAAG,EAAE,GAAG,MAAM;CAClC,CAAC,CAAC;AAEH,kHAAkH;AAClH,MAAM,CAAC,MAAM,kBAAkB,GAAG,qBAAqB,CAAC;AAIxD,8FAA8F;AAC9F,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAc,EAAE,GAAsB,EAA8B,EAAE;IACxG,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,GAAG;QAAE,OAAO,WAAW,CAAC;IACvE,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC;QAAE,OAAO,QAAQ,CAAC;IAClD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC"}
|