jagc 0.1.3 → 0.1.8

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
@@ -23,6 +23,78 @@ All notable changes to `jagc` are documented here.
23
23
 
24
24
  - None.
25
25
 
26
+ ## [0.1.8] - 2026-02-09
27
+
28
+ ### Added
29
+
30
+ - None.
31
+
32
+ ### Changed
33
+
34
+ - Release workflow now publishes with `NPM_CONFIG_PROVENANCE=false npm publish --access public` because npm does not support provenance for private GitHub source repositories.
35
+
36
+ ### Fixed
37
+
38
+ - None.
39
+
40
+ ## [0.1.7] - 2026-02-09
41
+
42
+ ### Added
43
+
44
+ - None.
45
+
46
+ ### Changed
47
+
48
+ - Release workflow now runs on Node 24 and upgrades npm to `>=11.5.1` so npm trusted publishing (OIDC) can authenticate correctly.
49
+
50
+ ### Fixed
51
+
52
+ - None.
53
+
54
+ ## [0.1.6] - 2026-02-09
55
+
56
+ ### Added
57
+
58
+ - None.
59
+
60
+ ### Changed
61
+
62
+ - Release workflow trusted-publish step now strips npmrc token lines and unsets `NODE_AUTH_TOKEN` before `npm publish`, while failing only if `NPM_TOKEN` is explicitly configured.
63
+
64
+ ### Fixed
65
+
66
+ - None.
67
+
68
+ ## [0.1.5] - 2026-02-09
69
+
70
+ ### Added
71
+
72
+ - None.
73
+
74
+ ### Changed
75
+
76
+ - Release workflow trusted-publish path now unsets token env only within the publish step (instead of exporting empty token env globally), while still failing fast if token auth is configured.
77
+
78
+ ### Fixed
79
+
80
+ - None.
81
+
82
+ ## [0.1.4] - 2026-02-09
83
+
84
+ ### Added
85
+
86
+ - None.
87
+
88
+ ### Changed
89
+
90
+ - Release workflow now enforces npm trusted publishing by stripping token-based npm auth (`NODE_AUTH_TOKEN` / `NPM_TOKEN`) and verifying token auth is absent before `npm publish --provenance`.
91
+ - Telegram progress updates no longer show status headers like `queued`, `working`, or `done`; they now start with a short single-word placeholder and drop it as soon as the first thinking/tool snippet arrives.
92
+ - Expanded Telegram startup placeholder variety with a larger set of creative single-word lines while preserving the same lowercase `word...` format.
93
+
94
+ ### Fixed
95
+
96
+ - None.
97
+
26
98
  ## [0.1.3] - 2026-02-09
27
99
 
28
100
  ### Added
package/README.md CHANGED
@@ -79,6 +79,7 @@ jagc model set <provider/model> --thread-key cli:default --json
79
79
  - Local server: `GET /healthz`, `POST /v1/messages`, `GET /v1/runs/:run_id`
80
80
  - CLI: `health`, `message`, `run wait`, `new`, `model list|get|set`, `thinking get|set`, `auth providers|login`
81
81
  - Telegram polling adapter (personal chats) with `/settings`, `/new`, `/model`, `/thinking`, `/auth`
82
+ - Telegram progress stream shows tool/thinking snippets; before the first snippet, a short placeholder line (for faster feedback)
82
83
  - Runtime semantics: same-thread `followUp` (default) and explicit `steer`
83
84
  - In-process scheduling + SQLite-backed recovery after restart
84
85
 
