@piagent/platform 1.4.1 → 1.5.1

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 (92) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +5 -1
  3. package/README.vi.md +21 -1
  4. package/docs/command-reference-vietnamese.md +2 -2
  5. package/docs/distribution-standard.md +7 -7
  6. package/docs/languages.json +2 -2
  7. package/docs/operator-manual-vietnamese.md +7 -7
  8. package/docs/publishing-for-teams.md +6 -0
  9. package/docs/release-install-policy.md +6 -6
  10. package/docs/security-threat-model.md +1 -1
  11. package/docs/team-onboarding.md +2 -2
  12. package/docs-site/architecture.html +1 -1
  13. package/docs-site/benchmark.html +1 -1
  14. package/docs-site/commands.html +1 -1
  15. package/docs-site/context-engine.html +1 -1
  16. package/docs-site/en/architecture.html +1 -1
  17. package/docs-site/en/benchmark.html +1 -1
  18. package/docs-site/en/commands.html +1 -1
  19. package/docs-site/en/context-engine.html +1 -1
  20. package/docs-site/en/index.html +1 -1
  21. package/docs-site/en/mcp-approval.html +1 -1
  22. package/docs-site/en/mcp-auth.html +1 -1
  23. package/docs-site/en/mcp-servers.html +1 -1
  24. package/docs-site/en/mcp.html +1 -1
  25. package/docs-site/en/permissions.html +1 -1
  26. package/docs-site/en/profiles.html +1 -1
  27. package/docs-site/en/quickstart.html +1 -1
  28. package/docs-site/en/runtime.html +1 -1
  29. package/docs-site/en/scope.html +1 -1
  30. package/docs-site/en/security.html +1 -1
  31. package/docs-site/en/team.html +1 -1
  32. package/docs-site/en/whats-new.html +1 -1
  33. package/docs-site/en/workflows.html +1 -1
  34. package/docs-site/index.html +1 -1
  35. package/docs-site/mcp-approval.html +1 -1
  36. package/docs-site/mcp-auth.html +1 -1
  37. package/docs-site/mcp-servers.html +1 -1
  38. package/docs-site/mcp.html +1 -1
  39. package/docs-site/permissions.html +1 -1
  40. package/docs-site/profiles.html +1 -1
  41. package/docs-site/quickstart.html +1 -1
  42. package/docs-site/runtime.html +1 -1
  43. package/docs-site/scope.html +1 -1
  44. package/docs-site/security.html +1 -1
  45. package/docs-site/team.html +1 -1
  46. package/docs-site/whats-new.html +1 -1
  47. package/docs-site/workflows.html +1 -1
  48. package/evals/fixtures/piagent-webui/document-workspace-v1.invalid.json +17 -0
  49. package/evals/fixtures/piagent-webui/document-workspace-v1.valid.json +42 -0
  50. package/evals/fixtures/piagent-webui/session-command-v1.valid.json +2 -1
  51. package/package.json +1 -1
  52. package/packages/piagent-core/extensions/document-intake.ts +6 -3
  53. package/packages/piagent-core/extensions/piagent-guard.ts +2 -2
  54. package/packages/piagent-core/package.json +1 -1
  55. package/packages/piagent-core/runtime/input/attachment-document-command.ts +39 -0
  56. package/packages/piagent-core/runtime/input/attachment-reservation.ts +36 -0
  57. package/packages/{piagent-webui/extension → piagent-core/runtime/input}/attachment-store.ts +221 -44
  58. package/packages/piagent-core/runtime/inspection/document-workspace-projection.ts +276 -0
  59. package/packages/piagent-core/runtime/inspection/project-runtime-inspection.ts +20 -5
  60. package/packages/piagent-core/runtime/inspection/session-identity.ts +20 -0
  61. package/packages/piagent-core/runtime/registration/workflow-commands.ts +5 -4
  62. package/packages/piagent-core/runtime/workflows/input-routing.ts +13 -2
  63. package/packages/piagent-webui/dist/client/assets/MarkdownMessage-Uouhx1QO.js +29 -0
  64. package/packages/piagent-webui/dist/client/assets/index-BV-_03yl.css +1 -0
  65. package/packages/piagent-webui/dist/client/assets/index-MBZq8XLV.js +174 -0
  66. package/packages/piagent-webui/dist/client/index.html +2 -2
  67. package/packages/piagent-webui/extension/piagent-webui.ts +15 -2
  68. package/packages/piagent-webui/extension/same-session-bridge.ts +9 -9
  69. package/packages/piagent-webui/gateway/ai-capability-inspection.ts +53 -0
  70. package/packages/piagent-webui/gateway/gateway-service.ts +23 -3
  71. package/packages/piagent-webui/gateway/native-project-picker.ts +63 -7
  72. package/packages/piagent-webui/gateway/session-attachment-registry.ts +165 -0
  73. package/packages/piagent-webui/gateway/session-catalog.ts +62 -9
  74. package/packages/piagent-webui/gateway/session-command-controller.ts +47 -14
  75. package/packages/piagent-webui/gateway/session-inspection-registry.ts +30 -10
  76. package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +19 -10
  77. package/packages/piagent-webui/package.json +3 -1
  78. package/packages/piagent-webui/server/core-inspection-provider.ts +48 -11
  79. package/packages/piagent-webui/server/ipc-read-model-client.ts +2 -0
  80. package/packages/piagent-webui/server/loopback-server.ts +63 -25
  81. package/packages/piagent-webui/server/read-model-provider.ts +2 -0
  82. package/packages/piagent-webui/server/read-only-router.ts +6 -0
  83. package/packages/piagent-webui/server/transcript-projection.ts +43 -2
  84. package/schemas/piagent-webui/attachment-v1.schema.json +24 -4
  85. package/schemas/piagent-webui/capabilities-v1.schema.json +2 -2
  86. package/schemas/piagent-webui/catalog-v1.json +9 -0
  87. package/schemas/piagent-webui/document-workspace-v1.schema.json +155 -0
  88. package/schemas/piagent-webui/session-command-v1.schema.json +14 -3
  89. package/schemas/piagent-webui/transcript-v1.schema.json +27 -0
  90. package/scripts/verify-local.sh +16 -1
  91. package/packages/piagent-webui/dist/client/assets/index-DwKCWbwd.css +0 -1
  92. package/packages/piagent-webui/dist/client/assets/index-bu7XpD9Q.js +0 -172
