gsd-pi 2.35.0 → 2.36.0-dev.f887f4e
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.md +3 -1
- package/dist/cli.js +7 -2
- package/dist/resource-loader.d.ts +1 -1
- package/dist/resource-loader.js +13 -1
- package/dist/resources/extensions/async-jobs/await-tool.js +0 -2
- package/dist/resources/extensions/async-jobs/job-manager.js +0 -6
- package/dist/resources/extensions/bg-shell/output-formatter.js +1 -19
- package/dist/resources/extensions/bg-shell/process-manager.js +0 -4
- package/dist/resources/extensions/bg-shell/types.js +0 -2
- package/dist/resources/extensions/context7/index.js +5 -0
- package/dist/resources/extensions/get-secrets-from-user.js +2 -30
- package/dist/resources/extensions/google-search/index.js +5 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +43 -1
- package/dist/resources/extensions/gsd/auto-loop.js +17 -3
- package/dist/resources/extensions/gsd/auto-model-selection.js +15 -3
- package/dist/resources/extensions/gsd/auto-recovery.js +35 -0
- package/dist/resources/extensions/gsd/auto-start.js +35 -2
- package/dist/resources/extensions/gsd/auto.js +59 -4
- package/dist/resources/extensions/gsd/commands-handlers.js +2 -2
- package/dist/resources/extensions/gsd/commands-inspect.js +10 -3
- package/dist/resources/extensions/gsd/commands-rate.js +31 -0
- package/dist/resources/extensions/gsd/commands.js +43 -1
- package/dist/resources/extensions/gsd/doctor-environment.js +26 -17
- package/dist/resources/extensions/gsd/files.js +11 -2
- package/dist/resources/extensions/gsd/gitignore.js +54 -7
- package/dist/resources/extensions/gsd/guided-flow.js +8 -2
- package/dist/resources/extensions/gsd/health-widget-core.js +96 -0
- package/dist/resources/extensions/gsd/health-widget.js +97 -46
- package/dist/resources/extensions/gsd/index.js +26 -33
- package/dist/resources/extensions/gsd/migrate-external.js +55 -2
- package/dist/resources/extensions/gsd/milestone-ids.js +3 -2
- package/dist/resources/extensions/gsd/paths.js +74 -7
- package/dist/resources/extensions/gsd/post-unit-hooks.js +4 -1
- package/dist/resources/extensions/gsd/preferences-validation.js +16 -1
- package/dist/resources/extensions/gsd/preferences.js +12 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
- package/dist/resources/extensions/gsd/roadmap-mutations.js +55 -0
- package/dist/resources/extensions/gsd/session-lock.js +53 -2
- package/dist/resources/extensions/gsd/state.js +2 -1
- package/dist/resources/extensions/gsd/templates/plan.md +8 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +12 -0
- package/dist/resources/extensions/remote-questions/remote-command.js +2 -22
- package/dist/resources/extensions/shared/mod.js +1 -1
- package/dist/resources/extensions/shared/sanitize.js +30 -0
- package/dist/resources/extensions/subagent/index.js +6 -14
- package/dist/resources/skills/core-web-vitals/SKILL.md +1 -1
- package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +1 -1
- package/dist/resources/skills/github-workflows/SKILL.md +0 -2
- package/dist/resources/skills/web-quality-audit/SKILL.md +0 -2
- package/package.json +2 -1
- package/packages/pi-agent-core/dist/agent.d.ts +10 -2
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +19 -8
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/src/agent.ts +31 -10
- package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/packages/pi-ai/src/providers/openai-responses.ts +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +20 -4
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +13 -2
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +36 -12
- package/packages/pi-coding-agent/src/core/resource-loader.ts +13 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/async-jobs/await-tool.ts +0 -2
- package/src/resources/extensions/async-jobs/job-manager.ts +0 -7
- package/src/resources/extensions/bg-shell/output-formatter.ts +0 -17
- package/src/resources/extensions/bg-shell/process-manager.ts +0 -4
- package/src/resources/extensions/bg-shell/types.ts +0 -12
- package/src/resources/extensions/context7/index.ts +7 -0
- package/src/resources/extensions/get-secrets-from-user.ts +2 -35
- package/src/resources/extensions/google-search/index.ts +7 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +49 -1
- package/src/resources/extensions/gsd/auto-loop.ts +22 -2
- package/src/resources/extensions/gsd/auto-model-selection.ts +23 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +39 -0
- package/src/resources/extensions/gsd/auto-start.ts +42 -2
- package/src/resources/extensions/gsd/auto.ts +61 -3
- package/src/resources/extensions/gsd/commands-handlers.ts +2 -2
- package/src/resources/extensions/gsd/commands-inspect.ts +10 -3
- package/src/resources/extensions/gsd/commands-rate.ts +55 -0
- package/src/resources/extensions/gsd/commands.ts +43 -1
- package/src/resources/extensions/gsd/doctor-environment.ts +26 -16
- package/src/resources/extensions/gsd/files.ts +12 -2
- package/src/resources/extensions/gsd/gitignore.ts +54 -7
- package/src/resources/extensions/gsd/guided-flow.ts +8 -2
- package/src/resources/extensions/gsd/health-widget-core.ts +129 -0
- package/src/resources/extensions/gsd/health-widget.ts +103 -59
- package/src/resources/extensions/gsd/index.ts +30 -33
- package/src/resources/extensions/gsd/migrate-external.ts +47 -2
- package/src/resources/extensions/gsd/milestone-ids.ts +3 -2
- package/src/resources/extensions/gsd/paths.ts +73 -7
- package/src/resources/extensions/gsd/post-unit-hooks.ts +5 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +16 -1
- package/src/resources/extensions/gsd/preferences.ts +14 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -0
- package/src/resources/extensions/gsd/roadmap-mutations.ts +66 -0
- package/src/resources/extensions/gsd/session-lock.ts +59 -2
- package/src/resources/extensions/gsd/state.ts +2 -1
- package/src/resources/extensions/gsd/templates/plan.md +8 -0
- package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +214 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +158 -0
- package/src/resources/extensions/gsd/tests/paths.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/test-utils.ts +165 -0
- package/src/resources/extensions/gsd/tests/validate-directory.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +32 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +11 -0
- package/src/resources/extensions/remote-questions/remote-command.ts +2 -23
- package/src/resources/extensions/shared/mod.ts +1 -1
- package/src/resources/extensions/shared/sanitize.ts +36 -0
- package/src/resources/extensions/subagent/index.ts +6 -12
- package/src/resources/skills/core-web-vitals/SKILL.md +1 -1
- package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +1 -1
- package/src/resources/skills/github-workflows/SKILL.md +0 -2
- package/src/resources/skills/web-quality-audit/SKILL.md +0 -2
- package/dist/resources/extensions/shared/wizard-ui.js +0 -478
- package/dist/resources/skills/swiftui/SKILL.md +0 -208
- package/dist/resources/skills/swiftui/references/animations.md +0 -921
- package/dist/resources/skills/swiftui/references/architecture.md +0 -1561
- package/dist/resources/skills/swiftui/references/layout-system.md +0 -1186
- package/dist/resources/skills/swiftui/references/navigation.md +0 -1492
- package/dist/resources/skills/swiftui/references/networking-async.md +0 -214
- package/dist/resources/skills/swiftui/references/performance.md +0 -1706
- package/dist/resources/skills/swiftui/references/platform-integration.md +0 -204
- package/dist/resources/skills/swiftui/references/state-management.md +0 -1443
- package/dist/resources/skills/swiftui/references/swiftdata.md +0 -297
- package/dist/resources/skills/swiftui/references/testing-debugging.md +0 -247
- package/dist/resources/skills/swiftui/references/uikit-appkit-interop.md +0 -218
- package/dist/resources/skills/swiftui/workflows/add-feature.md +0 -191
- package/dist/resources/skills/swiftui/workflows/build-new-app.md +0 -311
- package/dist/resources/skills/swiftui/workflows/debug-swiftui.md +0 -192
- package/dist/resources/skills/swiftui/workflows/optimize-performance.md +0 -197
- package/dist/resources/skills/swiftui/workflows/ship-app.md +0 -203
- package/dist/resources/skills/swiftui/workflows/write-tests.md +0 -235
- package/src/resources/extensions/shared/wizard-ui.ts +0 -551
- package/src/resources/skills/swiftui/SKILL.md +0 -208
- package/src/resources/skills/swiftui/references/animations.md +0 -921
- package/src/resources/skills/swiftui/references/architecture.md +0 -1561
- package/src/resources/skills/swiftui/references/layout-system.md +0 -1186
- package/src/resources/skills/swiftui/references/navigation.md +0 -1492
- package/src/resources/skills/swiftui/references/networking-async.md +0 -214
- package/src/resources/skills/swiftui/references/performance.md +0 -1706
- package/src/resources/skills/swiftui/references/platform-integration.md +0 -204
- package/src/resources/skills/swiftui/references/state-management.md +0 -1443
- package/src/resources/skills/swiftui/references/swiftdata.md +0 -297
- package/src/resources/skills/swiftui/references/testing-debugging.md +0 -247
- package/src/resources/skills/swiftui/references/uikit-appkit-interop.md +0 -218
- package/src/resources/skills/swiftui/workflows/add-feature.md +0 -191
- package/src/resources/skills/swiftui/workflows/build-new-app.md +0 -311
- package/src/resources/skills/swiftui/workflows/debug-swiftui.md +0 -192
- package/src/resources/skills/swiftui/workflows/optimize-performance.md +0 -197
- package/src/resources/skills/swiftui/workflows/ship-app.md +0 -203
- package/src/resources/skills/swiftui/workflows/write-tests.md +0 -235
|
@@ -32,8 +32,17 @@ let _lockPid = 0;
|
|
|
32
32
|
let _lockCompromised = false;
|
|
33
33
|
/** Whether we've already registered a process.on('exit') handler. */
|
|
34
34
|
let _exitHandlerRegistered = false;
|
|
35
|
+
/** Snapshotted lock file path — captured at acquireSessionLock time to avoid
|
|
36
|
+
* gsdRoot() resolving differently in worktree vs project root contexts (#1363). */
|
|
37
|
+
let _snapshotLockPath = null;
|
|
38
|
+
/** Timestamp when the session lock was acquired — used to detect false-positive
|
|
39
|
+
* onCompromised events from event loop stalls within the stale window (#1362). */
|
|
40
|
+
let _lockAcquiredAt = 0;
|
|
35
41
|
const LOCK_FILE = "auto.lock";
|
|
36
42
|
function lockPath(basePath) {
|
|
43
|
+
// If we have a snapshotted path from acquisition, use it for consistency
|
|
44
|
+
if (_snapshotLockPath)
|
|
45
|
+
return _snapshotLockPath;
|
|
37
46
|
return join(gsdRoot(basePath), LOCK_FILE);
|
|
38
47
|
}
|
|
39
48
|
// ─── Stray Lock Cleanup ─────────────────────────────────────────────────────
|
|
@@ -175,8 +184,17 @@ export function acquireSessionLock(basePath) {
|
|
|
175
184
|
onCompromised: () => {
|
|
176
185
|
// proper-lockfile detected mtime drift (system sleep, event loop stall, etc.).
|
|
177
186
|
// Default handler throws inside setTimeout — an uncaught exception that crashes
|
|
178
|
-
// or corrupts process state.
|
|
179
|
-
//
|
|
187
|
+
// or corrupts process state.
|
|
188
|
+
//
|
|
189
|
+
// False-positive suppression (#1362): If we're still within the stale window
|
|
190
|
+
// (30 min since acquisition), the mtime mismatch is from an event loop stall
|
|
191
|
+
// during a long LLM call — not a real takeover. Log and continue.
|
|
192
|
+
const elapsed = Date.now() - _lockAcquiredAt;
|
|
193
|
+
if (elapsed < 1_800_000) {
|
|
194
|
+
process.stderr.write(`[gsd] Lock heartbeat mismatch after ${Math.round(elapsed / 1000)}s — event loop stall, continuing.\n`);
|
|
195
|
+
return; // Suppress false positive
|
|
196
|
+
}
|
|
197
|
+
// Past the stale window — this is a real compromise
|
|
180
198
|
_lockCompromised = true;
|
|
181
199
|
_releaseFunction = null;
|
|
182
200
|
},
|
|
@@ -185,6 +203,8 @@ export function acquireSessionLock(basePath) {
|
|
|
185
203
|
_lockedPath = basePath;
|
|
186
204
|
_lockPid = process.pid;
|
|
187
205
|
_lockCompromised = false;
|
|
206
|
+
_lockAcquiredAt = Date.now();
|
|
207
|
+
_snapshotLockPath = lp; // Snapshot the resolved path for consistent access (#1363)
|
|
188
208
|
// Safety net: clean up lock dir on process exit if _releaseFunction
|
|
189
209
|
// wasn't called (e.g., normal exit after clean completion) (#1245).
|
|
190
210
|
ensureExitHandler(gsdDir);
|
|
@@ -211,6 +231,14 @@ export function acquireSessionLock(basePath) {
|
|
|
211
231
|
stale: 1_800_000, // 30 minutes — match primary lock settings
|
|
212
232
|
update: 10_000,
|
|
213
233
|
onCompromised: () => {
|
|
234
|
+
// Same false-positive suppression as the primary lock (#1512).
|
|
235
|
+
// Without this, the retry path fires _lockCompromised unconditionally
|
|
236
|
+
// on benign mtime drift (laptop sleep, heavy LLM event loop stalls).
|
|
237
|
+
const elapsed = Date.now() - _lockAcquiredAt;
|
|
238
|
+
if (elapsed < 1_800_000) {
|
|
239
|
+
process.stderr.write(`[gsd] Lock heartbeat mismatch after ${Math.round(elapsed / 1000)}s — event loop stall, continuing.\n`);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
214
242
|
_lockCompromised = true;
|
|
215
243
|
_releaseFunction = null;
|
|
216
244
|
},
|
|
@@ -219,6 +247,8 @@ export function acquireSessionLock(basePath) {
|
|
|
219
247
|
_lockedPath = basePath;
|
|
220
248
|
_lockPid = process.pid;
|
|
221
249
|
_lockCompromised = false;
|
|
250
|
+
_lockAcquiredAt = Date.now();
|
|
251
|
+
_snapshotLockPath = lp; // Snapshot for retry path too (#1363)
|
|
222
252
|
// Safety net — uses centralized handler to avoid double-registration
|
|
223
253
|
ensureExitHandler(gsdDir);
|
|
224
254
|
atomicWriteSync(lp, JSON.stringify(lockData, null, 2));
|
|
@@ -293,6 +323,25 @@ export function updateSessionLock(basePath, unitType, unitId, completedUnits, se
|
|
|
293
323
|
export function validateSessionLock(basePath) {
|
|
294
324
|
// Lock was compromised by proper-lockfile (mtime drift from sleep, stall, etc.)
|
|
295
325
|
if (_lockCompromised) {
|
|
326
|
+
// Recovery gate (#1512): Before declaring the lock lost, check if the lock
|
|
327
|
+
// file still contains our PID. If it does, no other process took over — the
|
|
328
|
+
// onCompromised fired from benign mtime drift (laptop sleep, event loop stall
|
|
329
|
+
// beyond the stale window). Attempt re-acquisition instead of giving up.
|
|
330
|
+
const lp = lockPath(basePath);
|
|
331
|
+
const existing = readExistingLockData(lp);
|
|
332
|
+
if (existing && existing.pid === process.pid) {
|
|
333
|
+
// Lock file still ours — try to re-acquire the OS lock
|
|
334
|
+
try {
|
|
335
|
+
const result = acquireSessionLock(basePath);
|
|
336
|
+
if (result.acquired) {
|
|
337
|
+
process.stderr.write(`[gsd] Lock recovered after onCompromised — lock file PID matched, re-acquired.\n`);
|
|
338
|
+
return true;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
// Re-acquisition failed — fall through to return false
|
|
343
|
+
}
|
|
344
|
+
}
|
|
296
345
|
return false;
|
|
297
346
|
}
|
|
298
347
|
// If we have an OS-level lock, we're still the owner
|
|
@@ -348,6 +397,8 @@ export function releaseSessionLock(basePath) {
|
|
|
348
397
|
_lockedPath = null;
|
|
349
398
|
_lockPid = 0;
|
|
350
399
|
_lockCompromised = false;
|
|
400
|
+
_lockAcquiredAt = 0;
|
|
401
|
+
_snapshotLockPath = null;
|
|
351
402
|
}
|
|
352
403
|
/**
|
|
353
404
|
* Check if a session lock exists and return its data (for crash recovery).
|
|
@@ -33,11 +33,12 @@ export function isValidationTerminal(validationContent) {
|
|
|
33
33
|
const verdict = match[1].match(/verdict:\s*(\S+)/);
|
|
34
34
|
if (!verdict)
|
|
35
35
|
return false;
|
|
36
|
+
const v = verdict[1] === 'passed' ? 'pass' : verdict[1];
|
|
36
37
|
// 'pass' and 'needs-attention' are always terminal.
|
|
37
38
|
// 'needs-remediation' is treated as terminal to prevent infinite loops
|
|
38
39
|
// when no remediation slices exist in the roadmap (#832). The validation
|
|
39
40
|
// report is preserved on disk for manual review.
|
|
40
|
-
return
|
|
41
|
+
return v === 'pass' || v === 'needs-attention' || v === 'needs-remediation';
|
|
41
42
|
}
|
|
42
43
|
const CACHE_TTL_MS = 100;
|
|
43
44
|
let _stateCache = null;
|
|
@@ -113,6 +113,14 @@
|
|
|
113
113
|
- Tasks execute sequentially in order (T01, T02, T03, ...)
|
|
114
114
|
- est: is informational (e.g. 30m, 1h, 2h) and optional
|
|
115
115
|
|
|
116
|
+
Verify field rules:
|
|
117
|
+
- MUST be a mechanically executable command: `npm test`, `grep -q "pattern" file`, `test -f path`
|
|
118
|
+
- For content/document tasks: verify file existence, section count, YAML validity, or word count
|
|
119
|
+
NOT exact phrasing, specific formulas, or "zero TBD" aspirational criteria
|
|
120
|
+
- If no command can verify the output, write: "Manual review — file exists and is non-empty"
|
|
121
|
+
- BAD: "Sections 3.1 and 3.2 exist with exact formulas. Zero TBD/TODO."
|
|
122
|
+
- GOOD: `grep -c "^## " doc.md` returns >= 4 (4+ sections), `! grep -q "TBD\|TODO" doc.md`
|
|
123
|
+
|
|
116
124
|
Integration closure rule:
|
|
117
125
|
- At least one slice in any multi-boundary milestone should perform real composition/wiring, not just contract hardening
|
|
118
126
|
- For the final assembly slice, verification must exercise the real entrypoint or runtime path
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* Key invariant: `createAutoWorktree()` and `enterAutoWorktree()` call
|
|
13
13
|
* `process.chdir()` internally — this class MUST NOT double-chdir.
|
|
14
14
|
*/
|
|
15
|
+
import { existsSync, unlinkSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
15
17
|
import { debugLog } from "./debug-logger.js";
|
|
16
18
|
// ─── WorktreeResolver ──────────────────────────────────────────────────────
|
|
17
19
|
export class WorktreeResolver {
|
|
@@ -253,6 +255,16 @@ export class WorktreeResolver {
|
|
|
253
255
|
fallback: "chdir-to-project-root",
|
|
254
256
|
});
|
|
255
257
|
ctx.notify(`Milestone merge failed: ${msg}`, "warning");
|
|
258
|
+
// Clean up stale merge state left by failed squash-merge (#1389)
|
|
259
|
+
try {
|
|
260
|
+
const gitDir = join(originalBase || this.s.basePath, ".git");
|
|
261
|
+
for (const f of ["SQUASH_MSG", "MERGE_HEAD", "MERGE_MSG"]) {
|
|
262
|
+
const p = join(gitDir, f);
|
|
263
|
+
if (existsSync(p))
|
|
264
|
+
unlinkSync(p);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
catch { /* best-effort */ }
|
|
256
268
|
// Error recovery: always restore to project root
|
|
257
269
|
if (originalBase) {
|
|
258
270
|
try {
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
* Remote Questions — /gsd remote command
|
|
3
3
|
*/
|
|
4
4
|
import { AuthStorage } from "@gsd/pi-coding-agent";
|
|
5
|
-
import {
|
|
5
|
+
import { Editor, Key, matchesKey, truncateToWidth } from "@gsd/pi-tui";
|
|
6
6
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
7
7
|
import { dirname, join } from "node:path";
|
|
8
8
|
import { getGlobalGSDPreferencesPath, loadEffectiveGSDPreferences } from "../gsd/preferences.js";
|
|
9
9
|
import { getRemoteConfigStatus, isValidChannelId, resolveRemoteConfig } from "./config.js";
|
|
10
|
-
import { sanitizeError } from "../shared/
|
|
10
|
+
import { maskEditorLine, sanitizeError } from "../shared/mod.js";
|
|
11
11
|
import { getLatestPromptSummary } from "./status.js";
|
|
12
12
|
export async function handleRemote(subcommand, ctx, _pi) {
|
|
13
13
|
const trimmed = subcommand.trim();
|
|
@@ -339,26 +339,6 @@ function removeRemoteQuestionsConfig() {
|
|
|
339
339
|
const next = frontmatter ? `---\n${frontmatter}\n---${content.slice(fmMatch[0].length)}` : content.slice(fmMatch[0].length).replace(/^\n+/, "");
|
|
340
340
|
writeFileSync(prefsPath, next, "utf-8");
|
|
341
341
|
}
|
|
342
|
-
function maskEditorLine(line) {
|
|
343
|
-
let output = "";
|
|
344
|
-
let i = 0;
|
|
345
|
-
while (i < line.length) {
|
|
346
|
-
if (line.startsWith(CURSOR_MARKER, i)) {
|
|
347
|
-
output += CURSOR_MARKER;
|
|
348
|
-
i += CURSOR_MARKER.length;
|
|
349
|
-
continue;
|
|
350
|
-
}
|
|
351
|
-
const ansiMatch = /^\x1b\[[0-9;]*m/.exec(line.slice(i));
|
|
352
|
-
if (ansiMatch) {
|
|
353
|
-
output += ansiMatch[0];
|
|
354
|
-
i += ansiMatch[0].length;
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
output += line[i] === " " ? " " : "*";
|
|
358
|
-
i += 1;
|
|
359
|
-
}
|
|
360
|
-
return output;
|
|
361
|
-
}
|
|
362
342
|
async function promptMaskedInput(ctx, label, hint) {
|
|
363
343
|
if (!ctx.hasUI)
|
|
364
344
|
return null;
|
|
@@ -6,6 +6,6 @@ export { toPosixPath } from "./path-display.js";
|
|
|
6
6
|
export { showInterviewRound } from "./interview-ui.js";
|
|
7
7
|
export { showNextAction } from "./next-action-ui.js";
|
|
8
8
|
export { showConfirm } from "./confirm-ui.js";
|
|
9
|
-
export { sanitizeError } from "./sanitize.js";
|
|
9
|
+
export { sanitizeError, maskEditorLine } from "./sanitize.js";
|
|
10
10
|
export { formatDateShort, truncateWithEllipsis } from "./format-utils.js";
|
|
11
11
|
export { splitFrontmatter, parseFrontmatterMap } from "./frontmatter.js";
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sanitize error messages by redacting token-like strings before surfacing.
|
|
3
|
+
* Also provides maskEditorLine for masking sensitive TUI editor input.
|
|
3
4
|
*/
|
|
5
|
+
import { CURSOR_MARKER } from "@gsd/pi-tui";
|
|
4
6
|
const TOKEN_PATTERNS = [
|
|
5
7
|
/xoxb-[A-Za-z0-9\-]+/g, // Slack bot tokens
|
|
6
8
|
/xoxp-[A-Za-z0-9\-]+/g, // Slack user tokens
|
|
@@ -15,3 +17,31 @@ export function sanitizeError(msg) {
|
|
|
15
17
|
}
|
|
16
18
|
return sanitized;
|
|
17
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Replace editor visible text with masked characters while preserving
|
|
22
|
+
* ANSI cursor/sequencer codes. Keeps border/metadata lines readable.
|
|
23
|
+
*/
|
|
24
|
+
export function maskEditorLine(line) {
|
|
25
|
+
if (line.startsWith("─")) {
|
|
26
|
+
return line;
|
|
27
|
+
}
|
|
28
|
+
let output = "";
|
|
29
|
+
let i = 0;
|
|
30
|
+
while (i < line.length) {
|
|
31
|
+
if (line.startsWith(CURSOR_MARKER, i)) {
|
|
32
|
+
output += CURSOR_MARKER;
|
|
33
|
+
i += CURSOR_MARKER.length;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const ansiMatch = /^\x1b\[[0-9;]*m/.exec(line.slice(i));
|
|
37
|
+
if (ansiMatch) {
|
|
38
|
+
output += ansiMatch[0];
|
|
39
|
+
i += ansiMatch[0].length;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const ch = line[i];
|
|
43
|
+
output += ch === " " ? " " : "*";
|
|
44
|
+
i += 1;
|
|
45
|
+
}
|
|
46
|
+
return output;
|
|
47
|
+
}
|
|
@@ -20,6 +20,7 @@ import { StringEnum } from "@gsd/pi-ai";
|
|
|
20
20
|
import { getMarkdownTheme } from "@gsd/pi-coding-agent";
|
|
21
21
|
import { Container, Markdown, Spacer, Text } from "@gsd/pi-tui";
|
|
22
22
|
import { Type } from "@sinclair/typebox";
|
|
23
|
+
import { formatTokenCount } from "../shared/mod.js";
|
|
23
24
|
import { discoverAgents } from "./agents.js";
|
|
24
25
|
import { createIsolation, mergeDeltaPatches, readIsolationMode, } from "./isolation.js";
|
|
25
26
|
import { registerWorker, updateWorker } from "./worker-registry.js";
|
|
@@ -58,31 +59,22 @@ async function stopLiveSubagents() {
|
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
|
-
function formatTokens(count) {
|
|
62
|
-
if (count < 1000)
|
|
63
|
-
return count.toString();
|
|
64
|
-
if (count < 10000)
|
|
65
|
-
return `${(count / 1000).toFixed(1)}k`;
|
|
66
|
-
if (count < 1000000)
|
|
67
|
-
return `${Math.round(count / 1000)}k`;
|
|
68
|
-
return `${(count / 1000000).toFixed(1)}M`;
|
|
69
|
-
}
|
|
70
62
|
function formatUsageStats(usage, model) {
|
|
71
63
|
const parts = [];
|
|
72
64
|
if (usage.turns)
|
|
73
65
|
parts.push(`${usage.turns} turn${usage.turns > 1 ? "s" : ""}`);
|
|
74
66
|
if (usage.input)
|
|
75
|
-
parts.push(`↑${
|
|
67
|
+
parts.push(`↑${formatTokenCount(usage.input)}`);
|
|
76
68
|
if (usage.output)
|
|
77
|
-
parts.push(`↓${
|
|
69
|
+
parts.push(`↓${formatTokenCount(usage.output)}`);
|
|
78
70
|
if (usage.cacheRead)
|
|
79
|
-
parts.push(`R${
|
|
71
|
+
parts.push(`R${formatTokenCount(usage.cacheRead)}`);
|
|
80
72
|
if (usage.cacheWrite)
|
|
81
|
-
parts.push(`W${
|
|
73
|
+
parts.push(`W${formatTokenCount(usage.cacheWrite)}`);
|
|
82
74
|
if (usage.cost)
|
|
83
75
|
parts.push(`$${(Number(usage.cost) || 0).toFixed(4)}`);
|
|
84
76
|
if (usage.contextTokens && usage.contextTokens > 0) {
|
|
85
|
-
parts.push(`ctx:${
|
|
77
|
+
parts.push(`ctx:${formatTokenCount(usage.contextTokens)}`);
|
|
86
78
|
}
|
|
87
79
|
if (model)
|
|
88
80
|
parts.push(model);
|
|
@@ -438,4 +438,4 @@ startTransition(() => setExpensiveState(newValue));
|
|
|
438
438
|
- [web.dev LCP](https://web.dev/articles/lcp)
|
|
439
439
|
- [web.dev INP](https://web.dev/articles/inp)
|
|
440
440
|
- [web.dev CLS](https://web.dev/articles/cls)
|
|
441
|
-
- [
|
|
441
|
+
- [Code Optimizer skill](../code-optimizer/SKILL.md)
|
|
@@ -42,7 +42,7 @@ The file must `export default function(pi: ExtensionAPI) { ... }`.
|
|
|
42
42
|
|
|
43
43
|
## Step 4: Check for Common Mistakes
|
|
44
44
|
|
|
45
|
-
Read
|
|
45
|
+
Read `../references/key-rules-gotchas.md` and verify each rule against the extension code.
|
|
46
46
|
|
|
47
47
|
## Step 5: Add Debugging
|
|
48
48
|
|
|
@@ -163,8 +163,6 @@ When performing an audit, structure findings as:
|
|
|
163
163
|
## References
|
|
164
164
|
|
|
165
165
|
For detailed guidelines on specific areas:
|
|
166
|
-
- [Performance Optimization](../performance/SKILL.md)
|
|
167
166
|
- [Core Web Vitals](../core-web-vitals/SKILL.md)
|
|
168
167
|
- [Accessibility](../accessibility/SKILL.md)
|
|
169
|
-
- [SEO](../seo/SKILL.md)
|
|
170
168
|
- [Best Practices](../best-practices/SKILL.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gsd-pi",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.36.0-dev.f887f4e",
|
|
4
4
|
"description": "GSD — Get Shit Done coding agent",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"copy-themes": "node scripts/copy-themes.cjs",
|
|
51
51
|
"copy-export-html": "node scripts/copy-export-html.cjs",
|
|
52
52
|
"test:unit": "node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/*.test.ts src/resources/extensions/gsd/tests/*.test.mjs src/tests/*.test.ts",
|
|
53
|
+
"test:marketplace": "GSD_TEST_CLONE_MARKETPLACES=1 node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/claude-import-tui.test.ts src/resources/extensions/gsd/tests/plugin-importer-live.test.ts src/tests/marketplace-discovery.test.ts",
|
|
53
54
|
"test:coverage": "c8 --reporter=text --reporter=lcov --exclude='src/resources/extensions/gsd/tests/**' --exclude='src/tests/**' --exclude='scripts/**' --exclude='native/**' --exclude='node_modules/**' --check-coverage --statements=50 --lines=50 --branches=20 --functions=20 node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/*.test.ts src/resources/extensions/gsd/tests/*.test.mjs src/tests/*.test.ts",
|
|
54
55
|
"test:integration": "node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/*integration*.test.ts src/tests/integration/*.test.ts",
|
|
55
56
|
"test": "npm run test:unit && npm run test:integration",
|
|
@@ -140,15 +140,23 @@ export declare class Agent {
|
|
|
140
140
|
* Queue a steering message to interrupt the agent mid-run.
|
|
141
141
|
* Delivered after current tool execution, skips remaining tools.
|
|
142
142
|
*/
|
|
143
|
-
steer(m: AgentMessage): void;
|
|
143
|
+
steer(m: AgentMessage, origin?: "user" | "system"): void;
|
|
144
144
|
/**
|
|
145
145
|
* Queue a follow-up message to be processed after the agent finishes.
|
|
146
146
|
* Delivered only when agent has no more tool calls or steering messages.
|
|
147
147
|
*/
|
|
148
|
-
followUp(m: AgentMessage): void;
|
|
148
|
+
followUp(m: AgentMessage, origin?: "user" | "system"): void;
|
|
149
149
|
clearSteeringQueue(): void;
|
|
150
150
|
clearFollowUpQueue(): void;
|
|
151
151
|
clearAllQueues(): void;
|
|
152
|
+
/**
|
|
153
|
+
* Drain user-origin messages from queues, leaving system messages in place.
|
|
154
|
+
* Used during abort to preserve messages the user explicitly typed.
|
|
155
|
+
*/
|
|
156
|
+
drainUserMessages(): {
|
|
157
|
+
steering: AgentMessage[];
|
|
158
|
+
followUp: AgentMessage[];
|
|
159
|
+
};
|
|
152
160
|
hasQueuedMessages(): boolean;
|
|
153
161
|
private dequeueSteeringMessages;
|
|
154
162
|
private dequeueFollowUpMessages;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEN,KAAK,YAAY,EACjB,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,mBAAmB,EAGxB,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAEX,UAAU,EACV,eAAe,EACf,YAAY,EACZ,UAAU,EACV,SAAS,EAKT,QAAQ,EACR,aAAa,EACb,MAAM,YAAY,CAAC;AASpB,MAAM,WAAW,YAAY;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAEnC;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAE5E;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAE/F;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,GAAG,eAAe,CAAC;IAEvC;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,GAAG,eAAe,CAAC;IAEvC;;OAEG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAEpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;IAEnF;;OAEG;IACH,SAAS,CAAC,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAE7C;;OAEG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;IAElC;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -145,15 +145,15 @@ export class Agent {
|
|
|
145
145
|
* Queue a steering message to interrupt the agent mid-run.
|
|
146
146
|
* Delivered after current tool execution, skips remaining tools.
|
|
147
147
|
*/
|
|
148
|
-
steer(m) {
|
|
149
|
-
this.steeringQueue.push(m);
|
|
148
|
+
steer(m, origin = "system") {
|
|
149
|
+
this.steeringQueue.push({ message: m, origin });
|
|
150
150
|
}
|
|
151
151
|
/**
|
|
152
152
|
* Queue a follow-up message to be processed after the agent finishes.
|
|
153
153
|
* Delivered only when agent has no more tool calls or steering messages.
|
|
154
154
|
*/
|
|
155
|
-
followUp(m) {
|
|
156
|
-
this.followUpQueue.push(m);
|
|
155
|
+
followUp(m, origin = "system") {
|
|
156
|
+
this.followUpQueue.push({ message: m, origin });
|
|
157
157
|
}
|
|
158
158
|
clearSteeringQueue() {
|
|
159
159
|
this.steeringQueue = [];
|
|
@@ -165,6 +165,17 @@ export class Agent {
|
|
|
165
165
|
this.steeringQueue = [];
|
|
166
166
|
this.followUpQueue = [];
|
|
167
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Drain user-origin messages from queues, leaving system messages in place.
|
|
170
|
+
* Used during abort to preserve messages the user explicitly typed.
|
|
171
|
+
*/
|
|
172
|
+
drainUserMessages() {
|
|
173
|
+
const userSteering = this.steeringQueue.filter((e) => e.origin === "user").map((e) => e.message);
|
|
174
|
+
const userFollowUp = this.followUpQueue.filter((e) => e.origin === "user").map((e) => e.message);
|
|
175
|
+
this.steeringQueue = this.steeringQueue.filter((e) => e.origin !== "user");
|
|
176
|
+
this.followUpQueue = this.followUpQueue.filter((e) => e.origin !== "user");
|
|
177
|
+
return { steering: userSteering, followUp: userFollowUp };
|
|
178
|
+
}
|
|
168
179
|
hasQueuedMessages() {
|
|
169
180
|
return this.steeringQueue.length > 0 || this.followUpQueue.length > 0;
|
|
170
181
|
}
|
|
@@ -173,11 +184,11 @@ export class Agent {
|
|
|
173
184
|
if (this.steeringQueue.length > 0) {
|
|
174
185
|
const first = this.steeringQueue[0];
|
|
175
186
|
this.steeringQueue = this.steeringQueue.slice(1);
|
|
176
|
-
return [first];
|
|
187
|
+
return [first.message];
|
|
177
188
|
}
|
|
178
189
|
return [];
|
|
179
190
|
}
|
|
180
|
-
const steering = this.steeringQueue.
|
|
191
|
+
const steering = this.steeringQueue.map((e) => e.message);
|
|
181
192
|
this.steeringQueue = [];
|
|
182
193
|
return steering;
|
|
183
194
|
}
|
|
@@ -186,11 +197,11 @@ export class Agent {
|
|
|
186
197
|
if (this.followUpQueue.length > 0) {
|
|
187
198
|
const first = this.followUpQueue[0];
|
|
188
199
|
this.followUpQueue = this.followUpQueue.slice(1);
|
|
189
|
-
return [first];
|
|
200
|
+
return [first.message];
|
|
190
201
|
}
|
|
191
202
|
return [];
|
|
192
203
|
}
|
|
193
|
-
const followUp = this.followUpQueue.
|
|
204
|
+
const followUp = this.followUpQueue.map((e) => e.message);
|
|
194
205
|
this.followUpQueue = [];
|
|
195
206
|
return followUp;
|
|
196
207
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Agent class that uses the agent-loop directly.\n * No transport abstraction - calls streamSimple via the loop.\n */\n\nimport {\n\tgetModel,\n\ttype ImageContent,\n\ttype Message,\n\ttype Model,\n\ttype SimpleStreamOptions,\n\tstreamSimple,\n\ttype TextContent,\n\ttype ThinkingBudgets,\n\ttype Transport,\n} from \"@gsd/pi-ai\";\nimport { agentLoop, agentLoopContinue, ZERO_USAGE } from \"./agent-loop.js\";\nimport type {\n\tAgentContext,\n\tAgentEvent,\n\tAgentLoopConfig,\n\tAgentMessage,\n\tAgentState,\n\tAgentTool,\n\tBeforeToolCallContext,\n\tBeforeToolCallResult,\n\tAfterToolCallContext,\n\tAfterToolCallResult,\n\tStreamFn,\n\tThinkingLevel,\n} from \"./types.js\";\n\n/**\n * Default convertToLlm: Keep only LLM-compatible messages, convert attachments.\n */\nfunction defaultConvertToLlm(messages: AgentMessage[]): Message[] {\n\treturn messages.filter((m) => m.role === \"user\" || m.role === \"assistant\" || m.role === \"toolResult\");\n}\n\nexport interface AgentOptions {\n\tinitialState?: Partial<AgentState>;\n\n\t/**\n\t * Converts AgentMessage[] to LLM-compatible Message[] before each LLM call.\n\t * Default filters to user/assistant/toolResult and converts attachments.\n\t */\n\tconvertToLlm?: (messages: AgentMessage[]) => Message[] | Promise<Message[]>;\n\n\t/**\n\t * Optional transform applied to context before convertToLlm.\n\t * Use for context pruning, injecting external context, etc.\n\t */\n\ttransformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise<AgentMessage[]>;\n\n\t/**\n\t * Steering mode: \"all\" = send all steering messages at once, \"one-at-a-time\" = one per turn\n\t */\n\tsteeringMode?: \"all\" | \"one-at-a-time\";\n\n\t/**\n\t * Follow-up mode: \"all\" = send all follow-up messages at once, \"one-at-a-time\" = one per turn\n\t */\n\tfollowUpMode?: \"all\" | \"one-at-a-time\";\n\n\t/**\n\t * Custom stream function (for proxy backends, etc.). Default uses streamSimple.\n\t */\n\tstreamFn?: StreamFn;\n\n\t/**\n\t * Optional session identifier forwarded to LLM providers.\n\t * Used by providers that support session-based caching (e.g., OpenAI Codex).\n\t */\n\tsessionId?: string;\n\n\t/**\n\t * Resolves an API key dynamically for each LLM call.\n\t * Useful for expiring tokens (e.g., GitHub Copilot OAuth).\n\t */\n\tgetApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;\n\n\t/**\n\t * Inspect or replace provider payloads before they are sent.\n\t */\n\tonPayload?: SimpleStreamOptions[\"onPayload\"];\n\n\t/**\n\t * Custom token budgets for thinking levels (token-based providers only).\n\t */\n\tthinkingBudgets?: ThinkingBudgets;\n\n\t/**\n\t * Preferred transport for providers that support multiple transports.\n\t */\n\ttransport?: Transport;\n\n\t/**\n\t * Maximum delay in milliseconds to wait for a retry when the server requests a long wait.\n\t * If the server's requested delay exceeds this value, the request fails immediately,\n\t * allowing higher-level retry logic to handle it with user visibility.\n\t * Default: 60000 (60 seconds). Set to 0 to disable the cap.\n\t */\n\tmaxRetryDelayMs?: number;\n}\n\nexport class Agent {\n\tprivate _state: AgentState = {\n\t\tsystemPrompt: \"\",\n\t\tmodel: getModel(\"google\", \"gemini-2.5-flash-lite-preview-06-17\"),\n\t\tthinkingLevel: \"off\",\n\t\ttools: [],\n\t\tmessages: [],\n\t\tisStreaming: false,\n\t\tstreamMessage: null,\n\t\tpendingToolCalls: new Set<string>(),\n\t\terror: undefined,\n\t};\n\n\tprivate listeners = new Set<(e: AgentEvent) => void>();\n\tprivate abortController?: AbortController;\n\tprivate convertToLlm: (messages: AgentMessage[]) => Message[] | Promise<Message[]>;\n\tprivate transformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise<AgentMessage[]>;\n\tprivate steeringQueue: AgentMessage[] = [];\n\tprivate followUpQueue: AgentMessage[] = [];\n\tprivate steeringMode: \"all\" | \"one-at-a-time\";\n\tprivate followUpMode: \"all\" | \"one-at-a-time\";\n\tpublic streamFn: StreamFn;\n\tprivate _sessionId?: string;\n\tpublic getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;\n\tprivate _onPayload?: SimpleStreamOptions[\"onPayload\"];\n\tprivate runningPrompt?: Promise<void>;\n\tprivate resolveRunningPrompt?: () => void;\n\tprivate _thinkingBudgets?: ThinkingBudgets;\n\tprivate _transport: Transport;\n\tprivate _maxRetryDelayMs?: number;\n\tprivate _beforeToolCall?: AgentLoopConfig[\"beforeToolCall\"];\n\tprivate _afterToolCall?: AgentLoopConfig[\"afterToolCall\"];\n\n\tconstructor(opts: AgentOptions = {}) {\n\t\tthis._state = { ...this._state, ...opts.initialState };\n\t\tthis.convertToLlm = opts.convertToLlm || defaultConvertToLlm;\n\t\tthis.transformContext = opts.transformContext;\n\t\tthis.steeringMode = opts.steeringMode || \"one-at-a-time\";\n\t\tthis.followUpMode = opts.followUpMode || \"one-at-a-time\";\n\t\tthis.streamFn = opts.streamFn || streamSimple;\n\t\tthis._sessionId = opts.sessionId;\n\t\tthis.getApiKey = opts.getApiKey;\n\t\tthis._onPayload = opts.onPayload;\n\t\tthis._thinkingBudgets = opts.thinkingBudgets;\n\t\tthis._transport = opts.transport ?? \"sse\";\n\t\tthis._maxRetryDelayMs = opts.maxRetryDelayMs;\n\t}\n\n\t/**\n\t * Get the current session ID used for provider caching.\n\t */\n\tget sessionId(): string | undefined {\n\t\treturn this._sessionId;\n\t}\n\n\t/**\n\t * Set the session ID for provider caching.\n\t * Call this when switching sessions (new session, branch, resume).\n\t */\n\tset sessionId(value: string | undefined) {\n\t\tthis._sessionId = value;\n\t}\n\n\t/**\n\t * Get the current thinking budgets.\n\t */\n\tget thinkingBudgets(): ThinkingBudgets | undefined {\n\t\treturn this._thinkingBudgets;\n\t}\n\n\t/**\n\t * Set custom thinking budgets for token-based providers.\n\t */\n\tset thinkingBudgets(value: ThinkingBudgets | undefined) {\n\t\tthis._thinkingBudgets = value;\n\t}\n\n\t/**\n\t * Get the current preferred transport.\n\t */\n\tget transport(): Transport {\n\t\treturn this._transport;\n\t}\n\n\t/**\n\t * Set the preferred transport.\n\t */\n\tsetTransport(value: Transport) {\n\t\tthis._transport = value;\n\t}\n\n\t/**\n\t * Get the current max retry delay in milliseconds.\n\t */\n\tget maxRetryDelayMs(): number | undefined {\n\t\treturn this._maxRetryDelayMs;\n\t}\n\n\t/**\n\t * Set the maximum delay to wait for server-requested retries.\n\t * Set to 0 to disable the cap.\n\t */\n\tset maxRetryDelayMs(value: number | undefined) {\n\t\tthis._maxRetryDelayMs = value;\n\t}\n\n\t/**\n\t * Install a hook called before each tool executes, after argument validation.\n\t * Return `{ block: true }` to prevent execution.\n\t */\n\tsetBeforeToolCall(fn: AgentLoopConfig[\"beforeToolCall\"]): void {\n\t\tthis._beforeToolCall = fn;\n\t}\n\n\t/**\n\t * Install a hook called after each tool executes, before results are emitted.\n\t * Return field overrides for content/details/isError.\n\t */\n\tsetAfterToolCall(fn: AgentLoopConfig[\"afterToolCall\"]): void {\n\t\tthis._afterToolCall = fn;\n\t}\n\n\tget state(): AgentState {\n\t\treturn this._state;\n\t}\n\n\tsubscribe(fn: (e: AgentEvent) => void): () => void {\n\t\tthis.listeners.add(fn);\n\t\treturn () => this.listeners.delete(fn);\n\t}\n\n\t// State mutators\n\tsetSystemPrompt(v: string) {\n\t\tthis._state.systemPrompt = v;\n\t}\n\n\tsetModel(m: Model<any>) {\n\t\tthis._state.model = m;\n\t}\n\n\tsetThinkingLevel(l: ThinkingLevel) {\n\t\tthis._state.thinkingLevel = l;\n\t}\n\n\tsetSteeringMode(mode: \"all\" | \"one-at-a-time\") {\n\t\tthis.steeringMode = mode;\n\t}\n\n\tgetSteeringMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.steeringMode;\n\t}\n\n\tsetFollowUpMode(mode: \"all\" | \"one-at-a-time\") {\n\t\tthis.followUpMode = mode;\n\t}\n\n\tgetFollowUpMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.followUpMode;\n\t}\n\n\tsetTools(t: AgentTool<any>[]) {\n\t\tthis._state.tools = t;\n\t}\n\n\treplaceMessages(ms: AgentMessage[]) {\n\t\tthis._state.messages = ms.slice();\n\t}\n\n\tappendMessage(m: AgentMessage) {\n\t\tthis._state.messages = [...this._state.messages, m];\n\t}\n\n\t/**\n\t * Queue a steering message to interrupt the agent mid-run.\n\t * Delivered after current tool execution, skips remaining tools.\n\t */\n\tsteer(m: AgentMessage) {\n\t\tthis.steeringQueue.push(m);\n\t}\n\n\t/**\n\t * Queue a follow-up message to be processed after the agent finishes.\n\t * Delivered only when agent has no more tool calls or steering messages.\n\t */\n\tfollowUp(m: AgentMessage) {\n\t\tthis.followUpQueue.push(m);\n\t}\n\n\tclearSteeringQueue() {\n\t\tthis.steeringQueue = [];\n\t}\n\n\tclearFollowUpQueue() {\n\t\tthis.followUpQueue = [];\n\t}\n\n\tclearAllQueues() {\n\t\tthis.steeringQueue = [];\n\t\tthis.followUpQueue = [];\n\t}\n\n\thasQueuedMessages(): boolean {\n\t\treturn this.steeringQueue.length > 0 || this.followUpQueue.length > 0;\n\t}\n\n\tprivate dequeueSteeringMessages(): AgentMessage[] {\n\t\tif (this.steeringMode === \"one-at-a-time\") {\n\t\t\tif (this.steeringQueue.length > 0) {\n\t\t\t\tconst first = this.steeringQueue[0];\n\t\t\t\tthis.steeringQueue = this.steeringQueue.slice(1);\n\t\t\t\treturn [first];\n\t\t\t}\n\t\t\treturn [];\n\t\t}\n\n\t\tconst steering = this.steeringQueue.slice();\n\t\tthis.steeringQueue = [];\n\t\treturn steering;\n\t}\n\n\tprivate dequeueFollowUpMessages(): AgentMessage[] {\n\t\tif (this.followUpMode === \"one-at-a-time\") {\n\t\t\tif (this.followUpQueue.length > 0) {\n\t\t\t\tconst first = this.followUpQueue[0];\n\t\t\t\tthis.followUpQueue = this.followUpQueue.slice(1);\n\t\t\t\treturn [first];\n\t\t\t}\n\t\t\treturn [];\n\t\t}\n\n\t\tconst followUp = this.followUpQueue.slice();\n\t\tthis.followUpQueue = [];\n\t\treturn followUp;\n\t}\n\n\tclearMessages() {\n\t\tthis._state.messages = [];\n\t}\n\n\tabort() {\n\t\tthis.abortController?.abort();\n\t}\n\n\twaitForIdle(): Promise<void> {\n\t\treturn this.runningPrompt ?? Promise.resolve();\n\t}\n\n\treset() {\n\t\tthis._state.messages = [];\n\t\tthis._state.isStreaming = false;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\tthis._state.error = undefined;\n\t\tthis.steeringQueue = [];\n\t\tthis.followUpQueue = [];\n\t}\n\n\t/** Send a prompt with an AgentMessage */\n\tasync prompt(message: AgentMessage | AgentMessage[]): Promise<void>;\n\tasync prompt(input: string, images?: ImageContent[]): Promise<void>;\n\tasync prompt(input: string | AgentMessage | AgentMessage[], images?: ImageContent[]) {\n\t\tif (this._state.isStreaming) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.\",\n\t\t\t);\n\t\t}\n\n\t\tconst model = this._state.model;\n\t\tif (!model) throw new Error(\"No model configured\");\n\n\t\tlet msgs: AgentMessage[];\n\n\t\tif (Array.isArray(input)) {\n\t\t\tmsgs = input;\n\t\t} else if (typeof input === \"string\") {\n\t\t\tconst content: Array<TextContent | ImageContent> = [{ type: \"text\", text: input }];\n\t\t\tif (images && images.length > 0) {\n\t\t\t\tcontent.push(...images);\n\t\t\t}\n\t\t\tmsgs = [\n\t\t\t\t{\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t];\n\t\t} else {\n\t\t\tmsgs = [input];\n\t\t}\n\n\t\tawait this._runLoop(msgs);\n\t}\n\n\t/**\n\t * Continue from current context (used for retries and resuming queued messages).\n\t */\n\tasync continue() {\n\t\tif (this._state.isStreaming) {\n\t\t\tthrow new Error(\"Agent is already processing. Wait for completion before continuing.\");\n\t\t}\n\n\t\tconst messages = this._state.messages;\n\t\tif (messages.length === 0) {\n\t\t\tthrow new Error(\"No messages to continue from\");\n\t\t}\n\t\tif (messages[messages.length - 1].role === \"assistant\") {\n\t\t\tconst queuedSteering = this.dequeueSteeringMessages();\n\t\t\tif (queuedSteering.length > 0) {\n\t\t\t\tawait this._runLoop(queuedSteering, { skipInitialSteeringPoll: true });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst queuedFollowUp = this.dequeueFollowUpMessages();\n\t\t\tif (queuedFollowUp.length > 0) {\n\t\t\t\tawait this._runLoop(queuedFollowUp);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthrow new Error(\"Cannot continue from message role: assistant\");\n\t\t}\n\n\t\tawait this._runLoop(undefined);\n\t}\n\n\t/**\n\t * Run the agent loop.\n\t * If messages are provided, starts a new conversation turn with those messages.\n\t * Otherwise, continues from existing context.\n\t */\n\tprivate async _runLoop(messages?: AgentMessage[], options?: { skipInitialSteeringPoll?: boolean }) {\n\t\tconst model = this._state.model;\n\t\tif (!model) throw new Error(\"No model configured\");\n\n\t\tthis.runningPrompt = new Promise<void>((resolve) => {\n\t\t\tthis.resolveRunningPrompt = resolve;\n\t\t});\n\n\t\tthis.abortController = new AbortController();\n\t\tthis._state.isStreaming = true;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.error = undefined;\n\n\t\tconst reasoning = this._state.thinkingLevel === \"off\" ? undefined : this._state.thinkingLevel;\n\n\t\tconst context: AgentContext = {\n\t\t\tsystemPrompt: this._state.systemPrompt,\n\t\t\tmessages: this._state.messages.slice(),\n\t\t\ttools: this._state.tools,\n\t\t};\n\n\t\tlet skipInitialSteeringPoll = options?.skipInitialSteeringPoll === true;\n\n\t\tconst config: AgentLoopConfig = {\n\t\t\tmodel,\n\t\t\treasoning,\n\t\t\tsessionId: this._sessionId,\n\t\t\tonPayload: this._onPayload,\n\t\t\ttransport: this._transport,\n\t\t\tthinkingBudgets: this._thinkingBudgets,\n\t\t\tmaxRetryDelayMs: this._maxRetryDelayMs,\n\t\t\tconvertToLlm: this.convertToLlm,\n\t\t\ttransformContext: this.transformContext,\n\t\t\tgetApiKey: this.getApiKey,\n\t\t\tgetSteeringMessages: async () => {\n\t\t\t\tif (skipInitialSteeringPoll) {\n\t\t\t\t\tskipInitialSteeringPoll = false;\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\treturn this.dequeueSteeringMessages();\n\t\t\t},\n\t\t\tgetFollowUpMessages: async () => this.dequeueFollowUpMessages(),\n\t\t\tbeforeToolCall: this._beforeToolCall,\n\t\t\tafterToolCall: this._afterToolCall,\n\t\t};\n\n\t\tlet partial: AgentMessage | null = null;\n\n\t\ttry {\n\t\t\tconst stream = messages\n\t\t\t\t? agentLoop(messages, context, config, this.abortController.signal, this.streamFn)\n\t\t\t\t: agentLoopContinue(context, config, this.abortController.signal, this.streamFn);\n\n\t\t\tfor await (const event of stream) {\n\t\t\t\t// Update internal state based on events\n\t\t\t\tswitch (event.type) {\n\t\t\t\t\tcase \"message_start\":\n\t\t\t\t\tcase \"message_update\":\n\t\t\t\t\t\tpartial = event.message;\n\t\t\t\t\t\tthis._state.streamMessage = event.message;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"message_end\":\n\t\t\t\t\t\tpartial = null;\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tthis.appendMessage(event.message);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"tool_execution_start\":\n\t\t\t\t\t\tthis._updatePendingToolCalls(\"add\", event.toolCallId);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"tool_execution_end\":\n\t\t\t\t\t\tthis._updatePendingToolCalls(\"delete\", event.toolCallId);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"turn_end\":\n\t\t\t\t\t\tif (event.message.role === \"assistant\" && (event.message as any).errorMessage) {\n\t\t\t\t\t\t\tthis._state.error = (event.message as any).errorMessage;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"agent_end\":\n\t\t\t\t\t\tthis._state.isStreaming = false;\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Emit to listeners\n\t\t\t\tthis.emit(event);\n\t\t\t}\n\n\t\t\t// Handle any remaining partial message\n\t\t\tif (partial && partial.role === \"assistant\" && partial.content.length > 0) {\n\t\t\t\tconst onlyEmpty = !partial.content.some(\n\t\t\t\t\t(c) =>\n\t\t\t\t\t\t(c.type === \"thinking\" && c.thinking.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"text\" && c.text.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"toolCall\" && c.name.trim().length > 0),\n\t\t\t\t);\n\t\t\t\tif (!onlyEmpty) {\n\t\t\t\t\tthis.appendMessage(partial);\n\t\t\t\t} else {\n\t\t\t\t\tif (this.abortController?.signal.aborted) {\n\t\t\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err: any) {\n\t\t\tconst errorMsg: AgentMessage = {\n\t\t\t\trole: \"assistant\",\n\t\t\t\tcontent: [{ type: \"text\", text: \"\" }],\n\t\t\t\tapi: model.api,\n\t\t\t\tprovider: model.provider,\n\t\t\t\tmodel: model.id,\n\t\t\t\tusage: ZERO_USAGE,\n\t\t\t\tstopReason: this.abortController?.signal.aborted ? \"aborted\" : \"error\",\n\t\t\t\terrorMessage: err?.message || String(err),\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t} as AgentMessage;\n\n\t\t\tthis.appendMessage(errorMsg);\n\t\t\tthis._state.error = err?.message || String(err);\n\t\t\tthis.emit({ type: \"agent_end\", messages: [errorMsg] });\n\t\t} finally {\n\t\t\tthis._state.isStreaming = false;\n\t\t\tthis._state.streamMessage = null;\n\t\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\t\tthis.abortController = undefined;\n\t\t\tthis.resolveRunningPrompt?.();\n\t\t\tthis.runningPrompt = undefined;\n\t\t\tthis.resolveRunningPrompt = undefined;\n\t\t}\n\t}\n\n\tprivate _updatePendingToolCalls(action: \"add\" | \"delete\", id: string): void {\n\t\tconst s = new Set(this._state.pendingToolCalls);\n\t\ts[action](id);\n\t\tthis._state.pendingToolCalls = s;\n\t}\n\n\tprivate emit(e: AgentEvent) {\n\t\tfor (const listener of this.listeners) {\n\t\t\tlistener(e);\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Agent class that uses the agent-loop directly.\n * No transport abstraction - calls streamSimple via the loop.\n */\n\nimport {\n\tgetModel,\n\ttype ImageContent,\n\ttype Message,\n\ttype Model,\n\ttype SimpleStreamOptions,\n\tstreamSimple,\n\ttype TextContent,\n\ttype ThinkingBudgets,\n\ttype Transport,\n} from \"@gsd/pi-ai\";\nimport { agentLoop, agentLoopContinue, ZERO_USAGE } from \"./agent-loop.js\";\nimport type {\n\tAgentContext,\n\tAgentEvent,\n\tAgentLoopConfig,\n\tAgentMessage,\n\tAgentState,\n\tAgentTool,\n\tBeforeToolCallContext,\n\tBeforeToolCallResult,\n\tAfterToolCallContext,\n\tAfterToolCallResult,\n\tStreamFn,\n\tThinkingLevel,\n} from \"./types.js\";\n\n/**\n * Default convertToLlm: Keep only LLM-compatible messages, convert attachments.\n */\nfunction defaultConvertToLlm(messages: AgentMessage[]): Message[] {\n\treturn messages.filter((m) => m.role === \"user\" || m.role === \"assistant\" || m.role === \"toolResult\");\n}\n\nexport interface AgentOptions {\n\tinitialState?: Partial<AgentState>;\n\n\t/**\n\t * Converts AgentMessage[] to LLM-compatible Message[] before each LLM call.\n\t * Default filters to user/assistant/toolResult and converts attachments.\n\t */\n\tconvertToLlm?: (messages: AgentMessage[]) => Message[] | Promise<Message[]>;\n\n\t/**\n\t * Optional transform applied to context before convertToLlm.\n\t * Use for context pruning, injecting external context, etc.\n\t */\n\ttransformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise<AgentMessage[]>;\n\n\t/**\n\t * Steering mode: \"all\" = send all steering messages at once, \"one-at-a-time\" = one per turn\n\t */\n\tsteeringMode?: \"all\" | \"one-at-a-time\";\n\n\t/**\n\t * Follow-up mode: \"all\" = send all follow-up messages at once, \"one-at-a-time\" = one per turn\n\t */\n\tfollowUpMode?: \"all\" | \"one-at-a-time\";\n\n\t/**\n\t * Custom stream function (for proxy backends, etc.). Default uses streamSimple.\n\t */\n\tstreamFn?: StreamFn;\n\n\t/**\n\t * Optional session identifier forwarded to LLM providers.\n\t * Used by providers that support session-based caching (e.g., OpenAI Codex).\n\t */\n\tsessionId?: string;\n\n\t/**\n\t * Resolves an API key dynamically for each LLM call.\n\t * Useful for expiring tokens (e.g., GitHub Copilot OAuth).\n\t */\n\tgetApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;\n\n\t/**\n\t * Inspect or replace provider payloads before they are sent.\n\t */\n\tonPayload?: SimpleStreamOptions[\"onPayload\"];\n\n\t/**\n\t * Custom token budgets for thinking levels (token-based providers only).\n\t */\n\tthinkingBudgets?: ThinkingBudgets;\n\n\t/**\n\t * Preferred transport for providers that support multiple transports.\n\t */\n\ttransport?: Transport;\n\n\t/**\n\t * Maximum delay in milliseconds to wait for a retry when the server requests a long wait.\n\t * If the server's requested delay exceeds this value, the request fails immediately,\n\t * allowing higher-level retry logic to handle it with user visibility.\n\t * Default: 60000 (60 seconds). Set to 0 to disable the cap.\n\t */\n\tmaxRetryDelayMs?: number;\n}\n\n/**\n * Internal wrapper that tracks message origin for origin-aware queue clearing.\n * \"user\" = typed by human in TUI; \"system\" = generated by extensions/background jobs.\n */\ninterface QueueEntry {\n\tmessage: AgentMessage;\n\torigin: \"user\" | \"system\";\n}\n\nexport class Agent {\n\tprivate _state: AgentState = {\n\t\tsystemPrompt: \"\",\n\t\tmodel: getModel(\"google\", \"gemini-2.5-flash-lite-preview-06-17\"),\n\t\tthinkingLevel: \"off\",\n\t\ttools: [],\n\t\tmessages: [],\n\t\tisStreaming: false,\n\t\tstreamMessage: null,\n\t\tpendingToolCalls: new Set<string>(),\n\t\terror: undefined,\n\t};\n\n\tprivate listeners = new Set<(e: AgentEvent) => void>();\n\tprivate abortController?: AbortController;\n\tprivate convertToLlm: (messages: AgentMessage[]) => Message[] | Promise<Message[]>;\n\tprivate transformContext?: (messages: AgentMessage[], signal?: AbortSignal) => Promise<AgentMessage[]>;\n\tprivate steeringQueue: QueueEntry[] = [];\n\tprivate followUpQueue: QueueEntry[] = [];\n\tprivate steeringMode: \"all\" | \"one-at-a-time\";\n\tprivate followUpMode: \"all\" | \"one-at-a-time\";\n\tpublic streamFn: StreamFn;\n\tprivate _sessionId?: string;\n\tpublic getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;\n\tprivate _onPayload?: SimpleStreamOptions[\"onPayload\"];\n\tprivate runningPrompt?: Promise<void>;\n\tprivate resolveRunningPrompt?: () => void;\n\tprivate _thinkingBudgets?: ThinkingBudgets;\n\tprivate _transport: Transport;\n\tprivate _maxRetryDelayMs?: number;\n\tprivate _beforeToolCall?: AgentLoopConfig[\"beforeToolCall\"];\n\tprivate _afterToolCall?: AgentLoopConfig[\"afterToolCall\"];\n\n\tconstructor(opts: AgentOptions = {}) {\n\t\tthis._state = { ...this._state, ...opts.initialState };\n\t\tthis.convertToLlm = opts.convertToLlm || defaultConvertToLlm;\n\t\tthis.transformContext = opts.transformContext;\n\t\tthis.steeringMode = opts.steeringMode || \"one-at-a-time\";\n\t\tthis.followUpMode = opts.followUpMode || \"one-at-a-time\";\n\t\tthis.streamFn = opts.streamFn || streamSimple;\n\t\tthis._sessionId = opts.sessionId;\n\t\tthis.getApiKey = opts.getApiKey;\n\t\tthis._onPayload = opts.onPayload;\n\t\tthis._thinkingBudgets = opts.thinkingBudgets;\n\t\tthis._transport = opts.transport ?? \"sse\";\n\t\tthis._maxRetryDelayMs = opts.maxRetryDelayMs;\n\t}\n\n\t/**\n\t * Get the current session ID used for provider caching.\n\t */\n\tget sessionId(): string | undefined {\n\t\treturn this._sessionId;\n\t}\n\n\t/**\n\t * Set the session ID for provider caching.\n\t * Call this when switching sessions (new session, branch, resume).\n\t */\n\tset sessionId(value: string | undefined) {\n\t\tthis._sessionId = value;\n\t}\n\n\t/**\n\t * Get the current thinking budgets.\n\t */\n\tget thinkingBudgets(): ThinkingBudgets | undefined {\n\t\treturn this._thinkingBudgets;\n\t}\n\n\t/**\n\t * Set custom thinking budgets for token-based providers.\n\t */\n\tset thinkingBudgets(value: ThinkingBudgets | undefined) {\n\t\tthis._thinkingBudgets = value;\n\t}\n\n\t/**\n\t * Get the current preferred transport.\n\t */\n\tget transport(): Transport {\n\t\treturn this._transport;\n\t}\n\n\t/**\n\t * Set the preferred transport.\n\t */\n\tsetTransport(value: Transport) {\n\t\tthis._transport = value;\n\t}\n\n\t/**\n\t * Get the current max retry delay in milliseconds.\n\t */\n\tget maxRetryDelayMs(): number | undefined {\n\t\treturn this._maxRetryDelayMs;\n\t}\n\n\t/**\n\t * Set the maximum delay to wait for server-requested retries.\n\t * Set to 0 to disable the cap.\n\t */\n\tset maxRetryDelayMs(value: number | undefined) {\n\t\tthis._maxRetryDelayMs = value;\n\t}\n\n\t/**\n\t * Install a hook called before each tool executes, after argument validation.\n\t * Return `{ block: true }` to prevent execution.\n\t */\n\tsetBeforeToolCall(fn: AgentLoopConfig[\"beforeToolCall\"]): void {\n\t\tthis._beforeToolCall = fn;\n\t}\n\n\t/**\n\t * Install a hook called after each tool executes, before results are emitted.\n\t * Return field overrides for content/details/isError.\n\t */\n\tsetAfterToolCall(fn: AgentLoopConfig[\"afterToolCall\"]): void {\n\t\tthis._afterToolCall = fn;\n\t}\n\n\tget state(): AgentState {\n\t\treturn this._state;\n\t}\n\n\tsubscribe(fn: (e: AgentEvent) => void): () => void {\n\t\tthis.listeners.add(fn);\n\t\treturn () => this.listeners.delete(fn);\n\t}\n\n\t// State mutators\n\tsetSystemPrompt(v: string) {\n\t\tthis._state.systemPrompt = v;\n\t}\n\n\tsetModel(m: Model<any>) {\n\t\tthis._state.model = m;\n\t}\n\n\tsetThinkingLevel(l: ThinkingLevel) {\n\t\tthis._state.thinkingLevel = l;\n\t}\n\n\tsetSteeringMode(mode: \"all\" | \"one-at-a-time\") {\n\t\tthis.steeringMode = mode;\n\t}\n\n\tgetSteeringMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.steeringMode;\n\t}\n\n\tsetFollowUpMode(mode: \"all\" | \"one-at-a-time\") {\n\t\tthis.followUpMode = mode;\n\t}\n\n\tgetFollowUpMode(): \"all\" | \"one-at-a-time\" {\n\t\treturn this.followUpMode;\n\t}\n\n\tsetTools(t: AgentTool<any>[]) {\n\t\tthis._state.tools = t;\n\t}\n\n\treplaceMessages(ms: AgentMessage[]) {\n\t\tthis._state.messages = ms.slice();\n\t}\n\n\tappendMessage(m: AgentMessage) {\n\t\tthis._state.messages = [...this._state.messages, m];\n\t}\n\n\t/**\n\t * Queue a steering message to interrupt the agent mid-run.\n\t * Delivered after current tool execution, skips remaining tools.\n\t */\n\tsteer(m: AgentMessage, origin: \"user\" | \"system\" = \"system\") {\n\t\tthis.steeringQueue.push({ message: m, origin });\n\t}\n\n\t/**\n\t * Queue a follow-up message to be processed after the agent finishes.\n\t * Delivered only when agent has no more tool calls or steering messages.\n\t */\n\tfollowUp(m: AgentMessage, origin: \"user\" | \"system\" = \"system\") {\n\t\tthis.followUpQueue.push({ message: m, origin });\n\t}\n\n\tclearSteeringQueue() {\n\t\tthis.steeringQueue = [];\n\t}\n\n\tclearFollowUpQueue() {\n\t\tthis.followUpQueue = [];\n\t}\n\n\tclearAllQueues() {\n\t\tthis.steeringQueue = [];\n\t\tthis.followUpQueue = [];\n\t}\n\n\t/**\n\t * Drain user-origin messages from queues, leaving system messages in place.\n\t * Used during abort to preserve messages the user explicitly typed.\n\t */\n\tdrainUserMessages(): { steering: AgentMessage[]; followUp: AgentMessage[] } {\n\t\tconst userSteering = this.steeringQueue.filter((e) => e.origin === \"user\").map((e) => e.message);\n\t\tconst userFollowUp = this.followUpQueue.filter((e) => e.origin === \"user\").map((e) => e.message);\n\t\tthis.steeringQueue = this.steeringQueue.filter((e) => e.origin !== \"user\");\n\t\tthis.followUpQueue = this.followUpQueue.filter((e) => e.origin !== \"user\");\n\t\treturn { steering: userSteering, followUp: userFollowUp };\n\t}\n\n\thasQueuedMessages(): boolean {\n\t\treturn this.steeringQueue.length > 0 || this.followUpQueue.length > 0;\n\t}\n\n\tprivate dequeueSteeringMessages(): AgentMessage[] {\n\t\tif (this.steeringMode === \"one-at-a-time\") {\n\t\t\tif (this.steeringQueue.length > 0) {\n\t\t\t\tconst first = this.steeringQueue[0];\n\t\t\t\tthis.steeringQueue = this.steeringQueue.slice(1);\n\t\t\t\treturn [first.message];\n\t\t\t}\n\t\t\treturn [];\n\t\t}\n\n\t\tconst steering = this.steeringQueue.map((e) => e.message);\n\t\tthis.steeringQueue = [];\n\t\treturn steering;\n\t}\n\n\tprivate dequeueFollowUpMessages(): AgentMessage[] {\n\t\tif (this.followUpMode === \"one-at-a-time\") {\n\t\t\tif (this.followUpQueue.length > 0) {\n\t\t\t\tconst first = this.followUpQueue[0];\n\t\t\t\tthis.followUpQueue = this.followUpQueue.slice(1);\n\t\t\t\treturn [first.message];\n\t\t\t}\n\t\t\treturn [];\n\t\t}\n\n\t\tconst followUp = this.followUpQueue.map((e) => e.message);\n\t\tthis.followUpQueue = [];\n\t\treturn followUp;\n\t}\n\n\tclearMessages() {\n\t\tthis._state.messages = [];\n\t}\n\n\tabort() {\n\t\tthis.abortController?.abort();\n\t}\n\n\twaitForIdle(): Promise<void> {\n\t\treturn this.runningPrompt ?? Promise.resolve();\n\t}\n\n\treset() {\n\t\tthis._state.messages = [];\n\t\tthis._state.isStreaming = false;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\tthis._state.error = undefined;\n\t\tthis.steeringQueue = [];\n\t\tthis.followUpQueue = [];\n\t}\n\n\t/** Send a prompt with an AgentMessage */\n\tasync prompt(message: AgentMessage | AgentMessage[]): Promise<void>;\n\tasync prompt(input: string, images?: ImageContent[]): Promise<void>;\n\tasync prompt(input: string | AgentMessage | AgentMessage[], images?: ImageContent[]) {\n\t\tif (this._state.isStreaming) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.\",\n\t\t\t);\n\t\t}\n\n\t\tconst model = this._state.model;\n\t\tif (!model) throw new Error(\"No model configured\");\n\n\t\tlet msgs: AgentMessage[];\n\n\t\tif (Array.isArray(input)) {\n\t\t\tmsgs = input;\n\t\t} else if (typeof input === \"string\") {\n\t\t\tconst content: Array<TextContent | ImageContent> = [{ type: \"text\", text: input }];\n\t\t\tif (images && images.length > 0) {\n\t\t\t\tcontent.push(...images);\n\t\t\t}\n\t\t\tmsgs = [\n\t\t\t\t{\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t];\n\t\t} else {\n\t\t\tmsgs = [input];\n\t\t}\n\n\t\tawait this._runLoop(msgs);\n\t}\n\n\t/**\n\t * Continue from current context (used for retries and resuming queued messages).\n\t */\n\tasync continue() {\n\t\tif (this._state.isStreaming) {\n\t\t\tthrow new Error(\"Agent is already processing. Wait for completion before continuing.\");\n\t\t}\n\n\t\tconst messages = this._state.messages;\n\t\tif (messages.length === 0) {\n\t\t\tthrow new Error(\"No messages to continue from\");\n\t\t}\n\t\tif (messages[messages.length - 1].role === \"assistant\") {\n\t\t\tconst queuedSteering = this.dequeueSteeringMessages();\n\t\t\tif (queuedSteering.length > 0) {\n\t\t\t\tawait this._runLoop(queuedSteering, { skipInitialSteeringPoll: true });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst queuedFollowUp = this.dequeueFollowUpMessages();\n\t\t\tif (queuedFollowUp.length > 0) {\n\t\t\t\tawait this._runLoop(queuedFollowUp);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthrow new Error(\"Cannot continue from message role: assistant\");\n\t\t}\n\n\t\tawait this._runLoop(undefined);\n\t}\n\n\t/**\n\t * Run the agent loop.\n\t * If messages are provided, starts a new conversation turn with those messages.\n\t * Otherwise, continues from existing context.\n\t */\n\tprivate async _runLoop(messages?: AgentMessage[], options?: { skipInitialSteeringPoll?: boolean }) {\n\t\tconst model = this._state.model;\n\t\tif (!model) throw new Error(\"No model configured\");\n\n\t\tthis.runningPrompt = new Promise<void>((resolve) => {\n\t\t\tthis.resolveRunningPrompt = resolve;\n\t\t});\n\n\t\tthis.abortController = new AbortController();\n\t\tthis._state.isStreaming = true;\n\t\tthis._state.streamMessage = null;\n\t\tthis._state.error = undefined;\n\n\t\tconst reasoning = this._state.thinkingLevel === \"off\" ? undefined : this._state.thinkingLevel;\n\n\t\tconst context: AgentContext = {\n\t\t\tsystemPrompt: this._state.systemPrompt,\n\t\t\tmessages: this._state.messages.slice(),\n\t\t\ttools: this._state.tools,\n\t\t};\n\n\t\tlet skipInitialSteeringPoll = options?.skipInitialSteeringPoll === true;\n\n\t\tconst config: AgentLoopConfig = {\n\t\t\tmodel,\n\t\t\treasoning,\n\t\t\tsessionId: this._sessionId,\n\t\t\tonPayload: this._onPayload,\n\t\t\ttransport: this._transport,\n\t\t\tthinkingBudgets: this._thinkingBudgets,\n\t\t\tmaxRetryDelayMs: this._maxRetryDelayMs,\n\t\t\tconvertToLlm: this.convertToLlm,\n\t\t\ttransformContext: this.transformContext,\n\t\t\tgetApiKey: this.getApiKey,\n\t\t\tgetSteeringMessages: async () => {\n\t\t\t\tif (skipInitialSteeringPoll) {\n\t\t\t\t\tskipInitialSteeringPoll = false;\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t\treturn this.dequeueSteeringMessages();\n\t\t\t},\n\t\t\tgetFollowUpMessages: async () => this.dequeueFollowUpMessages(),\n\t\t\tbeforeToolCall: this._beforeToolCall,\n\t\t\tafterToolCall: this._afterToolCall,\n\t\t};\n\n\t\tlet partial: AgentMessage | null = null;\n\n\t\ttry {\n\t\t\tconst stream = messages\n\t\t\t\t? agentLoop(messages, context, config, this.abortController.signal, this.streamFn)\n\t\t\t\t: agentLoopContinue(context, config, this.abortController.signal, this.streamFn);\n\n\t\t\tfor await (const event of stream) {\n\t\t\t\t// Update internal state based on events\n\t\t\t\tswitch (event.type) {\n\t\t\t\t\tcase \"message_start\":\n\t\t\t\t\tcase \"message_update\":\n\t\t\t\t\t\tpartial = event.message;\n\t\t\t\t\t\tthis._state.streamMessage = event.message;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"message_end\":\n\t\t\t\t\t\tpartial = null;\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tthis.appendMessage(event.message);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"tool_execution_start\":\n\t\t\t\t\t\tthis._updatePendingToolCalls(\"add\", event.toolCallId);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"tool_execution_end\":\n\t\t\t\t\t\tthis._updatePendingToolCalls(\"delete\", event.toolCallId);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"turn_end\":\n\t\t\t\t\t\tif (event.message.role === \"assistant\" && (event.message as any).errorMessage) {\n\t\t\t\t\t\t\tthis._state.error = (event.message as any).errorMessage;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"agent_end\":\n\t\t\t\t\t\tthis._state.isStreaming = false;\n\t\t\t\t\t\tthis._state.streamMessage = null;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Emit to listeners\n\t\t\t\tthis.emit(event);\n\t\t\t}\n\n\t\t\t// Handle any remaining partial message\n\t\t\tif (partial && partial.role === \"assistant\" && partial.content.length > 0) {\n\t\t\t\tconst onlyEmpty = !partial.content.some(\n\t\t\t\t\t(c) =>\n\t\t\t\t\t\t(c.type === \"thinking\" && c.thinking.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"text\" && c.text.trim().length > 0) ||\n\t\t\t\t\t\t(c.type === \"toolCall\" && c.name.trim().length > 0),\n\t\t\t\t);\n\t\t\t\tif (!onlyEmpty) {\n\t\t\t\t\tthis.appendMessage(partial);\n\t\t\t\t} else {\n\t\t\t\t\tif (this.abortController?.signal.aborted) {\n\t\t\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err: any) {\n\t\t\tconst errorMsg: AgentMessage = {\n\t\t\t\trole: \"assistant\",\n\t\t\t\tcontent: [{ type: \"text\", text: \"\" }],\n\t\t\t\tapi: model.api,\n\t\t\t\tprovider: model.provider,\n\t\t\t\tmodel: model.id,\n\t\t\t\tusage: ZERO_USAGE,\n\t\t\t\tstopReason: this.abortController?.signal.aborted ? \"aborted\" : \"error\",\n\t\t\t\terrorMessage: err?.message || String(err),\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t} as AgentMessage;\n\n\t\t\tthis.appendMessage(errorMsg);\n\t\t\tthis._state.error = err?.message || String(err);\n\t\t\tthis.emit({ type: \"agent_end\", messages: [errorMsg] });\n\t\t} finally {\n\t\t\tthis._state.isStreaming = false;\n\t\t\tthis._state.streamMessage = null;\n\t\t\tthis._state.pendingToolCalls = new Set<string>();\n\t\t\tthis.abortController = undefined;\n\t\t\tthis.resolveRunningPrompt?.();\n\t\t\tthis.runningPrompt = undefined;\n\t\t\tthis.resolveRunningPrompt = undefined;\n\t\t}\n\t}\n\n\tprivate _updatePendingToolCalls(action: \"add\" | \"delete\", id: string): void {\n\t\tconst s = new Set(this._state.pendingToolCalls);\n\t\ts[action](id);\n\t\tthis._state.pendingToolCalls = s;\n\t}\n\n\tprivate emit(e: AgentEvent) {\n\t\tfor (const listener of this.listeners) {\n\t\t\tlistener(e);\n\t\t}\n\t}\n}\n"]}
|