jeo-code 0.12.11 → 0.12.13

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 CHANGED
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  The README mirrors the latest 5 entries — regenerate with `bun run changelog:sync`.
9
9
 
10
+ ## [0.12.13] - 2026-11-03
11
+
12
+ ### Fixed
13
+ - **Discord messenger progress** — update the status message with only the latest activity on one line instead of accumulating previous steps.
14
+
15
+ ## [0.12.12] - 2026-11-03
16
+
17
+ ### Fixed
18
+ - **Discord messenger progress** — show safe, throttled step and tool updates in a single request status message, retaining recent activity and marking completion, failure, or cancellation without exposing tool arguments or output.
19
+
10
20
  ## [0.12.10] - 2026-11-02
11
21
  ## [0.12.11] - 2026-11-02
12
22
 
package/README.ja.md CHANGED
@@ -422,11 +422,11 @@ CI は `.github/workflows/npm-publish.yml` で公開します — GitHub リリ
422
422
  ## 変更履歴 (Changelog)
423
423
 
424
424
  <!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
425
+ - **[0.12.13]** (2026-11-03)
426
+ - **[0.12.12]** (2026-11-03)
425
427
  - **[0.12.10]** (2026-11-02)
426
428
  - **[0.12.11]** (2026-11-02)
427
429
  - **[0.12.9]** (2026-11-02)
428
- - **[0.12.7]** (2026-10-18) — Repair desktop screenshot vision feedback, macOS scrolling, complete drag gestures, and keyboard normalization.
429
- - **[0.12.6]** (2026-10-17) — Preserve OpenAI subscription authentication behind configured proxies, isolate account catalogs, and give provider-specific recovery instructions while retaining Antigravity OAuth calls.
430
430
 
431
431
  See [CHANGELOG.md](CHANGELOG.md) for the full history.
432
432
  <!-- CHANGELOG:END -->
package/README.ko.md CHANGED
@@ -477,11 +477,11 @@ CI는 `.github/workflows/npm-publish.yml`로 배포합니다 — GitHub 릴리
477
477
  ## 변경 이력 (Changelog)
478
478
 
479
479
  <!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
480
+ - **[0.12.13]** (2026-11-03)
481
+ - **[0.12.12]** (2026-11-03)
480
482
  - **[0.12.10]** (2026-11-02)
481
483
  - **[0.12.11]** (2026-11-02)
482
484
  - **[0.12.9]** (2026-11-02)
483
- - **[0.12.7]** (2026-10-18) — Repair desktop screenshot vision feedback, macOS scrolling, complete drag gestures, and keyboard normalization.
484
- - **[0.12.6]** (2026-10-17) — Preserve OpenAI subscription authentication behind configured proxies, isolate account catalogs, and give provider-specific recovery instructions while retaining Antigravity OAuth calls.
485
485
 
486
486
  See [CHANGELOG.md](CHANGELOG.md) for the full history.
487
487
  <!-- CHANGELOG:END -->
