@1agents/session-reader 0.6.2 → 0.7.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 +12 -0
- package/cordis.patch.yml +4 -0
- package/dist/bin/1session.js +26 -1
- package/dist/src/dsh/adapter.d.ts +18 -0
- package/dist/src/dsh/adapter.js +198 -0
- package/dist/src/dsh/client.d.ts +2 -0
- package/dist/src/dsh/client.js +18997 -0
- package/dist/src/dsh/index.d.ts +2 -0
- package/dist/src/dsh/index.js +2 -0
- package/dist/src/dsh/plugin.d.ts +3 -0
- package/dist/src/dsh/plugin.js +392 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/src/resolver.d.ts +7 -0
- package/dist/src/resolver.js +13 -8
- package/dist/src/store/read.d.ts +6 -2
- package/dist/src/store/read.js +14 -12
- package/dist/src/web/api.d.ts +72 -0
- package/dist/src/web/api.js +126 -0
- package/dist/src/web/app.d.ts +1 -0
- package/dist/src/web/app.js +18975 -0
- package/dist/src/web/server.d.ts +20 -0
- package/dist/src/web/server.js +126 -0
- package/package.json +25 -4
- package/skills/1session/SKILL.md +2 -1
- package/skills/1session/references/cli.md +16 -0
package/README.md
CHANGED
|
@@ -473,6 +473,18 @@ $ 1session graph ca8325e1
|
|
|
473
473
|
|
|
474
474
|
运行时捕获:若环境注入了 `SESSION_READER_CALLER_SESSION`,调用当下就直接落边(`observed / runtime:caller-env`),无需事后从历史里恢复。
|
|
475
475
|
|
|
476
|
+
## `1session web`:独立浏览器
|
|
477
|
+
|
|
478
|
+
没有 DSH 也能看同一套历史会话列表、对话预览和文件账本:
|
|
479
|
+
|
|
480
|
+
```bash
|
|
481
|
+
1session web # http://127.0.0.1:7780
|
|
482
|
+
1session web --open # 启动后打开默认浏览器
|
|
483
|
+
1session web --scope global # 默认列出全部工作区
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
列表只拉元数据,点击某一条会话后再加载对话与文件。这和 `1session serve`(DreamMate Network 的 JSON 服务)不是同一件事。
|
|
487
|
+
|
|
476
488
|
## `1session serve`:接入 DreamMate Network
|
|
477
489
|
|
|
478
490
|
把本地 Read Plane 原样暴露成网络能力——`1session overview <id>` 成为 `sessions.read`。
|
package/cordis.patch.yml
ADDED
package/dist/bin/1session.js
CHANGED
|
@@ -27,6 +27,8 @@ const USAGE = `1session — cross-agent session Read Plane
|
|
|
27
27
|
1session graph <session-id> [--json] 会话之间的引用关系
|
|
28
28
|
1session serve [--port 7777] [--host 127.0.0.1] [--token <t>] [--no-report]
|
|
29
29
|
起 HTTP Service,把本机会话接入 DreamMate Network
|
|
30
|
+
1session web [--port 7780] [--host 127.0.0.1] [--open] [--scope <path>|cwd|global]
|
|
31
|
+
起独立 Web 端,浏览历史会话列表、对话与文件(无需 DSH)
|
|
30
32
|
1session skill install|status|uninstall [--agent claude,codex,antigravity,grok,dsh]
|
|
31
33
|
[--copy] [--force] [--dry-run] [--json] 装到五家智能体的 skills 目录
|
|
32
34
|
1session search <query> [--scope <path>|cwd|global] [--since 24h] [--limit n] [--provider name]
|
|
@@ -48,7 +50,7 @@ Providers: antigravity (~/.gemini/antigravity/brain), claude (~/.claude/projects
|
|
|
48
50
|
/** Flags that never take a value, so they cannot swallow a positional. */
|
|
49
51
|
const BOOLEAN_FLAGS = new Set([
|
|
50
52
|
'json', 'failed', 'digest', 'regex', 'case', 'all', 'force', 'no-index', 'global',
|
|
51
|
-
'copy', 'dry-run', 'no-report', 'include-self',
|
|
53
|
+
'copy', 'dry-run', 'no-report', 'include-self', 'open',
|
|
52
54
|
]);
|
|
53
55
|
function parseArgs(argv) {
|
|
54
56
|
const [command = 'help', ...rest] = argv;
|
|
@@ -479,6 +481,29 @@ async function main() {
|
|
|
479
481
|
await new Promise(() => { });
|
|
480
482
|
break;
|
|
481
483
|
}
|
|
484
|
+
case 'web': {
|
|
485
|
+
const { serveWeb, DEFAULT_WEB_PORT } = await import('../src/web/server.js');
|
|
486
|
+
const scope = str(flags.scope) ?? (flags.global === true ? 'global' : 'cwd');
|
|
487
|
+
let cwd = process.cwd();
|
|
488
|
+
let defaultScope = 'cwd';
|
|
489
|
+
if (scope === 'global') {
|
|
490
|
+
defaultScope = 'global';
|
|
491
|
+
}
|
|
492
|
+
else if (scope !== 'cwd') {
|
|
493
|
+
cwd = canonicalizePath(scope);
|
|
494
|
+
if (!existsSync(cwd))
|
|
495
|
+
throw new Error(`--scope 目录不存在:${scope}`);
|
|
496
|
+
}
|
|
497
|
+
await serveWeb({
|
|
498
|
+
port: num(flags.port) ?? DEFAULT_WEB_PORT,
|
|
499
|
+
host: str(flags.host) ?? '127.0.0.1',
|
|
500
|
+
cwd,
|
|
501
|
+
defaultScope,
|
|
502
|
+
open: flags.open === true,
|
|
503
|
+
});
|
|
504
|
+
await new Promise(() => { });
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
482
507
|
case 'skill': {
|
|
483
508
|
const { describeState, installSkill, skillStatus, uninstallSkill, bundledSkillDir, } = await import('../src/skill.js');
|
|
484
509
|
const agents = str(flags.agent)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { NormalizedSession } from '../types.js';
|
|
2
|
+
export interface DshSessionEvent {
|
|
3
|
+
type: string;
|
|
4
|
+
seq: number;
|
|
5
|
+
time: number;
|
|
6
|
+
surfaceOp?: 'append';
|
|
7
|
+
data: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
export interface ConvertOptions {
|
|
10
|
+
/** Initial sequence number, defaults to 0 (DSH 0-based sequence convention). */
|
|
11
|
+
startSeq?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Converts a normalized session from @1agents/session-reader (across Claude, Codex,
|
|
15
|
+
* Antigravity, Grok, or DSH) into an ordered sequence of DSH SessionEvents suitable
|
|
16
|
+
* for direct ingestion and rendering by DSH Client UI (@deepseek-ai/dsh-client-ui-chat).
|
|
17
|
+
*/
|
|
18
|
+
export declare function convertSessionToDshEvents(session: NormalizedSession, options?: ConvertOptions): DshSessionEvent[];
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a normalized session from @1agents/session-reader (across Claude, Codex,
|
|
3
|
+
* Antigravity, Grok, or DSH) into an ordered sequence of DSH SessionEvents suitable
|
|
4
|
+
* for direct ingestion and rendering by DSH Client UI (@deepseek-ai/dsh-client-ui-chat).
|
|
5
|
+
*/
|
|
6
|
+
export function convertSessionToDshEvents(session, options = {}) {
|
|
7
|
+
const events = [];
|
|
8
|
+
let seq = options.startSeq ?? 0;
|
|
9
|
+
let currentTurn = 1;
|
|
10
|
+
let currentStep = 1;
|
|
11
|
+
let turnOpen = false;
|
|
12
|
+
let stepOpen = false;
|
|
13
|
+
const defaultTime = session.ref.createdAt
|
|
14
|
+
? Date.parse(session.ref.createdAt)
|
|
15
|
+
: Date.now();
|
|
16
|
+
function parseTime(timestamp) {
|
|
17
|
+
if (!timestamp)
|
|
18
|
+
return defaultTime;
|
|
19
|
+
const parsed = Date.parse(timestamp);
|
|
20
|
+
return isNaN(parsed) ? defaultTime : parsed;
|
|
21
|
+
}
|
|
22
|
+
function emit(type, data, time, surfaceOp) {
|
|
23
|
+
events.push({
|
|
24
|
+
type,
|
|
25
|
+
seq: seq++,
|
|
26
|
+
time,
|
|
27
|
+
...(surfaceOp ? { surfaceOp } : {}),
|
|
28
|
+
data,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function ensureTurnStart(turnNum, time) {
|
|
32
|
+
if (!turnOpen) {
|
|
33
|
+
emit('turn/start', { turn: turnNum }, time);
|
|
34
|
+
turnOpen = true;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function ensureStepStart(turnNum, stepNum, time) {
|
|
38
|
+
ensureTurnStart(turnNum, time);
|
|
39
|
+
if (!stepOpen) {
|
|
40
|
+
emit('step/start', { turn: turnNum, step: stepNum }, time);
|
|
41
|
+
stepOpen = true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function closeStep(turnNum, stepNum, time) {
|
|
45
|
+
if (stepOpen) {
|
|
46
|
+
emit('step/end', { turn: turnNum, step: stepNum }, time);
|
|
47
|
+
stepOpen = false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function closeTurn(turnNum, time, reason = 'completed') {
|
|
51
|
+
closeStep(turnNum, currentStep, time);
|
|
52
|
+
if (turnOpen) {
|
|
53
|
+
emit('turn/end', { turn: turnNum, reason: { kind: reason } }, time);
|
|
54
|
+
turnOpen = false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const providerName = session.ref.provider || 'external';
|
|
58
|
+
const modelName = session.stats.models[0] || 'assistant';
|
|
59
|
+
if (session.ref.title && session.ref.title.trim()) {
|
|
60
|
+
emit('session/title', {
|
|
61
|
+
title: session.ref.title.trim(),
|
|
62
|
+
messageSeqs: [],
|
|
63
|
+
source: { kind: 'user' },
|
|
64
|
+
}, defaultTime);
|
|
65
|
+
}
|
|
66
|
+
for (let i = 0; i < session.turns.length; i++) {
|
|
67
|
+
const turnEvent = session.turns[i];
|
|
68
|
+
const eventTime = parseTime(turnEvent.timestamp);
|
|
69
|
+
switch (turnEvent.kind) {
|
|
70
|
+
case 'user': {
|
|
71
|
+
// A new user prompt begins a new turn
|
|
72
|
+
if (turnOpen) {
|
|
73
|
+
closeTurn(currentTurn, eventTime);
|
|
74
|
+
currentTurn++;
|
|
75
|
+
currentStep = 1;
|
|
76
|
+
}
|
|
77
|
+
ensureStepStart(currentTurn, currentStep, eventTime);
|
|
78
|
+
emit('user/message', {
|
|
79
|
+
id: `msg-${turnEvent.id}`,
|
|
80
|
+
role: 'user',
|
|
81
|
+
content: [{ type: 'text', text: turnEvent.text ?? '' }],
|
|
82
|
+
source: { kind: 'user' },
|
|
83
|
+
}, eventTime, 'append');
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
case 'thinking': {
|
|
87
|
+
ensureStepStart(currentTurn, currentStep, eventTime);
|
|
88
|
+
const thinkingText = turnEvent.text ?? '';
|
|
89
|
+
if (thinkingText.trim()) {
|
|
90
|
+
emit('assistant/message', {
|
|
91
|
+
turn: currentTurn,
|
|
92
|
+
step: currentStep,
|
|
93
|
+
message: {
|
|
94
|
+
id: `asst-think-${turnEvent.id}`,
|
|
95
|
+
role: 'assistant',
|
|
96
|
+
content: [{ type: 'reasoning', text: thinkingText }],
|
|
97
|
+
source: { kind: 'model', provider: providerName, model: modelName },
|
|
98
|
+
},
|
|
99
|
+
stream: [
|
|
100
|
+
{
|
|
101
|
+
type: 'chunk',
|
|
102
|
+
time: eventTime,
|
|
103
|
+
chunk: {
|
|
104
|
+
type: 'reasoning-delta',
|
|
105
|
+
index: 0,
|
|
106
|
+
text: thinkingText,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
}, eventTime, 'append');
|
|
111
|
+
}
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
case 'tool_call': {
|
|
115
|
+
ensureStepStart(currentTurn, currentStep, eventTime);
|
|
116
|
+
const callId = turnEvent.id;
|
|
117
|
+
const toolName = turnEvent.toolName ?? 'tool';
|
|
118
|
+
const toolArgsStr = typeof turnEvent.toolArgs === 'string'
|
|
119
|
+
? turnEvent.toolArgs
|
|
120
|
+
: JSON.stringify(turnEvent.toolArgs ?? {});
|
|
121
|
+
emit('tool/call', {
|
|
122
|
+
turn: currentTurn,
|
|
123
|
+
step: currentStep,
|
|
124
|
+
callId,
|
|
125
|
+
name: toolName,
|
|
126
|
+
arguments: toolArgsStr,
|
|
127
|
+
}, eventTime);
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
case 'tool_result': {
|
|
131
|
+
ensureStepStart(currentTurn, currentStep, eventTime);
|
|
132
|
+
const callId = turnEvent.id;
|
|
133
|
+
const toolName = turnEvent.toolName ?? 'tool';
|
|
134
|
+
const resultContent = turnEvent.toolResult ?? '';
|
|
135
|
+
emit('tool/result', {
|
|
136
|
+
turn: currentTurn,
|
|
137
|
+
step: currentStep,
|
|
138
|
+
message: {
|
|
139
|
+
id: `tool-res-${callId}`,
|
|
140
|
+
role: 'user',
|
|
141
|
+
source: { kind: 'tool', callId, tool: toolName },
|
|
142
|
+
content: [
|
|
143
|
+
{
|
|
144
|
+
type: 'tool-result',
|
|
145
|
+
toolCallId: callId,
|
|
146
|
+
content: [{ type: 'text', text: resultContent }],
|
|
147
|
+
...(turnEvent.isError ? { isError: true } : {}),
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
...(turnEvent.exitCode !== undefined ? { meta: { exitCode: turnEvent.exitCode } } : {}),
|
|
152
|
+
}, eventTime, 'append');
|
|
153
|
+
// Tool execution concludes a step; next action starts a new step
|
|
154
|
+
closeStep(currentTurn, currentStep, eventTime);
|
|
155
|
+
currentStep++;
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case 'assistant': {
|
|
159
|
+
ensureStepStart(currentTurn, currentStep, eventTime);
|
|
160
|
+
const text = turnEvent.text ?? '';
|
|
161
|
+
emit('assistant/message', {
|
|
162
|
+
turn: currentTurn,
|
|
163
|
+
step: currentStep,
|
|
164
|
+
message: {
|
|
165
|
+
id: `asst-${turnEvent.id}`,
|
|
166
|
+
role: 'assistant',
|
|
167
|
+
content: [{ type: 'text', text }],
|
|
168
|
+
source: { kind: 'model', provider: providerName, model: modelName },
|
|
169
|
+
},
|
|
170
|
+
stream: [
|
|
171
|
+
{
|
|
172
|
+
type: 'chunk',
|
|
173
|
+
time: eventTime,
|
|
174
|
+
chunk: {
|
|
175
|
+
type: 'text-delta',
|
|
176
|
+
index: 0,
|
|
177
|
+
text,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
}, eventTime, 'append');
|
|
182
|
+
const nextEvent = session.turns[i + 1];
|
|
183
|
+
if (!nextEvent || nextEvent.kind === 'user') {
|
|
184
|
+
closeTurn(currentTurn, eventTime);
|
|
185
|
+
currentTurn++;
|
|
186
|
+
currentStep = 1;
|
|
187
|
+
}
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// Final cleanup if the last turn was still open
|
|
193
|
+
if (turnOpen) {
|
|
194
|
+
const lastTime = events.length > 0 ? events[events.length - 1].time : defaultTime;
|
|
195
|
+
closeTurn(currentTurn, lastTime);
|
|
196
|
+
}
|
|
197
|
+
return events;
|
|
198
|
+
}
|