@piagent/platform 1.48.0 → 1.48.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.
Files changed (87) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +2 -0
  3. package/README.vi.md +2 -0
  4. package/docs/command-reference-vietnamese.md +4 -3
  5. package/docs/distribution-standard.md +6 -6
  6. package/docs/harness-conformance.md +4 -0
  7. package/docs/languages.json +2 -2
  8. package/docs/operator-manual-vietnamese.md +7 -7
  9. package/docs/publishing-for-teams.md +2 -0
  10. package/docs/release-install-policy.md +2 -2
  11. package/docs/team-onboarding.md +2 -2
  12. package/docs-site/architecture.html +1 -1
  13. package/docs-site/assets/search-en.json +1 -1
  14. package/docs-site/assets/search-vi.json +1 -1
  15. package/docs-site/benchmark.html +1 -1
  16. package/docs-site/commands.html +1 -1
  17. package/docs-site/content/en/update.html +8 -0
  18. package/docs-site/content/update.html +8 -0
  19. package/docs-site/context-engine.html +1 -1
  20. package/docs-site/ecosystem.html +1 -1
  21. package/docs-site/en/architecture.html +1 -1
  22. package/docs-site/en/benchmark.html +1 -1
  23. package/docs-site/en/commands.html +1 -1
  24. package/docs-site/en/context-engine.html +1 -1
  25. package/docs-site/en/ecosystem.html +1 -1
  26. package/docs-site/en/index.html +15 -15
  27. package/docs-site/en/mcp-approval.html +1 -1
  28. package/docs-site/en/mcp-auth.html +1 -1
  29. package/docs-site/en/mcp-servers.html +1 -1
  30. package/docs-site/en/mcp.html +1 -1
  31. package/docs-site/en/permissions.html +1 -1
  32. package/docs-site/en/profiles.html +1 -1
  33. package/docs-site/en/quickstart.html +1 -1
  34. package/docs-site/en/runtime.html +1 -1
  35. package/docs-site/en/scope.html +1 -1
  36. package/docs-site/en/security.html +1 -1
  37. package/docs-site/en/team.html +1 -1
  38. package/docs-site/en/update.html +11 -3
  39. package/docs-site/en/whats-new.html +52 -28
  40. package/docs-site/en/windows.html +1 -1
  41. package/docs-site/en/workflows.html +1 -1
  42. package/docs-site/index.html +15 -15
  43. package/docs-site/mcp-approval.html +1 -1
  44. package/docs-site/mcp-auth.html +1 -1
  45. package/docs-site/mcp-servers.html +1 -1
  46. package/docs-site/mcp.html +1 -1
  47. package/docs-site/permissions.html +1 -1
  48. package/docs-site/profiles.html +1 -1
  49. package/docs-site/quickstart.html +1 -1
  50. package/docs-site/releases.json +72 -0
  51. package/docs-site/runtime.html +1 -1
  52. package/docs-site/scope.html +1 -1
  53. package/docs-site/security.html +1 -1
  54. package/docs-site/team.html +1 -1
  55. package/docs-site/update.html +11 -3
  56. package/docs-site/whats-new.html +52 -28
  57. package/docs-site/windows.html +1 -1
  58. package/docs-site/workflows.html +1 -1
  59. package/evals/private-holdout-v1/public-exposure.v2.json +2 -2
  60. package/package.json +1 -1
  61. package/packages/piagent-core/extensions/piagent-guard.ts +10 -2
  62. package/packages/piagent-core/managed/check-waiver.mjs +35 -0
  63. package/packages/piagent-core/managed/command-tools.mjs +2 -2
  64. package/packages/piagent-core/managed/session.mjs +2 -2
  65. package/packages/piagent-core/managed/workflow.mjs +4 -4
  66. package/packages/piagent-core/package.json +1 -1
  67. package/packages/piagent-core/runtime/inspection/runtime-event-store.ts +5 -1
  68. package/packages/piagent-core/runtime/solver/runtime-features.ts +52 -10
  69. package/packages/piagent-core/runtime/update/terminal-reload.mjs +122 -0
  70. package/packages/piagent-core/runtime/update/terminal-update-offer.mjs +1 -1
  71. package/packages/piagent-webui/dist/client/assets/{App-fZeIRoaD.js → App-Dg6Firq1.js} +1 -1
  72. package/packages/piagent-webui/dist/client/assets/{GatewayApp-CpC4lgYK.js → GatewayApp-CCczgphI.js} +3 -3
  73. package/packages/piagent-webui/dist/client/assets/{InspectionApp-pD-BqBXm.js → InspectionApp-CEilR0FG.js} +1 -1
  74. package/packages/piagent-webui/dist/client/assets/{SessionAgentWorkspace-3tM7Q6HH.js → SessionAgentWorkspace-yh0py16t.js} +1 -1
  75. package/packages/piagent-webui/dist/client/assets/{SessionInspectorDrawer-BJ94aQ6y.js → SessionInspectorDrawer-C-18TcGH.js} +2 -2
  76. package/packages/piagent-webui/dist/client/assets/{TerminalPanel-CtZyb0tj.js → TerminalPanel-B2-YAz2x.js} +1 -1
  77. package/packages/piagent-webui/dist/client/assets/{WorkspaceCodeEditor-BS_ZrjPN.js → WorkspaceCodeEditor-DAdMuw6x.js} +1 -1
  78. package/packages/piagent-webui/dist/client/assets/{WorkspaceExplorer-CkFBpcM7.js → WorkspaceExplorer-97MLNtEa.js} +3 -3
  79. package/packages/piagent-webui/dist/client/assets/{index-CNdhIouM.js → index-B8tL7HFz.js} +2 -2
  80. package/packages/piagent-webui/dist/client/assets/{transcript-view-model-CpEMY1xb.js → transcript-view-model-DqO4xO12.js} +1 -1
  81. package/packages/piagent-webui/dist/client/index.html +1 -1
  82. package/packages/piagent-webui/gateway/session-inspection-registry.ts +9 -4
  83. package/scripts/company-terminal.mjs +21 -1
  84. package/scripts/piagent-cli.mjs +44 -21
  85. package/scripts/piagent-studio.mjs +22 -2
  86. package/scripts/terminal-reload.mjs +15 -0
  87. package/scripts/update-global.mjs +10 -0
