runling 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +63 -0
- package/bin/runling.js +26 -0
- package/bin/workflow-loader.js +10 -0
- package/dist/extensions/web-fetch.d.ts +8 -0
- package/dist/extensions/web-fetch.js +245 -0
- package/dist/src/agent.d.ts +78 -0
- package/dist/src/agent.js +450 -0
- package/dist/src/ansi.d.ts +1 -0
- package/dist/src/ansi.js +9 -0
- package/dist/src/cli.d.ts +8 -0
- package/dist/src/cli.js +46 -0
- package/dist/src/config-reloader.d.ts +20 -0
- package/dist/src/config-reloader.js +110 -0
- package/dist/src/events.d.ts +82 -0
- package/dist/src/events.js +21 -0
- package/dist/src/git.d.ts +9 -0
- package/dist/src/git.js +82 -0
- package/dist/src/id.d.ts +1 -0
- package/dist/src/id.js +7 -0
- package/dist/src/index.d.ts +15 -0
- package/dist/src/index.js +14 -0
- package/dist/src/input.d.ts +14 -0
- package/dist/src/input.js +49 -0
- package/dist/src/log.d.ts +35 -0
- package/dist/src/log.js +92 -0
- package/dist/src/markdown.d.ts +2 -0
- package/dist/src/markdown.js +32 -0
- package/dist/src/model.d.ts +5 -0
- package/dist/src/model.js +10 -0
- package/dist/src/paths.d.ts +10 -0
- package/dist/src/paths.js +18 -0
- package/dist/src/runner.d.ts +43 -0
- package/dist/src/runner.js +200 -0
- package/dist/src/runtime.d.ts +62 -0
- package/dist/src/runtime.js +44 -0
- package/dist/src/schema.d.ts +3 -0
- package/dist/src/schema.js +17 -0
- package/dist/src/shell.d.ts +47 -0
- package/dist/src/shell.js +170 -0
- package/dist/src/step.d.ts +5 -0
- package/dist/src/step.js +39 -0
- package/dist/src/system-prompt.d.ts +2 -0
- package/dist/src/system-prompt.js +23 -0
- package/dist/src/text.d.ts +2 -0
- package/dist/src/text.js +6 -0
- package/dist/src/tui.d.ts +46 -0
- package/dist/src/tui.js +477 -0
- package/dist/src/usage.d.ts +35 -0
- package/dist/src/usage.js +90 -0
- package/dist/src/utils.d.ts +2 -0
- package/dist/src/utils.js +16 -0
- package/dist/src/web-config.d.ts +16 -0
- package/dist/src/web-config.js +22 -0
- package/dist/src/web-server.d.ts +8 -0
- package/dist/src/web-server.js +91 -0
- package/dist/src/workflow.d.ts +11 -0
- package/dist/src/workflow.js +39 -0
- package/dist/web/client/_app/immutable/assets/0.DkxYLsNr.css +1 -0
- package/dist/web/client/_app/immutable/assets/0.DkxYLsNr.css.br +0 -0
- package/dist/web/client/_app/immutable/assets/0.DkxYLsNr.css.gz +0 -0
- package/dist/web/client/_app/immutable/assets/2.D0D6RatL.css +1 -0
- package/dist/web/client/_app/immutable/assets/2.D0D6RatL.css.br +0 -0
- package/dist/web/client/_app/immutable/assets/2.D0D6RatL.css.gz +0 -0
- package/dist/web/client/_app/immutable/assets/plus-jakarta-sans-latin-ext-wght-italic.DJWiFoht.woff2 +0 -0
- package/dist/web/client/_app/immutable/assets/plus-jakarta-sans-latin-ext-wght-normal.DmpS2jIq.woff2 +0 -0
- package/dist/web/client/_app/immutable/assets/plus-jakarta-sans-latin-wght-italic.DnD1KgkH.woff2 +0 -0
- package/dist/web/client/_app/immutable/assets/plus-jakarta-sans-latin-wght-normal.eXO_dkmS.woff2 +0 -0
- package/dist/web/client/_app/immutable/assets/plus-jakarta-sans-vietnamese-wght-italic.CPBsCcxN.woff2 +0 -0
- package/dist/web/client/_app/immutable/assets/plus-jakarta-sans-vietnamese-wght-normal.qRpaaN48.woff2 +0 -0
- package/dist/web/client/_app/immutable/chunks/DVu8M-Ny.js +1 -0
- package/dist/web/client/_app/immutable/chunks/DVu8M-Ny.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/DVu8M-Ny.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/DZ8VO57n.js +2 -0
- package/dist/web/client/_app/immutable/chunks/DZ8VO57n.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/DZ8VO57n.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/DcSF4jBT.js +2 -0
- package/dist/web/client/_app/immutable/chunks/DcSF4jBT.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/DcSF4jBT.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/DhqrxzQW.js +1 -0
- package/dist/web/client/_app/immutable/chunks/DhqrxzQW.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/DhqrxzQW.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/DqKc9n9r.js +1 -0
- package/dist/web/client/_app/immutable/chunks/DqKc9n9r.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/DqKc9n9r.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/EYhLy6Dm.js +1 -0
- package/dist/web/client/_app/immutable/chunks/EYhLy6Dm.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/EYhLy6Dm.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/Jt-Bo-2J.js +1 -0
- package/dist/web/client/_app/immutable/chunks/Jt-Bo-2J.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/Jt-Bo-2J.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/N_quh2N-.js +1 -0
- package/dist/web/client/_app/immutable/chunks/N_quh2N-.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/N_quh2N-.js.gz +0 -0
- package/dist/web/client/_app/immutable/chunks/wbPk3Yxo.js +81 -0
- package/dist/web/client/_app/immutable/chunks/wbPk3Yxo.js.br +0 -0
- package/dist/web/client/_app/immutable/chunks/wbPk3Yxo.js.gz +0 -0
- package/dist/web/client/_app/immutable/entry/app.YNAAR_x0.js +2 -0
- package/dist/web/client/_app/immutable/entry/app.YNAAR_x0.js.br +0 -0
- package/dist/web/client/_app/immutable/entry/app.YNAAR_x0.js.gz +0 -0
- package/dist/web/client/_app/immutable/entry/start.BQmDILhe.js +1 -0
- package/dist/web/client/_app/immutable/entry/start.BQmDILhe.js.br +0 -0
- package/dist/web/client/_app/immutable/entry/start.BQmDILhe.js.gz +0 -0
- package/dist/web/client/_app/immutable/nodes/0.DNWnBVC3.js +1 -0
- package/dist/web/client/_app/immutable/nodes/0.DNWnBVC3.js.br +0 -0
- package/dist/web/client/_app/immutable/nodes/0.DNWnBVC3.js.gz +0 -0
- package/dist/web/client/_app/immutable/nodes/1.CZEgzXeT.js +1 -0
- package/dist/web/client/_app/immutable/nodes/1.CZEgzXeT.js.br +0 -0
- package/dist/web/client/_app/immutable/nodes/1.CZEgzXeT.js.gz +0 -0
- package/dist/web/client/_app/immutable/nodes/2.BSE8F3Ef.js +19 -0
- package/dist/web/client/_app/immutable/nodes/2.BSE8F3Ef.js.br +0 -0
- package/dist/web/client/_app/immutable/nodes/2.BSE8F3Ef.js.gz +0 -0
- package/dist/web/client/_app/version.json +1 -0
- package/dist/web/client/_app/version.json.br +0 -0
- package/dist/web/client/_app/version.json.gz +0 -0
- package/dist/web/env.js +70 -0
- package/dist/web/env.js.map +1 -0
- package/dist/web/handler.js +23 -0
- package/dist/web/handler.js.map +1 -0
- package/dist/web/index.js +146 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/server/chunks/chunks/exports.js-BZBK1HC9.js +161 -0
- package/dist/web/server/chunks/chunks/exports.js-BZBK1HC9.js.map +1 -0
- package/dist/web/server/chunks/chunks/internal.js-pcXelyRW.js +126 -0
- package/dist/web/server/chunks/chunks/internal.js-pcXelyRW.js.map +1 -0
- package/dist/web/server/chunks/chunks/root.js-HNgH7zyW.js +4349 -0
- package/dist/web/server/chunks/chunks/root.js-HNgH7zyW.js.map +1 -0
- package/dist/web/server/chunks/chunks/run-store.js-Dgbf5-M9.js +174 -0
- package/dist/web/server/chunks/chunks/run-store.js-Dgbf5-M9.js.map +1 -0
- package/dist/web/server/chunks/chunks/runs.js-vPPJr_ta.js +20 -0
- package/dist/web/server/chunks/chunks/runs.js-vPPJr_ta.js.map +1 -0
- package/dist/web/server/chunks/chunks/server.js-Bf8x1V_n.js +16 -0
- package/dist/web/server/chunks/chunks/server.js-Bf8x1V_n.js.map +1 -0
- package/dist/web/server/chunks/chunks/state.svelte.js-lAA5-aPf.js +12 -0
- package/dist/web/server/chunks/chunks/state.svelte.js-lAA5-aPf.js.map +1 -0
- package/dist/web/server/chunks/chunks/stream.js-CHB18nO5.js +51 -0
- package/dist/web/server/chunks/chunks/stream.js-CHB18nO5.js.map +1 -0
- package/dist/web/server/chunks/chunks/uneval.js-5Y6J9rDU.js +530 -0
- package/dist/web/server/chunks/chunks/uneval.js-5Y6J9rDU.js.map +1 -0
- package/dist/web/server/chunks/chunks/utils.js-BQzn9ikS.js +38 -0
- package/dist/web/server/chunks/chunks/utils.js-BQzn9ikS.js.map +1 -0
- package/dist/web/server/chunks/chunks/utils2.js-CPBdgO4h.js +1627 -0
- package/dist/web/server/chunks/chunks/utils2.js-CPBdgO4h.js.map +1 -0
- package/dist/web/server/chunks/chunks/web-config.js-CAwLL_g4.js +12 -0
- package/dist/web/server/chunks/chunks/web-config.js-CAwLL_g4.js.map +1 -0
- package/dist/web/server/chunks/chunks/webhook.js-nEb5r1eG.js +62 -0
- package/dist/web/server/chunks/chunks/webhook.js-nEb5r1eG.js.map +1 -0
- package/dist/web/server/chunks/entries/endpoints/api/config/events/_server.ts.js-DwgI16MG.js +20 -0
- package/dist/web/server/chunks/entries/endpoints/api/config/events/_server.ts.js-DwgI16MG.js.map +1 -0
- package/dist/web/server/chunks/entries/endpoints/api/runs/_id_/_server.ts.js-BSKmJv3K.js +14 -0
- package/dist/web/server/chunks/entries/endpoints/api/runs/_id_/_server.ts.js-BSKmJv3K.js.map +1 -0
- package/dist/web/server/chunks/entries/endpoints/api/runs/_id_/events/_server.ts.js-CWWee51l.js +23 -0
- package/dist/web/server/chunks/entries/endpoints/api/runs/_id_/events/_server.ts.js-CWWee51l.js.map +1 -0
- package/dist/web/server/chunks/entries/endpoints/api/runs/events/_server.ts.js-CY2mz9bH.js +28 -0
- package/dist/web/server/chunks/entries/endpoints/api/runs/events/_server.ts.js-CY2mz9bH.js.map +1 -0
- package/dist/web/server/chunks/entries/endpoints/api/runs/start/_name_/_server.ts.js-CD4RKiK6.js +30 -0
- package/dist/web/server/chunks/entries/endpoints/api/runs/start/_name_/_server.ts.js-CD4RKiK6.js.map +1 -0
- package/dist/web/server/chunks/entries/endpoints/api/webhooks/_name_/_server.ts.js-Dgh42cDJ.js +28 -0
- package/dist/web/server/chunks/entries/endpoints/api/webhooks/_name_/_server.ts.js-Dgh42cDJ.js.map +1 -0
- package/dist/web/server/chunks/entries/fallbacks/error.svelte.js-LEaHcOM2.js +27 -0
- package/dist/web/server/chunks/entries/fallbacks/error.svelte.js-LEaHcOM2.js.map +1 -0
- package/dist/web/server/chunks/entries/pages/_layout.svelte.js-D_wzPsk8.js +8 -0
- package/dist/web/server/chunks/entries/pages/_layout.svelte.js-D_wzPsk8.js.map +1 -0
- package/dist/web/server/chunks/entries/pages/_page.server.ts.js-oVQ0hBaN.js +27 -0
- package/dist/web/server/chunks/entries/pages/_page.server.ts.js-oVQ0hBaN.js.map +1 -0
- package/dist/web/server/chunks/entries/pages/_page.svelte.js-B7fSvh9U.js +141 -0
- package/dist/web/server/chunks/entries/pages/_page.svelte.js-B7fSvh9U.js.map +1 -0
- package/dist/web/server/chunks/handler-BpKA6eGq.js +1734 -0
- package/dist/web/server/chunks/handler-BpKA6eGq.js.map +1 -0
- package/dist/web/server/chunks/index.js-CVS44OGr.js +4157 -0
- package/dist/web/server/chunks/index.js-CVS44OGr.js.map +1 -0
- package/dist/web/server/chunks/manifest.js-CnB5rB3W.js +84 -0
- package/dist/web/server/chunks/manifest.js-CnB5rB3W.js.map +1 -0
- package/dist/web/server/chunks/nodes/0.js-BqA14fLU.js +9 -0
- package/dist/web/server/chunks/nodes/0.js-BqA14fLU.js.map +1 -0
- package/dist/web/server/chunks/nodes/1.js-DzvhRJCS.js +9 -0
- package/dist/web/server/chunks/nodes/1.js-DzvhRJCS.js.map +1 -0
- package/dist/web/server/chunks/nodes/2.js-DmujW_AW.js +20 -0
- package/dist/web/server/chunks/nodes/2.js-DmujW_AW.js.map +1 -0
- package/dist/web/shims.js +33 -0
- package/dist/web/shims.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
import { resolve } from "node:path";
|
|
10
|
+
import { pathToFileURL } from "node:url";
|
|
11
|
+
import { cli } from "./cli.js";
|
|
12
|
+
import { observeRunlingEvents, } from "./events.js";
|
|
13
|
+
import { log } from "./log.js";
|
|
14
|
+
import { renderMarkdown } from "./markdown.js";
|
|
15
|
+
import { createRunling, } from "./runtime.js";
|
|
16
|
+
import { TuiReporter } from "./tui.js";
|
|
17
|
+
import { isWorkflow } from "./workflow.js";
|
|
18
|
+
import { formatTokenUsage, getRecordedTokenUsage, resetTokenUsage, totalTokens, withTokenUsage, } from "./usage.js";
|
|
19
|
+
export function formatDuration(ms) {
|
|
20
|
+
if (ms < 1000) {
|
|
21
|
+
return `${Math.round(ms)}ms`;
|
|
22
|
+
}
|
|
23
|
+
const tenths = Math.round(ms / 100);
|
|
24
|
+
if (tenths < 600) {
|
|
25
|
+
return `${(tenths / 10).toFixed(1)}s`;
|
|
26
|
+
}
|
|
27
|
+
// Round before splitting the duration so seconds cannot render as `60s`.
|
|
28
|
+
const totalSeconds = Math.round(ms / 1000);
|
|
29
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
30
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
31
|
+
const seconds = totalSeconds % 60;
|
|
32
|
+
const parts = [];
|
|
33
|
+
if (hours > 0)
|
|
34
|
+
parts.push(`${hours}h`);
|
|
35
|
+
if (minutes > 0)
|
|
36
|
+
parts.push(`${minutes}m`);
|
|
37
|
+
if (seconds > 0)
|
|
38
|
+
parts.push(`${seconds}s`);
|
|
39
|
+
return parts.join("") || "0s";
|
|
40
|
+
}
|
|
41
|
+
export function formatWorkflowDetails(details, terminal = process.stdout) {
|
|
42
|
+
return terminal.isTTY
|
|
43
|
+
? renderMarkdown(details, terminal.columns ?? 80)
|
|
44
|
+
: details;
|
|
45
|
+
}
|
|
46
|
+
function isJsonValue(value, ancestors = new Set()) {
|
|
47
|
+
if (value === null ||
|
|
48
|
+
typeof value === "string" ||
|
|
49
|
+
typeof value === "boolean") {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
if (typeof value === "number") {
|
|
53
|
+
return Number.isFinite(value);
|
|
54
|
+
}
|
|
55
|
+
if (typeof value !== "object" || ancestors.has(value)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const prototype = Object.getPrototypeOf(value);
|
|
59
|
+
if (!Array.isArray(value) &&
|
|
60
|
+
prototype !== Object.prototype &&
|
|
61
|
+
prototype !== null) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
ancestors.add(value);
|
|
65
|
+
// JSON omits undefined object properties. Array entries must remain valid values.
|
|
66
|
+
const valid = Object.values(value).every((entry) => (entry === undefined && !Array.isArray(value)) || isJsonValue(entry, ancestors));
|
|
67
|
+
ancestors.delete(value);
|
|
68
|
+
return valid;
|
|
69
|
+
}
|
|
70
|
+
export function normalizeWorkflowResult(value) {
|
|
71
|
+
if (value === undefined) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
if (!isJsonValue(value)) {
|
|
75
|
+
throw new Error("Workflow output must be valid JSON");
|
|
76
|
+
}
|
|
77
|
+
if (typeof value === "string") {
|
|
78
|
+
return { summary: value };
|
|
79
|
+
}
|
|
80
|
+
if (typeof value === "object" && value !== null) {
|
|
81
|
+
const candidate = value;
|
|
82
|
+
if (typeof candidate.summary === "string" &&
|
|
83
|
+
(candidate.details === undefined ||
|
|
84
|
+
typeof candidate.details === "string") &&
|
|
85
|
+
(candidate.outputs === undefined ||
|
|
86
|
+
(isJsonValue(candidate.outputs) && !Array.isArray(candidate.outputs)))) {
|
|
87
|
+
return candidate;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { summary: "Workflow completed", outputs: { value } };
|
|
91
|
+
}
|
|
92
|
+
export async function executeWorkflow(run, f, options = {}) {
|
|
93
|
+
return reportExecution(() => log.indented(() => run(f)), options);
|
|
94
|
+
}
|
|
95
|
+
/** Run a workflow without assuming a terminal, printing, or changing process state. */
|
|
96
|
+
export async function runWorkflow(run, { cwd = process.cwd(), input, verbose = false, onInput, onEvent = () => { }, }) {
|
|
97
|
+
const f = createRunling({
|
|
98
|
+
cwd,
|
|
99
|
+
prompt: typeof input === "string" ? input : "",
|
|
100
|
+
verbose,
|
|
101
|
+
handleInput: onInput,
|
|
102
|
+
});
|
|
103
|
+
return observeRunlingEvents(onEvent, () => log.withDestination("silent", () => captureExecution(() => log.indented(() => run(f, input)))));
|
|
104
|
+
}
|
|
105
|
+
async function reportExecution(run, { json = false, presentation = "log", terminal = process.stdout, title = "Workflow", } = {}) {
|
|
106
|
+
const reporter = presentation === "tui" ? new TuiReporter(title) : undefined;
|
|
107
|
+
try {
|
|
108
|
+
reporter?.start();
|
|
109
|
+
const execution = await observeRunlingEvents(reporter?.handle ?? (() => { }), () => log.withDestination(presentation === "tui" ? "silent" : json ? "stderr" : "stdout", async () => {
|
|
110
|
+
if (presentation === "log")
|
|
111
|
+
log.info("Runling starting");
|
|
112
|
+
const execution = await captureExecution(() => run({ handleInput: reporter?.input }));
|
|
113
|
+
if (execution.error !== null) {
|
|
114
|
+
log.error(execution.error);
|
|
115
|
+
process.exitCode = 1;
|
|
116
|
+
}
|
|
117
|
+
else if (!json && execution.result !== null) {
|
|
118
|
+
if (presentation === "log") {
|
|
119
|
+
log.success(execution.result.summary);
|
|
120
|
+
if (execution.result.details !== undefined) {
|
|
121
|
+
console.log(`\n${formatWorkflowDetails(execution.result.details, terminal)}\n`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (presentation === "log" && totalTokens(execution.usage) > 0) {
|
|
126
|
+
log.info(`Total token usage: ${formatTokenUsage(execution.usage)}`);
|
|
127
|
+
}
|
|
128
|
+
if (presentation === "log") {
|
|
129
|
+
log.info(`Finished in ${formatDuration(execution.durationMs)}`);
|
|
130
|
+
}
|
|
131
|
+
return execution;
|
|
132
|
+
}));
|
|
133
|
+
reporter?.finish(execution);
|
|
134
|
+
if (json)
|
|
135
|
+
console.log(JSON.stringify(execution));
|
|
136
|
+
return execution;
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
reporter?.stop();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async function captureExecution(run) {
|
|
143
|
+
return withTokenUsage(() => captureExecutionInContext(run));
|
|
144
|
+
}
|
|
145
|
+
async function captureExecutionInContext(run) {
|
|
146
|
+
resetTokenUsage();
|
|
147
|
+
const start = performance.now();
|
|
148
|
+
let result = null;
|
|
149
|
+
let output = null;
|
|
150
|
+
let error = null;
|
|
151
|
+
try {
|
|
152
|
+
const value = await run();
|
|
153
|
+
result = normalizeWorkflowResult(value);
|
|
154
|
+
output = value ?? null;
|
|
155
|
+
}
|
|
156
|
+
catch (cause) {
|
|
157
|
+
error = cause instanceof Error ? cause.message : String(cause);
|
|
158
|
+
}
|
|
159
|
+
const usage = getRecordedTokenUsage();
|
|
160
|
+
const durationMs = performance.now() - start;
|
|
161
|
+
return {
|
|
162
|
+
durationMs,
|
|
163
|
+
usage,
|
|
164
|
+
output,
|
|
165
|
+
result,
|
|
166
|
+
error,
|
|
167
|
+
ok: error === null,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
export async function loadWorkflow(path) {
|
|
171
|
+
const resolvedPath = resolve(path);
|
|
172
|
+
const module = await import(__rewriteRelativeImportExtension(/* @vite-ignore */ pathToFileURL(resolvedPath).href));
|
|
173
|
+
if (!isWorkflow(module.default)) {
|
|
174
|
+
throw new Error(`Workflow ${resolvedPath} must have a schemaful default workflow export`);
|
|
175
|
+
}
|
|
176
|
+
return module.default;
|
|
177
|
+
}
|
|
178
|
+
export async function runRunling(argv = process.argv.slice(2)) {
|
|
179
|
+
const json = argv.includes("--json");
|
|
180
|
+
const presentation = shouldUseTui(argv) ? "tui" : "log";
|
|
181
|
+
const title = argv.find((argument) => !argument.startsWith("-")) ?? "Workflow";
|
|
182
|
+
await reportExecution(async ({ handleInput }) => {
|
|
183
|
+
const { workflowPath, prompt, verbose } = cli(argv, "runling");
|
|
184
|
+
const cwd = process.cwd();
|
|
185
|
+
const run = await loadWorkflow(workflowPath);
|
|
186
|
+
const f = createRunling({ cwd, prompt, verbose, handleInput });
|
|
187
|
+
return log.indented(() => run(f, prompt));
|
|
188
|
+
}, { json, presentation, title });
|
|
189
|
+
}
|
|
190
|
+
export function shouldUseTui(argv, terminal = {
|
|
191
|
+
stdinIsTTY: process.stdin.isTTY,
|
|
192
|
+
stdoutIsTTY: process.stdout.isTTY,
|
|
193
|
+
}) {
|
|
194
|
+
return (terminal.stdinIsTTY === true &&
|
|
195
|
+
terminal.stdoutIsTTY === true &&
|
|
196
|
+
!argv.includes("--json") &&
|
|
197
|
+
!argv.includes("--log") &&
|
|
198
|
+
!argv.includes("--verbose") &&
|
|
199
|
+
!argv.includes("-v"));
|
|
200
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { AgentOutcomeError, type AgentOptions, type RunAgentOptions } from "./agent.ts";
|
|
2
|
+
import { randomId } from "./id.ts";
|
|
3
|
+
import { type Input, type InputHandler } from "./input.ts";
|
|
4
|
+
import { createShell, createExec, CommandError, type Shell, type Exec } from "./shell.ts";
|
|
5
|
+
import { step } from "./step.ts";
|
|
6
|
+
import { concat } from "./utils.ts";
|
|
7
|
+
interface RunlingValues {
|
|
8
|
+
cwd: string;
|
|
9
|
+
prompt: string;
|
|
10
|
+
verbose: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface CreateRunlingOptions extends RunlingValues {
|
|
13
|
+
handleInput?: InputHandler;
|
|
14
|
+
}
|
|
15
|
+
export type JsonValue = null | boolean | number | string | JsonValue[] | {
|
|
16
|
+
[key: string]: JsonValue;
|
|
17
|
+
};
|
|
18
|
+
export interface WorkflowResult {
|
|
19
|
+
summary: string;
|
|
20
|
+
/** Human-readable Markdown shown after the summary in interactive mode. */
|
|
21
|
+
details?: string;
|
|
22
|
+
outputs?: Record<string, JsonValue>;
|
|
23
|
+
}
|
|
24
|
+
export type WorkflowReturn = WorkflowResult | JsonValue | undefined | void;
|
|
25
|
+
declare function agent(this: RunlingValues, options: AgentOptions): Promise<import("./agent.ts").RunlingAgent>;
|
|
26
|
+
declare function runAgent(this: RunlingValues, prompt: string, options: RunAgentOptions): Promise<import("./agent.ts").AgentResult>;
|
|
27
|
+
declare function getPwd(this: RunlingValues, cwd?: string): Promise<import("./git.ts").WorkingDirectory>;
|
|
28
|
+
declare function workingTreeHash(this: RunlingValues, cwd?: string): Promise<string>;
|
|
29
|
+
declare const runlingPrimitives: Readonly<{
|
|
30
|
+
agent: typeof agent;
|
|
31
|
+
AgentOutcomeError: typeof AgentOutcomeError;
|
|
32
|
+
runAgent: typeof runAgent;
|
|
33
|
+
getPwd: typeof getPwd;
|
|
34
|
+
workingTreeHash: typeof workingTreeHash;
|
|
35
|
+
randomId: typeof randomId;
|
|
36
|
+
log: {
|
|
37
|
+
level: import("./log.ts").LogLevel;
|
|
38
|
+
debug: (message: string) => void;
|
|
39
|
+
info: (message: string) => void;
|
|
40
|
+
success: (message: string) => void;
|
|
41
|
+
error: (message: string) => void;
|
|
42
|
+
colorize(text: string): string;
|
|
43
|
+
highlight: (text: string, color?: string) => string;
|
|
44
|
+
withColor<T>(color: string, work: import("./log.ts").LoggedWork<T>): T;
|
|
45
|
+
withDestination<T>(destination: "stdout" | "stderr" | "silent", work: import("./log.ts").LoggedWork<T>): T;
|
|
46
|
+
indented<T>(work: import("./log.ts").LoggedWork<T>): T;
|
|
47
|
+
};
|
|
48
|
+
step: typeof step;
|
|
49
|
+
createShell: typeof createShell;
|
|
50
|
+
createExec: typeof createExec;
|
|
51
|
+
CommandError: typeof CommandError;
|
|
52
|
+
ShellError: typeof CommandError;
|
|
53
|
+
concat: typeof concat;
|
|
54
|
+
}>;
|
|
55
|
+
type RunlingPrimitives = typeof runlingPrimitives;
|
|
56
|
+
export type Runling = RunlingPrimitives & RunlingValues & {
|
|
57
|
+
readonly input: Input;
|
|
58
|
+
readonly shell: Shell;
|
|
59
|
+
readonly exec: Exec;
|
|
60
|
+
};
|
|
61
|
+
export declare function createRunling({ handleInput, ...values }: CreateRunlingOptions): Runling;
|
|
62
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { agent as createAgent, AgentOutcomeError, runAgent as runAgentOnce, } from "./agent.js";
|
|
2
|
+
import { getPwd as captureWorkingDirectory, workingTreeHash as hashWorkingTree, } from "./git.js";
|
|
3
|
+
import { randomId } from "./id.js";
|
|
4
|
+
import { createInput } from "./input.js";
|
|
5
|
+
import { log } from "./log.js";
|
|
6
|
+
import { createShell, createExec, CommandError, ShellError, } from "./shell.js";
|
|
7
|
+
import { step } from "./step.js";
|
|
8
|
+
import { concat } from "./utils.js";
|
|
9
|
+
function agent(options) {
|
|
10
|
+
return createAgent({ ...options, cwd: options.cwd ?? this.cwd });
|
|
11
|
+
}
|
|
12
|
+
function runAgent(prompt, options) {
|
|
13
|
+
return runAgentOnce(prompt, { ...options, cwd: options.cwd ?? this.cwd });
|
|
14
|
+
}
|
|
15
|
+
function getPwd(cwd = this.cwd) {
|
|
16
|
+
return captureWorkingDirectory(cwd);
|
|
17
|
+
}
|
|
18
|
+
function workingTreeHash(cwd = this.cwd) {
|
|
19
|
+
return hashWorkingTree(cwd);
|
|
20
|
+
}
|
|
21
|
+
const runlingPrimitives = Object.freeze({
|
|
22
|
+
agent,
|
|
23
|
+
AgentOutcomeError,
|
|
24
|
+
runAgent,
|
|
25
|
+
getPwd,
|
|
26
|
+
workingTreeHash,
|
|
27
|
+
randomId,
|
|
28
|
+
log,
|
|
29
|
+
step,
|
|
30
|
+
createShell,
|
|
31
|
+
createExec,
|
|
32
|
+
CommandError,
|
|
33
|
+
ShellError,
|
|
34
|
+
concat,
|
|
35
|
+
});
|
|
36
|
+
export function createRunling({ handleInput, ...values }) {
|
|
37
|
+
return Object.freeze({
|
|
38
|
+
...runlingPrimitives,
|
|
39
|
+
...values,
|
|
40
|
+
input: createInput(handleInput),
|
|
41
|
+
shell: createShell({ verbose: values.verbose }),
|
|
42
|
+
exec: createExec({ verbose: values.verbose }),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import Ajv2020 from "ajv/dist/2020.js";
|
|
2
|
+
const validator = new Ajv2020({
|
|
3
|
+
strict: false,
|
|
4
|
+
validateFormats: false,
|
|
5
|
+
});
|
|
6
|
+
/** Validate an object schema against the JSON Schema 2020-12 meta-schema. */
|
|
7
|
+
export function isWorkflowSchema(value) {
|
|
8
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
return validator.validateSchema(value) === true;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ExecaError, type Options, type TemplateExpression } from "execa";
|
|
2
|
+
export interface ShellOutput {
|
|
3
|
+
stdout: Buffer;
|
|
4
|
+
stderr: Buffer;
|
|
5
|
+
exitCode: number;
|
|
6
|
+
}
|
|
7
|
+
export { ExecaError as ShellError, ExecaError as CommandError };
|
|
8
|
+
type ProcessResult = {
|
|
9
|
+
stdout?: unknown;
|
|
10
|
+
stderr?: unknown;
|
|
11
|
+
exitCode?: number;
|
|
12
|
+
};
|
|
13
|
+
type ShellExpression = string | number | boolean | null | undefined | {
|
|
14
|
+
raw: string;
|
|
15
|
+
} | readonly ShellExpression[];
|
|
16
|
+
type ShellArguments = [TemplateStringsArray, ...ShellExpression[]];
|
|
17
|
+
/** A configurable, single-execution Execa command with buffered output. */
|
|
18
|
+
export declare class Command implements PromiseLike<ShellOutput> {
|
|
19
|
+
private readonly launch;
|
|
20
|
+
private execution?;
|
|
21
|
+
private directory?;
|
|
22
|
+
private silent;
|
|
23
|
+
private throwOnError;
|
|
24
|
+
constructor(launch: (options: Options) => PromiseLike<ProcessResult>);
|
|
25
|
+
cwd(path: string): this;
|
|
26
|
+
quiet(value?: boolean): this;
|
|
27
|
+
nothrow(): this;
|
|
28
|
+
then<TResult1 = ShellOutput, TResult2 = never>(fulfilled?: ((value: ShellOutput) => TResult1 | PromiseLike<TResult1>) | null, rejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
|
|
29
|
+
text(): Promise<string>;
|
|
30
|
+
json(): Promise<any>;
|
|
31
|
+
private run;
|
|
32
|
+
}
|
|
33
|
+
export interface CreateShellOptions {
|
|
34
|
+
verbose?: boolean;
|
|
35
|
+
cwd?: string;
|
|
36
|
+
}
|
|
37
|
+
export { Command as ShellCommand };
|
|
38
|
+
export declare function createShell(options?: CreateShellOptions): (this: {
|
|
39
|
+
cwd?: string;
|
|
40
|
+
} | void, ...args: ShellArguments) => Command;
|
|
41
|
+
/** Execute a program directly. Execa parses the template without a shell. */
|
|
42
|
+
export declare function createExec(options?: CreateShellOptions): (this: {
|
|
43
|
+
cwd?: string;
|
|
44
|
+
} | void, strings: TemplateStringsArray, ...expressions: TemplateExpression[]) => Command;
|
|
45
|
+
export type Exec = ReturnType<typeof createExec>;
|
|
46
|
+
export type CreateExecOptions = CreateShellOptions;
|
|
47
|
+
export type Shell = ReturnType<typeof createShell>;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { emitRunlingEvent } from "./events.js";
|
|
2
|
+
import { log, logCommand } from "./log.js";
|
|
3
|
+
import { execa, ExecaError, } from "execa";
|
|
4
|
+
const COMMAND_COLOR = "#ae3ec9";
|
|
5
|
+
const COMMAND_PREVIEW_LENGTH = 200;
|
|
6
|
+
export { ExecaError as ShellError, ExecaError as CommandError };
|
|
7
|
+
/** A configurable, single-execution Execa command with buffered output. */
|
|
8
|
+
export class Command {
|
|
9
|
+
launch;
|
|
10
|
+
execution;
|
|
11
|
+
directory;
|
|
12
|
+
silent = true;
|
|
13
|
+
throwOnError = true;
|
|
14
|
+
constructor(launch) {
|
|
15
|
+
this.launch = launch;
|
|
16
|
+
}
|
|
17
|
+
cwd(path) {
|
|
18
|
+
this.directory = path;
|
|
19
|
+
return this;
|
|
20
|
+
}
|
|
21
|
+
quiet(value = true) {
|
|
22
|
+
this.silent = value;
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
nothrow() {
|
|
26
|
+
this.throwOnError = false;
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
then(fulfilled, rejected) {
|
|
30
|
+
return this.run().then(fulfilled, rejected);
|
|
31
|
+
}
|
|
32
|
+
async text() {
|
|
33
|
+
return (await this).stdout.toString();
|
|
34
|
+
}
|
|
35
|
+
async json() {
|
|
36
|
+
return JSON.parse(await this.text());
|
|
37
|
+
}
|
|
38
|
+
run() {
|
|
39
|
+
return (this.execution ??= Promise.resolve().then(async () => {
|
|
40
|
+
try {
|
|
41
|
+
const output = await this.launch({
|
|
42
|
+
cwd: this.directory,
|
|
43
|
+
encoding: "buffer",
|
|
44
|
+
stripFinalNewline: false,
|
|
45
|
+
reject: this.throwOnError,
|
|
46
|
+
stdin: "ignore",
|
|
47
|
+
stdout: this.silent ? "pipe" : ["pipe", "inherit"],
|
|
48
|
+
stderr: this.silent ? "pipe" : ["pipe", "inherit"],
|
|
49
|
+
preferLocal: true,
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
...output,
|
|
53
|
+
stdout: toBuffer(output.stdout),
|
|
54
|
+
stderr: toBuffer(output.stderr),
|
|
55
|
+
exitCode: output.exitCode ?? 1,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (error instanceof ExecaError) {
|
|
60
|
+
Object.assign(error, {
|
|
61
|
+
stdout: toBuffer(error.stdout),
|
|
62
|
+
stderr: toBuffer(error.stderr),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export { Command as ShellCommand };
|
|
71
|
+
export function createShell(options = {}) {
|
|
72
|
+
return function (...args) {
|
|
73
|
+
const [strings, ...expressions] = args;
|
|
74
|
+
const command = strings
|
|
75
|
+
.map((part, index) => part +
|
|
76
|
+
(index < expressions.length
|
|
77
|
+
? formatExpression(expressions[index])
|
|
78
|
+
: ""))
|
|
79
|
+
.join("");
|
|
80
|
+
return track(new Command((config) => execa("sh", ["-c", command], config)), formatCommand(...args), options, this?.cwd);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/** Execute a program directly. Execa parses the template without a shell. */
|
|
84
|
+
export function createExec(options = {}) {
|
|
85
|
+
return function (strings, ...expressions) {
|
|
86
|
+
const preview = strings
|
|
87
|
+
.map((part, index) => part +
|
|
88
|
+
(index < expressions.length
|
|
89
|
+
? JSON.stringify(expressions[index])
|
|
90
|
+
: ""))
|
|
91
|
+
.join("");
|
|
92
|
+
return track(new Command((config) => execa(config)(strings, ...expressions)), truncateCommand(preview), options, this?.cwd);
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function track(command, formattedCommand, options, contextCwd) {
|
|
96
|
+
const id = crypto.randomUUID();
|
|
97
|
+
const startedAt = performance.now();
|
|
98
|
+
emitRunlingEvent({
|
|
99
|
+
type: "command.started",
|
|
100
|
+
id,
|
|
101
|
+
command: formattedCommand,
|
|
102
|
+
});
|
|
103
|
+
logCommand(id, `${log.highlight("Running", COMMAND_COLOR)} ${formattedCommand}`);
|
|
104
|
+
command.quiet(!(options.verbose ?? false));
|
|
105
|
+
const cwd = options.cwd ?? contextCwd;
|
|
106
|
+
const configured = cwd === undefined ? command : command.cwd(cwd);
|
|
107
|
+
queueMicrotask(() => {
|
|
108
|
+
void configured.then((output) => emitRunlingEvent({
|
|
109
|
+
type: "command.finished",
|
|
110
|
+
id,
|
|
111
|
+
status: output.exitCode === 0 ? "completed" : "failed",
|
|
112
|
+
durationMs: performance.now() - startedAt,
|
|
113
|
+
output: shellOutput(output),
|
|
114
|
+
}), (error) => emitRunlingEvent({
|
|
115
|
+
type: "command.finished",
|
|
116
|
+
id,
|
|
117
|
+
status: "failed",
|
|
118
|
+
durationMs: performance.now() - startedAt,
|
|
119
|
+
output: shellOutput(error),
|
|
120
|
+
}));
|
|
121
|
+
});
|
|
122
|
+
return configured;
|
|
123
|
+
}
|
|
124
|
+
const shellOutput = (value) => {
|
|
125
|
+
if (typeof value !== "object" || value === null) {
|
|
126
|
+
return { stdout: "", stderr: "" };
|
|
127
|
+
}
|
|
128
|
+
const output = value;
|
|
129
|
+
return {
|
|
130
|
+
stdout: bufferText(output.stdout),
|
|
131
|
+
stderr: bufferText(output.stderr),
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
const bufferText = (value) => value instanceof Uint8Array ? new TextDecoder().decode(value) : "";
|
|
135
|
+
const toBuffer = (value) => value instanceof Uint8Array
|
|
136
|
+
? Buffer.from(value)
|
|
137
|
+
: Buffer.from(typeof value === "string" ? value : "");
|
|
138
|
+
function formatCommand(...[strings, ...expressions]) {
|
|
139
|
+
const command = strings
|
|
140
|
+
.map((part, index) => {
|
|
141
|
+
const expression = expressions[index];
|
|
142
|
+
return expression === undefined
|
|
143
|
+
? part
|
|
144
|
+
: `${part}${formatExpression(expression)}`;
|
|
145
|
+
})
|
|
146
|
+
.join("")
|
|
147
|
+
.trim()
|
|
148
|
+
.replaceAll("\n", " ");
|
|
149
|
+
return truncateCommand(command);
|
|
150
|
+
}
|
|
151
|
+
function truncateCommand(value) {
|
|
152
|
+
const command = value.trim().replaceAll("\n", " ");
|
|
153
|
+
if (command.length <= COMMAND_PREVIEW_LENGTH)
|
|
154
|
+
return command;
|
|
155
|
+
return `${command.slice(0, COMMAND_PREVIEW_LENGTH)}… (${(command.length - COMMAND_PREVIEW_LENGTH).toLocaleString()} characters omitted)`;
|
|
156
|
+
}
|
|
157
|
+
function formatExpression(expression) {
|
|
158
|
+
if (Array.isArray(expression)) {
|
|
159
|
+
return expression.map(formatExpression).join(" ");
|
|
160
|
+
}
|
|
161
|
+
if (typeof expression === "object" &&
|
|
162
|
+
expression !== null &&
|
|
163
|
+
"raw" in expression) {
|
|
164
|
+
return String(expression.raw);
|
|
165
|
+
}
|
|
166
|
+
const value = String(expression ?? "");
|
|
167
|
+
if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value))
|
|
168
|
+
return value;
|
|
169
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
170
|
+
}
|
package/dist/src/step.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { emitRunlingEvent, withRunlingActivity, } from "./events.js";
|
|
2
|
+
import { log, logStep } from "./log.js";
|
|
3
|
+
/**
|
|
4
|
+
* Runs a named workflow step, indenting any log output produced by its work.
|
|
5
|
+
*/
|
|
6
|
+
export function step(label, work) {
|
|
7
|
+
const id = crypto.randomUUID();
|
|
8
|
+
const startedAt = performance.now();
|
|
9
|
+
emitRunlingEvent({
|
|
10
|
+
type: "step.started",
|
|
11
|
+
id,
|
|
12
|
+
label,
|
|
13
|
+
});
|
|
14
|
+
logStep(label);
|
|
15
|
+
const finish = (status) => emitRunlingEvent({
|
|
16
|
+
type: "step.finished",
|
|
17
|
+
id,
|
|
18
|
+
status,
|
|
19
|
+
durationMs: performance.now() - startedAt,
|
|
20
|
+
});
|
|
21
|
+
try {
|
|
22
|
+
const result = withRunlingActivity(id, () => log.indented(work));
|
|
23
|
+
if (isPromiseLike(result)) {
|
|
24
|
+
void Promise.resolve(result).then(() => finish("completed"), () => finish("failed"));
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
finish("completed");
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
finish("failed");
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const isPromiseLike = (value) => (typeof value === "object" || typeof value === "function") &&
|
|
37
|
+
value !== null &&
|
|
38
|
+
"then" in value &&
|
|
39
|
+
typeof value.then === "function";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const RUNLING_SYSTEM_PROMPT = `
|
|
2
|
+
You are running inside Runling, a non-interactive software factory.
|
|
3
|
+
|
|
4
|
+
Complete the user's request autonomously using the available tools. Do not ask
|
|
5
|
+
follow-up questions when a reasonable interpretation is possible.
|
|
6
|
+
|
|
7
|
+
Always finish by calling report_outcome as your final action. Do not emit a
|
|
8
|
+
plain-text final response. The report summary must be a direct, concise,
|
|
9
|
+
single-line result. Do not describe your reasoning or restate the request.
|
|
10
|
+
|
|
11
|
+
Use outcome "completed" only when the request has been fulfilled. Use
|
|
12
|
+
"blocked" when external input or access is required, and "failed" when the
|
|
13
|
+
work was attempted but could not be completed.
|
|
14
|
+
`.trim();
|
|
15
|
+
export function formatAgentInstructions(instructions) {
|
|
16
|
+
if (instructions.length === 0) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
return [
|
|
20
|
+
"Additional instructions for this run:",
|
|
21
|
+
...instructions.map((instruction) => `- ${instruction}`),
|
|
22
|
+
].join("\n");
|
|
23
|
+
}
|
package/dist/src/text.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Component, type Terminal } from "@earendil-works/pi-tui";
|
|
2
|
+
import type { RunlingEvent } from "./events.ts";
|
|
3
|
+
import type { InputHandler } from "./input.ts";
|
|
4
|
+
import type { WorkflowExecution } from "./runner.ts";
|
|
5
|
+
export declare class RunlingDashboard implements Component {
|
|
6
|
+
private readonly title;
|
|
7
|
+
private readonly startedAt;
|
|
8
|
+
private readonly nodes;
|
|
9
|
+
private readonly nodesById;
|
|
10
|
+
private readonly agents;
|
|
11
|
+
private readonly inputEditors;
|
|
12
|
+
private logSequence;
|
|
13
|
+
private usage;
|
|
14
|
+
private execution?;
|
|
15
|
+
constructor(title: string, startedAt?: number);
|
|
16
|
+
handle: (event: RunlingEvent) => void;
|
|
17
|
+
finish(execution: WorkflowExecution): void;
|
|
18
|
+
invalidate(): void;
|
|
19
|
+
setInputEditor(id: string, editor: Component | undefined): void;
|
|
20
|
+
render(width: number): string[];
|
|
21
|
+
renderHeader(width: number): string[];
|
|
22
|
+
renderTranscript(width: number): string[];
|
|
23
|
+
renderFooter(width: number): string[];
|
|
24
|
+
private footer;
|
|
25
|
+
private addNode;
|
|
26
|
+
private hasParent;
|
|
27
|
+
private renderNode;
|
|
28
|
+
private wrapNode;
|
|
29
|
+
private spinner;
|
|
30
|
+
}
|
|
31
|
+
export declare class TuiReporter {
|
|
32
|
+
private readonly onCancel;
|
|
33
|
+
private readonly dashboard;
|
|
34
|
+
private readonly tui;
|
|
35
|
+
private timer?;
|
|
36
|
+
private started;
|
|
37
|
+
private stopped;
|
|
38
|
+
private readonly pendingInputs;
|
|
39
|
+
private readonly pendingEditors;
|
|
40
|
+
constructor(title: string, terminal?: Terminal, onCancel?: () => void);
|
|
41
|
+
handle: (event: RunlingEvent) => void;
|
|
42
|
+
input: InputHandler;
|
|
43
|
+
start(): void;
|
|
44
|
+
finish(execution: WorkflowExecution): void;
|
|
45
|
+
stop(): void;
|
|
46
|
+
}
|