package/README.md CHANGED
@@ -466,11 +466,11 @@ Huge thanks to [gajae-code](https://github.com/Yeachan-Heo/gajae-code) for the i
466
466
  ## Changelog
467
467
 
468
468
  <!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
469
+ - **[0.12.13]** (2026-11-03)
470
+ - **[0.12.12]** (2026-11-03)
469
471
  - **[0.12.10]** (2026-11-02)
470
472
  - **[0.12.11]** (2026-11-02)
471
473
  - **[0.12.9]** (2026-11-02)
472
- - **[0.12.7]** (2026-10-18) — Repair desktop screenshot vision feedback, macOS scrolling, complete drag gestures, and keyboard normalization.
473
- - **[0.12.6]** (2026-10-17) — Preserve OpenAI subscription authentication behind configured proxies, isolate account catalogs, and give provider-specific recovery instructions while retaining Antigravity OAuth calls.
474
474
 
475
475
  See [CHANGELOG.md](CHANGELOG.md) for the full history.
476
476
  <!-- CHANGELOG:END -->
package/README.zh.md CHANGED
@@ -420,11 +420,11 @@ CI 通过 `.github/workflows/npm-publish.yml` 发布 — GitHub 发布 release
420
420
  ## 更新日志 (Changelog)
421
421
 
422
422
  <!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
423
+ - **[0.12.13]** (2026-11-03)
424
+ - **[0.12.12]** (2026-11-03)
423
425
  - **[0.12.10]** (2026-11-02)
424
426
  - **[0.12.11]** (2026-11-02)
425
427
  - **[0.12.9]** (2026-11-02)
426
- - **[0.12.7]** (2026-10-18) — Repair desktop screenshot vision feedback, macOS scrolling, complete drag gestures, and keyboard normalization.
427
- - **[0.12.6]** (2026-10-17) — Preserve OpenAI subscription authentication behind configured proxies, isolate account catalogs, and give provider-specific recovery instructions while retaining Antigravity OAuth calls.
428
428
 
429
429
  See [CHANGELOG.md](CHANGELOG.md) for the full history.
430
430
  <!-- CHANGELOG:END -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jeo-code",
3
- "version": "0.12.11",
3
+ "version": "0.12.13",
4
4
  "description": "Clean, highly optimized AI coding agent using spec-first loop",
5
5
  "type": "module",
6
6
 
@@ -114,7 +114,7 @@ import type { ImageAttachment } from "../ai/types";
114
114
  import { renderMarkdownTables } from "../tui/components/markdown-table";
115
115
 
116
116
  import { stripMarkdown } from "../tui/components/markdown-text";
117
- import { summarizeForgeInvocation } from "../tui/components/forge";
117
+ import { createMessengerActivityEvents } from "../messenger/activity";
118
118
  import { formatDuration, formatUsage } from "../tui/components/duration";
119
119
 
120
120
  import { bashTool } from "../agent/tools";
@@ -1034,28 +1034,9 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
1034
1034
  // `step N/M` display seed: the explicit --max-steps cap, else the dynamic budget's
1035
1035
  // rolling base — the engine's onBudget event keeps the denominator honest as it grows.
1036
1036
  const initialStepLimit = flags.maxSteps > 0 ? flags.maxSteps : initialDynamicStepLimit();
1037
- // Plain (non-TTY / --no-tui) progress sink — the cmd-mode equivalent of the live TUI.
1037
+ // Literal workers send progress without exposing tool arguments or output.
1038
1038
  const streamEvents = (flags.literalPrompt || flags.literalWorker)
1039
- ? {
1040
- onStep: () => {
1041
- process.stderr.write("JEO_MESSENGER_STEP\n");
1042
- },
1043
- onAssistant: (_raw: string, invocation: any) => {
1044
- if (invocation?.tool) {
1045
- const summary = summarizeForgeInvocation(invocation.tool, invocation.arguments);
1046
- process.stderr.write(`JEO_MESSENGER_ACTIVITY ${summary.title}\n`);
1047
- }
1048
- },
1049
- onToolResult: (tool: string) => {
1050
- process.stderr.write(`JEO_MESSENGER_ACTIVITY Finished ${tool}\n`);
1051
- },
1052
- onNotice: (msg: string) => {
1053
- process.stderr.write(`JEO_MESSENGER_ACTIVITY ${msg}\n`);
1054
- },
1055
- onReasoningStart: () => {
1056
- process.stderr.write("JEO_MESSENGER_ACTIVITY Thinking...\n");
1057
- },
1058
- }
1039
+ ? createMessengerActivityEvents(text => process.stderr.write(`JEO_MESSENGER_ACTIVITY ${text}\n`))
1059
1040
  : createStreamEvents(initialStepLimit);
1060
1041
  let queueBusyInput: ((chunk: string) => boolean) | undefined;
1061
1042
  let queueBusyPasteActive: (() => boolean) | undefined;
@@ -1,30 +1,26 @@
1
1
  import type { AgentLoopEvents, ToolInvocation } from "../agent/engine";
2
2
  import type { MessengerActivityReporter } from "./types";
3
3
 
4
- /**
5
- * Derive one-line progress from session events: the model's declared tool intent (falling back to the
6
- * tool name) and long-running lifecycle notices. Raw tool arguments, results and errors never surface.
7
- */
4
+ /** Derive bounded progress without exposing tool arguments, results, or provider errors. */
8
5
  export function createMessengerActivityEvents(report: MessengerActivityReporter): AgentLoopEvents {
9
6
  let step = 0;
10
7
  return {
8
+ onStep(current) {
9
+ step = current;
10
+ report(`Step ${step} · Thinking`);
11
+ },
11
12
  onAssistant(_raw: string, invocation: ToolInvocation | null) {
12
13
  if (!invocation || invocation.tool === "done") return;
13
- step++;
14
- const intent =
15
- invocation.arguments &&
16
- typeof invocation.arguments.i === "string" &&
17
- invocation.arguments.i.trim()
18
- ? invocation.arguments.i.trim()
19
- : `Using ${invocation.tool}`;
20
- report(`Step ${step} · ${intent}`);
14
+ const tool = /^[a-zA-Z0-9_-]{1,40}$/.test(invocation.tool) ? invocation.tool : "tool";
15
+ report(`Step ${step} · Running ${tool}`);
16
+ },
17
+ onToolResult(tool, success) {
18
+ const name = /^[a-zA-Z0-9_-]{1,40}$/.test(tool) ? tool : "tool";
19
+ report(`Step ${step} · ${name} ${success ? "finished" : "failed"}`);
21
20
  },
22
21
  onNotice(message: string) {
23
- if (/compact/i.test(message)) {
24
- report("Compacting context");
25
- } else if (/retry|rate limit/i.test(message)) {
26
- report("Retrying after a provider error");
27
- }
22
+ if (/compact/i.test(message)) report("Compacting context");
23
+ else if (/retry|rate limit/i.test(message)) report("Retrying after a provider error");
28
24
  },
29
25
  };
30
26
  }
@@ -531,23 +531,19 @@ export function createDiscordAdapter(
531
531
  deps.fetch,
532
532
  );
533
533
  },
