@sublang/slc 0.1.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/LICENSE +201 -0
- package/README.md +192 -0
- package/dist/app.d.ts +85 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +233 -0
- package/dist/app.js.map +1 -0
- package/dist/artifacts.d.ts +61 -0
- package/dist/artifacts.d.ts.map +1 -0
- package/dist/artifacts.js +97 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +26 -0
- package/dist/cli.js.map +1 -0
- package/dist/cligent-agent.d.ts +11 -0
- package/dist/cligent-agent.d.ts.map +1 -0
- package/dist/cligent-agent.js +66 -0
- package/dist/cligent-agent.js.map +1 -0
- package/dist/compiled-executor.d.ts +42 -0
- package/dist/compiled-executor.d.ts.map +1 -0
- package/dist/compiled-executor.js +433 -0
- package/dist/compiled-executor.js.map +1 -0
- package/dist/config-file.d.ts +52 -0
- package/dist/config-file.d.ts.map +1 -0
- package/dist/config-file.js +159 -0
- package/dist/config-file.js.map +1 -0
- package/dist/config.d.ts +82 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +161 -0
- package/dist/config.js.map +1 -0
- package/dist/entry-module.d.ts +22 -0
- package/dist/entry-module.d.ts.map +1 -0
- package/dist/entry-module.js +216 -0
- package/dist/entry-module.js.map +1 -0
- package/dist/execution.d.ts +71 -0
- package/dist/execution.d.ts.map +1 -0
- package/dist/execution.js +207 -0
- package/dist/execution.js.map +1 -0
- package/dist/file-capability.d.ts +46 -0
- package/dist/file-capability.d.ts.map +1 -0
- package/dist/file-capability.js +234 -0
- package/dist/file-capability.js.map +1 -0
- package/dist/file-grants.d.ts +79 -0
- package/dist/file-grants.d.ts.map +1 -0
- package/dist/file-grants.js +133 -0
- package/dist/file-grants.js.map +1 -0
- package/dist/hash.d.ts +14 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +34 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/interpreter.d.ts +48 -0
- package/dist/interpreter.d.ts.map +1 -0
- package/dist/interpreter.js +118 -0
- package/dist/interpreter.js.map +1 -0
- package/dist/invocation.d.ts +64 -0
- package/dist/invocation.d.ts.map +1 -0
- package/dist/invocation.js +148 -0
- package/dist/invocation.js.map +1 -0
- package/dist/link.d.ts +63 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +172 -0
- package/dist/link.js.map +1 -0
- package/dist/markdown.d.ts +12 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +63 -0
- package/dist/markdown.js.map +1 -0
- package/dist/normalize.md +68 -0
- package/dist/phase-runner.d.ts +64 -0
- package/dist/phase-runner.d.ts.map +1 -0
- package/dist/phase-runner.js +322 -0
- package/dist/phase-runner.js.map +1 -0
- package/dist/phase.d.ts +62 -0
- package/dist/phase.d.ts.map +1 -0
- package/dist/phase.js +111 -0
- package/dist/phase.js.map +1 -0
- package/dist/pin-closure.d.ts +19 -0
- package/dist/pin-closure.d.ts.map +1 -0
- package/dist/pin-closure.js +110 -0
- package/dist/pin-closure.js.map +1 -0
- package/dist/pin-currency.d.ts +55 -0
- package/dist/pin-currency.d.ts.map +1 -0
- package/dist/pin-currency.js +435 -0
- package/dist/pin-currency.js.map +1 -0
- package/dist/pin-generate.d.ts +46 -0
- package/dist/pin-generate.d.ts.map +1 -0
- package/dist/pin-generate.js +131 -0
- package/dist/pin-generate.js.map +1 -0
- package/dist/pin-paths.d.ts +11 -0
- package/dist/pin-paths.d.ts.map +1 -0
- package/dist/pin-paths.js +108 -0
- package/dist/pin-paths.js.map +1 -0
- package/dist/pins.d.ts +84 -0
- package/dist/pins.d.ts.map +1 -0
- package/dist/pins.js +265 -0
- package/dist/pins.js.map +1 -0
- package/dist/pipeline.d.ts +61 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +147 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/playbook-contract.d.ts +194 -0
- package/dist/playbook-contract.d.ts.map +1 -0
- package/dist/playbook-contract.js +180 -0
- package/dist/playbook-contract.js.map +1 -0
- package/dist/playbook-ports.d.ts +53 -0
- package/dist/playbook-ports.d.ts.map +1 -0
- package/dist/playbook-ports.js +217 -0
- package/dist/playbook-ports.js.map +1 -0
- package/dist/resolver.d.ts +68 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +133 -0
- package/dist/resolver.js.map +1 -0
- package/dist/runner.d.ts +45 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +506 -0
- package/dist/runner.js.map +1 -0
- package/dist/runtime-package.d.ts +7 -0
- package/dist/runtime-package.d.ts.map +1 -0
- package/dist/runtime-package.js +132 -0
- package/dist/runtime-package.js.map +1 -0
- package/dist/slc.config.template.yaml +5 -0
- package/dist/verify-coverage.d.ts +99 -0
- package/dist/verify-coverage.d.ts.map +1 -0
- package/dist/verify-coverage.js +1949 -0
- package/dist/verify-coverage.js.map +1 -0
- package/dist/verify-support.d.ts +10 -0
- package/dist/verify-support.d.ts.map +1 -0
- package/dist/verify-support.js +52 -0
- package/dist/verify-support.js.map +1 -0
- package/dist/verify.d.ts +393 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +1790 -0
- package/dist/verify.js.map +1 -0
- package/package.json +76 -0
package/dist/app.js
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
3
|
+
/**
|
|
4
|
+
* The `slc` bin orchestrator (CLI package).
|
|
5
|
+
*
|
|
6
|
+
* `run` is the testable command-line entry: it short-circuits `--version` and
|
|
7
|
+
* `--help` before touching any pipeline or agent (CLI-1, CLI-2, CLI-9), builds
|
|
8
|
+
* the run dependencies from environment configuration (CLI-6, CLI-7, CLI-12),
|
|
9
|
+
* invokes the injectable `runSlc` core under a cancellation signal (CLI-10), and
|
|
10
|
+
* maps the result onto process streams and an exit code — produced artifact
|
|
11
|
+
* paths to stdout on success, the failure report to stderr otherwise (CLI-3,
|
|
12
|
+
* CLI-4, CLI-11). Every IO seam is injectable so the bin is integration-testable
|
|
13
|
+
* without a real agent; the `cli.ts` shim supplies the process-backed defaults
|
|
14
|
+
* and signal wiring. See specs/dev/cli.md and specs/user/cli.md.
|
|
15
|
+
*/
|
|
16
|
+
import { createRequire } from 'node:module';
|
|
17
|
+
import { createConfiguredCompiledFactory, createConfiguredExecutor, resolveAgentSelection, } from './config.js';
|
|
18
|
+
import { loadConfigFile } from './config-file.js';
|
|
19
|
+
import { createPipelineResolver, pipelineSearchRoots, withReservedPipelines, } from './resolver.js';
|
|
20
|
+
import { runSlc } from './runner.js';
|
|
21
|
+
const manifest = createRequire(import.meta.url)('../package.json');
|
|
22
|
+
if (typeof manifest.version !== 'string') {
|
|
23
|
+
throw new TypeError('package.json version must be a string');
|
|
24
|
+
}
|
|
25
|
+
const packageVersion = manifest.version;
|
|
26
|
+
/** The program name. */
|
|
27
|
+
export const name = 'slc';
|
|
28
|
+
/** Returns the slc version string. */
|
|
29
|
+
export function version() {
|
|
30
|
+
return packageVersion;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Builds the production {@link SlcDeps}: a pipeline resolver over the resolved
|
|
34
|
+
* search roots (CLI-6) — with the reserved `slc` reference routed to the
|
|
35
|
+
* meta-pipeline definitions `@sublang/playbook` provides (SELFHOST-2) — an
|
|
36
|
+
* interpreted executor for the resolved agent/model (CLI-7), and the
|
|
37
|
+
* compiled-execution factory a current pinned phase selects (CLI-8, PHEXEC-27).
|
|
38
|
+
* Configuration is loaded from the config file (DR-006, CLI-20) and
|
|
39
|
+
* then overridden per key by a non-blank environment variable, so existing
|
|
40
|
+
* env-only runs are unchanged and the file fills any key the environment leaves
|
|
41
|
+
* unset.
|
|
42
|
+
*
|
|
43
|
+
* @throws {import('./config-file.js').ConfigFileError} when an explicit
|
|
44
|
+
* `--config` path is absent or the file is malformed or invalid (CLI-21).
|
|
45
|
+
* @throws {import('./config.js').ConfigError} when neither source supplies an
|
|
46
|
+
* agent, or the resolved agent is unsupported (CLI-12).
|
|
47
|
+
*/
|
|
48
|
+
export async function buildSlcDeps({ env, cwd, signal, configPath, note },
|
|
49
|
+
// Injectable so a test can capture the executor options — notably the
|
|
50
|
+
// non-interactive write permission below — without constructing a real
|
|
51
|
+
// adapter, the same seam pattern as `createConfiguredExecutor`'s
|
|
52
|
+
// `adapterFactory`. Defaults to the production factories.
|
|
53
|
+
createExecutor = createConfiguredExecutor, createCompiled = createConfiguredCompiledFactory) {
|
|
54
|
+
const file = await loadConfigFile({
|
|
55
|
+
cwd,
|
|
56
|
+
configPath,
|
|
57
|
+
env,
|
|
58
|
+
// First-run seeding (DR-015): name the created user config on stderr.
|
|
59
|
+
onSeed: (path) => note?.(`slc: seeded ${path} (agent: claude-code)\n`),
|
|
60
|
+
});
|
|
61
|
+
const { selection, pipelinePath } = resolveRunConfig(env, file.config);
|
|
62
|
+
const resolver = withReservedPipelines(createPipelineResolver(pipelineSearchRoots(pipelinePath, cwd)));
|
|
63
|
+
// Auto-accept the agents' file operations so a non-interactive `slc` run can
|
|
64
|
+
// write its target artifact; the DR-003 generic checks still guard the
|
|
65
|
+
// protected inputs (DR-004).
|
|
66
|
+
const agentOpts = { cwd, permissions: { mode: 'auto' } };
|
|
67
|
+
const executor = createExecutor(selection, agentOpts);
|
|
68
|
+
const compiled = createCompiled(selection, agentOpts);
|
|
69
|
+
return { resolver, executor, compiled, cwd, signal };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Merges the environment over config-file values per key (DR-006, CLI-20): for
|
|
73
|
+
* each key a non-blank environment variable wins, otherwise the file value,
|
|
74
|
+
* otherwise the built-in default. The agent and model go through
|
|
75
|
+
* {@link resolveAgentSelection} so the supported-agent check stays single-sourced
|
|
76
|
+
* (CLI-7, CLI-12).
|
|
77
|
+
*/
|
|
78
|
+
export function resolveRunConfig(env, file) {
|
|
79
|
+
const selection = resolveAgentSelection({
|
|
80
|
+
SLC_AGENT: nonBlank(env.SLC_AGENT) ?? file.agent,
|
|
81
|
+
SLC_MODEL: nonBlank(env.SLC_MODEL) ?? file.model,
|
|
82
|
+
SLC_EFFORT: nonBlank(env.SLC_EFFORT) ?? file.effort,
|
|
83
|
+
});
|
|
84
|
+
const pipelinePath = nonBlank(env.SLC_PIPELINE_PATH) ?? file.pipelinePath;
|
|
85
|
+
return { selection, pipelinePath };
|
|
86
|
+
}
|
|
87
|
+
/** Returns `value` when set and not all-whitespace, else `undefined` (DR-006). */
|
|
88
|
+
function nonBlank(value) {
|
|
89
|
+
return value !== undefined && value.trim() !== '' ? value : undefined;
|
|
90
|
+
}
|
|
91
|
+
/** Usage text naming the documented invocation forms and configuration (CLI-2). */
|
|
92
|
+
export function usageText() {
|
|
93
|
+
return [
|
|
94
|
+
'Usage:',
|
|
95
|
+
' slc <pipeline>[.<phase>] <source> [-o <target>]',
|
|
96
|
+
' slc <pipeline> <source> [--normalize] [--no-optimize] [--link <target>] [--link-option name=value]...',
|
|
97
|
+
' slc <pipeline>.link <object>... <target> [-o <linked>] [--link-option name=value]...',
|
|
98
|
+
'',
|
|
99
|
+
'Artifacts land in the working directory (<cwd>/<basename>.<pipeline>/);',
|
|
100
|
+
'an entry source with a foreign extension is normalized first, and the',
|
|
101
|
+
'playbook pipeline links against the installed @sublang/playbook runtime',
|
|
102
|
+
'when --link is omitted, also emitting the runnable <basename>.ts entry.',
|
|
103
|
+
'',
|
|
104
|
+
'Options:',
|
|
105
|
+
' -o <path> final output path override',
|
|
106
|
+
' --link <target> link the full-pipeline output to <target>',
|
|
107
|
+
' --link-option name=value pass an opaque option to the link phase',
|
|
108
|
+
" --normalize rewrite raw input to the entry phase's source form first",
|
|
109
|
+
" -O, --optimize run the pipeline's pass phases (the default)",
|
|
110
|
+
' --no-optimize run the chain without pass phases',
|
|
111
|
+
' --config <path> load configuration from <path> (disables discovery)',
|
|
112
|
+
' -v, --version print version and exit',
|
|
113
|
+
' -h, --help print this help and exit',
|
|
114
|
+
'',
|
|
115
|
+
'Configuration:',
|
|
116
|
+
' Config file (YAML), discovered in order, then overridden per key by the',
|
|
117
|
+
' environment variable below:',
|
|
118
|
+
' ./slc.config.yaml',
|
|
119
|
+
' ${XDG_CONFIG_HOME:-~/.config}/slc/config.yaml',
|
|
120
|
+
' Keys: agent, model, effort, pipelinePath.',
|
|
121
|
+
'',
|
|
122
|
+
' SLC_AGENT agent CLI: claude-code | codex | gemini | opencode',
|
|
123
|
+
' SLC_MODEL optional model for the agent CLI',
|
|
124
|
+
' SLC_EFFORT optional adapter-scoped reasoning effort (e.g. xhigh)',
|
|
125
|
+
' SLC_PIPELINE_PATH search roots for <pipeline> references (default: cwd)',
|
|
126
|
+
'',
|
|
127
|
+
].join('\n');
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Splits `--config <path>` out of argv, returning the path and the remaining
|
|
131
|
+
* arguments for `runSlc` (CLI-20). `--config` is a bin-level flag, so it is
|
|
132
|
+
* removed before the grammar parser, which rejects unknown options.
|
|
133
|
+
*
|
|
134
|
+
* @throws {Error} when `--config` is given without a following value.
|
|
135
|
+
*/
|
|
136
|
+
function extractConfigFlag(argv) {
|
|
137
|
+
const rest = [];
|
|
138
|
+
let configPath;
|
|
139
|
+
for (let i = 0; i < argv.length; i++) {
|
|
140
|
+
if (argv[i] === '--config') {
|
|
141
|
+
const value = argv[++i];
|
|
142
|
+
if (value === undefined) {
|
|
143
|
+
throw new Error('missing value for --config <path>');
|
|
144
|
+
}
|
|
145
|
+
configPath = value;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
rest.push(argv[i]);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return { configPath, rest };
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Runs the `slc` command line and returns a process exit code (CLI package).
|
|
155
|
+
* Never rejects: configuration refusals and run failures are reported and
|
|
156
|
+
* mapped to a non-zero code.
|
|
157
|
+
*/
|
|
158
|
+
export async function run(argv, options = {}) {
|
|
159
|
+
const stdout = options.stdout ?? ((text) => void process.stdout.write(text));
|
|
160
|
+
const stderr = options.stderr ?? ((text) => void process.stderr.write(text));
|
|
161
|
+
// Conveniences short-circuit before any pipeline or agent work (CLI-1, CLI-2, CLI-9).
|
|
162
|
+
if (hasFlag(argv, '--version', '-v')) {
|
|
163
|
+
stdout(`${name} ${version()}\n`);
|
|
164
|
+
return 0;
|
|
165
|
+
}
|
|
166
|
+
if (hasFlag(argv, '--help', '-h')) {
|
|
167
|
+
stdout(usageText());
|
|
168
|
+
return 0;
|
|
169
|
+
}
|
|
170
|
+
const env = options.env ?? process.env;
|
|
171
|
+
const cwd = options.cwd ?? process.cwd();
|
|
172
|
+
const signal = options.signal ?? new AbortController().signal;
|
|
173
|
+
let deps;
|
|
174
|
+
let rest;
|
|
175
|
+
try {
|
|
176
|
+
// `--config <path>` is a bin-level flag: strip it before runSlc, whose
|
|
177
|
+
// grammar (parseInvocation) rejects unknown options (CLI-20).
|
|
178
|
+
const extracted = extractConfigFlag(argv);
|
|
179
|
+
rest = extracted.rest;
|
|
180
|
+
deps = await (options.buildDeps ?? buildSlcDeps)({
|
|
181
|
+
env,
|
|
182
|
+
cwd,
|
|
183
|
+
signal,
|
|
184
|
+
configPath: extracted.configPath,
|
|
185
|
+
note: stderr,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
// Configuration refusals — a bad `--config`, an invalid config file
|
|
190
|
+
// (CLI-21), or an unset/unsupported agent (CLI-12) — fail the run.
|
|
191
|
+
stderr(`${name}: ${messageOf(error)}\n`);
|
|
192
|
+
return 1;
|
|
193
|
+
}
|
|
194
|
+
const result = await runSlc(rest, deps);
|
|
195
|
+
if (result.ok) {
|
|
196
|
+
if (result.outputs.length > 0)
|
|
197
|
+
stdout(`${result.outputs.join('\n')}\n`);
|
|
198
|
+
// Surface any ambiguity the agent resolved without polluting the path output.
|
|
199
|
+
if (result.diagnostics.length > 0)
|
|
200
|
+
stderr(`${result.diagnostics.join('\n')}\n`);
|
|
201
|
+
return 0;
|
|
202
|
+
}
|
|
203
|
+
if (result.diagnostics.length > 0)
|
|
204
|
+
stderr(`${result.diagnostics.join('\n')}\n`);
|
|
205
|
+
return 1;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Wires `SIGINT`/`SIGTERM` on `emitter` to abort a fresh controller, returning
|
|
209
|
+
* its cancellation signal and a disposer that removes the listeners (CLI-10).
|
|
210
|
+
* The `cli.ts` shim passes `process`; tests pass a fake emitter so the
|
|
211
|
+
* interrupt-to-abort wiring is exercised without real signals.
|
|
212
|
+
*/
|
|
213
|
+
export function interruptSignal(emitter) {
|
|
214
|
+
const controller = new AbortController();
|
|
215
|
+
const onInterrupt = () => controller.abort();
|
|
216
|
+
emitter.once('SIGINT', onInterrupt);
|
|
217
|
+
emitter.once('SIGTERM', onInterrupt);
|
|
218
|
+
return {
|
|
219
|
+
signal: controller.signal,
|
|
220
|
+
dispose: () => {
|
|
221
|
+
emitter.removeListener('SIGINT', onInterrupt);
|
|
222
|
+
emitter.removeListener('SIGTERM', onInterrupt);
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/** True when argv contains any of the given exact flag tokens. */
|
|
227
|
+
function hasFlag(argv, ...flags) {
|
|
228
|
+
return argv.some((arg) => flags.includes(arg));
|
|
229
|
+
}
|
|
230
|
+
function messageOf(error) {
|
|
231
|
+
return error instanceof Error ? error.message : String(error);
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=app.js.map
|
package/dist/app.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Phase } from './phase.js';
|
|
2
|
+
/** Machine-readable reason a source path was refused. */
|
|
3
|
+
export type SourceErrorCode = 'invalid-source-name';
|
|
4
|
+
/** Raised when a source filename matches no applicable form (PIPE-6). */
|
|
5
|
+
export declare class SourceError extends Error {
|
|
6
|
+
readonly code: SourceErrorCode;
|
|
7
|
+
constructor(code: SourceErrorCode, message: string);
|
|
8
|
+
}
|
|
9
|
+
/** A source filename decomposed into its basename, plus the raw-input marker. */
|
|
10
|
+
export interface ParsedSource {
|
|
11
|
+
/** Basename with any trailing `.<source-format>` and extension stripped. */
|
|
12
|
+
basename: string;
|
|
13
|
+
/**
|
|
14
|
+
* True when an entry source carries a foreign extension: a raw input whose
|
|
15
|
+
* compilation auto-schedules normalization (DR-014, PIPE-6, PIPE-34).
|
|
16
|
+
*/
|
|
17
|
+
raw: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Validates a source path against the consuming phase's source format and
|
|
21
|
+
* extension, returning its `<basename>` (PIPE-6).
|
|
22
|
+
*
|
|
23
|
+
* The non-entry form requires `<basename>.<source-format>.<ext>`; the entry form
|
|
24
|
+
* also accepts the plain `<basename>.<ext>`, and an entry source with any other
|
|
25
|
+
* extension is a raw input whose `<basename>` is the name minus its actual
|
|
26
|
+
* extension (DR-014).
|
|
27
|
+
*
|
|
28
|
+
* @throws {SourceError} when the name matches no applicable form.
|
|
29
|
+
*/
|
|
30
|
+
export declare function parseSource(opts: {
|
|
31
|
+
path: string;
|
|
32
|
+
sourceFormat: string;
|
|
33
|
+
ext: string;
|
|
34
|
+
entry: boolean;
|
|
35
|
+
}): ParsedSource;
|
|
36
|
+
/**
|
|
37
|
+
* Computes the artifact directory under the invocation working directory,
|
|
38
|
+
* reusing the working directory itself without nesting when its leaf is
|
|
39
|
+
* already the canonical `<basename>.<pipeline>` (PIPE-7, DR-014).
|
|
40
|
+
*/
|
|
41
|
+
export declare function artifactDir(cwd: string, basename: string, pipeline: string): string;
|
|
42
|
+
/** Computes the canonical path of a `<basename>.<format>.<ext>` artifact (PIPE-8). */
|
|
43
|
+
export declare function artifactPath(artDir: string, basename: string, format: string, ext: string): string;
|
|
44
|
+
/** A planned artifact: the phase that writes it, its path, and its pipeline role. */
|
|
45
|
+
export interface ArtifactPlan {
|
|
46
|
+
phase: Phase;
|
|
47
|
+
path: string;
|
|
48
|
+
role: 'intermediate' | 'output';
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Plans the target artifact each phase writes: every non-terminal phase writes a
|
|
52
|
+
* canonical intermediate, and the terminal phase writes the output, overridden by
|
|
53
|
+
* `output` (`-o`) when provided while intermediates stay canonical (PIPE-8).
|
|
54
|
+
*/
|
|
55
|
+
export declare function planArtifacts(opts: {
|
|
56
|
+
phases: readonly Phase[];
|
|
57
|
+
basename: string;
|
|
58
|
+
artDir: string;
|
|
59
|
+
output?: string;
|
|
60
|
+
}): ArtifactPlan[];
|
|
61
|
+
//# sourceMappingURL=artifacts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,yDAAyD;AACzD,MAAM,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAEpD,yEAAyE;AACzE,qBAAa,WAAY,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;gBAEnB,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM;CAKnD;AAED,iFAAiF;AACjF,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,GAAG,EAAE,OAAO,CAAC;CACd;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,YAAY,CA4Cf;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,MAAM,CAMR;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,MAAM,CAER;AAED,qFAAqF;AACrF,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,cAAc,GAAG,QAAQ,CAAC;CACjC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,YAAY,EAAE,CAgBjB"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
3
|
+
/**
|
|
4
|
+
* Source-name validation and artifact-path computation (DR-001, DR-014).
|
|
5
|
+
*
|
|
6
|
+
* Implements PIPE-6 (the entry/non-entry source filename forms, with a
|
|
7
|
+
* foreign-extension entry source accepted as a raw input), PIPE-7 (compute the
|
|
8
|
+
* artifact directory under the invocation working directory, reusing it without
|
|
9
|
+
* nesting), and PIPE-8 (place intermediates and the output, honoring `-o`). See
|
|
10
|
+
* specs/dev/pipeline.md.
|
|
11
|
+
*/
|
|
12
|
+
import { basename as pathBasename, extname, join } from 'node:path';
|
|
13
|
+
/** Raised when a source filename matches no applicable form (PIPE-6). */
|
|
14
|
+
export class SourceError extends Error {
|
|
15
|
+
code;
|
|
16
|
+
constructor(code, message) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = 'SourceError';
|
|
19
|
+
this.code = code;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Validates a source path against the consuming phase's source format and
|
|
24
|
+
* extension, returning its `<basename>` (PIPE-6).
|
|
25
|
+
*
|
|
26
|
+
* The non-entry form requires `<basename>.<source-format>.<ext>`; the entry form
|
|
27
|
+
* also accepts the plain `<basename>.<ext>`, and an entry source with any other
|
|
28
|
+
* extension is a raw input whose `<basename>` is the name minus its actual
|
|
29
|
+
* extension (DR-014).
|
|
30
|
+
*
|
|
31
|
+
* @throws {SourceError} when the name matches no applicable form.
|
|
32
|
+
*/
|
|
33
|
+
export function parseSource(opts) {
|
|
34
|
+
const { path, sourceFormat, ext, entry } = opts;
|
|
35
|
+
const name = pathBasename(path);
|
|
36
|
+
if (!name.endsWith(ext)) {
|
|
37
|
+
if (entry) {
|
|
38
|
+
const actualExt = extname(name);
|
|
39
|
+
const basename = actualExt === '' ? name : name.slice(0, -actualExt.length);
|
|
40
|
+
if (basename.length === 0) {
|
|
41
|
+
throw new SourceError('invalid-source-name', `source "${name}" has an empty basename`);
|
|
42
|
+
}
|
|
43
|
+
return { basename, raw: true };
|
|
44
|
+
}
|
|
45
|
+
throw new SourceError('invalid-source-name', `source "${name}" must end with "${ext}"`);
|
|
46
|
+
}
|
|
47
|
+
const stem = name.slice(0, name.length - ext.length);
|
|
48
|
+
const qualifier = `.${sourceFormat}`;
|
|
49
|
+
let basename;
|
|
50
|
+
if (stem.endsWith(qualifier)) {
|
|
51
|
+
basename = stem.slice(0, stem.length - qualifier.length);
|
|
52
|
+
}
|
|
53
|
+
else if (entry) {
|
|
54
|
+
basename = stem;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
throw new SourceError('invalid-source-name', `source "${name}" must be named "<basename>.${sourceFormat}${ext}"`);
|
|
58
|
+
}
|
|
59
|
+
if (basename.length === 0) {
|
|
60
|
+
throw new SourceError('invalid-source-name', `source "${name}" has an empty basename`);
|
|
61
|
+
}
|
|
62
|
+
return { basename, raw: false };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Computes the artifact directory under the invocation working directory,
|
|
66
|
+
* reusing the working directory itself without nesting when its leaf is
|
|
67
|
+
* already the canonical `<basename>.<pipeline>` (PIPE-7, DR-014).
|
|
68
|
+
*/
|
|
69
|
+
export function artifactDir(cwd, basename, pipeline) {
|
|
70
|
+
const canonicalLeaf = `${basename}.${pipeline}`;
|
|
71
|
+
if (pathBasename(cwd) === canonicalLeaf) {
|
|
72
|
+
return cwd;
|
|
73
|
+
}
|
|
74
|
+
return join(cwd, canonicalLeaf);
|
|
75
|
+
}
|
|
76
|
+
/** Computes the canonical path of a `<basename>.<format>.<ext>` artifact (PIPE-8). */
|
|
77
|
+
export function artifactPath(artDir, basename, format, ext) {
|
|
78
|
+
return join(artDir, `${basename}.${format}${ext}`);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Plans the target artifact each phase writes: every non-terminal phase writes a
|
|
82
|
+
* canonical intermediate, and the terminal phase writes the output, overridden by
|
|
83
|
+
* `output` (`-o`) when provided while intermediates stay canonical (PIPE-8).
|
|
84
|
+
*/
|
|
85
|
+
export function planArtifacts(opts) {
|
|
86
|
+
const { phases, basename, artDir, output } = opts;
|
|
87
|
+
return phases.map((phase, index) => {
|
|
88
|
+
const isTerminal = index === phases.length - 1;
|
|
89
|
+
const canonical = artifactPath(artDir, basename, phase.target.format, phase.target.ext);
|
|
90
|
+
return {
|
|
91
|
+
phase,
|
|
92
|
+
role: isTerminal ? 'output' : 'intermediate',
|
|
93
|
+
path: isTerminal && output !== undefined ? output : canonical,
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,0EAA0E;AAE1E;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAOpE,yEAAyE;AACzE,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC3B,IAAI,CAAkB;IAE/B,YAAY,IAAqB,EAAE,OAAe;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAaD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,IAK3B;IACC,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IAChD,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAEhC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,QAAQ,GACZ,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YAC7D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,WAAW,CACnB,qBAAqB,EACrB,WAAW,IAAI,yBAAyB,CACzC,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QACjC,CAAC;QACD,MAAM,IAAI,WAAW,CACnB,qBAAqB,EACrB,WAAW,IAAI,oBAAoB,GAAG,GAAG,CAC1C,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,IAAI,YAAY,EAAE,CAAC;IACrC,IAAI,QAAgB,CAAC;IACrB,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC3D,CAAC;SAAM,IAAI,KAAK,EAAE,CAAC;QACjB,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,WAAW,CACnB,qBAAqB,EACrB,WAAW,IAAI,+BAA+B,YAAY,GAAG,GAAG,GAAG,CACpE,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,WAAW,CACnB,qBAAqB,EACrB,WAAW,IAAI,yBAAyB,CACzC,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,GAAW,EACX,QAAgB,EAChB,QAAgB;IAEhB,MAAM,aAAa,GAAG,GAAG,QAAQ,IAAI,QAAQ,EAAE,CAAC;IAChD,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,aAAa,EAAE,CAAC;QACxC,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;AAClC,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,QAAgB,EAChB,MAAc,EACd,GAAW;IAEX,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC;AACrD,CAAC;AASD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAK7B;IACC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAClD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACjC,MAAM,UAAU,GAAG,KAAK,KAAK,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAC/C,MAAM,SAAS,GAAG,YAAY,CAC5B,MAAM,EACN,QAAQ,EACR,KAAK,CAAC,MAAM,CAAC,MAAM,EACnB,KAAK,CAAC,MAAM,CAAC,GAAG,CACjB,CAAC;QACF,OAAO;YACL,KAAK;YACL,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc;YAC5C,IAAI,EAAE,UAAU,IAAI,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;SAC9D,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
4
|
+
/**
|
|
5
|
+
* The published `slc` executable shim (CLI package).
|
|
6
|
+
*
|
|
7
|
+
* It supplies the process-backed defaults `run` falls back to and wires
|
|
8
|
+
* cancellation through `interruptSignal`: an interrupt aborts the in-flight run
|
|
9
|
+
* via the signal passed into `runSlc` (CLI-10), and the returned exit code
|
|
10
|
+
* becomes the process exit status (CLI-11). All behavior lives in the testable
|
|
11
|
+
* `run`/`interruptSignal`; see app.ts.
|
|
12
|
+
*/
|
|
13
|
+
import { interruptSignal, run } from './index.js';
|
|
14
|
+
const { signal, dispose } = interruptSignal(process);
|
|
15
|
+
run(process.argv.slice(2), { signal })
|
|
16
|
+
.then((code) => {
|
|
17
|
+
dispose();
|
|
18
|
+
process.exit(code);
|
|
19
|
+
})
|
|
20
|
+
.catch((error) => {
|
|
21
|
+
dispose();
|
|
22
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
23
|
+
process.stderr.write(`slc: ${message}\n`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,sCAAsC;AACtC,0EAA0E;AAE1E;;;;;;;;GAQG;AAEH,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;AAErD,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC;KACnC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;IACb,OAAO,EAAE,CAAC;IACV,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC,CAAC;KACD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IACxB,OAAO,EAAE,CAAC;IACV,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,OAAO,IAAI,CAAC,CAAC;IAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AgentAdapter, PermissionPolicy } from '@sublang/cligent';
|
|
2
|
+
import type { AgentClient } from './interpreter.js';
|
|
3
|
+
/** Wraps a Cligent adapter as an {@link AgentClient} for the interpreter. */
|
|
4
|
+
export declare function createCligentAgent(opts: {
|
|
5
|
+
adapter: AgentAdapter;
|
|
6
|
+
maxTurns?: number;
|
|
7
|
+
permissions?: PermissionPolicy;
|
|
8
|
+
/** Adapter-scoped reasoning effort, validated by the configuration layer. */
|
|
9
|
+
effort?: string;
|
|
10
|
+
}): AgentClient;
|
|
11
|
+
//# sourceMappingURL=cligent-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cligent-agent.d.ts","sourceRoot":"","sources":["../src/cligent-agent.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,YAAY,EAGZ,gBAAgB,EACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,kBAAkB,CAAC;AAEpE,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,WAAW,CAwDd"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
3
|
+
/**
|
|
4
|
+
* Cligent-backed {@link AgentClient} (DR-004).
|
|
5
|
+
*
|
|
6
|
+
* Backs the interpreter's agent transport with Cligent (npm `@sublang/cligent`),
|
|
7
|
+
* draining its event stream into a normalized {@link AgentRunResult}. The host
|
|
8
|
+
* supplies the concrete `AgentAdapter` (e.g. Claude Code, Codex) and any write
|
|
9
|
+
* permissions, keeping agent selection a configuration concern (PHEXEC-13); the
|
|
10
|
+
* DR-003 write-scope sandbox would be configured here via `permissions`. This
|
|
11
|
+
* transport is exercised by integration runs, not unit tests, since it drives a
|
|
12
|
+
* real agent CLI. See specs/dev/phase-execution.md.
|
|
13
|
+
*/
|
|
14
|
+
import { Cligent } from '@sublang/cligent';
|
|
15
|
+
/** Wraps a Cligent adapter as an {@link AgentClient} for the interpreter. */
|
|
16
|
+
export function createCligentAgent(opts) {
|
|
17
|
+
const cligent = new Cligent(opts.adapter, {
|
|
18
|
+
maxTurns: opts.maxTurns,
|
|
19
|
+
permissions: opts.permissions,
|
|
20
|
+
// Validated adapter-scoped by the configuration layer (CLI-12).
|
|
21
|
+
...(opts.effort !== undefined ? { effort: opts.effort } : {}),
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
async run({ prompt, cwd, model, resume, allowedTools, signal, }) {
|
|
25
|
+
const texts = [];
|
|
26
|
+
let resultText = '';
|
|
27
|
+
let status = 'incomplete';
|
|
28
|
+
let resumeToken;
|
|
29
|
+
for await (const raw of cligent.run(prompt, {
|
|
30
|
+
abortSignal: signal,
|
|
31
|
+
cwd,
|
|
32
|
+
model,
|
|
33
|
+
...(resume !== undefined ? { resume } : {}),
|
|
34
|
+
...(allowedTools !== undefined
|
|
35
|
+
? { allowedTools: [...allowedTools] }
|
|
36
|
+
: {}),
|
|
37
|
+
})) {
|
|
38
|
+
const event = raw;
|
|
39
|
+
if (event.type === 'text') {
|
|
40
|
+
texts.push(event.payload.content);
|
|
41
|
+
}
|
|
42
|
+
else if (event.type === 'error') {
|
|
43
|
+
status = 'error';
|
|
44
|
+
texts.push(event.payload.message);
|
|
45
|
+
}
|
|
46
|
+
else if (event.type === 'done') {
|
|
47
|
+
status =
|
|
48
|
+
event.payload.status === 'success'
|
|
49
|
+
? 'success'
|
|
50
|
+
: event.payload.status === 'error'
|
|
51
|
+
? 'error'
|
|
52
|
+
: 'incomplete';
|
|
53
|
+
if (event.payload.result)
|
|
54
|
+
resultText = event.payload.result;
|
|
55
|
+
resumeToken = event.payload.resumeToken;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
status,
|
|
60
|
+
text: (resultText || texts.join('\n')).trim(),
|
|
61
|
+
...(resumeToken !== undefined ? { resumeToken } : {}),
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=cligent-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cligent-agent.js","sourceRoot":"","sources":["../src/cligent-agent.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,0EAA0E;AAE1E;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAU3C,6EAA6E;AAC7E,MAAM,UAAU,kBAAkB,CAAC,IAMlC;IACC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE;QACxC,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,gEAAgE;QAChE,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxE,CAAC,CAAC;IAEH,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,EACR,MAAM,EACN,GAAG,EACH,KAAK,EACL,MAAM,EACN,YAAY,EACZ,MAAM,GACP;YACC,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,IAAI,UAAU,GAAG,EAAE,CAAC;YACpB,IAAI,MAAM,GAA6B,YAAY,CAAC;YACpD,IAAI,WAA+B,CAAC;YAEpC,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE;gBAC1C,WAAW,EAAE,MAAM;gBACnB,GAAG;gBACH,KAAK;gBACL,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3C,GAAG,CAAC,YAAY,KAAK,SAAS;oBAC5B,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,YAAY,CAAC,EAAE;oBACrC,CAAC,CAAC,EAAE,CAAC;aACR,CAAC,EAAE,CAAC;gBACH,MAAM,KAAK,GAAe,GAAG,CAAC;gBAC9B,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBAC1B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACpC,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBAClC,MAAM,GAAG,OAAO,CAAC;oBACjB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACpC,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBACjC,MAAM;wBACJ,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS;4BAChC,CAAC,CAAC,SAAS;4BACX,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,OAAO;gCAChC,CAAC,CAAC,OAAO;gCACT,CAAC,CAAC,YAAY,CAAC;oBACrB,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM;wBAAE,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;oBAC5D,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;gBAC1C,CAAC;YACH,CAAC;YAED,OAAO;gBACL,MAAM;gBACN,IAAI,EAAE,CAAC,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;gBAC7C,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtD,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { PhaseExecutor } from './execution.js';
|
|
2
|
+
import type { AgentClient } from './interpreter.js';
|
|
3
|
+
import { type CompatiblePlaybookRuntimeFactory, type RuntimeContractProfile } from './playbook-contract.js';
|
|
4
|
+
import { type PlayerTransport } from './playbook-ports.js';
|
|
5
|
+
/**
|
|
6
|
+
* Imports a compiled `playbook` module and returns its runtime factory
|
|
7
|
+
* (PHEXEC-23).
|
|
8
|
+
*
|
|
9
|
+
* @throws when the module has no callable `createPlaybookRuntime` default export.
|
|
10
|
+
*/
|
|
11
|
+
export declare function loadPlaybookRuntime(artifactPath: string): Promise<CompatiblePlaybookRuntimeFactory>;
|
|
12
|
+
/**
|
|
13
|
+
* Adapts a compiled `playbook` artifact to the {@link PhaseExecutor} boundary
|
|
14
|
+
* (PHEXEC-24, PHEXEC-25): build the Cligent-backed Playbook ports, load and
|
|
15
|
+
* construct the runtime, drive one non-interactive root-session turn, and map
|
|
16
|
+
* the outcome, appending drained status and non-trace operational telemetry.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createCompiledExecutor(opts: {
|
|
19
|
+
/** Path to the compiled `playbook` module to load. */
|
|
20
|
+
artifactPath: string;
|
|
21
|
+
/** Run root for resolving the phase's workspace paths to absolute host paths. */
|
|
22
|
+
runRoot: string;
|
|
23
|
+
/** Agent transport(s) backing `callPlayer`; a factory yields one client per player id. */
|
|
24
|
+
player: PlayerTransport;
|
|
25
|
+
/** Shared agent transport backing `callCaptain` and `callJudge`. */
|
|
26
|
+
judge: AgentClient;
|
|
27
|
+
/** Per-player model binding, applied as configuration (PHEXEC-13). */
|
|
28
|
+
models?: Readonly<Record<string, string>>;
|
|
29
|
+
/** Model for players the `models` binding does not name (PHEXEC-13). */
|
|
30
|
+
defaultModel?: string;
|
|
31
|
+
/** Working directory handed to the agent transports. */
|
|
32
|
+
cwd?: string;
|
|
33
|
+
/** Stable authored phase identity used as the Playbook session's playbook id. */
|
|
34
|
+
playbookId?: string;
|
|
35
|
+
/** Session-id seam for deterministic tests; defaults to {@link randomUUID}. */
|
|
36
|
+
createSessionId?: () => string;
|
|
37
|
+
/** Exact pinned runtime boundary; defaults to the current legacy contract. */
|
|
38
|
+
runtimeContract?: RuntimeContractProfile;
|
|
39
|
+
/** Loader seam; defaults to {@link loadPlaybookRuntime}. */
|
|
40
|
+
loadFactory?: (artifactPath: string) => Promise<CompatiblePlaybookRuntimeFactory>;
|
|
41
|
+
}): PhaseExecutor;
|
|
42
|
+
//# sourceMappingURL=compiled-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compiled-executor.d.ts","sourceRoot":"","sources":["../src/compiled-executor.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAIV,aAAa,EACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAOpD,OAAO,EAKL,KAAK,gCAAgC,EAKrC,KAAK,sBAAsB,EAE5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEhF;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,gCAAgC,CAAC,CAW3C;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,sDAAsD;IACtD,YAAY,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,0FAA0F;IAC1F,MAAM,EAAE,eAAe,CAAC;IACxB,oEAAoE;IACpE,KAAK,EAAE,WAAW,CAAC;IACnB,sEAAsE;IACtE,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1C,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,eAAe,CAAC,EAAE,MAAM,MAAM,CAAC;IAC/B,8EAA8E;IAC9E,eAAe,CAAC,EAAE,sBAAsB,CAAC;IACzC,4DAA4D;IAC5D,WAAW,CAAC,EAAE,CACZ,YAAY,EAAE,MAAM,KACjB,OAAO,CAAC,gCAAgC,CAAC,CAAC;CAChD,GAAG,aAAa,CA+DhB"}
|