@@ -30,7 +30,7 @@
30
30
  <span>Pi Agent Platform</span>
31
31
  </a>
32
32
  <div class="top-actions">
33
- <span class="pill"><span class="pill-dot"></span>v1.4.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.5.1 docs · VI</span>
34
34
  <nav class="language-switch" aria-label="Ngôn ngữ">
35
35
  <a class="language-option current" href="/mcp-servers" hreflang="vi" lang="vi" aria-current="true">VI</a>
36
36
  <a class="language-option" href="/en/mcp-servers" hreflang="en" lang="en">EN</a>
@@ -30,7 +30,7 @@
30
30
  <span>Pi Agent Platform</span>
31
31
  </a>
32
32
  <div class="top-actions">
33
- <span class="pill"><span class="pill-dot"></span>v1.4.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.5.1 docs · VI</span>
34
34
  <nav class="language-switch" aria-label="Ngôn ngữ">
35
35
  <a class="language-option current" href="/mcp" hreflang="vi" lang="vi" aria-current="true">VI</a>
36
36
  <a class="language-option" href="/en/mcp" hreflang="en" lang="en">EN</a>
@@ -30,7 +30,7 @@
30
30
  <span>Pi Agent Platform</span>
31
31
  </a>
32
32
  <div class="top-actions">
33
- <span class="pill"><span class="pill-dot"></span>v1.4.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.5.1 docs · VI</span>
34
34
  <nav class="language-switch" aria-label="Ngôn ngữ">
35
35
  <a class="language-option current" href="/permissions" hreflang="vi" lang="vi" aria-current="true">VI</a>
