jeo-code 0.5.9 → 0.5.10
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.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/package.json +1 -1
- package/src/tui/components/transcript.ts +44 -14
package/README.ja.md
CHANGED
|
@@ -150,11 +150,11 @@ CI は `.github/workflows/npm-publish.yml` で公開します — GitHub リリ
|
|
|
150
150
|
## 変更履歴 (Changelog)
|
|
151
151
|
|
|
152
152
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
153
|
+
- **[0.5.10]** (2026-06-15) — `/resume` transcript no longer dumps raw JSON for batched tool calls.
|
|
153
154
|
- **[0.5.9]** (2026-06-15) — Bounded per-frame wrap for the live thinking/tool-output blocks — re-render cost no longer grows with stream length.
|
|
154
155
|
- **[0.5.8]** (2026-06-15) — Native Opik observability for the turn loop (opt-in `JEO_OPIK`, pure-TS no-op when unset) + autopilot convergence tracking.
|
|
155
156
|
- **[0.5.7]** (2026-06-15) — `/model` picker is default-only, `/clear` resets to the initial screen, ESC clears the input box, and a launch process-listener leak is fixed.
|
|
156
157
|
- **[0.5.6]** (2026-06-15) — `/model` sets only the default thinking; per-role reasoning moved to `/agents`.
|
|
157
|
-
- **[0.5.5]** (2026-06-15) — Full multi-line visibility — the input box scrolls to the caret and the submitted card shows every line.
|
|
158
158
|
|
|
159
159
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
160
160
|
<!-- CHANGELOG:END -->
|
package/README.ko.md
CHANGED
|
@@ -150,11 +150,11 @@ CI는 `.github/workflows/npm-publish.yml`로 배포합니다 — GitHub 릴리
|
|
|
150
150
|
## 변경 이력 (Changelog)
|
|
151
151
|
|
|
152
152
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
153
|
+
- **[0.5.10]** (2026-06-15) — `/resume` transcript no longer dumps raw JSON for batched tool calls.
|
|
153
154
|
- **[0.5.9]** (2026-06-15) — Bounded per-frame wrap for the live thinking/tool-output blocks — re-render cost no longer grows with stream length.
|
|
154
155
|
- **[0.5.8]** (2026-06-15) — Native Opik observability for the turn loop (opt-in `JEO_OPIK`, pure-TS no-op when unset) + autopilot convergence tracking.
|
|
155
156
|
- **[0.5.7]** (2026-06-15) — `/model` picker is default-only, `/clear` resets to the initial screen, ESC clears the input box, and a launch process-listener leak is fixed.
|
|
156
157
|
- **[0.5.6]** (2026-06-15) — `/model` sets only the default thinking; per-role reasoning moved to `/agents`.
|
|
157
|
-
- **[0.5.5]** (2026-06-15) — Full multi-line visibility — the input box scrolls to the caret and the submitted card shows every line.
|
|
158
158
|
|
|
159
159
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
160
160
|
<!-- CHANGELOG:END -->
|
package/README.md
CHANGED
|
@@ -150,11 +150,11 @@ Required npm token permissions (repository secret `NPM_TOKEN`):
|
|
|
150
150
|
## Changelog
|
|
151
151
|
|
|
152
152
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
153
|
+
- **[0.5.10]** (2026-06-15) — `/resume` transcript no longer dumps raw JSON for batched tool calls.
|
|
153
154
|
- **[0.5.9]** (2026-06-15) — Bounded per-frame wrap for the live thinking/tool-output blocks — re-render cost no longer grows with stream length.
|
|
154
155
|
- **[0.5.8]** (2026-06-15) — Native Opik observability for the turn loop (opt-in `JEO_OPIK`, pure-TS no-op when unset) + autopilot convergence tracking.
|
|
155
156
|
- **[0.5.7]** (2026-06-15) — `/model` picker is default-only, `/clear` resets to the initial screen, ESC clears the input box, and a launch process-listener leak is fixed.
|
|
156
157
|
- **[0.5.6]** (2026-06-15) — `/model` sets only the default thinking; per-role reasoning moved to `/agents`.
|
|
157
|
-
- **[0.5.5]** (2026-06-15) — Full multi-line visibility — the input box scrolls to the caret and the submitted card shows every line.
|
|
158
158
|
|
|
159
159
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
160
160
|
<!-- CHANGELOG:END -->
|
package/README.zh.md
CHANGED
|
@@ -150,11 +150,11 @@ CI 通过 `.github/workflows/npm-publish.yml` 发布 — GitHub 发布 release
|
|
|
150
150
|
## 更新日志 (Changelog)
|
|
151
151
|
|
|
152
152
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
153
|
+
- **[0.5.10]** (2026-06-15) — `/resume` transcript no longer dumps raw JSON for batched tool calls.
|
|
153
154
|
- **[0.5.9]** (2026-06-15) — Bounded per-frame wrap for the live thinking/tool-output blocks — re-render cost no longer grows with stream length.
|
|
154
155
|
- **[0.5.8]** (2026-06-15) — Native Opik observability for the turn loop (opt-in `JEO_OPIK`, pure-TS no-op when unset) + autopilot convergence tracking.
|
|
155
156
|
- **[0.5.7]** (2026-06-15) — `/model` picker is default-only, `/clear` resets to the initial screen, ESC clears the input box, and a launch process-listener leak is fixed.
|
|
156
157
|
- **[0.5.6]** (2026-06-15) — `/model` sets only the default thinking; per-role reasoning moved to `/agents`.
|
|
157
|
-
- **[0.5.5]** (2026-06-15) — Full multi-line visibility — the input box scrolls to the caret and the submitted card shows every line.
|
|
158
158
|
|
|
159
159
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
160
160
|
<!-- CHANGELOG:END -->
|
package/package.json
CHANGED
|
@@ -46,6 +46,20 @@ function firstToolResultLine(text: string | undefined): string {
|
|
|
46
46
|
.slice(0, 96) ?? "";
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
const TOOL_RESULT_GLOBAL = /^Tool \[([^\]]+)\] result \((ok|fail)\):/gm;
|
|
50
|
+
/** Split a tool-result user message — which for a BATCH holds several
|
|
51
|
+
* `Tool [x] result (ok|fail):` blocks joined by blank lines — into per-call
|
|
52
|
+
* verdicts in the order the engine emitted them (= the batch's call order). */
|
|
53
|
+
function parseToolVerdicts(text: string | undefined): { tool: string; status: string; firstLine: string }[] {
|
|
54
|
+
if (!text) return [];
|
|
55
|
+
const matches = [...text.matchAll(TOOL_RESULT_GLOBAL)];
|
|
56
|
+
return matches.map((mt, k) => {
|
|
57
|
+
const start = mt.index ?? 0;
|
|
58
|
+
const end = k + 1 < matches.length ? (matches[k + 1]!.index ?? text.length) : text.length;
|
|
59
|
+
return { tool: mt[1]!, status: mt[2]!, firstLine: firstToolResultLine(text.slice(start, end)) };
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
49
63
|
/** Format engine history as a scrollback-friendly transcript. */
|
|
50
64
|
export function formatTranscript(messages: readonly Message[], opts: TranscriptOptions = {}): string[] {
|
|
51
65
|
const color = opts.color !== false;
|
|
@@ -92,25 +106,41 @@ export function formatTranscript(messages: readonly Message[], opts: TranscriptO
|
|
|
92
106
|
lines.push(...clipBody(m.content, bodyCap));
|
|
93
107
|
continue;
|
|
94
108
|
}
|
|
95
|
-
// assistant:
|
|
96
|
-
|
|
109
|
+
// assistant: one or more JSON tool calls (compact ledger lines) or a prose reply.
|
|
110
|
+
// Handles BOTH the single `{tool,arguments}` form AND the batched `{tools:[...]}`
|
|
111
|
+
// form — the batch case previously parsed to no `tool` field, fell through, and
|
|
112
|
+
// dumped the raw JSON object into the transcript (the "/resume shows JSON" bug).
|
|
113
|
+
let parsed: { tool?: unknown; tools?: unknown; arguments?: unknown } | null = null;
|
|
97
114
|
try {
|
|
98
|
-
const
|
|
99
|
-
if (
|
|
115
|
+
const p: unknown = JSON.parse(m.content);
|
|
116
|
+
if (p && typeof p === "object") parsed = p as { tool?: unknown; tools?: unknown; arguments?: unknown };
|
|
100
117
|
} catch { /* prose reply */ }
|
|
101
|
-
|
|
102
|
-
|
|
118
|
+
const calls: { tool: string; arguments?: unknown }[] =
|
|
119
|
+
parsed && typeof parsed.tool === "string"
|
|
120
|
+
? [{ tool: parsed.tool, arguments: parsed.arguments }]
|
|
121
|
+
: parsed && Array.isArray(parsed.tools)
|
|
122
|
+
? (parsed.tools as { tool?: unknown; arguments?: unknown }[])
|
|
123
|
+
.filter(c => c && typeof c.tool === "string")
|
|
124
|
+
.map(c => ({ tool: c.tool as string, arguments: c.arguments }))
|
|
125
|
+
: [];
|
|
126
|
+
const toolCalls = calls.filter(c => c.tool !== "done");
|
|
127
|
+
if (toolCalls.length > 0) {
|
|
128
|
+
// The matching `Tool [x] result (ok|fail)` user message follows; for a batch it
|
|
129
|
+
// is ONE message with several blocks. Parse verdicts in call order.
|
|
103
130
|
const next = messages[i + 1];
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
131
|
+
const verdicts = next?.role === "user" ? parseToolVerdicts(next.content) : [];
|
|
132
|
+
toolCalls.forEach((c, ci) => {
|
|
133
|
+
const v = verdicts[ci] ?? verdicts.find(x => x.tool === c.tool);
|
|
134
|
+
const mark = v?.status === "fail" ? red(bad) : green(ok);
|
|
135
|
+
const title = summarizeForgeInvocation(c.tool, c.arguments).title;
|
|
136
|
+
const suffix = v?.firstLine ? dim(` — ${v.firstLine}`) : "";
|
|
137
|
+
lines.push(` ${mark} ${title}${suffix}`);
|
|
138
|
+
});
|
|
110
139
|
continue;
|
|
111
140
|
}
|
|
112
|
-
|
|
113
|
-
|
|
141
|
+
// A lone `done` (show its reason) or a plain prose reply.
|
|
142
|
+
const reason = parsed
|
|
143
|
+
? String((parsed.arguments as { reason?: unknown } | undefined)?.reason ?? "")
|
|
114
144
|
: m.content;
|
|
115
145
|
if (!reason.trim()) continue;
|
|
116
146
|
lines.push(`${magentaBold(`jeo ${jeoMark}`)}`);
|