asmgr 0.3.0 → 0.4.1
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 +5 -3
- package/dist/asmgr.mjs +66 -19
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -55,11 +55,11 @@ asmgr show --file /path/to/session.jsonl.zstd --format dialogue
|
|
|
55
55
|
asmgr html <session-id> --agent dsh -o dsh-session.html
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
以官方 [`dsh-v0.1.5-rc.1`](https://github.com/deepseek-ai/deepseek-harness/tree/dsh-v0.1.5-rc.1) 为基线,直接使用 `dsh-session-format-catalog` 的 v0→v3 解码/迁移及 `dsh-session/surface`
|
|
58
|
+
以官方 [`dsh-v0.1.5-rc.1`](https://github.com/deepseek-ai/deepseek-harness/tree/dsh-v0.1.5-rc.1) 为基线,直接使用 `dsh-session-format-catalog` 的 v0→v3 解码/迁移及 `dsh-session/surface` 的原始追加消息筛选。v4 存档复用官方 `dsh-session-format-v3-to-v4` 所依赖的 released v2 物理帧解码,再按 v4 词汇表(一等 tool-role 结果、`compact-checkpoint` 等生产者自有 source kind)投影;不升级已锁定的官方依赖。迁移在内存中进行,不依赖本机 DSH 安装、不启动插件、不改写源日志。主干包含直接用户输入、助手正文,以及原生或 PTC 调用中 `ask_user_question` 的题目、全部选项与匹配的回答;普通工具的参数和结果完全不显示。回答按官方格式记录,不额外推断回答者身份。
|
|
59
59
|
|
|
60
60
|
范围保持有限:不解释未知插件事件、注入上下文、失败模型尝试或任意 `meta`;不把压缩 replacement 当成新对话,不重复拼接 fork 的父会话。只显示官方 compact checkpoint 对应的摘要。图片/文件只显示占位符并提示损失;完整工具仍在 text/HTML/Markdown 中保留。HTML/Markdown 暂无独立的主干导出开关。
|
|
61
61
|
|
|
62
|
-
压缩日志需要运行时提供 Zstandard API(Node.js ≥ 22.15
|
|
62
|
+
压缩日志需要运行时提供 Zstandard API(Node.js ≥ 22.15);运行时缺少帧解码能力时明确报错,不把未读取内容当空会话。未知版本(含比已支持最高代 v4 更新的存档)、官方迁移器拒绝的旧日志、损坏或未写完的文件会报出路径与原因,不尝试自定义补救,也不会自动回退到旧一代文件。已知官方边界包括 v0 中的 `subagent/descriptor.version: 2`:最新迁移器明确拒绝它;不能仅把该字段改成 3 来冒充兼容。
|
|
63
63
|
|
|
64
64
|
## <a id="install"></a>安装
|
|
65
65
|
|
|
@@ -179,7 +179,9 @@ asmgr search "database migration" --session <session-id> # 只在一个会话
|
|
|
179
179
|
|
|
180
180
|
每条命中是一行 tab 分隔、以 `project` 列(cwd 最近的含 `.git` 祖先目录;找不到 `.git` 祖先时为 cwd 原值,无 cwd 时为 `(unscoped)`)开头:`project`、`agent`、`session-id`、`#条目`、`role/kind`、`摘录`。
|
|
181
181
|
|
|
182
|
-
`--session <id>` 把搜索限定到一个会话(先精确匹配 id
|
|
182
|
+
`--session <id>` 把搜索限定到一个会话(先精确匹配 id,否则按前缀匹配;DSH 的 id 是 `session-<uuid>`,直接给裸 uuid 也可以)——用来在**当前这个会话**里按关键词找模型回复,不必先用 `--file` 指路径。
|
|
183
|
+
|
|
184
|
+
跨会话搜索对每个会话独立解析:遇到官方迁移器拒绝或损坏的存档时,在 stderr 逐条报出路径与原因后跳过,不中断其余会话的检索;stdout 的命中行不受影响。
|
|
183
185
|
|
|
184
186
|
### `asmgr import`
|
|
185
187
|
|
package/dist/asmgr.mjs
CHANGED
|
@@ -43220,7 +43220,7 @@ var {
|
|
|
43220
43220
|
var BIN_NAME = "asmgr";
|
|
43221
43221
|
|
|
43222
43222
|
// src/cli/version.ts
|
|
43223
|
-
var VERSION = true ? "0.
|
|
43223
|
+
var VERSION = true ? "0.4.1" : devVersion();
|
|
43224
43224
|
|
|
43225
43225
|
// src/core/index.ts
|
|
43226
43226
|
import { stat as stat2 } from "node:fs/promises";
|
|
@@ -53417,6 +53417,7 @@ function deriveEventMessage2(event) {
|
|
|
53417
53417
|
}
|
|
53418
53418
|
|
|
53419
53419
|
// src/core/adapters/dsh.ts
|
|
53420
|
+
var DSH_NATIVE_VERSION = 4;
|
|
53420
53421
|
function isDshHeader(value) {
|
|
53421
53422
|
const row2 = record3(value);
|
|
53422
53423
|
return row2.type === "session" && typeof row2.version === "number" && typeof row2.id === "string";
|
|
@@ -53442,19 +53443,26 @@ function selectDshGenerations(paths) {
|
|
|
53442
53443
|
}
|
|
53443
53444
|
return [...other, ...selected.values()].sort();
|
|
53444
53445
|
}
|
|
53446
|
+
function readV4Header(header) {
|
|
53447
|
+
return { ...releasedV2SessionFormatCodec.decodeHeader({ ...record3(header), version: 2 }), version: DSH_NATIVE_VERSION };
|
|
53448
|
+
}
|
|
53445
53449
|
function headerRef(path3, header) {
|
|
53446
|
-
const
|
|
53447
|
-
if (
|
|
53450
|
+
const stored = record3(header).version;
|
|
53451
|
+
if (typeof stored === "number" && stored > DSH_NATIVE_VERSION) {
|
|
53452
|
+
throw new Error(`DSH \u4F1A\u8BDD\u4F7F\u7528\u66F4\u65B0\u7684\u5B58\u6863\u683C\u5F0F v${stored}\uFF0C\u672C\u7248\u672C\u6700\u9AD8\u652F\u6301 v${DSH_NATIVE_VERSION}`);
|
|
53453
|
+
}
|
|
53454
|
+
const decoded = stored === DSH_NATIVE_VERSION ? { storedVersion: DSH_NATIVE_VERSION, header: readV4Header(header) } : sessionFormatCatalog.readHeader(header);
|
|
53455
|
+
if ("reason" in decoded) throw new Error(decoded.reason);
|
|
53448
53456
|
const namedVersion = dshLogVersion(path3);
|
|
53449
|
-
if (namedVersion !== void 0 && namedVersion !==
|
|
53450
|
-
throw new Error(`DSH \u6587\u4EF6\u540D\u7248\u672C v${namedVersion} \u4E0E\u6587\u4EF6\u5934 v${
|
|
53457
|
+
if (namedVersion !== void 0 && namedVersion !== decoded.storedVersion) {
|
|
53458
|
+
throw new Error(`DSH \u6587\u4EF6\u540D\u7248\u672C v${namedVersion} \u4E0E\u6587\u4EF6\u5934 v${decoded.storedVersion} \u4E0D\u7B26`);
|
|
53451
53459
|
}
|
|
53452
53460
|
return {
|
|
53453
53461
|
agent: "dsh",
|
|
53454
|
-
id:
|
|
53462
|
+
id: decoded.header.id,
|
|
53455
53463
|
path: path3,
|
|
53456
|
-
cwd:
|
|
53457
|
-
startedAt: new Date(
|
|
53464
|
+
cwd: decoded.header.cwd,
|
|
53465
|
+
startedAt: new Date(decoded.header.createdAt).toISOString(),
|
|
53458
53466
|
source: { kind: "events", path: path3, lossy: false }
|
|
53459
53467
|
};
|
|
53460
53468
|
}
|
|
@@ -53472,6 +53480,19 @@ async function discoverDsh(root5) {
|
|
|
53472
53480
|
for (const path3 of files) refs.push(await refFromDshFile(path3));
|
|
53473
53481
|
return refs;
|
|
53474
53482
|
}
|
|
53483
|
+
function createDshRestore(headerRow) {
|
|
53484
|
+
if (record3(headerRow).version !== DSH_NATIVE_VERSION) {
|
|
53485
|
+
return sessionFormatCatalog.createRestore(headerRow, { recovery: "strict", validation: "current" });
|
|
53486
|
+
}
|
|
53487
|
+
const decoder = releasedV2SessionFormatCodec.createDecoder({ ...record3(headerRow), version: 2 }, "strict");
|
|
53488
|
+
const header = { ...decoder.header, version: DSH_NATIVE_VERSION };
|
|
53489
|
+
const collector = new SessionFormatEventCollector();
|
|
53490
|
+
return {
|
|
53491
|
+
header,
|
|
53492
|
+
decodeRow: (row2) => decoder.decodeRow(row2, collector),
|
|
53493
|
+
finish: () => ({ header, inheritedEventCount: decoder.finish(collector), events: collector.values })
|
|
53494
|
+
};
|
|
53495
|
+
}
|
|
53475
53496
|
async function parseDsh(ref) {
|
|
53476
53497
|
try {
|
|
53477
53498
|
let restore;
|
|
@@ -53479,7 +53500,7 @@ async function parseDsh(ref) {
|
|
|
53479
53500
|
for await (const row2 of iterateJsonl(ref.path)) {
|
|
53480
53501
|
if (!restore) {
|
|
53481
53502
|
source = headerRef(ref.path, row2);
|
|
53482
|
-
restore =
|
|
53503
|
+
restore = createDshRestore(row2);
|
|
53483
53504
|
} else restore.decodeRow(row2);
|
|
53484
53505
|
}
|
|
53485
53506
|
if (!restore) throw new Error("\u7A7A\u4F1A\u8BDD\u6587\u4EF6");
|
|
@@ -53595,7 +53616,8 @@ ${answer}`,
|
|
|
53595
53616
|
if (typeof data.compactionId === "string") summaries.set(data.compactionId, visibleText(data.summary));
|
|
53596
53617
|
} else if (raw2.type === "user/message" && isReplacementSurfaceEvent(event)) {
|
|
53597
53618
|
const source = record3(data.source);
|
|
53598
|
-
|
|
53619
|
+
const compacted = source.kind === "compact-checkpoint" || source.kind === "plugin" && source.plugin === "compact";
|
|
53620
|
+
if (compacted && typeof source.compactionId === "string") {
|
|
53599
53621
|
push3({ role: "event", kind: "compaction", text: summaries.get(source.compactionId) || "\u5BF9\u8BDD\u5DF2\u538B\u7F29", timestamp, rawType: raw2.type });
|
|
53600
53622
|
}
|
|
53601
53623
|
} else if (isAppendSurfaceEvent(event)) {
|
|
@@ -53609,24 +53631,24 @@ ${answer}`,
|
|
|
53609
53631
|
const text9 = visibleText(message.content);
|
|
53610
53632
|
if (text9.trim()) push3({ role: "assistant", kind: "message", text: text9, timestamp, rawType: raw2.type });
|
|
53611
53633
|
} else if (event.type === "tool/result") {
|
|
53612
|
-
const
|
|
53613
|
-
const linked = raw2.sourceEventSeqs?.map((seq) => callsBySeq.get(seq)).filter((value) => value !== void 0 && value.entry.tool?.callId ===
|
|
53614
|
-
const pending = linked.length > 1 ? void 0 : linked[0] ?? calls.get(callKey(
|
|
53615
|
-
if (pending) finishTool(pending,
|
|
53634
|
+
const result = toolResult(event.data.message);
|
|
53635
|
+
const linked = raw2.sourceEventSeqs?.map((seq) => callsBySeq.get(seq)).filter((value) => value !== void 0 && value.entry.tool?.callId === result.callId) ?? [];
|
|
53636
|
+
const pending = linked.length > 1 ? void 0 : linked[0] ?? calls.get(callKey(result.callId));
|
|
53637
|
+
if (pending) finishTool(pending, result.content, result.isError, event.data.error?.code, timestamp);
|
|
53616
53638
|
else push3({
|
|
53617
53639
|
role: "tool",
|
|
53618
53640
|
kind: "tool",
|
|
53619
|
-
text: visibleText(
|
|
53641
|
+
text: visibleText(result.content),
|
|
53620
53642
|
timestamp,
|
|
53621
53643
|
rawType: raw2.type,
|
|
53622
|
-
tool: { callId:
|
|
53644
|
+
tool: { callId: result.callId, result: { type: result.isError ? "failure" : "success", log: visibleText(result.content) } }
|
|
53623
53645
|
});
|
|
53624
53646
|
} else {
|
|
53625
53647
|
diagnostics.ignored++;
|
|
53626
53648
|
continue;
|
|
53627
53649
|
}
|
|
53628
53650
|
} else {
|
|
53629
|
-
if (
|
|
53651
|
+
if (isKnownDshEventType(raw2.type)) diagnostics.ignored++;
|
|
53630
53652
|
else {
|
|
53631
53653
|
diagnostics.unknown++;
|
|
53632
53654
|
unknown2.add(raw2.type);
|
|
@@ -53651,6 +53673,18 @@ ${answer}`,
|
|
|
53651
53673
|
function record3(value) {
|
|
53652
53674
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
53653
53675
|
}
|
|
53676
|
+
function toolResult(message) {
|
|
53677
|
+
const row2 = record3(message);
|
|
53678
|
+
if (row2.role === "tool") {
|
|
53679
|
+
return { callId: String(row2.toolCallId), content: row2.content, isError: row2.isError === true };
|
|
53680
|
+
}
|
|
53681
|
+
const wrapper = record3(Array.isArray(row2.content) ? row2.content[0] : void 0);
|
|
53682
|
+
return { callId: String(wrapper.toolCallId), content: wrapper.content, isError: wrapper.isError === true };
|
|
53683
|
+
}
|
|
53684
|
+
var V4_EVENT_TYPES = /* @__PURE__ */ new Set(["developer/message", "workspace/changes"]);
|
|
53685
|
+
function isKnownDshEventType(type) {
|
|
53686
|
+
return KNOWN_SESSION_EVENT_TYPES.has(type) || V4_EVENT_TYPES.has(type);
|
|
53687
|
+
}
|
|
53654
53688
|
function parseJson(value) {
|
|
53655
53689
|
if (typeof value !== "string") return value;
|
|
53656
53690
|
try {
|
|
@@ -54767,13 +54801,25 @@ async function findSession(id, agents = AGENTS, roots = {}) {
|
|
|
54767
54801
|
return findSessionAmong(await discoverSessions(agents, roots), id);
|
|
54768
54802
|
}
|
|
54769
54803
|
function findSessionAmong(refs, id) {
|
|
54770
|
-
|
|
54804
|
+
for (const needle of id.startsWith("session-") ? [id] : [id, `session-${id}`]) {
|
|
54805
|
+
const found = refs.find((session) => session.id === needle) ?? refs.find((session) => session.id.startsWith(needle));
|
|
54806
|
+
if (found) return found;
|
|
54807
|
+
}
|
|
54808
|
+
return void 0;
|
|
54771
54809
|
}
|
|
54772
54810
|
async function searchRefs(refs, query, limit = 20) {
|
|
54773
54811
|
const hits = [];
|
|
54774
54812
|
const needle = query.toLowerCase();
|
|
54813
|
+
let skipped = 0;
|
|
54775
54814
|
for (const ref of refs) {
|
|
54776
|
-
|
|
54815
|
+
let parsed;
|
|
54816
|
+
try {
|
|
54817
|
+
parsed = await parseSession(ref);
|
|
54818
|
+
} catch (error) {
|
|
54819
|
+
skipped++;
|
|
54820
|
+
console.error(`\u8DF3\u8FC7\u65E0\u6CD5\u89E3\u6790\u7684\u4F1A\u8BDD ${ref.path}\uFF1A${error instanceof Error ? error.message : String(error)}`);
|
|
54821
|
+
continue;
|
|
54822
|
+
}
|
|
54777
54823
|
for (const entry of parsed.entries) {
|
|
54778
54824
|
const searchText = timelineEntrySearchText(entry);
|
|
54779
54825
|
if (!searchText.toLowerCase().includes(needle)) continue;
|
|
@@ -54796,6 +54842,7 @@ async function searchRefs(refs, query, limit = 20) {
|
|
|
54796
54842
|
if (hits.length >= limit) return hits;
|
|
54797
54843
|
}
|
|
54798
54844
|
}
|
|
54845
|
+
if (skipped > 0) console.error(`\u5DF2\u8DF3\u8FC7 ${skipped} \u4E2A\u65E0\u6CD5\u89E3\u6790\u7684\u4F1A\u8BDD\uFF08\u8BE6\u89C1\u4E0A\u65B9\u5404\u6761\u8DEF\u5F84\u4E0E\u539F\u56E0\uFF09`);
|
|
54799
54846
|
return hits;
|
|
54800
54847
|
}
|
|
54801
54848
|
async function summarizeSession(ref) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "asmgr",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Search and render coding-agent sessions and public ChatGPT shares as self-contained HTML or Markdown.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"@deepseek-ai/dsh-session": "0.1.5-rc.1",
|
|
31
31
|
"@deepseek-ai/dsh-session-format": "0.1.5-rc.1",
|
|
32
32
|
"@deepseek-ai/dsh-session-format-catalog": "0.1.5-rc.1",
|
|
33
|
+
"@deepseek-ai/dsh-session-format-v2-to-v3": "0.1.5-rc.1",
|
|
33
34
|
"@semantic-release/changelog": "^6.0.3",
|
|
34
35
|
"@semantic-release/exec": "^7.0.3",
|
|
35
36
|
"@semantic-release/git": "^10.0.1",
|