shennian 0.2.89 → 0.2.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/wechat-channel/macos/manifest.json +13 -4
- package/dist/assets/wechat-channel/macos/shennian-wechat-channel-helper +0 -0
- package/dist/bin/shennian.js +1 -1
- package/dist/publish-build-manifest.json +548 -0
- package/dist/scripts/wechat-rpa-confirmation.mjs +5 -97
- package/dist/src/agent-env.js +4 -105
- package/dist/src/agents/adapter.js +1 -19
- package/dist/src/agents/claude.js +8 -305
- package/dist/src/agents/codex-control.js +2 -188
- package/dist/src/agents/codex-utils.js +7 -200
- package/dist/src/agents/codex.js +15 -916
- package/dist/src/agents/command-spec.js +2 -413
- package/dist/src/agents/config-status.js +1 -226
- package/dist/src/agents/cursor.js +1 -249
- package/dist/src/agents/custom.js +4 -271
- package/dist/src/agents/detect.js +1 -56
- package/dist/src/agents/external-channel-instructions.js +10 -94
- package/dist/src/agents/gemini.js +1 -173
- package/dist/src/agents/manager.js +13 -157
- package/dist/src/agents/model-registry/cache.js +1 -37
- package/dist/src/agents/model-registry/discovery.js +2 -187
- package/dist/src/agents/model-registry/parsers.js +4 -447
- package/dist/src/agents/model-registry/runner.js +1 -30
- package/dist/src/agents/model-registry/service.js +1 -78
- package/dist/src/agents/model-registry/types.js +1 -8
- package/dist/src/agents/model-registry.js +1 -18
- package/dist/src/agents/openclaw.js +2 -275
- package/dist/src/agents/opencode.js +1 -231
- package/dist/src/agents/pi-context.js +12 -217
- package/dist/src/agents/pi.js +14 -723
- package/dist/src/agents/platform-instructions.js +9 -54
- package/dist/src/channels/base.js +1 -3
- package/dist/src/channels/registry.js +1 -30
- package/dist/src/channels/reply-split.js +10 -89
- package/dist/src/channels/runtime.js +5 -564
- package/dist/src/channels/secret-registry.js +1 -46
- package/dist/src/channels/websocket.js +8 -378
- package/dist/src/channels/wechat-channel/anchor.js +1 -65
- package/dist/src/channels/wechat-channel/client.js +1 -96
- package/dist/src/channels/wechat-channel/cooldown.js +1 -38
- package/dist/src/channels/wechat-channel/fingerprint.js +1 -71
- package/dist/src/channels/wechat-channel/helper-assets.d.ts +10 -1
- package/dist/src/channels/wechat-channel/helper-assets.js +1 -68
- package/dist/src/channels/wechat-channel/helper-client.js +3 -149
- package/dist/src/channels/wechat-channel/helper-protocol.d.ts +1 -1
- package/dist/src/channels/wechat-channel/helper-protocol.js +1 -115
- package/dist/src/channels/wechat-channel/index.d.ts +1 -0
- package/dist/src/channels/wechat-channel/index.js +1 -19
- package/dist/src/channels/wechat-channel/ledger.js +1 -54
- package/dist/src/channels/wechat-channel/media-resolver.js +1 -181
- package/dist/src/channels/wechat-channel/message-key.js +1 -105
- package/dist/src/channels/wechat-channel/observer.js +1 -118
- package/dist/src/channels/wechat-channel/outbound-ledger.d.ts +3 -0
- package/dist/src/channels/wechat-channel/outbound-ledger.js +2 -112
- package/dist/src/channels/wechat-channel/outbound-sender.d.ts +26 -0
- package/dist/src/channels/wechat-channel/outbound-sender.js +1 -0
- package/dist/src/channels/wechat-channel/preflight.js +1 -48
- package/dist/src/channels/wechat-channel/runner.js +1 -84
- package/dist/src/channels/wechat-channel/runtime.js +1 -66
- package/dist/src/channels/wechat-channel/scheduler.d.ts +5 -0
- package/dist/src/channels/wechat-channel/scheduler.js +1 -152
- package/dist/src/channels/wechat-rpa/macos-flow.js +1 -96
- package/dist/src/channels/wechat-rpa/macos.js +6 -48
- package/dist/src/channels/wechat-rpa/normalizer.js +7 -127
- package/dist/src/channels/wechat-rpa.js +6 -1028
- package/dist/src/channels/wecom.js +4 -357
- package/dist/src/commands/agent.js +6 -131
- package/dist/src/commands/daemon-windows.js +8 -48
- package/dist/src/commands/daemon.js +19 -1013
- package/dist/src/commands/external-attachments.js +1 -51
- package/dist/src/commands/external.js +1 -137
- package/dist/src/commands/manager.js +2 -391
- package/dist/src/commands/pair-qr.js +1 -6
- package/dist/src/commands/pair.js +9 -287
- package/dist/src/commands/tools.js +1 -34
- package/dist/src/commands/upgrade.js +1 -198
- package/dist/src/config/index.js +1 -35
- package/dist/src/daemon-log.js +6 -58
- package/dist/src/env-path.js +1 -64
- package/dist/src/fs/boundary.js +1 -126
- 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 +2 -404
- package/dist/src/log-reporter.js +1 -16
- package/dist/src/manager/prompt.js +29 -34
- package/dist/src/manager/registry.js +2 -269
- package/dist/src/manager/runtime.js +19 -1007
- package/dist/src/native-fusion/config.js +1 -5
- package/dist/src/native-fusion/opencode-parser.js +3 -123
- package/dist/src/native-fusion/parser-common.js +8 -264
- package/dist/src/native-fusion/parsers.js +8 -729
- package/dist/src/native-fusion/service.js +2 -225
- package/dist/src/native-fusion/state.js +1 -22
- package/dist/src/native-fusion/types.js +1 -1
- package/dist/src/region.js +1 -88
- package/dist/src/relay/client.js +1 -343
- package/dist/src/session/archive-zip.js +1 -220
- 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 -751
- package/dist/src/session/handlers/control.js +1 -55
- package/dist/src/session/handlers/fs.js +1 -783
- package/dist/src/session/handlers/session-refresh.js +1 -47
- package/dist/src/session/handlers/skills.js +1 -121
- package/dist/src/session/handlers/title.js +1 -60
- package/dist/src/session/handlers/tool-detail.js +1 -218
- package/dist/src/session/manager.js +1 -319
- package/dist/src/session/projection.js +1 -54
- package/dist/src/session/queue.js +4 -317
- package/dist/src/session/remote-attachments.js +1 -72
- package/dist/src/session/store.js +3 -109
- package/dist/src/session/types.js +1 -4
- package/dist/src/skills/registry.js +15 -148
- package/dist/src/skills/setup.js +1 -101
- package/dist/src/tools/markdown-to-pdf.js +10 -346
- package/dist/src/upgrade/engine.js +3 -347
- package/package.json +3 -2
|
@@ -1,5 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// @test src/__tests__/native-fusion-config.test.ts
|
|
3
|
-
export function isNativeFusionEnabled(env = process.env) {
|
|
4
|
-
return env.SHENNIAN_NATIVE_FUSION_DISABLED !== '1';
|
|
5
|
-
}
|
|
1
|
+
function n(e=process.env){return e.SHENNIAN_NATIVE_FUSION_DISABLED!=="1"}export{n as isNativeFusionEnabled};
|
|
@@ -1,123 +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
|
-
function parseJsonObject(value) {
|
|
8
|
-
try {
|
|
9
|
-
const parsed = JSON.parse(value);
|
|
10
|
-
return typeof parsed === 'object' && parsed !== null ? parsed : null;
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
function textFromOpenCodeParts(parts) {
|
|
17
|
-
return parts
|
|
18
|
-
.filter((part) => part.type === 'text' || part.type === 'reasoning')
|
|
19
|
-
.map((part) => typeof part.text === 'string' ? part.text : '')
|
|
20
|
-
.filter(Boolean)
|
|
21
|
-
.join('\n\n')
|
|
22
|
-
.trim();
|
|
23
|
-
}
|
|
24
|
-
function pushOpenCodeEvent(events, snapshotPath, session, message, role, payload, modelId, terminal) {
|
|
25
|
-
if (!payload)
|
|
26
|
-
return;
|
|
27
|
-
events.push({
|
|
28
|
-
agentType: 'opencode',
|
|
29
|
-
sourceMode: 'opencode_session_import',
|
|
30
|
-
sourceSessionKey: session.id,
|
|
31
|
-
sourceEventKey: `opencode:${session.id}:${message.id}:${role}`,
|
|
32
|
-
cursor: `${snapshotPath}:${message.time_created}:${message.id}`,
|
|
33
|
-
role,
|
|
34
|
-
ts: message.time_created,
|
|
35
|
-
payload,
|
|
36
|
-
title: session.title,
|
|
37
|
-
modelId,
|
|
38
|
-
workDir: session.directory,
|
|
39
|
-
terminal,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
export function parseOpenCodeSessionSnapshot(snapshotPath, snapshot) {
|
|
43
|
-
const events = [];
|
|
44
|
-
const sessionsById = new Map(snapshot.sessions.map((session) => [session.id, session]));
|
|
45
|
-
const partsByMessage = new Map();
|
|
46
|
-
for (const partRow of snapshot.parts) {
|
|
47
|
-
const data = parseJsonObject(partRow.data);
|
|
48
|
-
if (!data)
|
|
49
|
-
continue;
|
|
50
|
-
const list = partsByMessage.get(partRow.message_id) ?? [];
|
|
51
|
-
list.push(data);
|
|
52
|
-
partsByMessage.set(partRow.message_id, list);
|
|
53
|
-
}
|
|
54
|
-
for (const message of [...snapshot.messages].sort((left, right) => left.time_created - right.time_created)) {
|
|
55
|
-
const session = sessionsById.get(message.session_id);
|
|
56
|
-
if (!session)
|
|
57
|
-
continue;
|
|
58
|
-
const data = parseJsonObject(message.data);
|
|
59
|
-
if (!data)
|
|
60
|
-
continue;
|
|
61
|
-
const role = data.role === 'user' ? 'user' : data.role === 'assistant' ? 'agent' : null;
|
|
62
|
-
if (!role)
|
|
63
|
-
continue;
|
|
64
|
-
const parts = partsByMessage.get(message.id) ?? [];
|
|
65
|
-
const payload = textFromOpenCodeParts(parts);
|
|
66
|
-
const modelId = typeof data.modelID === 'string'
|
|
67
|
-
? `${typeof data.providerID === 'string' ? `${data.providerID}/` : ''}${data.modelID}`
|
|
68
|
-
: null;
|
|
69
|
-
pushOpenCodeEvent(events, snapshotPath, session, message, role, payload, modelId, role === 'agent');
|
|
70
|
-
}
|
|
71
|
-
return events;
|
|
72
|
-
}
|
|
73
|
-
export function listOpenCodeSessionFiles() {
|
|
74
|
-
const dataDir = path.join(os.homedir(), '.local', 'share', 'opencode');
|
|
75
|
-
const snapshot = path.join(dataDir, 'shennian-opencode-session-snapshot.opencode-session.json');
|
|
76
|
-
refreshOpenCodeSessionSnapshot(snapshot);
|
|
77
|
-
return fs.existsSync(snapshot) ? [snapshot] : [];
|
|
78
|
-
}
|
|
79
|
-
function queryOpenCodeDb(query) {
|
|
80
|
-
const spec = resolveBuiltinCommand('opencode');
|
|
81
|
-
if (!spec)
|
|
82
|
-
return [];
|
|
83
|
-
const result = spawnResolvedCommandSync(spec, ['db', query, '--format', 'json'], {
|
|
84
|
-
encoding: 'utf-8',
|
|
85
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
86
|
-
timeout: 10_000,
|
|
87
|
-
});
|
|
88
|
-
if (result.status !== 0)
|
|
89
|
-
return [];
|
|
90
|
-
try {
|
|
91
|
-
const parsed = JSON.parse(String(result.stdout ?? ''));
|
|
92
|
-
return Array.isArray(parsed) ? parsed : [];
|
|
93
|
-
}
|
|
94
|
-
catch {
|
|
95
|
-
return [];
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
function refreshOpenCodeSessionSnapshot(snapshotPath) {
|
|
99
|
-
try {
|
|
100
|
-
const sessions = queryOpenCodeDb('select id, title, directory, time_created, time_updated from session where time_archived is null order by time_updated asc');
|
|
101
|
-
if (sessions.length === 0)
|
|
102
|
-
return;
|
|
103
|
-
const messages = queryOpenCodeDb('select id, session_id, time_created, data from message order by time_created asc, id asc');
|
|
104
|
-
const parts = queryOpenCodeDb('select id, message_id, session_id, time_created, data from part order by message_id asc, id asc');
|
|
105
|
-
fs.mkdirSync(path.dirname(snapshotPath), { recursive: true });
|
|
106
|
-
fs.writeFileSync(snapshotPath, JSON.stringify({ sessions, messages, parts }));
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
/* best-effort native import */
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
export function parseOpenCodeSessionFile(filePath, startOffset) {
|
|
113
|
-
const stat = fs.statSync(filePath);
|
|
114
|
-
if (startOffset >= stat.size)
|
|
115
|
-
return { nextOffset: stat.size, events: [] };
|
|
116
|
-
if (startOffset > 0)
|
|
117
|
-
return { nextOffset: stat.size, events: [] };
|
|
118
|
-
const snapshot = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
119
|
-
return {
|
|
120
|
-
nextOffset: stat.size,
|
|
121
|
-
events: parseOpenCodeSessionSnapshot(filePath, snapshot),
|
|
122
|
-
};
|
|
123
|
-
}
|
|
1
|
+
import d from"node:fs";import g from"node:os";import p from"node:path";import{resolveBuiltinCommand as _,spawnResolvedCommandSync as S}from"../agents/command-spec.js";function m(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){n&&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:r.time_created,payload:n,title:s.title,modelId:i,workDir:s.directory,terminal:o})}function v(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=m(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=m(n.data);if(!o)continue;const a=o.role==="user"?"user":o.role==="assistant"?"agent":null;if(!a)continue;const f=c.get(n.id)??[],l=O(f),y=typeof o.modelID=="string"?`${typeof o.providerID=="string"?`${o.providerID}/`:""}${o.modelID}`:null;h(s,t,i,n,a,l,y,a==="agent")}return s}function w(){const t=p.join(g.homedir(),".local","share","opencode"),e=p.join(t,"shennian-opencode-session-snapshot.opencode-session.json");return x(e),d.existsSync(e)?[e]:[]}function u(t){const e=_("opencode");if(!e)return[];const s=S(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 x(t){try{const e=u("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=u("select id, session_id, time_created, data from message order by time_created asc, id asc"),r=u("select id, message_id, session_id, time_created, data from part order by message_id asc, id asc");d.mkdirSync(p.dirname(t),{recursive:!0}),d.writeFileSync(t,JSON.stringify({sessions:e,messages:s,parts:r}))}catch{}}function D(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:v(t,r)}}export{w as listOpenCodeSessionFiles,D as parseOpenCodeSessionFile,v as parseOpenCodeSessionSnapshot};
|
|
@@ -1,264 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
'/root/.claude-mem/observer-session',
|
|
10
|
-
];
|
|
11
|
-
const DEFAULT_NATIVE_SCAN_IGNORED_CLAUDE_PROJECT_DIRS = DEFAULT_NATIVE_SCAN_IGNORED_PATHS.map(encodeClaudeProjectDir);
|
|
12
|
-
export function normalizeText(text) {
|
|
13
|
-
return stripGitDirectiveArtifacts(text.replace(/\r\n/g, '\n').trim());
|
|
14
|
-
}
|
|
15
|
-
const GIT_DIRECTIVE_LINE_RE = /^\s*::git-[a-z-]+\{[^\n]*\}\s*$/gm;
|
|
16
|
-
function stripGitDirectiveArtifacts(text) {
|
|
17
|
-
if (!text)
|
|
18
|
-
return '';
|
|
19
|
-
const hadDirective = /(^|\n)\s*::git-[a-z-]+\{[^\n]*\}\s*(?=\n|$)/.test(text);
|
|
20
|
-
if (!hadDirective)
|
|
21
|
-
return text;
|
|
22
|
-
const stripped = text.replace(GIT_DIRECTIVE_LINE_RE, '');
|
|
23
|
-
if (!stripped.trim())
|
|
24
|
-
return '';
|
|
25
|
-
return stripped.replace(/[ \t]+\n/g, '\n').replace(/\n+$/g, '');
|
|
26
|
-
}
|
|
27
|
-
export function readTimestamp(value) {
|
|
28
|
-
if (typeof value !== 'string')
|
|
29
|
-
return null;
|
|
30
|
-
const ts = Date.parse(value);
|
|
31
|
-
return Number.isFinite(ts) ? ts : null;
|
|
32
|
-
}
|
|
33
|
-
export function safeParse(line) {
|
|
34
|
-
try {
|
|
35
|
-
const parsed = JSON.parse(line);
|
|
36
|
-
return typeof parsed === 'object' && parsed !== null ? parsed : null;
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
export function readJsonlLines(filePath, startOffset, onLine) {
|
|
43
|
-
const stat = fs.statSync(filePath);
|
|
44
|
-
const fileSize = stat.size;
|
|
45
|
-
if (startOffset >= fileSize)
|
|
46
|
-
return fileSize;
|
|
47
|
-
const fd = fs.openSync(filePath, 'r');
|
|
48
|
-
try {
|
|
49
|
-
const chunkSize = 256 * 1024;
|
|
50
|
-
const buffer = Buffer.allocUnsafe(chunkSize);
|
|
51
|
-
let position = startOffset;
|
|
52
|
-
let nextOffset = startOffset;
|
|
53
|
-
let carry = Buffer.alloc(0);
|
|
54
|
-
let skippingOversizedLine = false;
|
|
55
|
-
while (position < fileSize) {
|
|
56
|
-
const bytesRead = fs.readSync(fd, buffer, 0, Math.min(chunkSize, fileSize - position), position);
|
|
57
|
-
if (bytesRead <= 0)
|
|
58
|
-
break;
|
|
59
|
-
position += bytesRead;
|
|
60
|
-
let chunk = buffer.subarray(0, bytesRead);
|
|
61
|
-
if (carry.length > 0) {
|
|
62
|
-
chunk = Buffer.concat([carry, chunk]);
|
|
63
|
-
carry = Buffer.alloc(0);
|
|
64
|
-
}
|
|
65
|
-
let lineStart = 0;
|
|
66
|
-
while (lineStart < chunk.length) {
|
|
67
|
-
const newlineIndex = chunk.indexOf(0x0a, lineStart);
|
|
68
|
-
if (newlineIndex < 0)
|
|
69
|
-
break;
|
|
70
|
-
const lineBuffer = chunk.subarray(lineStart, newlineIndex);
|
|
71
|
-
const lineOffset = nextOffset;
|
|
72
|
-
nextOffset += newlineIndex - lineStart + 1;
|
|
73
|
-
lineStart = newlineIndex + 1;
|
|
74
|
-
if (!skippingOversizedLine && lineBuffer.length > 0 && lineBuffer.length <= MAX_JSONL_LINE_BYTES) {
|
|
75
|
-
onLine(lineBuffer.toString('utf8'), lineOffset);
|
|
76
|
-
}
|
|
77
|
-
skippingOversizedLine = false;
|
|
78
|
-
}
|
|
79
|
-
if (lineStart < chunk.length) {
|
|
80
|
-
const remaining = chunk.subarray(lineStart);
|
|
81
|
-
if (skippingOversizedLine || remaining.length > MAX_JSONL_LINE_BYTES) {
|
|
82
|
-
skippingOversizedLine = true;
|
|
83
|
-
nextOffset += remaining.length;
|
|
84
|
-
carry = Buffer.alloc(0);
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
carry = Buffer.from(remaining);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
if (!skippingOversizedLine && carry.length > 0 && carry.length <= MAX_JSONL_LINE_BYTES) {
|
|
92
|
-
onLine(carry.toString('utf8'), nextOffset);
|
|
93
|
-
}
|
|
94
|
-
return fileSize;
|
|
95
|
-
}
|
|
96
|
-
finally {
|
|
97
|
-
fs.closeSync(fd);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
export function readClaudeEventCwd(parsed) {
|
|
101
|
-
return typeof parsed.cwd === 'string' && parsed.cwd.trim() ? parsed.cwd : null;
|
|
102
|
-
}
|
|
103
|
-
export function isClaudeSubagentTranscript(filePath) {
|
|
104
|
-
return path.basename(path.dirname(filePath)) === 'subagents';
|
|
105
|
-
}
|
|
106
|
-
export function normalizePathForCompare(filePath) {
|
|
107
|
-
const normalized = path.resolve(filePath);
|
|
108
|
-
return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
|
|
109
|
-
}
|
|
110
|
-
export function isSameOrChildPath(filePath, parentPath) {
|
|
111
|
-
const normalizedFilePath = normalizePathForCompare(filePath);
|
|
112
|
-
const normalizedParentPath = normalizePathForCompare(parentPath);
|
|
113
|
-
return normalizedFilePath === normalizedParentPath
|
|
114
|
-
|| normalizedFilePath.startsWith(normalizedParentPath + path.sep);
|
|
115
|
-
}
|
|
116
|
-
export function encodeClaudeProjectDir(filePath) {
|
|
117
|
-
return path.resolve(filePath).replace(/\//g, '-');
|
|
118
|
-
}
|
|
119
|
-
export function shouldIgnoreNativeScanPath(filePath) {
|
|
120
|
-
return DEFAULT_NATIVE_SCAN_IGNORED_PATHS.some((ignoredPath) => isSameOrChildPath(filePath, ignoredPath));
|
|
121
|
-
}
|
|
122
|
-
export function shouldIgnoreClaudeProjectDir(projectDirName) {
|
|
123
|
-
return DEFAULT_NATIVE_SCAN_IGNORED_CLAUDE_PROJECT_DIRS.includes(projectDirName);
|
|
124
|
-
}
|
|
125
|
-
export function shouldIgnoreClaudeTranscriptPath(filePath) {
|
|
126
|
-
const root = path.join(os.homedir(), '.claude', 'projects');
|
|
127
|
-
const relative = path.relative(root, filePath);
|
|
128
|
-
if (!relative || relative.startsWith('..') || path.isAbsolute(relative))
|
|
129
|
-
return false;
|
|
130
|
-
const [projectDirName] = relative.split(path.sep);
|
|
131
|
-
return projectDirName ? shouldIgnoreClaudeProjectDir(projectDirName) : false;
|
|
132
|
-
}
|
|
133
|
-
export function makeCursor(filePath, offset) {
|
|
134
|
-
return `${filePath}:${offset}`;
|
|
135
|
-
}
|
|
136
|
-
export function makeEventKey(filePath, offset, kind) {
|
|
137
|
-
const fingerprint = createHash('sha1').update(filePath).digest('hex').slice(0, 16);
|
|
138
|
-
return `${fingerprint}:${offset}:${kind}`;
|
|
139
|
-
}
|
|
140
|
-
export function safeStringify(value) {
|
|
141
|
-
if (value == null)
|
|
142
|
-
return '';
|
|
143
|
-
if (typeof value === 'string')
|
|
144
|
-
return value;
|
|
145
|
-
try {
|
|
146
|
-
return JSON.stringify(value);
|
|
147
|
-
}
|
|
148
|
-
catch {
|
|
149
|
-
return String(value);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
export function normalizeToolText(text) {
|
|
153
|
-
return text.replace(/\r\n/g, '\n').trim();
|
|
154
|
-
}
|
|
155
|
-
export function parseStructuredString(value) {
|
|
156
|
-
if (typeof value !== 'string')
|
|
157
|
-
return value;
|
|
158
|
-
const trimmed = value.trim();
|
|
159
|
-
if (!trimmed)
|
|
160
|
-
return '';
|
|
161
|
-
try {
|
|
162
|
-
return JSON.parse(trimmed);
|
|
163
|
-
}
|
|
164
|
-
catch {
|
|
165
|
-
return value;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
export function summarizeToolResult(value) {
|
|
169
|
-
if (value == null)
|
|
170
|
-
return '';
|
|
171
|
-
if (typeof value === 'string')
|
|
172
|
-
return normalizeToolText(value);
|
|
173
|
-
if (Array.isArray(value)) {
|
|
174
|
-
const textParts = value
|
|
175
|
-
.map((item) => extractTextContent(item))
|
|
176
|
-
.filter(Boolean);
|
|
177
|
-
if (textParts.length > 0)
|
|
178
|
-
return normalizeToolText(textParts.join('\n\n'));
|
|
179
|
-
}
|
|
180
|
-
if (typeof value === 'object') {
|
|
181
|
-
const text = extractTextContent(value);
|
|
182
|
-
if (text)
|
|
183
|
-
return normalizeToolText(text);
|
|
184
|
-
}
|
|
185
|
-
return normalizeToolText(safeStringify(value));
|
|
186
|
-
}
|
|
187
|
-
export function extractTextContent(value) {
|
|
188
|
-
if (value == null)
|
|
189
|
-
return '';
|
|
190
|
-
if (typeof value === 'string')
|
|
191
|
-
return value;
|
|
192
|
-
if (Array.isArray(value)) {
|
|
193
|
-
return value
|
|
194
|
-
.map((item) => extractTextContent(item))
|
|
195
|
-
.filter(Boolean)
|
|
196
|
-
.join('\n\n');
|
|
197
|
-
}
|
|
198
|
-
if (typeof value !== 'object')
|
|
199
|
-
return '';
|
|
200
|
-
const record = value;
|
|
201
|
-
if (typeof record.text === 'string')
|
|
202
|
-
return record.text;
|
|
203
|
-
if (typeof record.output === 'string')
|
|
204
|
-
return record.output;
|
|
205
|
-
if (typeof record.message === 'string')
|
|
206
|
-
return record.message;
|
|
207
|
-
if ('Ok' in record)
|
|
208
|
-
return extractTextContent(record.Ok);
|
|
209
|
-
if ('Err' in record)
|
|
210
|
-
return extractTextContent(record.Err);
|
|
211
|
-
if ('content' in record)
|
|
212
|
-
return extractTextContent(record.content);
|
|
213
|
-
if ('contentItems' in record)
|
|
214
|
-
return extractTextContent(record.contentItems);
|
|
215
|
-
if ('result' in record)
|
|
216
|
-
return extractTextContent(record.result);
|
|
217
|
-
return '';
|
|
218
|
-
}
|
|
219
|
-
export function buildToolPayload(name, args, result) {
|
|
220
|
-
const payload = {
|
|
221
|
-
v: 1,
|
|
222
|
-
type: 'tool',
|
|
223
|
-
name,
|
|
224
|
-
};
|
|
225
|
-
if (args !== undefined)
|
|
226
|
-
payload.args = args;
|
|
227
|
-
if (result !== undefined)
|
|
228
|
-
payload.result = summarizeToolResult(result);
|
|
229
|
-
return JSON.stringify(payload);
|
|
230
|
-
}
|
|
231
|
-
export function escapeMarkdownLabel(label) {
|
|
232
|
-
return label.replace(/[[\]\\]/g, '\\$&');
|
|
233
|
-
}
|
|
234
|
-
export function buildMarkdownImageRef(filePath, label = 'Generated image') {
|
|
235
|
-
return ``;
|
|
236
|
-
}
|
|
237
|
-
export function buildImagePayload(filePath) {
|
|
238
|
-
const name = path.basename(filePath) || 'generated-image.png';
|
|
239
|
-
return JSON.stringify({
|
|
240
|
-
v: 1,
|
|
241
|
-
type: 'image',
|
|
242
|
-
content: buildMarkdownImageRef(filePath, name),
|
|
243
|
-
attachments: [
|
|
244
|
-
{
|
|
245
|
-
path: filePath,
|
|
246
|
-
name,
|
|
247
|
-
mimeType: 'image/png',
|
|
248
|
-
kind: 'image',
|
|
249
|
-
},
|
|
250
|
-
],
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
export function inferMimeType(filePath) {
|
|
254
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
255
|
-
if (ext === '.png')
|
|
256
|
-
return 'image/png';
|
|
257
|
-
if (ext === '.jpg' || ext === '.jpeg')
|
|
258
|
-
return 'image/jpeg';
|
|
259
|
-
if (ext === '.webp')
|
|
260
|
-
return 'image/webp';
|
|
261
|
-
if (ext === '.gif')
|
|
262
|
-
return 'image/gif';
|
|
263
|
-
return 'application/octet-stream';
|
|
264
|
-
}
|
|
1
|
+
import{createHash as C}from"node:crypto";import m from"node:fs";import N from"node:os";import i from"node:path";const x=64*1024*1024,T=["/root/.claude-mem/observer-session"],_=T.map(w);function G(t){return A(t.replace(/\r\n/g,`
|
|
2
|
+
`).trim())}const z=/^\s*::git-[a-z-]+\{[^\n]*\}\s*$/gm;function A(t){if(!t)return"";if(!/(^|\n)\s*::git-[a-z-]+\{[^\n]*\}\s*(?=\n|$)/.test(t))return t;const r=t.replace(z,"");return r.trim()?r.replace(/[ \t]+\n/g,`
|
|
3
|
+
`).replace(/\n+$/g,""):""}function M(t){if(typeof t!="string")return null;const e=Date.parse(t);return Number.isFinite(e)?e:null}function U(t){try{const e=JSON.parse(t);return typeof e=="object"&&e!==null?e:null}catch{return null}}function V(t,e,r){const u=m.statSync(t).size;if(e>=u)return u;const S=m.openSync(t,"r");try{const b=Buffer.allocUnsafe(262144);let l=e,g=e,o=Buffer.alloc(0),p=!1;for(;l<u;){const y=m.readSync(S,b,0,Math.min(262144,u-l),l);if(y<=0)break;l+=y;let a=b.subarray(0,y);o.length>0&&(a=Buffer.concat([o,a]),o=Buffer.alloc(0));let c=0;for(;c<a.length;){const s=a.indexOf(10,c);if(s<0)break;const h=a.subarray(c,s),I=g;g+=s-c+1,c=s+1,!p&&h.length>0&&h.length<=x&&r(h.toString("utf8"),I),p=!1}if(c<a.length){const s=a.subarray(c);p||s.length>x?(p=!0,g+=s.length,o=Buffer.alloc(0)):o=Buffer.from(s)}}return!p&&o.length>0&&o.length<=x&&r(o.toString("utf8"),g),u}finally{m.closeSync(S)}}function H(t){return typeof t.cwd=="string"&&t.cwd.trim()?t.cwd:null}function W(t){return i.basename(i.dirname(t))==="subagents"}function E(t){const e=i.resolve(t);return process.platform==="win32"?e.toLowerCase():e}function k(t,e){const r=E(t),n=E(e);return r===n||r.startsWith(n+i.sep)}function w(t){return i.resolve(t).replace(/\//g,"-")}function K(t){return T.some(e=>k(t,e))}function D(t){return _.includes(t)}function X(t){const e=i.join(N.homedir(),".claude","projects"),r=i.relative(e,t);if(!r||r.startsWith("..")||i.isAbsolute(r))return!1;const[n]=r.split(i.sep);return n?D(n):!1}function Y(t,e){return`${t}:${e}`}function q(t,e,r){return`${C("sha1").update(t).digest("hex").slice(0,16)}:${e}:${r}`}function O(t){if(t==null)return"";if(typeof t=="string")return t;try{return JSON.stringify(t)}catch{return String(t)}}function d(t){return t.replace(/\r\n/g,`
|
|
4
|
+
`).trim()}function Q(t){if(typeof t!="string")return t;const e=t.trim();if(!e)return"";try{return JSON.parse(e)}catch{return t}}function j(t){if(t==null)return"";if(typeof t=="string")return d(t);if(Array.isArray(t)){const e=t.map(r=>f(r)).filter(Boolean);if(e.length>0)return d(e.join(`
|
|
5
|
+
|
|
6
|
+
`))}if(typeof t=="object"){const e=f(t);if(e)return d(e)}return d(O(t))}function f(t){if(t==null)return"";if(typeof t=="string")return t;if(Array.isArray(t))return t.map(r=>f(r)).filter(Boolean).join(`
|
|
7
|
+
|
|
8
|
+
`);if(typeof t!="object")return"";const e=t;return typeof e.text=="string"?e.text:typeof e.output=="string"?e.output:typeof e.message=="string"?e.message:"Ok"in e?f(e.Ok):"Err"in e?f(e.Err):"content"in e?f(e.content):"contentItems"in e?f(e.contentItems):"result"in e?f(e.result):""}function Z(t,e,r){const n={v:1,type:"tool",name:t};return e!==void 0&&(n.args=e),r!==void 0&&(n.result=j(r)),JSON.stringify(n)}function P(t){return t.replace(/[[\]\\]/g,"\\$&")}function $(t,e="Generated image"){return``}function v(t){const e=i.basename(t)||"generated-image.png";return JSON.stringify({v:1,type:"image",content:$(t,e),attachments:[{path:t,name:e,mimeType:"image/png",kind:"image"}]})}function tt(t){const e=i.extname(t).toLowerCase();return e===".png"?"image/png":e===".jpg"||e===".jpeg"?"image/jpeg":e===".webp"?"image/webp":e===".gif"?"image/gif":"application/octet-stream"}export{v as buildImagePayload,$ as buildMarkdownImageRef,Z as buildToolPayload,w as encodeClaudeProjectDir,P as escapeMarkdownLabel,f as extractTextContent,tt as inferMimeType,W as isClaudeSubagentTranscript,k as isSameOrChildPath,Y as makeCursor,q as makeEventKey,E as normalizePathForCompare,G as normalizeText,d as normalizeToolText,Q as parseStructuredString,H as readClaudeEventCwd,V as readJsonlLines,M as readTimestamp,U as safeParse,O as safeStringify,D as shouldIgnoreClaudeProjectDir,X as shouldIgnoreClaudeTranscriptPath,K as shouldIgnoreNativeScanPath,j as summarizeToolResult};
|