@@ -215,11 +215,57 @@ function parseNonNegativeInteger(value) {
215
215
  //#endregion
216
216
  //#region src/adapters/telegram-progress-helpers.ts
217
217
  const maxProgressToolLabelChars = 180;
218
+ const progressStartupLines = [
219
+ "thinking...",
220
+ "pondering...",
221
+ "pontificating...",
222
+ "ruminating...",
223
+ "scheming...",
224
+ "noodling...",
225
+ "conjuring...",
226
+ "wizarding...",
227
+ "calculating...",
228
+ "brainstormulating...",
229
+ "plotting...",
230
+ "synthesizing...",
231
+ "brainweaving...",
232
+ "daydreaming...",
233
+ "freestyling...",
234
+ "juggling...",
235
+ "moonwalking...",
236
+ "spelunking...",
237
+ "tinkering...",
238
+ "orchestrating...",
239
+ "harmonizing...",
240
+ "improvising...",
241
+ "scribbling...",
242
+ "whittling...",
243
+ "refactoring...",
244
+ "calibrating...",
245
+ "optimizing...",
246
+ "triangulating...",
247
+ "decoding...",
248
+ "untangling...",
249
+ "stargazing...",
250
+ "alchemizing...",
251
+ "clockworking...",
252
+ "mapmaking...",
253
+ "narrating...",
254
+ "riffing...",
255
+ "ideating...",
256
+ "debugomancy...",
257
+ "foreshadowing...",
258
+ "compiling..."
259
+ ];
218
260
  function summarizeToolLabel(toolName, payload, maxChars = maxProgressToolLabelChars) {
219
261
  const argsHint = summarizeToolArgs(toolName, payload);
220
262
  if (!argsHint) return truncateLine(toolName, maxChars);
221
263
  return truncateLine(`${toolName} ${argsHint}`, maxChars);
222
264
  }
265
+ function pickProgressStartupLine(randomValue = Math.random()) {
266
+ const normalized = Number.isFinite(randomValue) ? randomValue - Math.floor(randomValue) : 0;
267
+ return progressStartupLines[Math.min(progressStartupLines.length - 1, Math.floor(normalized * progressStartupLines.length))] ?? progressStartupLines[0] ?? "thinking...";
268
+ }
223
269
  function normalizePreviewDelta(text) {
224
270
  return text.replaceAll("\r", "");
225
271
  }
@@ -236,22 +282,6 @@ function truncateMessage(text, maxChars) {
236
282
  function truncateLine(text, maxChars) {
237
283
  return truncateMessage(text.replaceAll("\n", " ").trim(), maxChars);
238
284
  }
239
- function formatDuration(milliseconds) {
240
- const totalSeconds = Math.max(0, Math.floor(milliseconds / 1e3));
241
- const minutes = Math.floor(totalSeconds / 60);
242
- const seconds = totalSeconds % 60;
243
- if (minutes <= 0) return `${seconds}s`;
244
- return `${minutes}m ${seconds}s`;
245
- }
246
- function renderProgressStatusLabel(options) {
247
- if (options.phase === "queued") return { text: "queued" };
248
- if (options.phase === "succeeded") return { text: "done" };
249
- if (options.phase === "failed") return { text: "failed" };
250
- if (options.currentToolLabel) return { text: "using a tool" };
251
- if (options.now - options.lastThinkingAt <= 8e3 && options.lastThinkingAt > 0) return { text: "thinking" };
252
- if (options.isLongRunning) return { text: "running in background" };
253
- return { text: "working" };
254
- }
255
285
  function isEditMessageGoneError(error) {
256
286
  if (!(error instanceof Error)) return false;
257
287
  const message = error.message.toLowerCase();
@@ -314,14 +344,14 @@ const maxThinkingPreviewChars = 240;
314
344
  const maxDeltaChars = 200;
315
345
  const minThinkingLogIntervalMs = 1800;
316
346
  var TelegramRunProgressReporter = class {
317
- startedAt = Date.now();
318
347
  messageLimit;
319
348
  minEditIntervalMs;
320
349
  typingIntervalMs;
350
+ startupLine = pickProgressStartupLine();
321
351
  phase = "queued";
352
+ showStartupLine = true;
322
353
  isLongRunning = false;
323
354
  terminalErrorMessage = null;
324
- lastThinkingAt = 0;
325
355
  lastThinkingLoggedAt = 0;
326
356
  thinkingPreview = "";
327
357
  hasPendingThinkingPreview = false;
@@ -385,9 +415,9 @@ var TelegramRunProgressReporter = class {
385
415
  case "assistant_thinking_delta": {
386
416
  this.phase = "running";
387
417
  const now = Date.now();
388
- this.lastThinkingAt = now;
389
418
  const delta = normalizePreviewDelta(event.delta);
390
419
  if (delta.trim().length > 0) {
420
+ this.showStartupLine = false;
391
421
  this.thinkingPreview = appendTail(this.thinkingPreview, delta.slice(-maxDeltaChars), maxThinkingPreviewChars);
392
422
  this.hasPendingThinkingPreview = true;
393
423
  if (now - this.lastThinkingLoggedAt >= minThinkingLogIntervalMs) immediateRender = this.flushThinkingPreviewToLog(now) || immediateRender;
@@ -396,6 +426,7 @@ var TelegramRunProgressReporter = class {
396
426
  }
397
427
  case "tool_execution_start": {
398
428
  this.phase = "running";
429
+ this.showStartupLine = false;
399
430
  const label = summarizeToolLabel(event.toolName, event.args);
400
431
  this.toolLabelsByCallId.set(event.toolCallId, label);
401
432
  this.currentTool = {
@@ -410,6 +441,7 @@ var TelegramRunProgressReporter = class {
410
441
  break;
411
442
  case "tool_execution_end": {
412
443
  this.phase = "running";
444
+ this.showStartupLine = false;
413
445
  const label = this.toolLabelsByCallId.get(event.toolCallId) ?? summarizeToolLabel(event.toolName, void 0);
414
446
  this.toolLabelsByCallId.delete(event.toolCallId);
415
447
  if (event.isError) immediateRender = this.pushEventLogLine(`> ${label} failed`) || immediateRender;
@@ -576,18 +608,12 @@ var TelegramRunProgressReporter = class {
576
608
  }
577
609
  }
578
610
  renderProgressText() {
579
- const now = Date.now();
580
- const elapsed = formatDuration(now - this.startedAt);
581
- const lines = [`${renderProgressStatusLabel({
582
- phase: this.phase,
583
- isLongRunning: this.isLongRunning,
584
- currentToolLabel: this.currentTool?.label ?? null,
585
- lastThinkingAt: this.lastThinkingAt,
586
- now
587
- }).text} · ${elapsed}`];
611
+ const lines = [];
612
+ if (this.showStartupLine) lines.push(this.startupLine);
588
613
  lines.push(...this.eventLogLines);
589
614
  if (this.isLongRunning && this.phase === "running") lines.push("still running in background. i'll send the final response when done.");
590
615
  if (this.phase === "failed" && this.terminalErrorMessage) lines.push(`error: ${truncateLine(this.terminalErrorMessage, 240)}`);
616
+ if (lines.length === 0) lines.push("...");
591
617
  return this.renderTrimmedLines(lines);
592
618
  }
593
619
  flushThinkingPreviewToLog(now = Date.now()) {
@@ -120,6 +120,7 @@ Operational note:
120
120
  - Telegram `/new` and API `DELETE /v1/threads/:thread_key/session` abort/dispose the current thread session, clear persisted `thread_sessions` mapping, and cause the next message to create a fresh pi session.
121
121
  - Adapter starts a per-run progress reporter (in-chat append-style progress message + typing indicator) as soon as a run is ingested.
122
122
  - Progress is driven by run-level events emitted from `RunService` and pi session events forwarded by `ThreadRunController` (`assistant_text_delta`, `assistant_thinking_delta`, `tool_execution_*`, turn/agent lifecycle), rendered as compact append-log lines (`>` for tool calls with args-focused snippets, `~` for short thinking snippets).
123
+ - Until the first visible thinking/tool snippet arrives, the progress message shows a short single-word placeholder (for immediate feedback); once the first snippet arrives, that placeholder is removed.
123
124
  - Status updates are edit-throttled and retry-aware for Telegram rate limits (`retry_after`).
124
125
  - Adapter waits for terminal run status and replies with output/error.
125
126
  - If foreground wait exceeds adapter timeout, Telegram receives a "still running" notice and the adapter continues waiting in the background, then posts final output when complete.
package/docs/release.md CHANGED
@@ -17,6 +17,8 @@ This is the canonical publish procedure for `jagc`.
17
17
  - Repo: `<github-owner>/jagc`
18
18
  3. Ensure GitHub Actions is enabled and can request OIDC tokens.
19
19
  - Workflow must have `permissions: id-token: write`.
20
+ 4. Do **not** configure npm publish tokens (`NODE_AUTH_TOKEN` / `NPM_TOKEN`) for this repo.
21
+ - Release workflow enforces tokenless publish and fails if token auth is present.
20
22
 
21
23
  > 2FA remains enabled on the npm account. Trusted publishing avoids long-lived npm tokens in repo secrets.
22
24
 
@@ -62,8 +64,9 @@ If npm does not allow trusted publishing setup before the package exists, do one
62
64
  - Workflow verifies tag/version/changelog consistency.
63
65
  - Workflow runs `pnpm release:gate`.
64
66
  - Workflow publishes with:
65
- - `npm publish --access public --provenance`
67
+ - `NPM_CONFIG_PROVENANCE=false npm publish --access public`
66
68
  - Workflow creates/updates GitHub release notes from the matching changelog section.
69
+ - Note: npm provenance is currently unsupported for private GitHub repositories.
67
70
 
68
71
  6. **Post-release verification**
69
72
  - `npm view jagc version dist-tags --json`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jagc",
3
- "version": "0.1.3",
3
+ "version": "0.1.8",
4
4
  "description": "just a good clanker",
5
5
  "license": "MIT",
6
6
  "type": "module",