archymedes-cli 2.3.0 → 2.5.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/{archymedes-aj30app4.mjs → archymedes-06fh0z84.mjs} +370 -159
- package/dist/{archymedes-d5wqcmdr.mjs → archymedes-0jxzsh4z.mjs} +97 -97
- package/dist/archymedes-130jt0wr.mjs +1231 -0
- package/dist/{archymedes-twbks7g3.mjs → archymedes-138genyy.mjs} +214 -5
- package/dist/{archymedes-h13ap0za.mjs → archymedes-1g1y6q74.mjs} +1 -1
- package/dist/{archymedes-dz59nvw7.mjs → archymedes-2kvjaajw.mjs} +21 -11
- package/dist/{archymedes-g8y3rt6t.mjs → archymedes-5vhvv8kr.mjs} +332 -9
- package/dist/{archymedes-4kx65anz.mjs → archymedes-a3ms7jvr.mjs} +43 -12
- package/dist/{archymedes-tsne2m7p.mjs → archymedes-bmtdqqwt.mjs} +2 -2
- package/dist/{archymedes-sf9t1hz9.mjs → archymedes-d3azqkay.mjs} +176 -77
- package/dist/archymedes-main.mjs +31312 -28352
- package/dist/archymedes-w4bjfye7.mjs +280 -0
- package/dist/{editor-screen-g08zzt70.mjs → editor-screen-e01mn7dd.mjs} +49 -14
- package/dist/{factory-7vtm2fed.mjs → factory-hyv8agr0.mjs} +326 -326
- package/dist/{file-screen-ma9yxq2b.mjs → file-screen-stcxznwy.mjs} +11 -9
- package/dist/{guide-screen-gd129txd.mjs → guide-screen-w5nb9sry.mjs} +10 -8
- package/dist/{index-qvgcwsvm.mjs → index-teq1cta4.mjs} +1 -1
- package/dist/{node-mdgzx68h.mjs → node-0fh63p8z.mjs} +7 -7
- package/dist/pager-screen-aamt6xv0.mjs +155 -0
- package/dist/projection-x6x6hm9t.mjs +248 -0
- package/dist/{sandbox-templates-9jcjws23.mjs → sandbox-templates-8sd1psez.mjs} +2 -2
- package/dist/workspace-screen-62k6hnq7.mjs +70 -0
- package/package.json +2 -2
- package/dist/archymedes-a10k8yrk.mjs +0 -464
- package/dist/workspace-screen-8cwk6jz9.mjs +0 -241
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
windowStart
|
|
3
|
-
} from "./archymedes-
|
|
3
|
+
} from "./archymedes-a3ms7jvr.mjs";
|
|
4
4
|
import {
|
|
5
5
|
joinHorizontal,
|
|
6
6
|
padToWidth,
|
|
7
7
|
paginator
|
|
8
|
-
} from "./archymedes-
|
|
8
|
+
} from "./archymedes-5vhvv8kr.mjs";
|
|
9
9
|
import {
|
|
10
10
|
NO_COLOR_PALETTE,
|
|
11
|
-
UNICODE_GLYPHS
|
|
12
|
-
|
|
11
|
+
UNICODE_GLYPHS,
|
|
12
|
+
exitTopTermUIApp
|
|
13
|
+
} from "./archymedes-130jt0wr.mjs";
|
|
13
14
|
import {
|
|
14
15
|
__require
|
|
15
16
|
} from "./archymedes-x67v3n58.mjs";
|
|
16
17
|
|
|
17
|
-
// src/ui/file-screen.tsx
|
|
18
|
+
// packages/archymedes-cli/src/ui/file-screen.tsx
|
|
18
19
|
import { useAsync, useInput, useState } from "@termuijs/jsx";
|
|
19
20
|
import { Box, Text } from "@termuijs/widgets";
|
|
20
21
|
|
|
21
|
-
//
|
|
22
|
+
// packages/core/src/cli/file-tree.ts
|
|
22
23
|
function buildFileTree(paths) {
|
|
23
24
|
const root = { name: "", path: "", kind: "dir", children: [] };
|
|
24
25
|
for (const raw of paths) {
|
|
@@ -59,7 +60,7 @@ function directorySummary(node) {
|
|
|
59
60
|
}
|
|
60
61
|
return { files, dirs };
|
|
61
62
|
}
|
|
62
|
-
// src/ui/file-browser.ts
|
|
63
|
+
// packages/archymedes-cli/src/ui/file-browser.ts
|
|
63
64
|
function flattenTree(tree, expanded, depth = 0, trunks = []) {
|
|
64
65
|
const rows = [];
|
|
65
66
|
for (const [index, node] of tree.entries()) {
|
|
@@ -228,7 +229,7 @@ function composeFileFrame(state, preview, glyphs = UNICODE_GLYPHS) {
|
|
|
228
229
|
});
|
|
229
230
|
}
|
|
230
231
|
const overflow = rows.length > height ? ` ${paginator(selectedIndex < 0 ? 0 : selectedIndex, rows.length)}` : "";
|
|
231
|
-
const footer = state.searching ? `search: ${state.query}▏ Enter open · Esc done` : `↑↓ move · →/l open · ←/h close · Enter pick a file · / search ·
|
|
232
|
+
const footer = state.searching ? `search: ${state.query}▏ Enter open · Esc done` : `↑↓ move · →/l open · ←/h close · Enter pick a file · / search · Esc back${state.query ? ` filter: ${state.query}` : ""}${overflow}`;
|
|
232
233
|
out.push({ text: padToWidth(` ${footer}`, columns), dim: true, color: theme.textMuted });
|
|
233
234
|
return out;
|
|
234
235
|
}
|
|
@@ -251,7 +252,7 @@ function previewToLines(preview, width) {
|
|
|
251
252
|
}
|
|
252
253
|
}
|
|
253
254
|
|
|
254
|
-
// src/ui/file-screen.tsx
|
|
255
|
+
// packages/archymedes-cli/src/ui/file-screen.tsx
|
|
255
256
|
import { jsxDEV } from "@termuijs/jsx/jsx-dev-runtime";
|
|
256
257
|
var Panel = Box;
|
|
257
258
|
var Line = Text;
|
|
@@ -301,6 +302,7 @@ async function runFileScreen(options) {
|
|
|
301
302
|
if (settled)
|
|
302
303
|
return;
|
|
303
304
|
settled = true;
|
|
305
|
+
exitTopTermUIApp();
|
|
304
306
|
resolve(picked);
|
|
305
307
|
};
|
|
306
308
|
renderApp(FileScreen, {
|
|
@@ -4,28 +4,29 @@ import {
|
|
|
4
4
|
newViewport,
|
|
5
5
|
visibleLines,
|
|
6
6
|
wrapText
|
|
7
|
-
} from "./archymedes-
|
|
7
|
+
} from "./archymedes-d3azqkay.mjs";
|
|
8
8
|
import {
|
|
9
9
|
joinHorizontal,
|
|
10
10
|
padToWidth,
|
|
11
11
|
scrollIndicator,
|
|
12
12
|
scrollPercent,
|
|
13
13
|
sliceToWidth
|
|
14
|
-
} from "./archymedes-
|
|
15
|
-
import"./archymedes-
|
|
14
|
+
} from "./archymedes-5vhvv8kr.mjs";
|
|
15
|
+
import"./archymedes-bmtdqqwt.mjs";
|
|
16
16
|
import {
|
|
17
17
|
NO_COLOR_PALETTE,
|
|
18
|
+
exitTopTermUIApp,
|
|
18
19
|
visibleWidth
|
|
19
|
-
} from "./archymedes-
|
|
20
|
+
} from "./archymedes-130jt0wr.mjs";
|
|
20
21
|
import {
|
|
21
22
|
__require
|
|
22
23
|
} from "./archymedes-x67v3n58.mjs";
|
|
23
24
|
|
|
24
|
-
// src/ui/guide-screen.tsx
|
|
25
|
+
// packages/archymedes-cli/src/ui/guide-screen.tsx
|
|
25
26
|
import { useInput, useState } from "@termuijs/jsx";
|
|
26
27
|
import { Box, Text } from "@termuijs/widgets";
|
|
27
28
|
|
|
28
|
-
// src/ui/guide-browser.ts
|
|
29
|
+
// packages/archymedes-cli/src/ui/guide-browser.ts
|
|
29
30
|
function initialGuideState(columns, rows, palette = NO_COLOR_PALETTE) {
|
|
30
31
|
return { topics: GUIDE_TOPICS, selected: 0, scroll: 0, query: "", searching: false, columns, rows, palette };
|
|
31
32
|
}
|
|
@@ -208,12 +209,12 @@ function composeGuideFrame(state) {
|
|
|
208
209
|
});
|
|
209
210
|
}
|
|
210
211
|
const position = lines.length > height ? ` ${scrollIndicator(scrollPercent(start, lines.length, height))}` : "";
|
|
211
|
-
const footer = state.searching ? `search: ${state.query}▏ Enter done · Esc done` : `↑↓ topic · ←→ scroll · space page · / search ·
|
|
212
|
+
const footer = state.searching ? `search: ${state.query}▏ Enter done · Esc done` : `↑↓ topic · ←→ scroll · space page · / search · Esc back${state.query ? ` filter: ${state.query}` : ""}${position}`;
|
|
212
213
|
rows.push({ text: padToWidth(` ${footer}`, columns), dim: true, color: theme.textMuted });
|
|
213
214
|
return rows;
|
|
214
215
|
}
|
|
215
216
|
|
|
216
|
-
// src/ui/guide-screen.tsx
|
|
217
|
+
// packages/archymedes-cli/src/ui/guide-screen.tsx
|
|
217
218
|
import { jsxDEV } from "@termuijs/jsx/jsx-dev-runtime";
|
|
218
219
|
var Panel = Box;
|
|
219
220
|
var Line = Text;
|
|
@@ -253,6 +254,7 @@ async function runGuideScreen(options) {
|
|
|
253
254
|
if (settled)
|
|
254
255
|
return;
|
|
255
256
|
settled = true;
|
|
257
|
+
exitTopTermUIApp();
|
|
256
258
|
resolve();
|
|
257
259
|
};
|
|
258
260
|
renderApp(GuideScreen, {
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
__classPrivateFieldSet,
|
|
6
6
|
loggerFor,
|
|
7
7
|
promiseWithResolvers
|
|
8
|
-
} from "./archymedes-
|
|
8
|
+
} from "./archymedes-0jxzsh4z.mjs";
|
|
9
9
|
import"./archymedes-x67v3n58.mjs";
|
|
10
10
|
|
|
11
|
-
//
|
|
11
|
+
// node_modules/.bun/@anthropic-ai+sdk@0.116.0+ab3ed8e9421bfd7b/node_modules/@anthropic-ai/sdk/tools/agent-toolset/node.mjs
|
|
12
12
|
import * as fs3 from "node:fs/promises";
|
|
13
13
|
import * as fssync2 from "node:fs";
|
|
14
14
|
import * as path3 from "node:path";
|
|
@@ -16,7 +16,7 @@ import * as cp from "node:child_process";
|
|
|
16
16
|
import * as crypto from "node:crypto";
|
|
17
17
|
import * as readline from "node:readline";
|
|
18
18
|
|
|
19
|
-
//
|
|
19
|
+
// node_modules/.bun/@anthropic-ai+sdk@0.116.0+ab3ed8e9421bfd7b/node_modules/@anthropic-ai/sdk/lib/transform-json-schema.mjs
|
|
20
20
|
var SUPPORTED_STRING_FORMATS = new Set([
|
|
21
21
|
"date-time",
|
|
22
22
|
"time",
|
|
@@ -30,7 +30,7 @@ var SUPPORTED_STRING_FORMATS = new Set([
|
|
|
30
30
|
"uuid"
|
|
31
31
|
]);
|
|
32
32
|
|
|
33
|
-
//
|
|
33
|
+
// node_modules/.bun/@anthropic-ai+sdk@0.116.0+ab3ed8e9421bfd7b/node_modules/@anthropic-ai/sdk/helpers/beta/json-schema.mjs
|
|
34
34
|
function betaTool(options) {
|
|
35
35
|
if (options.inputSchema.type !== "object") {
|
|
36
36
|
throw new Error(`JSON schema for tool "${options.name}" must be an object, but got ${options.inputSchema.type}`);
|
|
@@ -46,7 +46,7 @@ function betaTool(options) {
|
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
//
|
|
49
|
+
// node_modules/.bun/@anthropic-ai+sdk@0.116.0+ab3ed8e9421bfd7b/node_modules/@anthropic-ai/sdk/tools/agent-toolset/fs-util.mjs
|
|
50
50
|
import * as fs from "node:fs/promises";
|
|
51
51
|
import * as path from "node:path";
|
|
52
52
|
import { randomUUID } from "node:crypto";
|
|
@@ -145,7 +145,7 @@ function fsErrorMessage(err, file) {
|
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
//
|
|
148
|
+
// node_modules/.bun/@anthropic-ai+sdk@0.116.0+ab3ed8e9421bfd7b/node_modules/@anthropic-ai/sdk/tools/agent-toolset/skills.mjs
|
|
149
149
|
import * as fs2 from "node:fs/promises";
|
|
150
150
|
import * as fssync from "node:fs";
|
|
151
151
|
import * as path2 from "node:path";
|
|
@@ -304,7 +304,7 @@ async function readHead(file, n) {
|
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
-
//
|
|
307
|
+
// node_modules/.bun/@anthropic-ai+sdk@0.116.0+ab3ed8e9421bfd7b/node_modules/@anthropic-ai/sdk/tools/agent-toolset/node.mjs
|
|
308
308
|
var _BashSession_instances;
|
|
309
309
|
var _BashSession_proc;
|
|
310
310
|
var _BashSession_buf;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__require
|
|
3
|
+
} from "./archymedes-x67v3n58.mjs";
|
|
4
|
+
|
|
5
|
+
// packages/archymedes-cli/src/ui/pager-screen.tsx
|
|
6
|
+
import { useInput, useState } from "@termuijs/jsx";
|
|
7
|
+
import { Box, Text } from "@termuijs/widgets";
|
|
8
|
+
|
|
9
|
+
// packages/archymedes-cli/src/ui/text-pager.ts
|
|
10
|
+
var ANSI = /\x1b\[[0-9;?]*[A-Za-z]|\x1b\][^\x07]*\x07/g;
|
|
11
|
+
function initialPagerState(text, height) {
|
|
12
|
+
const lines = text.replace(ANSI, "").replace(/\r/g, "").split(`
|
|
13
|
+
`);
|
|
14
|
+
const rows = Math.max(1, height);
|
|
15
|
+
return { lines, top: Math.max(0, lines.length - rows), height: rows, search: { query: "", typing: false } };
|
|
16
|
+
}
|
|
17
|
+
function keyToPagerAction(key, character, state) {
|
|
18
|
+
const name = key.name ?? "";
|
|
19
|
+
if (key.ctrl && name === "c")
|
|
20
|
+
return { kind: "exit" };
|
|
21
|
+
if (state.search.typing) {
|
|
22
|
+
if (name === "escape")
|
|
23
|
+
return { kind: "searchCancel" };
|
|
24
|
+
if (name === "return" || name === "enter")
|
|
25
|
+
return { kind: "searchCommit" };
|
|
26
|
+
if (name === "backspace")
|
|
27
|
+
return { kind: "searchBackspace" };
|
|
28
|
+
if (character && character.length === 1 && character >= " ")
|
|
29
|
+
return { kind: "searchType", character };
|
|
30
|
+
return { kind: "none" };
|
|
31
|
+
}
|
|
32
|
+
if (name === "escape" || character === "q")
|
|
33
|
+
return { kind: "exit" };
|
|
34
|
+
if (name === "up" || character === "k")
|
|
35
|
+
return { kind: "scroll", rows: -1 };
|
|
36
|
+
if (name === "down" || character === "j" || name === "return" || name === "enter")
|
|
37
|
+
return { kind: "scroll", rows: 1 };
|
|
38
|
+
if (name === "pageup" || character === "b")
|
|
39
|
+
return { kind: "scroll", rows: -(state.height - 1) };
|
|
40
|
+
if (name === "pagedown" || name === "space" || character === " ")
|
|
41
|
+
return { kind: "scroll", rows: state.height - 1 };
|
|
42
|
+
if (name === "home" || character === "g")
|
|
43
|
+
return { kind: "home" };
|
|
44
|
+
if (name === "end" || character === "G")
|
|
45
|
+
return { kind: "end" };
|
|
46
|
+
if (character === "/")
|
|
47
|
+
return { kind: "search" };
|
|
48
|
+
if (character === "n")
|
|
49
|
+
return { kind: "searchNext" };
|
|
50
|
+
return { kind: "none" };
|
|
51
|
+
}
|
|
52
|
+
function clampTop(state, top) {
|
|
53
|
+
return Math.max(0, Math.min(top, Math.max(0, state.lines.length - state.height)));
|
|
54
|
+
}
|
|
55
|
+
function findFrom(state, from) {
|
|
56
|
+
const needle = state.search.query.toLowerCase();
|
|
57
|
+
if (!needle)
|
|
58
|
+
return -1;
|
|
59
|
+
for (let offset = 0;offset < state.lines.length; offset += 1) {
|
|
60
|
+
const row = (from + offset) % state.lines.length;
|
|
61
|
+
if (state.lines[row].toLowerCase().includes(needle))
|
|
62
|
+
return row;
|
|
63
|
+
}
|
|
64
|
+
return -1;
|
|
65
|
+
}
|
|
66
|
+
function applyPagerAction(state, action) {
|
|
67
|
+
switch (action.kind) {
|
|
68
|
+
case "exit":
|
|
69
|
+
return { state, exit: true };
|
|
70
|
+
case "scroll":
|
|
71
|
+
return { state: { ...state, top: clampTop(state, state.top + action.rows), message: undefined } };
|
|
72
|
+
case "home":
|
|
73
|
+
return { state: { ...state, top: 0, message: undefined } };
|
|
74
|
+
case "end":
|
|
75
|
+
return { state: { ...state, top: clampTop(state, state.lines.length), message: undefined } };
|
|
76
|
+
case "search":
|
|
77
|
+
return { state: { ...state, search: { query: "", typing: true }, message: undefined } };
|
|
78
|
+
case "searchType":
|
|
79
|
+
return { state: { ...state, search: { ...state.search, query: state.search.query + action.character } } };
|
|
80
|
+
case "searchBackspace":
|
|
81
|
+
return { state: { ...state, search: { ...state.search, query: state.search.query.slice(0, -1) } } };
|
|
82
|
+
case "searchCancel":
|
|
83
|
+
return { state: { ...state, search: { query: "", typing: false } } };
|
|
84
|
+
case "searchCommit":
|
|
85
|
+
case "searchNext": {
|
|
86
|
+
const settled = { ...state, search: { ...state.search, typing: false } };
|
|
87
|
+
const row = findFrom(settled, action.kind === "searchCommit" ? state.top : state.top + 1);
|
|
88
|
+
if (row < 0)
|
|
89
|
+
return { state: { ...settled, message: state.search.query ? `no match for "${state.search.query}"` : undefined } };
|
|
90
|
+
return { state: { ...settled, top: clampTop(settled, row), message: undefined } };
|
|
91
|
+
}
|
|
92
|
+
default:
|
|
93
|
+
return { state };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function composePagerFrame(state, columns, title = "transcript") {
|
|
97
|
+
const clip = (text) => text.length <= columns ? text : text.slice(0, Math.max(0, columns - 1));
|
|
98
|
+
const last = Math.min(state.lines.length, state.top + state.height);
|
|
99
|
+
const position = `${state.lines.length === 0 ? 0 : state.top + 1}-${last} of ${state.lines.length}`;
|
|
100
|
+
const body = state.lines.slice(state.top, state.top + state.height).map((text) => ({ text: clip(text) }));
|
|
101
|
+
while (body.length < state.height)
|
|
102
|
+
body.push({ text: "" });
|
|
103
|
+
const bar = state.search.typing ? `/${state.search.query} Enter find · Esc cancel` : state.message ?? "↑↓ scroll · PgUp/PgDn page · g/G ends · / find · Esc back";
|
|
104
|
+
return [
|
|
105
|
+
{ text: clip(`${title} ${position}`), bold: true },
|
|
106
|
+
...body,
|
|
107
|
+
{ text: clip(bar), dim: true }
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// packages/archymedes-cli/src/ui/pager-screen.tsx
|
|
112
|
+
import { jsxDEV } from "@termuijs/jsx/jsx-dev-runtime";
|
|
113
|
+
var Panel = Box;
|
|
114
|
+
var Line = Text;
|
|
115
|
+
var CHROME_ROWS = 2;
|
|
116
|
+
function PagerScreen({ columns, rows, text, title, onExit }) {
|
|
117
|
+
const [state, setState] = useState(() => initialPagerState(text, rows - CHROME_ROWS));
|
|
118
|
+
useInput((input, key) => {
|
|
119
|
+
const action = keyToPagerAction({ name: key?.key, ctrl: key?.ctrl }, input, state);
|
|
120
|
+
const step = applyPagerAction(state, action);
|
|
121
|
+
if (step.exit) {
|
|
122
|
+
onExit();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
setState(step.state);
|
|
126
|
+
});
|
|
127
|
+
const frame = composePagerFrame(state, columns, title);
|
|
128
|
+
return /* @__PURE__ */ jsxDEV(Panel, {
|
|
129
|
+
flexDirection: "column",
|
|
130
|
+
width: columns,
|
|
131
|
+
height: rows,
|
|
132
|
+
children: frame.map((row, index) => /* @__PURE__ */ jsxDEV(Line, {
|
|
133
|
+
bold: row.bold,
|
|
134
|
+
dimColor: row.dim,
|
|
135
|
+
children: row.text
|
|
136
|
+
}, `row-${index}`, false, undefined, this))
|
|
137
|
+
}, undefined, false, undefined, this);
|
|
138
|
+
}
|
|
139
|
+
async function runPagerScreen(options) {
|
|
140
|
+
const { renderApp } = await import("@termuijs/jsx");
|
|
141
|
+
await new Promise((resolve) => {
|
|
142
|
+
let settled = false;
|
|
143
|
+
const finish = () => {
|
|
144
|
+
if (settled)
|
|
145
|
+
return;
|
|
146
|
+
settled = true;
|
|
147
|
+
resolve();
|
|
148
|
+
};
|
|
149
|
+
renderApp(PagerScreen, { ...options, onExit: finish, fullscreen: true }).catch(finish);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
export {
|
|
153
|
+
runPagerScreen,
|
|
154
|
+
PagerScreen
|
|
155
|
+
};
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import {
|
|
2
|
+
eventJournalPath,
|
|
3
|
+
readEventJournal
|
|
4
|
+
} from "./archymedes-w4bjfye7.mjs";
|
|
5
|
+
import {
|
|
6
|
+
__require
|
|
7
|
+
} from "./archymedes-x67v3n58.mjs";
|
|
8
|
+
|
|
9
|
+
// packages/core/src/cli/projection.ts
|
|
10
|
+
import { promises as fs } from "node:fs";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
var PROJECTION_SCHEMA_VERSION = 1;
|
|
13
|
+
async function loadSqlite() {
|
|
14
|
+
const original = process.emitWarning;
|
|
15
|
+
process.emitWarning = (warning, ...rest) => {
|
|
16
|
+
const text = typeof warning === "string" ? warning : warning?.message ?? "";
|
|
17
|
+
const type = typeof rest[0] === "string" ? rest[0] : rest[0]?.type;
|
|
18
|
+
if (type === "ExperimentalWarning" && /sqlite/i.test(text))
|
|
19
|
+
return;
|
|
20
|
+
return original.call(process, warning, ...rest);
|
|
21
|
+
};
|
|
22
|
+
try {
|
|
23
|
+
return await import("node:sqlite");
|
|
24
|
+
} finally {
|
|
25
|
+
process.emitWarning = original;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
var SCHEMA = `
|
|
29
|
+
CREATE TABLE meta (key TEXT PRIMARY KEY, value TEXT NOT NULL) STRICT;
|
|
30
|
+
CREATE TABLE events (
|
|
31
|
+
session_id TEXT NOT NULL,
|
|
32
|
+
sequence INTEGER NOT NULL,
|
|
33
|
+
timestamp TEXT NOT NULL,
|
|
34
|
+
type TEXT NOT NULL,
|
|
35
|
+
turn_id TEXT,
|
|
36
|
+
hash TEXT NOT NULL,
|
|
37
|
+
payload TEXT NOT NULL,
|
|
38
|
+
PRIMARY KEY (session_id, sequence)
|
|
39
|
+
) STRICT;
|
|
40
|
+
CREATE INDEX events_by_type ON events (session_id, type, sequence);
|
|
41
|
+
-- One row per approval request, updated in place when its decision arrives. Querying "still
|
|
42
|
+
-- waiting" is then an index lookup rather than a join of every request against every decision.
|
|
43
|
+
CREATE TABLE approvals (
|
|
44
|
+
session_id TEXT NOT NULL,
|
|
45
|
+
action_digest TEXT NOT NULL,
|
|
46
|
+
requested_seq INTEGER NOT NULL,
|
|
47
|
+
turn_id TEXT,
|
|
48
|
+
tool_name TEXT NOT NULL,
|
|
49
|
+
summary TEXT NOT NULL,
|
|
50
|
+
decided_seq INTEGER,
|
|
51
|
+
decision TEXT,
|
|
52
|
+
PRIMARY KEY (session_id, requested_seq)
|
|
53
|
+
) STRICT;
|
|
54
|
+
CREATE INDEX approvals_pending ON approvals (session_id, decided_seq);
|
|
55
|
+
-- Searchable text, lowercased once at write time so a query is a scan of prepared values rather
|
|
56
|
+
-- than a per-row LOWER(). FTS5 is deliberately not used: it is a compile-time option, and a
|
|
57
|
+
-- projection that only works on some builds of Node is worse than one that is merely linear.
|
|
58
|
+
CREATE TABLE searchable (
|
|
59
|
+
session_id TEXT NOT NULL,
|
|
60
|
+
sequence INTEGER NOT NULL,
|
|
61
|
+
kind TEXT NOT NULL,
|
|
62
|
+
text TEXT NOT NULL,
|
|
63
|
+
PRIMARY KEY (session_id, sequence, kind)
|
|
64
|
+
) STRICT;
|
|
65
|
+
`;
|
|
66
|
+
function textOf(payload) {
|
|
67
|
+
if (payload.type === "runtime") {
|
|
68
|
+
const event = payload.event;
|
|
69
|
+
if (event.type === "tool_call")
|
|
70
|
+
return [{ kind: "tool_call", text: `${event.toolName} ${JSON.stringify(event.arguments)}` }];
|
|
71
|
+
if (event.type === "tool_result")
|
|
72
|
+
return [{ kind: "tool_result", text: event.content }];
|
|
73
|
+
if (event.type === "runtime_stop")
|
|
74
|
+
return [{ kind: "summary", text: event.summary }];
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
if (payload.type === "approval_requested")
|
|
78
|
+
return [{ kind: "approval", text: payload.request.summary }];
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
class SessionProjection {
|
|
83
|
+
database;
|
|
84
|
+
root;
|
|
85
|
+
file;
|
|
86
|
+
constructor(database, root, file) {
|
|
87
|
+
this.database = database;
|
|
88
|
+
this.root = root;
|
|
89
|
+
this.file = file;
|
|
90
|
+
}
|
|
91
|
+
static async open(root, options = {}) {
|
|
92
|
+
const file = options.file ?? path.join(root, ".archymedes", "projection.db");
|
|
93
|
+
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
94
|
+
const { DatabaseSync } = await loadSqlite();
|
|
95
|
+
const build = () => {
|
|
96
|
+
const database2 = new DatabaseSync(file);
|
|
97
|
+
database2.exec(SCHEMA);
|
|
98
|
+
database2.prepare("INSERT INTO meta (key, value) VALUES (?, ?)").run("schemaVersion", String(PROJECTION_SCHEMA_VERSION));
|
|
99
|
+
return database2;
|
|
100
|
+
};
|
|
101
|
+
let database;
|
|
102
|
+
try {
|
|
103
|
+
database = new DatabaseSync(file);
|
|
104
|
+
const row = database.prepare("SELECT value FROM meta WHERE key = 'schemaVersion'").get();
|
|
105
|
+
if (row?.value !== String(PROJECTION_SCHEMA_VERSION)) {
|
|
106
|
+
database.close();
|
|
107
|
+
database = undefined;
|
|
108
|
+
await fs.rm(file, { force: true });
|
|
109
|
+
database = build();
|
|
110
|
+
}
|
|
111
|
+
} catch {
|
|
112
|
+
try {
|
|
113
|
+
database?.close();
|
|
114
|
+
} catch {}
|
|
115
|
+
await fs.rm(file, { force: true });
|
|
116
|
+
database = build();
|
|
117
|
+
}
|
|
118
|
+
return new SessionProjection(database, root, file);
|
|
119
|
+
}
|
|
120
|
+
close() {
|
|
121
|
+
this.database.close();
|
|
122
|
+
}
|
|
123
|
+
async rebuild(sessionId) {
|
|
124
|
+
const events = await readEventJournal(this.root, sessionId);
|
|
125
|
+
this.database.exec("BEGIN");
|
|
126
|
+
try {
|
|
127
|
+
for (const table of ["events", "approvals", "searchable"]) {
|
|
128
|
+
this.database.prepare(`DELETE FROM ${table} WHERE session_id = ?`).run(sessionId);
|
|
129
|
+
}
|
|
130
|
+
const insertEvent = this.database.prepare("INSERT INTO events (session_id, sequence, timestamp, type, turn_id, hash, payload) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
|
131
|
+
const insertApproval = this.database.prepare("INSERT INTO approvals (session_id, action_digest, requested_seq, turn_id, tool_name, summary) VALUES (?, ?, ?, ?, ?, ?)");
|
|
132
|
+
const decideApproval = this.database.prepare("UPDATE approvals SET decided_seq = ?, decision = ? WHERE session_id = ? AND action_digest = ? AND decided_seq IS NULL");
|
|
133
|
+
const insertText = this.database.prepare("INSERT INTO searchable (session_id, sequence, kind, text) VALUES (?, ?, ?, ?)");
|
|
134
|
+
for (const event of events) {
|
|
135
|
+
const payload = event.payload;
|
|
136
|
+
const turnId = "turnId" in payload ? payload.turnId : null;
|
|
137
|
+
insertEvent.run(sessionId, event.sequence, event.timestamp, payload.type, turnId, event.hash, JSON.stringify(payload));
|
|
138
|
+
if (payload.type === "approval_requested") {
|
|
139
|
+
insertApproval.run(sessionId, payload.request.actionDigest, event.sequence, turnId, payload.request.toolName, payload.request.summary);
|
|
140
|
+
}
|
|
141
|
+
if (payload.type === "approval_decided") {
|
|
142
|
+
decideApproval.run(event.sequence, payload.decision, sessionId, payload.actionDigest);
|
|
143
|
+
}
|
|
144
|
+
for (const entry of textOf(payload))
|
|
145
|
+
insertText.run(sessionId, event.sequence, entry.kind, entry.text.toLowerCase());
|
|
146
|
+
}
|
|
147
|
+
this.database.exec("COMMIT");
|
|
148
|
+
return { events: events.length };
|
|
149
|
+
} catch (error) {
|
|
150
|
+
this.database.exec("ROLLBACK");
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async rebuildAll() {
|
|
155
|
+
const directory = path.dirname(eventJournalPath(this.root, "placeholder"));
|
|
156
|
+
const files = await fs.readdir(directory).catch(() => []);
|
|
157
|
+
let events = 0;
|
|
158
|
+
let sessions = 0;
|
|
159
|
+
for (const file of files) {
|
|
160
|
+
if (!file.endsWith(".jsonl"))
|
|
161
|
+
continue;
|
|
162
|
+
const result = await this.rebuild(file.slice(0, -6));
|
|
163
|
+
events += result.events;
|
|
164
|
+
sessions += 1;
|
|
165
|
+
}
|
|
166
|
+
return { sessions, events };
|
|
167
|
+
}
|
|
168
|
+
eventsAfter(sessionId, cursor, limit = 500) {
|
|
169
|
+
const rows = this.database.prepare("SELECT session_id, sequence, timestamp, type, turn_id, hash, payload FROM events WHERE session_id = ? AND sequence > ? ORDER BY sequence LIMIT ?").all(sessionId, cursor, limit);
|
|
170
|
+
return rows.map((row) => ({
|
|
171
|
+
sessionId: row.session_id,
|
|
172
|
+
sequence: row.sequence,
|
|
173
|
+
timestamp: row.timestamp,
|
|
174
|
+
type: row.type,
|
|
175
|
+
turnId: row.turn_id ?? null,
|
|
176
|
+
hash: row.hash,
|
|
177
|
+
payload: JSON.parse(row.payload)
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
cursor(sessionId) {
|
|
181
|
+
const row = this.database.prepare("SELECT MAX(sequence) AS last FROM events WHERE session_id = ?").get(sessionId);
|
|
182
|
+
return row?.last ?? 0;
|
|
183
|
+
}
|
|
184
|
+
pendingApprovals(sessionId) {
|
|
185
|
+
const rows = sessionId ? this.database.prepare("SELECT * FROM approvals WHERE decided_seq IS NULL AND session_id = ? ORDER BY requested_seq").all(sessionId) : this.database.prepare("SELECT * FROM approvals WHERE decided_seq IS NULL ORDER BY session_id, requested_seq").all();
|
|
186
|
+
return rows.map((row) => ({
|
|
187
|
+
sessionId: row.session_id,
|
|
188
|
+
actionDigest: row.action_digest,
|
|
189
|
+
requestedSeq: row.requested_seq,
|
|
190
|
+
turnId: row.turn_id ?? null,
|
|
191
|
+
toolName: row.tool_name,
|
|
192
|
+
summary: row.summary
|
|
193
|
+
}));
|
|
194
|
+
}
|
|
195
|
+
search(query, options = {}) {
|
|
196
|
+
const needle = query.trim().toLowerCase();
|
|
197
|
+
if (!needle)
|
|
198
|
+
return [];
|
|
199
|
+
const pattern = `%${needle.replace(/[\\%_]/g, (character) => `\\${character}`)}%`;
|
|
200
|
+
const limit = options.limit ?? 50;
|
|
201
|
+
const rows = options.sessionId ? this.database.prepare("SELECT * FROM searchable WHERE text LIKE ? ESCAPE '\\' AND session_id = ? ORDER BY sequence LIMIT ?").all(pattern, options.sessionId, limit) : this.database.prepare("SELECT * FROM searchable WHERE text LIKE ? ESCAPE '\\' ORDER BY session_id, sequence LIMIT ?").all(pattern, limit);
|
|
202
|
+
return rows.map((row) => ({ sessionId: row.session_id, sequence: row.sequence, kind: row.kind, text: row.text }));
|
|
203
|
+
}
|
|
204
|
+
sessions() {
|
|
205
|
+
const rows = this.database.prepare("SELECT session_id, COUNT(*) AS events, MIN(timestamp) AS first_at, MAX(timestamp) AS last_at, MAX(sequence) AS last_sequence FROM events GROUP BY session_id ORDER BY last_at DESC").all();
|
|
206
|
+
return rows.map((row) => ({
|
|
207
|
+
sessionId: row.session_id,
|
|
208
|
+
events: row.events,
|
|
209
|
+
firstAt: row.first_at,
|
|
210
|
+
lastAt: row.last_at,
|
|
211
|
+
lastSequence: row.last_sequence
|
|
212
|
+
}));
|
|
213
|
+
}
|
|
214
|
+
fork(sessionId, newSessionId, throughSequence) {
|
|
215
|
+
if (newSessionId === sessionId)
|
|
216
|
+
throw new Error("A fork needs a different session id");
|
|
217
|
+
this.database.exec("BEGIN");
|
|
218
|
+
try {
|
|
219
|
+
for (const table of ["events", "approvals", "searchable"]) {
|
|
220
|
+
this.database.prepare(`DELETE FROM ${table} WHERE session_id = ?`).run(newSessionId);
|
|
221
|
+
}
|
|
222
|
+
this.database.prepare("INSERT INTO events (session_id, sequence, timestamp, type, turn_id, hash, payload) SELECT ?, sequence, timestamp, type, turn_id, hash, payload FROM events WHERE session_id = ? AND sequence <= ?").run(newSessionId, sessionId, throughSequence);
|
|
223
|
+
this.database.prepare("INSERT INTO approvals (session_id, action_digest, requested_seq, turn_id, tool_name, summary, decided_seq, decision) SELECT ?, action_digest, requested_seq, turn_id, tool_name, summary, decided_seq, decision FROM approvals WHERE session_id = ? AND requested_seq <= ?").run(newSessionId, sessionId, throughSequence);
|
|
224
|
+
this.database.prepare("INSERT INTO searchable (session_id, sequence, kind, text) SELECT ?, sequence, kind, text FROM searchable WHERE session_id = ? AND sequence <= ?").run(newSessionId, sessionId, throughSequence);
|
|
225
|
+
this.database.exec("COMMIT");
|
|
226
|
+
return { events: this.cursor(newSessionId) === 0 ? 0 : this.eventsAfter(newSessionId, 0, Number.MAX_SAFE_INTEGER).length };
|
|
227
|
+
} catch (error) {
|
|
228
|
+
this.database.exec("ROLLBACK");
|
|
229
|
+
throw error;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
archive(sessionId) {
|
|
233
|
+
this.database.exec("BEGIN");
|
|
234
|
+
try {
|
|
235
|
+
for (const table of ["events", "approvals", "searchable"]) {
|
|
236
|
+
this.database.prepare(`DELETE FROM ${table} WHERE session_id = ?`).run(sessionId);
|
|
237
|
+
}
|
|
238
|
+
this.database.exec("COMMIT");
|
|
239
|
+
} catch (error) {
|
|
240
|
+
this.database.exec("ROLLBACK");
|
|
241
|
+
throw error;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
export {
|
|
246
|
+
SessionProjection,
|
|
247
|
+
PROJECTION_SCHEMA_VERSION
|
|
248
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ALLOWED_SANDBOX_PROGRAMS
|
|
3
|
-
} from "./archymedes-
|
|
3
|
+
} from "./archymedes-1g1y6q74.mjs";
|
|
4
4
|
import"./archymedes-x67v3n58.mjs";
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// packages/core/src/sandbox-templates.ts
|
|
7
7
|
var WORKSPACE_PRESETS = [
|
|
8
8
|
{
|
|
9
9
|
id: "general",
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {
|
|
2
|
+
applyAction,
|
|
3
|
+
composeFrame,
|
|
4
|
+
keyToAction
|
|
5
|
+
} from "./archymedes-138genyy.mjs";
|
|
6
|
+
import"./archymedes-5vhvv8kr.mjs";
|
|
7
|
+
import"./archymedes-bmtdqqwt.mjs";
|
|
8
|
+
import {
|
|
9
|
+
exitTopTermUIApp
|
|
10
|
+
} from "./archymedes-130jt0wr.mjs";
|
|
11
|
+
import {
|
|
12
|
+
__require
|
|
13
|
+
} from "./archymedes-x67v3n58.mjs";
|
|
14
|
+
|
|
15
|
+
// packages/archymedes-cli/src/ui/workspace-screen.tsx
|
|
16
|
+
import { useInput, useInterval, useState } from "@termuijs/jsx";
|
|
17
|
+
import { Box, Text } from "@termuijs/widgets";
|
|
18
|
+
import { jsxDEV } from "@termuijs/jsx/jsx-dev-runtime";
|
|
19
|
+
var Panel = Box;
|
|
20
|
+
var Line = Text;
|
|
21
|
+
function Workspace({ read, onExit, refreshMs = 200 }) {
|
|
22
|
+
const [snapshot, setSnapshot] = useState(() => read());
|
|
23
|
+
useInterval(() => {
|
|
24
|
+
setSnapshot((current) => ({ ...read(), selected: current.selected, scroll: current.scroll }));
|
|
25
|
+
}, refreshMs);
|
|
26
|
+
useInput((input, key) => {
|
|
27
|
+
const action = keyToAction({ name: key?.key, ctrl: key?.ctrl, shift: key?.shift }, input);
|
|
28
|
+
if (action.kind === "exit") {
|
|
29
|
+
onExit();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
setSnapshot((current) => applyAction(current, action));
|
|
33
|
+
});
|
|
34
|
+
const rows = composeFrame(snapshot);
|
|
35
|
+
return /* @__PURE__ */ jsxDEV(Panel, {
|
|
36
|
+
flexDirection: "column",
|
|
37
|
+
width: snapshot.columns,
|
|
38
|
+
height: snapshot.rows,
|
|
39
|
+
children: rows.map((row, index) => /* @__PURE__ */ jsxDEV(Line, {
|
|
40
|
+
bold: row.bold,
|
|
41
|
+
dimColor: row.dim,
|
|
42
|
+
inverse: row.inverse,
|
|
43
|
+
color: row.color,
|
|
44
|
+
children: row.text
|
|
45
|
+
}, `row-${index}`, false, undefined, this))
|
|
46
|
+
}, undefined, false, undefined, this);
|
|
47
|
+
}
|
|
48
|
+
async function runWorkspace(host) {
|
|
49
|
+
const { renderApp } = await import("@termuijs/jsx");
|
|
50
|
+
await new Promise((resolve) => {
|
|
51
|
+
let settled = false;
|
|
52
|
+
const finish = () => {
|
|
53
|
+
if (settled)
|
|
54
|
+
return;
|
|
55
|
+
settled = true;
|
|
56
|
+
exitTopTermUIApp();
|
|
57
|
+
host.onExit?.();
|
|
58
|
+
resolve();
|
|
59
|
+
};
|
|
60
|
+
renderApp(Workspace, {
|
|
61
|
+
read: host.read,
|
|
62
|
+
onExit: finish,
|
|
63
|
+
fullscreen: true
|
|
64
|
+
}).catch(finish);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
runWorkspace,
|
|
69
|
+
Workspace
|
|
70
|
+
};
|