shennian 0.3.86 → 0.4.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 +3 -2
- package/dist/bin/shennian.js +1 -1
- package/dist/publish-build-manifest.json +32 -27
- package/dist/src/agents/adapter.js +1 -19
- package/dist/src/agents/claude-managed-permissions.js +1 -248
- package/dist/src/agents/claude.js +8 -393
- package/dist/src/agents/codex-managed-permissions.js +1 -294
- package/dist/src/agents/codex-managed-room-tools.js +1 -249
- package/dist/src/agents/codex-utils.js +7 -200
- package/dist/src/agents/codex.d.ts +7 -1
- package/dist/src/agents/codex.js +17 -1352
- package/dist/src/agents/config-status.js +1 -226
- package/dist/src/agents/cursor-managed-permissions.js +2 -299
- package/dist/src/agents/cursor.js +1 -314
- package/dist/src/agents/custom.js +4 -418
- package/dist/src/agents/external-channel-instructions.js +11 -94
- package/dist/src/agents/gemini.js +1 -180
- package/dist/src/agents/manager.js +18 -250
- package/dist/src/agents/model-registry/cache.js +1 -37
- package/dist/src/agents/model-registry/discovery.js +2 -188
- package/dist/src/agents/model-registry/parsers.js +4 -521
- package/dist/src/agents/model-registry/runner.js +1 -30
- package/dist/src/agents/model-registry/service.js +1 -115
- package/dist/src/agents/model-registry/types.js +1 -8
- package/dist/src/agents/model-registry.js +1 -19
- package/dist/src/agents/native-capabilities.js +1 -237
- package/dist/src/agents/openclaw.js +2 -293
- package/dist/src/agents/opencode-managed-permissions.js +2 -187
- package/dist/src/agents/opencode.js +1 -298
- package/dist/src/agents/platform-instructions.js +17 -46
- package/dist/src/agents/runtime-compatibility.js +1 -44
- package/dist/src/agents/workbuddy-managed-permissions.js +2 -329
- package/dist/src/agents/workbuddy.js +3 -444
- package/dist/src/commands/logout.d.ts +3 -0
- package/dist/src/commands/logout.js +1 -0
- package/dist/src/daemon-ipc/paths.js +1 -1
- package/dist/src/fs/boundary.js +1 -185
- package/dist/src/fs/handler.js +1 -130
- package/dist/src/fs/security.js +1 -32
- package/dist/src/fs/text-decoder.js +1 -110
- package/dist/src/index.js +3 -587
- package/dist/src/manager/prompt.js +29 -34
- package/dist/src/manager/registry.js +1 -317
- package/dist/src/manager/retired-external-channel-compat.js +1 -40
- package/dist/src/manager/runtime.js +23 -1514
- package/dist/src/native-fusion/codex-parser.d.ts +3 -1
- package/dist/src/native-fusion/codex-parser.js +4 -660
- package/dist/src/native-fusion/codex-user-input.js +5 -102
- package/dist/src/native-fusion/config.js +1 -5
- package/dist/src/native-fusion/file-watcher.js +1 -191
- package/dist/src/native-fusion/local-repository.js +2 -569
- package/dist/src/native-fusion/opencode-parser.js +3 -130
- package/dist/src/native-fusion/parser-common.d.ts +6 -1
- package/dist/src/native-fusion/parser-common.js +4 -4
- package/dist/src/native-fusion/parsers.d.ts +4 -2
- package/dist/src/native-fusion/parsers.js +3 -140
- package/dist/src/native-fusion/service.js +2 -739
- package/dist/src/native-fusion/session-header.js +2 -101
- package/dist/src/native-fusion/state.js +2 -104
- package/dist/src/native-fusion/types.js +1 -1
- package/dist/src/personal-sync/machine-authority.js +1 -34
- package/dist/src/room/activation-audit.js +2 -45
- package/dist/src/room/activation-policy.js +1 -30
- package/dist/src/room/activation-service.js +8 -408
- package/dist/src/room/invite-bootstrap.js +1 -156
- package/dist/src/room/managed-prompt-composer.d.ts +1 -1
- package/dist/src/room/managed-prompt-composer.js +17 -16
- package/dist/src/room/managed-room-binding.js +1 -167
- package/dist/src/room/managed-room-ipc.d.ts +4 -0
- package/dist/src/room/managed-room-ipc.js +2 -2
- package/dist/src/room/mirror-sync-service.d.ts +1 -0
- package/dist/src/room/mirror-sync-service.js +1 -183
- package/dist/src/room/room-binding-client.js +1 -151
- package/dist/src/session/archive-zip.js +1 -220
- package/dist/src/session/deletion-sync-state.js +2 -136
- package/dist/src/session/handlers/agent-capabilities.js +1 -14
- package/dist/src/session/handlers/agent-config.js +1 -150
- package/dist/src/session/handlers/agents.js +1 -55
- package/dist/src/session/handlers/chat.js +2 -1030
- package/dist/src/session/handlers/control.js +1 -61
- package/dist/src/session/handlers/fs.js +1 -594
- package/dist/src/session/handlers/message-status.js +1 -15
- package/dist/src/session/handlers/remote-access.js +1 -43
- package/dist/src/session/handlers/room-managed.js +1 -101
- package/dist/src/session/handlers/session-refresh.js +1 -35
- package/dist/src/session/handlers/title.js +1 -79
- package/dist/src/session/handlers/tool-detail.js +1 -149
- package/dist/src/session/handlers/voice-window.js +1 -62
- package/dist/src/session/history-subscriptions.js +1 -470
- package/dist/src/session/manager.d.ts +1 -0
- package/dist/src/session/manager.js +1 -658
- package/dist/src/session/native-cleanup-outbox.js +2 -287
- package/dist/src/session/native-session-lifecycle.js +6 -327
- package/dist/src/session/queue.d.ts +8 -0
- package/dist/src/session/queue.js +6 -6
- package/dist/src/upgrade/scheduler.js +1 -126
- package/node_modules/@shennian/wire/dist/agent-workspace.js +2 -2
- package/package.json +1 -1
|
@@ -1,130 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import os from 'node:os';
|
|
5
|
-
import path from 'node:path';
|
|
6
|
-
import { resolveBuiltinCommand, spawnResolvedCommandSync } from '../agents/command-spec.js';
|
|
7
|
-
import { normalizeNativeTimestamp } from './session-header.js';
|
|
8
|
-
function parseJsonObject(value) {
|
|
9
|
-
try {
|
|
10
|
-
const parsed = JSON.parse(value);
|
|
11
|
-
return typeof parsed === 'object' && parsed !== null ? parsed : null;
|
|
12
|
-
}
|
|
13
|
-
catch {
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
function textFromOpenCodeParts(parts) {
|
|
18
|
-
return parts
|
|
19
|
-
.filter((part) => part.type === 'text' || part.type === 'reasoning')
|
|
20
|
-
.map((part) => typeof part.text === 'string' ? part.text : '')
|
|
21
|
-
.filter(Boolean)
|
|
22
|
-
.join('\n\n')
|
|
23
|
-
.trim();
|
|
24
|
-
}
|
|
25
|
-
function pushOpenCodeEvent(events, snapshotPath, session, message, role, payload, modelId, terminal) {
|
|
26
|
-
if (!payload)
|
|
27
|
-
return;
|
|
28
|
-
const eventTimestamp = normalizeNativeTimestamp(message.time_created);
|
|
29
|
-
const sourceSessionCreatedAtMs = normalizeNativeTimestamp(session.time_created);
|
|
30
|
-
if (!eventTimestamp || !sourceSessionCreatedAtMs)
|
|
31
|
-
return;
|
|
32
|
-
events.push({
|
|
33
|
-
agentType: 'opencode',
|
|
34
|
-
sourceMode: 'opencode_session_import',
|
|
35
|
-
sourceSessionKey: session.id,
|
|
36
|
-
sourceEventKey: `opencode:${session.id}:${message.id}:${role}`,
|
|
37
|
-
cursor: `${snapshotPath}:${message.time_created}:${message.id}`,
|
|
38
|
-
role,
|
|
39
|
-
ts: eventTimestamp,
|
|
40
|
-
payload,
|
|
41
|
-
title: session.title,
|
|
42
|
-
titleSource: 'agent_native',
|
|
43
|
-
modelId,
|
|
44
|
-
workDir: session.directory,
|
|
45
|
-
terminal,
|
|
46
|
-
sourceSessionCreatedAtMs,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
export function parseOpenCodeSessionSnapshot(snapshotPath, snapshot) {
|
|
50
|
-
const events = [];
|
|
51
|
-
const sessionsById = new Map(snapshot.sessions.map((session) => [session.id, session]));
|
|
52
|
-
const partsByMessage = new Map();
|
|
53
|
-
for (const partRow of snapshot.parts) {
|
|
54
|
-
const data = parseJsonObject(partRow.data);
|
|
55
|
-
if (!data)
|
|
56
|
-
continue;
|
|
57
|
-
const list = partsByMessage.get(partRow.message_id) ?? [];
|
|
58
|
-
list.push(data);
|
|
59
|
-
partsByMessage.set(partRow.message_id, list);
|
|
60
|
-
}
|
|
61
|
-
for (const message of [...snapshot.messages].sort((left, right) => left.time_created - right.time_created)) {
|
|
62
|
-
const session = sessionsById.get(message.session_id);
|
|
63
|
-
if (!session)
|
|
64
|
-
continue;
|
|
65
|
-
const data = parseJsonObject(message.data);
|
|
66
|
-
if (!data)
|
|
67
|
-
continue;
|
|
68
|
-
const role = data.role === 'user' ? 'user' : data.role === 'assistant' ? 'agent' : null;
|
|
69
|
-
if (!role)
|
|
70
|
-
continue;
|
|
71
|
-
const parts = partsByMessage.get(message.id) ?? [];
|
|
72
|
-
const payload = textFromOpenCodeParts(parts);
|
|
73
|
-
const modelId = typeof data.modelID === 'string'
|
|
74
|
-
? `${typeof data.providerID === 'string' ? `${data.providerID}/` : ''}${data.modelID}`
|
|
75
|
-
: null;
|
|
76
|
-
pushOpenCodeEvent(events, snapshotPath, session, message, role, payload, modelId, role === 'agent');
|
|
77
|
-
}
|
|
78
|
-
return events;
|
|
79
|
-
}
|
|
80
|
-
export function listOpenCodeSessionFiles() {
|
|
81
|
-
const dataDir = path.join(os.homedir(), '.local', 'share', 'opencode');
|
|
82
|
-
const snapshot = path.join(dataDir, 'shennian-opencode-session-snapshot.opencode-session.json');
|
|
83
|
-
refreshOpenCodeSessionSnapshot(snapshot);
|
|
84
|
-
return fs.existsSync(snapshot) ? [snapshot] : [];
|
|
85
|
-
}
|
|
86
|
-
function queryOpenCodeDb(query) {
|
|
87
|
-
const spec = resolveBuiltinCommand('opencode');
|
|
88
|
-
if (!spec)
|
|
89
|
-
return [];
|
|
90
|
-
const result = spawnResolvedCommandSync(spec, ['db', query, '--format', 'json'], {
|
|
91
|
-
encoding: 'utf-8',
|
|
92
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
93
|
-
timeout: 10_000,
|
|
94
|
-
});
|
|
95
|
-
if (result.status !== 0)
|
|
96
|
-
return [];
|
|
97
|
-
try {
|
|
98
|
-
const parsed = JSON.parse(String(result.stdout ?? ''));
|
|
99
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
return [];
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
function refreshOpenCodeSessionSnapshot(snapshotPath) {
|
|
106
|
-
try {
|
|
107
|
-
const sessions = queryOpenCodeDb('select id, title, directory, time_created, time_updated from session where time_archived is null order by time_updated asc');
|
|
108
|
-
if (sessions.length === 0)
|
|
109
|
-
return;
|
|
110
|
-
const messages = queryOpenCodeDb('select id, session_id, time_created, data from message order by time_created asc, id asc');
|
|
111
|
-
const parts = queryOpenCodeDb('select id, message_id, session_id, time_created, data from part order by message_id asc, id asc');
|
|
112
|
-
fs.mkdirSync(path.dirname(snapshotPath), { recursive: true });
|
|
113
|
-
fs.writeFileSync(snapshotPath, JSON.stringify({ sessions, messages, parts }));
|
|
114
|
-
}
|
|
115
|
-
catch {
|
|
116
|
-
/* best-effort native import */
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
export function parseOpenCodeSessionFile(filePath, startOffset) {
|
|
120
|
-
const stat = fs.statSync(filePath);
|
|
121
|
-
if (startOffset >= stat.size)
|
|
122
|
-
return { nextOffset: stat.size, events: [] };
|
|
123
|
-
if (startOffset > 0)
|
|
124
|
-
return { nextOffset: stat.size, events: [] };
|
|
125
|
-
const snapshot = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
126
|
-
return {
|
|
127
|
-
nextOffset: stat.size,
|
|
128
|
-
events: parseOpenCodeSessionSnapshot(filePath, snapshot),
|
|
129
|
-
};
|
|
130
|
-
}
|
|
1
|
+
import d from"node:fs";import _ from"node:os";import u from"node:path";import{resolveBuiltinCommand as S,spawnResolvedCommandSync as v}from"../agents/command-spec.js";import{normalizeNativeTimestamp as f}from"./session-header.js";function l(t){try{const e=JSON.parse(t);return typeof e=="object"&&e!==null?e:null}catch{return null}}function O(t){return t.filter(e=>e.type==="text"||e.type==="reasoning").map(e=>typeof e.text=="string"?e.text:"").filter(Boolean).join(`
|
|
2
|
+
|
|
3
|
+
`).trim()}function h(t,e,s,r,c,n,i,o){if(!n)return;const a=f(r.time_created),p=f(s.time_created);!a||!p||t.push({agentType:"opencode",sourceMode:"opencode_session_import",sourceSessionKey:s.id,sourceEventKey:`opencode:${s.id}:${r.id}:${c}`,cursor:`${e}:${r.time_created}:${r.id}`,role:c,ts:a,payload:n,title:s.title,titleSource:"agent_native",modelId:i,workDir:s.directory,terminal:o,sourceSessionCreatedAtMs:p})}function x(t,e){const s=[],r=new Map(e.sessions.map(n=>[n.id,n])),c=new Map;for(const n of e.parts){const i=l(n.data);if(!i)continue;const o=c.get(n.message_id)??[];o.push(i),c.set(n.message_id,o)}for(const n of[...e.messages].sort((i,o)=>i.time_created-o.time_created)){const i=r.get(n.session_id);if(!i)continue;const o=l(n.data);if(!o)continue;const a=o.role==="user"?"user":o.role==="assistant"?"agent":null;if(!a)continue;const p=c.get(n.id)??[],y=O(p),g=typeof o.modelID=="string"?`${typeof o.providerID=="string"?`${o.providerID}/`:""}${o.modelID}`:null;h(s,t,i,n,a,y,g,a==="agent")}return s}function I(){const t=u.join(_.homedir(),".local","share","opencode"),e=u.join(t,"shennian-opencode-session-snapshot.opencode-session.json");return C(e),d.existsSync(e)?[e]:[]}function m(t){const e=S("opencode");if(!e)return[];const s=v(e,["db",t,"--format","json"],{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1e4});if(s.status!==0)return[];try{const r=JSON.parse(String(s.stdout??""));return Array.isArray(r)?r:[]}catch{return[]}}function C(t){try{const e=m("select id, title, directory, time_created, time_updated from session where time_archived is null order by time_updated asc");if(e.length===0)return;const s=m("select id, session_id, time_created, data from message order by time_created asc, id asc"),r=m("select id, message_id, session_id, time_created, data from part order by message_id asc, id asc");d.mkdirSync(u.dirname(t),{recursive:!0}),d.writeFileSync(t,JSON.stringify({sessions:e,messages:s,parts:r}))}catch{}}function z(t,e){const s=d.statSync(t);if(e>=s.size)return{nextOffset:s.size,events:[]};if(e>0)return{nextOffset:s.size,events:[]};const r=JSON.parse(d.readFileSync(t,"utf8"));return{nextOffset:s.size,events:x(t,r)}}export{I as listOpenCodeSessionFiles,z as parseOpenCodeSessionFile,x as parseOpenCodeSessionSnapshot};
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
export declare const MAX_JSONL_SCAN_BYTES_PER_PASS: number;
|
|
2
1
|
export declare function normalizeText(text: string): string;
|
|
3
2
|
export declare function readTimestamp(value: unknown): number | null;
|
|
4
3
|
export declare function safeParse(line: string): Record<string, unknown> | null;
|
|
5
4
|
export declare function readJsonlLines(filePath: string, startOffset: number, onLine: (line: string, lineOffset: number) => void): number;
|
|
5
|
+
/**
|
|
6
|
+
* Drain the complete JSONL snapshot that exists when the read starts while
|
|
7
|
+
* yielding between disk chunks. The chunk size bounds one synchronous slice;
|
|
8
|
+
* it is deliberately not a transcript or reconciliation limit.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readJsonlLinesCooperatively(filePath: string, startOffset: number, onLine: (line: string, lineOffset: number) => void): Promise<number>;
|
|
6
11
|
export declare function findJsonlLookbackOffset(filePath: string, startOffset: number, lineCount?: number): number;
|
|
7
12
|
export declare function readClaudeEventCwd(parsed: Record<string, unknown>): string | null;
|
|
8
13
|
export declare function isClaudeSubagentTranscript(filePath: string): boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createHash as
|
|
2
|
-
`).trim())}const
|
|
3
|
-
`).replace(/\n+$/g,""):""}function
|
|
4
|
-
`).trim()}function
|
|
1
|
+
import{createHash as E}from"node:crypto";import d from"node:fs";import w from"node:os";import c from"node:path";const x=64*1024*1024,S=256*1024,I=["/root/.claude-mem/observer-session",c.join(w.tmpdir(),"shennian-agent-e2e")],N=I.map(O);function J(e){return _(e.replace(/\r\n/g,`
|
|
2
|
+
`).trim())}const T=/^\s*::git-[a-z-]+\{[^\n]*\}\s*$/gm;function _(e){if(!e)return"";if(!/(^|\n)\s*::git-[a-z-]+\{[^\n]*\}\s*(?=\n|$)/.test(e))return e;const n=e.replace(T,"");return n.trim()?n.replace(/[ \t]+\n/g,`
|
|
3
|
+
`).replace(/\n+$/g,""):""}function P(e){if(typeof e!="string")return null;const t=Date.parse(e);return Number.isFinite(t)?t:null}function $(e){try{const t=JSON.parse(e);return typeof t=="object"&&t!==null?t:null}catch{return null}}function j(e,t,n){const i=d.statSync(e).size;if(t>=i)return i;const g=d.openSync(e,"r");try{const p=Buffer.allocUnsafe(S);let l=t,o=t,u=Buffer.alloc(0),m=!1;for(;l<i;){const h=d.readSync(g,p,0,Math.min(S,i-l),l);if(h<=0)break;l+=h;let a=p.subarray(0,h);u.length>0&&(a=Buffer.concat([u,a]),u=Buffer.alloc(0));let s=0;for(;s<a.length;){const r=a.indexOf(10,s);if(r<0)break;const y=a.subarray(s,r),b=o;o+=r-s+1,s=r+1,!m&&y.length>0&&y.length<=x&&n(y.toString("utf8"),b),m=!1}if(s<a.length){const r=a.subarray(s);m||r.length>x?(m=!0,o+=r.length,u=Buffer.alloc(0)):u=Buffer.from(r)}}return o}finally{d.closeSync(g)}}async function M(e,t,n){const i=(await d.promises.stat(e)).size;if(t>=i)return i;const g=await d.promises.open(e,"r");try{const p=Buffer.allocUnsafe(S);let l=t,o=t,u=Buffer.alloc(0),m=!1;for(;l<i;){const{bytesRead:h}=await g.read(p,0,Math.min(S,i-l),l);if(h<=0)break;l+=h;let a=p.subarray(0,h);u.length>0&&(a=Buffer.concat([u,a]),u=Buffer.alloc(0));let s=0;for(;s<a.length;){const r=a.indexOf(10,s);if(r<0)break;const y=a.subarray(s,r),b=o;o+=r-s+1,s=r+1,!m&&y.length>0&&y.length<=x&&n(y.toString("utf8"),b),m=!1}if(s<a.length){const r=a.subarray(s);m||r.length>x?(m=!0,o+=r.length,u=Buffer.alloc(0)):u=Buffer.from(r)}l<i&&await new Promise(r=>setImmediate(r))}return o}finally{await g.close()}}function U(e,t,n=64){if(t<=0||n<=0)return 0;const f=d.openSync(e,"r");try{let i=t,g=n;for(;i>0;){const p=Math.min(i,65536);i-=p;const l=Buffer.allocUnsafe(p);d.readSync(f,l,0,p,i);for(let o=p-1;o>=0;o-=1)if(!(l[o]!==10||i+o+1===t)&&(g-=1,g===0))return i+o+1}return 0}finally{d.closeSync(f)}}function F(e){return typeof e.cwd=="string"&&e.cwd.trim()?e.cwd:null}function G(e){return c.basename(c.dirname(e))==="subagents"}function C(e){const t=c.resolve(e);return process.platform==="win32"?t.toLowerCase():t}function B(e,t){const n=C(e),f=C(t);return n===f||n.startsWith(f+c.sep)}function O(e){return c.resolve(e).replace(/\//g,"-")}function H(e){return I.some(t=>B(e,t))}function k(e){return N.includes(e)}function V(e){const t=c.join(w.homedir(),".claude","projects"),n=c.relative(t,e);if(!n||n.startsWith("..")||c.isAbsolute(n))return!1;const[f]=n.split(c.sep);return f?k(f):!1}function K(e,t){return`${e}:${t}`}function W(e,t,n){return`${E("sha1").update(e).digest("hex").slice(0,16)}:${t}:${n}`}function Y(e){if(e==null)return"";if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return String(e)}}function X(e){return e.replace(/\r\n/g,`
|
|
4
|
+
`).trim()}function q(e){if(typeof e!="string")return e;const t=e.trim();if(!t)return"";try{return JSON.parse(t)}catch{return e}}function Q(e){const t={v:1,type:"tool",name:e.name,toolCallId:e.toolCallId,detailRevision:e.detailRevision,status:e.status,resultOmitted:!0,detailAvailable:!0,...e.durationMs!==void 0?{durationMs:e.durationMs}:{}};return JSON.stringify(t)}function D(e){return e.replace(/[[\]\\]/g,"\\$&")}function L(e,t="Generated image"){return``}function Z(e){const t=c.basename(e)||"generated-image.png";return JSON.stringify({v:1,type:"image",content:L(e,t),attachments:[{path:e,name:t,mimeType:"image/png",kind:"image"}]})}function ee(e){const t=c.extname(e).toLowerCase();return t===".png"?"image/png":t===".jpg"||t===".jpeg"?"image/jpeg":t===".webp"?"image/webp":t===".gif"?"image/gif":"application/octet-stream"}export{Z as buildImagePayload,L as buildMarkdownImageRef,Q as buildToolPayload,O as encodeClaudeProjectDir,D as escapeMarkdownLabel,U as findJsonlLookbackOffset,ee as inferMimeType,G as isClaudeSubagentTranscript,B as isSameOrChildPath,K as makeCursor,W as makeEventKey,C as normalizePathForCompare,J as normalizeText,X as normalizeToolText,q as parseStructuredString,F as readClaudeEventCwd,j as readJsonlLines,M as readJsonlLinesCooperatively,P as readTimestamp,$ as safeParse,Y as safeStringify,k as shouldIgnoreClaudeProjectDir,V as shouldIgnoreClaudeTranscriptPath,H as shouldIgnoreNativeScanPath};
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { ParsedNativeEvent } from './types.js';
|
|
2
|
-
export { listCodexRolloutFiles, lookupCodexThreadName, parseCodexRolloutChunk, } from './codex-parser.js';
|
|
2
|
+
export { listCodexRolloutFiles, lookupCodexThreadName, parseCodexRolloutChunk, parseCodexRolloutChunkCooperatively, } from './codex-parser.js';
|
|
3
3
|
export { inspectNativeSessionFile, normalizeNativeTimestamp } from './session-header.js';
|
|
4
4
|
export { listOpenCodeSessionFiles, parseOpenCodeSessionFile, parseOpenCodeSessionSnapshot, type OpenCodeSnapshot, } from './opencode-parser.js';
|
|
5
5
|
export declare function listNativeTranscriptRoots(): string[];
|
|
6
6
|
export declare function listClaudeTranscriptFiles(): string[];
|
|
7
7
|
export declare function lookupClaudeTranscriptCwd(sourceSessionKey: string): string | null;
|
|
8
|
-
|
|
8
|
+
type ClaudeTranscriptChunk = {
|
|
9
9
|
nextOffset: number;
|
|
10
10
|
events: ParsedNativeEvent[];
|
|
11
11
|
};
|
|
12
|
+
export declare function parseClaudeTranscriptChunk(filePath: string, startOffset: number): ClaudeTranscriptChunk;
|
|
13
|
+
export declare function parseClaudeTranscriptChunkCooperatively(filePath: string, startOffset: number): Promise<ClaudeTranscriptChunk>;
|
|
@@ -1,140 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import os from 'node:os';
|
|
5
|
-
import path from 'node:path';
|
|
6
|
-
export { listCodexRolloutFiles, lookupCodexThreadName, parseCodexRolloutChunk, } from './codex-parser.js';
|
|
7
|
-
export { inspectNativeSessionFile, normalizeNativeTimestamp } from './session-header.js';
|
|
8
|
-
export { listOpenCodeSessionFiles, parseOpenCodeSessionFile, parseOpenCodeSessionSnapshot, } from './opencode-parser.js';
|
|
9
|
-
import { makeCursor, makeEventKey, normalizeText, readClaudeEventCwd, readJsonlLines, readTimestamp, safeParse, isClaudeSubagentTranscript, shouldIgnoreClaudeProjectDir, shouldIgnoreClaudeTranscriptPath, shouldIgnoreNativeScanPath, } from './parser-common.js';
|
|
10
|
-
export function listNativeTranscriptRoots() {
|
|
11
|
-
return [
|
|
12
|
-
path.join(os.homedir(), '.codex', 'sessions'),
|
|
13
|
-
path.join(os.homedir(), '.codex', 'archived_sessions'),
|
|
14
|
-
path.join(os.homedir(), '.claude', 'projects'),
|
|
15
|
-
path.join(os.homedir(), '.local', 'share', 'opencode'),
|
|
16
|
-
];
|
|
17
|
-
}
|
|
18
|
-
function relativeProjectDir(cwd) {
|
|
19
|
-
const home = os.homedir();
|
|
20
|
-
if (cwd.startsWith(home))
|
|
21
|
-
return cwd.slice(home.length).replace(/^\//, '') || '~';
|
|
22
|
-
return cwd.replace(/\//g, '-');
|
|
23
|
-
}
|
|
24
|
-
export function listClaudeTranscriptFiles() {
|
|
25
|
-
const root = path.join(os.homedir(), '.claude', 'projects');
|
|
26
|
-
if (!fs.existsSync(root))
|
|
27
|
-
return [];
|
|
28
|
-
const files = [];
|
|
29
|
-
const walk = (dir) => {
|
|
30
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
31
|
-
const full = path.join(dir, entry.name);
|
|
32
|
-
if (entry.isDirectory()) {
|
|
33
|
-
if (dir === root && shouldIgnoreClaudeProjectDir(entry.name))
|
|
34
|
-
continue;
|
|
35
|
-
walk(full);
|
|
36
|
-
}
|
|
37
|
-
else if (entry.isFile() && entry.name.endsWith('.jsonl'))
|
|
38
|
-
files.push(full);
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
walk(root);
|
|
42
|
-
return files.sort();
|
|
43
|
-
}
|
|
44
|
-
export function lookupClaudeTranscriptCwd(sourceSessionKey) {
|
|
45
|
-
if (!sourceSessionKey)
|
|
46
|
-
return null;
|
|
47
|
-
const match = listClaudeTranscriptFiles().find((filePath) => path.basename(filePath, '.jsonl') === sourceSessionKey);
|
|
48
|
-
if (!match)
|
|
49
|
-
return null;
|
|
50
|
-
let found = null;
|
|
51
|
-
readJsonlLines(match, 0, (line) => {
|
|
52
|
-
if (found || !line.trim())
|
|
53
|
-
return;
|
|
54
|
-
const parsed = safeParse(line);
|
|
55
|
-
if (!parsed)
|
|
56
|
-
return;
|
|
57
|
-
const cwd = readClaudeEventCwd(parsed);
|
|
58
|
-
if (cwd)
|
|
59
|
-
found = cwd;
|
|
60
|
-
});
|
|
61
|
-
return found;
|
|
62
|
-
}
|
|
63
|
-
export function parseClaudeTranscriptChunk(filePath, startOffset) {
|
|
64
|
-
const fileSize = fs.statSync(filePath).size;
|
|
65
|
-
if (isClaudeSubagentTranscript(filePath) || shouldIgnoreClaudeTranscriptPath(filePath)) {
|
|
66
|
-
return { nextOffset: fileSize, events: [] };
|
|
67
|
-
}
|
|
68
|
-
const events = [];
|
|
69
|
-
const sourceSessionKey = path.basename(filePath, '.jsonl');
|
|
70
|
-
const fallbackWorkDir = relativeProjectDir(path.dirname(filePath).replace(path.join(os.homedir(), '.claude', 'projects') + path.sep, ''));
|
|
71
|
-
if (shouldIgnoreNativeScanPath(fallbackWorkDir)) {
|
|
72
|
-
return { nextOffset: fileSize, events: [] };
|
|
73
|
-
}
|
|
74
|
-
let title = '';
|
|
75
|
-
const nextOffset = readJsonlLines(filePath, startOffset, (line, lineOffset) => {
|
|
76
|
-
const parsed = safeParse(line);
|
|
77
|
-
if (!parsed)
|
|
78
|
-
return;
|
|
79
|
-
const ts = readTimestamp(parsed.timestamp);
|
|
80
|
-
const type = typeof parsed.type === 'string' ? parsed.type : '';
|
|
81
|
-
if (!ts || !type)
|
|
82
|
-
return;
|
|
83
|
-
const eventCwd = readClaudeEventCwd(parsed);
|
|
84
|
-
if (eventCwd && shouldIgnoreNativeScanPath(eventCwd))
|
|
85
|
-
return;
|
|
86
|
-
if (type === 'user') {
|
|
87
|
-
const message = typeof parsed.message === 'object' && parsed.message !== null
|
|
88
|
-
? parsed.message
|
|
89
|
-
: null;
|
|
90
|
-
const text = typeof message?.content === 'string' ? normalizeText(message.content) : '';
|
|
91
|
-
if (!text)
|
|
92
|
-
return;
|
|
93
|
-
if (!title)
|
|
94
|
-
title = text.slice(0, 80);
|
|
95
|
-
events.push({
|
|
96
|
-
agentType: 'claude',
|
|
97
|
-
sourceMode: 'claude_transcript_import',
|
|
98
|
-
sourceSessionKey,
|
|
99
|
-
sourceEventKey: makeEventKey(filePath, lineOffset, 'user'),
|
|
100
|
-
cursor: makeCursor(filePath, lineOffset),
|
|
101
|
-
role: 'user',
|
|
102
|
-
ts,
|
|
103
|
-
payload: text,
|
|
104
|
-
title,
|
|
105
|
-
titleSource: 'first_user_fallback',
|
|
106
|
-
workDir: eventCwd ?? fallbackWorkDir,
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
else if (type === 'assistant') {
|
|
110
|
-
const message = typeof parsed.message === 'object' && parsed.message !== null
|
|
111
|
-
? parsed.message
|
|
112
|
-
: null;
|
|
113
|
-
const content = Array.isArray(message?.content) ? message.content : [];
|
|
114
|
-
const text = normalizeText(content
|
|
115
|
-
.map((part) => typeof part === 'object' && part !== null && typeof part.text === 'string'
|
|
116
|
-
? part.text
|
|
117
|
-
: '')
|
|
118
|
-
.filter(Boolean)
|
|
119
|
-
.join('\n\n'));
|
|
120
|
-
if (!text)
|
|
121
|
-
return;
|
|
122
|
-
const modelId = typeof message?.model === 'string' ? message.model : null;
|
|
123
|
-
events.push({
|
|
124
|
-
agentType: 'claude',
|
|
125
|
-
sourceMode: 'claude_transcript_import',
|
|
126
|
-
sourceSessionKey,
|
|
127
|
-
sourceEventKey: makeEventKey(filePath, lineOffset, 'assistant'),
|
|
128
|
-
cursor: makeCursor(filePath, lineOffset),
|
|
129
|
-
role: 'agent',
|
|
130
|
-
ts,
|
|
131
|
-
payload: text,
|
|
132
|
-
title,
|
|
133
|
-
titleSource: 'first_user_fallback',
|
|
134
|
-
modelId,
|
|
135
|
-
workDir: eventCwd ?? fallbackWorkDir,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
return { nextOffset, events };
|
|
140
|
-
}
|
|
1
|
+
import h from"node:fs";import l from"node:os";import i from"node:path";import{listCodexRolloutFiles as U,lookupCodexThreadName as V,parseCodexRolloutChunk as X,parseCodexRolloutChunkCooperatively as Y}from"./codex-parser.js";import{inspectNativeSessionFile as $,normalizeNativeTimestamp as P}from"./session-header.js";import{listOpenCodeSessionFiles as te,parseOpenCodeSessionFile as oe,parseOpenCodeSessionSnapshot as ne}from"./opencode-parser.js";import{makeCursor as g,makeEventKey as j,normalizeText as v,readClaudeEventCwd as k,readJsonlLines as T,readJsonlLinesCooperatively as D,readTimestamp as L,safeParse as S,isClaudeSubagentTranscript as N,shouldIgnoreClaudeProjectDir as z,shouldIgnoreClaudeTranscriptPath as E,shouldIgnoreNativeScanPath as b}from"./parser-common.js";function M(){return[i.join(l.homedir(),".codex","sessions"),i.join(l.homedir(),".codex","archived_sessions"),i.join(l.homedir(),".claude","projects"),i.join(l.homedir(),".local","share","opencode")]}function I(e){const o=l.homedir();return e.startsWith(o)?e.slice(o.length).replace(/^\//,"")||"~":e.replace(/\//g,"-")}function R(){const e=i.join(l.homedir(),".claude","projects");if(!h.existsSync(e))return[];const o=[],t=r=>{for(const n of h.readdirSync(r,{withFileTypes:!0})){const a=i.join(r,n.name);if(n.isDirectory()){if(r===e&&z(n.name))continue;t(a)}else n.isFile()&&n.name.endsWith(".jsonl")&&o.push(a)}};return t(e),o.sort()}function B(e){if(!e)return null;const o=R().find(r=>i.basename(r,".jsonl")===e);if(!o)return null;let t=null;return T(o,0,r=>{if(t||!r.trim())return;const n=S(r);if(!n)return;const a=k(n);a&&(t=a)}),t}function _(e){const o=h.statSync(e).size;if(N(e)||E(e))return{nextOffset:o,events:[]};const t=[],r=i.basename(e,".jsonl"),n=I(i.dirname(e).replace(i.join(l.homedir(),".claude","projects")+i.sep,""));if(b(n))return{nextOffset:o,events:[]};let a="";return{onLine:(m,p)=>{const s=S(m);if(!s)return;const C=L(s.timestamp),y=typeof s.type=="string"?s.type:"";if(!C||!y)return;const d=k(s);if(!(d&&b(d))){if(y==="user"){const c=typeof s.message=="object"&&s.message!==null?s.message:null,u=typeof c?.content=="string"?v(c.content):"";if(!u)return;a||(a=u.slice(0,80)),t.push({agentType:"claude",sourceMode:"claude_transcript_import",sourceSessionKey:r,sourceEventKey:j(e,p,"user"),cursor:g(e,p),role:"user",ts:C,payload:u,title:a,titleSource:"first_user_fallback",workDir:d??n})}else if(y==="assistant"){const c=typeof s.message=="object"&&s.message!==null?s.message:null,u=Array.isArray(c?.content)?c.content:[],x=v(u.map(f=>typeof f=="object"&&f!==null&&typeof f.text=="string"?f.text:"").filter(Boolean).join(`
|
|
2
|
+
|
|
3
|
+
`));if(!x)return;const F=typeof c?.model=="string"?c.model:null;t.push({agentType:"claude",sourceMode:"claude_transcript_import",sourceSessionKey:r,sourceEventKey:j(e,p,"assistant"),cursor:g(e,p),role:"agent",ts:C,payload:x,title:a,titleSource:"first_user_fallback",modelId:F,workDir:d??n})}}},finish:m=>({nextOffset:m,events:t})}}function w(e){return"nextOffset"in e}function q(e,o){const t=_(e);return w(t)?t:t.finish(T(e,o,t.onLine))}async function G(e,o){const t=_(e);return w(t)?t:t.finish(await D(e,o,t.onLine))}export{$ as inspectNativeSessionFile,R as listClaudeTranscriptFiles,U as listCodexRolloutFiles,M as listNativeTranscriptRoots,te as listOpenCodeSessionFiles,B as lookupClaudeTranscriptCwd,V as lookupCodexThreadName,P as normalizeNativeTimestamp,q as parseClaudeTranscriptChunk,G as parseClaudeTranscriptChunkCooperatively,X as parseCodexRolloutChunk,Y as parseCodexRolloutChunkCooperatively,oe as parseOpenCodeSessionFile,ne as parseOpenCodeSessionSnapshot};
|