toolcraft-openapi 0.0.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/README.md +64 -0
- package/dist/api-command.d.ts +7 -0
- package/dist/api-command.js +4 -0
- package/dist/auth/bearer-token-auth.d.ts +8 -0
- package/dist/auth/bearer-token-auth.js +216 -0
- package/dist/auth/types.d.ts +9 -0
- package/dist/auth/types.js +1 -0
- package/dist/bin/generate.d.ts +40 -0
- package/dist/bin/generate.js +248 -0
- package/dist/define-client.d.ts +20 -0
- package/dist/define-client.js +148 -0
- package/dist/generate.d.ts +210 -0
- package/dist/generate.js +1131 -0
- package/dist/group-by-noun.d.ts +6 -0
- package/dist/group-by-noun.js +17 -0
- package/dist/http.d.ts +26 -0
- package/dist/http.js +123 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +6 -0
- package/dist/interpreter.d.ts +6 -0
- package/dist/interpreter.js +289 -0
- package/dist/lock.d.ts +14 -0
- package/dist/lock.js +48 -0
- package/dist/naming.d.ts +24 -0
- package/dist/naming.js +218 -0
- package/dist/request-shape.d.ts +15 -0
- package/dist/request-shape.js +5 -0
- package/dist/runtime.d.ts +13 -0
- package/dist/runtime.js +94 -0
- package/dist/spec-source.d.ts +11 -0
- package/dist/spec-source.js +63 -0
- package/node_modules/@poe-code/design-system/dist/acp/components.d.ts +11 -0
- package/node_modules/@poe-code/design-system/dist/acp/components.js +121 -0
- package/node_modules/@poe-code/design-system/dist/acp/index.d.ts +3 -0
- package/node_modules/@poe-code/design-system/dist/acp/index.js +2 -0
- package/node_modules/@poe-code/design-system/dist/acp/writer.d.ts +13 -0
- package/node_modules/@poe-code/design-system/dist/acp/writer.js +21 -0
- package/node_modules/@poe-code/design-system/dist/components/command-errors.d.ts +16 -0
- package/node_modules/@poe-code/design-system/dist/components/command-errors.js +22 -0
- package/node_modules/@poe-code/design-system/dist/components/help-formatter.d.ts +20 -0
- package/node_modules/@poe-code/design-system/dist/components/help-formatter.js +27 -0
- package/node_modules/@poe-code/design-system/dist/components/index.d.ts +10 -0
- package/node_modules/@poe-code/design-system/dist/components/index.js +7 -0
- package/node_modules/@poe-code/design-system/dist/components/logger.d.ts +11 -0
- package/node_modules/@poe-code/design-system/dist/components/logger.js +60 -0
- package/node_modules/@poe-code/design-system/dist/components/symbols.d.ts +12 -0
- package/node_modules/@poe-code/design-system/dist/components/symbols.js +71 -0
- package/node_modules/@poe-code/design-system/dist/components/table.d.ts +13 -0
- package/node_modules/@poe-code/design-system/dist/components/table.js +74 -0
- package/node_modules/@poe-code/design-system/dist/components/text.d.ts +14 -0
- package/node_modules/@poe-code/design-system/dist/components/text.js +104 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/ansi.d.ts +18 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/ansi.js +298 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/buffer.d.ts +25 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/buffer.js +189 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/border.d.ts +9 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/border.js +123 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/footer.d.ts +8 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/footer.js +57 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/output-pane.d.ts +12 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/output-pane.js +254 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/stats-pane.d.ts +7 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/components/stats-pane.js +121 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/dashboard.d.ts +20 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/dashboard.js +167 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/demo.d.ts +13 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/demo.js +145 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/index.d.ts +8 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/index.js +4 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/keymap.d.ts +3 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/keymap.js +99 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/layout.d.ts +25 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/layout.js +79 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/should-use-dashboard.d.ts +10 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/should-use-dashboard.js +7 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/snapshot.d.ts +10 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/snapshot.js +68 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/store.d.ts +8 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/store.js +51 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/terminal.d.ts +37 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/terminal.js +233 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/types.d.ts +36 -0
- package/node_modules/@poe-code/design-system/dist/dashboard/types.js +1 -0
- package/node_modules/@poe-code/design-system/dist/index.d.ts +33 -0
- package/node_modules/@poe-code/design-system/dist/index.js +31 -0
- package/node_modules/@poe-code/design-system/dist/internal/output-format.d.ts +6 -0
- package/node_modules/@poe-code/design-system/dist/internal/output-format.js +22 -0
- package/node_modules/@poe-code/design-system/dist/internal/strip-ansi.d.ts +1 -0
- package/node_modules/@poe-code/design-system/dist/internal/strip-ansi.js +3 -0
- package/node_modules/@poe-code/design-system/dist/internal/theme-detect.d.ts +11 -0
- package/node_modules/@poe-code/design-system/dist/internal/theme-detect.js +49 -0
- package/node_modules/@poe-code/design-system/dist/prompts/index.d.ts +66 -0
- package/node_modules/@poe-code/design-system/dist/prompts/index.js +132 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/cancel.d.ts +2 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/cancel.js +9 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/intro.d.ts +1 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/intro.js +15 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/log.d.ts +18 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/log.js +101 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/note.d.ts +1 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/note.js +39 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/outro.d.ts +1 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/outro.js +16 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/spinner.d.ts +6 -0
- package/node_modules/@poe-code/design-system/dist/prompts/primitives/spinner.js +74 -0
- package/node_modules/@poe-code/design-system/dist/prompts/theme.d.ts +11 -0
- package/node_modules/@poe-code/design-system/dist/prompts/theme.js +12 -0
- package/node_modules/@poe-code/design-system/dist/static/index.d.ts +4 -0
- package/node_modules/@poe-code/design-system/dist/static/index.js +2 -0
- package/node_modules/@poe-code/design-system/dist/static/menu.d.ts +11 -0
- package/node_modules/@poe-code/design-system/dist/static/menu.js +36 -0
- package/node_modules/@poe-code/design-system/dist/static/spinner.d.ts +14 -0
- package/node_modules/@poe-code/design-system/dist/static/spinner.js +46 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/ast.d.ts +92 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/ast.js +1 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/demo-content.d.ts +2 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/demo-content.js +139 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/index.d.ts +6 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/index.js +8 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/block.d.ts +7 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/block.js +1495 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/frontmatter.d.ts +8 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/frontmatter.js +412 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/inline.d.ts +10 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/inline.js +1166 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser.d.ts +5 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser.js +42 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/renderer.d.ts +6 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/renderer.js +572 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/testing/theme-render-fixture.d.ts +1 -0
- package/node_modules/@poe-code/design-system/dist/terminal-markdown/testing/theme-render-fixture.js +27 -0
- package/node_modules/@poe-code/design-system/dist/tokens/colors.d.ts +35 -0
- package/node_modules/@poe-code/design-system/dist/tokens/colors.js +34 -0
- package/node_modules/@poe-code/design-system/dist/tokens/index.d.ts +4 -0
- package/node_modules/@poe-code/design-system/dist/tokens/index.js +4 -0
- package/node_modules/@poe-code/design-system/dist/tokens/spacing.d.ts +6 -0
- package/node_modules/@poe-code/design-system/dist/tokens/spacing.js +6 -0
- package/node_modules/@poe-code/design-system/dist/tokens/typography.d.ts +7 -0
- package/node_modules/@poe-code/design-system/dist/tokens/typography.js +8 -0
- package/node_modules/@poe-code/design-system/dist/tokens/widths.d.ts +5 -0
- package/node_modules/@poe-code/design-system/dist/tokens/widths.js +5 -0
- package/node_modules/@poe-code/design-system/package.json +25 -0
- package/node_modules/auth-store/README.md +47 -0
- package/node_modules/auth-store/dist/create-secret-store.d.ts +2 -0
- package/node_modules/auth-store/dist/create-secret-store.js +35 -0
- package/node_modules/auth-store/dist/encrypted-file-store.d.ts +39 -0
- package/node_modules/auth-store/dist/encrypted-file-store.js +156 -0
- package/node_modules/auth-store/dist/index.d.ts +7 -0
- package/node_modules/auth-store/dist/index.js +4 -0
- package/node_modules/auth-store/dist/keychain-store.d.ts +22 -0
- package/node_modules/auth-store/dist/keychain-store.js +111 -0
- package/node_modules/auth-store/dist/provider-store.d.ts +10 -0
- package/node_modules/auth-store/dist/provider-store.js +28 -0
- package/node_modules/auth-store/dist/types.d.ts +20 -0
- package/node_modules/auth-store/dist/types.js +1 -0
- package/node_modules/auth-store/package.json +25 -0
- package/package.json +48 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { createDashboard } from "./dashboard.js";
|
|
5
|
+
const OUTPUT_INTERVAL_MS = 500;
|
|
6
|
+
const STATS_INTERVAL_MS = 1_000;
|
|
7
|
+
const DEMO_DURATION_MS = 30_000;
|
|
8
|
+
const TOKENS_IN_PER_ITERATION = 137;
|
|
9
|
+
const TOKENS_OUT_PER_ITERATION = 89;
|
|
10
|
+
const OUTPUT_KINDS = ["info", "success", "error", "tool", "status"];
|
|
11
|
+
const OUTPUT_MESSAGES = {
|
|
12
|
+
info: [
|
|
13
|
+
"Analyzing repository state",
|
|
14
|
+
"Inspecting agent configuration",
|
|
15
|
+
"Collecting recent command output"
|
|
16
|
+
],
|
|
17
|
+
success: [
|
|
18
|
+
"Generated provider config",
|
|
19
|
+
"Updated dashboard layout",
|
|
20
|
+
"Saved session checkpoint"
|
|
21
|
+
],
|
|
22
|
+
error: [
|
|
23
|
+
"Retrying transient network request",
|
|
24
|
+
"Tool execution returned a non-zero exit code",
|
|
25
|
+
"Encountered a recoverable validation error"
|
|
26
|
+
],
|
|
27
|
+
tool: [
|
|
28
|
+
"Running npm test -- --runInBand",
|
|
29
|
+
"Executing npm run lint:types",
|
|
30
|
+
"Opening task plan documentation"
|
|
31
|
+
],
|
|
32
|
+
status: [
|
|
33
|
+
"Waiting for follow-up task",
|
|
34
|
+
"Streaming model response",
|
|
35
|
+
"Syncing derived metrics"
|
|
36
|
+
]
|
|
37
|
+
};
|
|
38
|
+
const RUNNING_ACTIONS = [
|
|
39
|
+
"Planning next step",
|
|
40
|
+
"Executing tool call",
|
|
41
|
+
"Reviewing tool results",
|
|
42
|
+
"Updating working memory",
|
|
43
|
+
"Preparing final response"
|
|
44
|
+
];
|
|
45
|
+
const INITIAL_ACTION = "Connecting to provider";
|
|
46
|
+
const COMPLETED_ACTION = "Completed";
|
|
47
|
+
export function startDashboardDemo(dashboard, runtime = {}) {
|
|
48
|
+
const setIntervalFn = runtime.setInterval ?? globalThis.setInterval.bind(globalThis);
|
|
49
|
+
const clearIntervalFn = runtime.clearInterval ?? globalThis.clearInterval.bind(globalThis);
|
|
50
|
+
const setTimeoutFn = runtime.setTimeout ?? globalThis.setTimeout.bind(globalThis);
|
|
51
|
+
const clearTimeoutFn = runtime.clearTimeout ?? globalThis.clearTimeout.bind(globalThis);
|
|
52
|
+
const now = runtime.now ?? Date.now;
|
|
53
|
+
const random = runtime.random ?? Math.random;
|
|
54
|
+
let outputCount = 0;
|
|
55
|
+
let iterations = 0;
|
|
56
|
+
let cleanedUp = false;
|
|
57
|
+
dashboard.updateStats({
|
|
58
|
+
status: "running",
|
|
59
|
+
currentAction: INITIAL_ACTION
|
|
60
|
+
});
|
|
61
|
+
const outputTimer = setIntervalFn(() => {
|
|
62
|
+
const kind = OUTPUT_KINDS[outputCount % OUTPUT_KINDS.length] ?? "info";
|
|
63
|
+
dashboard.appendOutput({
|
|
64
|
+
kind,
|
|
65
|
+
text: pickOutputMessage(kind, random),
|
|
66
|
+
ts: now()
|
|
67
|
+
});
|
|
68
|
+
outputCount += 1;
|
|
69
|
+
}, OUTPUT_INTERVAL_MS);
|
|
70
|
+
const statsTimer = setIntervalFn(() => {
|
|
71
|
+
iterations += 1;
|
|
72
|
+
dashboard.updateStats({
|
|
73
|
+
status: "running",
|
|
74
|
+
iterations,
|
|
75
|
+
tokensIn: iterations * TOKENS_IN_PER_ITERATION,
|
|
76
|
+
tokensOut: iterations * TOKENS_OUT_PER_ITERATION,
|
|
77
|
+
elapsedMs: iterations * STATS_INTERVAL_MS,
|
|
78
|
+
currentAction: RUNNING_ACTIONS[(iterations - 1) % RUNNING_ACTIONS.length] ?? INITIAL_ACTION
|
|
79
|
+
});
|
|
80
|
+
}, STATS_INTERVAL_MS);
|
|
81
|
+
const finishTimeout = setTimeoutFn(() => {
|
|
82
|
+
cleanup();
|
|
83
|
+
dashboard.updateStats({
|
|
84
|
+
status: "done",
|
|
85
|
+
iterations,
|
|
86
|
+
tokensIn: iterations * TOKENS_IN_PER_ITERATION,
|
|
87
|
+
tokensOut: iterations * TOKENS_OUT_PER_ITERATION,
|
|
88
|
+
elapsedMs: DEMO_DURATION_MS,
|
|
89
|
+
currentAction: COMPLETED_ACTION
|
|
90
|
+
});
|
|
91
|
+
}, DEMO_DURATION_MS);
|
|
92
|
+
function cleanup() {
|
|
93
|
+
if (cleanedUp) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
cleanedUp = true;
|
|
97
|
+
clearTimeoutFn(finishTimeout);
|
|
98
|
+
clearIntervalFn(outputTimer);
|
|
99
|
+
clearIntervalFn(statsTimer);
|
|
100
|
+
}
|
|
101
|
+
return cleanup;
|
|
102
|
+
}
|
|
103
|
+
function pickOutputMessage(kind, random) {
|
|
104
|
+
const options = OUTPUT_MESSAGES[kind];
|
|
105
|
+
const cappedRandom = Math.max(0, Math.min(0.999_999, random()));
|
|
106
|
+
const index = Math.floor(cappedRandom * options.length);
|
|
107
|
+
return options[index] ?? options[0] ?? kind;
|
|
108
|
+
}
|
|
109
|
+
export async function main() {
|
|
110
|
+
const dashboard = createDashboard({ title: "Agent Output", statsTitle: "Stats" });
|
|
111
|
+
const stopDemo = startDashboardDemo(dashboard);
|
|
112
|
+
let shutDown = false;
|
|
113
|
+
const shutdown = (exitCode) => {
|
|
114
|
+
if (shutDown) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
shutDown = true;
|
|
118
|
+
stopDemo();
|
|
119
|
+
dashboard.destroy();
|
|
120
|
+
if (exitCode !== undefined) {
|
|
121
|
+
process.exit(exitCode);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
dashboard.onCommand((command) => {
|
|
125
|
+
if (command === "quit") {
|
|
126
|
+
shutdown(0);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
process.once("SIGINT", () => {
|
|
130
|
+
shutdown(0);
|
|
131
|
+
});
|
|
132
|
+
process.once("SIGTERM", () => {
|
|
133
|
+
shutdown(0);
|
|
134
|
+
});
|
|
135
|
+
dashboard.start();
|
|
136
|
+
}
|
|
137
|
+
const entry = process.argv[1];
|
|
138
|
+
const isMain = typeof entry === "string" && path.resolve(entry) === fileURLToPath(import.meta.url);
|
|
139
|
+
if (isMain) {
|
|
140
|
+
main().catch((error) => {
|
|
141
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
142
|
+
process.stderr.write(`${message}\n`);
|
|
143
|
+
process.exitCode = 1;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { createDashboard } from "./dashboard.js";
|
|
2
|
+
export { shouldUseInteractiveDashboard } from "./should-use-dashboard.js";
|
|
3
|
+
export type { Dashboard, DashboardOptions } from "./dashboard.js";
|
|
4
|
+
export { renderDashboardSnapshot } from "./snapshot.js";
|
|
5
|
+
export type { SnapshotOptions } from "./snapshot.js";
|
|
6
|
+
export type { OutputItem, OutputItemKind, DashboardStats, Command, DashboardState } from "./types.js";
|
|
7
|
+
export { defaultHints } from "./components/footer.js";
|
|
8
|
+
export type { FooterHint } from "./components/footer.js";
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const commands = ["forceQuit", "quit", "edit", "pause", "retry", "view-log"];
|
|
2
|
+
const defaultBindings = {
|
|
3
|
+
forceQuit: ["Ctrl+C"],
|
|
4
|
+
quit: ["q"],
|
|
5
|
+
edit: ["e"],
|
|
6
|
+
pause: ["p"],
|
|
7
|
+
retry: ["r"],
|
|
8
|
+
"view-log": ["l"]
|
|
9
|
+
};
|
|
10
|
+
export function createKeymap(overrides) {
|
|
11
|
+
const bindings = new Map();
|
|
12
|
+
for (const command of commands) {
|
|
13
|
+
const keys = overrides?.[command] ?? defaultBindings[command];
|
|
14
|
+
bindings.set(command, keys
|
|
15
|
+
.map(parseBinding)
|
|
16
|
+
.filter((binding) => binding !== undefined));
|
|
17
|
+
}
|
|
18
|
+
return (event) => {
|
|
19
|
+
for (const command of commands) {
|
|
20
|
+
const commandBindings = bindings.get(command);
|
|
21
|
+
if (commandBindings?.some((binding) => matches(binding, event))) {
|
|
22
|
+
return command;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function parseBinding(binding) {
|
|
29
|
+
const value = binding.trim();
|
|
30
|
+
if (value.length === 0) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const parts = value.split("+").map((part) => part.trim()).filter(Boolean);
|
|
34
|
+
if (parts.length === 0) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
let ctrl = false;
|
|
38
|
+
let meta = false;
|
|
39
|
+
let shift = false;
|
|
40
|
+
const key = parts.at(-1);
|
|
41
|
+
if (key === undefined) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
for (const modifier of parts.slice(0, -1)) {
|
|
45
|
+
const normalized = modifier.toLowerCase();
|
|
46
|
+
if (normalized === "ctrl" || normalized === "control") {
|
|
47
|
+
ctrl = true;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (normalized === "meta" || normalized === "alt") {
|
|
51
|
+
meta = true;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (normalized === "shift") {
|
|
55
|
+
shift = true;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (parts.length === 1 && isShiftedCharacter(key)) {
|
|
60
|
+
shift = true;
|
|
61
|
+
}
|
|
62
|
+
if (key.length === 1) {
|
|
63
|
+
return {
|
|
64
|
+
ch: normalizeBindingCharacter(key, shift),
|
|
65
|
+
ctrl,
|
|
66
|
+
meta,
|
|
67
|
+
shift
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
name: key.toLowerCase(),
|
|
72
|
+
ctrl,
|
|
73
|
+
meta,
|
|
74
|
+
shift
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function matches(binding, event) {
|
|
78
|
+
if (binding.ctrl !== event.ctrl ||
|
|
79
|
+
binding.meta !== event.meta ||
|
|
80
|
+
binding.shift !== event.shift) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
if (binding.ch !== undefined) {
|
|
84
|
+
return event.ch === binding.ch || event.name === binding.ch.toLowerCase();
|
|
85
|
+
}
|
|
86
|
+
if (binding.name !== undefined) {
|
|
87
|
+
return event.name === binding.name;
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
function isShiftedCharacter(value) {
|
|
92
|
+
return value.length === 1 && value.toLowerCase() !== value && value.toUpperCase() === value;
|
|
93
|
+
}
|
|
94
|
+
function normalizeBindingCharacter(value, shift) {
|
|
95
|
+
if (!shift || value.toLowerCase() === value.toUpperCase()) {
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
return value.toUpperCase();
|
|
99
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Rect } from "./types.js";
|
|
2
|
+
export type LayoutOptions = {
|
|
3
|
+
totalWidth: number;
|
|
4
|
+
totalHeight: number;
|
|
5
|
+
rightPaneWidth?: number;
|
|
6
|
+
footerHeight?: number;
|
|
7
|
+
borderWidth?: number;
|
|
8
|
+
};
|
|
9
|
+
export type DashboardLayout = {
|
|
10
|
+
outerBorder: Rect;
|
|
11
|
+
leftPane: Rect;
|
|
12
|
+
rightPane: Rect;
|
|
13
|
+
divider: {
|
|
14
|
+
x: number;
|
|
15
|
+
top: number;
|
|
16
|
+
bottom: number;
|
|
17
|
+
};
|
|
18
|
+
footer: Rect;
|
|
19
|
+
footerDivider: {
|
|
20
|
+
y: number;
|
|
21
|
+
left: number;
|
|
22
|
+
right: number;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export declare function computeDashboardLayout(opts: LayoutOptions): DashboardLayout;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const DEFAULT_RIGHT_PANE_WIDTH = 25;
|
|
2
|
+
const DEFAULT_FOOTER_HEIGHT = 1;
|
|
3
|
+
const DEFAULT_BORDER_WIDTH = 1;
|
|
4
|
+
const MIN_LEFT_PANE_WIDTH = 20;
|
|
5
|
+
export function computeDashboardLayout(opts) {
|
|
6
|
+
const totalWidth = normalizeSize(opts.totalWidth);
|
|
7
|
+
const totalHeight = normalizeSize(opts.totalHeight);
|
|
8
|
+
const borderWidth = normalizeSize(opts.borderWidth ?? DEFAULT_BORDER_WIDTH);
|
|
9
|
+
const footerHeight = normalizeSize(opts.footerHeight ?? DEFAULT_FOOTER_HEIGHT);
|
|
10
|
+
const requestedRightPaneWidth = normalizeSize(opts.rightPaneWidth ?? DEFAULT_RIGHT_PANE_WIDTH);
|
|
11
|
+
const maxX = Math.max(0, totalWidth - 1);
|
|
12
|
+
const maxY = Math.max(0, totalHeight - 1);
|
|
13
|
+
const outerBorder = { x: 0, y: 0, width: totalWidth, height: totalHeight };
|
|
14
|
+
const innerWidth = Math.max(0, totalWidth - (borderWidth * 2));
|
|
15
|
+
const innerHeight = Math.max(0, totalHeight - (borderWidth * 2));
|
|
16
|
+
const innerX = clampCoordinate(borderWidth, maxX);
|
|
17
|
+
const innerY = clampCoordinate(borderWidth, maxY);
|
|
18
|
+
const dividerWidth = innerWidth > 0 ? 1 : 0;
|
|
19
|
+
const availablePaneWidth = Math.max(0, innerWidth - dividerWidth);
|
|
20
|
+
const leftPaneWidth = computeLeftPaneWidth(availablePaneWidth, requestedRightPaneWidth);
|
|
21
|
+
const rightPaneWidth = Math.max(0, availablePaneWidth - leftPaneWidth);
|
|
22
|
+
const actualFooterHeight = Math.min(footerHeight, innerHeight);
|
|
23
|
+
const footerDividerHeight = innerHeight > actualFooterHeight ? 1 : 0;
|
|
24
|
+
const contentHeight = Math.max(0, innerHeight - actualFooterHeight - footerDividerHeight);
|
|
25
|
+
const leftPane = {
|
|
26
|
+
x: innerX,
|
|
27
|
+
y: innerY,
|
|
28
|
+
width: leftPaneWidth,
|
|
29
|
+
height: contentHeight
|
|
30
|
+
};
|
|
31
|
+
const dividerX = clampCoordinate(leftPane.x + leftPane.width, maxX);
|
|
32
|
+
const rightPane = {
|
|
33
|
+
x: clampCoordinate(dividerX + dividerWidth, maxX),
|
|
34
|
+
y: innerY,
|
|
35
|
+
width: rightPaneWidth,
|
|
36
|
+
height: contentHeight
|
|
37
|
+
};
|
|
38
|
+
const dividerTop = innerY;
|
|
39
|
+
const dividerBottom = clampCoordinate(dividerTop + Math.max(contentHeight - 1, 0), maxY);
|
|
40
|
+
const footerDividerY = clampCoordinate(innerY + contentHeight, maxY);
|
|
41
|
+
const footerY = clampCoordinate(footerDividerY + footerDividerHeight, maxY);
|
|
42
|
+
const footerDividerLeft = innerX;
|
|
43
|
+
const footerDividerRight = clampCoordinate(Math.max(innerX, totalWidth - borderWidth - 1), maxX);
|
|
44
|
+
return {
|
|
45
|
+
outerBorder,
|
|
46
|
+
leftPane,
|
|
47
|
+
rightPane,
|
|
48
|
+
divider: {
|
|
49
|
+
x: dividerX,
|
|
50
|
+
top: dividerTop,
|
|
51
|
+
bottom: dividerBottom
|
|
52
|
+
},
|
|
53
|
+
footer: {
|
|
54
|
+
x: innerX,
|
|
55
|
+
y: footerY,
|
|
56
|
+
width: innerWidth,
|
|
57
|
+
height: actualFooterHeight
|
|
58
|
+
},
|
|
59
|
+
footerDivider: {
|
|
60
|
+
y: footerDividerY,
|
|
61
|
+
left: footerDividerLeft,
|
|
62
|
+
right: footerDividerRight
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function computeLeftPaneWidth(availablePaneWidth, requestedRightPaneWidth) {
|
|
67
|
+
if (availablePaneWidth <= 0) {
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
const maxRightPaneWidth = Math.max(0, availablePaneWidth - MIN_LEFT_PANE_WIDTH);
|
|
71
|
+
const rightPaneWidth = Math.min(requestedRightPaneWidth, maxRightPaneWidth);
|
|
72
|
+
return Math.max(0, availablePaneWidth - rightPaneWidth);
|
|
73
|
+
}
|
|
74
|
+
function normalizeSize(value) {
|
|
75
|
+
return Math.max(0, Math.floor(value));
|
|
76
|
+
}
|
|
77
|
+
function clampCoordinate(value, max) {
|
|
78
|
+
return Math.max(0, Math.min(value, max));
|
|
79
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { resolveOutputFormat } from "../internal/output-format.js";
|
|
2
|
+
export function shouldUseInteractiveDashboard(enabled, io = process) {
|
|
3
|
+
return enabled === true
|
|
4
|
+
&& resolveOutputFormat() === "terminal"
|
|
5
|
+
&& Boolean(io.stdin.isTTY)
|
|
6
|
+
&& Boolean(io.stdout.isTTY);
|
|
7
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DashboardStats, OutputItem } from "./types.js";
|
|
2
|
+
export type SnapshotOptions = {
|
|
3
|
+
width?: number;
|
|
4
|
+
height?: number;
|
|
5
|
+
title?: string;
|
|
6
|
+
statsTitle?: string;
|
|
7
|
+
items?: OutputItem[];
|
|
8
|
+
stats?: DashboardStats;
|
|
9
|
+
};
|
|
10
|
+
export declare function renderDashboardSnapshot(opts?: SnapshotOptions): string;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ScreenBuffer, cellToAnsi } from "./buffer.js";
|
|
2
|
+
import { renderBorder } from "./components/border.js";
|
|
3
|
+
import { defaultHints, renderFooter } from "./components/footer.js";
|
|
4
|
+
import { renderOutputPane } from "./components/output-pane.js";
|
|
5
|
+
import { renderStatsPane } from "./components/stats-pane.js";
|
|
6
|
+
import { computeDashboardLayout } from "./layout.js";
|
|
7
|
+
const SNAPSHOT_WIDTH = 80;
|
|
8
|
+
const SNAPSHOT_HEIGHT = 20;
|
|
9
|
+
const RIGHT_PANE_WIDTH = 25;
|
|
10
|
+
export function renderDashboardSnapshot(opts = {}) {
|
|
11
|
+
const width = opts.width ?? SNAPSHOT_WIDTH;
|
|
12
|
+
const height = opts.height ?? SNAPSHOT_HEIGHT;
|
|
13
|
+
const title = opts.title ?? "Agent Output";
|
|
14
|
+
const statsTitle = opts.statsTitle ?? "Stats";
|
|
15
|
+
const items = opts.items ?? defaultItems();
|
|
16
|
+
const stats = opts.stats ?? defaultStats();
|
|
17
|
+
const layout = computeDashboardLayout({
|
|
18
|
+
totalWidth: width,
|
|
19
|
+
totalHeight: height,
|
|
20
|
+
rightPaneWidth: RIGHT_PANE_WIDTH
|
|
21
|
+
});
|
|
22
|
+
const buffer = new ScreenBuffer(width, height);
|
|
23
|
+
renderBorder(buffer, layout, {
|
|
24
|
+
leftTitle: title,
|
|
25
|
+
rightTitle: statsTitle,
|
|
26
|
+
style: { dim: true }
|
|
27
|
+
});
|
|
28
|
+
renderOutputPane(buffer, layout.leftPane, items);
|
|
29
|
+
renderStatsPane(buffer, layout.rightPane, stats);
|
|
30
|
+
renderFooter(buffer, layout.footer, defaultHints());
|
|
31
|
+
return bufferToAnsi(buffer);
|
|
32
|
+
}
|
|
33
|
+
function bufferToAnsi(buffer) {
|
|
34
|
+
const lines = [];
|
|
35
|
+
for (let y = 0; y < buffer.height; y += 1) {
|
|
36
|
+
let line = "";
|
|
37
|
+
for (let x = 0; x < buffer.width; x += 1) {
|
|
38
|
+
line += cellToAnsi(buffer.get(x, y));
|
|
39
|
+
}
|
|
40
|
+
lines.push(line);
|
|
41
|
+
}
|
|
42
|
+
return lines.join("\n");
|
|
43
|
+
}
|
|
44
|
+
function defaultItems() {
|
|
45
|
+
const now = Date.now();
|
|
46
|
+
return [
|
|
47
|
+
{ kind: "info", text: "Analyzing repository state", ts: now },
|
|
48
|
+
{ kind: "tool", text: "Running npm test -- --runInBand", ts: now + 500 },
|
|
49
|
+
{ kind: "success", text: "Generated provider config", ts: now + 1000 },
|
|
50
|
+
{ kind: "status", text: "Streaming model response", ts: now + 1500 },
|
|
51
|
+
{ kind: "info", text: "Inspecting agent configuration", ts: now + 2000 },
|
|
52
|
+
{ kind: "tool", text: "Executing npm run lint:types", ts: now + 2500 },
|
|
53
|
+
{ kind: "error", text: "Retrying transient network request", ts: now + 3000 },
|
|
54
|
+
{ kind: "success", text: "Updated dashboard layout", ts: now + 3500 },
|
|
55
|
+
{ kind: "info", text: "Collecting recent command output", ts: now + 4000 },
|
|
56
|
+
{ kind: "status", text: "Waiting for follow-up task", ts: now + 4500 }
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
function defaultStats() {
|
|
60
|
+
return {
|
|
61
|
+
status: "running",
|
|
62
|
+
iterations: 5,
|
|
63
|
+
tokensIn: 685,
|
|
64
|
+
tokensOut: 445,
|
|
65
|
+
elapsedMs: 5000,
|
|
66
|
+
currentAction: "Executing tool call"
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DashboardState, DashboardStats, OutputItem } from "./types.js";
|
|
2
|
+
export type DashboardStore = {
|
|
3
|
+
getState(): DashboardState;
|
|
4
|
+
appendOutput(item: OutputItem): void;
|
|
5
|
+
updateStats(partial: Partial<DashboardStats>): void;
|
|
6
|
+
onChange(handler: () => void): () => void;
|
|
7
|
+
};
|
|
8
|
+
export declare function createStore(): DashboardStore;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const MAX_RETAINED_OUTPUT = 256;
|
|
2
|
+
export function createStore() {
|
|
3
|
+
let state = {
|
|
4
|
+
output: [],
|
|
5
|
+
stats: {
|
|
6
|
+
status: "idle",
|
|
7
|
+
iterations: 0,
|
|
8
|
+
tokensIn: 0,
|
|
9
|
+
tokensOut: 0,
|
|
10
|
+
elapsedMs: 0
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
const listeners = new Set();
|
|
14
|
+
function notify() {
|
|
15
|
+
for (const listener of listeners) {
|
|
16
|
+
listener();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function getState() {
|
|
20
|
+
return state;
|
|
21
|
+
}
|
|
22
|
+
function appendOutput(item) {
|
|
23
|
+
const next = state.output.length >= MAX_RETAINED_OUTPUT
|
|
24
|
+
? [...state.output.slice(state.output.length - MAX_RETAINED_OUTPUT + 1), item]
|
|
25
|
+
: [...state.output, item];
|
|
26
|
+
state = { ...state, output: next };
|
|
27
|
+
notify();
|
|
28
|
+
}
|
|
29
|
+
function updateStats(partial) {
|
|
30
|
+
state = {
|
|
31
|
+
...state,
|
|
32
|
+
stats: {
|
|
33
|
+
...state.stats,
|
|
34
|
+
...partial
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
notify();
|
|
38
|
+
}
|
|
39
|
+
function onChange(handler) {
|
|
40
|
+
listeners.add(handler);
|
|
41
|
+
return () => {
|
|
42
|
+
listeners.delete(handler);
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
getState,
|
|
47
|
+
appendOutput,
|
|
48
|
+
updateStats,
|
|
49
|
+
onChange
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Cell } from "./types.js";
|
|
2
|
+
export type KeypressEvent = {
|
|
3
|
+
name?: string;
|
|
4
|
+
ch?: string;
|
|
5
|
+
ctrl: boolean;
|
|
6
|
+
meta: boolean;
|
|
7
|
+
shift: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type TerminalDriver = {
|
|
10
|
+
enterRawMode(): void;
|
|
11
|
+
exitRawMode(): void;
|
|
12
|
+
enterAltScreen(): void;
|
|
13
|
+
exitAltScreen(): void;
|
|
14
|
+
disableLineWrap(): void;
|
|
15
|
+
enableLineWrap(): void;
|
|
16
|
+
hideCursor(): void;
|
|
17
|
+
showCursor(): void;
|
|
18
|
+
moveTo(x: number, y: number): void;
|
|
19
|
+
write(text: string): void;
|
|
20
|
+
flush(changes: Array<{
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
cell: Cell;
|
|
24
|
+
}>): void;
|
|
25
|
+
getSize(): {
|
|
26
|
+
cols: number;
|
|
27
|
+
rows: number;
|
|
28
|
+
};
|
|
29
|
+
onResize(handler: () => void): () => void;
|
|
30
|
+
onKeypress(handler: (key: KeypressEvent) => void): () => void;
|
|
31
|
+
destroy(): void;
|
|
32
|
+
};
|
|
33
|
+
export declare function createTerminalDriver(opts?: {
|
|
34
|
+
stdin?: NodeJS.ReadStream;
|
|
35
|
+
stdout?: NodeJS.WriteStream;
|
|
36
|
+
}): TerminalDriver;
|
|
37
|
+
export declare function parseKeypress(data: Buffer): KeypressEvent | undefined;
|