@aligndottech/cli 0.34.0 → 0.35.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/README.md +2 -0
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +5 -0
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/decisions/index.d.ts.map +1 -1
- package/dist/commands/decisions/index.js +9 -1
- package/dist/commands/decisions/index.js.map +1 -1
- package/dist/commands/import/sessions.d.ts +16 -0
- package/dist/commands/import/sessions.d.ts.map +1 -0
- package/dist/commands/import/sessions.js +122 -0
- package/dist/commands/import/sessions.js.map +1 -0
- package/dist/commands/import.d.ts.map +1 -1
- package/dist/commands/import.js +2 -0
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/push.d.ts +25 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +98 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/ratify.d.ts +23 -0
- package/dist/commands/ratify.d.ts.map +1 -0
- package/dist/commands/ratify.js +51 -0
- package/dist/commands/ratify.js.map +1 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +5 -2
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/why.d.ts.map +1 -1
- package/dist/commands/why.js +4 -1
- package/dist/commands/why.js.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/answer-render.d.ts +2 -0
- package/dist/lib/answer-render.d.ts.map +1 -0
- package/dist/lib/answer-render.js +24 -0
- package/dist/lib/answer-render.js.map +1 -0
- package/dist/lib/capture-sources.d.ts +4 -0
- package/dist/lib/capture-sources.d.ts.map +1 -1
- package/dist/lib/capture-sources.js +1 -0
- package/dist/lib/capture-sources.js.map +1 -1
- package/dist/lib/decider-kind.d.ts +37 -0
- package/dist/lib/decider-kind.d.ts.map +1 -0
- package/dist/lib/decider-kind.js +41 -0
- package/dist/lib/decider-kind.js.map +1 -0
- package/dist/lib/decisions-context.d.ts +7 -0
- package/dist/lib/decisions-context.d.ts.map +1 -1
- package/dist/lib/decisions-context.js +29 -6
- package/dist/lib/decisions-context.js.map +1 -1
- package/dist/lib/gateway-client.d.ts +32 -0
- package/dist/lib/gateway-client.d.ts.map +1 -1
- package/dist/lib/gateway-client.js +10 -0
- package/dist/lib/gateway-client.js.map +1 -1
- package/dist/lib/git.d.ts +18 -0
- package/dist/lib/git.d.ts.map +1 -1
- package/dist/lib/git.js +31 -0
- package/dist/lib/git.js.map +1 -1
- package/dist/lib/import-defaults.d.ts +1 -0
- package/dist/lib/import-defaults.d.ts.map +1 -1
- package/dist/lib/import-defaults.js +1 -0
- package/dist/lib/import-defaults.js.map +1 -1
- package/dist/lib/local-db.d.ts +56 -1
- package/dist/lib/local-db.d.ts.map +1 -1
- package/dist/lib/local-db.js +104 -7
- package/dist/lib/local-db.js.map +1 -1
- package/dist/lib/local-gateway-client.d.ts +50 -0
- package/dist/lib/local-gateway-client.d.ts.map +1 -1
- package/dist/lib/local-gateway-client.js +90 -4
- package/dist/lib/local-gateway-client.js.map +1 -1
- package/dist/lib/local-llm.d.ts.map +1 -1
- package/dist/lib/local-llm.js +2 -1
- package/dist/lib/local-llm.js.map +1 -1
- package/dist/lib/personal-import.d.ts +26 -0
- package/dist/lib/personal-import.d.ts.map +1 -1
- package/dist/lib/personal-import.js +43 -0
- package/dist/lib/personal-import.js.map +1 -1
- package/dist/lib/sessions/adapters/claude-code.d.ts +4 -0
- package/dist/lib/sessions/adapters/claude-code.d.ts.map +1 -0
- package/dist/lib/sessions/adapters/claude-code.js +93 -0
- package/dist/lib/sessions/adapters/claude-code.js.map +1 -0
- package/dist/lib/sessions/adapters/codex.d.ts +6 -0
- package/dist/lib/sessions/adapters/codex.d.ts.map +1 -0
- package/dist/lib/sessions/adapters/codex.js +91 -0
- package/dist/lib/sessions/adapters/codex.js.map +1 -0
- package/dist/lib/sessions/adapters/cursor.d.ts +17 -0
- package/dist/lib/sessions/adapters/cursor.d.ts.map +1 -0
- package/dist/lib/sessions/adapters/cursor.js +31 -0
- package/dist/lib/sessions/adapters/cursor.js.map +1 -0
- package/dist/lib/sessions/adapters/gemini-cli.d.ts +15 -0
- package/dist/lib/sessions/adapters/gemini-cli.d.ts.map +1 -0
- package/dist/lib/sessions/adapters/gemini-cli.js +29 -0
- package/dist/lib/sessions/adapters/gemini-cli.js.map +1 -0
- package/dist/lib/sessions/adapters/opencode.d.ts +4 -0
- package/dist/lib/sessions/adapters/opencode.d.ts.map +1 -0
- package/dist/lib/sessions/adapters/opencode.js +100 -0
- package/dist/lib/sessions/adapters/opencode.js.map +1 -0
- package/dist/lib/sessions/adapters/pi.d.ts +4 -0
- package/dist/lib/sessions/adapters/pi.d.ts.map +1 -0
- package/dist/lib/sessions/adapters/pi.js +102 -0
- package/dist/lib/sessions/adapters/pi.js.map +1 -0
- package/dist/lib/sessions/extract-structured.d.ts +21 -0
- package/dist/lib/sessions/extract-structured.d.ts.map +1 -0
- package/dist/lib/sessions/extract-structured.js +72 -0
- package/dist/lib/sessions/extract-structured.js.map +1 -0
- package/dist/lib/sessions/fs-scan.d.ts +10 -0
- package/dist/lib/sessions/fs-scan.d.ts.map +1 -0
- package/dist/lib/sessions/fs-scan.js +33 -0
- package/dist/lib/sessions/fs-scan.js.map +1 -0
- package/dist/lib/sessions/registry.d.ts +11 -0
- package/dist/lib/sessions/registry.d.ts.map +1 -0
- package/dist/lib/sessions/registry.js +22 -0
- package/dist/lib/sessions/registry.js.map +1 -0
- package/dist/lib/sessions/source-url.d.ts +10 -0
- package/dist/lib/sessions/source-url.d.ts.map +1 -0
- package/dist/lib/sessions/source-url.js +20 -0
- package/dist/lib/sessions/source-url.js.map +1 -0
- package/dist/lib/sessions/types.d.ts +62 -0
- package/dist/lib/sessions/types.d.ts.map +1 -0
- package/dist/lib/sessions/types.js +19 -0
- package/dist/lib/sessions/types.js.map +1 -0
- package/dist/lib/setup-ux.d.ts.map +1 -1
- package/dist/lib/setup-ux.js +5 -3
- package/dist/lib/setup-ux.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
/** opencode stores every session in one shared SQLite database, so a "session file" here is
|
|
6
|
+
* a composite `<dbPath>#<sessionId>` identifier rather than a real file - the split point
|
|
7
|
+
* every function in this module agrees on. */
|
|
8
|
+
function splitCompositeId(id) {
|
|
9
|
+
const hash = id.indexOf('#');
|
|
10
|
+
if (hash === -1)
|
|
11
|
+
return null;
|
|
12
|
+
return { dbPath: id.slice(0, hash), sessionId: id.slice(hash + 1) };
|
|
13
|
+
}
|
|
14
|
+
export function locateSessionFilesUnder(dbPath, cwd) {
|
|
15
|
+
if (!existsSync(dbPath))
|
|
16
|
+
return [];
|
|
17
|
+
const db = new DatabaseSync(dbPath, { readOnly: true });
|
|
18
|
+
try {
|
|
19
|
+
const rows = db.prepare('SELECT id FROM session WHERE directory = ? ORDER BY time_created DESC').all(cwd);
|
|
20
|
+
return rows.map(r => `${dbPath}#${r.id}`);
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
db.close();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function parsePart(raw) {
|
|
27
|
+
try {
|
|
28
|
+
return JSON.parse(raw);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function parseOpencodeSession(compositeId) {
|
|
35
|
+
const split = splitCompositeId(compositeId);
|
|
36
|
+
if (!split)
|
|
37
|
+
return null;
|
|
38
|
+
const { dbPath, sessionId } = split;
|
|
39
|
+
if (!existsSync(dbPath))
|
|
40
|
+
return null;
|
|
41
|
+
const db = new DatabaseSync(dbPath, { readOnly: true });
|
|
42
|
+
try {
|
|
43
|
+
const sessionRow = db.prepare('SELECT directory FROM session WHERE id = ?').get(sessionId);
|
|
44
|
+
if (!sessionRow)
|
|
45
|
+
return null;
|
|
46
|
+
const messages = db.prepare('SELECT id, data FROM message WHERE session_id = ? ORDER BY time_created').all(sessionId);
|
|
47
|
+
const turns = [];
|
|
48
|
+
for (const msg of messages) {
|
|
49
|
+
let msgData;
|
|
50
|
+
try {
|
|
51
|
+
msgData = JSON.parse(msg.data);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const role = msgData.role;
|
|
57
|
+
if (role !== 'user' && role !== 'assistant')
|
|
58
|
+
continue;
|
|
59
|
+
const parts = db.prepare('SELECT data FROM part WHERE message_id = ? ORDER BY time_created').all(msg.id);
|
|
60
|
+
let text = '';
|
|
61
|
+
const toolCalls = [];
|
|
62
|
+
const toolResults = {};
|
|
63
|
+
for (const partRow of parts) {
|
|
64
|
+
const part = parsePart(partRow.data);
|
|
65
|
+
if (!part)
|
|
66
|
+
continue;
|
|
67
|
+
if (part.type === 'text' && typeof part.text === 'string') {
|
|
68
|
+
text += (text ? '\n' : '') + part.text;
|
|
69
|
+
}
|
|
70
|
+
else if (part.type === 'tool' && typeof part.callID === 'string' && typeof part.tool === 'string') {
|
|
71
|
+
// Unlike the JSONL agents, opencode records a call and its result in ONE row
|
|
72
|
+
// (state.input / state.output) - no separate pending-result step needed.
|
|
73
|
+
toolCalls.push({ id: part.callID, name: part.tool, arguments: part.state?.input });
|
|
74
|
+
const output = part.state?.output;
|
|
75
|
+
if (output !== undefined) {
|
|
76
|
+
toolResults[part.callID] = typeof output === 'string' ? output : JSON.stringify(output);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// step-start / step-finish / reasoning: internal bookkeeping, not a turn's content.
|
|
80
|
+
}
|
|
81
|
+
turns.push({ role, text, toolCalls, toolResults, timestamp: null });
|
|
82
|
+
}
|
|
83
|
+
if (turns.length === 0)
|
|
84
|
+
return null;
|
|
85
|
+
return { agent: 'opencode', sessionId, cwd: sessionRow.directory, turns };
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
db.close();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export const opencodeAdapter = {
|
|
92
|
+
agent: 'opencode',
|
|
93
|
+
fixtureVerified: true,
|
|
94
|
+
locateSessionFiles(cwd) {
|
|
95
|
+
const dbPath = join(homedir(), '.local', 'share', 'opencode', 'opencode.db');
|
|
96
|
+
return locateSessionFilesUnder(dbPath, cwd);
|
|
97
|
+
},
|
|
98
|
+
parseSession: parseOpencodeSession,
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=opencode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../../../src/lib/sessions/adapters/opencode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.d.ts","sourceRoot":"","sources":["../../../../src/lib/sessions/adapters/pi.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAoB,cAAc,EAAgC,MAAM,aAAa,CAAC;AA+BlG,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAGnF;AAuED,eAAO,MAAM,SAAS,EAAE,cAQvB,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { findFilesRecursive, sortByMtimeDesc } from '../fs-scan.js';
|
|
5
|
+
function parseLine(raw) {
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(raw);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** Only pi's first line (`type: "session"`) carries cwd - unlike Claude Code, later lines
|
|
14
|
+
* do not repeat it, so this only needs to look at the first parseable line. */
|
|
15
|
+
function peekCwd(filePath) {
|
|
16
|
+
const firstLine = readFileSync(filePath, 'utf8').split('\n').find(l => l.trim());
|
|
17
|
+
if (!firstLine)
|
|
18
|
+
return null;
|
|
19
|
+
return parseLine(firstLine)?.cwd ?? null;
|
|
20
|
+
}
|
|
21
|
+
export function locateSessionFilesUnder(sessionsRoot, cwd) {
|
|
22
|
+
const files = findFilesRecursive(sessionsRoot, /\.jsonl$/);
|
|
23
|
+
return sortByMtimeDesc(files.filter(f => peekCwd(f) === cwd));
|
|
24
|
+
}
|
|
25
|
+
function extractText(content) {
|
|
26
|
+
let text = '';
|
|
27
|
+
const toolCalls = [];
|
|
28
|
+
if (typeof content === 'string') {
|
|
29
|
+
text = content;
|
|
30
|
+
}
|
|
31
|
+
else if (Array.isArray(content)) {
|
|
32
|
+
for (const block of content) {
|
|
33
|
+
if (!block || typeof block !== 'object')
|
|
34
|
+
continue;
|
|
35
|
+
const b = block;
|
|
36
|
+
if (b['type'] === 'text' && typeof b['text'] === 'string') {
|
|
37
|
+
text += (text ? '\n' : '') + b['text'];
|
|
38
|
+
}
|
|
39
|
+
else if (b['type'] === 'toolCall' && typeof b['id'] === 'string' && typeof b['name'] === 'string') {
|
|
40
|
+
toolCalls.push({ id: b['id'], name: b['name'], arguments: b['arguments'] });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return { text, toolCalls };
|
|
45
|
+
}
|
|
46
|
+
/** pi's toolResult text lives in a `content: [{type:'text', text}]` array on its own
|
|
47
|
+
* message, same shape as a user/assistant message's text blocks. */
|
|
48
|
+
function extractResultText(content) {
|
|
49
|
+
return extractText(content).text;
|
|
50
|
+
}
|
|
51
|
+
function parsePiSession(filePath) {
|
|
52
|
+
const text = readFileSync(filePath, 'utf8');
|
|
53
|
+
const turns = [];
|
|
54
|
+
let sessionId = null;
|
|
55
|
+
let cwd = null;
|
|
56
|
+
// toolResult lines are their own top-level pi message (role: 'toolResult'), not nested
|
|
57
|
+
// inside the next user/assistant turn the way Claude Code embeds a tool_result block -
|
|
58
|
+
// so a pending result is carried forward and merged into whichever real turn comes next.
|
|
59
|
+
let pendingResults = {};
|
|
60
|
+
for (const rawLine of text.split('\n')) {
|
|
61
|
+
if (!rawLine.trim())
|
|
62
|
+
continue;
|
|
63
|
+
const line = parseLine(rawLine);
|
|
64
|
+
if (!line)
|
|
65
|
+
continue;
|
|
66
|
+
if (line.type === 'session') {
|
|
67
|
+
sessionId ??= line.id ?? null;
|
|
68
|
+
cwd ??= line.cwd ?? null;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (line.type !== 'message')
|
|
72
|
+
continue;
|
|
73
|
+
const role = line.message?.role;
|
|
74
|
+
if (role === 'toolResult' && typeof line.message?.toolCallId === 'string') {
|
|
75
|
+
pendingResults[line.message.toolCallId] = extractResultText(line.message.content);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (role !== 'user' && role !== 'assistant')
|
|
79
|
+
continue;
|
|
80
|
+
const { text: turnText, toolCalls } = extractText(line.message?.content);
|
|
81
|
+
turns.push({ role, text: turnText, toolCalls, toolResults: pendingResults, timestamp: line.timestamp ?? null });
|
|
82
|
+
pendingResults = {};
|
|
83
|
+
}
|
|
84
|
+
// A pi transcript ending immediately after a toolResult (nothing to attach it to yet) -
|
|
85
|
+
// fold it onto the last turn rather than dropping it.
|
|
86
|
+
if (Object.keys(pendingResults).length > 0 && turns.length > 0) {
|
|
87
|
+
Object.assign(turns[turns.length - 1].toolResults, pendingResults);
|
|
88
|
+
}
|
|
89
|
+
if (!sessionId || turns.length === 0)
|
|
90
|
+
return null;
|
|
91
|
+
return { agent: 'pi', sessionId, cwd, turns };
|
|
92
|
+
}
|
|
93
|
+
export const piAdapter = {
|
|
94
|
+
agent: 'pi',
|
|
95
|
+
fixtureVerified: true,
|
|
96
|
+
locateSessionFiles(cwd) {
|
|
97
|
+
const root = join(homedir(), '.pi', 'agent', 'sessions');
|
|
98
|
+
return locateSessionFilesUnder(root, cwd);
|
|
99
|
+
},
|
|
100
|
+
parseSession: parsePiSession,
|
|
101
|
+
};
|
|
102
|
+
//# sourceMappingURL=pi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.js","sourceRoot":"","sources":["../../../../src/lib/sessions/adapters/pi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AgentName, CanonicalSession } from './types.js';
|
|
2
|
+
export interface SessionDecisionCandidate {
|
|
3
|
+
agent: AgentName;
|
|
4
|
+
sessionId: string;
|
|
5
|
+
/** The structured tool call's own id - unique within the session, and the value used to
|
|
6
|
+
* build the source_url's messageId segment. */
|
|
7
|
+
messageId: string;
|
|
8
|
+
question: string;
|
|
9
|
+
header: string | null;
|
|
10
|
+
options: Array<{
|
|
11
|
+
label: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
}>;
|
|
14
|
+
/** The answer, verbatim - either a listed option's label or free text (Claude Code's
|
|
15
|
+
* "Other"). Never null here: a candidate with no resolvable answer is not returned at
|
|
16
|
+
* all (see extractAskUserQuestion). */
|
|
17
|
+
chosenLabel: string;
|
|
18
|
+
timestamp: string | null;
|
|
19
|
+
}
|
|
20
|
+
export declare function extractStructuredDecisions(session: CanonicalSession): SessionDecisionCandidate[];
|
|
21
|
+
//# sourceMappingURL=extract-structured.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-structured.d.ts","sourceRoot":"","sources":["../../../src/lib/sessions/extract-structured.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAe,MAAM,YAAY,CAAC;AAE3E,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB;oDACgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD;;4CAEwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAUD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,gBAAgB,GAAG,wBAAwB,EAAE,CAEhG"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const PRODUCERS = {
|
|
2
|
+
'claude-code': extractAskUserQuestion,
|
|
3
|
+
};
|
|
4
|
+
export function extractStructuredDecisions(session) {
|
|
5
|
+
return PRODUCERS[session.agent]?.(session) ?? [];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Claude Code's AskUserQuestion tool_result is free text, not structured JSON - the tool
|
|
9
|
+
* itself renders it that way (`"<question>"="<answer>". <trailing sentence>`). Anchoring on
|
|
10
|
+
* the question's own text (echoed verbatim by the tool) rather than splitting on commas
|
|
11
|
+
* keeps this correct even when an answer itself contains a comma or a quote.
|
|
12
|
+
*/
|
|
13
|
+
function parseAnsweredText(resultText, question) {
|
|
14
|
+
const marker = `"${question}"=`;
|
|
15
|
+
const idx = resultText.indexOf(marker);
|
|
16
|
+
if (idx === -1)
|
|
17
|
+
return null;
|
|
18
|
+
const after = resultText.slice(idx + marker.length);
|
|
19
|
+
if (!after.startsWith('"'))
|
|
20
|
+
return null;
|
|
21
|
+
const body = after.slice(1);
|
|
22
|
+
// The two real trailing phrasings this tool emits, whichever fires depends on whether one
|
|
23
|
+
// question was asked or several. A quote not followed by either is inside the answer.
|
|
24
|
+
const suffixMatch = body.search(/"\.\s*(Read the answers|You can now continue)/);
|
|
25
|
+
if (suffixMatch !== -1)
|
|
26
|
+
return body.slice(0, suffixMatch);
|
|
27
|
+
// Last resort (e.g. this is the final question in a multi-question call, with nothing
|
|
28
|
+
// trailing but the closing quote): take up to the last quote in the string.
|
|
29
|
+
const lastQuote = body.lastIndexOf('"');
|
|
30
|
+
return lastQuote === -1 ? null : body.slice(0, lastQuote);
|
|
31
|
+
}
|
|
32
|
+
function extractAskUserQuestion(session) {
|
|
33
|
+
const candidates = [];
|
|
34
|
+
for (const turn of session.turns) {
|
|
35
|
+
for (const call of turn.toolCalls) {
|
|
36
|
+
if (call.name !== 'AskUserQuestion')
|
|
37
|
+
continue;
|
|
38
|
+
const input = call.arguments;
|
|
39
|
+
const q = input?.questions?.[0];
|
|
40
|
+
if (!q)
|
|
41
|
+
continue;
|
|
42
|
+
const resultText = findToolResult(session.turns, call.id);
|
|
43
|
+
if (resultText === null)
|
|
44
|
+
continue;
|
|
45
|
+
const chosenLabel = parseAnsweredText(resultText, q.question);
|
|
46
|
+
// A rejection ("the tool use was rejected...") or any other unrecognised result shape
|
|
47
|
+
// has no `"<question>"=` marker, so this is also where a decline is filtered out -
|
|
48
|
+
// nothing was decided, so nothing is a candidate.
|
|
49
|
+
if (chosenLabel === null)
|
|
50
|
+
continue;
|
|
51
|
+
candidates.push({
|
|
52
|
+
agent: session.agent,
|
|
53
|
+
sessionId: session.sessionId,
|
|
54
|
+
messageId: call.id,
|
|
55
|
+
question: q.question,
|
|
56
|
+
header: q.header ?? null,
|
|
57
|
+
options: q.options.map(o => ({ label: o.label, ...(o.description !== undefined ? { description: o.description } : {}) })),
|
|
58
|
+
chosenLabel,
|
|
59
|
+
timestamp: turn.timestamp,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return candidates;
|
|
64
|
+
}
|
|
65
|
+
function findToolResult(turns, toolCallId) {
|
|
66
|
+
for (const turn of turns) {
|
|
67
|
+
if (toolCallId in turn.toolResults)
|
|
68
|
+
return turn.toolResults[toolCallId];
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=extract-structured.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-structured.js","sourceRoot":"","sources":["../../../src/lib/sessions/extract-structured.ts"],"names":[],"mappings":"AAsBA,MAAM,SAAS,GAAyC;IACtD,aAAa,EAAE,sBAAsB;CACtC,CAAC;AAEF,MAAM,UAAU,0BAA0B,CAAC,OAAyB;IAClE,OAAO,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;AACnD,CAAC;AAUD;;;;;GAKG;AACH,SAAS,iBAAiB,CAAC,UAAkB,EAAE,QAAgB;IAC7D,MAAM,MAAM,GAAG,IAAI,QAAQ,IAAI,CAAC;IAChC,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5B,0FAA0F;IAC1F,sFAAsF;IACtF,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,+CAA+C,CAAC,CAAC;IACjF,IAAI,WAAW,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IAC1D,sFAAsF;IACtF,4EAA4E;IAC5E,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACxC,OAAO,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAyB;IACvD,MAAM,UAAU,GAA+B,EAAE,CAAC;IAClD,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACjC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAClC,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB;gBAAE,SAAS;YAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,SAA6C,CAAC;YACjE,MAAM,CAAC,GAAG,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;YAChC,IAAI,CAAC,CAAC;gBAAE,SAAS;YACjB,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;YAC1D,IAAI,UAAU,KAAK,IAAI;gBAAE,SAAS;YAClC,MAAM,WAAW,GAAG,iBAAiB,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC9D,sFAAsF;YACtF,mFAAmF;YACnF,kDAAkD;YAClD,IAAI,WAAW,KAAK,IAAI;gBAAE,SAAS;YACnC,UAAU,CAAC,IAAI,CAAC;gBACd,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,SAAS,EAAE,IAAI,CAAC,EAAE;gBAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,IAAI;gBACxB,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACzH,WAAW;gBACX,SAAS,EAAE,IAAI,CAAC,SAAS;aAC1B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,cAAc,CAAC,KAAoB,EAAE,UAAkB;IAC9D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,UAAU,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every file under `root` (recursively) whose full path matches `pattern`. A missing or
|
|
3
|
+
* unreadable root is "this agent has never run here" - the normal case, not an error - so
|
|
4
|
+
* it returns [] rather than throwing. Every adapter's locateSessionFiles builds on this.
|
|
5
|
+
*/
|
|
6
|
+
export declare function findFilesRecursive(root: string, pattern: RegExp): string[];
|
|
7
|
+
/** Newest-first by mtime - agent-agnostic, so it works whether or not a format's own
|
|
8
|
+
* embedded timestamp was parseable. */
|
|
9
|
+
export declare function sortByMtimeDesc(files: string[]): string[];
|
|
10
|
+
//# sourceMappingURL=fs-scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-scan.d.ts","sourceRoot":"","sources":["../../../src/lib/sessions/fs-scan.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAiB1E;AAED;wCACwC;AACxC,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAEzD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readdirSync, statSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Every file under `root` (recursively) whose full path matches `pattern`. A missing or
|
|
5
|
+
* unreadable root is "this agent has never run here" - the normal case, not an error - so
|
|
6
|
+
* it returns [] rather than throwing. Every adapter's locateSessionFiles builds on this.
|
|
7
|
+
*/
|
|
8
|
+
export function findFilesRecursive(root, pattern) {
|
|
9
|
+
let entries;
|
|
10
|
+
try {
|
|
11
|
+
entries = readdirSync(root, { withFileTypes: true });
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
const found = [];
|
|
17
|
+
for (const entry of entries) {
|
|
18
|
+
const full = join(root, entry.name);
|
|
19
|
+
if (entry.isDirectory()) {
|
|
20
|
+
found.push(...findFilesRecursive(full, pattern));
|
|
21
|
+
}
|
|
22
|
+
else if (pattern.test(full)) {
|
|
23
|
+
found.push(full);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return found;
|
|
27
|
+
}
|
|
28
|
+
/** Newest-first by mtime - agent-agnostic, so it works whether or not a format's own
|
|
29
|
+
* embedded timestamp was parseable. */
|
|
30
|
+
export function sortByMtimeDesc(files) {
|
|
31
|
+
return [...files].sort((a, b) => statSync(b).mtimeMs - statSync(a).mtimeMs);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=fs-scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-scan.js","sourceRoot":"","sources":["../../../src/lib/sessions/fs-scan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,OAAe;IAC9D,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QACnD,CAAC;aAAM,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;wCACwC;AACxC,MAAM,UAAU,eAAe,CAAC,KAAe;IAC7C,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAC9E,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SessionAdapter } from './types.js';
|
|
2
|
+
export declare const ADAPTERS: SessionAdapter[];
|
|
3
|
+
export interface DetectedAgent {
|
|
4
|
+
adapter: SessionAdapter;
|
|
5
|
+
files: string[];
|
|
6
|
+
}
|
|
7
|
+
/** `align import sessions`' auto-detect: every agent that has actually left session data
|
|
8
|
+
* for this project. An agent with zero files is "never run here" - the normal case for
|
|
9
|
+
* five of six adapters on any one machine - so it is silently excluded, not reported. */
|
|
10
|
+
export declare function detectAgents(cwd: string, adapters?: SessionAdapter[]): DetectedAgent[];
|
|
11
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/lib/sessions/registry.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,eAAO,MAAM,QAAQ,EAAE,cAAc,EAEpC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;0FAE0F;AAC1F,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAc,EAAa,GAAG,aAAa,EAAE,CAOhG"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { claudeCodeAdapter } from './adapters/claude-code.js';
|
|
2
|
+
import { codexAdapter } from './adapters/codex.js';
|
|
3
|
+
import { cursorAdapter } from './adapters/cursor.js';
|
|
4
|
+
import { geminiCliAdapter } from './adapters/gemini-cli.js';
|
|
5
|
+
import { opencodeAdapter } from './adapters/opencode.js';
|
|
6
|
+
import { piAdapter } from './adapters/pi.js';
|
|
7
|
+
export const ADAPTERS = [
|
|
8
|
+
claudeCodeAdapter, codexAdapter, cursorAdapter, geminiCliAdapter, opencodeAdapter, piAdapter,
|
|
9
|
+
];
|
|
10
|
+
/** `align import sessions`' auto-detect: every agent that has actually left session data
|
|
11
|
+
* for this project. An agent with zero files is "never run here" - the normal case for
|
|
12
|
+
* five of six adapters on any one machine - so it is silently excluded, not reported. */
|
|
13
|
+
export function detectAgents(cwd, adapters = ADAPTERS) {
|
|
14
|
+
const found = [];
|
|
15
|
+
for (const adapter of adapters) {
|
|
16
|
+
const files = adapter.locateSessionFiles(cwd);
|
|
17
|
+
if (files.length > 0)
|
|
18
|
+
found.push({ adapter, files });
|
|
19
|
+
}
|
|
20
|
+
return found;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/lib/sessions/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG7C,MAAM,CAAC,MAAM,QAAQ,GAAqB;IACxC,iBAAiB,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,SAAS;CAC7F,CAAC;AAOF;;0FAE0F;AAC1F,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,WAA6B,QAAQ;IAC7E,MAAM,KAAK,GAAoB,EAAE,CAAC;IAClC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AgentName } from './types.js';
|
|
2
|
+
/** ALI-808 shared contract: the agent name lives in the scheme, `platform` stays the single
|
|
3
|
+
* value `agent-session` everywhere else. */
|
|
4
|
+
export declare function buildSessionSourceUrl(agent: AgentName, sessionId: string, messageId: string): string;
|
|
5
|
+
export declare function parseSessionSourceUrl(url: string): {
|
|
6
|
+
agent: AgentName;
|
|
7
|
+
sessionId: string;
|
|
8
|
+
messageId: string;
|
|
9
|
+
} | null;
|
|
10
|
+
//# sourceMappingURL=source-url.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-url.d.ts","sourceRoot":"","sources":["../../../src/lib/sessions/source-url.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAI5C;6CAC6C;AAC7C,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpG;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAWpH"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const AGENTS = ['claude-code', 'codex', 'cursor', 'gemini-cli', 'opencode', 'pi'];
|
|
2
|
+
/** ALI-808 shared contract: the agent name lives in the scheme, `platform` stays the single
|
|
3
|
+
* value `agent-session` everywhere else. */
|
|
4
|
+
export function buildSessionSourceUrl(agent, sessionId, messageId) {
|
|
5
|
+
return `${agent}-session://${sessionId}/${messageId}`;
|
|
6
|
+
}
|
|
7
|
+
export function parseSessionSourceUrl(url) {
|
|
8
|
+
for (const agent of AGENTS) {
|
|
9
|
+
const prefix = `${agent}-session://`;
|
|
10
|
+
if (url.startsWith(prefix)) {
|
|
11
|
+
const rest = url.slice(prefix.length);
|
|
12
|
+
const slash = rest.indexOf('/');
|
|
13
|
+
if (slash === -1)
|
|
14
|
+
return null;
|
|
15
|
+
return { agent, sessionId: rest.slice(0, slash), messageId: rest.slice(slash + 1) };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=source-url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-url.js","sourceRoot":"","sources":["../../../src/lib/sessions/source-url.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAAyB,CAAC,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;AAExG;6CAC6C;AAC7C,MAAM,UAAU,qBAAqB,CAAC,KAAgB,EAAE,SAAiB,EAAE,SAAiB;IAC1F,OAAO,GAAG,KAAK,cAAc,SAAS,IAAI,SAAS,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,GAAG,KAAK,aAAa,CAAC;QACrC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACtC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAChC,IAAI,KAAK,KAAK,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC9B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;QACtF,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ALI-808: the canonical shape every per-agent adapter parses into, so extraction (Pass A,
|
|
3
|
+
* and eventually ALI-809's Pass B) never learns which agent it is reading - the same
|
|
4
|
+
* `normalizeHookPayload` pattern used for the destructive-command guard (ALI-357/#1953) and
|
|
5
|
+
* the pre-edit conflict check (align-cli#86), both cited in the ALI-608 addendum.
|
|
6
|
+
*/
|
|
7
|
+
/** The six agents named in the ALI-808 shared contract. Not every adapter parses content yet
|
|
8
|
+
* (see `fixtureVerified` on SessionAdapter) - the name is reserved even where the reader
|
|
9
|
+
* is not, because it is also the scheme host in a session's source_url. */
|
|
10
|
+
export type AgentName = 'claude-code' | 'codex' | 'cursor' | 'gemini-cli' | 'opencode' | 'pi';
|
|
11
|
+
export interface SessionToolCall {
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
arguments: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface SessionTurn {
|
|
17
|
+
role: 'user' | 'assistant';
|
|
18
|
+
/** The turn's own text, own words - never a tool result or a system reminder. Empty
|
|
19
|
+
* string, not absent, when a turn is tool-calls-only (keeps every consumer's access
|
|
20
|
+
* uniform rather than optional-chaining everywhere). */
|
|
21
|
+
text: string;
|
|
22
|
+
toolCalls: SessionToolCall[];
|
|
23
|
+
/** Keyed by SessionToolCall.id, when the transcript records a result for it. A missing
|
|
24
|
+
* key means "no result recorded", not "empty result" - the two are different facts
|
|
25
|
+
* (a cancelled tool call vs. one that returned nothing). */
|
|
26
|
+
toolResults: Record<string, string>;
|
|
27
|
+
/** ISO-8601, or null when the source did not carry one for this turn. */
|
|
28
|
+
timestamp: string | null;
|
|
29
|
+
}
|
|
30
|
+
export interface CanonicalSession {
|
|
31
|
+
agent: AgentName;
|
|
32
|
+
sessionId: string;
|
|
33
|
+
/** The working directory the agent was running in, when the source records one. */
|
|
34
|
+
cwd: string | null;
|
|
35
|
+
turns: SessionTurn[];
|
|
36
|
+
}
|
|
37
|
+
export interface SessionAdapter {
|
|
38
|
+
agent: AgentName;
|
|
39
|
+
/** True only when a real captured session backs this adapter's fixture (the ALI-808
|
|
40
|
+
* shared-contract gate: "the gate is the fixture, not the agent name"). False means
|
|
41
|
+
* `parseSession` is intentionally unimplemented - see fixtures/sessions/README.md for
|
|
42
|
+
* which agents and why. */
|
|
43
|
+
fixtureVerified: boolean;
|
|
44
|
+
/** Session files for the given project directory, newest first. Never throws on a
|
|
45
|
+
* missing/unreadable agent data directory - that is "this agent has no local data
|
|
46
|
+
* here", not an error, and every caller (detectAgents, the import command) treats an
|
|
47
|
+
* empty array as the normal "not installed / never used here" case. */
|
|
48
|
+
locateSessionFiles(cwd: string): string[];
|
|
49
|
+
/** Parses one session file. Returns null for a file that does not belong to this agent's
|
|
50
|
+
* format (defensive - locateSessionFiles should not hand it one, but a caller passing an
|
|
51
|
+
* arbitrary path must get an honest null rather than a throw). Throws
|
|
52
|
+
* SessionFormatUnverifiedError for an adapter with fixtureVerified === false. */
|
|
53
|
+
parseSession(filePath: string): CanonicalSession | null;
|
|
54
|
+
}
|
|
55
|
+
/** Thrown by an unverified adapter's parseSession, instead of guessing at a format nobody
|
|
56
|
+
* has confirmed against a real session (verification.md: a plausible construction is not
|
|
57
|
+
* data). Naming the fixtures README in the message is deliberate - it is the one place
|
|
58
|
+
* that explains why and what unblocks it. */
|
|
59
|
+
export declare class SessionFormatUnverifiedError extends Error {
|
|
60
|
+
constructor(agent: AgentName);
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/sessions/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;4EAE4E;AAC5E,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,YAAY,GAAG,UAAU,GAAG,IAAI,CAAC;AAE9F,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B;;6DAEyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B;;iEAE6D;IAC7D,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,yEAAyE;IACzE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB;;;gCAG4B;IAC5B,eAAe,EAAE,OAAO,CAAC;IACzB;;;4EAGwE;IACxE,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1C;;;sFAGkF;IAClF,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;CACzD;AAED;;;8CAG8C;AAC9C,qBAAa,4BAA6B,SAAQ,KAAK;gBACzC,KAAK,EAAE,SAAS;CAQ7B"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ALI-808: the canonical shape every per-agent adapter parses into, so extraction (Pass A,
|
|
3
|
+
* and eventually ALI-809's Pass B) never learns which agent it is reading - the same
|
|
4
|
+
* `normalizeHookPayload` pattern used for the destructive-command guard (ALI-357/#1953) and
|
|
5
|
+
* the pre-edit conflict check (align-cli#86), both cited in the ALI-608 addendum.
|
|
6
|
+
*/
|
|
7
|
+
/** Thrown by an unverified adapter's parseSession, instead of guessing at a format nobody
|
|
8
|
+
* has confirmed against a real session (verification.md: a plausible construction is not
|
|
9
|
+
* data). Naming the fixtures README in the message is deliberate - it is the one place
|
|
10
|
+
* that explains why and what unblocks it. */
|
|
11
|
+
export class SessionFormatUnverifiedError extends Error {
|
|
12
|
+
constructor(agent) {
|
|
13
|
+
super(`${agent}'s session format is not fixture-verified yet (no real captured session was ` +
|
|
14
|
+
`available - see src/__tests__/fixtures/sessions/README.md). Capture a real session and ` +
|
|
15
|
+
`add it as a fixture before parsing this agent's data.`);
|
|
16
|
+
this.name = 'SessionFormatUnverifiedError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/sessions/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuDH;;;8CAG8C;AAC9C,MAAM,OAAO,4BAA6B,SAAQ,KAAK;IACrD,YAAY,KAAgB;QAC1B,KAAK,CACH,GAAG,KAAK,8EAA8E;YACtF,yFAAyF;YACzF,uDAAuD,CACxD,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,8BAA8B,CAAC;IAC7C,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup-ux.d.ts","sourceRoot":"","sources":["../../src/lib/setup-ux.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAA6B,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"setup-ux.d.ts","sourceRoot":"","sources":["../../src/lib/setup-ux.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAA6B,MAAM,uBAAuB,CAAC;AAyBrF;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAIpF;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWxF;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CACpC,MAAM,EACN;IACE,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CAClD,CAQF,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,GAAE,OAAO,OAAO,CAAC,MAAuB,GAAG,IAAI,CAIzF;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,GACzC,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAczD;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAKtG"}
|
package/dist/lib/setup-ux.js
CHANGED
|
@@ -9,9 +9,11 @@ import * as readline from 'node:readline';
|
|
|
9
9
|
* directly, which the flow around them is not.
|
|
10
10
|
*/
|
|
11
11
|
// Lines the prompt needs beyond the option rows themselves: the message, clack's
|
|
12
|
-
// top and bottom rules, the
|
|
13
|
-
//
|
|
14
|
-
|
|
12
|
+
// top and bottom rules, the key hint, and one spare. This was 8 while the picker was
|
|
13
|
+
// drawn under a screenful of git output; the screen has been cleared before the
|
|
14
|
+
// picker since ALI-794, so the extra slack only hid rows. Measured 2026-09-03: a
|
|
15
|
+
// 12-row panel showed 4 of 8 sources and read as truncated. Now it shows 7.
|
|
16
|
+
const RESERVED_ROWS = 5;
|
|
15
17
|
// Below this a paginated list is unusable, so we overflow slightly rather than
|
|
16
18
|
// render one option at a time. clack scrolls within maxItems, so a floor is safe.
|
|
17
19
|
const MIN_VISIBLE = 3;
|
package/dist/lib/setup-ux.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup-ux.js","sourceRoot":"","sources":["../../src/lib/setup-ux.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAqB,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C;;;;;;GAMG;AAEH,iFAAiF;AACjF,4EAA4E;AAC5E,
|
|
1
|
+
{"version":3,"file":"setup-ux.js","sourceRoot":"","sources":["../../src/lib/setup-ux.ts"],"names":[],"mappings":"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"}
|