534
- async activity(message, text, signal) {
534
+ async activity(message, text, signal, outcome = "success") {
535
535
  const channelId = message.threadId ?? message.channelId;
536
536
  const key = JSON.stringify([channelId, message.messageId]);
537
537
  const messages = `${DISCORD_API}/channels/${encodeURIComponent(channelId)}/messages`;
538
538
  const statusId = activityMessages.get(key);
539
539
  if (text === undefined) {
540
540
  if (!statusId) return;
541
+ const label = outcome === "success" ? "✅ Complete" : outcome === "failure" ? "❌ Failed" : "⏹ Cancelled";
541
542
  try {
542
543
  await messengerFetchJson(
543
544
  `${messages}/${encodeURIComponent(statusId)}`,
544
- {
545
- method: "PATCH",
546
- headers: headers(),
547
- body: JSON.stringify({ content: "✅ Complete", allowed_mentions: { parse: [] } }),
548
- },
549
- signal,
550
- deps.fetch,
545
+ { method: "PATCH", headers: headers(), body: JSON.stringify({ content: label, allowed_mentions: { parse: [] } }) },
546
+ signal, deps.fetch,
551
547
  );
552
548
  } catch (error) {
553
549
  if (!(error instanceof MessengerHttpError && error.status === 404)) throw error;
@@ -555,18 +551,13 @@ export function createDiscordAdapter(
555
551
  activityMessages.delete(key);
556
552
  return;
557
553
  }
558
- const content = `⏳ ${text}`;
554
+ const content = `⏳ ${text.replace(/[\r\n]+/g, " ")}`;
559
555
  if (statusId) {
560
556
  try {
561
557
  await messengerFetchJson(
562
558
  `${messages}/${encodeURIComponent(statusId)}`,
563
- {
564
- method: "PATCH",
565
- headers: headers(),
566
- body: JSON.stringify({ content, allowed_mentions: { parse: [] } }),
567
- },
568
- signal,
569
- deps.fetch,
559
+ { method: "PATCH", headers: headers(), body: JSON.stringify({ content, allowed_mentions: { parse: [] } }) },
560
+ signal, deps.fetch,
570
561
  );
571
562
  return;
572
563
  } catch (error) {
@@ -576,13 +567,8 @@ export function createDiscordAdapter(
576
567
  }
577
568
  const created = await messengerFetchJson(
578
569
  messages,
579
- {
580
- method: "POST",
581
- headers: headers(),
582
- body: JSON.stringify({ content, allowed_mentions: { parse: [] }, flags: DISCORD_ACTIVITY_FLAGS }),
583
- },
584
- signal,
585
- deps.fetch,
570
+ { method: "POST", headers: headers(), body: JSON.stringify({ content, allowed_mentions: { parse: [] }, flags: DISCORD_ACTIVITY_FLAGS }) },
571
+ signal, deps.fetch,
586
572
  );
587
573
  if (!isRecord(created) || typeof created.id !== "string" || !created.id)
588
574
  throw new Error("Discord activity message returned no ID");
@@ -33,8 +33,8 @@ export function activityLine(text: string): string {
33
33
 
34
34
  export interface ActivityReporter {
35
35
  report: MessengerActivityReporter;
36
- /** Stop updates and remove any shown line; idempotent and never rejects. */
37
- close(): Promise<void>;
36
+ /** Stop updates and finalize the status; idempotent and never rejects. */
37
+ close(outcome?: "success" | "failure" | "cancelled"): Promise<void>;
38
38
  }
39
39
 
40
40
  const NO_ACTIVITY: ActivityReporter = { report() {}, close: () => Promise.resolve() };
@@ -132,7 +132,7 @@ export function createActivityReporter(
132
132
  pumping = true;
133
133
  pump = run();
134
134
  },
135
- close() {
135
+ close(outcome = "success") {
136
136
  closing ??= (async () => {
137
137
  closed = true;
138
138
  wake?.();
@@ -140,7 +140,7 @@ export function createActivityReporter(
140
140
  if (!shown) return;
141
141
  for (let attempt = 0; ; attempt++) {
142
142
  try {
143
- await boundedActivity(bounded => activity.call(adapter, destination, undefined, bounded));
143
+ await boundedActivity(bounded => activity.call(adapter, destination, undefined, bounded, outcome));
144
144
  return;
145
145
  } catch (error) {
146
146
  const wait =
@@ -340,6 +340,7 @@ export function createMessengerGateway(
340
340
  conversationTails.set(conversation, tail);
341
341
  await previous;
342
342
  activity = createActivityReporter(adapter, destination, signal, activityIntervalMs);
343
+ activity.report("Starting request");
343
344
  let text: string;
344
345
  try {
345
346
  text = await reply(destination, signal, activity.report);
@@ -353,9 +354,6 @@ export function createMessengerGateway(
353
354
  }
354
355
  if (signal.aborted) return;
355
356
  text = "The request could not be completed. Please try again.";
356
- } finally {
357
- // Retire the status line alongside reply delivery rather than delaying the reply on it.
358
- void activity.close();
359
357
  }
360
358
  if (!signal.aborted && text.trim()) {
361
359
  // A failed send may already have delivered a chunk: never retry the entire reply.
@@ -363,9 +361,10 @@ export function createMessengerGateway(
363
361
  }
364
362
  if (!signal.aborted) status(failed ? "failure" : "success");
365
363
  } catch {
364
+ failed = true;
366
365
  if (!signal.aborted) status("failure");
367
366
  } finally {
368
- await activity.close();
367
+ await activity.close(failed ? "failure" : signal.aborted ? "cancelled" : "success");
369
368
  release();
370
369
  if (tail && conversationTails.get(conversation) === tail) conversationTails.delete(conversation);
371
370
  resolve();
@@ -31,11 +31,8 @@ export interface MessengerAdapter {
31
31
  status: "processing" | "success" | "failure",
32
32
  signal?: AbortSignal,
33
33
  ): Promise<void>;
34
- /**
35
- * Show `text` (one sanitized line) as the request's single in-progress status, editing it in place on
36
- * later calls; `undefined` removes it. The gateway serializes and throttles calls per request.
37
- */
38
- activity?(message: MessengerMessage, text: string | undefined, signal?: AbortSignal): Promise<void>;
34
+ /** Update the request's progress; undefined finishes it with the supplied outcome. */
35
+ activity?(message: MessengerMessage, text: string | undefined, signal?: AbortSignal, outcome?: "success" | "failure" | "cancelled"): Promise<void>;
39
36
  }
40
37
 
41
38
  export interface MessengerPlatformConfig {