pi-orchestrator-config 4.2.1 → 4.3.2
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 +52 -61
- package/agents/git-expert.md +5 -1
- package/agents/github-expert.md +4 -1
- package/extensions/acpx-provider/runtime-models.ts +18 -6
- package/extensions/cli-provider/agents/claude.ts +3 -2
- package/extensions/cli-provider/agents/cursor.ts +3 -5
- package/extensions/cli-provider/agents/gemini.ts +3 -2
- package/extensions/cli-provider/discover.ts +7 -7
- package/extensions/cli-provider/index.ts +5 -0
- package/extensions/cli-provider/runtime-models.ts +18 -6
- package/extensions/cli-provider/session-reaper.ts +5 -7
- package/extensions/cli-provider/sessions.ts +4 -0
- package/extensions/cli-provider/shared/discover-cache.ts +17 -176
- package/extensions/coms/coms-p2p.ts +1719 -423
- package/extensions/coms/coms-shared.ts +261 -39
- package/extensions/coms/coms-wrapper.ts +100 -62
- package/extensions/coms/index.ts +8 -4
- package/extensions/coms/mixed-turn.ts +26 -0
- package/extensions/coms/probe-socket.ts +42 -0
- package/extensions/coms/themeMap.ts +0 -1
- package/extensions/image-gen/image-gen.ts +19 -1
- package/extensions/orchestrator/async-agents.ts +509 -85
- package/extensions/orchestrator/cron.ts +14 -8
- package/extensions/orchestrator/dreaming.ts +31 -24
- package/extensions/orchestrator/enforcement-helpers.ts +459 -17
- package/extensions/orchestrator/enforcement-rules.ts +5 -4
- package/extensions/orchestrator/enforcement.ts +79 -25
- package/extensions/orchestrator/extended-autocomplete.ts +7 -0
- package/extensions/orchestrator/git-helpers.ts +2 -2
- package/extensions/orchestrator/index.ts +23 -10
- package/extensions/orchestrator/markdown-transformer.ts +313 -0
- package/extensions/orchestrator/memory-embeddings.ts +36 -34
- package/extensions/orchestrator/memory-provenance.ts +29 -25
- package/extensions/orchestrator/memory-scoring.ts +23 -18
- package/extensions/orchestrator/memory-tools.ts +10 -3
- package/extensions/orchestrator/overlay-dashboard.ts +17 -5
- package/extensions/orchestrator/pi-config-review-state.ts +44 -33
- package/extensions/orchestrator/project-settings.ts +220 -21
- package/extensions/orchestrator/review-porcelain.ts +4 -0
- package/extensions/orchestrator/review-ui.ts +11 -5
- package/extensions/orchestrator/rule-placeholders.ts +384 -1
- package/extensions/orchestrator/rules.ts +80 -132
- package/extensions/orchestrator/settings-tui-helpers.ts +380 -0
- package/extensions/orchestrator/settings-tui-submenus.ts +647 -0
- package/extensions/orchestrator/settings-tui.ts +636 -0
- package/extensions/orchestrator/state-jsonl.ts +431 -0
- package/extensions/orchestrator/subagent-tool.ts +105 -50
- package/extensions/orchestrator/sync-limit.ts +23 -0
- package/extensions/orchestrator/task-lifecycle.ts +77 -67
- package/extensions/orchestrator/utils.ts +8 -5
- package/extensions/pidash/pidash.ts +193 -156
- package/extensions/pidiff/pidiff.ts +64 -38
- package/extensions/pidiff/spawn-lock.ts +62 -0
- package/extensions/pitasks/index.ts +430 -0
- package/extensions/pitasks/reminders.ts +37 -0
- package/extensions/pitasks/task-store.ts +467 -0
- package/extensions/pitasks/task-tools.ts +375 -0
- package/extensions/pitasks/task-widget.ts +181 -0
- package/extensions/pitasks/types.ts +38 -0
- package/extensions/providers/acpx-driver.ts +12 -2
- package/extensions/providers/built-in-drivers.ts +6 -6
- package/extensions/providers/claude-driver.ts +1 -1
- package/extensions/providers/cursor-cli-driver.ts +1 -1
- package/extensions/providers/gemini-driver.ts +1 -1
- package/extensions/providers/index.ts +144 -26
- package/extensions/providers/initialized-guard.ts +27 -0
- package/extensions/providers/restore-default-model.ts +596 -0
- package/extensions/providers/session-shutdown.ts +39 -0
- package/extensions/shared/coms-active.ts +23 -0
- package/extensions/shared/create-runtime-provider.ts +2 -0
- package/extensions/shared/daemon-manager.ts +0 -8
- package/extensions/shared/file-logger.ts +132 -25
- package/extensions/shared/logger.ts +50 -0
- package/extensions/shared/models-dev.ts +421 -0
- package/extensions/shared/oneshot.ts +116 -0
- package/extensions/shared/resolve-binary.ts +191 -0
- package/extensions/shared/types.ts +3 -0
- package/package.json +7 -2
- package/prompts/coderabbit-rate-limit.md +2 -0
- package/rules/00-orchestrator-core.md +3 -0
- package/rules/10-agent-routing.md +1 -1
- package/rules/20-code-review-loop.md +38 -16
- package/rules/30-prompt-templates.md +4 -0
- package/rules/35-memory.md +3 -3
- package/rules/40-critical-rules.md +3 -0
- package/rules/55-coms-protocol.md +84 -18
- package/rules/60-task-tracking.md +2 -0
- package/settings-keys.json +481 -20
- package/templates/coms-feature-manager-prompt.md +4 -6
- package/extensions/coms/coms-net-server.ts +0 -1642
- package/extensions/coms/coms-net-wrapper.ts +0 -521
- package/extensions/coms/coms-net.ts +0 -1589
|
@@ -26,8 +26,10 @@ import type {
|
|
|
26
26
|
SimpleStreamOptions,
|
|
27
27
|
StreamOptions,
|
|
28
28
|
} from "@earendil-works/pi-ai";
|
|
29
|
+
import { createLogger } from "../shared/logger.js";
|
|
29
30
|
import { createAssistantMessageEventStream } from "@earendil-works/pi-ai";
|
|
30
31
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
32
|
+
import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
31
33
|
import { asStringArray, getSetting } from "../orchestrator/project-settings.js";
|
|
32
34
|
import { buildExternalSystemPrompt } from "../shared/build-system-prompt.js";
|
|
33
35
|
import {
|
|
@@ -36,10 +38,14 @@ import {
|
|
|
36
38
|
} from "../orchestrator/utils.js";
|
|
37
39
|
import {
|
|
38
40
|
buildAmbientLoginAuth,
|
|
39
|
-
buildRuntimeModel,
|
|
40
41
|
createRuntimeProvider,
|
|
41
42
|
filterModelsWhenConfigured,
|
|
42
43
|
} from "../shared/create-runtime-provider.js";
|
|
44
|
+
import {
|
|
45
|
+
applyThinkingLevelFromModel,
|
|
46
|
+
loadModelsDevCatalog,
|
|
47
|
+
type ModelsDevCatalog,
|
|
48
|
+
} from "../shared/models-dev.js";
|
|
43
49
|
import { StreamAssembler, createAssistantMessageOutput } from "../shared/stream-builder.js";
|
|
44
50
|
import { ProviderDriverRegistry } from "../shared/provider-registry.js";
|
|
45
51
|
import type { ProviderInstance, DiscoveredModel } from "../shared/provider-driver.js";
|
|
@@ -48,13 +54,18 @@ import { mapCliDiscoveredModels } from "../cli-provider/runtime-models.js";
|
|
|
48
54
|
import { mapAcpxDiscoveredModels } from "../acpx-provider/runtime-models.js";
|
|
49
55
|
import {
|
|
50
56
|
startCliSessionReaper,
|
|
51
|
-
stopCliSessionReaper,
|
|
52
57
|
} from "../cli-provider/session-reaper.js";
|
|
53
58
|
import {
|
|
54
59
|
readPiSessionIdFromManager,
|
|
55
60
|
} from "../cli-provider/sessions.js";
|
|
56
61
|
import { fileLog } from "../shared/file-logger.js";
|
|
57
62
|
import { isCliAgentName } from "../cli-provider/providers.js";
|
|
63
|
+
import {
|
|
64
|
+
isProvidersInitialized,
|
|
65
|
+
markProvidersInitialized,
|
|
66
|
+
} from "./initialized-guard.js";
|
|
67
|
+
import { restoreDefaultModelOnSessionStart } from "./restore-default-model.js";
|
|
68
|
+
import { teardownProvidersOnSessionShutdown } from "./session-shutdown.js";
|
|
58
69
|
|
|
59
70
|
const LOG_DOMAIN = "providers";
|
|
60
71
|
const DISCOVERY_TIMEOUT_MS = 30_000;
|
|
@@ -70,7 +81,6 @@ const cliInstances = new Map<string, ProviderInstance>();
|
|
|
70
81
|
const acpxInstances = new Map<string, ProviderInstance>();
|
|
71
82
|
|
|
72
83
|
let projectCwd = "";
|
|
73
|
-
let initialized = false;
|
|
74
84
|
|
|
75
85
|
// ---------------------------------------------------------------------------
|
|
76
86
|
// Configured Gates
|
|
@@ -185,12 +195,13 @@ async function registerCliAgent(
|
|
|
185
195
|
pi: ExtensionAPI,
|
|
186
196
|
agent: string,
|
|
187
197
|
instance: ProviderInstance,
|
|
198
|
+
catalog: ModelsDevCatalog | null,
|
|
188
199
|
): Promise<void> {
|
|
189
200
|
const providerId = `cli-${agent}`;
|
|
190
201
|
const snapshot = instance.snapshot.getSnapshot();
|
|
191
202
|
const discovered = snapshot.models;
|
|
192
203
|
|
|
193
|
-
const models = mapCliDiscoveredModels(agent, discovered);
|
|
204
|
+
const models = mapCliDiscoveredModels(agent, discovered, catalog);
|
|
194
205
|
const streamFn = makeStreamFunction("cli", agent, () => cliInstances.get(agent));
|
|
195
206
|
|
|
196
207
|
const provider = await createRuntimeProvider({
|
|
@@ -209,7 +220,8 @@ async function registerCliAgent(
|
|
|
209
220
|
const inst = cliInstances.get(agent);
|
|
210
221
|
if (!inst) return [];
|
|
211
222
|
const snap = await inst.snapshot.refresh();
|
|
212
|
-
|
|
223
|
+
const fresh = await loadModelsDevCatalog();
|
|
224
|
+
return mapCliDiscoveredModels(agent, snap.models, fresh);
|
|
213
225
|
},
|
|
214
226
|
filterModels: (catalog, credential) =>
|
|
215
227
|
filterModelsWhenConfigured(catalog, credential, () =>
|
|
@@ -226,12 +238,13 @@ async function registerAcpxAgent(
|
|
|
226
238
|
pi: ExtensionAPI,
|
|
227
239
|
agent: string,
|
|
228
240
|
instance: ProviderInstance,
|
|
241
|
+
catalog: ModelsDevCatalog | null,
|
|
229
242
|
): Promise<void> {
|
|
230
243
|
const providerId = `acpx-${agent}`;
|
|
231
244
|
const snapshot = instance.snapshot.getSnapshot();
|
|
232
245
|
const modelIds = snapshot.models.map((m) => m.id);
|
|
233
246
|
|
|
234
|
-
const models = mapAcpxDiscoveredModels(agent, modelIds);
|
|
247
|
+
const models = mapAcpxDiscoveredModels(agent, modelIds, catalog);
|
|
235
248
|
const streamFn = makeStreamFunction("acpx", agent, () => acpxInstances.get(agent));
|
|
236
249
|
|
|
237
250
|
const provider = await createRuntimeProvider({
|
|
@@ -249,7 +262,8 @@ async function registerAcpxAgent(
|
|
|
249
262
|
const inst = acpxInstances.get(agent);
|
|
250
263
|
if (!inst) return [];
|
|
251
264
|
const snap = await inst.snapshot.refresh();
|
|
252
|
-
|
|
265
|
+
const fresh = await loadModelsDevCatalog();
|
|
266
|
+
return mapAcpxDiscoveredModels(agent, snap.models.map((m) => m.id), fresh);
|
|
253
267
|
},
|
|
254
268
|
filterModels: (catalog, credential) =>
|
|
255
269
|
filterModelsWhenConfigured(catalog, credential, () =>
|
|
@@ -266,15 +280,27 @@ async function registerAcpxAgent(
|
|
|
266
280
|
// Extension Entry Point
|
|
267
281
|
// ---------------------------------------------------------------------------
|
|
268
282
|
|
|
283
|
+
const log = createLogger("providers");
|
|
284
|
+
log.debug("providers module loaded");
|
|
285
|
+
|
|
269
286
|
export default async function (pi: ExtensionAPI) {
|
|
270
287
|
// pi --help / --version — skip discovery
|
|
271
288
|
if (isPiMetaInvocation()) return;
|
|
272
289
|
|
|
273
290
|
// Idempotency guard — shims re-export this default, so it may be called
|
|
274
291
|
// multiple times (cli-provider shim, acpx-provider shim, providers dir).
|
|
275
|
-
// Only run once per
|
|
276
|
-
|
|
277
|
-
|
|
292
|
+
// Only run once per session; session_shutdown resets so /new|/resume|/fork
|
|
293
|
+
// re-registers providers on the next factory invocation.
|
|
294
|
+
if (isProvidersInitialized()) {
|
|
295
|
+
log.debug(
|
|
296
|
+
"providers factory early-return: already initialized (same-session double-load)",
|
|
297
|
+
);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
markProvidersInitialized();
|
|
301
|
+
log.debug(
|
|
302
|
+
"providers factory: proceeding after reset / first load — re-entering discovery",
|
|
303
|
+
);
|
|
278
304
|
|
|
279
305
|
const versionCheck = checkMinPiVersion();
|
|
280
306
|
if (!versionCheck.ok && versionCheck.installed !== null) {
|
|
@@ -295,6 +321,14 @@ export default async function (pi: ExtensionAPI) {
|
|
|
295
321
|
// CLI agents (load in subagent children too)
|
|
296
322
|
// ---------------------------------------------------------------------------
|
|
297
323
|
const cliAgentList = asStringArray(getSetting(projectCwd, "cli_agents")).filter(isCliAgentName);
|
|
324
|
+
const acpxAgentList = asStringArray(getSetting(projectCwd, "acpx_agents"));
|
|
325
|
+
const modelsDevCatalog =
|
|
326
|
+
cliAgentList.length > 0 || acpxAgentList.length > 0
|
|
327
|
+
? await loadModelsDevCatalog()
|
|
328
|
+
: null;
|
|
329
|
+
if (modelsDevCatalog) {
|
|
330
|
+
log.info("models.dev catalog loaded for cli/acpx model fill");
|
|
331
|
+
}
|
|
298
332
|
|
|
299
333
|
if (cliAgentList.length > 0) {
|
|
300
334
|
startCliSessionReaper({
|
|
@@ -339,8 +373,8 @@ export default async function (pi: ExtensionAPI) {
|
|
|
339
373
|
|
|
340
374
|
const cliResults = await Promise.allSettled(
|
|
341
375
|
cliAgentList.map(async (agent) => {
|
|
342
|
-
const driverKind = CLI_AGENT_TO_DRIVER[agent];
|
|
343
|
-
if (
|
|
376
|
+
const driverKind = Object.hasOwn(CLI_AGENT_TO_DRIVER, agent) ? CLI_AGENT_TO_DRIVER[agent] : undefined;
|
|
377
|
+
if (typeof driverKind !== "string" || driverKind.length === 0) {
|
|
344
378
|
fileLog(LOG_DOMAIN, "warn", LOG_DOMAIN,
|
|
345
379
|
`cli-${agent}: no driver registered`);
|
|
346
380
|
return null;
|
|
@@ -397,7 +431,7 @@ export default async function (pi: ExtensionAPI) {
|
|
|
397
431
|
if (result.status !== "fulfilled" || !result.value) continue;
|
|
398
432
|
const { agent, instance } = result.value;
|
|
399
433
|
try {
|
|
400
|
-
await registerCliAgent(pi, agent, instance);
|
|
434
|
+
await registerCliAgent(pi, agent, instance, modelsDevCatalog);
|
|
401
435
|
} catch (err) {
|
|
402
436
|
fileLog(LOG_DOMAIN, "error", LOG_DOMAIN,
|
|
403
437
|
`cli-${agent}: registration failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -412,7 +446,12 @@ export default async function (pi: ExtensionAPI) {
|
|
|
412
446
|
|
|
413
447
|
const acpxResults = await Promise.allSettled(
|
|
414
448
|
acpxAgentList.map(async (agent) => {
|
|
415
|
-
const driverKind = ACPX_AGENT_TO_DRIVER[agent]
|
|
449
|
+
const driverKind = Object.hasOwn(ACPX_AGENT_TO_DRIVER, agent) ? ACPX_AGENT_TO_DRIVER[agent] : undefined;
|
|
450
|
+
if (typeof driverKind !== "string" || driverKind.length === 0) {
|
|
451
|
+
fileLog(LOG_DOMAIN, "warn", LOG_DOMAIN,
|
|
452
|
+
`acpx-${agent}: no driver mapping in ACPX_AGENT_TO_DRIVER`);
|
|
453
|
+
return null;
|
|
454
|
+
}
|
|
416
455
|
// Only proceed if the driver is registered
|
|
417
456
|
if (!registry.getDriver(driverKind)) {
|
|
418
457
|
fileLog(LOG_DOMAIN, "warn", LOG_DOMAIN,
|
|
@@ -437,7 +476,11 @@ export default async function (pi: ExtensionAPI) {
|
|
|
437
476
|
{ driver: driverKind, config: { agent }, enabled: true },
|
|
438
477
|
projectCwd,
|
|
439
478
|
);
|
|
440
|
-
if (timedOut)
|
|
479
|
+
if (timedOut) {
|
|
480
|
+
fileLog(LOG_DOMAIN, "warn", LOG_DOMAIN,
|
|
481
|
+
`acpx-${agent}: completed after timeout — cleaning up`);
|
|
482
|
+
return { agent, instance };
|
|
483
|
+
}
|
|
441
484
|
acpxInstances.set(agent, instance);
|
|
442
485
|
return { agent, instance };
|
|
443
486
|
} catch (err) {
|
|
@@ -471,7 +514,7 @@ export default async function (pi: ExtensionAPI) {
|
|
|
471
514
|
if (result.status !== "fulfilled" || !result.value) continue;
|
|
472
515
|
const { agent, instance } = result.value;
|
|
473
516
|
try {
|
|
474
|
-
await registerAcpxAgent(pi, agent, instance);
|
|
517
|
+
await registerAcpxAgent(pi, agent, instance, modelsDevCatalog);
|
|
475
518
|
} catch (err) {
|
|
476
519
|
fileLog(LOG_DOMAIN, "error", LOG_DOMAIN,
|
|
477
520
|
`acpx-${agent}: registration failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -482,7 +525,8 @@ export default async function (pi: ExtensionAPI) {
|
|
|
482
525
|
// Run CLI and ACPX discovery concurrently
|
|
483
526
|
await Promise.all([discoverAndRegisterCli(), discoverAndRegisterAcpx()]);
|
|
484
527
|
|
|
485
|
-
// Show discovery summary on session start
|
|
528
|
+
// Show discovery summary on session start; restore saved default model when
|
|
529
|
+
// findInitialModel raced hasConfiguredAuth false → wrong initial model (#753).
|
|
486
530
|
const providerSummaryParts: string[] = [];
|
|
487
531
|
for (const [agent, inst] of cliInstances) {
|
|
488
532
|
const count = inst.snapshot.getSnapshot().models.length;
|
|
@@ -492,22 +536,96 @@ export default async function (pi: ExtensionAPI) {
|
|
|
492
536
|
const count = inst.snapshot.getSnapshot().models.length;
|
|
493
537
|
providerSummaryParts.push(`acpx-${agent} (${count})`);
|
|
494
538
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
539
|
+
|
|
540
|
+
// Fire-and-forget restore so session_start is not blocked by retries (#753).
|
|
541
|
+
// Omit registeredProviders: cli/acpx-only lists falsely fail-fast native defaults.
|
|
542
|
+
const applyCliAcpxThinking = (model: { id: string; provider: string } | undefined) => {
|
|
543
|
+
log.debug("applyCliAcpxThinking", model?.provider, model?.id);
|
|
544
|
+
try {
|
|
545
|
+
applyThinkingLevelFromModel(
|
|
546
|
+
model,
|
|
547
|
+
(level) => pi.setThinkingLevel(level as ThinkingLevel),
|
|
548
|
+
() => pi.getThinkingLevel(),
|
|
549
|
+
);
|
|
550
|
+
} catch (err) {
|
|
551
|
+
log.warn(
|
|
552
|
+
"thinking from id failed",
|
|
553
|
+
err instanceof Error ? err.message : String(err),
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
pi.on("session_start", (event, ctx) => {
|
|
559
|
+
const reason = typeof event?.reason === "string" ? event.reason : "";
|
|
560
|
+
if (providerSummaryParts.length > 0 && ctx.hasUI) {
|
|
498
561
|
try {
|
|
499
562
|
ctx.ui.notify(`Providers: ${providerSummaryParts.join(", ")}`, "info");
|
|
500
|
-
} catch {
|
|
563
|
+
} catch (err) {
|
|
564
|
+
log.debug(
|
|
565
|
+
"providers notify skipped",
|
|
566
|
+
err instanceof Error ? err.message : String(err),
|
|
567
|
+
);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
applyCliAcpxThinking(
|
|
571
|
+
ctx.model
|
|
572
|
+
? { id: ctx.model.id, provider: String(ctx.model.provider) }
|
|
573
|
+
: undefined,
|
|
574
|
+
);
|
|
575
|
+
// agentDir via PI_CODING_AGENT_DIR / ~/.pi/agent only (ctx has cwd, not agentDir).
|
|
576
|
+
// Merge global + cwd/.pi/settings.json (project wins) only when trusted —
|
|
577
|
+
// same gate as pi SettingsManager (ctx.isProjectTrusted). Fail closed.
|
|
578
|
+
const cwd = typeof ctx.cwd === "string" ? ctx.cwd : undefined;
|
|
579
|
+
let projectTrusted = false;
|
|
580
|
+
try {
|
|
581
|
+
projectTrusted = typeof ctx.isProjectTrusted === "function"
|
|
582
|
+
? ctx.isProjectTrusted() === true
|
|
583
|
+
: false;
|
|
584
|
+
} catch (err) {
|
|
585
|
+
log.debug(
|
|
586
|
+
"restore-default-model isProjectTrusted failed",
|
|
587
|
+
err instanceof Error ? err.message : String(err),
|
|
588
|
+
);
|
|
589
|
+
projectTrusted = false;
|
|
590
|
+
}
|
|
591
|
+
void restoreDefaultModelOnSessionStart({
|
|
592
|
+
ctx: {
|
|
593
|
+
model: ctx.model
|
|
594
|
+
? { id: ctx.model.id, provider: String(ctx.model.provider) }
|
|
595
|
+
: undefined,
|
|
596
|
+
modelRegistry: ctx.modelRegistry,
|
|
597
|
+
},
|
|
598
|
+
reason,
|
|
599
|
+
cwd,
|
|
600
|
+
projectTrusted,
|
|
601
|
+
getCurrentModel: () =>
|
|
602
|
+
ctx.model
|
|
603
|
+
? { id: ctx.model.id, provider: String(ctx.model.provider) }
|
|
604
|
+
: undefined,
|
|
605
|
+
setModel: (model) => pi.setModel(model as Model<any>),
|
|
606
|
+
}).catch((err) => {
|
|
607
|
+
log.warn(
|
|
608
|
+
"restore-default-model session_start error",
|
|
609
|
+
err instanceof Error ? err.message : String(err),
|
|
610
|
+
);
|
|
501
611
|
});
|
|
502
|
-
}
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
pi.on("model_select", (event) => {
|
|
615
|
+
applyCliAcpxThinking({
|
|
616
|
+
id: event.model.id,
|
|
617
|
+
provider: String(event.model.provider),
|
|
618
|
+
});
|
|
619
|
+
});
|
|
503
620
|
|
|
504
621
|
// ---------------------------------------------------------------------------
|
|
505
622
|
// Shutdown
|
|
506
623
|
// ---------------------------------------------------------------------------
|
|
507
624
|
pi.on("session_shutdown", async () => {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
625
|
+
await teardownProvidersOnSessionShutdown(
|
|
626
|
+
registry,
|
|
627
|
+
cliInstances,
|
|
628
|
+
acpxInstances,
|
|
629
|
+
);
|
|
512
630
|
});
|
|
513
631
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-scoped init guard for the unified providers extension.
|
|
3
|
+
*
|
|
4
|
+
* Shims (cli-provider / acpx-provider) and providers/ may call the same
|
|
5
|
+
* default factory multiple times in one process — early-return while set.
|
|
6
|
+
* session_shutdown must clear this so /new|/resume|/fork re-registers (#752).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createLogger } from "../shared/logger.js";
|
|
10
|
+
|
|
11
|
+
const log = createLogger("providers");
|
|
12
|
+
|
|
13
|
+
let initialized = false;
|
|
14
|
+
|
|
15
|
+
export function isProvidersInitialized(): boolean {
|
|
16
|
+
return initialized;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function markProvidersInitialized(): void {
|
|
20
|
+
initialized = true;
|
|
21
|
+
log.debug("initialized-guard", "markProvidersInitialized → true");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function resetProvidersInitialized(): void {
|
|
25
|
+
initialized = false;
|
|
26
|
+
log.debug("initialized-guard", "resetProvidersInitialized → false");
|
|
27
|
+
}
|