@aui.io/apollo 0.1.7 → 0.1.10
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/node_modules/@aui.io/apollo-cli/bin/apollo.js +8 -5
- package/node_modules/@aui.io/apollo-cli/dist/src/commands/operate.js +3 -10
- package/node_modules/@aui.io/apollo-cli/dist/src/commands/operate.js.map +1 -1
- package/node_modules/@aui.io/apollo-cli/package.json +3 -3
- package/node_modules/@aui.io/apollo-core/dist/src/api/runtime-api.d.ts +13 -0
- package/node_modules/@aui.io/apollo-core/dist/src/api/runtime-api.js +17 -0
- package/node_modules/@aui.io/apollo-core/dist/src/api/runtime-api.js.map +1 -1
- package/node_modules/@aui.io/apollo-core/dist/src/services/hierarchy.js +7 -1
- package/node_modules/@aui.io/apollo-core/dist/src/services/hierarchy.js.map +1 -1
- package/node_modules/@aui.io/apollo-core/dist/src/services/messaging.d.ts +17 -0
- package/node_modules/@aui.io/apollo-core/dist/src/services/messaging.js +27 -0
- package/node_modules/@aui.io/apollo-core/dist/src/services/messaging.js.map +1 -1
- package/node_modules/@aui.io/apollo-core/package.json +1 -1
- package/node_modules/@aui.io/apollo-tui/dist/src/actions/ActionPalette.d.ts +13 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/actions/ActionPalette.js +47 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/actions/ActionPalette.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/actions/registry.d.ts +28 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/actions/registry.js +219 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/actions/registry.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/activity/ActivityDrawer.d.ts +8 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/activity/ActivityDrawer.js +43 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/activity/ActivityDrawer.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/activity/ActivitySummary.d.ts +5 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/activity/ActivitySummary.js +26 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/activity/ActivitySummary.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/activity/operationStore.d.ts +67 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/activity/operationStore.js +138 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/activity/operationStore.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/AuthorHome.d.ts +27 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/AuthorHome.js +92 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/AuthorHome.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/DiffView.d.ts +46 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/DiffView.js +87 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/DiffView.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/SessionPane.d.ts +15 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/SessionPane.js +38 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/SessionPane.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/ValidationView.d.ts +11 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/ValidationView.js +34 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/ValidationView.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/VersionsView.d.ts +9 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/VersionsView.js +31 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/VersionsView.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/backend/claudeCode.d.ts +23 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/backend/claudeCode.js +293 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/backend/claudeCode.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/backend/index.d.ts +4 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/backend/index.js +13 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/backend/index.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/backend/sessions.d.ts +3 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/backend/sessions.js +36 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/backend/sessions.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/backend/types.d.ts +85 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/backend/types.js +11 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/backend/types.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/data.d.ts +78 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/data.js +279 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/data.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/session.d.ts +64 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/session.js +319 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/session.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/tree.d.ts +25 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/tree.js +69 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/author/tree.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/context/ContextSwitcher.d.ts +23 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/context/ContextSwitcher.js +60 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/context/ContextSwitcher.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/index.d.ts +19 -2
- package/node_modules/@aui.io/apollo-tui/dist/src/index.js +24 -2
- package/node_modules/@aui.io/apollo-tui/dist/src/index.js.map +1 -1
- package/node_modules/@aui.io/apollo-tui/dist/src/keyprobe.d.ts +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/keyprobe.js +51 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/keyprobe.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/actions.d.ts +56 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/actions.js +1019 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/actions.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/clipboard.d.ts +7 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/clipboard.js +33 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/clipboard.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/commands.d.ts +10 -4
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/commands.js +444 -23
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/commands.js.map +1 -1
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/confirm.d.ts +10 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/confirm.js +12 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/confirm.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/ide.d.ts +16 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/ide.js +39 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/ide.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/keydiag.d.ts +17 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/keydiag.js +76 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/keydiag.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/keys.d.ts +64 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/keys.js +105 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/keys.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/modes.d.ts +18 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/modes.js +24 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/modes.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/picker.d.ts +28 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/picker.js +72 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/picker.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/place.d.ts +26 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/place.js +32 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/place.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/scope.d.ts +29 -6
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/scope.js +112 -13
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/scope.js.map +1 -1
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/sheet.d.ts +5 -10
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/sheet.js +2 -1
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/sheet.js.map +1 -1
- package/node_modules/@aui.io/apollo-tui/dist/src/opentui-app.js +2106 -273
- package/node_modules/@aui.io/apollo-tui/dist/src/opentui-app.js.map +1 -1
- package/node_modules/@aui.io/apollo-tui/dist/src/shell/Breadcrumb.d.ts +15 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/shell/Breadcrumb.js +22 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/shell/Breadcrumb.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/shell/FooterHints.d.ts +8 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/shell/FooterHints.js +23 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/shell/FooterHints.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/shell/ModeNav.d.ts +4 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/shell/ModeNav.js +7 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/shell/ModeNav.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/Composer.d.ts +20 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/Composer.js +29 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/Composer.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/InspectorPane.d.ts +15 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/InspectorPane.js +27 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/InspectorPane.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/TalkView.d.ts +30 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/TalkView.js +60 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/TalkView.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/ThreadsPane.d.ts +17 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/ThreadsPane.js +61 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/ThreadsPane.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/data.d.ts +107 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/data.js +235 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/talk/data.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/theme/tokens.d.ts +8 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/theme/tokens.js +9 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/theme/tokens.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/ui/ConfirmPane.d.ts +4 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/ui/ConfirmPane.js +15 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/ui/ConfirmPane.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/ui/OutputPane.d.ts +5 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/ui/OutputPane.js +16 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/ui/OutputPane.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/ui/PickerPane.d.ts +10 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/ui/PickerPane.js +29 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/ui/PickerPane.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/ui/SheetPane.d.ts +4 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/ui/SheetPane.js +22 -0
- package/node_modules/@aui.io/apollo-tui/dist/src/ui/SheetPane.js.map +1 -0
- package/node_modules/@aui.io/apollo-tui/package.json +2 -2
- package/package.json +4 -4
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/tabs.d.ts +0 -10
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/tabs.js +0 -19
- package/node_modules/@aui.io/apollo-tui/dist/src/lib/tabs.js.map +0 -1
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Author workbench data layer — snapshots of the local checkout vs baseline,
|
|
3
|
+
* structured validation records, and content diffs vs the remote version.
|
|
4
|
+
* All reads go through apollo-core; the filesystem is the source of truth.
|
|
5
|
+
*/
|
|
6
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import { readBaseline } from "@aui.io/apollo-core/bundle/baseline.js";
|
|
10
|
+
import { readProgramFiles } from "@aui.io/apollo-core/bundle/files.js";
|
|
11
|
+
import { bundleFiles } from "@aui.io/apollo-core/bundle/materialize.js";
|
|
12
|
+
import { localDiff, validateLocalBundle, } from "@aui.io/apollo-core/services/bundles.js";
|
|
13
|
+
export function agentRootOf(context) {
|
|
14
|
+
return (context.agentRoot ??
|
|
15
|
+
(context.bindingPath ? path.dirname(context.bindingPath) : undefined));
|
|
16
|
+
}
|
|
17
|
+
export function bundleSrcRoot(context) {
|
|
18
|
+
const root = agentRootOf(context);
|
|
19
|
+
return root ? path.join(root, "bundle", "src") : undefined;
|
|
20
|
+
}
|
|
21
|
+
export async function loadAuthorSnapshot(context) {
|
|
22
|
+
const loadedAt = Date.now();
|
|
23
|
+
if (!context.agentId) {
|
|
24
|
+
return { unavailable: "No active agent", loadedAt };
|
|
25
|
+
}
|
|
26
|
+
const baseline = await readBaseline(homedir(), context.agentId).catch(() => null);
|
|
27
|
+
try {
|
|
28
|
+
const diff = await localDiff(context);
|
|
29
|
+
return {
|
|
30
|
+
diff,
|
|
31
|
+
...(baseline?.versionTag ? { baselineTag: baseline.versionTag } : {}),
|
|
32
|
+
...(baseline?.writtenAt ? { baselineAt: baseline.writtenAt } : {}),
|
|
33
|
+
loadedAt,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
return {
|
|
38
|
+
...(baseline?.versionTag ? { baselineTag: baseline.versionTag } : {}),
|
|
39
|
+
unavailable: error instanceof Error ? error.message : String(error),
|
|
40
|
+
loadedAt,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export async function runValidationRecord(context, runtime) {
|
|
45
|
+
const result = await validateLocalBundle(context, runtime);
|
|
46
|
+
return { result, at: Date.now(), stale: false };
|
|
47
|
+
}
|
|
48
|
+
export function changeEntries(diff) {
|
|
49
|
+
if (!diff)
|
|
50
|
+
return [];
|
|
51
|
+
return [
|
|
52
|
+
...diff.added.map((p) => ({ status: "A", path: p })),
|
|
53
|
+
...diff.changed.map((p) => ({ status: "M", path: p })),
|
|
54
|
+
...diff.removed.map((p) => ({ status: "D", path: p })),
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
export function changesSummary(diff) {
|
|
58
|
+
if (!diff)
|
|
59
|
+
return "unknown";
|
|
60
|
+
const total = diff.added.length + diff.changed.length + diff.removed.length;
|
|
61
|
+
if (total === 0)
|
|
62
|
+
return "clean";
|
|
63
|
+
return `+${diff.added.length} ~${diff.changed.length} -${diff.removed.length}`;
|
|
64
|
+
}
|
|
65
|
+
export function relativeTime(atMs, nowMs = Date.now()) {
|
|
66
|
+
const seconds = Math.max(0, Math.round((nowMs - atMs) / 1000));
|
|
67
|
+
if (seconds < 10)
|
|
68
|
+
return "just now";
|
|
69
|
+
if (seconds < 60)
|
|
70
|
+
return `${seconds}s ago`;
|
|
71
|
+
const minutes = Math.round(seconds / 60);
|
|
72
|
+
if (minutes < 60)
|
|
73
|
+
return `${minutes}m ago`;
|
|
74
|
+
const hours = Math.round(minutes / 60);
|
|
75
|
+
if (hours < 48)
|
|
76
|
+
return `${hours}h ago`;
|
|
77
|
+
return `${Math.round(hours / 24)}d ago`;
|
|
78
|
+
}
|
|
79
|
+
export function validationSummary(record) {
|
|
80
|
+
if (!record)
|
|
81
|
+
return "not run";
|
|
82
|
+
const errors = record.result.findings.filter((f) => f.level !== "warning").length;
|
|
83
|
+
const warnings = record.result.findings.filter((f) => f.level === "warning").length;
|
|
84
|
+
const state = record.result.valid && errors === 0 ? "✓ valid" : `✕ ${errors} error(s)`;
|
|
85
|
+
const age = relativeTime(record.at);
|
|
86
|
+
const staleNote = record.stale ? " · stale (files changed)" : "";
|
|
87
|
+
return `${state}${warnings ? ` · ${warnings} warning(s)` : ""} · ${age}${staleNote}`;
|
|
88
|
+
}
|
|
89
|
+
/** Local program files (path → content) for content diffs. */
|
|
90
|
+
export async function readLocalFiles(context) {
|
|
91
|
+
const root = bundleSrcRoot(context);
|
|
92
|
+
if (!root)
|
|
93
|
+
return {};
|
|
94
|
+
const program = await readProgramFiles(root);
|
|
95
|
+
return program.files;
|
|
96
|
+
}
|
|
97
|
+
/** Remote files at the bound tag (path → content). One fetch, caller caches. */
|
|
98
|
+
export async function fetchRemoteFiles(context, management) {
|
|
99
|
+
if (!context.agentId)
|
|
100
|
+
throw new Error("No active agent");
|
|
101
|
+
if (!context.versionTag)
|
|
102
|
+
throw new Error("No version tag bound");
|
|
103
|
+
const version = await management.resolveVersion(context.agentId, context.versionTag);
|
|
104
|
+
const pull = await management.pullVersion(context.agentId, version.id);
|
|
105
|
+
return bundleFiles(pull.bundle);
|
|
106
|
+
}
|
|
107
|
+
export function defaultDiffStyle(width) {
|
|
108
|
+
return width >= 140 ? "split" : "unified";
|
|
109
|
+
}
|
|
110
|
+
/** Pair unified diff lines into aligned split rows (Git style). */
|
|
111
|
+
export function splitRows(lines) {
|
|
112
|
+
const rows = [];
|
|
113
|
+
let removals = [];
|
|
114
|
+
let additions = [];
|
|
115
|
+
const flush = () => {
|
|
116
|
+
const count = Math.max(removals.length, additions.length);
|
|
117
|
+
for (let i = 0; i < count; i++) {
|
|
118
|
+
rows.push({ left: removals[i], right: additions[i] });
|
|
119
|
+
}
|
|
120
|
+
removals = [];
|
|
121
|
+
additions = [];
|
|
122
|
+
};
|
|
123
|
+
for (const line of lines) {
|
|
124
|
+
if (line.tag === "-")
|
|
125
|
+
removals.push(line);
|
|
126
|
+
else if (line.tag === "+")
|
|
127
|
+
additions.push(line);
|
|
128
|
+
else {
|
|
129
|
+
flush();
|
|
130
|
+
rows.push({ left: line, right: line });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
flush();
|
|
134
|
+
return rows;
|
|
135
|
+
}
|
|
136
|
+
const MAX_DIFF_LINES = 2000;
|
|
137
|
+
/**
|
|
138
|
+
* Line diff (common prefix/suffix trim + LCS middle). Good enough for program
|
|
139
|
+
* files; oversized inputs degrade to a truncation notice.
|
|
140
|
+
*/
|
|
141
|
+
export function diffLines(before, after) {
|
|
142
|
+
const a = before.split("\n");
|
|
143
|
+
const b = after.split("\n");
|
|
144
|
+
let start = 0;
|
|
145
|
+
while (start < a.length && start < b.length && a[start] === b[start])
|
|
146
|
+
start++;
|
|
147
|
+
let endA = a.length;
|
|
148
|
+
let endB = b.length;
|
|
149
|
+
while (endA > start && endB > start && a[endA - 1] === b[endB - 1]) {
|
|
150
|
+
endA--;
|
|
151
|
+
endB--;
|
|
152
|
+
}
|
|
153
|
+
const midA = a.slice(start, endA);
|
|
154
|
+
const midB = b.slice(start, endB);
|
|
155
|
+
if (midA.length + midB.length > MAX_DIFF_LINES) {
|
|
156
|
+
return [
|
|
157
|
+
{ tag: " ", text: `(diff too large — ${midA.length} vs ${midB.length} changed lines)` },
|
|
158
|
+
];
|
|
159
|
+
}
|
|
160
|
+
// LCS table over the trimmed middle.
|
|
161
|
+
const rows = midA.length + 1;
|
|
162
|
+
const cols = midB.length + 1;
|
|
163
|
+
const table = new Uint16Array(rows * cols);
|
|
164
|
+
for (let i = midA.length - 1; i >= 0; i--) {
|
|
165
|
+
for (let j = midB.length - 1; j >= 0; j--) {
|
|
166
|
+
table[i * cols + j] =
|
|
167
|
+
midA[i] === midB[j]
|
|
168
|
+
? table[(i + 1) * cols + j + 1] + 1
|
|
169
|
+
: Math.max(table[(i + 1) * cols + j], table[i * cols + j + 1]);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const lines = [];
|
|
173
|
+
for (let k = 0; k < start; k++)
|
|
174
|
+
lines.push({ tag: " ", text: a[k] });
|
|
175
|
+
let i = 0;
|
|
176
|
+
let j = 0;
|
|
177
|
+
while (i < midA.length && j < midB.length) {
|
|
178
|
+
if (midA[i] === midB[j]) {
|
|
179
|
+
lines.push({ tag: " ", text: midA[i] });
|
|
180
|
+
i++;
|
|
181
|
+
j++;
|
|
182
|
+
}
|
|
183
|
+
else if (table[(i + 1) * cols + j] >= table[i * cols + j + 1]) {
|
|
184
|
+
lines.push({ tag: "-", text: midA[i] });
|
|
185
|
+
i++;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
lines.push({ tag: "+", text: midB[j] });
|
|
189
|
+
j++;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
while (i < midA.length)
|
|
193
|
+
lines.push({ tag: "-", text: midA[i++] });
|
|
194
|
+
while (j < midB.length)
|
|
195
|
+
lines.push({ tag: "+", text: midB[j++] });
|
|
196
|
+
for (let k = endA; k < a.length; k++)
|
|
197
|
+
lines.push({ tag: " ", text: a[k] });
|
|
198
|
+
return lines;
|
|
199
|
+
}
|
|
200
|
+
/** Content diff for one changed file: remote (bound tag) → local. */
|
|
201
|
+
export function fileContentDiff(filePath, localFiles, remoteFiles) {
|
|
202
|
+
const local = localFiles[filePath];
|
|
203
|
+
const remote = remoteFiles[filePath];
|
|
204
|
+
if (local === undefined && remote === undefined) {
|
|
205
|
+
return [{ tag: " ", text: "(file not found locally or remotely)" }];
|
|
206
|
+
}
|
|
207
|
+
// A missing file is not an empty file — one-sided diffs are all +/-.
|
|
208
|
+
if (remote === undefined) {
|
|
209
|
+
return local.split("\n").map((text) => ({ tag: "+", text }));
|
|
210
|
+
}
|
|
211
|
+
if (local === undefined) {
|
|
212
|
+
return remote.split("\n").map((text) => ({ tag: "-", text }));
|
|
213
|
+
}
|
|
214
|
+
return diffLines(remote, local);
|
|
215
|
+
}
|
|
216
|
+
export function formatVersionRow(version) {
|
|
217
|
+
const label = version.label ? ` · ${version.label}` : "";
|
|
218
|
+
return `${version.version_tag.padEnd(10)} ${version.status.padEnd(10)}${label}`;
|
|
219
|
+
}
|
|
220
|
+
const PLACE_SKIP_DIRS = new Set([
|
|
221
|
+
".git",
|
|
222
|
+
"node_modules",
|
|
223
|
+
".apollo",
|
|
224
|
+
"dist",
|
|
225
|
+
".venv",
|
|
226
|
+
"__pycache__",
|
|
227
|
+
]);
|
|
228
|
+
/**
|
|
229
|
+
* Relative file paths under `root` for the browse tree (workspace level or
|
|
230
|
+
* clean checkouts). Skips vendored/system dirs; capped for sanity.
|
|
231
|
+
*/
|
|
232
|
+
export async function listPlaceFiles(root, cap = 800) {
|
|
233
|
+
const out = [];
|
|
234
|
+
async function walk(dir, rel) {
|
|
235
|
+
if (out.length >= cap)
|
|
236
|
+
return;
|
|
237
|
+
let entries;
|
|
238
|
+
try {
|
|
239
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
return; // unreadable dir — skip silently
|
|
243
|
+
}
|
|
244
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
245
|
+
for (const entry of entries) {
|
|
246
|
+
if (out.length >= cap)
|
|
247
|
+
return;
|
|
248
|
+
if (entry.name.startsWith(".") && entry.name !== ".apollorc")
|
|
249
|
+
continue;
|
|
250
|
+
if (PLACE_SKIP_DIRS.has(entry.name))
|
|
251
|
+
continue;
|
|
252
|
+
const childRel = rel ? `${rel}/${entry.name}` : entry.name;
|
|
253
|
+
if (entry.isDirectory())
|
|
254
|
+
await walk(path.join(dir, entry.name), childRel);
|
|
255
|
+
else if (entry.isFile())
|
|
256
|
+
out.push(childRel);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
await walk(root, "");
|
|
260
|
+
return out;
|
|
261
|
+
}
|
|
262
|
+
const MAX_PREVIEW_BYTES = 256 * 1024;
|
|
263
|
+
const MAX_PREVIEW_LINES = 2000;
|
|
264
|
+
/** Read one file for the browse preview (size-capped, line-capped). */
|
|
265
|
+
export async function readPlaceFile(root, rel) {
|
|
266
|
+
const content = await readFile(path.join(root, rel), "utf8");
|
|
267
|
+
const clipped = content.length > MAX_PREVIEW_BYTES
|
|
268
|
+
? content.slice(0, MAX_PREVIEW_BYTES)
|
|
269
|
+
: content;
|
|
270
|
+
const lines = clipped.split("\n");
|
|
271
|
+
if (lines.length > MAX_PREVIEW_LINES) {
|
|
272
|
+
return [
|
|
273
|
+
...lines.slice(0, MAX_PREVIEW_LINES),
|
|
274
|
+
`… ${lines.length - MAX_PREVIEW_LINES} more line(s)`,
|
|
275
|
+
];
|
|
276
|
+
}
|
|
277
|
+
return lines;
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.js","sourceRoot":"","sources":["../../../src/author/data.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Author copilot session — a multi-turn transcript of work units, reduced
|
|
3
|
+
* from normalized backend events. Pure and backend-agnostic: the UI renders
|
|
4
|
+
* `sessionRows` and never looks inside vendor payloads.
|
|
5
|
+
*
|
|
6
|
+
* Unit semantics (Claude-Code-like): prose renders in full; tool calls
|
|
7
|
+
* (Bash, Edit, Skill, …) are one-line units that expand (Enter) to show
|
|
8
|
+
* their input and result; prompts and outcomes mark turn boundaries.
|
|
9
|
+
*/
|
|
10
|
+
import type { BackendEvent } from "./backend/types.js";
|
|
11
|
+
export type UnitKind = "prompt" | "text" | "thinking" | "action" | "outcome";
|
|
12
|
+
export type UnitStatus = "running" | "ok" | "error" | "cancelled";
|
|
13
|
+
export interface WorkUnit {
|
|
14
|
+
id: number;
|
|
15
|
+
turn: number;
|
|
16
|
+
kind: UnitKind;
|
|
17
|
+
/** One-line summary ("Bash — ls", "turn complete · 2 turns"); prose units use body only. */
|
|
18
|
+
label: string;
|
|
19
|
+
/** Expandable payload: tool input/result lines; prose lines for text units. */
|
|
20
|
+
body: string[];
|
|
21
|
+
status?: UnitStatus;
|
|
22
|
+
/** Backend correlation id — matches action-start/action/action-result. */
|
|
23
|
+
actionId?: string;
|
|
24
|
+
/** Accumulating from deltas; the complete event replaces the content. */
|
|
25
|
+
streaming?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface SessionState {
|
|
28
|
+
units: WorkUnit[];
|
|
29
|
+
nextId: number;
|
|
30
|
+
turn: number;
|
|
31
|
+
running: boolean;
|
|
32
|
+
backend: string;
|
|
33
|
+
}
|
|
34
|
+
export declare function sessionCreate(backend: string): SessionState;
|
|
35
|
+
/** A new user instruction starts a turn (appends to the same transcript). */
|
|
36
|
+
export declare function sessionPrompt(session: SessionState, text: string): SessionState;
|
|
37
|
+
/**
|
|
38
|
+
* Strip the checkout prefix from event text so tool lines read as repo paths
|
|
39
|
+
* (`bundle/src/program.yaml`, not `/Users/…/agents/x/bundle/src/program.yaml`).
|
|
40
|
+
* Applied at the app seam — works for any backend.
|
|
41
|
+
*/
|
|
42
|
+
export declare function relativizeEvent(event: BackendEvent, root: string): BackendEvent;
|
|
43
|
+
export declare function sessionEvent(session: SessionState, event: BackendEvent): SessionState;
|
|
44
|
+
export declare function sessionCancel(session: SessionState): SessionState;
|
|
45
|
+
export type RowTone = "prompt" | "prose" | "thinking" | "action" | "action-running" | "action-error" | "body" | "outcome-ok" | "outcome-error" | "outcome-cancelled" | "hint" | "queued" | "spacer";
|
|
46
|
+
export interface SessionRow {
|
|
47
|
+
/** Index into session.units this row belongs to (spacers bind forward). */
|
|
48
|
+
unit: number;
|
|
49
|
+
/** First visible row of the unit — the cursor lands here. */
|
|
50
|
+
isLabel: boolean;
|
|
51
|
+
tone: RowTone;
|
|
52
|
+
text: string;
|
|
53
|
+
}
|
|
54
|
+
/** Word-wrap one line to a width; hard-breaks anything unbreakable. */
|
|
55
|
+
export declare function wrapText(line: string, width: number): string[];
|
|
56
|
+
/**
|
|
57
|
+
* Flatten the session into renderable rows. `width` is the usable pane
|
|
58
|
+
* width — rows are pre-wrapped so row counts (and scroll targets) are exact.
|
|
59
|
+
* `queued` prompts (typed while a turn runs) render as dim trailing rows;
|
|
60
|
+
* they become real prompt units when their turn starts.
|
|
61
|
+
*/
|
|
62
|
+
export declare function sessionRows(session: SessionState, expanded: ReadonlySet<number>, width: number, queued?: readonly string[]): SessionRow[];
|
|
63
|
+
/** First row of a unit — the scroll target when the cursor moves. */
|
|
64
|
+
export declare function unitRowOffset(rows: SessionRow[], unitIndex: number): number;
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
const UNIT_CAP = 400;
|
|
2
|
+
export function sessionCreate(backend) {
|
|
3
|
+
return { units: [], nextId: 1, turn: 0, running: false, backend };
|
|
4
|
+
}
|
|
5
|
+
function append(session, unit) {
|
|
6
|
+
const next = { ...unit, id: session.nextId, turn: session.turn };
|
|
7
|
+
return {
|
|
8
|
+
...session,
|
|
9
|
+
nextId: session.nextId + 1,
|
|
10
|
+
units: [...session.units, next].slice(-UNIT_CAP),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** A new user instruction starts a turn (appends to the same transcript). */
|
|
14
|
+
export function sessionPrompt(session, text) {
|
|
15
|
+
const started = { ...session, turn: session.turn + 1, running: true };
|
|
16
|
+
return append(started, { kind: "prompt", label: text, body: [] });
|
|
17
|
+
}
|
|
18
|
+
/** Terminal events settle pending work — nothing spins afterwards. */
|
|
19
|
+
function settleUnits(units) {
|
|
20
|
+
return units.map((u) => {
|
|
21
|
+
if (u.kind === "action" && u.status === "running") {
|
|
22
|
+
return { ...u, status: "ok", streaming: false };
|
|
23
|
+
}
|
|
24
|
+
if (u.streaming)
|
|
25
|
+
return { ...u, streaming: false };
|
|
26
|
+
return u;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/** Append a delta to body lines, splitting embedded newlines. */
|
|
30
|
+
function appendDelta(body, delta) {
|
|
31
|
+
const fragments = delta.split("\n");
|
|
32
|
+
if (body.length === 0)
|
|
33
|
+
return fragments;
|
|
34
|
+
const next = [...body];
|
|
35
|
+
next[next.length - 1] = `${next[next.length - 1]}${fragments[0]}`;
|
|
36
|
+
return [...next, ...fragments.slice(1)];
|
|
37
|
+
}
|
|
38
|
+
/** Replace one unit immutably. */
|
|
39
|
+
function patchUnit(session, index, patch) {
|
|
40
|
+
const units = [...session.units];
|
|
41
|
+
units[index] = { ...units[index], ...patch };
|
|
42
|
+
return { ...session, units };
|
|
43
|
+
}
|
|
44
|
+
function lastIndexBy(units, match) {
|
|
45
|
+
for (let i = units.length - 1; i >= 0; i--) {
|
|
46
|
+
if (match(units[i]))
|
|
47
|
+
return i;
|
|
48
|
+
}
|
|
49
|
+
return -1;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Strip the checkout prefix from event text so tool lines read as repo paths
|
|
53
|
+
* (`bundle/src/program.yaml`, not `/Users/…/agents/x/bundle/src/program.yaml`).
|
|
54
|
+
* Applied at the app seam — works for any backend.
|
|
55
|
+
*/
|
|
56
|
+
export function relativizeEvent(event, root) {
|
|
57
|
+
if (!root)
|
|
58
|
+
return event;
|
|
59
|
+
const prefix = root.endsWith("/") ? root : `${root}/`;
|
|
60
|
+
const strip = (text) => text.split(prefix).join("");
|
|
61
|
+
switch (event.type) {
|
|
62
|
+
case "action":
|
|
63
|
+
return {
|
|
64
|
+
...event,
|
|
65
|
+
label: strip(event.label),
|
|
66
|
+
...(event.detail !== undefined ? { detail: strip(event.detail) } : {}),
|
|
67
|
+
...(event.body !== undefined ? { body: event.body.map(strip) } : {}),
|
|
68
|
+
};
|
|
69
|
+
case "action-start":
|
|
70
|
+
return { ...event, label: strip(event.label) };
|
|
71
|
+
case "action-result":
|
|
72
|
+
return { ...event, body: event.body.map(strip) };
|
|
73
|
+
default:
|
|
74
|
+
return event;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export function sessionEvent(session, event) {
|
|
78
|
+
if (!session.running)
|
|
79
|
+
return session;
|
|
80
|
+
switch (event.type) {
|
|
81
|
+
// Streaming fragments accumulate into a trailing streaming unit; the
|
|
82
|
+
// complete text/action event that follows replaces them (authoritative).
|
|
83
|
+
case "text-delta":
|
|
84
|
+
case "thinking-delta": {
|
|
85
|
+
const kind = event.type === "text-delta" ? "text" : "thinking";
|
|
86
|
+
const last = session.units[session.units.length - 1];
|
|
87
|
+
if (last?.kind === kind && last.streaming) {
|
|
88
|
+
return patchUnit(session, session.units.length - 1, {
|
|
89
|
+
body: appendDelta(last.body, event.text),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return append(session, {
|
|
93
|
+
kind,
|
|
94
|
+
label: kind === "thinking" ? "thinking" : "",
|
|
95
|
+
body: event.text.split("\n"),
|
|
96
|
+
streaming: true,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
case "action-start":
|
|
100
|
+
return append(session, {
|
|
101
|
+
kind: "action",
|
|
102
|
+
label: event.label,
|
|
103
|
+
body: [],
|
|
104
|
+
status: "running",
|
|
105
|
+
actionId: event.id,
|
|
106
|
+
streaming: true,
|
|
107
|
+
});
|
|
108
|
+
case "text": {
|
|
109
|
+
const streamed = lastIndexBy(session.units, (u) => u.kind === "text" && u.streaming === true);
|
|
110
|
+
if (streamed >= 0) {
|
|
111
|
+
return patchUnit(session, streamed, {
|
|
112
|
+
body: event.text.split("\n"),
|
|
113
|
+
streaming: false,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return append(session, { kind: "text", label: "", body: event.text.split("\n") });
|
|
117
|
+
}
|
|
118
|
+
case "action": {
|
|
119
|
+
const label = `${event.label}${event.detail ? ` — ${event.detail}` : ""}`;
|
|
120
|
+
if (event.id) {
|
|
121
|
+
const started = lastIndexBy(session.units, (u) => u.actionId === event.id);
|
|
122
|
+
if (started >= 0) {
|
|
123
|
+
return patchUnit(session, started, {
|
|
124
|
+
label,
|
|
125
|
+
body: event.body ?? [],
|
|
126
|
+
streaming: false,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return append(session, {
|
|
131
|
+
kind: "action",
|
|
132
|
+
label,
|
|
133
|
+
body: event.body ?? [],
|
|
134
|
+
// With a correlation id a result will arrive; without one, nothing is pending.
|
|
135
|
+
status: event.id ? "running" : "ok",
|
|
136
|
+
...(event.id ? { actionId: event.id } : {}),
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
case "action-result": {
|
|
140
|
+
const index = lastIndexBy(session.units, (u) => u.actionId === event.id);
|
|
141
|
+
if (index < 0)
|
|
142
|
+
return session;
|
|
143
|
+
const unit = session.units[index];
|
|
144
|
+
return patchUnit(session, index, {
|
|
145
|
+
status: event.ok ? "ok" : "error",
|
|
146
|
+
streaming: false,
|
|
147
|
+
body: event.body.length > 0
|
|
148
|
+
? [...unit.body, ...(unit.body.length > 0 ? [""] : []), "→ result:", ...event.body]
|
|
149
|
+
: unit.body,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
case "error":
|
|
153
|
+
return append({ ...session, running: false, units: settleUnits(session.units) }, { kind: "outcome", label: event.message, body: [], status: "error" });
|
|
154
|
+
case "done":
|
|
155
|
+
return append({ ...session, running: false, units: settleUnits(session.units) }, {
|
|
156
|
+
kind: "outcome",
|
|
157
|
+
label: `turn complete${event.summary ? ` · ${event.summary}` : ""}`,
|
|
158
|
+
body: [],
|
|
159
|
+
status: "ok",
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
export function sessionCancel(session) {
|
|
164
|
+
if (!session.running)
|
|
165
|
+
return session;
|
|
166
|
+
return append({ ...session, running: false, units: settleUnits(session.units) }, { kind: "outcome", label: "turn cancelled", body: [], status: "cancelled" });
|
|
167
|
+
}
|
|
168
|
+
/** Word-wrap one line to a width; hard-breaks anything unbreakable. */
|
|
169
|
+
export function wrapText(line, width) {
|
|
170
|
+
const max = Math.max(8, width);
|
|
171
|
+
if (line.length <= max)
|
|
172
|
+
return [line];
|
|
173
|
+
const out = [];
|
|
174
|
+
let rest = line;
|
|
175
|
+
while (rest.length > max) {
|
|
176
|
+
let cut = rest.lastIndexOf(" ", max);
|
|
177
|
+
if (cut <= 0)
|
|
178
|
+
cut = max;
|
|
179
|
+
out.push(rest.slice(0, cut));
|
|
180
|
+
rest = rest.slice(cut).trimStart();
|
|
181
|
+
}
|
|
182
|
+
out.push(rest);
|
|
183
|
+
return out;
|
|
184
|
+
}
|
|
185
|
+
const BODY_INDENT = " ";
|
|
186
|
+
/** Marker + glyph for an action unit: expandability and live status. */
|
|
187
|
+
function actionPrefix(unit, expanded) {
|
|
188
|
+
const marker = unit.body.length > 0 ? (expanded ? "▾" : "▸") : " ";
|
|
189
|
+
const glyph = unit.status === "running" ? "⚙" : unit.status === "error" ? "✕" : "⚙";
|
|
190
|
+
return `${marker} ${glyph} `;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Flatten the session into renderable rows. `width` is the usable pane
|
|
194
|
+
* width — rows are pre-wrapped so row counts (and scroll targets) are exact.
|
|
195
|
+
* `queued` prompts (typed while a turn runs) render as dim trailing rows;
|
|
196
|
+
* they become real prompt units when their turn starts.
|
|
197
|
+
*/
|
|
198
|
+
export function sessionRows(session, expanded, width, queued = []) {
|
|
199
|
+
const rows = [];
|
|
200
|
+
const bodyWidth = width - BODY_INDENT.length;
|
|
201
|
+
session.units.forEach((unit, index) => {
|
|
202
|
+
const spacerBefore = rows.length > 0 && (unit.kind === "prompt" || unit.kind === "outcome");
|
|
203
|
+
if (spacerBefore) {
|
|
204
|
+
rows.push({ unit: index, isLabel: false, tone: "spacer", text: "" });
|
|
205
|
+
}
|
|
206
|
+
switch (unit.kind) {
|
|
207
|
+
case "prompt": {
|
|
208
|
+
wrapText(`you: ${unit.label}`, width).forEach((text, i) => {
|
|
209
|
+
rows.push({ unit: index, isLabel: i === 0, tone: "prompt", text });
|
|
210
|
+
});
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
case "text": {
|
|
214
|
+
let first = true;
|
|
215
|
+
for (const line of unit.body) {
|
|
216
|
+
for (const text of wrapText(line, width)) {
|
|
217
|
+
rows.push({ unit: index, isLabel: first, tone: "prose", text });
|
|
218
|
+
first = false;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
case "thinking": {
|
|
224
|
+
const isOpen = expanded.has(unit.id);
|
|
225
|
+
const marker = unit.body.length > 0 ? (isOpen ? "▾" : "▸") : " ";
|
|
226
|
+
rows.push({
|
|
227
|
+
unit: index,
|
|
228
|
+
isLabel: true,
|
|
229
|
+
tone: "thinking",
|
|
230
|
+
text: `${marker} ✻ thinking${unit.streaming ? "…" : ""}`,
|
|
231
|
+
});
|
|
232
|
+
if (isOpen) {
|
|
233
|
+
for (const line of unit.body) {
|
|
234
|
+
for (const text of wrapText(line, bodyWidth)) {
|
|
235
|
+
rows.push({
|
|
236
|
+
unit: index,
|
|
237
|
+
isLabel: false,
|
|
238
|
+
tone: "body",
|
|
239
|
+
text: `${BODY_INDENT}${text}`,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
case "action": {
|
|
247
|
+
const isOpen = expanded.has(unit.id);
|
|
248
|
+
const prefix = actionPrefix(unit, isOpen);
|
|
249
|
+
const tone = unit.status === "running"
|
|
250
|
+
? "action-running"
|
|
251
|
+
: unit.status === "error"
|
|
252
|
+
? "action-error"
|
|
253
|
+
: "action";
|
|
254
|
+
wrapText(`${prefix}${unit.label}`, width).forEach((text, i) => {
|
|
255
|
+
rows.push({ unit: index, isLabel: i === 0, tone, text });
|
|
256
|
+
});
|
|
257
|
+
if (isOpen) {
|
|
258
|
+
for (const line of unit.body) {
|
|
259
|
+
for (const text of wrapText(line, bodyWidth)) {
|
|
260
|
+
rows.push({
|
|
261
|
+
unit: index,
|
|
262
|
+
isLabel: false,
|
|
263
|
+
tone: "body",
|
|
264
|
+
text: `${BODY_INDENT}${text}`,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
case "outcome": {
|
|
272
|
+
const tone = unit.status === "error"
|
|
273
|
+
? "outcome-error"
|
|
274
|
+
: unit.status === "cancelled"
|
|
275
|
+
? "outcome-cancelled"
|
|
276
|
+
: "outcome-ok";
|
|
277
|
+
const glyph = unit.status === "error" ? "✕" : unit.status === "cancelled" ? "◼" : "✓";
|
|
278
|
+
wrapText(`${glyph} ${unit.label}`, width).forEach((text, i) => {
|
|
279
|
+
rows.push({ unit: index, isLabel: i === 0, tone, text });
|
|
280
|
+
});
|
|
281
|
+
if (unit.status === "ok") {
|
|
282
|
+
rows.push({
|
|
283
|
+
unit: index,
|
|
284
|
+
isLabel: false,
|
|
285
|
+
tone: "hint",
|
|
286
|
+
text: "→ d review diff · v validate · p push",
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
// Live indicator while the backend works (before any queued follow-ups).
|
|
294
|
+
if (session.running) {
|
|
295
|
+
rows.push({
|
|
296
|
+
unit: Math.max(0, session.units.length - 1),
|
|
297
|
+
isLabel: false,
|
|
298
|
+
tone: "action-running",
|
|
299
|
+
text: "…",
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
// Queued prompts trail the transcript (sent when the running turn ends).
|
|
303
|
+
queued.forEach((text, i) => {
|
|
304
|
+
const virtualUnit = session.units.length + i;
|
|
305
|
+
if (rows.length > 0) {
|
|
306
|
+
rows.push({ unit: virtualUnit, isLabel: false, tone: "spacer", text: "" });
|
|
307
|
+
}
|
|
308
|
+
for (const line of wrapText(`you (queued): ${text}`, width)) {
|
|
309
|
+
rows.push({ unit: virtualUnit, isLabel: false, tone: "queued", text: line });
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
return rows;
|
|
313
|
+
}
|
|
314
|
+
/** First row of a unit — the scroll target when the cursor moves. */
|
|
315
|
+
export function unitRowOffset(rows, unitIndex) {
|
|
316
|
+
const at = rows.findIndex((r) => r.unit === unitIndex && r.isLabel);
|
|
317
|
+
return at < 0 ? 0 : at;
|
|
318
|
+
}
|
|
319
|
+
//# sourceMappingURL=session.js.map
|