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,82 @@
|
|
|
1
|
+
import type { TokenUsage } from "./usage.ts";
|
|
2
|
+
export type RunlingEventPayload = {
|
|
3
|
+
type: "log";
|
|
4
|
+
level: "debug" | "info" | "success" | "error";
|
|
5
|
+
message: string;
|
|
6
|
+
depth: number;
|
|
7
|
+
color: string;
|
|
8
|
+
source?: "step" | "agent" | "command" | "input";
|
|
9
|
+
sourceId?: string;
|
|
10
|
+
} | {
|
|
11
|
+
type: "step.started";
|
|
12
|
+
id: string;
|
|
13
|
+
label: string;
|
|
14
|
+
} | {
|
|
15
|
+
type: "step.finished";
|
|
16
|
+
id: string;
|
|
17
|
+
status: "completed" | "failed";
|
|
18
|
+
durationMs: number;
|
|
19
|
+
} | {
|
|
20
|
+
type: "command.started";
|
|
21
|
+
id: string;
|
|
22
|
+
command: string;
|
|
23
|
+
} | {
|
|
24
|
+
type: "command.finished";
|
|
25
|
+
id: string;
|
|
26
|
+
status: "completed" | "failed";
|
|
27
|
+
durationMs: number;
|
|
28
|
+
output: {
|
|
29
|
+
stdout: string;
|
|
30
|
+
stderr: string;
|
|
31
|
+
};
|
|
32
|
+
} | {
|
|
33
|
+
type: "input.requested";
|
|
34
|
+
id: string;
|
|
35
|
+
message: string;
|
|
36
|
+
defaultValue?: string;
|
|
37
|
+
} | {
|
|
38
|
+
type: "input.finished";
|
|
39
|
+
id: string;
|
|
40
|
+
status: "answered";
|
|
41
|
+
value: string;
|
|
42
|
+
durationMs: number;
|
|
43
|
+
} | {
|
|
44
|
+
type: "input.finished";
|
|
45
|
+
id: string;
|
|
46
|
+
status: "failed";
|
|
47
|
+
durationMs: number;
|
|
48
|
+
} | {
|
|
49
|
+
type: "agent.started";
|
|
50
|
+
agentId: string;
|
|
51
|
+
model: string;
|
|
52
|
+
color: string;
|
|
53
|
+
} | {
|
|
54
|
+
type: "agent.progress";
|
|
55
|
+
agentId: string;
|
|
56
|
+
text: string;
|
|
57
|
+
} | {
|
|
58
|
+
type: "agent.action";
|
|
59
|
+
agentId: string;
|
|
60
|
+
action: string;
|
|
61
|
+
} | {
|
|
62
|
+
type: "agent.usage";
|
|
63
|
+
agentId: string;
|
|
64
|
+
usage: TokenUsage;
|
|
65
|
+
} | {
|
|
66
|
+
type: "agent.finished";
|
|
67
|
+
agentId: string;
|
|
68
|
+
outcome: "completed" | "blocked" | "failed";
|
|
69
|
+
usage: TokenUsage;
|
|
70
|
+
} | {
|
|
71
|
+
type: "usage.updated";
|
|
72
|
+
usage: TokenUsage;
|
|
73
|
+
};
|
|
74
|
+
export type RunlingEvent = RunlingEventPayload & {
|
|
75
|
+
activityId?: string;
|
|
76
|
+
timestamp: number;
|
|
77
|
+
};
|
|
78
|
+
export type RunlingEventListener = (event: RunlingEvent) => void;
|
|
79
|
+
export declare const emitRunlingEvent: (payload: RunlingEventPayload) => void;
|
|
80
|
+
export declare const observeRunlingEvents: <T>(listener: RunlingEventListener, work: () => T) => T;
|
|
81
|
+
export declare const withRunlingActivity: <T>(id: string, work: () => T) => T;
|
|
82
|
+
export declare const bindRunlingContext: <Args extends unknown[], Result>(work: (...args: Args) => Result) => ((...args: Args) => Result);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
const listeners = new AsyncLocalStorage();
|
|
3
|
+
const activity = new AsyncLocalStorage();
|
|
4
|
+
export const emitRunlingEvent = (payload) => {
|
|
5
|
+
const event = {
|
|
6
|
+
...payload,
|
|
7
|
+
activityId: activity.getStore(),
|
|
8
|
+
timestamp: performance.now(),
|
|
9
|
+
};
|
|
10
|
+
for (const listener of listeners.getStore() ?? [])
|
|
11
|
+
listener(event);
|
|
12
|
+
};
|
|
13
|
+
export const observeRunlingEvents = (listener, work) => listeners.run([...(listeners.getStore() ?? []), listener], work);
|
|
14
|
+
export const withRunlingActivity = (id, work) => activity.run(id, work);
|
|
15
|
+
export const bindRunlingContext = (work) => {
|
|
16
|
+
const capturedListeners = listeners.getStore() ?? [];
|
|
17
|
+
const capturedActivity = activity.getStore();
|
|
18
|
+
return (...args) => listeners.run(capturedListeners, () => capturedActivity === undefined
|
|
19
|
+
? work(...args)
|
|
20
|
+
: activity.run(capturedActivity, () => work(...args)));
|
|
21
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function workingTreeHash(cwd?: string): Promise<string>;
|
|
2
|
+
export declare class WorkingDirectory {
|
|
3
|
+
readonly path: string;
|
|
4
|
+
private readonly initialHash;
|
|
5
|
+
private constructor();
|
|
6
|
+
static create(path?: string): Promise<WorkingDirectory>;
|
|
7
|
+
get hasChanges(): Promise<boolean>;
|
|
8
|
+
}
|
|
9
|
+
export declare function getPwd(path?: string): Promise<WorkingDirectory>;
|
package/dist/src/git.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { createReadStream } from "node:fs";
|
|
2
|
+
import { lstat, readlink } from "node:fs/promises";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
import { execFile } from "node:child_process";
|
|
6
|
+
import { promisify } from "node:util";
|
|
7
|
+
const exec = promisify(execFile);
|
|
8
|
+
async function git(cwd, args) {
|
|
9
|
+
const { stdout } = await exec("git", args, {
|
|
10
|
+
cwd,
|
|
11
|
+
encoding: "buffer",
|
|
12
|
+
maxBuffer: 128 * 1024 * 1024,
|
|
13
|
+
});
|
|
14
|
+
return stdout;
|
|
15
|
+
}
|
|
16
|
+
async function hasHead(cwd) {
|
|
17
|
+
try {
|
|
18
|
+
await git(cwd, ["rev-parse", "--verify", "HEAD"]);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function updateField(hasher, value) {
|
|
26
|
+
const bytes = typeof value === "string" ? new TextEncoder().encode(value) : value;
|
|
27
|
+
hasher.update(`${bytes.byteLength}:`);
|
|
28
|
+
hasher.update(bytes instanceof ArrayBuffer ? new Uint8Array(bytes) : bytes);
|
|
29
|
+
}
|
|
30
|
+
async function updateUntrackedFile(hasher, cwd, path) {
|
|
31
|
+
const absolutePath = resolve(cwd, path);
|
|
32
|
+
const stat = await lstat(absolutePath);
|
|
33
|
+
updateField(hasher, path);
|
|
34
|
+
updateField(hasher, String(stat.mode));
|
|
35
|
+
if (stat.isSymbolicLink()) {
|
|
36
|
+
updateField(hasher, await readlink(absolutePath));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (!stat.isFile()) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
updateField(hasher, String(stat.size));
|
|
43
|
+
for await (const chunk of createReadStream(absolutePath)) {
|
|
44
|
+
hasher.update(chunk);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export async function workingTreeHash(cwd = process.cwd()) {
|
|
48
|
+
const hasher = createHash("sha256");
|
|
49
|
+
if (await hasHead(cwd)) {
|
|
50
|
+
updateField(hasher, await git(cwd, ["diff", "--binary", "HEAD"]));
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
updateField(hasher, await git(cwd, ["diff", "--binary", "--cached"]));
|
|
54
|
+
updateField(hasher, await git(cwd, ["diff", "--binary"]));
|
|
55
|
+
}
|
|
56
|
+
const untrackedFiles = new TextDecoder()
|
|
57
|
+
.decode(await git(cwd, ["ls-files", "--others", "--exclude-standard", "-z"]))
|
|
58
|
+
.split("\0")
|
|
59
|
+
.filter(Boolean)
|
|
60
|
+
.sort();
|
|
61
|
+
for (const path of untrackedFiles) {
|
|
62
|
+
await updateUntrackedFile(hasher, cwd, path);
|
|
63
|
+
}
|
|
64
|
+
return hasher.digest("hex");
|
|
65
|
+
}
|
|
66
|
+
export class WorkingDirectory {
|
|
67
|
+
path;
|
|
68
|
+
initialHash;
|
|
69
|
+
constructor(path, initialHash) {
|
|
70
|
+
this.path = path;
|
|
71
|
+
this.initialHash = initialHash;
|
|
72
|
+
}
|
|
73
|
+
static async create(path = process.cwd()) {
|
|
74
|
+
return new WorkingDirectory(path, await workingTreeHash(path));
|
|
75
|
+
}
|
|
76
|
+
get hasChanges() {
|
|
77
|
+
return workingTreeHash(this.path).then((currentHash) => currentHash !== this.initialHash);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export function getPwd(path = process.cwd()) {
|
|
81
|
+
return WorkingDirectory.create(path);
|
|
82
|
+
}
|
package/dist/src/id.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function randomId(): string;
|
package/dist/src/id.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { randomInt } from "node:crypto";
|
|
2
|
+
import { adjectives, nouns } from "human-id";
|
|
3
|
+
export function randomId() {
|
|
4
|
+
const adjective = adjectives[randomInt(adjectives.length)];
|
|
5
|
+
const noun = nouns[randomInt(nouns.length)];
|
|
6
|
+
return `${adjective}-${noun}-${randomInt(1_000, 10_000)}`;
|
|
7
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { agent, type AgentExtension, type AgentExtensionAPI, AgentOutcomeError, type AgentOptions, type AgentReport, type AgentResult, type AgentResourceOptions, type AgentRunOptions, type CompletedAgentReport, defineAgentExtension, type RunlingAgent, runAgent, type RunAgentOptions, } from "./agent.ts";
|
|
2
|
+
export { getPwd, WorkingDirectory, workingTreeHash } from "./git.ts";
|
|
3
|
+
export type { RunlingEvent, RunlingEventListener, RunlingEventPayload, } from "./events.ts";
|
|
4
|
+
export { randomId } from "./id.ts";
|
|
5
|
+
export { createInput, InputUnavailableError, type Input, type InputHandler, type InputOptions, type InputRequest, } from "./input.ts";
|
|
6
|
+
export { log, type LogLevel } from "./log.ts";
|
|
7
|
+
export { step, type StepWork } from "./step.ts";
|
|
8
|
+
export { createShell, createExec, CommandError, type Exec, type CreateExecOptions, type CreateShellOptions, ShellError, type Shell, } from "./shell.ts";
|
|
9
|
+
export { concat, type ConcatPart } from "./utils.ts";
|
|
10
|
+
export { isWorkflow, workflow, type Workflow, type WorkflowDefinition, } from "./workflow.ts";
|
|
11
|
+
export { Type, type Static, type TSchema } from "typebox";
|
|
12
|
+
export { isWorkflowSchema } from "./schema.ts";
|
|
13
|
+
export { createRunling, type Runling, type CreateRunlingOptions, type JsonValue, type WorkflowResult, type WorkflowReturn, } from "./runtime.ts";
|
|
14
|
+
export { runWorkflow, type RunWorkflowOptions, type WorkflowExecution, } from "./runner.ts";
|
|
15
|
+
export { accumulateTokenUsage, emptyTokenUsage, formatTokenUsage, getRecordedTokenUsage, isTokenUsage, recordTokenUsage, resetTokenUsage, totalTokens, type TokenUsage, } from "./usage.ts";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { agent, AgentOutcomeError, defineAgentExtension, runAgent, } from "./agent.js";
|
|
2
|
+
export { getPwd, WorkingDirectory, workingTreeHash } from "./git.js";
|
|
3
|
+
export { randomId } from "./id.js";
|
|
4
|
+
export { createInput, InputUnavailableError, } from "./input.js";
|
|
5
|
+
export { log } from "./log.js";
|
|
6
|
+
export { step } from "./step.js";
|
|
7
|
+
export { createShell, createExec, CommandError, ShellError, } from "./shell.js";
|
|
8
|
+
export { concat } from "./utils.js";
|
|
9
|
+
export { isWorkflow, workflow, } from "./workflow.js";
|
|
10
|
+
export { Type } from "typebox";
|
|
11
|
+
export { isWorkflowSchema } from "./schema.js";
|
|
12
|
+
export { createRunling, } from "./runtime.js";
|
|
13
|
+
export { runWorkflow, } from "./runner.js";
|
|
14
|
+
export { accumulateTokenUsage, emptyTokenUsage, formatTokenUsage, getRecordedTokenUsage, isTokenUsage, recordTokenUsage, resetTokenUsage, totalTokens, } from "./usage.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface InputOptions {
|
|
2
|
+
defaultValue?: string;
|
|
3
|
+
signal?: AbortSignal;
|
|
4
|
+
}
|
|
5
|
+
export interface InputRequest extends InputOptions {
|
|
6
|
+
id: string;
|
|
7
|
+
message: string;
|
|
8
|
+
}
|
|
9
|
+
export type InputHandler = (request: InputRequest) => Promise<string>;
|
|
10
|
+
export type Input = (message: string, options?: InputOptions) => Promise<string>;
|
|
11
|
+
export declare class InputUnavailableError extends Error {
|
|
12
|
+
constructor(message: string);
|
|
13
|
+
}
|
|
14
|
+
export declare const createInput: (handleInput?: InputHandler) => Input;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { bindRunlingContext, emitRunlingEvent } from "./events.js";
|
|
2
|
+
import { log, logInput } from "./log.js";
|
|
3
|
+
export class InputUnavailableError extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(`Workflow requested input, but this host cannot provide it: ${message}`);
|
|
6
|
+
this.name = "InputUnavailableError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export const createInput = (handleInput) => async (message, options = {}) => {
|
|
10
|
+
const id = crypto.randomUUID();
|
|
11
|
+
const startedAt = performance.now();
|
|
12
|
+
const request = { id, message, ...options };
|
|
13
|
+
const emit = bindRunlingContext(emitRunlingEvent);
|
|
14
|
+
emit({
|
|
15
|
+
type: "input.requested",
|
|
16
|
+
id,
|
|
17
|
+
message,
|
|
18
|
+
defaultValue: options.defaultValue,
|
|
19
|
+
});
|
|
20
|
+
logInput(id, "info", `${log.highlight("Asking", "#f59f00")} ${message}`);
|
|
21
|
+
try {
|
|
22
|
+
options.signal?.throwIfAborted();
|
|
23
|
+
if (handleInput === undefined)
|
|
24
|
+
throw new InputUnavailableError(message);
|
|
25
|
+
const value = await handleInput(request);
|
|
26
|
+
if (typeof value !== "string") {
|
|
27
|
+
throw new TypeError("An input handler must return a string");
|
|
28
|
+
}
|
|
29
|
+
emit({
|
|
30
|
+
type: "input.finished",
|
|
31
|
+
id,
|
|
32
|
+
status: "answered",
|
|
33
|
+
value,
|
|
34
|
+
durationMs: performance.now() - startedAt,
|
|
35
|
+
});
|
|
36
|
+
logInput(id, "success", `${log.highlight("Answered")} ${value}`);
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
emit({
|
|
41
|
+
type: "input.finished",
|
|
42
|
+
id,
|
|
43
|
+
status: "failed",
|
|
44
|
+
durationMs: performance.now() - startedAt,
|
|
45
|
+
});
|
|
46
|
+
logInput(id, "error", `${log.highlight("Input failed", "crimson")} ${message}`);
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
declare function highlight(text: string, color?: string): string;
|
|
2
|
+
export type LogLevel = "info" | "debug";
|
|
3
|
+
type LogDestination = "stdout" | "stderr" | "silent";
|
|
4
|
+
interface LogSource {
|
|
5
|
+
type: "agent" | "command" | "input";
|
|
6
|
+
id: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const logStep: (message: string) => void;
|
|
9
|
+
export declare const logCommand: (id: string, message: string) => void;
|
|
10
|
+
export declare const logInput: (id: string, level: "info" | "success" | "error", message: string) => void;
|
|
11
|
+
export declare const withLogSource: <T>(source: LogSource, work: LoggedWork<T>) => T;
|
|
12
|
+
/** A chunk of work whose log output is indented one level deeper. */
|
|
13
|
+
export type LoggedWork<T> = () => T;
|
|
14
|
+
export declare const log: {
|
|
15
|
+
level: LogLevel;
|
|
16
|
+
debug: (message: string) => void;
|
|
17
|
+
info: (message: string) => void;
|
|
18
|
+
success: (message: string) => void;
|
|
19
|
+
error: (message: string) => void;
|
|
20
|
+
/** Renders `text` in the active contextual color, if there is one. */
|
|
21
|
+
colorize(text: string): string;
|
|
22
|
+
/** Renders `text` in a bold, bright color. */
|
|
23
|
+
highlight: typeof highlight;
|
|
24
|
+
/** Runs `work` with log markers rendered in `color`. */
|
|
25
|
+
withColor<T>(color: string, work: LoggedWork<T>): T;
|
|
26
|
+
/** Runs `work` with informational output written to `destination`. */
|
|
27
|
+
withDestination<T>(destination: LogDestination, work: LoggedWork<T>): T;
|
|
28
|
+
/**
|
|
29
|
+
* Runs `work` with all of its log output indented one level deeper than the
|
|
30
|
+
* surrounding log output. The indentation level is restored once `work`
|
|
31
|
+
* finishes, even if it throws.
|
|
32
|
+
*/
|
|
33
|
+
indented<T>(work: LoggedWork<T>): T;
|
|
34
|
+
};
|
|
35
|
+
export {};
|
package/dist/src/log.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { ansiColor } from "./ansi.js";
|
|
2
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
+
import { emitRunlingEvent } from "./events.js";
|
|
4
|
+
function paint(color, text) {
|
|
5
|
+
const ansi = ansiColor(color);
|
|
6
|
+
return ansi ? `${ansi}${text}\x1b[0m` : text;
|
|
7
|
+
}
|
|
8
|
+
function highlight(text, color = "white") {
|
|
9
|
+
const ansi = ansiColor(color) ?? "";
|
|
10
|
+
return `\x1b[1m${ansi}${text}\x1b[0m`;
|
|
11
|
+
}
|
|
12
|
+
const INDENT_UNIT = " ";
|
|
13
|
+
/**
|
|
14
|
+
* Tracks how deeply nested the currently running work is. Using
|
|
15
|
+
* `AsyncLocalStorage` keeps concurrent steps (e.g. two agents running at the
|
|
16
|
+
* same time) from corrupting each other's indentation level.
|
|
17
|
+
*/
|
|
18
|
+
const depthStorage = new AsyncLocalStorage();
|
|
19
|
+
const colorStorage = new AsyncLocalStorage();
|
|
20
|
+
const destinationStorage = new AsyncLocalStorage();
|
|
21
|
+
const sourceStorage = new AsyncLocalStorage();
|
|
22
|
+
function indent() {
|
|
23
|
+
return INDENT_UNIT.repeat(depthStorage.getStore() ?? 0);
|
|
24
|
+
}
|
|
25
|
+
function write(level, message, defaultColor, source) {
|
|
26
|
+
const color = colorStorage.getStore() ?? defaultColor;
|
|
27
|
+
const contextualSource = sourceStorage.getStore();
|
|
28
|
+
emitRunlingEvent({
|
|
29
|
+
type: "log",
|
|
30
|
+
level,
|
|
31
|
+
message,
|
|
32
|
+
depth: depthStorage.getStore() ?? 0,
|
|
33
|
+
color,
|
|
34
|
+
source: source ?? contextualSource?.type,
|
|
35
|
+
sourceId: contextualSource?.id,
|
|
36
|
+
});
|
|
37
|
+
const destination = destinationStorage.getStore();
|
|
38
|
+
if (destination === "silent")
|
|
39
|
+
return;
|
|
40
|
+
const symbol = level === "success"
|
|
41
|
+
? "✓"
|
|
42
|
+
: level === "error"
|
|
43
|
+
? "✗"
|
|
44
|
+
: level === "debug"
|
|
45
|
+
? "·"
|
|
46
|
+
: "●";
|
|
47
|
+
const line = `${indent()}${paint(color, symbol)} ${message}`;
|
|
48
|
+
if (level === "error" || destination === "stderr") {
|
|
49
|
+
console.error(line);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
console.log(line);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export const logStep = (message) => write("info", message, "dodgerblue", "step");
|
|
56
|
+
export const logCommand = (id, message) => withLogSource({ type: "command", id }, () => log.info(message));
|
|
57
|
+
export const logInput = (id, level, message) => withLogSource({ type: "input", id }, () => log[level](message));
|
|
58
|
+
export const withLogSource = (source, work) => sourceStorage.run(source, work);
|
|
59
|
+
export const log = {
|
|
60
|
+
level: "info",
|
|
61
|
+
debug: (message) => {
|
|
62
|
+
if (log.level === "debug") {
|
|
63
|
+
write("debug", message, "gray");
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
info: (message) => write("info", message, "dodgerblue"),
|
|
67
|
+
success: (message) => write("success", message, "limegreen"),
|
|
68
|
+
error: (message) => write("error", message, "crimson"),
|
|
69
|
+
/** Renders `text` in the active contextual color, if there is one. */
|
|
70
|
+
colorize(text) {
|
|
71
|
+
const color = colorStorage.getStore();
|
|
72
|
+
return color === undefined ? text : paint(color, text);
|
|
73
|
+
},
|
|
74
|
+
/** Renders `text` in a bold, bright color. */
|
|
75
|
+
highlight,
|
|
76
|
+
/** Runs `work` with log markers rendered in `color`. */
|
|
77
|
+
withColor(color, work) {
|
|
78
|
+
return colorStorage.run(color, work);
|
|
79
|
+
},
|
|
80
|
+
/** Runs `work` with informational output written to `destination`. */
|
|
81
|
+
withDestination(destination, work) {
|
|
82
|
+
return destinationStorage.run(destination, work);
|
|
83
|
+
},
|
|
84
|
+
/**
|
|
85
|
+
* Runs `work` with all of its log output indented one level deeper than the
|
|
86
|
+
* surrounding log output. The indentation level is restored once `work`
|
|
87
|
+
* finishes, even if it throws.
|
|
88
|
+
*/
|
|
89
|
+
indented(work) {
|
|
90
|
+
return depthStorage.run((depthStorage.getStore() ?? 0) + 1, work);
|
|
91
|
+
},
|
|
92
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ansiColor } from "./ansi.js";
|
|
2
|
+
import { Markdown } from "@earendil-works/pi-tui";
|
|
3
|
+
const foreground = (color) => (text) => {
|
|
4
|
+
const open = ansiColor(color);
|
|
5
|
+
return open ? `${open}${text}\x1b[39m` : text;
|
|
6
|
+
};
|
|
7
|
+
const style = (open, close) => (text) => `\x1b[${open}m${text}\x1b[${close}m`;
|
|
8
|
+
const bold = style(1, 22);
|
|
9
|
+
const dim = style(2, 22);
|
|
10
|
+
const theme = {
|
|
11
|
+
heading: (text) => bold(foreground("white")(text)),
|
|
12
|
+
link: foreground("cyan"),
|
|
13
|
+
linkUrl: dim,
|
|
14
|
+
code: foreground("magenta"),
|
|
15
|
+
codeBlock: foreground("white"),
|
|
16
|
+
codeBlockBorder: dim,
|
|
17
|
+
quote: dim,
|
|
18
|
+
quoteBorder: foreground("gray"),
|
|
19
|
+
hr: foreground("gray"),
|
|
20
|
+
listBullet: foreground("cyan"),
|
|
21
|
+
bold,
|
|
22
|
+
italic: style(3, 23),
|
|
23
|
+
strikethrough: style(9, 29),
|
|
24
|
+
underline: style(4, 24),
|
|
25
|
+
};
|
|
26
|
+
/** Renders Markdown as width-aware ANSI terminal text. */
|
|
27
|
+
export const renderMarkdown = (markdown, width) => new Markdown(markdown, 0, 0, theme)
|
|
28
|
+
.render(Number.isFinite(width) && width > 0
|
|
29
|
+
? Math.max(1, Math.floor(width))
|
|
30
|
+
: 80)
|
|
31
|
+
.map((line) => line.trimEnd())
|
|
32
|
+
.join("\n");
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function parseModelReference(reference) {
|
|
2
|
+
const separator = reference.indexOf("/");
|
|
3
|
+
if (separator <= 0 || separator === reference.length - 1) {
|
|
4
|
+
throw new Error(`Invalid model reference "${reference}"; expected "provider/model-id"`);
|
|
5
|
+
}
|
|
6
|
+
return {
|
|
7
|
+
provider: reference.slice(0, separator),
|
|
8
|
+
id: reference.slice(separator + 1),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a path for display: strip the working directory prefix so paths
|
|
3
|
+
* echoed in logs look like local (project-relative) paths.
|
|
4
|
+
*/
|
|
5
|
+
export declare function displayPath(path: string, cwd?: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Best-effort removal of absolute working-directory prefixes from a free-form
|
|
8
|
+
* string (e.g. an echoed shell command) so embedded paths read as relative.
|
|
9
|
+
*/
|
|
10
|
+
export declare function displayText(text: string, cwd?: string): string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a path for display: strip the working directory prefix so paths
|
|
3
|
+
* echoed in logs look like local (project-relative) paths.
|
|
4
|
+
*/
|
|
5
|
+
export function displayPath(path, cwd = process.cwd()) {
|
|
6
|
+
if (path === cwd)
|
|
7
|
+
return ".";
|
|
8
|
+
if (path.startsWith(`${cwd}/`))
|
|
9
|
+
return path.slice(cwd.length + 1);
|
|
10
|
+
return path;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Best-effort removal of absolute working-directory prefixes from a free-form
|
|
14
|
+
* string (e.g. an echoed shell command) so embedded paths read as relative.
|
|
15
|
+
*/
|
|
16
|
+
export function displayText(text, cwd = process.cwd()) {
|
|
17
|
+
return text.replaceAll(`${cwd}/`, "");
|
|
18
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type RunlingEventListener } from "./events.ts";
|
|
2
|
+
import type { InputHandler } from "./input.ts";
|
|
3
|
+
import { type Runling, type WorkflowResult, type WorkflowReturn } from "./runtime.ts";
|
|
4
|
+
import type { Static, TSchema } from "typebox";
|
|
5
|
+
import { type Workflow } from "./workflow.ts";
|
|
6
|
+
import { getRecordedTokenUsage } from "./usage.ts";
|
|
7
|
+
export declare function formatDuration(ms: number): string;
|
|
8
|
+
export interface WorkflowExecution<Output = unknown> {
|
|
9
|
+
durationMs: number;
|
|
10
|
+
usage: ReturnType<typeof getRecordedTokenUsage>;
|
|
11
|
+
output: Output | null;
|
|
12
|
+
result: WorkflowResult | null;
|
|
13
|
+
error: string | null;
|
|
14
|
+
ok: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface TerminalCapabilities {
|
|
17
|
+
isTTY?: boolean;
|
|
18
|
+
columns?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface ExecutionOptions {
|
|
21
|
+
json?: boolean;
|
|
22
|
+
presentation?: "log" | "tui";
|
|
23
|
+
terminal?: TerminalCapabilities;
|
|
24
|
+
title?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface RunWorkflowOptions<Input = unknown> {
|
|
27
|
+
cwd?: string;
|
|
28
|
+
input: Input;
|
|
29
|
+
verbose?: boolean;
|
|
30
|
+
onInput?: InputHandler;
|
|
31
|
+
onEvent?: RunlingEventListener;
|
|
32
|
+
}
|
|
33
|
+
export declare function formatWorkflowDetails(details: string, terminal?: TerminalCapabilities): string;
|
|
34
|
+
export declare function normalizeWorkflowResult(value: unknown): WorkflowResult | null;
|
|
35
|
+
export declare function executeWorkflow(run: (f: Runling) => Promise<WorkflowReturn> | WorkflowReturn, f: Runling, options?: ExecutionOptions): Promise<WorkflowExecution>;
|
|
36
|
+
/** Run a workflow without assuming a terminal, printing, or changing process state. */
|
|
37
|
+
export declare function runWorkflow<InputSchema extends TSchema, OutputSchema extends TSchema>(run: Workflow<InputSchema, OutputSchema>, { cwd, input, verbose, onInput, onEvent, }: RunWorkflowOptions<Static<InputSchema>>): Promise<WorkflowExecution<Static<OutputSchema>>>;
|
|
38
|
+
export declare function loadWorkflow(path: string): Promise<Workflow>;
|
|
39
|
+
export declare function runRunling(argv?: readonly string[]): Promise<void>;
|
|
40
|
+
export declare function shouldUseTui(argv: readonly string[], terminal?: {
|
|
41
|
+
stdinIsTTY?: boolean;
|
|
42
|
+
stdoutIsTTY?: boolean;
|
|
43
|
+
}): boolean;
|