@@ -249,13 +249,18 @@ export class SessionInspectionRegistry {
249
249
  ...(provider === "agent_watch_managed" && value.managedFast === true ? { managedFast: true } : {}),
250
250
  ...(provider === "agent_watch_managed" && value.managedBypass === true ? { managedBypass: true } : {}) }];
251
251
  });
252
- // Only offer a default present in the authenticated host catalog. Retain
253
- // the previous Sol baseline for accounts that have not received GPT-6 yet.
252
+ // A new conversation starts where the Terminal does: the model and thinking
253
+ // level Pi keeps in settings.json (the last ones chosen with /model). Only
254
+ // a default present in the authenticated host catalog is offered; an account
255
+ // that set none gets the Sol baseline (GPT-5.6 before GPT-6 reached it).
254
256
  const managed = models.length === 1 && models[0].provider === 'agent_watch_managed';
255
- const defaultModel = managed ? models[0] : ["gpt-6-sol", "gpt-5.6-sol"].map((id) => models.find((value) => value.provider === "openai-codex" && value.modelId === id)).find(Boolean);
257
+ const settings = this.#agentDir ? safeRead(() => JSON.parse(fs.readFileSync(path.join(this.#agentDir!, "settings.json"), "utf8")) as Record<string, unknown>, {}) : {};
258
+ const chosen = models.find((value) => value.provider === settings.defaultProvider && value.modelId === settings.defaultModel);
259
+ const defaultModel = managed ? models[0] : chosen ?? ["gpt-6-sol", "gpt-5.6-sol"].map((id) => models.find((value) => value.provider === "openai-codex" && value.modelId === id)).find(Boolean);
260
+ const chosenThinking = !managed && typeof settings.defaultThinkingLevel === "string" && defaultModel?.thinkingLevels.includes(settings.defaultThinkingLevel) ? settings.defaultThinkingLevel : null;
256
261
  return { schemaVersion: 1, version: "piagent-session-creation-options-v1", generatedAt: new Date().toISOString(),
257
262
  projects: [...projects.values()].slice(0, 200), models,
258
- defaultModelRef: defaultModel?.modelRef ?? null, defaultThinkingLevel: defaultModel ? (defaultModel.thinkingLevels.includes("high") ? "high" : defaultModel.thinkingLevels[0] ?? null) : null,
263
+ defaultModelRef: defaultModel?.modelRef ?? null, defaultThinkingLevel: defaultModel ? chosenThinking ?? (defaultModel.thinkingLevels.includes("high") ? "high" : defaultModel.thinkingLevels[0] ?? null) : null,
259
264
  profiles: managed ? [] : profiles, workflows: [],
260
265
  runtimeActions: managed ? [] : WEBUI_RUNTIME_ACTIONS,
261
266
  webSearch: inspectWebSearchCapability({ agentDir: this.#agentDir, models: availableModels }),
@@ -9,6 +9,7 @@ import { execFile } from 'node:child_process';
9
9
  import { pathToFileURL } from 'node:url';
10
10
 
11
11
  import { registerTerminalUpdateOffer } from '../packages/piagent-core/runtime/update/terminal-update-offer.mjs';
12
+ import { watchTerminalReload } from '../packages/piagent-core/runtime/update/terminal-reload.mjs';
12
13
  import { registerStyleCommand } from '../packages/piagent-core/runtime/terminal/terminal-style.mjs';
13
14
  import { parseFailure } from '../packages/piagent-core/runtime/managed-failure.mjs';
14
15
  import { checkpointsOf } from '../packages/piagent-core/managed/checkpoints.mjs';
@@ -258,6 +259,16 @@ export function companyMode(Base, { summary, whatsNew, components }) {
258
259
  const say = (mode, name, tone = 'warning') => mode.showExtensionNotify(companyCommandText(name, summary()), tone);
259
260
  return class CompanyInteractiveMode extends Base {
260
261
  async handleShareCommand() { say(this, 'share'); }
262
+ // Pi's own shutdown without its process.exit: the Terminal is restored and
263
+ // the session closed, then piagent-studio.mjs hands over to the new release.
264
+ async stopForRestart() {
265
+ if (this.isShuttingDown) return;
266
+ this.isShuttingDown = true;
267
+ this.themeController?.disableAutoSync?.();
268
+ await this.ui.terminal.drainInput(1000);
269
+ this.stop();
270
+ await this.runtimeHost.dispose();
271
+ }
261
272
  async handleBugCommand() { say(this, 'bug'); }
262
273
  suggestBugReport() {}
263
274
  crashReportInstructions() { return 'Lần sau mở lại: piagent studio, rồi /resume. Gửi admin của team giờ xảy ra lỗi.'; }
@@ -285,7 +296,7 @@ export function companyMode(Base, { summary, whatsNew, components }) {
285
296
  };
286
297
  }
287
298
 
288
- export function companyTerminalExtension({ managed, packageRoot, sdkRoot, bindingChanged = () => false }) {
299
+ export function companyTerminalExtension({ managed, packageRoot, sdkRoot, bindingChanged = () => false, restartInPlace = null }) {
289
300
  const require = createRequire(path.join(sdkRoot, 'package.json'));
290
301
  let tui;
291
302
  const components = async () => (tui ??= await import(pathToFileURL(require.resolve('@earendil-works/pi-tui')).href));
@@ -302,6 +313,15 @@ export function companyTerminalExtension({ managed, packageRoot, sdkRoot, bindin
302
313
  registerTerminalUpdateOffer(pi, { installed, packageRoot, restart: 'piagent studio',
303
314
  afterUpdate: () => bindingChanged() ? 'Bản mới đổi trình khởi chạy công ty: Agent Watch tự cập nhật cấu hình (cần Agent Watch đang chạy); piagent studio chờ việc này khi mở lại.' : null });
304
315
 
316
+ // `piagent reload` and a finished update: the company code is loaded once
317
+ // per process, so this Terminal starts again in place on the same
318
+ // conversation (piagent-studio.mjs), when idle. A Terminal opened by an
319
+ // older launcher cannot be started again for the member: it says so.
320
+ watchTerminalReload(pi, { apply: async (ctx, request) => {
321
+ if (!restartInPlace) { ctx.ui.notify(`Có Piagent ${request.version ?? 'mới'}: thoát rồi mở lại \`piagent studio\`, rồi /resume, để dùng bản mới.`, 'warning'); return; }
322
+ setTimeout(() => { void restartInPlace(); }, 0);
323
+ } });
324
+
305
325
  // The member's pick of look (/style); /settings is not offered here.
306
326
  registerStyleCommand(pi, { remember: true });
307
327
 
@@ -29,7 +29,8 @@ const scriptByCommand = {
29
29
  "piagent-dashboard": "scripts/piagent-dashboard.mjs",
30
30
  "piagent-pi-host": "scripts/pi-host.mjs",
31
31
  "piagent-skills": "scripts/skill-sources.mjs",
32
- "piagent-restore-pi": "scripts/personal-pi-restore.mjs"
32
+ "piagent-restore-pi": "scripts/personal-pi-restore.mjs",
33
+ "piagent-reload": "scripts/terminal-reload.mjs"
33
34
  };
34
35
 
35
36
  const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
@@ -93,6 +94,7 @@ if (invokedAs === "piagent") {
93
94
  console.log(" dashboard Open and manage the local session hub");
94
95
  console.log(" studio Open the managed company agent imported by Agent Watch");
95
96
  console.log(" pi Same as `piagent`: Pi on the release Piagent is qualified on, in Piagent's home");
97
+ console.log(" reload Move every open Piagent Terminal to the installed release, without closing them");
96
98
  console.log(" restore-pi Take an older Piagent install out of your own pi (~/.pi/agent)");
97
99
  console.log(" pi-host Show or install the Pi host Piagent runs");
98
100
  console.log(" skills Add, list or remove skill sources such as mattpocock/skills");
@@ -196,18 +198,48 @@ const runner = target.endsWith(".mjs") ? process.execPath : "bash";
196
198
  const runnerArgs = target.endsWith(".mjs")
197
199
  ? ["--disable-warning=ExperimentalWarning", "--import", pathToFileURL(path.join(sourceRoot, "scripts", "register-typescript-loader.mjs")).href, target]
198
200
  : [target];
199
- const child = spawn(runner, [...runnerArgs, ...forwardedArgs], {
200
- cwd: process.cwd(),
201
- env: script === "scripts/piagent-studio.mjs" ? { PATH: "/usr/bin:/bin", HOME: os.homedir(), TERM: process.env.TERM || "xterm-256color", LANG: "en_US.UTF-8" }
202
- : { ...process.env, PI_CODING_AGENT_DIR: piagentHome(), ...(terminal ? { PIAGENT_ACTIVE: "1" } : {}) },
203
- stdio: "inherit"
204
- });
201
+ // The company Terminal can start again in place on a new release (`piagent
202
+ // reload`, or after `piagent-update`): it writes the arguments that reopen its
203
+ // conversation to this file and exits with RESTART_CODE; the files of the
204
+ // installed release are run again with them, in the same terminal window.
205
+ const RESTART_CODE = 75;
206
+ const restartFile = script === "scripts/piagent-studio.mjs" ? path.join(os.homedir(), ".pi", "piagent-restart", `${process.pid}.json`) : null;
207
+ function takeRestart() {
208
+ if (!restartFile) return null;
209
+ try {
210
+ const value = JSON.parse(fs.readFileSync(restartFile, "utf8"));
211
+ fs.rmSync(restartFile, { force: true });
212
+ return Array.isArray(value?.args) && value.args.every((arg) => typeof arg === "string") ? value.args : null;
213
+ } catch { return null; }
214
+ }
205
215
 
206
- child.once("error", (error) => {
207
- const code = error && typeof error === "object" && "code" in error ? ` (${error.code})` : "";
208
- console.error(`Pi Agent command could not start ${runner}${code}. Ensure it is installed and available on PATH.`);
209
- process.exit(1);
210
- });
216
+ let child;
217
+ function launch(args) {
218
+ child = spawn(runner, [...runnerArgs, ...args], {
219
+ cwd: process.cwd(),
220
+ env: script === "scripts/piagent-studio.mjs" ? { PATH: "/usr/bin:/bin", HOME: os.homedir(), TERM: process.env.TERM || "xterm-256color", LANG: "en_US.UTF-8", PIAGENT_RESTART_FILE: restartFile }
221
+ : { ...process.env, PI_CODING_AGENT_DIR: piagentHome(), ...(terminal ? { PIAGENT_ACTIVE: "1" } : {}) },
222
+ stdio: "inherit"
223
+ });
224
+
225
+ child.once("error", (error) => {
226
+ const code = error && typeof error === "object" && "code" in error ? ` (${error.code})` : "";
227
+ console.error(`Pi Agent command could not start ${runner}${code}. Ensure it is installed and available on PATH.`);
228
+ process.exit(1);
229
+ });
230
+
231
+ child.once("exit", (code, signal) => {
232
+ if (signal) {
233
+ process.removeAllListeners(signal);
234
+ process.kill(process.pid, signal);
235
+ return;
236
+ }
237
+ const again = code === RESTART_CODE ? takeRestart() : null;
238
+ if (again) { launch(again); return; }
239
+ process.exit(code ?? 1);
240
+ });
241
+ }
242
+ launch(forwardedArgs);
211
243
 
212
244
  // A command stopped from outside (a script, an editor, a timeout) stops its
213
245
  // child too, rather than leaving a company run going in the background. A
@@ -215,12 +247,3 @@ child.once("error", (error) => {
215
247
  // stays until the child has finished.
216
248
  for (const signal of ["SIGTERM", "SIGHUP"]) process.on(signal, () => { try { child.kill(signal); } catch { /* already gone */ } });
217
249
  process.on("SIGINT", () => {});
218
-
219
- child.once("exit", (code, signal) => {
220
- if (signal) {
221
- process.removeAllListeners(signal);
222
- process.kill(process.pid, signal);
223
- return;
224
- }
225
- process.exit(code ?? 1);
226
- });
@@ -30,6 +30,11 @@ const home = os.homedir();
30
30
  // Read before the environment is cleared: a Herdr pane's socket for the
31
31
  // Terminal's reporter, and the PATH that finds the Windows browser from WSL.
32
32
  const herdr = herdrEnvironment(), ambientPath = process.env.PATH;
33
+ // The launcher (piagent-cli.mjs) names a file for a restart in place: the
34
+ // Terminal writes the arguments that reopen this conversation there and exits
35
+ // with RESTART_CODE, and the launcher starts the installed release with them.
36
+ const RESTART_CODE = 75, restartFile = /\/\.pi\/piagent-restart\/\d+\.json$/.test(process.env.PIAGENT_RESTART_FILE ?? '') ? process.env.PIAGENT_RESTART_FILE : null;
37
+ let relaunch = null;
33
38
  // Joining Agent Watch takes a few seconds; keys typed before the Terminal draws are lost, so say so.
34
39
  if (!['--check', '--prompt', '--serve', '--doctor', '--web', '--rpc'].some((f) => flags.has(f)) && process.stderr.isTTY) process.stderr.write('Piagent công ty: đang kết nối Agent Watch, chờ ô nhập hiện ra rồi gõ…\n');
35
40
  // Do this before importing the SDK: it must not discover personal keys, Node
@@ -148,7 +153,8 @@ try {
148
153
  const { companyTerminalExtension, companyToolRenderers, companyInteractiveMode, harnessSummary } = await import('./company-terminal.mjs');
149
154
  const toolRenderers = await companyToolRenderers(config.sdk_root);
150
155
  const packageRoot = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
151
- const terminal = companyTerminalExtension({ managed: () => current, packageRoot, sdkRoot: config.sdk_root,
156
+ const restart = { request: null };
157
+ const terminal = companyTerminalExtension({ managed: () => current, packageRoot, sdkRoot: config.sdk_root, restartInPlace: restartFile ? () => restart.request?.() : null,
152
158
  bindingChanged: () => { try { return digest(config.entrypoint) !== config.entrypoint_sha256; } catch { return true; } } });
153
159
  // Herdr shows the Terminal's state and reopens it after a restart; scripted runs have no pane to show.
154
160
  const reportToHerdr = herdr && !['--check', '--prompt', '--rpc'].some((f) => flags.has(f));
@@ -216,7 +222,15 @@ try {
216
222
  : write(typeof chunk === 'string' && chunk.includes('To resume this session:') ? `Mở lại cuộc trò chuyện này: piagent studio --project ${project}, rồi /resume\n` : chunk, ...rest);
217
223
  // /share, /bug, /login, /model, /thinking, /settings and /changelog: company-terminal.mjs.
218
224
  const CompanyMode = await companyInteractiveMode(api, { sdkRoot: config.sdk_root, packageRoot, summary: () => harnessSummary(current) });
219
- await new CompanyMode(host, { verbose: false }).run();
225
+ const mode = new CompanyMode(host, { verbose: false });
226
+ const restarting = new Promise((resolve) => { restart.request = async () => {
227
+ if (relaunch) return;
228
+ const file = current?.session.sessionManager.getSessionFile?.(), saved = file && fs.existsSync(file) ? file : null;
229
+ const kept = []; for (let i = 0; i < args.length; i++) { if (args[i] === '--session') { i++; continue; } kept.push(args[i]); }
230
+ relaunch = [...kept, ...(saved ? ['--session', saved] : [])];
231
+ await mode.stopForRestart(); resolve();
232
+ }; });
233
+ await Promise.race([mode.run(), restarting]);
220
234
  }
221
235
  }
222
236
  } catch (error) {
@@ -229,3 +243,9 @@ try {
229
243
  : process.platform === 'linux' ? 'Trong Agent Watch cho Windows, chọn lại Kết nối Piagent trong WSL.' : 'Mở Agent Watch → Studio, nhập lại cấu hình cho Piagent, hoặc kiểm tra quyền Keychain.');
230
244
  process.stderr.write(`Agent Watch: ${code}. ${hint}\n`); process.exitCode = 1;
231
245
  } finally { await gateway?.close(); if (current) await current.dispose(); else await broker?.dispose(); hold?.release(); }
246
+ if (relaunch && restartFile) {
247
+ fs.mkdirSync(path.dirname(restartFile), { recursive: true, mode: 0o700 });
248
+ fs.writeFileSync(restartFile, JSON.stringify({ args: relaunch }), { mode: 0o600 });
249
+ process.stderr.write('Piagent công ty: đang mở lại với bản mới, giữ nguyên cuộc trò chuyện…\n');
250
+ process.exit(RESTART_CODE);
251
+ }
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ // `piagent reload`: every open Piagent Terminal on this machine (`piagent`
3
+ // and `piagent studio`) loads the installed release when it is idle; a task
4
+ // running in one finishes first. The conversation stays open. piagent-update
5
+ // asks the same once it installed a release.
6
+ import fs from "node:fs";
7
+ import { requestTerminalReload } from "../packages/piagent-core/runtime/update/terminal-reload.mjs";
8
+
9
+ if (process.argv.slice(2).some((arg) => ["--help", "-h"].includes(arg))) {
10
+ console.log("Usage: piagent reload\n\nEvery open Piagent Terminal (piagent, piagent studio) loads the installed release when it is idle.\nA task running in one finishes first; the conversation stays open.");
11
+ process.exit(0);
12
+ }
13
+ const manifest = JSON.parse(fs.readFileSync(new URL("../package.json", import.meta.url), "utf8"));
14
+ requestTerminalReload({ version: manifest.version, piHost: manifest.peerDependencies?.["@earendil-works/pi-coding-agent"] ?? null });
15
+ console.log(`Piagent ${manifest.version}: các Terminal đang mở (piagent, piagent studio) sẽ nạp bản này khi rảnh; Terminal đang chạy task thì nạp khi task xong. Cuộc trò chuyện giữ nguyên.`);
@@ -552,6 +552,16 @@ function main() {
552
552
  : `\nPASS: updated to v${targetHelper}.`);
553
553
  // A dashboard started before the update still serves the earlier release.
554
554
  if (!options.dryRun && helperNeedsChange) console.log("Open the dashboard with `piagent dashboard`: one still running an earlier release is restarted on the new one.");
555
+ // Open Terminals move to the new release when they are idle (a run in
556
+ // progress finishes first): the same request as `piagent reload`.
557
+ if (!options.dryRun && (helperNeedsChange || packageNeedsChange)) {
558
+ import("../packages/piagent-core/runtime/update/terminal-reload.mjs")
559
+ .then(({ requestTerminalReload }) => {
560
+ requestTerminalReload({ version: targetHelper, piHost: targetHost });
561
+ console.log("Open Terminals (piagent, piagent studio) load the new release when idle; a running task finishes first.");
562
+ })
563
+ .catch(() => console.log("Open Terminals keep the earlier release until reopened (`piagent reload` asks them again)."));
564
+ }
555
565
  }
556
566
 
557
567
  main();