36
36
  <a class="language-option" href="/en/permissions" hreflang="en" lang="en">EN</a>
@@ -30,7 +30,7 @@
30
30
  <span>Pi Agent Platform</span>
31
31
  </a>
32
32
  <div class="top-actions">
33
- <span class="pill"><span class="pill-dot"></span>v1.4.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.5.1 docs · VI</span>
34
34
  <nav class="language-switch" aria-label="Ngôn ngữ">
35
35
  <a class="language-option current" href="/profiles" hreflang="vi" lang="vi" aria-current="true">VI</a>
36
36
  <a class="language-option" href="/en/profiles" hreflang="en" lang="en">EN</a>
@@ -30,7 +30,7 @@
30
30
  <span>Pi Agent Platform</span>
31
31
  </a>
32
32
  <div class="top-actions">
33
- <span class="pill"><span class="pill-dot"></span>v1.4.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.5.1 docs · VI</span>
34
34
  <nav class="language-switch" aria-label="Ngôn ngữ">
35
35
  <a class="language-option current" href="/quickstart" hreflang="vi" lang="vi" aria-current="true">VI</a>
36
36
  <a class="language-option" href="/en/quickstart" hreflang="en" lang="en">EN</a>
@@ -30,7 +30,7 @@
30
30
  <span>Pi Agent Platform</span>
31
31
  </a>
32
32
  <div class="top-actions">
33
- <span class="pill"><span class="pill-dot"></span>v1.4.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.5.1 docs · VI</span>
34
34
  <nav class="language-switch" aria-label="Ngôn ngữ">
35
35
  <a class="language-option current" href="/runtime" hreflang="vi" lang="vi" aria-current="true">VI</a>
36
36
  <a class="language-option" href="/en/runtime" hreflang="en" lang="en">EN</a>
@@ -30,7 +30,7 @@
30
30
  <span>Pi Agent Platform</span>
31
31
  </a>
32
32
  <div class="top-actions">
33
- <span class="pill"><span class="pill-dot"></span>v1.4.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.5.1 docs · VI</span>
34
34
  <nav class="language-switch" aria-label="Ngôn ngữ">
35
35
  <a class="language-option current" href="/scope" hreflang="vi" lang="vi" aria-current="true">VI</a>
36
36
  <a class="language-option" href="/en/scope" hreflang="en" lang="en">EN</a>
@@ -30,7 +30,7 @@
30
30
  <span>Pi Agent Platform</span>
31
31
  </a>
32
32
  <div class="top-actions">
33
- <span class="pill"><span class="pill-dot"></span>v1.4.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.5.1 docs · VI</span>
34
34
  <nav class="language-switch" aria-label="Ngôn ngữ">
35
35
  <a class="language-option current" href="/security" hreflang="vi" lang="vi" aria-current="true">VI</a>
36
36
  <a class="language-option" href="/en/security" hreflang="en" lang="en">EN</a>
@@ -30,7 +30,7 @@
30
30
  <span>Pi Agent Platform</span>
31
31
  </a>
32
32
  <div class="top-actions">
33
- <span class="pill"><span class="pill-dot"></span>v1.4.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.5.1 docs · VI</span>
34
34
  <nav class="language-switch" aria-label="Ngôn ngữ">
35
35
  <a class="language-option current" href="/team" hreflang="vi" lang="vi" aria-current="true">VI</a>
36
36
  <a class="language-option" href="/en/team" hreflang="en" lang="en">EN</a>
@@ -30,7 +30,7 @@
30
30
  <span>Pi Agent Platform</span>
31
31
  </a>
32
32
  <div class="top-actions">
33
- <span class="pill"><span class="pill-dot"></span>v1.4.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.5.1 docs · VI</span>
34
34
  <nav class="language-switch" aria-label="Ngôn ngữ">
35
35
  <a class="language-option current" href="/whats-new" hreflang="vi" lang="vi" aria-current="true">VI</a>
