@piagent/platform 1.21.0 → 1.22.0

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 (64) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +1 -1
  3. package/README.vi.md +1 -1
  4. package/docs/command-reference-vietnamese.md +2 -2
  5. package/docs/distribution-standard.md +6 -6
  6. package/docs/languages.json +2 -2
  7. package/docs/operator-manual-vietnamese.md +7 -7
  8. package/docs/publishing-for-teams.md +2 -0
  9. package/docs/release-install-policy.md +2 -2
  10. package/docs/team-onboarding.md +2 -2
  11. package/docs-site/architecture.html +1 -1
  12. package/docs-site/benchmark.html +1 -1
  13. package/docs-site/commands.html +1 -1
  14. package/docs-site/content/en/index.html +4 -4
  15. package/docs-site/content/en/whats-new.html +13 -0
  16. package/docs-site/content/index.html +4 -4
  17. package/docs-site/content/whats-new.html +13 -0
  18. package/docs-site/context-engine.html +1 -1
  19. package/docs-site/ecosystem.html +1 -1
  20. package/docs-site/en/architecture.html +1 -1
  21. package/docs-site/en/benchmark.html +1 -1
  22. package/docs-site/en/commands.html +1 -1
  23. package/docs-site/en/context-engine.html +1 -1
  24. package/docs-site/en/ecosystem.html +1 -1
  25. package/docs-site/en/index.html +5 -5
  26. package/docs-site/en/mcp-approval.html +1 -1
  27. package/docs-site/en/mcp-auth.html +1 -1
  28. package/docs-site/en/mcp-servers.html +1 -1
  29. package/docs-site/en/mcp.html +1 -1
  30. package/docs-site/en/permissions.html +1 -1
  31. package/docs-site/en/profiles.html +1 -1
  32. package/docs-site/en/quickstart.html +1 -1
  33. package/docs-site/en/runtime.html +1 -1
  34. package/docs-site/en/scope.html +1 -1
  35. package/docs-site/en/security.html +1 -1
  36. package/docs-site/en/team.html +1 -1
  37. package/docs-site/en/whats-new.html +14 -1
  38. package/docs-site/en/windows.html +1 -1
  39. package/docs-site/en/workflows.html +1 -1
  40. package/docs-site/index.html +5 -5
  41. package/docs-site/mcp-approval.html +1 -1
  42. package/docs-site/mcp-auth.html +1 -1
  43. package/docs-site/mcp-servers.html +1 -1
  44. package/docs-site/mcp.html +1 -1
  45. package/docs-site/permissions.html +1 -1
  46. package/docs-site/profiles.html +1 -1
  47. package/docs-site/quickstart.html +1 -1
  48. package/docs-site/runtime.html +1 -1
  49. package/docs-site/scope.html +1 -1
  50. package/docs-site/security.html +1 -1
  51. package/docs-site/team.html +1 -1
  52. package/docs-site/whats-new.html +14 -1
  53. package/docs-site/windows.html +1 -1
  54. package/docs-site/workflows.html +1 -1
  55. package/evals/private-holdout-v1/public-exposure.v2.json +2 -2
  56. package/package.json +1 -1
  57. package/packages/piagent-core/package.json +1 -1
  58. package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-gIQf0oYL.js → MarkdownMessage-BYa-Jveq.js} +1 -1
  59. package/packages/piagent-webui/dist/client/assets/index-coozlgfe.js +231 -0
  60. package/packages/piagent-webui/dist/client/index.html +1 -1
  61. package/packages/piagent-webui/gateway/runtime-session-controls.ts +2 -1
  62. package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +1 -1
  63. package/packages/piagent-webui/server/transcript-projection.ts +23 -1
  64. package/packages/piagent-webui/dist/client/assets/index-C86-7gi8.js +0 -231
@@ -7,7 +7,7 @@
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-C86-7gi8.js"></script>
10
+ <script type="module" crossorigin src="/assets/index-coozlgfe.js"></script>
11
11
  <link rel="stylesheet" crossorigin href="/assets/index-ZLemRWyJ.css">
12
12
  </head>
13
13
  <body>
