@thincoder/core 0.9.1 → 0.9.3
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/CHANGELOG.md +63 -0
- package/LICENSE +21 -0
- package/README.md +90 -0
- package/advisor/loop.mjs +2 -2
- package/advisor/run.mjs +1 -1
- package/agent/completion.mjs +3 -1
- package/agent/family-tools.mjs +24 -11
- package/agent/helpers.mjs +11 -2
- package/agent/run-stages.mjs +27 -5
- package/agent/setup-reminders.mjs +67 -11
- package/agent/setup.mjs +6 -0
- package/agent/write-gate.mjs +5 -5
- package/agent-tools/advisor-async.mjs +4 -4
- package/agent-tools/advisor.mjs +3 -3
- package/agent-tools/async-discard.mjs +1 -1
- package/agent-tools/audit-block.mjs +106 -0
- package/agent-tools/batch-lifecycle.mjs +301 -0
- package/agent-tools/batch-segment.mjs +16 -263
- package/agent-tools/batch-skeleton.mjs +156 -0
- package/agent-tools/batch.mjs +410 -0
- package/agent-tools/context.mjs +174 -0
- package/agent-tools/eng.mjs +4 -0
- package/agent-tools/goal.mjs +7 -0
- package/agent-tools/parent-channel.mjs +18 -1
- package/agent-tools/plan.mjs +39 -5
- package/agent-tools/read-history.mjs +122 -24
- package/agent-tools/settings.mjs +4 -2
- package/agent-tools/subagent-async.mjs +3 -3
- package/agent-tools/subagent-spawn.mjs +29 -101
- package/agent-tools/task.mjs +11 -0
- package/agent-tools.mjs +9 -2
- package/agent.mjs +10 -4
- package/config.mjs +1 -1
- package/context.mjs +66 -121
- package/fts-text.mjs +41 -0
- package/generate-title.mjs +6 -6
- package/i18n.mjs +4 -4
- package/ledger-cmd.mjs +30 -7
- package/ledger-db.mjs +22 -2
- package/ledger-executors.mjs +103 -0
- package/ledger-surface.mjs +15 -8
- package/ledger.mjs +15 -4
- package/manifest.mjs +172 -60
- package/memory/core.mjs +4 -18
- package/memory/schema.mjs +4 -11
- package/package.json +22 -1
- package/prompts/advisor-design.md +1 -1
- package/prompts/advisor-round2.md +1 -1
- package/prompts/advisor-round3.md +1 -1
- package/prompts/common.md +3 -3
- package/prompts/discipline-engineering.md +17 -2
- package/prompts/persona-eng-coder.md +1 -1
- package/prompts/persona-eng-designer.md +1 -1
- package/prompts/persona-engineering.md +9 -6
- package/session-gc.mjs +129 -74
- package/session-index-build.mjs +298 -0
- package/session-index-cmd.mjs +61 -0
- package/session-index-pass.mjs +95 -0
- package/session-index-query.mjs +102 -0
- package/session-index.mjs +285 -0
- package/session-lifecycle.mjs +18 -5
- package/session-slots-manifest.mjs +55 -3
- package/session-stale.mjs +247 -0
- package/token-window.mjs +188 -0
- package/tools/bash.mjs +4 -15
- package/tools/execute.mjs +5 -13
- package/tools/git-checkpoint.mjs +1 -1
- package/tools/git-ext.mjs +23 -20
- package/tools/git-run.mjs +141 -0
- package/tools/git.mjs +56 -45
- package/tools/index.mjs +3 -1
- package/tools/process-tree.mjs +20 -0
- package/tools/shared.mjs +8 -4
- package/traces/trace-cleanup.mjs +109 -0
- package/traces/trace-store.mjs +32 -36
package/traces/trace-store.mjs
CHANGED
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
* **单遍序列化**:脱敏内联进输出缓冲(不构造复制图 + 二次全量字符串)——字段名/次序
|
|
21
21
|
* 与 `JSON.stringify` 形态同构(T-TR1 等价断言)。
|
|
22
22
|
* - 容量 / 清理(§2.5 #116 / A21 已裁 · 按建议——取 VSC 侧):**完整落盘**(不截断、
|
|
23
|
-
* 不丢行、不丢记录);**清理 = 每写一次 prune**(写盘成功后顺带 `
|
|
24
|
-
* 与写盘同在 fire-and-forget
|
|
23
|
+
* 不丢行、不丢记录);**清理 = 每写一次 prune**(写盘成功后顺带 `maybePruneTraces`——
|
|
24
|
+
* 与写盘同在 fire-and-forget 异步体内)。2026-09-21(TRACES.md §6.4):判据改**目录级三段梯**
|
|
25
|
+
* + 每写 prune **节流**;清理实现外提 `trace-cleanup.mjs`(本档包装保既有 import 面)。
|
|
25
26
|
* - seq = 当日目录内最大已有 seq + 1(D-TR3——跨会话/进程重启不覆写既有旧轨迹——
|
|
26
27
|
* 18.6.1 评审 #3);**进程内 seqCache(§23.3.2——消除逐调用同步扫目录)**:首次
|
|
27
28
|
* readdirSync 后进程内递增预留,目录被清理(retention)后取下界重扫一次(防御)。
|
|
@@ -35,7 +36,8 @@
|
|
|
35
36
|
* 记录不输出 round 字段(全设计无 round 定义——删——不发明无来源字段)。
|
|
36
37
|
*/
|
|
37
38
|
import { readdirSync, existsSync } from "node:fs"
|
|
38
|
-
import { appendFile, mkdir
|
|
39
|
+
import { appendFile, mkdir } from "node:fs/promises"
|
|
40
|
+
import { cleanupTraces as cleanupTracesImpl } from "./trace-cleanup.mjs"
|
|
39
41
|
import { join } from "node:path"
|
|
40
42
|
import { createHash } from "node:crypto"
|
|
41
43
|
import { configDir, loadConfig } from "../config.mjs"
|
|
@@ -87,17 +89,33 @@ export function tracesDirFor(dateStr) {
|
|
|
87
89
|
return join(tracesRoot(), dateStr)
|
|
88
90
|
}
|
|
89
91
|
|
|
90
|
-
// ─── 容量 / 清理策略(§2.5 #116 / A21 已裁 · 按建议——取 VSC
|
|
92
|
+
// ─── 容量 / 清理策略(§2.5 #116 / A21 已裁 · 按建议——取 VSC 侧)(§6.4 判据面)─────────
|
|
91
93
|
// 完整落盘:不截断、不丢行(无单消息/单记录额度,无在途丢弃);清理 = 每写一次 prune
|
|
92
|
-
//
|
|
94
|
+
// (写盘成功后顺带清理——与写盘同在 fire-and-forget 异步体内,永不阻塞 chat)。
|
|
93
95
|
|
|
94
|
-
// 进程内 seq 缓存(§23.3.2:dir →
|
|
95
|
-
// 目录被清理(retention)后取下界重扫一次(防御))。
|
|
96
|
+
// 进程内 seq 缓存(§23.3.2:dir → 已预留 max;首次读盘后递增预留,目录被清理后取下界重扫一次)。
|
|
96
97
|
const _seqCache = new Map()
|
|
98
|
+
// 每写 prune 节流(D-TR12 · §6.4):窗 = 10 分钟 + 在飞合并(同窗 3 连写 ⇒ 扫描 ≤1 次)。
|
|
99
|
+
export const PRUNE_THROTTLE_MS = 10 * 60_000
|
|
100
|
+
let _pruneAt = 0, _pruneInFlight = null
|
|
97
101
|
|
|
98
|
-
/** 测试缝:清进程内状态(seqCache
|
|
102
|
+
/** 测试缝:清进程内状态(seqCache + 节流窗/在飞——**跨用例残留**,用例须显式复位)。 */
|
|
99
103
|
export function _resetTraceStateForTest() {
|
|
100
104
|
_seqCache.clear()
|
|
105
|
+
_pruneAt = 0
|
|
106
|
+
_pruneInFlight = null
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** 每写 prune(`recordChatTrace` 写盘成功后调用):窗内 / 在飞 ⇒ 不发起新扫描。
|
|
110
|
+
* 返回 = 新扫描 promise(首次发起)/ `false`(窗内 / 在飞——不重复扫);`now` = 测试注入缝。 */
|
|
111
|
+
export function maybePruneTraces({ dir = tracesRoot(), retentionHours = 24, now = Date.now() } = {}) {
|
|
112
|
+
if (_pruneInFlight) return false // 在飞合并:同窗并发不重复发起扫描
|
|
113
|
+
if (now - _pruneAt < PRUNE_THROTTLE_MS) return false
|
|
114
|
+
_pruneAt = now
|
|
115
|
+
_pruneInFlight = cleanupTracesImpl({ dir, retentionHours })
|
|
116
|
+
.catch(() => 0) // 清理失败静默——不影响写盘(fire-and-forget 同纪律)
|
|
117
|
+
.finally(() => { _pruneInFlight = null })
|
|
118
|
+
return _pruneInFlight
|
|
101
119
|
}
|
|
102
120
|
|
|
103
121
|
function scanMaxSeq(dir) {
|
|
@@ -266,38 +284,16 @@ export function recordChatTrace(provider, opts = {}, result = null, error = null
|
|
|
266
284
|
await _traceHooks.append(join(dir, `${sessionKey}-${seq}.jsonl`), record + "\n")
|
|
267
285
|
let retentionHours = 24
|
|
268
286
|
try { retentionHours = loadConfig()?.traces?.retentionHours ?? 24 } catch { /* 默认 24h */ }
|
|
269
|
-
await
|
|
287
|
+
await maybePruneTraces({ dir: tracesRoot(), retentionHours }) // D-TR12:每写节流(窗内 ⇒ false 即返)
|
|
270
288
|
} catch {
|
|
271
289
|
// F-TR3:落盘/prune 失败静默降级——不抛错、不阻塞 chat() 返回
|
|
272
290
|
}
|
|
273
291
|
})()
|
|
274
292
|
}
|
|
275
293
|
|
|
276
|
-
/**
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
* 后顺带调用——fire-and-forget 异步体内);CLI 启动点的启动清理保留(本端不动)。
|
|
282
|
-
* 返回删除文件数。
|
|
283
|
-
*/
|
|
284
|
-
export async function cleanupTraces({ dir = tracesRoot(), retentionHours = 24 } = {}) {
|
|
285
|
-
const cutoff = Date.now() - retentionHours * 3_600_000
|
|
286
|
-
let days
|
|
287
|
-
try { days = await readdir(dir) } catch { return 0 } // 目录不存在/不可读 → 无事可做
|
|
288
|
-
let removed = 0
|
|
289
|
-
for (const day of days) {
|
|
290
|
-
const dayDir = join(dir, day)
|
|
291
|
-
try { if (!(await stat(dayDir)).isDirectory()) continue } catch { continue }
|
|
292
|
-
let names
|
|
293
|
-
try { names = await readdir(dayDir) } catch { continue }
|
|
294
|
-
for (const n of names) {
|
|
295
|
-
if (!n.endsWith(".jsonl")) continue
|
|
296
|
-
try {
|
|
297
|
-
if ((await stat(join(dayDir, n))).mtimeMs < cutoff) { await unlink(join(dayDir, n)); removed++ }
|
|
298
|
-
} catch { /* 单个文件失败不影响其余 */ }
|
|
299
|
-
}
|
|
300
|
-
try { if ((await readdir(dayDir)).length === 0) await rmdir(dayDir) } catch {}
|
|
301
|
-
}
|
|
302
|
-
return removed
|
|
294
|
+
/** D-TR10 清理面(D-TR11 目录级三段梯)——实现外提 `traces/trace-cleanup.mjs`;此处包装保
|
|
295
|
+
* 既有 import 面与缺省 `dir`(`tracesRoot()` 单源——测试经 `THINCODER_TRACES_DIR` 隔离)。
|
|
296
|
+
* 调用点 = 每写 prune(经 `maybePruneTraces`)+ 启动清理(壳侧);返回删除文件数。 */
|
|
297
|
+
export function cleanupTraces({ dir = tracesRoot(), retentionHours = 24 } = {}) {
|
|
298
|
+
return cleanupTracesImpl({ dir, retentionHours })
|
|
303
299
|
}
|