@fly3366/deepjit 0.1.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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +134 -0
  3. package/README.zh.md +126 -0
  4. package/cordis.patch.yml +16 -0
  5. package/dist/collector.d.ts +31 -0
  6. package/dist/collector.js +258 -0
  7. package/dist/collector.js.map +1 -0
  8. package/dist/compiler/optimize.d.ts +30 -0
  9. package/dist/compiler/optimize.js +47 -0
  10. package/dist/compiler/optimize.js.map +1 -0
  11. package/dist/compiler/tiering.d.ts +22 -0
  12. package/dist/compiler/tiering.js +20 -0
  13. package/dist/compiler/tiering.js.map +1 -0
  14. package/dist/config.d.ts +42 -0
  15. package/dist/config.js +42 -0
  16. package/dist/config.js.map +1 -0
  17. package/dist/feedback.d.ts +43 -0
  18. package/dist/feedback.js +172 -0
  19. package/dist/feedback.js.map +1 -0
  20. package/dist/flow-executor.d.ts +46 -0
  21. package/dist/flow-executor.js +184 -0
  22. package/dist/flow-executor.js.map +1 -0
  23. package/dist/genai.d.ts +27 -0
  24. package/dist/genai.js +57 -0
  25. package/dist/genai.js.map +1 -0
  26. package/dist/i18n.d.ts +40 -0
  27. package/dist/i18n.js +81 -0
  28. package/dist/i18n.js.map +1 -0
  29. package/dist/index.d.ts +9 -0
  30. package/dist/index.js +170 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/metrics.d.ts +28 -0
  33. package/dist/metrics.js +68 -0
  34. package/dist/metrics.js.map +1 -0
  35. package/dist/miner.d.ts +14 -0
  36. package/dist/miner.js +93 -0
  37. package/dist/miner.js.map +1 -0
  38. package/dist/paths.d.ts +13 -0
  39. package/dist/paths.js +44 -0
  40. package/dist/paths.js.map +1 -0
  41. package/dist/status-tool.d.ts +21 -0
  42. package/dist/status-tool.js +113 -0
  43. package/dist/status-tool.js.map +1 -0
  44. package/dist/store.d.ts +122 -0
  45. package/dist/store.js +317 -0
  46. package/dist/store.js.map +1 -0
  47. package/dist/summarizer.d.ts +102 -0
  48. package/dist/summarizer.js +472 -0
  49. package/dist/summarizer.js.map +1 -0
  50. package/package.json +74 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DeepJIT Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,134 @@
