@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 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`。
@@ -0,0 +1,4 @@
1
+ # DeepSeek Harness bundle patch for @1agents/session-reader
2
+ - insert:
3
+ - id: session-reader
4
+ name: '@1agents/session-reader'
@@ -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
+ }
@@ -0,0 +1,2 @@
1
+ export declare const inject: string[];
2
+ export declare function apply(_ctx: any): void;