oharness 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/dist/bin/sync.d.ts +3 -0
- package/dist/bin/sync.js +4 -0
- package/dist/bin/sync.js.map +1 -0
- package/dist/bin/web.d.ts +10 -0
- package/dist/bin/web.js +11 -0
- package/dist/bin/web.js.map +1 -0
- package/dist/headless/main.d.ts +2 -0
- package/dist/headless/main.js +133 -0
- package/dist/headless/main.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/providers.d.ts +2 -0
- package/dist/providers.js +3 -0
- package/dist/providers.js.map +1 -0
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +3 -0
- package/dist/tools.js.map +1 -0
- package/dist/ui/artifact.d.ts +32 -0
- package/dist/ui/artifact.js +49 -0
- package/dist/ui/artifact.js.map +1 -0
- package/dist/ui/auth.d.ts +14 -0
- package/dist/ui/auth.js +177 -0
- package/dist/ui/auth.js.map +1 -0
- package/dist/ui/colors.d.ts +21 -0
- package/dist/ui/colors.js +28 -0
- package/dist/ui/colors.js.map +1 -0
- package/dist/ui/ink/app.d.ts +13 -0
- package/dist/ui/ink/app.js +418 -0
- package/dist/ui/ink/app.js.map +1 -0
- package/dist/ui/ink/logo.d.ts +6 -0
- package/dist/ui/ink/logo.js +20 -0
- package/dist/ui/ink/logo.js.map +1 -0
- package/dist/ui/ink/main.d.ts +2 -0
- package/dist/ui/ink/main.js +55 -0
- package/dist/ui/ink/main.js.map +1 -0
- package/dist/ui/ink/screen.d.ts +15 -0
- package/dist/ui/ink/screen.js +76 -0
- package/dist/ui/ink/screen.js.map +1 -0
- package/dist/ui/ink/select.d.ts +24 -0
- package/dist/ui/ink/select.js +74 -0
- package/dist/ui/ink/select.js.map +1 -0
- package/dist/ui/main.d.ts +2 -0
- package/dist/ui/main.js +1062 -0
- package/dist/ui/main.js.map +1 -0
- package/dist/ui/render.d.ts +15 -0
- package/dist/ui/render.js +130 -0
- package/dist/ui/render.js.map +1 -0
- package/dist/ui/select.d.ts +26 -0
- package/dist/ui/select.js +107 -0
- package/dist/ui/select.js.map +1 -0
- package/dist/ui/tui/app.d.ts +96 -0
- package/dist/ui/tui/app.js +476 -0
- package/dist/ui/tui/app.js.map +1 -0
- package/dist/ui/tui/editor.d.ts +40 -0
- package/dist/ui/tui/editor.js +124 -0
- package/dist/ui/tui/editor.js.map +1 -0
- package/dist/ui/tui/keys.d.ts +25 -0
- package/dist/ui/tui/keys.js +133 -0
- package/dist/ui/tui/keys.js.map +1 -0
- package/dist/ui/tui/layout.d.ts +63 -0
- package/dist/ui/tui/layout.js +202 -0
- package/dist/ui/tui/layout.js.map +1 -0
- package/dist/ui/tui/logo.d.ts +18 -0
- package/dist/ui/tui/logo.js +33 -0
- package/dist/ui/tui/logo.js.map +1 -0
- package/dist/ui/tui/screen.d.ts +48 -0
- package/dist/ui/tui/screen.js +150 -0
- package/dist/ui/tui/screen.js.map +1 -0
- package/dist/ui/tui/width.d.ts +30 -0
- package/dist/ui/tui/width.js +197 -0
- package/dist/ui/tui/width.js.map +1 -0
- package/dist/ui/wordmark.d.ts +30 -0
- package/dist/ui/wordmark.js +63 -0
- package/dist/ui/wordmark.js.map +1 -0
- package/package.json +49 -0
package/dist/bin/sync.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/bin/sync.ts"],"names":[],"mappings":";AACA,yEAAyE;AACzE,OAAO,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The `oharness-web` binary.
|
|
4
|
+
*
|
|
5
|
+
* The server lives in its own package so it can be deployed without a terminal
|
|
6
|
+
* frontend attached. This shim exists so a single `npm i -g oharness` still
|
|
7
|
+
* puts every frontend on the PATH: npm links the bins of the package being
|
|
8
|
+
* installed, not the bins of its dependencies.
|
|
9
|
+
*/
|
|
10
|
+
import "@oharness/server/main.ts";
|
package/dist/bin/web.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The `oharness-web` binary.
|
|
4
|
+
*
|
|
5
|
+
* The server lives in its own package so it can be deployed without a terminal
|
|
6
|
+
* frontend attached. This shim exists so a single `npm i -g oharness` still
|
|
7
|
+
* puts every frontend on the PATH: npm links the bins of the package being
|
|
8
|
+
* installed, not the bins of its dependencies.
|
|
9
|
+
*/
|
|
10
|
+
import "@oharness/server/main.ts";
|
|
11
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/bin/web.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AACH,OAAO,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Harness } from "@oharness/engine/harness.ts";
|
|
3
|
+
import { errorMessage } from "@oharness/engine/core/errors.ts";
|
|
4
|
+
const HELP = `oharness-headless — run an agent with no UI
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
oharness-headless [options] [prompt]
|
|
8
|
+
echo "prompt" | oharness-headless [options]
|
|
9
|
+
|
|
10
|
+
Writes one JSON object per line to stdout: the AgentEvent stream, ending with
|
|
11
|
+
a "done" event. Diagnostics go to stderr. Exit code is 1 if the run failed.
|
|
12
|
+
|
|
13
|
+
Options:
|
|
14
|
+
-m, --model <id> Model alias or provider/model
|
|
15
|
+
-r, --resume <id> Continue an existing session
|
|
16
|
+
-C, --cwd <dir> Working directory for the agent
|
|
17
|
+
--permission-mode <m> default | acceptEdits | plan | auto | bypassPermissions
|
|
18
|
+
-h, --help Show this help
|
|
19
|
+
|
|
20
|
+
Nobody is present to answer a permission prompt, so anything that would ask is
|
|
21
|
+
denied and reported as a permission_result event. Pre-authorize work with
|
|
22
|
+
permission rules in settings, or pass --permission-mode.`;
|
|
23
|
+
function parseArgs(argv) {
|
|
24
|
+
const args = { help: false };
|
|
25
|
+
const rest = [];
|
|
26
|
+
for (let i = 0; i < argv.length; i++) {
|
|
27
|
+
const arg = argv[i];
|
|
28
|
+
switch (arg) {
|
|
29
|
+
case "-m":
|
|
30
|
+
case "--model":
|
|
31
|
+
args.model = argv[++i];
|
|
32
|
+
break;
|
|
33
|
+
case "-r":
|
|
34
|
+
case "--resume":
|
|
35
|
+
args.resume = argv[++i];
|
|
36
|
+
break;
|
|
37
|
+
case "-C":
|
|
38
|
+
case "--cwd":
|
|
39
|
+
args.cwd = argv[++i];
|
|
40
|
+
break;
|
|
41
|
+
case "--permission-mode":
|
|
42
|
+
args.permissionMode = argv[++i];
|
|
43
|
+
break;
|
|
44
|
+
case "-h":
|
|
45
|
+
case "--help":
|
|
46
|
+
args.help = true;
|
|
47
|
+
break;
|
|
48
|
+
default:
|
|
49
|
+
rest.push(arg);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (rest.length)
|
|
53
|
+
args.prompt = rest.join(" ");
|
|
54
|
+
return args;
|
|
55
|
+
}
|
|
56
|
+
/** Everything piped in, so `echo ... | oharness-headless` works. */
|
|
57
|
+
async function readStdin() {
|
|
58
|
+
if (process.stdin.isTTY)
|
|
59
|
+
return "";
|
|
60
|
+
const chunks = [];
|
|
61
|
+
for await (const chunk of process.stdin)
|
|
62
|
+
chunks.push(chunk);
|
|
63
|
+
return Buffer.concat(chunks).toString("utf8").trim();
|
|
64
|
+
}
|
|
65
|
+
function emit(event) {
|
|
66
|
+
process.stdout.write(`${JSON.stringify(event)}\n`);
|
|
67
|
+
}
|
|
68
|
+
async function main() {
|
|
69
|
+
const args = parseArgs(process.argv.slice(2));
|
|
70
|
+
if (args.help) {
|
|
71
|
+
console.log(HELP);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const prompt = args.prompt || (await readStdin());
|
|
75
|
+
if (!prompt) {
|
|
76
|
+
emit({ type: "error", error: "no prompt given (pass one as an argument or on stdin)", fatal: true });
|
|
77
|
+
process.exitCode = 1;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const harness = await Harness.create({
|
|
81
|
+
...(args.cwd ? { cwd: args.cwd } : {}),
|
|
82
|
+
// There is no one to ask. Denying is the only honest answer — silently
|
|
83
|
+
// approving would make unattended runs strictly more dangerous than
|
|
84
|
+
// attended ones, which is backwards.
|
|
85
|
+
permissionPrompt: async () => false,
|
|
86
|
+
});
|
|
87
|
+
if (args.permissionMode)
|
|
88
|
+
harness.config.permissionMode = args.permissionMode;
|
|
89
|
+
const controller = new AbortController();
|
|
90
|
+
// Supervisors send SIGTERM; both should stop the turn rather than leave a
|
|
91
|
+
// half-written transcript behind.
|
|
92
|
+
const stop = () => controller.abort();
|
|
93
|
+
process.on("SIGINT", stop);
|
|
94
|
+
process.on("SIGTERM", stop);
|
|
95
|
+
let failed = false;
|
|
96
|
+
// Everything after `Harness.create` runs inside this block: MCP servers are
|
|
97
|
+
// already spawned by then, so an exception on the way to the first turn —
|
|
98
|
+
// an unresolvable model, for instance — must still reach `close()` or it
|
|
99
|
+
// leaves subprocesses behind.
|
|
100
|
+
try {
|
|
101
|
+
const session = args.resume
|
|
102
|
+
? ((await harness.resumeSession(args.resume, args.model)) ??
|
|
103
|
+
(await harness.createSession({ model: args.model })))
|
|
104
|
+
: await harness.createSession({ model: args.model });
|
|
105
|
+
if (args.resume && session.id !== args.resume) {
|
|
106
|
+
emit({ type: "notice", message: `no session ${args.resume}; started ${session.id}` });
|
|
107
|
+
}
|
|
108
|
+
emit({ type: "session", id: session.id, model: session.model.id, cwd: session.cwd });
|
|
109
|
+
for await (const event of harness.agent(session).run(prompt, { signal: controller.signal })) {
|
|
110
|
+
emit(event);
|
|
111
|
+
if (event.type === "error" && event.fatal)
|
|
112
|
+
failed = true;
|
|
113
|
+
if (event.type === "done" && event.stopReason === "error")
|
|
114
|
+
failed = true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
emit({ type: "error", error: errorMessage(err), fatal: true });
|
|
119
|
+
failed = true;
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
process.off("SIGINT", stop);
|
|
123
|
+
process.off("SIGTERM", stop);
|
|
124
|
+
await harness.close();
|
|
125
|
+
}
|
|
126
|
+
if (failed)
|
|
127
|
+
process.exitCode = 1;
|
|
128
|
+
}
|
|
129
|
+
main().catch((err) => {
|
|
130
|
+
emit({ type: "error", error: errorMessage(err), fatal: true });
|
|
131
|
+
process.exitCode = 1;
|
|
132
|
+
});
|
|
133
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/headless/main.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `oharness` library surface.
|
|
3
|
+
*
|
|
4
|
+
* The engine is its own package now, but embedding applications installed
|
|
5
|
+
* `oharness` and imported from it — so this re-exports the engine whole
|
|
6
|
+
* rather than making every one of them change an import to gain nothing.
|
|
7
|
+
*/
|
|
8
|
+
export * from "@oharness/engine";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `oharness` library surface.
|
|
3
|
+
*
|
|
4
|
+
* The engine is its own package now, but embedding applications installed
|
|
5
|
+
* `oharness` and imported from it — so this re-exports the engine whole
|
|
6
|
+
* rather than making every one of them change an import to gain nothing.
|
|
7
|
+
*/
|
|
8
|
+
export * from "@oharness/engine";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,cAAc,qCAAqC,CAAC"}
|
package/dist/tools.d.ts
ADDED
package/dist/tools.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,cAAc,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ArtifactDescriptor, ArtifactKind } from "@oharness/engine/artifacts/store.ts";
|
|
2
|
+
/**
|
|
3
|
+
* What the terminal does with each kind of artifact.
|
|
4
|
+
*
|
|
5
|
+
* This table is the terminal's half of the contract in artifacts/store.ts, and
|
|
6
|
+
* the reason it is a table rather than a switch buried in a renderer: every
|
|
7
|
+
* kind must have an answer here, including the kinds a terminal cannot show,
|
|
8
|
+
* and `test/artifacts.test.ts` fails if one is missing. Without that, adding a
|
|
9
|
+
* kind would light it up in the browser and leave a silent blank here — the
|
|
10
|
+
* exact failure the contract exists to prevent.
|
|
11
|
+
*
|
|
12
|
+
* `inline` means the body itself is worth putting on screen. `refusal` is the
|
|
13
|
+
* honest sentence shown when it is not: a terminal that pretends to render a
|
|
14
|
+
* PNG is worse than one that says where to go and gets out of the way.
|
|
15
|
+
*/
|
|
16
|
+
export interface TerminalRendering {
|
|
17
|
+
inline: boolean;
|
|
18
|
+
refusal?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const TERMINAL_ARTIFACT_RENDERING: Record<ArtifactKind, TerminalRendering>;
|
|
21
|
+
/** Guards against a kind being added to the engine and forgotten here. */
|
|
22
|
+
export declare function unhandledKinds(): ArtifactKind[];
|
|
23
|
+
export declare function formatBytes(bytes: number): string;
|
|
24
|
+
/**
|
|
25
|
+
* The one-line summary, shared by both terminal frontends so an artifact reads
|
|
26
|
+
* the same whether or not the full-screen UI is running.
|
|
27
|
+
*/
|
|
28
|
+
export declare function artifactSummary(artifact: ArtifactDescriptor): string;
|
|
29
|
+
/** The dimmed second line: either a refusal or nothing. */
|
|
30
|
+
export declare function artifactNote(artifact: ArtifactDescriptor): string | undefined;
|
|
31
|
+
/** Whether this kind's body should be previewed inline in the terminal. */
|
|
32
|
+
export declare function rendersInline(kind: ArtifactKind): boolean;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ARTIFACT_KINDS } from "@oharness/engine/artifacts/store.ts";
|
|
2
|
+
import { c } from "./colors.js";
|
|
3
|
+
export const TERMINAL_ARTIFACT_RENDERING = {
|
|
4
|
+
// Prose and source are what a terminal is for.
|
|
5
|
+
text: { inline: true },
|
|
6
|
+
markdown: { inline: true },
|
|
7
|
+
code: { inline: true },
|
|
8
|
+
// SVG is source as much as it is a picture, and reading the markup is a real
|
|
9
|
+
// (if narrow) answer — but printing 40 lines of path data helps nobody, so
|
|
10
|
+
// it gets the summary and an offer rather than the body.
|
|
11
|
+
vector: { inline: false, refusal: "vector image — open the web frontend to see it rendered" },
|
|
12
|
+
// Raster bytes. Some terminals do support inline images (kitty, iTerm2,
|
|
13
|
+
// sixel), which would mean rasterising here and taking a dependency the
|
|
14
|
+
// CLI's pinned list deliberately makes someone justify. Not worth it yet.
|
|
15
|
+
image: { inline: false, refusal: "image — open the web frontend to see it" },
|
|
16
|
+
// HTML that has to execute to mean anything. There is no textual degradation
|
|
17
|
+
// of a page: its source is not the artifact, the rendered result is.
|
|
18
|
+
page: { inline: false, refusal: "HTML page — open the web frontend to see it rendered" },
|
|
19
|
+
};
|
|
20
|
+
/** Guards against a kind being added to the engine and forgotten here. */
|
|
21
|
+
export function unhandledKinds() {
|
|
22
|
+
return ARTIFACT_KINDS.filter((kind) => TERMINAL_ARTIFACT_RENDERING[kind] === undefined);
|
|
23
|
+
}
|
|
24
|
+
export function formatBytes(bytes) {
|
|
25
|
+
if (bytes < 1024)
|
|
26
|
+
return `${bytes} B`;
|
|
27
|
+
if (bytes < 1024 * 1024)
|
|
28
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
29
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The one-line summary, shared by both terminal frontends so an artifact reads
|
|
33
|
+
* the same whether or not the full-screen UI is running.
|
|
34
|
+
*/
|
|
35
|
+
export function artifactSummary(artifact) {
|
|
36
|
+
const parts = [artifact.kind, formatBytes(artifact.bytes)];
|
|
37
|
+
if (artifact.version > 1)
|
|
38
|
+
parts.push(`v${artifact.version}`);
|
|
39
|
+
return `${artifact.title} ${c.gray(`(${parts.join(" · ")})`)}`;
|
|
40
|
+
}
|
|
41
|
+
/** The dimmed second line: either a refusal or nothing. */
|
|
42
|
+
export function artifactNote(artifact) {
|
|
43
|
+
return TERMINAL_ARTIFACT_RENDERING[artifact.kind]?.refusal;
|
|
44
|
+
}
|
|
45
|
+
/** Whether this kind's body should be previewed inline in the terminal. */
|
|
46
|
+
export function rendersInline(kind) {
|
|
47
|
+
return TERMINAL_ARTIFACT_RENDERING[kind]?.inline === true;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=artifact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact.js","sourceRoot":"","sources":["../../src/ui/artifact.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,CAAC,EAAE,MAAM,aAAa,CAAC;AAqBhC,MAAM,CAAC,MAAM,2BAA2B,GAA4C;IAClF,+CAA+C;IAC/C,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;IACtB,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;IAC1B,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;IACtB,6EAA6E;IAC7E,2EAA2E;IAC3E,yDAAyD;IACzD,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,yDAAyD,EAAE;IAC7F,wEAAwE;IACxE,wEAAwE;IACxE,0EAA0E;IAC1E,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,yCAAyC,EAAE;IAC5E,6EAA6E;IAC7E,qEAAqE;IACrE,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,sDAAsD,EAAE;CACzF,CAAC;AAEF,0EAA0E;AAC1E,MAAM,UAAU,cAAc;IAC5B,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,2BAA2B,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,IAAI,CAAC;IACtC,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAClE,OAAO,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AACpD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAA4B;IAC1D,MAAM,KAAK,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3D,IAAI,QAAQ,CAAC,OAAO,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7D,OAAO,GAAG,QAAQ,CAAC,KAAK,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;AAClE,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,YAAY,CAAC,QAA4B;IACvD,OAAO,2BAA2B,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;AAC7D,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,aAAa,CAAC,IAAkB;IAC9C,OAAO,2BAA2B,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { createInterface } from "node:readline/promises";
|
|
2
|
+
import type { AuthManager } from "@oharness/engine/auth/manager.ts";
|
|
3
|
+
type Readline = ReturnType<typeof createInterface>;
|
|
4
|
+
/**
|
|
5
|
+
* Interactive login, driven entirely off the provider's declared methods.
|
|
6
|
+
*
|
|
7
|
+
* Nothing here knows what any particular vendor needs — prompts, conditional
|
|
8
|
+
* fields and the choice between flows all come from the declaration, which is
|
|
9
|
+
* what lets a new subscription provider be added without touching the CLI.
|
|
10
|
+
*/
|
|
11
|
+
export declare function runLogin(auth: AuthManager, rl: Readline, providerId?: string): Promise<void>;
|
|
12
|
+
export declare function runLogout(auth: AuthManager, providerId: string): Promise<void>;
|
|
13
|
+
export declare function printAuthStatus(auth: AuthManager): Promise<void>;
|
|
14
|
+
export {};
|
package/dist/ui/auth.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { errorMessage } from "@oharness/engine/core/errors.ts";
|
|
3
|
+
import { c } from "./render.js";
|
|
4
|
+
/**
|
|
5
|
+
* Interactive login, driven entirely off the provider's declared methods.
|
|
6
|
+
*
|
|
7
|
+
* Nothing here knows what any particular vendor needs — prompts, conditional
|
|
8
|
+
* fields and the choice between flows all come from the declaration, which is
|
|
9
|
+
* what lets a new subscription provider be added without touching the CLI.
|
|
10
|
+
*/
|
|
11
|
+
export async function runLogin(auth, rl, providerId) {
|
|
12
|
+
const provider = providerId
|
|
13
|
+
? auth.get(providerId)
|
|
14
|
+
: await pickProvider(auth, rl);
|
|
15
|
+
if (!provider) {
|
|
16
|
+
console.log(c.red(`Unknown provider${providerId ? ` "${providerId}"` : ""}. Known: ${auth
|
|
17
|
+
.list()
|
|
18
|
+
.map((p) => p.id)
|
|
19
|
+
.join(", ")}`));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (provider.methods.length === 0) {
|
|
23
|
+
console.log(c.yellow(`${provider.label} declares no login methods.`));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const methodIndex = await pickMethod(provider.methods, rl);
|
|
27
|
+
if (methodIndex === undefined)
|
|
28
|
+
return;
|
|
29
|
+
const method = provider.methods[methodIndex];
|
|
30
|
+
const answers = await collectAnswers(auth, method, rl);
|
|
31
|
+
if (!answers)
|
|
32
|
+
return;
|
|
33
|
+
try {
|
|
34
|
+
if (method.type === "api") {
|
|
35
|
+
await auth.submit(provider.id, methodIndex, answers);
|
|
36
|
+
console.log(c.green(`✓ Signed in to ${provider.label}`));
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const flow = await auth.authorize(provider.id, methodIndex, answers);
|
|
40
|
+
console.log(`\n${c.bold(flow.instructions)}`);
|
|
41
|
+
// A flow with no URL delivers its code elsewhere (email); printing and
|
|
42
|
+
// opening an empty address would just look broken.
|
|
43
|
+
if (flow.url) {
|
|
44
|
+
console.log(c.cyan(flow.url));
|
|
45
|
+
await openBrowser(flow.url);
|
|
46
|
+
}
|
|
47
|
+
if (flow.method === "auto") {
|
|
48
|
+
console.log(c.gray("\nWaiting for authorization…"));
|
|
49
|
+
const result = await flow.callback();
|
|
50
|
+
await auth.complete(provider.id, result);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const code = (await rl.question(c.yellow("\nPaste the code here: "))).trim();
|
|
54
|
+
if (!code) {
|
|
55
|
+
console.log(c.yellow("Cancelled."));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const result = await flow.callback(code);
|
|
59
|
+
await auth.complete(provider.id, result);
|
|
60
|
+
}
|
|
61
|
+
console.log(c.green(`✓ Signed in to ${provider.label}`));
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
console.log(c.red(`✗ Login failed: ${errorMessage(err)}`));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export async function runLogout(auth, providerId) {
|
|
68
|
+
const removed = await auth.logout(providerId);
|
|
69
|
+
console.log(removed
|
|
70
|
+
? c.green(`✓ Removed stored credentials for ${providerId}`)
|
|
71
|
+
: c.yellow(`No stored credentials for ${providerId}`));
|
|
72
|
+
// Env-var credentials survive logout, and silently continuing to work is
|
|
73
|
+
// exactly the kind of thing that wastes an afternoon.
|
|
74
|
+
if (await auth.isAuthenticated(providerId)) {
|
|
75
|
+
const resolved = await auth.resolve({ providerId });
|
|
76
|
+
console.log(c.yellow(`Note: ${providerId} still authenticates via ${resolved?.source ?? "another source"}.`));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export async function printAuthStatus(auth) {
|
|
80
|
+
const statuses = await auth.status();
|
|
81
|
+
for (const status of statuses) {
|
|
82
|
+
const mark = status.authenticated ? c.green("✓") : c.gray("○");
|
|
83
|
+
const detail = status.authenticated
|
|
84
|
+
? c.gray(status.source ?? "authenticated")
|
|
85
|
+
: c.gray("not signed in");
|
|
86
|
+
const expiry = status.expiresAt && status.expiresAt > 0
|
|
87
|
+
? c.gray(` expires ${new Date(status.expiresAt).toISOString().slice(0, 16).replace("T", " ")}`)
|
|
88
|
+
: "";
|
|
89
|
+
console.log(`${mark} ${status.providerId.padEnd(12)} ${detail}${expiry}`);
|
|
90
|
+
}
|
|
91
|
+
console.log(c.gray(`\nCredentials: ${auth.store.location}`));
|
|
92
|
+
console.log(c.gray("Sign in with: oharness auth login <provider>"));
|
|
93
|
+
}
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
async function pickProvider(auth, rl) {
|
|
96
|
+
const providers = auth.list();
|
|
97
|
+
console.log(c.bold("Which provider?"));
|
|
98
|
+
providers.forEach((provider, index) => {
|
|
99
|
+
console.log(` ${index + 1}. ${provider.label} ${c.gray(`(${provider.id})`)}`);
|
|
100
|
+
});
|
|
101
|
+
const answer = (await rl.question(c.yellow("> "))).trim();
|
|
102
|
+
const index = Number(answer) - 1;
|
|
103
|
+
return Number.isInteger(index) ? providers[index] : undefined;
|
|
104
|
+
}
|
|
105
|
+
async function pickMethod(methods, rl) {
|
|
106
|
+
if (methods.length === 1)
|
|
107
|
+
return 0;
|
|
108
|
+
console.log(c.bold("\nHow do you want to sign in?"));
|
|
109
|
+
methods.forEach((method, index) => {
|
|
110
|
+
console.log(` ${index + 1}. ${method.label} ${c.gray(`(${method.type})`)}`);
|
|
111
|
+
});
|
|
112
|
+
const answer = (await rl.question(c.yellow("> "))).trim();
|
|
113
|
+
const index = Number(answer) - 1;
|
|
114
|
+
if (!Number.isInteger(index) || index < 0 || index >= methods.length) {
|
|
115
|
+
console.log(c.yellow("Cancelled."));
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
return index;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Walk the declared prompts. Re-filtered after each answer so a `when`
|
|
122
|
+
* condition can reveal or hide later prompts based on what was just entered.
|
|
123
|
+
*/
|
|
124
|
+
async function collectAnswers(auth, method, rl) {
|
|
125
|
+
const answers = {};
|
|
126
|
+
const asked = new Set();
|
|
127
|
+
while (true) {
|
|
128
|
+
const pending = auth
|
|
129
|
+
.promptsFor(method, answers)
|
|
130
|
+
.find((prompt) => !asked.has(prompt.key));
|
|
131
|
+
if (!pending)
|
|
132
|
+
break;
|
|
133
|
+
asked.add(pending.key);
|
|
134
|
+
const value = await ask(pending, rl);
|
|
135
|
+
if (value === undefined) {
|
|
136
|
+
console.log(c.yellow("Cancelled."));
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
answers[pending.key] = value;
|
|
140
|
+
if (pending.type === "text" && pending.validate) {
|
|
141
|
+
const error = pending.validate(value);
|
|
142
|
+
if (error) {
|
|
143
|
+
console.log(c.red(` ${error}`));
|
|
144
|
+
asked.delete(pending.key);
|
|
145
|
+
delete answers[pending.key];
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return answers;
|
|
150
|
+
}
|
|
151
|
+
async function ask(prompt, rl) {
|
|
152
|
+
if (prompt.type === "select") {
|
|
153
|
+
console.log(`\n${prompt.message}`);
|
|
154
|
+
prompt.options.forEach((option, index) => {
|
|
155
|
+
console.log(` ${index + 1}. ${option.label}${option.hint ? c.gray(` — ${option.hint}`) : ""}`);
|
|
156
|
+
});
|
|
157
|
+
const answer = (await rl.question(c.yellow("> "))).trim();
|
|
158
|
+
const index = Number(answer) - 1;
|
|
159
|
+
return prompt.options[index]?.value;
|
|
160
|
+
}
|
|
161
|
+
const suffix = prompt.placeholder ? c.gray(` (${prompt.placeholder})`) : "";
|
|
162
|
+
const answer = await rl.question(`\n${prompt.message}${suffix}${c.yellow(": ")}`);
|
|
163
|
+
return answer.trim() === "" ? undefined : answer.trim();
|
|
164
|
+
}
|
|
165
|
+
/** Best effort — a headless host just reads the URL off the terminal. */
|
|
166
|
+
async function openBrowser(url) {
|
|
167
|
+
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
168
|
+
try {
|
|
169
|
+
const child = spawn(command, [url], { stdio: "ignore", detached: true });
|
|
170
|
+
child.on("error", () => { });
|
|
171
|
+
child.unref();
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
// Ignore: the URL is already printed above.
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/ui/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ANSI colour, and the decision of whether to use it.
|
|
3
|
+
*
|
|
4
|
+
* Its own module because both the event renderer and the artifact table need
|
|
5
|
+
* it, and having the table import it from the renderer put a cycle between
|
|
6
|
+
* them. The cycle happened to be safe — nothing touches `c` at module scope —
|
|
7
|
+
* but "happens to be safe" is a property that survives exactly until someone
|
|
8
|
+
* adds a top-level constant that uses it.
|
|
9
|
+
*/
|
|
10
|
+
export declare const c: {
|
|
11
|
+
dim: (s: string) => string;
|
|
12
|
+
bold: (s: string) => string;
|
|
13
|
+
red: (s: string) => string;
|
|
14
|
+
green: (s: string) => string;
|
|
15
|
+
yellow: (s: string) => string;
|
|
16
|
+
blue: (s: string) => string;
|
|
17
|
+
magenta: (s: string) => string;
|
|
18
|
+
cyan: (s: string) => string;
|
|
19
|
+
gray: (s: string) => string;
|
|
20
|
+
lime: (s: string) => string;
|
|
21
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ANSI colour, and the decision of whether to use it.
|
|
3
|
+
*
|
|
4
|
+
* Its own module because both the event renderer and the artifact table need
|
|
5
|
+
* it, and having the table import it from the renderer put a cycle between
|
|
6
|
+
* them. The cycle happened to be safe — nothing touches `c` at module scope —
|
|
7
|
+
* but "happens to be safe" is a property that survives exactly until someone
|
|
8
|
+
* adds a top-level constant that uses it.
|
|
9
|
+
*/
|
|
10
|
+
const useColor = process.stdout.isTTY && process.env["NO_COLOR"] === undefined;
|
|
11
|
+
const ESC = "\u001b";
|
|
12
|
+
const code = (n) => (s) => (useColor ? `${ESC}[${n}m${s}${ESC}[0m` : s);
|
|
13
|
+
export const c = {
|
|
14
|
+
dim: code("2"),
|
|
15
|
+
bold: code("1"),
|
|
16
|
+
red: code("31"),
|
|
17
|
+
green: code("32"),
|
|
18
|
+
yellow: code("33"),
|
|
19
|
+
blue: code("34"),
|
|
20
|
+
magenta: code("35"),
|
|
21
|
+
cyan: code("36"),
|
|
22
|
+
gray: code("90"),
|
|
23
|
+
// The brand's yellow-green, as a 256-colour index rather than one of the
|
|
24
|
+
// eight: the basic green is whatever the user's theme decided green is, and
|
|
25
|
+
// a mark that changes hue per terminal is not a mark.
|
|
26
|
+
lime: code("38;5;154"),
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=colors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/ui/colors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,SAAS,CAAC;AAE/E,MAAM,GAAG,GAAG,QAAQ,CAAC;AACrB,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAExF,MAAM,CAAC,MAAM,CAAC,GAAG;IACf,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;IACd,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;IACf,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC;IACf,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC;IACjB,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC;IAClB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC;IACnB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;IAChB,yEAAyE;IACzE,4EAA4E;IAC5E,sDAAsD;IACtD,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC;CACvB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Agent } from "@oharness/engine/agent/agent.ts";
|
|
3
|
+
import type { Session } from "@oharness/engine/agent/session.ts";
|
|
4
|
+
import type { Harness } from "@oharness/engine/harness.ts";
|
|
5
|
+
import type { PermissionRequest } from "@oharness/engine/agent/permissions.ts";
|
|
6
|
+
export interface InkAppProps {
|
|
7
|
+
harness: Harness;
|
|
8
|
+
session: Session;
|
|
9
|
+
agent: Agent;
|
|
10
|
+
/** Registered by the app so the engine's prompt reaches this component. */
|
|
11
|
+
bindPrompt: (prompt: (request: PermissionRequest) => Promise<boolean>) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function App({ harness, session, agent, bindPrompt }: InkAppProps): React.ReactElement;
|