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 +72 -0
- package/README.md +1 -0
- package/dist/server/main.mjs +54 -28
- package/docs/architecture.md +1 -0
- package/docs/release.md +4 -1
- package/package.json +1 -1
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
|
|
package/dist/server/main.mjs
CHANGED
|
@@ -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
|
|
580
|
-
|
|
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()) {
|
package/docs/architecture.md
CHANGED
|
@@ -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
|
|
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`
|