@halyard/cli 0.1.2 → 0.2.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 +88 -1
- package/dist/cli.js +27 -4
- package/dist/cli.js.map +1 -1
- package/dist/commands/api-keys.d.ts +3 -0
- package/dist/commands/api-keys.d.ts.map +1 -0
- package/dist/commands/api-keys.js +90 -0
- package/dist/commands/api-keys.js.map +1 -0
- package/dist/commands/hook.d.ts +6 -0
- package/dist/commands/hook.d.ts.map +1 -0
- package/dist/commands/hook.js +106 -0
- package/dist/commands/hook.js.map +1 -0
- package/dist/commands/login.d.ts +17 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +111 -14
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/orgs.d.ts +3 -0
- package/dist/commands/orgs.d.ts.map +1 -0
- package/dist/commands/orgs.js +102 -0
- package/dist/commands/orgs.js.map +1 -0
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +29 -6
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/sessions.d.ts +3 -0
- package/dist/commands/sessions.d.ts.map +1 -0
- package/dist/commands/sessions.js +139 -0
- package/dist/commands/sessions.js.map +1 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +28 -3
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/skills.d.ts +12 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/skills.js +171 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +51 -49
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/users.d.ts +13 -0
- package/dist/commands/users.d.ts.map +1 -0
- package/dist/commands/users.js +205 -0
- package/dist/commands/users.js.map +1 -0
- package/dist/commands/whoami.d.ts +21 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +77 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/lib/api-client.d.ts +64 -2
- package/dist/lib/api-client.d.ts.map +1 -1
- package/dist/lib/api-client.js +32 -7
- package/dist/lib/api-client.js.map +1 -1
- package/dist/lib/auth.d.ts +42 -6
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +101 -27
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/config-files.d.ts +6 -0
- package/dist/lib/config-files.d.ts.map +1 -0
- package/dist/lib/config-files.js +27 -0
- package/dist/lib/config-files.js.map +1 -0
- package/dist/lib/config.d.ts +13 -7
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +22 -8
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/copilot-export.d.ts +31 -0
- package/dist/lib/copilot-export.d.ts.map +1 -0
- package/dist/lib/copilot-export.js +129 -0
- package/dist/lib/copilot-export.js.map +1 -0
- package/dist/lib/discovery.d.ts +60 -2
- package/dist/lib/discovery.d.ts.map +1 -1
- package/dist/lib/discovery.js +187 -15
- package/dist/lib/discovery.js.map +1 -1
- package/dist/lib/hook-discovery.d.ts +43 -0
- package/dist/lib/hook-discovery.d.ts.map +1 -0
- package/dist/lib/hook-discovery.js +90 -0
- package/dist/lib/hook-discovery.js.map +1 -0
- package/dist/lib/hook-input.d.ts +36 -0
- package/dist/lib/hook-input.d.ts.map +1 -0
- package/dist/lib/hook-input.js +161 -0
- package/dist/lib/hook-input.js.map +1 -0
- package/dist/lib/hook-runner.d.ts +48 -0
- package/dist/lib/hook-runner.d.ts.map +1 -0
- package/dist/lib/hook-runner.js +306 -0
- package/dist/lib/hook-runner.js.map +1 -0
- package/dist/lib/http.d.ts +18 -0
- package/dist/lib/http.d.ts.map +1 -0
- package/dist/lib/http.js +54 -0
- package/dist/lib/http.js.map +1 -0
- package/dist/lib/opencode-export.d.ts +22 -0
- package/dist/lib/opencode-export.d.ts.map +1 -0
- package/dist/lib/opencode-export.js +53 -0
- package/dist/lib/opencode-export.js.map +1 -0
- package/dist/lib/output.d.ts +27 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +74 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/preflight.d.ts +35 -0
- package/dist/lib/preflight.d.ts.map +1 -0
- package/dist/lib/preflight.js +54 -0
- package/dist/lib/preflight.js.map +1 -0
- package/dist/lib/repo-binding.d.ts +43 -0
- package/dist/lib/repo-binding.d.ts.map +1 -0
- package/dist/lib/repo-binding.js +158 -0
- package/dist/lib/repo-binding.js.map +1 -0
- package/dist/lib/repo-identity.d.ts +29 -0
- package/dist/lib/repo-identity.d.ts.map +1 -0
- package/dist/lib/repo-identity.js +113 -0
- package/dist/lib/repo-identity.js.map +1 -0
- package/dist/lib/setup-hooks.d.ts +41 -0
- package/dist/lib/setup-hooks.d.ts.map +1 -0
- package/dist/lib/setup-hooks.js +276 -0
- package/dist/lib/setup-hooks.js.map +1 -0
- package/dist/lib/setup.d.ts +4 -1
- package/dist/lib/setup.d.ts.map +1 -1
- package/dist/lib/setup.js +20 -31
- package/dist/lib/setup.js.map +1 -1
- package/dist/lib/skill-batches.d.ts +16 -0
- package/dist/lib/skill-batches.d.ts.map +1 -0
- package/dist/lib/skill-batches.js +35 -0
- package/dist/lib/skill-batches.js.map +1 -0
- package/dist/lib/skill-files.d.ts +4 -0
- package/dist/lib/skill-files.d.ts.map +1 -0
- package/dist/lib/skill-files.js +36 -0
- package/dist/lib/skill-files.js.map +1 -0
- package/dist/lib/skill-fingerprint.d.ts +55 -0
- package/dist/lib/skill-fingerprint.d.ts.map +1 -0
- package/dist/lib/skill-fingerprint.js +204 -0
- package/dist/lib/skill-fingerprint.js.map +1 -0
- package/dist/lib/skills-discovery.d.ts +57 -0
- package/dist/lib/skills-discovery.d.ts.map +1 -0
- package/dist/lib/skills-discovery.js +157 -0
- package/dist/lib/skills-discovery.js.map +1 -0
- package/dist/lib/skills-sync.d.ts +66 -0
- package/dist/lib/skills-sync.d.ts.map +1 -0
- package/dist/lib/skills-sync.js +251 -0
- package/dist/lib/skills-sync.js.map +1 -0
- package/dist/lib/sync-runner.d.ts +56 -0
- package/dist/lib/sync-runner.d.ts.map +1 -0
- package/dist/lib/sync-runner.js +106 -0
- package/dist/lib/sync-runner.js.map +1 -0
- package/dist/lib/sync-state.d.ts +36 -6
- package/dist/lib/sync-state.d.ts.map +1 -1
- package/dist/lib/sync-state.js +41 -11
- package/dist/lib/sync-state.js.map +1 -1
- package/package.json +10 -5
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Copilot CLI integration.
|
|
3
|
+
*
|
|
4
|
+
* Copilot CLI (verified against v1.0.82) keeps all sessions in one shared
|
|
5
|
+
* SQLite store, `~/.copilot/session-store.db`:
|
|
6
|
+
*
|
|
7
|
+
* - `sessions` (id, cwd, repository, branch, created_at, updated_at)
|
|
8
|
+
* - `turns` (session_id, turn_index, user_message, assistant_response, timestamp)
|
|
9
|
+
* - `assistant_usage_events` (session_id, model, input_tokens, output_tokens,
|
|
10
|
+
* cache_read_tokens, cache_write_tokens, reasoning_tokens, ...)
|
|
11
|
+
* - `forge_trajectory_events` (session_id, event_type, command, exit_code, ...)
|
|
12
|
+
*
|
|
13
|
+
* Since there is no per-session file to upload, each session is exported as
|
|
14
|
+
* a versioned JSONL bundle the server-side parser understands
|
|
15
|
+
* (`packages/queue/src/lib/session-parsers/copilot.ts`): one
|
|
16
|
+
* `halyard_copilot_session` meta line, then `turn` / `usage` / `trajectory`
|
|
17
|
+
* records.
|
|
18
|
+
*
|
|
19
|
+
* The store is read via the built-in `node:sqlite` module (Node ≥ 22.13,
|
|
20
|
+
* read-only — no native dependency). On older Nodes, or when anything about
|
|
21
|
+
* the store is unreadable, discovery degrades to "no sessions" rather than
|
|
22
|
+
* breaking `halyard sync` for other providers.
|
|
23
|
+
*/
|
|
24
|
+
export declare const COPILOT_BUNDLE_VERSION = 1;
|
|
25
|
+
export interface CopilotSessionRef {
|
|
26
|
+
id: string;
|
|
27
|
+
updatedAt: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function listCopilotSessions(): CopilotSessionRef[];
|
|
30
|
+
export declare function buildCopilotBundle(sessionId: string): Buffer;
|
|
31
|
+
//# sourceMappingURL=copilot-export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilot-export.d.ts","sourceRoot":"","sources":["../../src/lib/copilot-export.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,eAAO,MAAM,sBAAsB,IAAI,CAAA;AAEvC,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;CAClB;AA2BD,wBAAgB,mBAAmB,IAAI,iBAAiB,EAAE,CAqBzD;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAmD5D"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
4
|
+
/**
|
|
5
|
+
* GitHub Copilot CLI integration.
|
|
6
|
+
*
|
|
7
|
+
* Copilot CLI (verified against v1.0.82) keeps all sessions in one shared
|
|
8
|
+
* SQLite store, `~/.copilot/session-store.db`:
|
|
9
|
+
*
|
|
10
|
+
* - `sessions` (id, cwd, repository, branch, created_at, updated_at)
|
|
11
|
+
* - `turns` (session_id, turn_index, user_message, assistant_response, timestamp)
|
|
12
|
+
* - `assistant_usage_events` (session_id, model, input_tokens, output_tokens,
|
|
13
|
+
* cache_read_tokens, cache_write_tokens, reasoning_tokens, ...)
|
|
14
|
+
* - `forge_trajectory_events` (session_id, event_type, command, exit_code, ...)
|
|
15
|
+
*
|
|
16
|
+
* Since there is no per-session file to upload, each session is exported as
|
|
17
|
+
* a versioned JSONL bundle the server-side parser understands
|
|
18
|
+
* (`packages/queue/src/lib/session-parsers/copilot.ts`): one
|
|
19
|
+
* `halyard_copilot_session` meta line, then `turn` / `usage` / `trajectory`
|
|
20
|
+
* records.
|
|
21
|
+
*
|
|
22
|
+
* The store is read via the built-in `node:sqlite` module (Node ≥ 22.13,
|
|
23
|
+
* read-only — no native dependency). On older Nodes, or when anything about
|
|
24
|
+
* the store is unreadable, discovery degrades to "no sessions" rather than
|
|
25
|
+
* breaking `halyard sync` for other providers.
|
|
26
|
+
*/
|
|
27
|
+
export const COPILOT_BUNDLE_VERSION = 1;
|
|
28
|
+
function copilotDir() {
|
|
29
|
+
return process.env.COPILOT_DIR ?? join(homedir(), '.copilot');
|
|
30
|
+
}
|
|
31
|
+
function openStore() {
|
|
32
|
+
const dbPath = join(copilotDir(), 'session-store.db');
|
|
33
|
+
if (!existsSync(dbPath))
|
|
34
|
+
return null;
|
|
35
|
+
try {
|
|
36
|
+
// node:sqlite is unflagged from Node 22.13; getBuiltinModule avoids a
|
|
37
|
+
// hard import so older runtimes degrade gracefully.
|
|
38
|
+
const sqlite = process.getBuiltinModule?.('node:sqlite');
|
|
39
|
+
if (!sqlite?.DatabaseSync)
|
|
40
|
+
return null;
|
|
41
|
+
return new sqlite.DatabaseSync(dbPath, { readOnly: true });
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export function listCopilotSessions() {
|
|
48
|
+
const db = openStore();
|
|
49
|
+
if (!db)
|
|
50
|
+
return [];
|
|
51
|
+
try {
|
|
52
|
+
// Only sessions with actual conversation or usage activity — Copilot
|
|
53
|
+
// creates empty session rows for launches that never reach a turn.
|
|
54
|
+
const rows = db
|
|
55
|
+
.prepare(`SELECT s.id AS id, s.updated_at AS updated_at FROM sessions s
|
|
56
|
+
WHERE EXISTS (SELECT 1 FROM turns t WHERE t.session_id = s.id)
|
|
57
|
+
OR EXISTS (SELECT 1 FROM assistant_usage_events u WHERE u.session_id = s.id)`)
|
|
58
|
+
.all();
|
|
59
|
+
return rows
|
|
60
|
+
.filter((r) => typeof r.id === 'string')
|
|
61
|
+
.map((r) => ({ id: r.id, updatedAt: String(r.updated_at ?? '') }));
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
db.close();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function buildCopilotBundle(sessionId) {
|
|
71
|
+
const db = openStore();
|
|
72
|
+
if (!db) {
|
|
73
|
+
throw new Error('Copilot session store is not readable (requires Node >= 22.13)');
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const session = db.prepare('SELECT * FROM sessions WHERE id = ?').all(sessionId)[0];
|
|
77
|
+
if (!session)
|
|
78
|
+
throw new Error(`Copilot session not found: ${sessionId}`);
|
|
79
|
+
const lines = [
|
|
80
|
+
JSON.stringify({
|
|
81
|
+
type: 'halyard_copilot_session',
|
|
82
|
+
bundleVersion: COPILOT_BUNDLE_VERSION,
|
|
83
|
+
session,
|
|
84
|
+
workspace: readWorkspaceYaml(sessionId),
|
|
85
|
+
}),
|
|
86
|
+
];
|
|
87
|
+
const push = (type, rows) => {
|
|
88
|
+
for (const row of rows)
|
|
89
|
+
lines.push(JSON.stringify({ type, ...row }));
|
|
90
|
+
};
|
|
91
|
+
push('turn', db
|
|
92
|
+
.prepare('SELECT turn_index, user_message, assistant_response, timestamp FROM turns WHERE session_id = ? ORDER BY turn_index')
|
|
93
|
+
.all(sessionId));
|
|
94
|
+
push('usage', db
|
|
95
|
+
.prepare(`SELECT turn_index, model, input_tokens, output_tokens, cache_read_tokens,
|
|
96
|
+
cache_write_tokens, reasoning_tokens, duration_ms, created_at
|
|
97
|
+
FROM assistant_usage_events WHERE session_id = ? ORDER BY id`)
|
|
98
|
+
.all(sessionId));
|
|
99
|
+
push('trajectory', db
|
|
100
|
+
.prepare(`SELECT tool_call_id, turn_index, event_type, command, exit_code, created_at
|
|
101
|
+
FROM forge_trajectory_events WHERE session_id = ? ORDER BY id`)
|
|
102
|
+
.all(sessionId));
|
|
103
|
+
return Buffer.from(`${lines.join('\n')}\n`);
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
db.close();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Best-effort read of the per-session workspace.yaml (flat `key: value`
|
|
111
|
+
* lines only — no YAML dependency needed for this shape).
|
|
112
|
+
*/
|
|
113
|
+
function readWorkspaceYaml(sessionId) {
|
|
114
|
+
const path = join(copilotDir(), 'session-state', sessionId, 'workspace.yaml');
|
|
115
|
+
try {
|
|
116
|
+
const parsed = {};
|
|
117
|
+
for (const line of readFileSync(path, 'utf-8').split('\n')) {
|
|
118
|
+
const idx = line.indexOf(': ');
|
|
119
|
+
if (idx <= 0)
|
|
120
|
+
continue;
|
|
121
|
+
parsed[line.slice(0, idx).trim()] = line.slice(idx + 2).trim();
|
|
122
|
+
}
|
|
123
|
+
return parsed;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=copilot-export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilot-export.js","sourceRoot":"","sources":["../../src/lib/copilot-export.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/discovery.d.ts
CHANGED
|
@@ -1,12 +1,32 @@
|
|
|
1
|
+
export type SessionProvider = 'claude' | 'codex' | 'gemini' | 'opencode' | 'copilot';
|
|
2
|
+
export declare const SESSION_PROVIDERS: SessionProvider[];
|
|
1
3
|
export interface DiscoveredSession {
|
|
2
|
-
provider:
|
|
4
|
+
provider: SessionProvider;
|
|
5
|
+
/**
|
|
6
|
+
* Stable sync-state key. A real file path for file-backed providers
|
|
7
|
+
* (claude/codex/gemini); a `provider://sessionId` pseudo-path for
|
|
8
|
+
* store-backed providers (opencode/copilot) whose sessions live in a
|
|
9
|
+
* shared database rather than one file.
|
|
10
|
+
*/
|
|
3
11
|
filePath: string;
|
|
4
12
|
sessionId: string;
|
|
5
13
|
sizeBytes: number;
|
|
14
|
+
/**
|
|
15
|
+
* Working directory the session ran in, extracted from the log head.
|
|
16
|
+
* Only populated for providers whose log format is known to carry it
|
|
17
|
+
* (claude, codex); absent sessions count as unresolved in scoped sync.
|
|
18
|
+
*/
|
|
19
|
+
cwd?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Change marker for store-backed sessions — hashed in place of file
|
|
22
|
+
* contents so sync can skip unchanged sessions without exporting them.
|
|
23
|
+
* Absent for file-backed sessions (their bytes are hashed directly).
|
|
24
|
+
*/
|
|
25
|
+
freshness?: string;
|
|
6
26
|
}
|
|
7
27
|
/**
|
|
8
28
|
* Discover Claude Code session log files.
|
|
9
|
-
* Claude Code stores sessions in ~/.claude/projects/<project-hash>/
|
|
29
|
+
* Claude Code stores sessions in ~/.claude/projects/<project-hash>/
|
|
10
30
|
* Session files are JSONL format.
|
|
11
31
|
*/
|
|
12
32
|
export declare function discoverClaudeSessions(): DiscoveredSession[];
|
|
@@ -15,8 +35,46 @@ export declare function discoverClaudeSessions(): DiscoveredSession[];
|
|
|
15
35
|
* Codex stores sessions in ~/.codex/sessions/<yyyy>/<mm>/<dd>/rollout-*.jsonl
|
|
16
36
|
*/
|
|
17
37
|
export declare function discoverCodexSessions(): DiscoveredSession[];
|
|
38
|
+
/**
|
|
39
|
+
* Discover Gemini CLI chat session files.
|
|
40
|
+
* Gemini CLI stores sessions in ~/.gemini/tmp/<project>/chats/session-*.jsonl
|
|
41
|
+
* (legacy sessions are single-JSON `.json` files; subagent sessions live in
|
|
42
|
+
* chats/<parent-session-id>/ subdirectories).
|
|
43
|
+
*/
|
|
44
|
+
export declare function discoverGeminiSessions(): DiscoveredSession[];
|
|
45
|
+
/**
|
|
46
|
+
* Discover OpenCode sessions. OpenCode keeps everything in a SQLite
|
|
47
|
+
* database; sessions are listed via the `opencode` CLI itself and exported
|
|
48
|
+
* one at a time at upload time (see loadSessionContent).
|
|
49
|
+
*/
|
|
50
|
+
export declare function discoverOpencodeSessions(): DiscoveredSession[];
|
|
51
|
+
/**
|
|
52
|
+
* Discover GitHub Copilot CLI sessions. Copilot CLI keeps all sessions in
|
|
53
|
+
* one shared SQLite store (~/.copilot/session-store.db); each session is
|
|
54
|
+
* exported as a JSONL bundle at upload time (see loadSessionContent).
|
|
55
|
+
*/
|
|
56
|
+
export declare function discoverCopilotSessions(): DiscoveredSession[];
|
|
18
57
|
/**
|
|
19
58
|
* Auto-detect which providers have session files available.
|
|
20
59
|
*/
|
|
21
60
|
export declare function discoverAllSessions(providerFilter?: string): DiscoveredSession[];
|
|
61
|
+
/**
|
|
62
|
+
* Materialize the bytes to upload for a discovered session: the file itself
|
|
63
|
+
* for file-backed providers, or a synthesized export for store-backed ones.
|
|
64
|
+
*/
|
|
65
|
+
export declare function loadSessionContent(session: DiscoveredSession): Promise<Buffer>;
|
|
66
|
+
/** The name the ingest endpoint stores for the uploaded blob. */
|
|
67
|
+
export declare function uploadFileName(session: DiscoveredSession): string;
|
|
68
|
+
/**
|
|
69
|
+
* Claude session logs: the first records are often non-cwd entries
|
|
70
|
+
* (type:"queue-operation", "last-prompt", ...); a record carrying a `cwd`
|
|
71
|
+
* string reliably appears within the first few lines. Scan up to
|
|
72
|
+
* MAX_HEAD_LINES JSON lines and take the first `cwd` found.
|
|
73
|
+
*/
|
|
74
|
+
export declare function extractClaudeCwd(head: string): string | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Codex session logs: the first line is a session_meta record with the cwd at
|
|
77
|
+
* `payload.cwd` (older formats used a top-level `cwd`).
|
|
78
|
+
*/
|
|
79
|
+
export declare function extractCodexCwd(firstLine: string): string | undefined;
|
|
22
80
|
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/lib/discovery.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/lib/discovery.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAA;AAEpF,eAAO,MAAM,iBAAiB,EAAE,eAAe,EAM9C,CAAA;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,eAAe,CAAA;IACzB;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAOD;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,iBAAiB,EAAE,CAoB5D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,iBAAiB,EAAE,CAO3D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,IAAI,iBAAiB,EAAE,CAmB5D;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,iBAAiB,EAAE,CAQ9D;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,iBAAiB,EAAE,CAQ7D;AAUD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAOhF;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAQpF;AAED,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAIjE;AAsDD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAYjE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAWrE"}
|
package/dist/lib/discovery.js
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
import { homedir } from 'node:os';
|
|
2
|
-
import { join, basename } from 'node:path';
|
|
3
|
-
import { readdirSync, statSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join, basename, extname } from 'node:path';
|
|
3
|
+
import { readdirSync, readFileSync, statSync, existsSync, openSync, readSync, closeSync, } from 'node:fs';
|
|
4
|
+
import { buildCopilotBundle, listCopilotSessions } from './copilot-export.js';
|
|
5
|
+
import { exportOpencodeSession, listOpencodeSessions } from './opencode-export.js';
|
|
6
|
+
export const SESSION_PROVIDERS = [
|
|
7
|
+
'claude',
|
|
8
|
+
'codex',
|
|
9
|
+
'gemini',
|
|
10
|
+
'opencode',
|
|
11
|
+
'copilot',
|
|
12
|
+
];
|
|
13
|
+
/** How much of a session file to read when looking for the cwd record. */
|
|
14
|
+
const HEAD_BYTES = 64 * 1024;
|
|
15
|
+
/** How many head lines to scan for a Claude cwd record. */
|
|
16
|
+
const MAX_HEAD_LINES = 50;
|
|
4
17
|
/**
|
|
5
18
|
* Discover Claude Code session log files.
|
|
6
|
-
* Claude Code stores sessions in ~/.claude/projects/<project-hash>/
|
|
19
|
+
* Claude Code stores sessions in ~/.claude/projects/<project-hash>/
|
|
7
20
|
* Session files are JSONL format.
|
|
8
21
|
*/
|
|
9
22
|
export function discoverClaudeSessions() {
|
|
@@ -18,7 +31,7 @@ export function discoverClaudeSessions() {
|
|
|
18
31
|
if (!statSync(projectPath).isDirectory())
|
|
19
32
|
continue;
|
|
20
33
|
// Look for JSONL files directly in project dir and in sessions subdirs
|
|
21
|
-
|
|
34
|
+
walkForSessionFiles(projectPath, 'claude', ['.jsonl'], sessions, 0);
|
|
22
35
|
}
|
|
23
36
|
}
|
|
24
37
|
catch {
|
|
@@ -35,24 +48,108 @@ export function discoverCodexSessions() {
|
|
|
35
48
|
if (!existsSync(codexDir))
|
|
36
49
|
return [];
|
|
37
50
|
const sessions = [];
|
|
38
|
-
|
|
51
|
+
walkForSessionFiles(codexDir, 'codex', ['.jsonl'], sessions, 0);
|
|
39
52
|
return sessions;
|
|
40
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Discover Gemini CLI chat session files.
|
|
56
|
+
* Gemini CLI stores sessions in ~/.gemini/tmp/<project>/chats/session-*.jsonl
|
|
57
|
+
* (legacy sessions are single-JSON `.json` files; subagent sessions live in
|
|
58
|
+
* chats/<parent-session-id>/ subdirectories).
|
|
59
|
+
*/
|
|
60
|
+
export function discoverGeminiSessions() {
|
|
61
|
+
const geminiTmp = join(homedir(), '.gemini', 'tmp');
|
|
62
|
+
if (!existsSync(geminiTmp))
|
|
63
|
+
return [];
|
|
64
|
+
const sessions = [];
|
|
65
|
+
try {
|
|
66
|
+
for (const project of readdirSync(geminiTmp)) {
|
|
67
|
+
const chatsDir = join(geminiTmp, project, 'chats');
|
|
68
|
+
try {
|
|
69
|
+
if (!statSync(chatsDir).isDirectory())
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
walkForSessionFiles(chatsDir, 'gemini', ['.jsonl', '.json'], sessions, 0);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// Permission errors - silently skip
|
|
80
|
+
}
|
|
81
|
+
return sessions;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Discover OpenCode sessions. OpenCode keeps everything in a SQLite
|
|
85
|
+
* database; sessions are listed via the `opencode` CLI itself and exported
|
|
86
|
+
* one at a time at upload time (see loadSessionContent).
|
|
87
|
+
*/
|
|
88
|
+
export function discoverOpencodeSessions() {
|
|
89
|
+
return listOpencodeSessions().map((s) => ({
|
|
90
|
+
provider: 'opencode',
|
|
91
|
+
filePath: `opencode://${s.id}`,
|
|
92
|
+
sessionId: s.id,
|
|
93
|
+
sizeBytes: 0,
|
|
94
|
+
freshness: `${s.id}:${s.timeUpdated}`,
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Discover GitHub Copilot CLI sessions. Copilot CLI keeps all sessions in
|
|
99
|
+
* one shared SQLite store (~/.copilot/session-store.db); each session is
|
|
100
|
+
* exported as a JSONL bundle at upload time (see loadSessionContent).
|
|
101
|
+
*/
|
|
102
|
+
export function discoverCopilotSessions() {
|
|
103
|
+
return listCopilotSessions().map((s) => ({
|
|
104
|
+
provider: 'copilot',
|
|
105
|
+
filePath: `copilot://${s.id}`,
|
|
106
|
+
sessionId: s.id,
|
|
107
|
+
sizeBytes: 0,
|
|
108
|
+
freshness: `${s.id}:${s.updatedAt}`,
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
const DISCOVERERS = {
|
|
112
|
+
claude: discoverClaudeSessions,
|
|
113
|
+
codex: discoverCodexSessions,
|
|
114
|
+
gemini: discoverGeminiSessions,
|
|
115
|
+
opencode: discoverOpencodeSessions,
|
|
116
|
+
copilot: discoverCopilotSessions,
|
|
117
|
+
};
|
|
41
118
|
/**
|
|
42
119
|
* Auto-detect which providers have session files available.
|
|
43
120
|
*/
|
|
44
121
|
export function discoverAllSessions(providerFilter) {
|
|
45
122
|
const sessions = [];
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
sessions.push(...discoverCodexSessions());
|
|
123
|
+
for (const provider of SESSION_PROVIDERS) {
|
|
124
|
+
if (providerFilter && providerFilter !== provider)
|
|
125
|
+
continue;
|
|
126
|
+
sessions.push(...DISCOVERERS[provider]());
|
|
51
127
|
}
|
|
52
128
|
return sessions;
|
|
53
129
|
}
|
|
54
|
-
/**
|
|
55
|
-
|
|
130
|
+
/**
|
|
131
|
+
* Materialize the bytes to upload for a discovered session: the file itself
|
|
132
|
+
* for file-backed providers, or a synthesized export for store-backed ones.
|
|
133
|
+
*/
|
|
134
|
+
export async function loadSessionContent(session) {
|
|
135
|
+
if (session.provider === 'opencode') {
|
|
136
|
+
return exportOpencodeSession(session.sessionId);
|
|
137
|
+
}
|
|
138
|
+
if (session.provider === 'copilot') {
|
|
139
|
+
return buildCopilotBundle(session.sessionId);
|
|
140
|
+
}
|
|
141
|
+
return readFileSync(session.filePath);
|
|
142
|
+
}
|
|
143
|
+
/** The name the ingest endpoint stores for the uploaded blob. */
|
|
144
|
+
export function uploadFileName(session) {
|
|
145
|
+
if (session.provider === 'opencode')
|
|
146
|
+
return `${session.sessionId}.json`;
|
|
147
|
+
if (session.provider === 'copilot')
|
|
148
|
+
return `${session.sessionId}.jsonl`;
|
|
149
|
+
return basename(session.filePath);
|
|
150
|
+
}
|
|
151
|
+
/** Recursively walk a directory for session files, with a max depth. */
|
|
152
|
+
function walkForSessionFiles(dir, provider, extensions, results, depth) {
|
|
56
153
|
if (depth > 3)
|
|
57
154
|
return; // Don't recurse too deep
|
|
58
155
|
try {
|
|
@@ -62,14 +159,15 @@ function walkForJsonl(dir, provider, results, depth) {
|
|
|
62
159
|
try {
|
|
63
160
|
const stat = statSync(fullPath);
|
|
64
161
|
if (stat.isDirectory()) {
|
|
65
|
-
|
|
162
|
+
walkForSessionFiles(fullPath, provider, extensions, results, depth + 1);
|
|
66
163
|
}
|
|
67
|
-
else if (
|
|
164
|
+
else if (extensions.includes(extname(entry)) && stat.size > 0) {
|
|
68
165
|
results.push({
|
|
69
166
|
provider,
|
|
70
167
|
filePath: fullPath,
|
|
71
|
-
sessionId: basename(entry,
|
|
168
|
+
sessionId: basename(entry, extname(entry)),
|
|
72
169
|
sizeBytes: stat.size,
|
|
170
|
+
cwd: extractSessionCwd(fullPath, provider),
|
|
73
171
|
});
|
|
74
172
|
}
|
|
75
173
|
}
|
|
@@ -82,4 +180,78 @@ function walkForJsonl(dir, provider, results, depth) {
|
|
|
82
180
|
// Skip directories we can't read
|
|
83
181
|
}
|
|
84
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Extract the session's working directory from the head of a log file.
|
|
185
|
+
* Only claude and codex formats are known to carry it; other providers
|
|
186
|
+
* return undefined (their sessions count as unresolved in scoped sync).
|
|
187
|
+
*/
|
|
188
|
+
function extractSessionCwd(filePath, provider) {
|
|
189
|
+
if (provider !== 'claude' && provider !== 'codex')
|
|
190
|
+
return undefined;
|
|
191
|
+
const head = readFileHead(filePath);
|
|
192
|
+
if (head === null)
|
|
193
|
+
return undefined;
|
|
194
|
+
if (provider === 'codex') {
|
|
195
|
+
const firstLine = head.split('\n', 1)[0] ?? '';
|
|
196
|
+
return extractCodexCwd(firstLine);
|
|
197
|
+
}
|
|
198
|
+
return extractClaudeCwd(head);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Claude session logs: the first records are often non-cwd entries
|
|
202
|
+
* (type:"queue-operation", "last-prompt", ...); a record carrying a `cwd`
|
|
203
|
+
* string reliably appears within the first few lines. Scan up to
|
|
204
|
+
* MAX_HEAD_LINES JSON lines and take the first `cwd` found.
|
|
205
|
+
*/
|
|
206
|
+
export function extractClaudeCwd(head) {
|
|
207
|
+
const lines = head.split('\n', MAX_HEAD_LINES);
|
|
208
|
+
for (const line of lines) {
|
|
209
|
+
if (!line.trim())
|
|
210
|
+
continue;
|
|
211
|
+
try {
|
|
212
|
+
const parsed = JSON.parse(line);
|
|
213
|
+
if (typeof parsed.cwd === 'string' && parsed.cwd.length > 0)
|
|
214
|
+
return parsed.cwd;
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
// Malformed (or truncated tail) line - keep scanning
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Codex session logs: the first line is a session_meta record with the cwd at
|
|
224
|
+
* `payload.cwd` (older formats used a top-level `cwd`).
|
|
225
|
+
*/
|
|
226
|
+
export function extractCodexCwd(firstLine) {
|
|
227
|
+
try {
|
|
228
|
+
const parsed = JSON.parse(firstLine);
|
|
229
|
+
if (typeof parsed.payload?.cwd === 'string' && parsed.payload.cwd.length > 0) {
|
|
230
|
+
return parsed.payload.cwd;
|
|
231
|
+
}
|
|
232
|
+
if (typeof parsed.cwd === 'string' && parsed.cwd.length > 0)
|
|
233
|
+
return parsed.cwd;
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
// Malformed first line
|
|
237
|
+
}
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
/** Read up to HEAD_BYTES from the start of a file without loading the rest. */
|
|
241
|
+
function readFileHead(filePath) {
|
|
242
|
+
try {
|
|
243
|
+
const fd = openSync(filePath, 'r');
|
|
244
|
+
try {
|
|
245
|
+
const buffer = Buffer.alloc(HEAD_BYTES);
|
|
246
|
+
const bytesRead = readSync(fd, buffer, 0, HEAD_BYTES, 0);
|
|
247
|
+
return buffer.toString('utf-8', 0, bytesRead);
|
|
248
|
+
}
|
|
249
|
+
finally {
|
|
250
|
+
closeSync(fd);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
85
257
|
//# sourceMappingURL=discovery.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/lib/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/lib/discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type HookClient, type HookEvent } from './hook-input.js';
|
|
2
|
+
/**
|
|
3
|
+
* What `halyard hook` uploads for a client when the payload carries no
|
|
4
|
+
* transcript path. Claude and Codex logs record their cwd, so their sweeps go
|
|
5
|
+
* through the repo-scoped sync pipeline (`sync-runner`), which resolves each
|
|
6
|
+
* session's cwd to a repo identity. The clients below have no cwd in their
|
|
7
|
+
* transcripts, so they are matched by path or session id instead.
|
|
8
|
+
*/
|
|
9
|
+
export interface SweepTarget {
|
|
10
|
+
file: string;
|
|
11
|
+
provider: string;
|
|
12
|
+
}
|
|
13
|
+
export interface SweepContext {
|
|
14
|
+
homeDir: string;
|
|
15
|
+
projectRoot: string;
|
|
16
|
+
sessionId: string;
|
|
17
|
+
transcriptPath: string;
|
|
18
|
+
event: HookEvent;
|
|
19
|
+
env: NodeJS.ProcessEnv;
|
|
20
|
+
}
|
|
21
|
+
export type SweepPlan = {
|
|
22
|
+
kind: 'files';
|
|
23
|
+
targets: SweepTarget[];
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'sync';
|
|
26
|
+
provider: string;
|
|
27
|
+
/** Restrict to sessions whose cwd resolves to this repo (Claude, Codex). */
|
|
28
|
+
scoped: boolean;
|
|
29
|
+
};
|
|
30
|
+
/** Claude keeps subagent transcripts beside the main one:
|
|
31
|
+
* <dir>/<session>.jsonl + <dir>/<session>/subagents/agent-*.jsonl */
|
|
32
|
+
export declare function claudeSessionFiles(transcript: string): string[];
|
|
33
|
+
/** Rollout files end in the thread id: rollout-<timestamp>-<id>.jsonl */
|
|
34
|
+
export declare function findCodexRollout(homeDir: string, sessionId: string): string | null;
|
|
35
|
+
/** ~/.cursor/projects/<path-slug>/agent-transcripts/<conversation>/<conversation>.jsonl */
|
|
36
|
+
export declare function sweepCursor(ctx: SweepContext): SweepTarget[];
|
|
37
|
+
/** Grok Build keeps sessions under ~/.grok/sessions; the payload carries only
|
|
38
|
+
* the session id, so match on it. Layout is undocumented — best effort. */
|
|
39
|
+
export declare function sweepGrok(ctx: SweepContext): SweepTarget[];
|
|
40
|
+
/** Amp caches threads as T-<id>.json under ~/.local/share/amp (or AMP_DATA_DIR). */
|
|
41
|
+
export declare function sweepAmp(ctx: SweepContext): SweepTarget[];
|
|
42
|
+
export declare function sweepForClient(client: HookClient, ctx: SweepContext): SweepPlan;
|
|
43
|
+
//# sourceMappingURL=hook-discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-discovery.d.ts","sourceRoot":"","sources":["../../src/lib/hook-discovery.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,iBAAiB,CAAA;AAExB;;;;;;GAMG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;IACtB,KAAK,EAAE,SAAS,CAAA;IAChB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;CACvB;AAED,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,WAAW,EAAE,CAAA;CAAE,GACzC;IACE,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,4EAA4E;IAC5E,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AAuBL;sEACsE;AACtE,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAW/D;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASlF;AAED,2FAA2F;AAC3F,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,WAAW,EAAE,CAO5D;AAED;4EAC4E;AAC5E,wBAAgB,SAAS,CAAC,GAAG,EAAE,YAAY,GAAG,WAAW,EAAE,CAQ1D;AAED,oFAAoF;AACpF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,YAAY,GAAG,WAAW,EAAE,CAQzD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,GAAG,SAAS,CAe/E"}
|