@oh-my-pi/pi-coding-agent 17.3.4 → 17.3.7
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 +88 -0
- package/dist/{CHANGELOG-trcc215s.md → CHANGELOG-1hmwwt45.md} +88 -0
- package/dist/cli.js +3156 -3163
- package/dist/docs-index.generated.txt +1 -1
- package/dist/types/cli/stats-cli.d.ts +1 -6
- package/dist/types/commands/stats.d.ts +4 -0
- package/dist/types/config/model-discovery.d.ts +2 -0
- package/dist/types/config/model-registry.d.ts +6 -1
- package/dist/types/config/settings-schema.d.ts +10 -0
- package/dist/types/debug/report-bundle.d.ts +7 -2
- package/dist/types/extensibility/extensions/loader.d.ts +2 -0
- package/dist/types/extensibility/extensions/runner.d.ts +24 -6
- package/dist/types/extensibility/extensions/types.d.ts +60 -0
- package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +4 -0
- package/dist/types/launch/presence.d.ts +11 -0
- package/dist/types/lsp/client.d.ts +22 -0
- package/dist/types/lsp/workspace-diagnostics.d.ts +2 -0
- package/dist/types/mcp/config.d.ts +3 -1
- package/dist/types/modes/components/tool-execution.d.ts +3 -1
- package/dist/types/registry/agent-lifecycle.d.ts +11 -0
- package/dist/types/registry/agent-registry.d.ts +4 -0
- package/dist/types/session/agent-session-types.d.ts +0 -2
- package/dist/types/session/agent-session.d.ts +20 -0
- package/dist/types/session/date-cwd-reminder.d.ts +22 -0
- package/dist/types/session/irc-bridge.d.ts +2 -0
- package/dist/types/session/messages.d.ts +4 -0
- package/dist/types/session/session-loader.d.ts +18 -11
- package/dist/types/session/session-maintenance.d.ts +6 -2
- package/dist/types/session/session-manager.d.ts +19 -3
- package/dist/types/session/session-tools.d.ts +0 -1
- package/dist/types/session/turn-recovery.d.ts +7 -7
- package/dist/types/slash-commands/helpers/stats-dashboard.d.ts +1 -0
- package/dist/types/tools/browser/attach.d.ts +16 -0
- package/dist/types/tools/browser/launch.d.ts +2 -2
- package/dist/types/tools/browser.d.ts +1 -1
- package/dist/types/tools/builtin-names.d.ts +1 -1
- package/dist/types/tools/file-write-fallback.d.ts +124 -0
- package/dist/types/tools/hub/jobs.d.ts +6 -0
- package/dist/types/tools/hub/types.d.ts +6 -0
- package/dist/types/tools/index.d.ts +1 -0
- package/dist/types/tools/path-utils.d.ts +23 -0
- package/dist/types/vibe/runtime.d.ts +3 -3
- package/package.json +13 -13
- package/src/auto-thinking/classifier.ts +37 -23
- package/src/cli/models-cli.ts +1 -1
- package/src/cli/stats-cli.ts +6 -72
- package/src/commands/stats.ts +7 -4
- package/src/commit/analysis/conventional.ts +15 -9
- package/src/commit/analysis/summary.ts +15 -9
- package/src/commit/changelog/generate.ts +15 -9
- package/src/commit/map-reduce/map-phase.ts +3 -19
- package/src/commit/map-reduce/reduce-phase.ts +15 -9
- package/src/config/model-discovery.ts +3 -3
- package/src/config/model-registry.ts +29 -16
- package/src/config/settings-schema.ts +13 -0
- package/src/debug/report-bundle.ts +25 -59
- package/src/discovery/claude-plugins.ts +2 -1
- package/src/discovery/claude.ts +4 -2
- package/src/discovery/helpers.ts +5 -0
- package/src/edit/hashline/filesystem.ts +9 -3
- package/src/edit/modes/patch.ts +31 -5
- package/src/edit/renderer.ts +48 -19
- package/src/extensibility/extensions/loader.ts +20 -5
- package/src/extensibility/extensions/runner.ts +239 -24
- package/src/extensibility/extensions/types.ts +62 -0
- package/src/extensibility/extensions/wrapper.ts +26 -11
- package/src/extensibility/legacy-pi-ai-shim.ts +4 -0
- package/src/extensibility/plugins/marketplace/manager.ts +15 -18
- package/src/irc/bus.ts +1 -1
- package/src/launch/broker.ts +8 -1
- package/src/launch/presence.ts +77 -1
- package/src/lsp/client.ts +35 -3
- package/src/lsp/clients/biome-client.ts +47 -93
- package/src/lsp/servers.ts +17 -11
- package/src/lsp/tool.ts +2 -4
- package/src/lsp/workspace-diagnostics.ts +24 -2
- package/src/lsp/writethrough.ts +20 -10
- package/src/mcp/config.ts +50 -6
- package/src/memories/index.ts +29 -25
- package/src/mnemopi/backend.ts +13 -11
- package/src/modes/components/ask-dialog.ts +25 -5
- package/src/modes/components/tool-execution.ts +10 -6
- package/src/modes/components/welcome.ts +4 -1
- package/src/modes/controllers/extension-ui-controller.ts +52 -32
- package/src/modes/controllers/selector-controller.ts +6 -0
- package/src/modes/controllers/tan-command-controller.ts +1 -0
- package/src/modes/interactive-mode.ts +49 -10
- package/src/modes/theme/defaults/birch.json +2 -2
- package/src/prompts/system/checkpoint-active-notice.md +5 -0
- package/src/prompts/system/date-cwd-reminder.md +3 -0
- package/src/prompts/system/project-prompt.md +0 -1
- package/src/prompts/system/rewind-report.md +1 -3
- package/src/prompts/tools/browser.md +1 -0
- package/src/prompts/tools/rewind.md +1 -13
- package/src/registry/agent-lifecycle.ts +34 -0
- package/src/registry/agent-registry.ts +27 -2
- package/src/registry/persisted-agents.ts +40 -20
- package/src/sdk.ts +32 -2
- package/src/session/agent-session-types.ts +0 -2
- package/src/session/agent-session.ts +178 -46
- package/src/session/date-cwd-reminder.ts +77 -0
- package/src/session/irc-bridge.ts +5 -0
- package/src/session/messages.ts +5 -1
- package/src/session/session-loader.ts +106 -64
- package/src/session/session-maintenance.ts +189 -115
- package/src/session/session-manager.ts +142 -35
- package/src/session/session-persistence.ts +4 -4
- package/src/session/session-storage.ts +18 -5
- package/src/session/session-tools.ts +5 -10
- package/src/session/turn-recovery.ts +102 -20
- package/src/session/unexpected-stop-classifier.ts +33 -21
- package/src/slash-commands/builtin-session.ts +1 -1
- package/src/slash-commands/helpers/stats-dashboard.ts +23 -9
- package/src/system-prompt.ts +0 -5
- package/src/task/executor.ts +4 -15
- package/src/task/persisted-revive.ts +3 -6
- package/src/tools/ask.ts +10 -3
- package/src/tools/browser/attach.ts +80 -25
- package/src/tools/browser/launch.ts +44 -15
- package/src/tools/browser/relay/daemon.ts +3 -7
- package/src/tools/browser/render.ts +1 -1
- package/src/tools/browser/shared-daemon.ts +3 -7
- package/src/tools/browser.ts +5 -5
- package/src/tools/builtin-names.ts +7 -3
- package/src/tools/checkpoint.ts +1 -7
- package/src/tools/file-write-fallback.ts +467 -0
- package/src/tools/hub/index.ts +1 -1
- package/src/tools/hub/jobs.ts +20 -3
- package/src/tools/hub/types.ts +6 -0
- package/src/tools/index.ts +1 -0
- package/src/tools/path-utils.ts +79 -0
- package/src/tools/render-utils.ts +53 -21
- package/src/tools/think.ts +15 -3
- package/src/tts/speech-enhancer.ts +19 -14
- package/src/utils/commit-message-generator.ts +14 -12
- package/src/utils/title-generator.ts +23 -19
- package/src/vibe/runtime.ts +32 -17
|
@@ -47,7 +47,6 @@ Additional workspace directories. This CURRENT workspace state supersedes worksp
|
|
|
47
47
|
{{/each}}
|
|
48
48
|
</workspace-roots>
|
|
49
49
|
{{/if}}
|
|
50
|
-
Today: {{date}}; current working directory: '{{cwd}}'.
|
|
51
50
|
|
|
52
51
|
<critical>
|
|
53
52
|
- Each response MUST advance the task; completion only stopping condition.
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
Checkpoint
|
|
2
|
-
Context: branch summary and retained report below.
|
|
3
|
-
NEVER call `rewind` again for this checkpoint; continue from retained report.
|
|
1
|
+
Checkpoint called and rewound. Report retained below. Need explore again → new `checkpoint`.
|
|
4
2
|
|
|
5
3
|
Report:
|
|
6
4
|
{{report}}
|
|
@@ -21,6 +21,7 @@ Drives real Chromium tab; full puppeteer access via JS.
|
|
|
21
21
|
|
|
22
22
|
- `app.path` → NEVER tamper with a real desktop app (no stealth patches).
|
|
23
23
|
- `app.relay: true` → drive the user's own Chrome tabs via the omp browser relay (auto-started; needs the OMP Browser Relay extension installed). `app.target` picks a tab by URL/title substring; without it the visible tab is adopted without stealing focus.
|
|
24
|
+
- `close` releases the named tool session. It closes tool-owned headless pages and owned cmux surfaces, but NEVER closes pages in CDP-connected or relay browsers. Spawned-browser pages remain open unless `kill: true` terminates their process.
|
|
24
25
|
- Selectors: CSS + puppeteer `aria/…`, `text/…`, `xpath/…`, `pierce/…`. Playwright-only pseudos (`:has-text()`, `:visible`) are REJECTED.
|
|
25
26
|
</instruction>
|
|
26
27
|
|
|
@@ -1,13 +1 @@
|
|
|
1
|
-
End active checkpoint; rewind context to it, replacing intermediate exploration with your report.
|
|
2
|
-
|
|
3
|
-
Call immediately after investigative work started by `checkpoint`.
|
|
4
|
-
|
|
5
|
-
Requirements:
|
|
6
|
-
- `report` MUST be concise, factual, actionable; include key findings, decisions, unresolved risks.
|
|
7
|
-
- AVOID raw scratch logs unless essential.
|
|
8
|
-
- MUST call before yielding if checkpoint active.
|
|
9
|
-
|
|
10
|
-
Behavior:
|
|
11
|
-
- No active checkpoint → error. Checkpoint already rewound → continue from retained report; NEVER retry.
|
|
12
|
-
- Success → session rewinds, retains your report as context, closes checkpoint.
|
|
13
|
-
- Successful rewind final for that checkpoint; repeat calls error.
|
|
1
|
+
End the active checkpoint; rewind context to it, replacing intermediate exploration with your report.
|
|
@@ -174,6 +174,40 @@ export class AgentLifecycleManager {
|
|
|
174
174
|
);
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Reclaim a provably-dead parked corpse so a fresh spawn can reuse its id.
|
|
179
|
+
* Refuses live, adopted, in-flight, or cold-revivable refs. For a parked ref
|
|
180
|
+
* restored from disk, the persisted factory is consulted before removal
|
|
181
|
+
* because cold revivers are created lazily by {@link ensureLive}.
|
|
182
|
+
*
|
|
183
|
+
* Only refs in the registry this manager owns are touched; the transcript
|
|
184
|
+
* stays readable at `history://<id>`. Returns true when the corpse was
|
|
185
|
+
* unregistered.
|
|
186
|
+
*/
|
|
187
|
+
async reclaimDeadCorpse(id: string, expected: AgentRef): Promise<boolean> {
|
|
188
|
+
const ref = this.#registry.get(id);
|
|
189
|
+
if (ref !== expected || ref.status !== "parked" || ref.session) return false;
|
|
190
|
+
if (this.#adopted.has(id) || this.#parks.has(id) || this.#revivals.has(id)) return false;
|
|
191
|
+
|
|
192
|
+
const persistedFactory = ref.sessionFile ? this.#persistedReviverFactory : undefined;
|
|
193
|
+
if (persistedFactory) {
|
|
194
|
+
try {
|
|
195
|
+
if (await persistedFactory(ref)) return false;
|
|
196
|
+
} catch (error) {
|
|
197
|
+
logger.warn("AgentLifecycleManager.reclaimDeadCorpse: persisted reviver probe failed", {
|
|
198
|
+
id,
|
|
199
|
+
error: error instanceof Error ? error.message : String(error),
|
|
200
|
+
});
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
// The factory awaited I/O; another lifecycle operation may now own or
|
|
204
|
+
// have replaced this ref. Revalidate every reclaim invariant.
|
|
205
|
+
if (this.#registry.get(id) !== ref || ref.status !== "parked" || ref.session) return false;
|
|
206
|
+
if (this.#adopted.has(id) || this.#parks.has(id) || this.#revivals.has(id)) return false;
|
|
207
|
+
}
|
|
208
|
+
return this.#registry.unregister(id, ref);
|
|
209
|
+
}
|
|
210
|
+
|
|
177
211
|
/**
|
|
178
212
|
* True when this manager owns `registry` — i.e. its adopt/park/revive state
|
|
179
213
|
* describes that registry's refs. Lets a caller holding a specific registry
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* revival) and are only removed on explicit release/teardown.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { logger } from "@oh-my-pi/pi-utils";
|
|
12
13
|
import type { AgentSession } from "../session/agent-session";
|
|
13
14
|
import { oneLineLabel } from "../task/types";
|
|
14
15
|
|
|
@@ -135,6 +136,11 @@ export class AgentRegistry {
|
|
|
135
136
|
return expected === undefined || ref === expected || ref.session === expected;
|
|
136
137
|
}
|
|
137
138
|
|
|
139
|
+
#rejectStatusUpdate(id: string, status: AgentStatus, reason: string): false {
|
|
140
|
+
logger.debug("Agent registry status update rejected", { id, status, reason });
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
138
144
|
register(input: RegisterInput): AgentRef {
|
|
139
145
|
const now = Date.now();
|
|
140
146
|
const ref: AgentRef = {
|
|
@@ -181,10 +187,15 @@ export class AgentRegistry {
|
|
|
181
187
|
|
|
182
188
|
setStatus(id: string, status: AgentStatus, expected?: AgentRefExpectation): boolean {
|
|
183
189
|
const ref = this.#refs.get(id);
|
|
184
|
-
if (!ref
|
|
190
|
+
if (!ref) return this.#rejectStatusUpdate(id, status, "missing-ref");
|
|
191
|
+
if (!this.#matchesExpected(ref, expected)) {
|
|
192
|
+
return this.#rejectStatusUpdate(id, status, "session-ownership-changed");
|
|
193
|
+
}
|
|
185
194
|
// `aborted` is terminal: delayed progress/revival work from the killed
|
|
186
195
|
// generation must never transition the tombstone back to a live status.
|
|
187
|
-
if (ref.status === "aborted")
|
|
196
|
+
if (ref.status === "aborted") {
|
|
197
|
+
return status === "aborted" || this.#rejectStatusUpdate(id, status, "aborted-is-terminal");
|
|
198
|
+
}
|
|
188
199
|
if (ref.status === status) return true;
|
|
189
200
|
ref.status = status;
|
|
190
201
|
// Activity describes current work; it is meaningless once the agent
|
|
@@ -270,6 +281,20 @@ export class AgentRegistry {
|
|
|
270
281
|
);
|
|
271
282
|
}
|
|
272
283
|
|
|
284
|
+
/** Whether a ref's claimed running state is corroborated by its attached live session. */
|
|
285
|
+
isRunning(ref: AgentRef): boolean {
|
|
286
|
+
if (ref.status !== "running") return false;
|
|
287
|
+
return ref.session?.isStreaming === true;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** Mirror a session's authoritative run-state notifications into its owned registry ref. */
|
|
291
|
+
syncSessionStatus(id: string, session: AgentSession): () => void {
|
|
292
|
+
const unsubscribe = session.subscribeRunState(status => {
|
|
293
|
+
this.setStatus(id, status, session);
|
|
294
|
+
});
|
|
295
|
+
return unsubscribe;
|
|
296
|
+
}
|
|
297
|
+
|
|
273
298
|
onChange(listener: RegistryListener): () => void {
|
|
274
299
|
this.#listeners.add(listener);
|
|
275
300
|
return () => this.#listeners.delete(listener);
|
|
@@ -25,6 +25,8 @@ interface PersistedAgentMetadata {
|
|
|
25
25
|
createdAt?: number;
|
|
26
26
|
lastActivity?: number;
|
|
27
27
|
history?: AgentHistorySummary;
|
|
28
|
+
/** True when the file is only a SessionManager header (no session_init, no messages). */
|
|
29
|
+
incomplete?: boolean;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
interface PersistedTranscript {
|
|
@@ -244,6 +246,8 @@ async function readPersistedAgentMetadata(sessionFile: string): Promise<Persiste
|
|
|
244
246
|
let createdAt: number | undefined;
|
|
245
247
|
let activity: string | undefined;
|
|
246
248
|
let history: AgentHistorySummary = {};
|
|
249
|
+
let hasSessionInit = false;
|
|
250
|
+
let hasConversation = false;
|
|
247
251
|
try {
|
|
248
252
|
await visitEntriesFromFileStream(
|
|
249
253
|
sessionFile,
|
|
@@ -264,7 +268,12 @@ async function readPersistedAgentMetadata(sessionFile: string): Promise<Persiste
|
|
|
264
268
|
}
|
|
265
269
|
return;
|
|
266
270
|
}
|
|
271
|
+
if (record.type === "message" || record.type === "custom_message") {
|
|
272
|
+
hasConversation = true;
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
267
275
|
if (record.type !== "session_init") return;
|
|
276
|
+
hasSessionInit = true;
|
|
268
277
|
createdAt ??= timestampOf(record.timestamp);
|
|
269
278
|
if (typeof record.task === "string") activity = summarizePersistedTask(record.task);
|
|
270
279
|
const inferred = typeof record.systemPrompt === "string" ? inferBundledAgent(record.systemPrompt) : {};
|
|
@@ -290,6 +299,7 @@ async function readPersistedAgentMetadata(sessionFile: string): Promise<Persiste
|
|
|
290
299
|
activity,
|
|
291
300
|
createdAt: createdAt ?? file?.birthtimeMs,
|
|
292
301
|
lastActivity: file?.mtimeMs,
|
|
302
|
+
incomplete: !hasSessionInit && !hasConversation,
|
|
293
303
|
history: {
|
|
294
304
|
...history,
|
|
295
305
|
...(hasOutput ? { outputPath } : {}),
|
|
@@ -425,26 +435,36 @@ async function registerPersistedSubagentsFromDir(
|
|
|
425
435
|
if (!registry.get(id)) {
|
|
426
436
|
const metadata = await readPersistedAgentMetadata(sessionFile);
|
|
427
437
|
if (!shouldContinue()) return;
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
438
|
+
// Metadata reads yield. A spawn may claim the id while this scan is
|
|
439
|
+
// inspecting the file; never replace that live generation with a
|
|
440
|
+
// transcript-derived parked ref.
|
|
441
|
+
const unclaimed = !registry.get(id);
|
|
442
|
+
// SessionManager.open writes title+session before createAgentSession
|
|
443
|
+
// claims the id. Parking that stub makes the spawn's expectedAgentRef:null
|
|
444
|
+
// CAS fail with "already owned by another session generation".
|
|
445
|
+
if (unclaimed && metadata.incomplete && !tombstoned) continue;
|
|
446
|
+
if (unclaimed) {
|
|
447
|
+
registry.register({
|
|
448
|
+
id,
|
|
449
|
+
displayName: id,
|
|
450
|
+
kind: "sub",
|
|
451
|
+
parentId: parentId ?? MAIN_AGENT_ID,
|
|
452
|
+
session: null,
|
|
453
|
+
sessionFile,
|
|
454
|
+
activity: metadata.activity,
|
|
455
|
+
createdAt: metadata.createdAt,
|
|
456
|
+
lastActivity: metadata.lastActivity,
|
|
457
|
+
history: metadata.history,
|
|
458
|
+
status: tombstoned ? "aborted" : "parked",
|
|
459
|
+
});
|
|
460
|
+
const ref = registry.get(id);
|
|
461
|
+
transcripts.push({
|
|
462
|
+
id,
|
|
463
|
+
sessionFile,
|
|
464
|
+
createdAt: ref?.createdAt,
|
|
465
|
+
lastActivity: ref?.lastActivity,
|
|
466
|
+
});
|
|
467
|
+
}
|
|
448
468
|
}
|
|
449
469
|
await registerPersistedSubagentsFromDir(
|
|
450
470
|
registry,
|
package/src/sdk.ts
CHANGED
|
@@ -136,6 +136,7 @@ import {
|
|
|
136
136
|
import { AgentSession, type InitialRetryFallbackState, type PlanYolo, type Prewalk } from "./session/agent-session";
|
|
137
137
|
import { discoverAuthStorage as discoverAuthStorageFromConfig } from "./session/auth-broker-config";
|
|
138
138
|
import type { AuthStorage } from "./session/auth-storage";
|
|
139
|
+
import { withDateCwdReminder } from "./session/date-cwd-reminder";
|
|
139
140
|
import { createInterruptedTurnAbortMessage } from "./session/exit-diagnostics";
|
|
140
141
|
import {
|
|
141
142
|
type CustomMessage,
|
|
@@ -222,6 +223,8 @@ import { ttsTool } from "./tools/tts";
|
|
|
222
223
|
import { resolveActiveRepoContext } from "./utils/active-repo-context";
|
|
223
224
|
import { EventBus } from "./utils/event-bus";
|
|
224
225
|
import { normalizeProviderContextImagesForModel } from "./utils/image-loading";
|
|
226
|
+
import { formatLocalCalendarDate } from "./utils/local-date";
|
|
227
|
+
import { normalizePromptPath } from "./utils/prompt-path";
|
|
225
228
|
import { buildNamedToolChoice } from "./utils/tool-choice";
|
|
226
229
|
import { VibeSessionRegistry } from "./vibe/runtime";
|
|
227
230
|
import { buildWorkspaceTree, type WorkspaceTree } from "./workspace-tree";
|
|
@@ -3034,6 +3037,20 @@ async function createAgentSessionScoped(options: CreateAgentSessionOptions): Pro
|
|
|
3034
3037
|
options.expectedAgentRef === undefined
|
|
3035
3038
|
? agentRegistry.register(registrationInput)
|
|
3036
3039
|
: agentRegistry.registerIfAvailable(registrationInput, options.expectedAgentRef);
|
|
3040
|
+
if (!registeredAgentRef && options.expectedAgentRef === null) {
|
|
3041
|
+
// A fresh spawn collided with an existing id. If that id is held by a
|
|
3042
|
+
// provably-dead parked corpse — no live session, no reviver — reclaim it
|
|
3043
|
+
// so this new generation can take the id instead of failing forever at
|
|
3044
|
+
// construction. Without this, one such corpse (isolated-run park,
|
|
3045
|
+
// interrupted construction) poisons the id for the whole process (#8490).
|
|
3046
|
+
// The reclaim is gated by the lifecycle owner and only touches the
|
|
3047
|
+
// registry it manages; the corpse's transcript stays at history://.
|
|
3048
|
+
const stale = agentRegistry.get(resolvedAgentId);
|
|
3049
|
+
const lifecycle = AgentLifecycleManager.global();
|
|
3050
|
+
if (stale && lifecycle.manages(agentRegistry) && (await lifecycle.reclaimDeadCorpse(resolvedAgentId, stale))) {
|
|
3051
|
+
registeredAgentRef = agentRegistry.registerIfAvailable(registrationInput, null);
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3037
3054
|
if (!registeredAgentRef) {
|
|
3038
3055
|
throw new Error(`Agent "${resolvedAgentId}" is already owned by another session generation.`);
|
|
3039
3056
|
}
|
|
@@ -3130,7 +3147,15 @@ async function createAgentSessionScoped(options: CreateAgentSessionOptions): Pro
|
|
|
3130
3147
|
let transformed = obfuscator ? obfuscateProviderContext(obfuscator, context) : context;
|
|
3131
3148
|
if (snapcompactInline) transformed = await snapcompactInline.transform(transformed, transformModel);
|
|
3132
3149
|
transformed = clampProviderContextImages(transformed, transformModel);
|
|
3133
|
-
|
|
3150
|
+
transformed = await normalizeProviderContextImagesForModel(transformed, transformModel);
|
|
3151
|
+
// Keep per-request volatility out of the system prompt: the date/cwd
|
|
3152
|
+
// reminder rides on the first user turn so open-weight providers keep
|
|
3153
|
+
// their tool-schema prefix cache (#7404).
|
|
3154
|
+
return withDateCwdReminder(
|
|
3155
|
+
transformed,
|
|
3156
|
+
formatLocalCalendarDate(),
|
|
3157
|
+
normalizePromptPath(sessionManager.getCwd()),
|
|
3158
|
+
);
|
|
3134
3159
|
};
|
|
3135
3160
|
const onPayload = async (payload: unknown, model?: Model) => {
|
|
3136
3161
|
return await extensionRunner.emitBeforeProviderRequest(payload, model);
|
|
@@ -3771,7 +3796,12 @@ async function createAgentSessionScoped(options: CreateAgentSessionOptions): Pro
|
|
|
3771
3796
|
transformProviderContext: async (context, transformModel) => {
|
|
3772
3797
|
let transformed = obfuscator ? obfuscateProviderContext(obfuscator, context) : context;
|
|
3773
3798
|
transformed = clampProviderContextImages(transformed, transformModel);
|
|
3774
|
-
|
|
3799
|
+
transformed = await normalizeProviderContextImagesForModel(transformed, transformModel);
|
|
3800
|
+
return withDateCwdReminder(
|
|
3801
|
+
transformed,
|
|
3802
|
+
formatLocalCalendarDate(),
|
|
3803
|
+
normalizePromptPath(sessionManager.getCwd()),
|
|
3804
|
+
);
|
|
3775
3805
|
},
|
|
3776
3806
|
thinkingBudgets: agent.thinkingBudgets,
|
|
3777
3807
|
temperature: agent.temperature,
|
|
@@ -211,8 +211,6 @@ export interface AgentSessionConfig {
|
|
|
211
211
|
toolNames: string[],
|
|
212
212
|
tools: Map<string, AgentTool>,
|
|
213
213
|
) => Promise<{ systemPrompt: string[]; xdevCatalogNames?: readonly string[] }>;
|
|
214
|
-
/** Local calendar date provider used by prompt-cache invalidation. */
|
|
215
|
-
getLocalCalendarDate?: () => string;
|
|
216
214
|
/** Tools mounted under `xd://`, for `/tools` display. */
|
|
217
215
|
getXdevToolEntries?: () => Array<{ name: string; summary: string }>;
|
|
218
216
|
/** `xd://` presentation state backed by the canonical tool map. */
|