36
36
  <a class="language-option" href="/en/whats-new" hreflang="en" lang="en">EN</a>
@@ -30,7 +30,7 @@
30
30
  <span>Pi Agent Platform</span>
31
31
  </a>
32
32
  <div class="top-actions">
33
- <span class="pill"><span class="pill-dot"></span>v1.4.1 docs · VI</span>
33
+ <span class="pill"><span class="pill-dot"></span>v1.5.1 docs · VI</span>
34
34
  <nav class="language-switch" aria-label="Ngôn ngữ">
35
35
  <a class="language-option current" href="/workflows" hreflang="vi" lang="vi" aria-current="true">VI</a>
36
36
  <a class="language-option" href="/en/workflows" hreflang="en" lang="en">EN</a>
@@ -0,0 +1,17 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "version": "piagent-webui-document-workspace-v1",
4
+ "messageType": "document",
5
+ "generatedAt": "2026-08-17T09:00:00.000Z",
6
+ "documentRef": "document_01",
7
+ "state": "unavailable",
8
+ "name": null,
9
+ "relativePath": null,
10
+ "rootRef": null,
11
+ "format": null,
12
+ "text": "# Ke hoach quy ba\n\nContent that must never accompany a refusal.\n",
13
+ "sizeBytes": null,
14
+ "truncated": false,
15
+ "redacted": false,
16
+ "reasonCode": "document-protected"
17
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "version": "piagent-webui-document-workspace-v1",
4
+ "messageType": "listing",
5
+ "generatedAt": "2026-08-17T09:00:00.000Z",
6
+ "state": "ready",
7
+ "roots": [
8
+ { "rootRef": "document-root_01", "path": "/workspace/project", "source": "project", "documentCount": 2 },
9
+ { "rootRef": "document-root_02", "path": "/home/operator/Downloads", "source": "profile", "documentCount": 1 }
10
+ ],
11
+ "documents": [
12
+ {
13
+ "documentRef": "document_01",
14
+ "rootRef": "document-root_01",
15
+ "name": "ke-hoach.md",
16
+ "relativePath": "tai-lieu/ke-hoach.md",
17
+ "extension": "md",
18
+ "sizeBytes": 4096,
19
+ "modifiedAt": "2026-08-17T08:30:00.000Z"
20
+ },
21
+ {
22
+ "documentRef": "document_02",
23
+ "rootRef": "document-root_01",
24
+ "name": "bao-cao.docx",
25
+ "relativePath": "tai-lieu/bao-cao.docx",
26
+ "extension": "docx",
27
+ "sizeBytes": 245760,
28
+ "modifiedAt": "2026-08-17T08:45:00.000Z"
29
+ },
30
+ {
31
+ "documentRef": "document_03",
32
+ "rootRef": "document-root_02",
33
+ "name": "vendor-spec.pdf",
34
+ "relativePath": "vendor-spec.pdf",
35
+ "extension": "pdf",
36
+ "sizeBytes": 1048576,
37
+ "modifiedAt": "2026-08-16T17:10:00.000Z"
38
+ }
39
+ ],
40
+ "truncated": false,
41
+ "reasonCode": null
42
+ }
@@ -14,6 +14,7 @@
14
14
  "delivery": "new-operation",
15
15
  "message": "Continue the gateway implementation.",
16
16
  "messageRequestId": "message_request_01",
17
- "expectedOperationRef": null
17
+ "expectedOperationRef": null,
18
+ "attachmentRefs": ["attachment_01"]
18
19
  }
19
20
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@piagent/platform",
3
- "version": "1.4.1",
3
+ "version": "1.5.1",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -51,7 +51,7 @@ export type DocumentExtraction =
51
51
  | { status: "ok"; text: string; truncated: boolean; kind: "text" | "docx" | "pdf" }
52
52
  | { status: "error"; reason: string };
53
53
 
54
- type DocumentCommandResult = { status: number | null; stdout: string; stderr: string; error?: Error };
54
+ export type DocumentCommandResult = { status: number | null; stdout: string; stderr: string; error?: Error };
55
55
 
