@piagent/platform 1.31.1 → 1.32.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 (64) hide show
  1. package/CHANGELOG.md +28 -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 +12 -0
  16. package/docs-site/content/index.html +4 -4
  17. package/docs-site/content/whats-new.html +12 -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 +13 -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 +13 -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/managed/request-stream.mjs +33 -4
  58. package/packages/piagent-core/package.json +1 -1
  59. package/packages/piagent-core/runtime/managed-failure.mjs +5 -0
  60. package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-ZFXG_br8.js → MarkdownMessage-dCzZ2b6f.js} +1 -1
  61. package/packages/piagent-webui/dist/client/assets/{index-B3ODBFGj.js → index-CZ02zZjO.js} +5 -5
  62. package/packages/piagent-webui/dist/client/index.html +1 -1
  63. package/packages/piagent-webui/server/loopback-server.ts +1 -0
  64. package/packages/piagent-webui/server/session-auth.ts +16 -3
@@ -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-B3ODBFGj.js"></script>
10
+ <script type="module" crossorigin src="/assets/index-CZ02zZjO.js"></script>
11
11
  <link rel="stylesheet" crossorigin href="/assets/index-B5XOKQy-.css">
12
12
  </head>
13
13
  <body>
@@ -112,6 +112,7 @@ export async function startLoopbackServer(options: {
112
112
  // Charging every tab and every prior launch to one localhost IP lets a
113
113
  // refresh or an unauthenticated local process lock out the active operator.
114
114
  const browserSession = auth.authenticate(request, now);
115
+ if (browserSession && auth.renew(browserSession, now)) response.setHeader("Set-Cookie", auth.cookieHeader(browserSession));
115
116
  const rateKey = browserSession ? `${remote}:${browserSession.id}` : `remote:${remote}`;
116
117
  for (const [key, value] of rates) if (now - value.windowStart >= 60_000) rates.delete(key);
117
118
  const rate = rates.get(rateKey) ?? { windowStart: now, requests: 0, bootstrapFailures: 0 };
@@ -20,20 +20,23 @@ function cookie(request: IncomingMessage, name: string): string | null {
20
20
  return null;
21
21
  }
22
22
 
23
- export type BrowserSession = { id: string; csrf: string; expiresAt: number };
23
+ export type BrowserSession = { id: string; csrf: string; expiresAt: number; startedAt: number };
24
24
 
25
25
  export class SessionAuthority {
26
26
  readonly #initialBootstrap: string;
27
27
  readonly #bootstrapTtlMs: number;
28
28
  readonly #sessionTtlMs: number;
29
+ readonly #sessionMaxMs: number;
29
30
  readonly #cookieSigningKey = randomBytes(32);
30
31
  #cookieName = SESSION_COOKIE;
31
32
  #bootstraps = new Map<string, number>();
32
33
  #sessions = new Map<string, BrowserSession>();
33
34
 
34
- constructor(options: { now?: number; bootstrapTtlMs?: number; sessionTtlMs?: number } = {}) {
35
+ constructor(options: { now?: number; bootstrapTtlMs?: number; sessionTtlMs?: number; sessionMaxMs?: number } = {}) {
35
36
  this.#bootstrapTtlMs = options.bootstrapTtlMs ?? 60_000;
37
+ // 8 hours unused; a tab in use is renewed (renew), up to 7 days.
36
38
  this.#sessionTtlMs = options.sessionTtlMs ?? 8 * 60 * 60_000;
39
+ this.#sessionMaxMs = options.sessionMaxMs ?? 7 * 24 * 60 * 60_000;
37
40
  this.#initialBootstrap = this.issueBootstrapCapability(options.now ?? Date.now());
38
41
  }
39
42
 
@@ -59,7 +62,7 @@ export class SessionAuthority {
59
62
  const match = [...this.#bootstraps].find(([value, createdAt]) => now <= createdAt + this.#bootstrapTtlMs && equal(candidate, value));
60
63
  if (!match) return null;
61
64
  this.#bootstraps.delete(match[0]);
62
- const session = { id: randomUUID(), csrf: secret(), expiresAt: now + this.#sessionTtlMs };
65
+ const session = { id: randomUUID(), csrf: secret(), expiresAt: now + this.#sessionTtlMs, startedAt: now };
63
66
  this.#sessions.set(session.id, session);
64
67
  return session;
65
68
  }
@@ -79,6 +82,16 @@ export class SessionAuthority {
79
82
  return session;
80
83
  }
81
84
 
85
+ // A session ended 8 hours after its launch even while its tab was in use:
86
+ // a turn that ran or hung that long ended on the expired screen. An open
87
+ // tab asks every minute, so past half its time a request moves the expiry
88
+ // on, within the cap; true when the caller must send the cookie again.
89
+ renew(session: BrowserSession, now = Date.now()): boolean {
90
+ const next = Math.min(now + this.#sessionTtlMs, session.startedAt + this.#sessionMaxMs);
91
+ if (next - session.expiresAt < this.#sessionTtlMs / 2) return false;
92
+ session.expiresAt = next; return true;
93
+ }
94
+
82
95
  authorizeMutation(request: IncomingMessage, now = Date.now()): BrowserSession | null {
83
96
  const session = this.authenticate(request, now);
84
97
  const csrf = request.headers["x-piagent-csrf"];