@piagent/platform 1.48.1 → 1.48.3
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 +32 -0
- package/README.md +2 -0
- package/README.vi.md +2 -0
- package/docs/command-reference-vietnamese.md +4 -3
- package/docs/distribution-standard.md +6 -6
- package/docs/harness-conformance.md +4 -0
- package/docs/languages.json +2 -2
- package/docs/operator-manual-vietnamese.md +7 -7
- package/docs/publishing-for-teams.md +2 -0
- package/docs/release-install-policy.md +2 -2
- package/docs/team-onboarding.md +2 -2
- package/docs-site/architecture.html +1 -1
- package/docs-site/assets/search-en.json +1 -1
- package/docs-site/assets/search-vi.json +1 -1
- package/docs-site/benchmark.html +1 -1
- package/docs-site/commands.html +1 -1
- package/docs-site/content/en/update.html +8 -0
- package/docs-site/content/update.html +8 -0
- package/docs-site/context-engine.html +1 -1
- package/docs-site/ecosystem.html +1 -1
- package/docs-site/en/architecture.html +1 -1
- package/docs-site/en/benchmark.html +1 -1
- package/docs-site/en/commands.html +1 -1
- package/docs-site/en/context-engine.html +1 -1
- package/docs-site/en/ecosystem.html +1 -1
- package/docs-site/en/index.html +15 -15
- package/docs-site/en/mcp-approval.html +1 -1
- package/docs-site/en/mcp-auth.html +1 -1
- package/docs-site/en/mcp-servers.html +1 -1
- package/docs-site/en/mcp.html +1 -1
- package/docs-site/en/permissions.html +1 -1
- package/docs-site/en/profiles.html +1 -1
- package/docs-site/en/quickstart.html +1 -1
- package/docs-site/en/runtime.html +1 -1
- package/docs-site/en/scope.html +1 -1
- package/docs-site/en/security.html +1 -1
- package/docs-site/en/team.html +1 -1
- package/docs-site/en/update.html +11 -3
- package/docs-site/en/whats-new.html +52 -27
- package/docs-site/en/windows.html +1 -1
- package/docs-site/en/workflows.html +1 -1
- package/docs-site/index.html +15 -15
- package/docs-site/mcp-approval.html +1 -1
- package/docs-site/mcp-auth.html +1 -1
- package/docs-site/mcp-servers.html +1 -1
- package/docs-site/mcp.html +1 -1
- package/docs-site/permissions.html +1 -1
- package/docs-site/profiles.html +1 -1
- package/docs-site/quickstart.html +1 -1
- package/docs-site/releases.json +77 -0
- package/docs-site/runtime.html +1 -1
- package/docs-site/scope.html +1 -1
- package/docs-site/security.html +1 -1
- package/docs-site/team.html +1 -1
- package/docs-site/update.html +11 -3
- package/docs-site/whats-new.html +52 -27
- package/docs-site/windows.html +1 -1
- package/docs-site/workflows.html +1 -1
- package/evals/private-holdout-v1/public-exposure.v2.json +2 -2
- package/package.json +1 -1
- package/packages/piagent-core/extensions/piagent-guard.ts +4 -1
- package/packages/piagent-core/extensions/workspace-inspection.ts +4 -1
- package/packages/piagent-core/managed/check-waiver.mjs +35 -0
- package/packages/piagent-core/managed/command-tools.mjs +2 -2
- package/packages/piagent-core/managed/dist/workspace/manifest.json +1 -1
- package/packages/piagent-core/managed/dist/workspace/worker.mjs +7 -1
- package/packages/piagent-core/managed/patch-snapshot.mjs +28 -13
- package/packages/piagent-core/managed/review-snapshot-request.mjs +1 -1
- package/packages/piagent-core/managed/review-snapshot-worker.mjs +52 -11
- package/packages/piagent-core/managed/session.mjs +9 -9
- package/packages/piagent-core/managed/workflow.mjs +8 -7
- package/packages/piagent-core/package.json +1 -1
- package/packages/piagent-core/runtime/update/terminal-reload.mjs +122 -0
- package/packages/piagent-core/runtime/update/terminal-update-offer.mjs +1 -1
- package/packages/piagent-webui/dist/client/assets/{ActivityPanel-DxQ3_dyT.js → ActivityPanel-Bv-jc1s3.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/App-DqN7B1JR.js +5 -0
- package/packages/piagent-webui/dist/client/assets/AttachmentImage-eZKqLYZ2.js +1 -0
- package/packages/piagent-webui/dist/client/assets/GatewayApp-B3--WjSd.js +63 -0
- package/packages/piagent-webui/dist/client/assets/{InspectionApp-pD-BqBXm.js → InspectionApp-BKQiA0Ce.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/{LineReview-C_0ZpgCH.js → LineReview-CB3mQe7m.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/MarkdownMessage-zw5RxDmZ.js +29 -0
- package/packages/piagent-webui/dist/client/assets/{SessionAgentWorkspace-3tM7Q6HH.js → SessionAgentWorkspace-ZAdRbxVA.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/SessionInspectorDrawer-B2e4-1FG.js +2 -0
- package/packages/piagent-webui/dist/client/assets/SettingsNavigation-C3MC0X4P.js +3 -0
- package/packages/piagent-webui/dist/client/assets/SettingsPage-D4os5vHj.js +1 -0
- package/packages/piagent-webui/dist/client/assets/{TerminalPanel-CtZyb0tj.js → TerminalPanel-CVYUiDkn.js} +2 -2
- package/packages/piagent-webui/dist/client/assets/{TerminalView-yaIg6RCs.js → TerminalView-C3upxbKw.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/{WorkspaceCodeEditor-BS_ZrjPN.js → WorkspaceCodeEditor-E0Zopcke.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/WorkspaceExplorer-DldLoJyf.js +5 -0
- package/packages/piagent-webui/dist/client/assets/WorkspaceFilePreview-CvIBYige.js +1 -0
- package/packages/piagent-webui/dist/client/assets/{WorkspaceQuickOpen-CJmMBmK8.js → WorkspaceQuickOpen-Bi-kTEEU.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/index-DcrpSyBK.js +37 -0
- package/packages/piagent-webui/dist/client/assets/{tab-close-ITV4Cf4X.js → tab-close-BwkkhMH7.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/transcript-view-model-acWtHGyE.js +3 -0
- package/packages/piagent-webui/dist/client/assets/{ui-preferences-0waeSO-S.js → ui-preferences-OfS30-ZV.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/{vendor-CSDKB7mU.js → vendor-DNZbaWhT.js} +62 -26
- package/packages/piagent-webui/dist/client/assets/{workspace-api-D8sJkiZB.js → workspace-api-CFBR73lU.js} +1 -1
- package/packages/piagent-webui/dist/client/assets/workspace-navigation-DW8zhH6U.js +1 -0
- package/packages/piagent-webui/dist/client/index.html +3 -3
- package/packages/piagent-webui/shared/process-copy.ts +2 -1
- package/schemas/piagent-webui/workspace-media-v1.schema.json +6 -0
- package/scripts/company-terminal.mjs +21 -1
- package/scripts/piagent-cli.mjs +44 -21
- package/scripts/piagent-studio.mjs +22 -2
- package/scripts/terminal-reload.mjs +15 -0
- package/scripts/update-global.mjs +10 -0
- package/packages/piagent-webui/dist/client/assets/App-fZeIRoaD.js +0 -5
- package/packages/piagent-webui/dist/client/assets/GatewayApp-CpC4lgYK.js +0 -99
- package/packages/piagent-webui/dist/client/assets/MarkdownMessage-DGt5B-6D.js +0 -29
- package/packages/piagent-webui/dist/client/assets/SessionInspectorDrawer-BJ94aQ6y.js +0 -2
- package/packages/piagent-webui/dist/client/assets/SettingsNavigation-BFfqMcuL.js +0 -3
- package/packages/piagent-webui/dist/client/assets/SettingsPage-CxpZ7cdM.js +0 -1
- package/packages/piagent-webui/dist/client/assets/WorkspaceExplorer-CkFBpcM7.js +0 -5
- package/packages/piagent-webui/dist/client/assets/index-CNdhIouM.js +0 -37
- package/packages/piagent-webui/dist/client/assets/transcript-view-model-CpEMY1xb.js +0 -3
- package/packages/piagent-webui/dist/client/assets/workspace-navigation-DkVobhwg.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./bootstrap-CedkNtRG.js";async function t(t,n,r,i){let a=new URLSearchParams({path:r}),o=await fetch(`/api/v1/sessions/${encodeURIComponent(t)}/inspection/workspace/${n}?${a}`,{credentials:`same-origin`,headers:{Accept:`application/json`},signal:i});if(o.status===401&&e(),!o.ok)throw Error(`workspace-read-failed`);return await o.json()}var n=(e,n,r)=>t(e,`tree`,n,r),r=(e,n,r)=>t(e,`file`,n,r),i=(e,n,r)=>t(e,`media`,n,r);async function a(t,n,r){let i=await fetch(`/api/v1/sessions/${encodeURIComponent(t)}/inspection/workspace/paths?${new URLSearchParams({query:n})}`,{credentials:`same-origin`,headers:{Accept:`application/json`},signal:r});if(i.status===401&&e(),!i.ok)throw Error(`workspace-read-failed`);return await i.json()}async function o(t,n,r){let i=await fetch(`/api/v1/sessions/${encodeURIComponent(t)}/inspection/workspace/search?${new URLSearchParams({query:n})}`,{credentials:`same-origin`,headers:{Accept:`application/json`},signal:r});if(i.status===401&&e(),!i.ok)throw Error(`workspace-read-failed`);return await i.json()}
|
|
1
|
+
import{o as e}from"./bootstrap-CedkNtRG.js";async function t(t,n,r,i){let a=new URLSearchParams({path:r}),o=await fetch(`/api/v1/sessions/${encodeURIComponent(t)}/inspection/workspace/${n}?${a}`,{credentials:`same-origin`,headers:{Accept:`application/json`},signal:i});if(o.status===401&&e(),!o.ok)throw Error(`workspace-read-failed`);return await o.json()}var n=(e,n,r)=>t(e,`tree`,n,r),r=(e,n,r)=>t(e,`file`,n,r),i=(e,n,r)=>t(e,`media`,n,r);async function a(t,n,r){let i=await fetch(`/api/v1/sessions/${encodeURIComponent(t)}/inspection/workspace/paths?${new URLSearchParams({query:n})}`,{credentials:`same-origin`,headers:{Accept:`application/json`},signal:r});if(i.status===401&&e(),!i.ok)throw Error(`workspace-read-failed`);return await i.json()}async function o(t,n,r){let i=await fetch(`/api/v1/sessions/${encodeURIComponent(t)}/inspection/workspace/search?${new URLSearchParams({query:n})}`,{credentials:`same-origin`,headers:{Accept:`application/json`},signal:r});if(i.status===401&&e(),!i.ok)throw Error(`workspace-read-failed`);return await i.json()}async function s(e,t){let n=t.split(`/`).at(-1)??`file`,a=await i(e,t).catch(()=>null),o=a?.data&&a.mime?`data:${a.mime};base64,${a.data}`:null,s=!1;if(!o){let n=await r(e,t).catch(()=>null);if(typeof n?.content!=`string`)return!1;o=URL.createObjectURL(new Blob([n.content],{type:`text/plain`})),s=!0}let c=document.createElement(`a`);return c.href=o,c.download=n,document.body.append(c),c.click(),c.remove(),s&&setTimeout(()=>URL.revokeObjectURL(o),1e4),!0}export{s as a,n as i,i as n,o,a as r,r as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{An as t,Rn as n,Ut as r,zt as i}from"./vendor-DNZbaWhT.js";import{i as a,n as o}from"./ui-preferences-OfS30-ZV.js";import{h as s}from"./api-BQS4Dtrr.js";var c=e(n(),1);function l(e,t=1){let n=/^(.+?)(?::(\d+)(?::\d+)?)?$/.exec(e.replace(/^@/,``)),r=n?.[1];return!r||r.length>4096||/^[~/]/.test(r)||/[\\\x00-\x1f\x7f:]/.test(r)||r.split(`/`).some(e=>!e||e===`.`||e===`..`)?null:{path:r,line:Math.max(1,Math.min(1e6,Number(n?.[2])||t||1))}}function u(e){let t=e.trim();if(!t||t.length>4096||/^(?:https?|mailto|data|javascript):/i.test(t)||t.startsWith(`#`))return null;if(/^file:/i.test(t))try{t=new URL(t).pathname}catch{return null}try{t=decodeURIComponent(t)}catch{}let n=/#L(\d+)(?:-L?\d+)?$/.exec(t),r=n?Number(n[1]):void 0;if(n&&(t=t.slice(0,n.index)),t=t.replace(/^\.\//,``),t.startsWith(`/`)){let e=/^(\/.+?)(?::(\d+)(?::\d+)?)?$/.exec(t),n=e?.[1]??``;return!n||/[\x00-\x1f\x7f]/.test(n)||n.split(`/`).slice(1).some(e=>!e||e===`.`||e===`..`)?null:{path:n,line:Math.max(1,Math.min(1e6,r??(Number(e?.[2])||1))),absolute:!0}}let i=l(t,r);return i?{...i,absolute:!1}:null}var d=t(),f=`piagent-workspace-open`;async function p(e,t){let n=(await s(e)).roots.find(e=>e.source===`project`&&t.startsWith(`${e.path.replace(/\/+$/,``)}/`));return n?t.slice(n.path.replace(/\/+$/,``).length+1):null}async function m(e,t){return t.absolute?p(e,t.path):t.path}var h=(0,c.createContext)(null);function g(){return(0,c.useContext)(h)}var _=(0,c.createContext)(null);function v({sessionRef:e,onOpen:t,children:n}){let r=n=>{t(),window.dispatchEvent(new CustomEvent(f,{detail:{sessionRef:e,...n}}))};return(0,d.jsx)(_.Provider,{value:e?t=>{if(!(`absolute`in t)||!t.absolute){r({path:t.path,line:t.line});return}p(e,t.path).then(e=>{e&&r({path:e,line:t.line})},()=>void 0)}:null,children:(0,d.jsx)(h.Provider,{value:e??null,children:n})})}function y({path:e,line:t,children:n}){let i=(0,c.useContext)(_),{locale:s}=a(),u=l(e,t);return!i||!u?n?(0,d.jsx)(d.Fragment,{children:n}):null:(0,d.jsx)(r,{size:`small`,onClick:()=>i(u),sx:{textTransform:`none`,verticalAlign:`baseline`},children:n??o(s,`Mở trong editor`,`Open in editor`)})}function b({link:e,children:t}){let n=(0,c.useContext)(_),{locale:r}=a();return n?(0,d.jsx)(i,{component:`button`,type:`button`,underline:`hover`,onClick:()=>n(e),title:o(r,`Mở ${e.path}`,`Open ${e.path}`),sx:{font:`inherit`,verticalAlign:`baseline`,textAlign:`left`},children:t}):(0,d.jsx)(d.Fragment,{children:t})}function x({children:e}){return(0,d.jsx)(d.Fragment,{children:c.Children.map(e,e=>typeof e==`string`?e.split(/((?<![\w@])@[\w./-]+\.[\w]+(?::\d+)?)/g).map((e,t)=>e.startsWith(`@`)&&l(e)?(0,d.jsx)(y,{path:e,children:e},t):e):e)})}export{v as a,u as c,x as i,l,y as n,m as o,b as r,g as s,f as t};
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
<meta name="csp-nonce" content="__PIAGENT_CSP_NONCE__" />
|
|
8
8
|
<meta name="piagent-webui-mode" content="__PIAGENT_WEBUI_MODE__" />
|
|
9
9
|
<title>Piagent WebUI</title>
|
|
10
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
+
<script type="module" crossorigin src="/assets/index-DcrpSyBK.js"></script>
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-hePW80VL.js">
|
|
12
|
-
<link rel="modulepreload" crossorigin href="/assets/vendor-
|
|
13
|
-
<link rel="modulepreload" crossorigin href="/assets/ui-preferences-
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/vendor-DNZbaWhT.js">
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/assets/ui-preferences-OfS30-ZV.js">
|
|
14
14
|
<link rel="stylesheet" crossorigin href="/assets/index-CjM70M7D.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
@@ -15,7 +15,8 @@ const SEVERITY: Record<string, [string, string]> = { blocking: ["blocking", "blo
|
|
|
15
15
|
const KIND: Record<string, [string, string]> = { wrong_premise: ["sai giả định", "wrong premise"], conflicts_with_request: ["conflict với yêu cầu", "conflicts with the request"],
|
|
16
16
|
ambiguous: ["chưa rõ ràng", "ambiguous"], out_of_scope: ["out of scope", "out of scope"] };
|
|
17
17
|
const UNAVAILABLE: Record<string, [string, string]> = { too_large: ["patch quá lớn", "the patch is too large"], not_git: ["thư mục không phải git", "not a git repository"],
|
|
18
|
-
limit: ["subagent đã hết lượt gọi", "the subagent ran out of calls"], failed: ["subagent lỗi", "the subagent failed"]
|
|
18
|
+
limit: ["subagent đã hết lượt gọi", "the subagent ran out of calls"], failed: ["subagent lỗi", "the subagent failed"],
|
|
19
|
+
runtime_changed: ["Piagent vừa được cập nhật, hãy mở lại cuộc trò chuyện", "Piagent was just updated; reopen the conversation"] };
|
|
19
20
|
|
|
20
21
|
// How a code-changing turn ended against the Harness workflow, in a few words.
|
|
21
22
|
export function outcomeText(process: ProcessCopyInput, locale: CopyLocale): string {
|
|
@@ -40,6 +40,12 @@
|
|
|
40
40
|
"image/bmp",
|
|
41
41
|
"image/x-icon",
|
|
42
42
|
"image/avif",
|
|
43
|
+
"image/svg+xml",
|
|
44
|
+
"application/pdf",
|
|
45
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
46
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
47
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
48
|
+
"application/zip",
|
|
43
49
|
null
|
|
44
50
|
]
|
|
45
51
|
},
|
|
@@ -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
|
|
package/scripts/piagent-cli.mjs
CHANGED
|
@@ -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
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
|
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
|
-
|
|
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();
|