56
56
  export function expandHome(candidate: string, home: string | undefined): string {
57
57
  if (candidate === "~") return home ?? candidate;
@@ -450,7 +450,10 @@ export function extractPdfFromDescriptor(
450
450
  // stdout out. The converter is handed the already-open descriptor rather than
451
451
  // a path, so it reads the file whose identity was verified and cannot be
452
452
  // pointed somewhere else by a name that changed in the meantime.
453
- const result = run("pdftotext", ["-layout", "-enc", "UTF-8", "-", "-"], fd);
453
+ return extractPdfCommandResult(run("pdftotext", ["-layout", "-enc", "UTF-8", "-", "-"], fd));
454
+ }
455
+
456
+ export function extractPdfCommandResult(result: DocumentCommandResult): DocumentExtraction {
454
457
  if (result.error) {
455
458
  return {
456
459
  status: "error",
@@ -471,7 +474,7 @@ export function extractPdfFromDescriptor(
471
474
 
472
475
  // spawnSync blocks the whole runtime, so an external converter that never
473
476
  // returns would hang the session rather than fail the read.
474
- const PDF_TIMEOUT_MS = 20_000;
477
+ export const PDF_TIMEOUT_MS = 20_000;
475
478
 
476
479
  export function probeExecutableOnPath(executable: string): DocumentCommandResult {
477
480
  const result = spawnSync("/bin/sh", ["-c", 'command -v "$1"', "piagent-command-probe", executable], {
@@ -115,7 +115,7 @@ import {
115
115
  activeTaskToolGroups
116
116
  } from "../runtime/tools/tool-groups.ts";
117
117
  import type { PiagentToolGroup } from "../runtime/tools/tool-groups.ts";
118
- import { shortTaskLabel } from "../runtime/workflows/input-routing.ts";
118
+ import { freshRequestParts, shortTaskLabel } from "../runtime/workflows/input-routing.ts";
119
119
  import {
120
120
  automaticAcceptanceCriteria,
121
121
  automaticReviewLenses,
@@ -4705,7 +4705,7 @@ export default function piagentGuard(pi: ExtensionAPI) {
4705
4705
  safeTaskId, searchContextIndex, searchContextIndexV2, searchMemoryFiles, selectRuntimeAction,
4706
4706
  selectValueFromUi, selectVerificationPlan, semanticCompactionInstructions, sendWorkflowFollowUp, setPermissionOverrideForContext,
4707
4707
  semanticRepairCompletionBlock: (cwd: string, taskRunId: string) => semanticRepairRuntime.completionBlock(cwd, taskRunId),
4708
- shellArg, shortTaskLabel, solverShadow, summarizeAttempt, taskChangedFileEvidence,
4708
+ freshRequestParts, shellArg, shortTaskLabel, solverShadow, summarizeAttempt, taskChangedFileEvidence,
4709
4709
  techContextDirPath, techContextFilePath, techContextRelativePath, techOptionById, techStackPath,
4710
4710
  telemetry, toolRegistryConfig, trajectoryRuntime, uniqueStrings, usageExactCommands,
4711
4711
  validTaskScopePattern, validateNewWorkPlan, verifierCommandInstructions, verifyProjectCapabilityState, workingTreeEvidenceDigest,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@piagent/core",
3
- "version": "1.4.1",
3
+ "version": "1.5.1",
4
4
  "type": "module",
5
5
  "private": true,
6
6
  "license": "MIT",
@@ -0,0 +1,39 @@
1
+ import { spawn } from "node:child_process";
2
+
3
+ import { MAX_DOCUMENT_BYTES, PDF_TIMEOUT_MS, probeExecutableOnPath,
4
+ type DocumentCommandResult } from "../../extensions/document-intake.ts";
5
+
6
+ export type AttachmentDocumentCommand = (executable: string, args: string[], input?: Buffer) =>
7
+ DocumentCommandResult | Promise<DocumentCommandResult>;
8
+
9
+ // The converter is external and may consume its full timeout. Run it without a
10
+ // shell and without blocking Pi's event loop, while bounding both output pipes.
11
+ export function runAttachmentDocumentCommand(executable: string, args: string[], input?: Buffer):
12
+ DocumentCommandResult | Promise<DocumentCommandResult> {
13
+ if (executable === "command") return probeExecutableOnPath(args[1] ?? "");
14
+ return new Promise((resolve) => {
15
+ let child: ReturnType<typeof spawn>;
16
+ try { child = spawn(executable, args, { stdio: ["pipe", "pipe", "pipe"] }); }
17
+ catch (cause) { resolve({ status: null, stdout: "", stderr: "", error: cause as Error }); return; }
18
+ const stdout: Buffer[] = [], stderr: Buffer[] = []; let stdoutBytes = 0, stderrBytes = 0, settled = false;
19
+ const finish = (result: DocumentCommandResult) => {
20
+ if (settled) return; settled = true; clearTimeout(timer); resolve(result);
21
+ };
22
+ const overflow = () => {
23
+ child.kill("SIGKILL");
24
+ const error = new Error("document converter output exceeded its limit"); (error as NodeJS.ErrnoException).code = "ENOBUFS";
25
+ finish({ status: null, stdout: "", stderr: "", error });
26
+ };
27
+ child.stdout.on("data", (chunk: Buffer) => { stdoutBytes += chunk.length; if (stdoutBytes > MAX_DOCUMENT_BYTES) overflow(); else stdout.push(chunk); });
28
+ child.stderr.on("data", (chunk: Buffer) => { stderrBytes += chunk.length; if (stderrBytes > MAX_DOCUMENT_BYTES) overflow(); else stderr.push(chunk); });
29
+ child.on("error", (error) => finish({ status: null, stdout: "", stderr: "", error }));
30
+ child.on("close", (status) => finish({ status, stdout: Buffer.concat(stdout).toString("utf8"), stderr: Buffer.concat(stderr).toString("utf8") }));
31
+ const timer = setTimeout(() => {
32
+ child.kill("SIGKILL"); const error = new Error("document converter ETIMEDOUT");
33
+ finish({ status: null, stdout: "", stderr: "", error });
34
+ }, PDF_TIMEOUT_MS);
35
+ timer.unref();
36
+ child.stdin.on("error", () => undefined);
37
+ child.stdin.end(input);
38
+ });
39
+ }
@@ -0,0 +1,36 @@
1
+ export type AttachmentReservation<T> = {
2
+ prepared: T;
3
+ commit(): void;
4
+ release(): void;
5
+ };
6
+
7
+ // A small transaction primitive for staged attachments. The map is the lock:
8
+ // only one dispatch may prepare a ref, and only that dispatch may consume it.
9
+ export function reserveAttachments<TRecord extends { attachmentRef: string }, TPrepared>(input: {
10
+ records: TRecord[];
11
+ live: Map<string, TRecord>;
12
+ reservations: Map<string, string>;
13
+ token: string;
14
+ prepared: TPrepared;
15
+ consume(record: TRecord): void;
16
+ }): AttachmentReservation<TPrepared> {
17
+ for (const record of input.records) input.reservations.set(record.attachmentRef, input.token);
18
+ let state: "active" | "committed" | "released" = "active";
19
+ return {
20
+ prepared: input.prepared,
21
+ commit: () => {
22
+ if (state === "committed") return;
23
+ if (state !== "active" || input.records.some((record) => input.live.get(record.attachmentRef) !== record
24
+ || input.reservations.get(record.attachmentRef) !== input.token)) throw new Error("attachment-reservation-unavailable");
25
+ state = "committed";
26
+ input.records.forEach(input.consume);
27
+ },
28
+ release: () => {
29
+ if (state !== "active") return;
30
+ state = "released";
31
+ for (const record of input.records) {
32
+ if (input.reservations.get(record.attachmentRef) === input.token) input.reservations.delete(record.attachmentRef);
33
+ }
34
+ }
35
+ };
36
+ }