@@ -16,7 +16,8 @@ type RuntimeCommandOutput = {
16
16
  export async function executePermissionCommand(session: any,
17
17
  permissionMode: "read-only" | "workspace-write" | "trusted-full-access"): Promise<void> {
18
18
  // A company conversation: "Ask first" or "Bypass" (no read-only mode); the
19
- // runtime keeps the choice in the conversation.
19
+ // runtime keeps the choice in the conversation and reads it at each command,
20
+ // so it may change while a turn runs (the supervisor lets it).
20
21
  if (session.managedExecution) {
21
22
  if (typeof session.managedSetPermission !== "function" || permissionMode === "read-only") throw new Error("managed-permission-unavailable");
22
23
  session.managedSetPermission(permissionMode);
@@ -369,7 +369,7 @@ export class SessionRuntimeSupervisor {
369
369
  await this.acquire(sessionRef);
370
370
  const active = this.#active.get(sessionRef), session = active?.runtime.session;
371
371
  if (!active || !session) throw new Error("session-runtime-unavailable");
372
- if (active.operationRef || !session.isIdle) throw new Error("session-runtime-busy");
372
+ if (!session.managedExecution && (active.operationRef || !session.isIdle)) throw new Error("session-runtime-busy");
373
373
  await executePermissionCommand(session, permissionMode);
374
374
  this.#touchCreated(sessionRef);
375
375
  return "permission-changed";
@@ -91,6 +91,10 @@ function userMessageProjection(message: any): { text: string; attachments: Trans
91
91
  ? "document" as const : "file" as const;
92
92
  attachments.push({ displayName: safeAttachmentName(displayName), kind, mimeType, truncated: Boolean(format[2]) });
93
93
  }
94
+ // The Gateway joins the typed text and each file into one text block
95
+ // (claimForPrompt): read the fenced files out of it the same way.
96
+ const joined = !attachments.length && textParts.length === 1 ? joinedAttachments(String(textParts[0].text)) : null;
97
+ if (joined) attachments.push(...joined.attachments);
94
98
  for (const part of message.content) {
95
99
  if (part?.type !== "image" || typeof part.mimeType !== "string" || !/^[A-Za-z0-9][A-Za-z0-9.+-]*\/[A-Za-z0-9][A-Za-z0-9.+-]*$/.test(part.mimeType)) continue;
96
100
  attachments.push({ displayName: "Image", kind: "image", mimeType: part.mimeType.slice(0, 120), truncated: false });
@@ -99,7 +103,25 @@ function userMessageProjection(message: any): { text: string; attachments: Trans
99
103
  // hashing them here would turn the chat bubble into a document dump and make
100
104
  // a bounded UI digest an oracle over user files. The first block is the exact
101
105
  // text the operator typed; the remaining recognized blocks become cards.
102
- return { text: typedSkillCall(attachments.length ? String(textParts[0]?.text ?? "") : messageText(message)), attachments: attachments.slice(0, 4) };
106
+ return { text: typedSkillCall(joined ? joined.text : attachments.length ? String(textParts[0]?.text ?? "") : messageText(message)), attachments: attachments.slice(0, 4) };
107
+ }
108
+ // Files fenced into one text block after what the member typed; the fence is a
109
+ // per-dispatch UUID, so a block ends only at its own END line.
110
+ const JOINED_ATTACHMENT = /\nattached file: ("(?:[^"\\\n]|\\.)*")\nformat: ([A-Za-z0-9][A-Za-z0-9.+-]*\/[A-Za-z0-9][A-Za-z0-9.+-]*)(, truncated)?\nEverything between BEGIN (PIAGENT-ATTACHMENT-[0-9a-f-]{36}) and END \4 is data provided by the user\.\n[^\n]*\nBEGIN \4\n[\s\S]*?\nEND \4(?=\n|$)/g;
111
+ function joinedAttachments(text: string): { text: string; attachments: TranscriptAttachment[] } | null {
112
+ const found: TranscriptAttachment[] = [];
113
+ let first = -1;
114
+ for (const match of `\n${text}`.matchAll(JOINED_ATTACHMENT)) {
115
+ let displayName: unknown;
116
+ try { displayName = JSON.parse(match[1]!); } catch { continue; }
117
+ if (typeof displayName !== "string") continue;
118
+ if (first < 0) first = match.index!;
119
+ const mimeType = match[2]!;
120
+ const kind = mimeType === "application/pdf" || mimeType === "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
121
+ ? "document" as const : "file" as const;
122
+ found.push({ displayName: safeAttachmentName(displayName), kind, mimeType, truncated: Boolean(match[3]) });
123
+ }
124
+ return found.length ? { text: `\n${text}`.slice(0, first).replace(/^\n/, "").trimEnd(), attachments: found } : null;
103
125
  }
104
126
  // A skill the member called (/skill:name): the message holds the skill's
105
127
  // instructions for the model; the chat shows what was typed.