1
+ <p align="center">
2
+ <img src="assets/banner.jpeg" alt="DeepJIT banner" width="800">
3
+ </p>
4
+
5
+ # DeepJIT
6
+
7
+ A JIT compiler plugin for [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) (dsh).
8
+
9
+ [中文文档](README.zh.md)
10
+
11
+ ## Overview
12
+
13
+ DeepJIT watches agent execution traces, mines recurring "hot" workflows, and
14
+ compiles them with an LLM into reusable **skills** (markdown) or **flows**
15
+ (step templates) — then feeds them back into the running harness, no restart.
16
+ It is for anyone who repeats similar multi-tool workflows and wants dsh to
17
+ turn them into fast, reusable assets.
18
+
19
+ ```
20
+ traces ──► SQLite ──► hot-path mining ──► LLM compile ──► skills / flows ──► dsh
21
+ ```
22
+
23
+ - Artifacts live under `~/.dsh/deepjit/` and hot-reload into dsh.
24
+ - JIT never compiles its own tools, so it can't feed on itself.
25
+ - Lifecycle (compiler-style): an AOT pass validates flows against the live tool
26
+ registry and constant-folds literal args; tiering promotes hot, reliable
27
+ skills to flows and deoptimizes unreliable flows; GC prunes stale artifacts.
28
+
29
+ ## Compatibility
30
+
31
+ | Item | Value |
32
+ |---|---|
33
+ | DSH version | `@deepseek-ai/dsh` `0.1.1-rc.2` (runtime-verified) |
34
+ | DSH mainline | `cd5ef814` (static-checked 2026-08-28; used APIs unchanged) |
35
+ | Verified commit | `5869674` (2026-08-13) |
36
+ | Node | `^22.19 \|\| >=24` |
37
+ | Profiles | `headless`, `web` |
38
+
39
+ dsh is pre-release; APIs may drift. Pins `@deepseek-ai/*` to `0.1.0-rc.6`.
40
+
41
+ ## Install / Uninstall
42
+
43
+ ```sh
44
+ # install (git, no npm release needed)
45
+ dsh plugin --profile web add github:fly3366/DeepJIT
46
+
47
+ # disable for one profile
48
+ dsh plugin --profile web remove deepjit
49
+
50
+ # fully remove local data
51
+ rm -rf ~/.dsh/deepjit
52
+ ```
53
+
54
+ ## Quick start
55
+
56
+ ```sh
57
+ dsh plugin --profile headless add github:fly3366/DeepJIT
58
+ DEEPSEEK_API_KEY=... dsh --profile headless "read package.json and tsconfig.json, then summarize"
59
+ # repeat similar tasks; deepjit mines and compiles hot flows automatically
60
+ dsh --profile headless "use deepjit_status to list compiled artifacts"
61
+ ```
62
+
63
+ ## Configuration
64
+
65
+ Override in `cordis.patch.yml` or a profile patch. Key options (full list in
66
+ [`src/config.ts`](src/config.ts)):
67
+
68
+ | Key | Default | Description |
69
+ |---|---|---|
70
+ | `enabled` | `true` | master switch |
71
+ | `summarizeIntervalMs` | `600000` | JIT cycle (mine + compile) |
72
+ | `minRepeat` | `3` | min occurrences for a hot sequence |
73
+ | `argumentAware` | `false` | include sorted arg-key signatures in mined sequences |
74
+ | `compileCandidates` | `1` | best-of-N candidates per compile; higher = better quality, more LLM calls |
75
+ | `minFlowSteps` | `2` | min tool steps a flow must have to be compiled |
76
+ | `minPatternValue` | `6` | min value score (`count × steps`) to justify a compile |
77
+ | `flushBatchSize` | `200` | trace rows per batched SQLite write |
78
+ | `maxPendingCalls` | `10000` | cap for in-memory pending/raw maps (bounds memory) |
79
+ | `minerMaxRows` | `20000` | max trace rows read per session per mining cycle |
80
+ | `transcriptMaxRows` | `2000` | max tool rows read per compile transcript |
81
+ | `gcEnabled` / `gcStaleMs` / `gcProtectMs` | `true` / 14d / 1d | GC: disable artifacts unused beyond `gcStaleMs` after a `gcProtectMs` grace |
82
+ | `dryRun` | `false` | publish artifacts as disabled; enable manually via `deepjit_status` |
83
+ | `traceRetentionMs` / `patternRetentionMs` | 7d / 7d | prune trace rows / stale uncompiled patterns older than this |
84
+ | `deoptMinUses` / `deoptMaxSuccessRate` | `5` / `0.5` | disable a flow used ≥N times with success rate ≤ this (deoptimization) |
85
+ | `qualityMinUses` / `minQuality` | `5` / `0` | disable active artifacts used ≥N times whose quality score < minQuality (0 = off) |
86
+ | `promoteMinUses` / `promoteMinSuccessRate` | `5` / `0.8` | recompile a hot, reliable skill's pattern as a flow (promotion) |
87
+ | `llmProvider` / `llmModel` | `deepseek-official` / (session) | compile model; empty = reuse session model |
88
+ | `locale` | `auto` | `en` / `zh` / `auto` (dsh locale → `LANG` → English) |
89
+
90
+ Sensitive: no keys are stored. The compile call uses dsh's credential service
91
+ or the launching environment's `DEEPSEEK_API_KEY`.
92
+
93
+ ## Permissions & data
94
+
95
+ - **Files**: writes only under `~/.dsh/deepjit/` (SQLite traces, skills, flows, log);
96
+ reads session JSONL via `ctx.sessionPersistence` for compile drill-down.
97
+ - **Network**: LLM calls go through dsh's `ctx.llm` (DeepSeek provider); no other network access.
98
+ - **Credentials**: none stored; resolved by dsh or the environment.
99
+ - **User data**: stores compact execution traces (tool args/results, message text).
100
+ - **Tools**: flow steps run through `ctx.tools.execute` and the normal permission gates.
101
+ - **Observability**: dsh's OTel telemetry covers agent sessions only; DeepJIT keeps its
102
+ own counters (traces flushed, compiles, LLM latency, GC/deopt/promote) and emits
103
+ **GenAI semantic-convention spans** (`gen_ai.*`: system/model/usage tokens) for each
104
+ LLM call. Read counters via `deepjit_status {action:"metrics"}`; spans export via
105
+ [dsh-o11y-plugin](https://github.com/fly3366/dsh-o11y-plugin) when present.
106
+
107
+ ## Troubleshooting
108
+
109
+ - Log: `~/.dsh/deepjit/deepjit.log`. Database: `~/.dsh/deepjit/deepjit.db`.
110
+ - `MISSING_CREDENTIAL` → export `DEEPSEEK_API_KEY` or store it in dsh's Models page.
111
+ - `TRANSPORT`/`NO_ADAPTER` on compile → usually a transient LLM call failure; deepjit retries and falls back to the next cycle.
112
+ - Roll back: `dsh plugin --profile <p> remove deepjit`, then `rm -rf ~/.dsh/deepjit`.
113
+
114
+ ## Development
115
+
116
+ ```sh
117
+ npm install && npm test # node:test, run natively via Node type stripping
118
+ npm run typecheck && npm run build
119
+ ```
120
+
121
+ See [CONTRIBUTING.md](CONTRIBUTING.md) and [AGENTS.md](AGENTS.md).
122
+
123
+ ## Related work
124
+
125
+ The "compile recurring workflows just-in-time" idea and the best-of-N compile
126
+ selection are inspired by
127
+ [JIT-Agent — Scaling Harness Intelligence via Just-in-Time Harness Evolution](https://arxiv.org/abs/2608.25593)
128
+ ([bingreeky/JIT](https://github.com/bingreeky/JIT)). DeepJIT adapts that
129
+ harness-evolution concept to run online inside a live dsh session, compiling
130
+ recurring tool flows into skills/flows rather than synthesizing whole harnesses.
131
+
132
+ ## License & security
133
+
134
+ [MIT](LICENSE). Report vulnerabilities privately per [SECURITY.md](SECURITY.md).
package/README.zh.md ADDED
@@ -0,0 +1,126 @@
1
+ <p align="center">
2
+ <img src="assets/banner.jpeg" alt="DeepJIT banner" width="800">
3
+ </p>
4
+
5
+ # DeepJIT
6
+
7
+ [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) (dsh) 的 JIT 编译插件。
8
+
9
+ [English](README.md) | 中文
10
+
11
+ ## 概述
12
+
13
+ DeepJIT 持续采集 agent 执行 trace,挖掘反复出现的"热点"流程,用 LLM 编译为
14
+ 可复用的 **skill**(markdown)或 **flow**(步骤模板),并自动回馈给运行中的
15
+ dsh,无需重启。适合经常重复相似多工具工作流、希望 dsh 把它们沉淀为可复用资产的人。
16
+
17
+ ```
18
+ trace ──► SQLite ──► 热点挖掘 ──► LLM 编译 ──► skill / flow ──► dsh
19
+ ```
20
+
21
+ - 产物存放在 `~/.dsh/deepjit/`,自动热加载进 dsh。
22
+ - JIT 不编译自己的工具,避免自噬循环。
23
+ - 生命周期(编译器式):AOT pass 对照实时工具注册表校验 flow 并常量折叠字面参数;
24
+ 分层(tiering)把高频可靠的 skill 升级为 flow、对不可靠 flow 去优化;GC 剪枝过期产物。
25
+
26
+ ## 兼容性
27
+
28
+ | 项 | 值 |
29
+ |---|---|
30
+ | DSH 版本 | `@deepseek-ai/dsh` `0.1.1-rc.2`(运行级验证) |
31
+ | DSH mainline | `cd5ef814`(2026-08-28 静态核对,所用 API 无变化) |
32
+ | 验证 commit | `5869674`(2026-08-13) |
33
+ | Node | `^22.19 \|\| >=24` |
34
+ | 适用 profile | `headless`、`web` |
35
+
36
+ dsh 处于预发布阶段,API 可能变化;依赖 pin 到 `@deepseek-ai/*` `0.1.0-rc.6`。
37
+
38
+ ## 安装 / 卸载
39
+
40
+ ```sh
41
+ # 安装(git 直装,无需 npm 发布)
42
+ dsh plugin --profile web add github:fly3366/DeepJIT
43
+
44
+ # 从某个 profile 移除
45
+ dsh plugin --profile web remove deepjit
46
+
47
+ # 彻底删除本地数据
48
+ rm -rf ~/.dsh/deepjit
49
+ ```
50
+
51
+ ## 快速开始
52
+
53
+ ```sh
54
+ dsh plugin --profile headless add github:fly3366/DeepJIT
55
+ DEEPSEEK_API_KEY=... dsh --profile headless "读取 package.json 和 tsconfig.json 并总结"
56
+ # 重复类似任务,deepjit 会自动挖掘并编译热点流程
57
+ dsh --profile headless "用 deepjit_status 列出已编译产物"
58
+ ```
59
+
60
+ ## 配置
61
+
62
+ 在 `cordis.patch.yml` 或 profile patch 中覆盖。主要配置项(完整列表见
63
+ [`src/config.ts`](src/config.ts)):
64
+
65
+ | 配置 | 默认 | 说明 |
66
+ |---|---|---|
67
+ | `enabled` | `true` | 总开关 |
68
+ | `summarizeIntervalMs` | `600000` | JIT 周期(挖掘+编译) |
69
+ | `minRepeat` | `3` | 热点序列最少出现次数 |
70
+ | `argumentAware` | `false` | 挖掘序列中加入排序后的参数键签名 |
71
+ | `compileCandidates` | `1` | 每次编译生成 N 个候选取最优;越大质量越好、LLM 调用越多 |
72
+ | `minFlowSteps` | `2` | 可编译流程的最少工具步数 |
73
+ | `minPatternValue` | `6` | 触发编译的最小价值分(`count × steps`) |
74
+ | `flushBatchSize` | `200` | 每批写入 SQLite 的 trace 行数 |
75
+ | `maxPendingCalls` | `10000` | 内存 pending/raw 映射上限(约束内存) |
76
+ | `minerMaxRows` | `20000` | 每会话每挖掘周期最多读取的 trace 行数 |
77
+ | `transcriptMaxRows` | `2000` | 每次编译转录最多读取的工具行数 |
78
+ | `gcEnabled` / `gcStaleMs` / `gcProtectMs` | `true` / 14天 / 1天 | GC:宽限期后禁用超过 `gcStaleMs` 未用的产物 |
79
+ | `dryRun` | `false` | 产物以禁用态发布,需经 `deepjit_status` 手动启用 |
80
+ | `traceRetentionMs` / `patternRetentionMs` | 7天 / 7天 | 剪枝超期的 trace 行 / 未编译 pattern |
81
+ | `deoptMinUses` / `deoptMaxSuccessRate` | `5` / `0.5` | 使用≥N 次且成功率≤此值的 flow 被禁用(去优化) |
82
+ | `qualityMinUses` / `minQuality` | `5` / `0` | 使用≥N 次且质量分<minQuality 的活跃产物被禁用(0=关) |
83
+ | `promoteMinUses` / `promoteMinSuccessRate` | `5` / `0.8` | 高频且可靠的 skill 其 pattern 重编译为 flow(升级) |
84
+ | `llmProvider` / `llmModel` | `deepseek-official` /(跟随会话) | 编译模型;留空=复用会话模型 |
85
+ | `locale` | `auto` | `en` / `zh` / `auto`(dsh locale → `LANG` → 英文) |
86
+
87
+ 敏感项:不存储任何密钥。编译调用走 dsh 凭据服务或启动环境的 `DEEPSEEK_API_KEY`。
88
+
89
+ ## 权限与数据
90
+
91
+ - **文件**:只写 `~/.dsh/deepjit/`(SQLite trace、skill、flow、日志);
92
+ 编译下钻时通过 `ctx.sessionPersistence` 读取会话 JSONL。
93
+ - **网络**:LLM 调用走 dsh 的 `ctx.llm`(DeepSeek provider),无其他网络访问。
94
+ - **凭据**:不存储,由 dsh 或环境解析。
95
+ - **用户数据**:存储紧凑执行 trace(工具参数/结果、消息文本)。
96
+ - **工具**:flow 每步走 `ctx.tools.execute` 与正常权限闸门。
97
+ - **可观测**:dsh 的 OTel 遥测只覆盖 agent 会话;DeepJIT 自维护计数器
98
+ (trace 刷写、编译、LLM 时延、GC/deopt/升级)。用
99
+ `deepjit_status {action:"metrics"}` 查看。
100
+
101
+ ## 故障排查
102
+
103
+ - 日志:`~/.dsh/deepjit/deepjit.log`;数据库:`~/.dsh/deepjit/deepjit.db`。
104
+ - `MISSING_CREDENTIAL` → 导出 `DEEPSEEK_API_KEY` 或在 dsh Models 页保存。
105
+ - 编译时 `TRANSPORT`/`NO_ADAPTER` → 多为 LLM 瞬时失败;deepjit 会重试并在下个周期兜底。
106
+ - 回滚:`dsh plugin --profile <p> remove deepjit`,再 `rm -rf ~/.dsh/deepjit`。
107
+
108
+ ## 开发
109
+
110
+ ```sh
111
+ npm install && npm test # node:test,Node 类型剥离原生运行
112
+ npm run typecheck && npm run build
113
+ ```
114
+
115
+ 见 [CONTRIBUTING.md](CONTRIBUTING.md)、[AGENTS.md](AGENTS.md)。
116
+
117
+ ## 相关工作
118
+
119
+ "即时编译重复工作流"的思路与 best-of-N 编译选择借鉴自
120
+ [JIT-Agent — Scaling Harness Intelligence via Just-in-Time Harness Evolution](https://arxiv.org/abs/2608.25593)
121
+ ([bingreeky/JIT](https://github.com/bingreeky/JIT))。DeepJIT 将该 harness 演化概念
122
+ 适配为在运行的 dsh 会话内在线编译重复工具流为 skill/flow,而非合成整个 harness。
123
+
124
+ ## 许可与安全
125
+
126
+ [MIT](LICENSE)。安全问题请按 [SECURITY.md](SECURITY.md) 私下报告。
@@ -0,0 +1,16 @@
1
+ # DeepJIT plugin bundle patch.
2
+ # Install: dsh plugin --profile <name> add /path/to/deepjit (pnpm link)
3
+ # or, once published: dsh plugin --profile <name> add @fly3366/deepjit
4
+ - insert:
5
+ - id: deepjit
6
+ name: '@fly3366/deepjit'
7
+
8
+ # Make the skill filesystem provider watch our isolated artifact directory so
9
+ # generated skills hot-reload without touching ~/.dsh/skills or project dirs.
10
+ # NOTE: this row overrides the base `skill-filesystem` row wholesale; if the
11
+ # base bundle later adds other config here, re-merge them.
12
+ - id: skill-filesystem
13
+ name: '@deepseek-ai/dsh-skill-filesystem'
14
+ config:
15
+ customSkillDirs:
16
+ - !!js 'String(process.env.DSH_HOME || (process.env.HOME || "") + "/.dsh") + "/deepjit/skills"'
@@ -0,0 +1,31 @@
1
+ import { DeepJitStore } from './store.ts';
2
+ /**
3
+ * Subscribes to session/event + tools/result, buffers compact trace rows in
4
+ * memory and flushes them to SQLite in batches.
5
+ */
6
+ export declare class TraceCollector {
7
+ private buffer;
8
+ private pendingCalls;
9
+ private rawValues;
10
+ private rowsByCallId;
11
+ private seenSessions;
12
+ private maxResultChars;
13
+ private flushBatchSize;
14
+ private maxPendingCalls;
15
+ private store;
16
+ private flush;
17
+ constructor(store: DeepJitStore, flush: () => void, maxResultChars: number, flushBatchSize: number, maxPendingCalls?: number);
18
+ /** Diagnostic: number of tool calls awaiting a result (bounded by maxPendingCalls). */
19
+ get pendingCount(): number;
20
+ /** Evict oldest entries so a map never grows past the configured cap. */
21
+ private capMap;
22
+ /** ctx.on('session/event') handler; event envelope: {type, seq, time, data, ...} */
23
+ handleEvent(sessionId: unknown, event: unknown): void;
24
+ /** ctx.on('tools/result') handler; captures the raw frozen value for a call. */
25
+ handleToolResult(exec: unknown, result: unknown): void;
26
+ /** Track invocation of compiled artifacts (separate from mining) for GC. */
27
+ private recordArtifactUsage;
28
+ private push;
29
+ /** Flush buffered rows to the store. */
30
+ flushSync(): void;
31
+ }
@@ -0,0 +1,258 @@
1
+ import { metrics } from "./metrics.js";
2
+ /** deepjit's own tools are excluded from traces to prevent JIT self-compilation loops. */
3
+ const JIT_TOOL_PREFIX = 'deepjit_';
4
+ function isJitTool(name) {
5
+ return name.startsWith(JIT_TOOL_PREFIX);
6
+ }
7
+ function truncate(text, maxChars) {
8
+ if (text.length <= maxChars)
9
+ return text;
10
+ return text.slice(0, maxChars) + `\n…[truncated ${text.length - maxChars} chars]`;
11
+ }
12
+ function stringify(value, maxChars) {
13
+ if (value === undefined || value === null)
14
+ return '';
15
+ try {
16
+ return truncate(JSON.stringify(value), maxChars);
17
+ }
18
+ catch {
19
+ return truncate(String(value), maxChars);
20
+ }
21
+ }
22
+ function textOfMessage(message, maxChars) {
23
+ // Message or { content: ContentBlock[] }; text blocks may be nested inside
24
+ // tool-result blocks, so collect recursively.
25
+ const content = Array.isArray(message) ? message : message?.content;
26
+ if (!Array.isArray(content))
27
+ return '';
28
+ const parts = [];
29
+ const walk = (blocks) => {
30
+ for (const block of blocks) {
31
+ const b = block;
32
+ if (b.type === 'text' && typeof b.text === 'string')
33
+ parts.push(b.text);
34
+ if (Array.isArray(b.content))
35
+ walk(b.content);
36
+ }
37
+ };
38
+ walk(content);
39
+ return truncate(parts.join('\n'), maxChars);
40
+ }
41
+ /**
42
+ * Subscribes to session/event + tools/result, buffers compact trace rows in
43
+ * memory and flushes them to SQLite in batches.
44
+ */
45
+ export class TraceCollector {
46
+ buffer = [];
47
+ pendingCalls = new Map();
48
+ rawValues = new Map();
49
+ rowsByCallId = new Map();
50
+ seenSessions = new Set();
51
+ maxResultChars;
52
+ flushBatchSize;
53
+ maxPendingCalls;
54
+ store;
55
+ flush;
56
+ constructor(store, flush, maxResultChars, flushBatchSize, maxPendingCalls = 10_000) {
57
+ this.store = store;
58
+ this.flush = flush;
59
+ this.maxResultChars = maxResultChars;
60
+ this.flushBatchSize = flushBatchSize;
61
+ this.maxPendingCalls = maxPendingCalls;
62
+ }
63
+ /** Diagnostic: number of tool calls awaiting a result (bounded by maxPendingCalls). */
64
+ get pendingCount() {
65
+ return this.pendingCalls.size;
66
+ }
67
+ /** Evict oldest entries so a map never grows past the configured cap. */
68
+ capMap(map) {
69
+ while (map.size > this.maxPendingCalls) {
70
+ const oldest = map.keys().next().value;
71
+ if (oldest === undefined)
72
+ break;
73
+ map.delete(oldest);
74
+ }
75
+ }
76
+ /** ctx.on('session/event') handler; event envelope: {type, seq, time, data, ...} */
77
+ handleEvent(sessionId, event) {
78
+ const env = event;
79
+ if (!env.type || typeof env.seq !== 'number' || typeof env.time !== 'number')
80
+ return;
81
+ const sid = String(sessionId);
82
+ const { type, seq, time } = env;
83
+ if (!this.seenSessions.has(sid)) {
84
+ this.seenSessions.add(sid);
85
+ if (this.seenSessions.size > this.maxPendingCalls) {
86
+ const oldest = this.seenSessions.keys().next().value;
87
+ if (oldest !== undefined)
88
+ this.seenSessions.delete(oldest);
89
+ }
90
+ this.store.upsertSession(sid, time);
91
+ }
92
+ switch (type) {
93
+ case 'user/message': {
94
+ const text = textOfMessage(env.data, this.maxResultChars);
95
+ if (text)
96
+ this.push({ session_id: sid, turn: 0, step: null, kind: 'user', seq, ts_ms: time, payload: JSON.stringify({ text }) });
97
+ break;
98
+ }
99
+ case 'assistant/message': {
100
+ const data = env.data;
101
+ const text = textOfMessage(data?.message, this.maxResultChars);
102
+ if (!text)
103
+ break;
104
+ this.push({
105
+ session_id: sid,
106
+ turn: Number(data?.turn ?? 0),
107
+ step: data?.step != null ? Number(data.step) : null,
108
+ kind: 'assistant',
109
+ seq,
110
+ ts_ms: time,
111
+ payload: JSON.stringify({ text, usage: data?.usage ?? undefined }),
112
+ });
113
+ break;
114
+ }
115
+ case 'tool/call': {
116
+ const data = env.data;
117
+ if (!data.callId)
118
+ break;
119
+ this.recordArtifactUsage(data.name, data.arguments);
120
+ if (data.name && isJitTool(data.name))
121
+ break;
122
+ this.pendingCalls.set(data.callId, {
123
+ tsMs: time,
124
+ name: String(data.name ?? ''),
125
+ args: truncate(String(data.arguments ?? ''), this.maxResultChars),
126
+ });
127
+ this.capMap(this.pendingCalls);
128
+ break;
129
+ }
130
+ case 'tool/result': {
131
+ const data = env.data;
132
+ const callId = data.callId ?? data.message?.source?.callId;
133
+ if (!callId)
134
+ break;
135
+ const call = this.pendingCalls.get(callId);
136
+ this.pendingCalls.delete(callId);
137
+ if (!call || isJitTool(call.name))
138
+ break;
139
+ const text = textOfMessage(data.message, this.maxResultChars);
140
+ const raw = this.rawValues.get(callId);
141
+ this.rawValues.delete(callId);
142
+ const payload = {
143
+ name: call?.name ?? '',
144
+ callId,
145
+ args: call?.args ?? '',
146
+ result_ok: !data.error,
147
+ result_text: text,
148
+ tool_ms: call ? Math.max(0, time - call.tsMs) : 0,
149
+ };
150
+ if (raw)
151
+ payload.raw_value = raw;
152
+ const row = {
153
+ session_id: sid,
154
+ turn: Number(data?.turn ?? 0),
155
+ step: data?.step != null ? Number(data.step) : null,
156
+ kind: 'tool',
157
+ seq,
158
+ ts_ms: time,
159
+ payload: JSON.stringify(payload),
160
+ };
161
+ const entry = this.push(row);
162
+ this.rowsByCallId.set(callId, entry);
163
+ break;
164
+ }
165
+ case 'turn/start':
166
+ case 'turn/end':
167
+ case 'step/start':
168
+ case 'step/end': {
169
+ const data = env.data;
170
+ this.push({
171
+ session_id: sid,
172
+ turn: Number(data?.turn ?? 0),
173
+ step: data?.step != null ? Number(data.step) : null,
174
+ kind: 'boundary',
175
+ seq,
176
+ ts_ms: time,
177
+ payload: JSON.stringify({ boundary: type, reason: data?.reason ?? null }),
178
+ });
179
+ break;
180
+ }
181
+ case 'request/context': {
182
+ const data = env.data;
183
+ this.store.setSessionContext(sid, data?.provider, data?.model);
184
+ break;
185
+ }
186
+ default:
187
+ break;
188
+ }
189
+ }
190
+ /** ctx.on('tools/result') handler; captures the raw frozen value for a call. */
191
+ handleToolResult(exec, result) {
192
+ const e = exec;
193
+ const r = result;
194
+ if (!e.callId)
195
+ return;
196
+ const value = stringify(r?.value, this.maxResultChars);
197
+ const entry = this.rowsByCallId.get(e.callId);
198
+ if (entry) {
199
+ // Row already buffered; patch the raw value in place.
200
+ try {
201
+ const payload = JSON.parse(entry.row.payload);
202
+ if (!payload.raw_value) {
203
+ payload.raw_value = value;
204
+ payload.result_ok = entry.row.kind === 'tool' ? !r?.isError : payload.result_ok;
205
+ entry.row.payload = JSON.stringify(payload);
206
+ entry.patched = true;
207
+ }
208
+ }
209
+ catch {
210
+ // keep the row as-is
211
+ }
212
+ }
213
+ else {
214
+ this.rawValues.set(e.callId, value);
215
+ this.capMap(this.rawValues);
216
+ }
217
+ }
218
+ /** Track invocation of compiled artifacts (separate from mining) for GC. */
219
+ recordArtifactUsage(name, argsJson) {
220
+ if (!name)
221
+ return;
222
+ try {
223
+ if (name === 'deepjit_flow') {
224
+ const flow = JSON.parse(argsJson ?? '{}').flow;
225
+ if (typeof flow === 'string' && flow)
226
+ this.store.recordUsage(flow);
227
+ }
228
+ else if (name === 'skill') {
229
+ const skill = JSON.parse(argsJson ?? '{}').name;
230
+ if (typeof skill === 'string' && skill.startsWith('deepjit-'))
231
+ this.store.recordUsage(skill);
232
+ }
233
+ }
234
+ catch {
235
+ // usage tracking is best-effort
236
+ }
237
+ }
238
+ push(row) {
239
+ const entry = { row };
240
+ this.buffer.push(entry);
241
+ if (this.buffer.length >= this.flushBatchSize)
242
+ this.flush();
243
+ return entry;
244
+ }
245
+ /** Flush buffered rows to the store. */
246
+ flushSync() {
247
+ if (this.buffer.length === 0)
248
+ return;
249
+ const rows = this.buffer.map((b) => b.row);
250
+ this.buffer = [];
251
+ this.rowsByCallId.clear();
252
+ this.rawValues.clear();
253
+ this.store.insertTraces(rows);
254
+ metrics.inc('flushes');
255
+ metrics.inc('traces_flushed', rows.length);
256
+ }
257
+ }
258
+ //# sourceMappingURL=collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collector.js","sourceRoot":"","sources":["../src/collector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Compiler "optimize" pass (AOT): validate a candidate flow against the live
3
+ * tool registry and constant-fold literal arguments ahead of time, so the
4
+ * runtime executor does less work and bad flows are rejected at compile time.
5
+ *
6
+ * Mirrors a compiler's middle-end: it never performs side effects, only
7
+ * analysis + rewriting of the IR (the step list).
8
+ */
9
+ export interface FlowStepIR {
10
+ tool: string;
11
+ args: Record<string, unknown>;
12
+ onError?: 'stop' | 'continue' | 'retry';
13
+ timeoutMs?: number;
14
+ }
15
+ export interface AotContext {
16
+ /** Live tool-registry lookup; nested deepjit_flow is always allowed. */
17
+ toolExists: (name: string) => boolean;
18
+ }
19
+ export interface OptimizedFlow {
20
+ steps: FlowStepIR[];
21
+ /** Number of argument values resolved at compile time (constant-folded). */
22
+ foldedLiterals: number;
23
+ /** Number of arguments left for runtime binding (${input.*}). */
24
+ dynamicBindings: number;
25
+ }
26
+ /**
27
+ * Validate and partially-evaluate a flow IR. Throws if a step references a
28
+ * tool that does not exist in the live registry (and is not a nested flow).
29
+ */
30
+ export declare function optimizeFlow(steps: FlowStepIR[], ctx: AotContext): OptimizedFlow;