@piagent/platform 1.46.1 → 1.46.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.
- package/CHANGELOG.md +16 -0
- package/docs/command-reference-vietnamese.md +2 -2
- package/docs/distribution-standard.md +6 -6
- package/docs/operator-manual-vietnamese.md +7 -7
- package/docs/publishing-for-teams.md +1 -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/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 +9 -9
- 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 +3 -3
- package/docs-site/en/whats-new.html +27 -16
- package/docs-site/en/windows.html +1 -1
- package/docs-site/en/workflows.html +1 -1
- package/docs-site/index.html +9 -9
- 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 +31 -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 +3 -3
- package/docs-site/whats-new.html +27 -16
- package/docs-site/windows.html +1 -1
- package/docs-site/workflows.html +1 -1
- package/evals/private-holdout-v1/public-exposure.v2.json +1 -1
- package/package.json +1 -1
- package/packages/piagent-core/extensions/piagent-guard.ts +4 -1
- package/packages/piagent-core/package.json +1 -1
- package/packages/piagent-core/runtime/hooks/session-hooks.ts +6 -0
- package/packages/piagent-webui/gateway/gateway-session-stream.ts +24 -0
|
@@ -25,6 +25,9 @@ type SessionHookDependencies = {
|
|
|
25
25
|
) => TaskContract | undefined;
|
|
26
26
|
onTurnEnd?: (ctx: ExtensionContext) => void;
|
|
27
27
|
onAgentSettled?: (ctx: ExtensionContext) => void | Promise<void>;
|
|
28
|
+
// Display-only work after settlement. Pi takes the next message only when
|
|
29
|
+
// agent_settled handlers return, so this runs without holding the host.
|
|
30
|
+
afterAgentSettled?: (ctx: ExtensionContext) => void | Promise<void>;
|
|
28
31
|
beforeShutdown?: (ctx: ExtensionContext) => void | Promise<void>;
|
|
29
32
|
};
|
|
30
33
|
|
|
@@ -103,6 +106,9 @@ export function registerSessionHooks(pi: ExtensionAPI, dependencies: SessionHook
|
|
|
103
106
|
taskOutcome: task?.trace.outcome
|
|
104
107
|
});
|
|
105
108
|
await dependencies.onAgentSettled?.(ctx);
|
|
109
|
+
if (dependencies.afterAgentSettled) {
|
|
110
|
+
void Promise.resolve().then(() => dependencies.afterAgentSettled?.(ctx)).catch(() => undefined);
|
|
111
|
+
}
|
|
106
112
|
});
|
|
107
113
|
|
|
108
114
|
pi.on("session_compact", async (event, ctx) => {
|
|
@@ -13,6 +13,16 @@ const MAX_EVENTS = 128;
|
|
|
13
13
|
const MAX_DELTA = 16_384;
|
|
14
14
|
const PRIVATE_BEGIN = /-----BEGIN [A-Z ]*PRIVATE KEY-----/;
|
|
15
15
|
const PRIVATE_END = /-----END [A-Z ]*PRIVATE KEY-----/;
|
|
16
|
+
// Within a line, text goes out as it arrives except its last words: a secret
|
|
17
|
+
// written over several words ("Authorization: Basic …", "password: …",
|
|
18
|
+
// "--token …") is then whole on one side of every cut.
|
|
19
|
+
const HELD_WORDS = 6;
|
|
20
|
+
// A key whose quoted value has not closed yet (`password = "two words…`).
|
|
21
|
+
const OPEN_QUOTED_VALUE = /(?:(?::=|:|=)\s*|--[A-Za-z][A-Za-z0-9_.-]*\s+)(["'])(?:(?!\1)[^\r\n])*$/;
|
|
22
|
+
// Pieces of a line share MAX_EVENTS with whole lines: they grow as the
|
|
23
|
+
// operation's events are spent, and stop leaving whole lines a reserve.
|
|
24
|
+
const PIECE_EVENTS = 96;
|
|
25
|
+
const PIECE_MIN_CHARS = 24;
|
|
16
26
|
const RUNTIME_DRIFT = /Installed Piagent runtime changed (?:during this session|while the capability lock was being re-pinned)/i;
|
|
17
27
|
const COMPLETION_GATE = /^\[Piagent completion gate: (CONTINUING|NOT APPROVED)\]/i;
|
|
18
28
|
|
|
@@ -327,6 +337,7 @@ export class GatewaySessionStream {
|
|
|
327
337
|
const space = this.#buffer.search(/\s\S*$/);
|
|
328
338
|
take = space >= 0 ? space + 1 : this.#buffer.length >= 16_384 ? this.#buffer.length : 0;
|
|
329
339
|
}
|
|
340
|
+
if (take <= 0 && !final) take = this.#pieceEnd();
|
|
330
341
|
if (take <= 0) return;
|
|
331
342
|
const candidate = this.#buffer.slice(0, take), privateStart = candidate.search(PRIVATE_BEGIN);
|
|
332
343
|
if (privateStart >= 0 && !PRIVATE_END.test(candidate.slice(privateStart))) {
|
|
@@ -341,6 +352,19 @@ export class GatewaySessionStream {
|
|
|
341
352
|
this.#emit(redactSensitiveText(clean(source)).text);
|
|
342
353
|
}
|
|
343
354
|
|
|
355
|
+
#pieceEnd(): number {
|
|
356
|
+
if (this.#eventCount >= PIECE_EVENTS) return 0;
|
|
357
|
+
const line = this.#buffer, words = [...line.matchAll(/\s+(?=\S)/g)];
|
|
358
|
+
if (words.length < HELD_WORDS) return 0;
|
|
359
|
+
const word = words[words.length - HELD_WORDS]!, end = word.index + word[0].length;
|
|
360
|
+
if (end < PIECE_MIN_CHARS * 2 ** Math.floor(this.#eventCount / 32)) return 0;
|
|
361
|
+
// Wait for the quote to close: its words would otherwise leave the key.
|
|
362
|
+
if (OPEN_QUOTED_VALUE.test(line)) return 0;
|
|
363
|
+
const head = line.slice(0, end), tail = line.slice(end);
|
|
364
|
+
// The cut must not change what redaction finds in the text known so far.
|
|
365
|
+
return redactSensitiveText(head).text + redactSensitiveText(tail).text === redactSensitiveText(line).text ? end : 0;
|
|
366
|
+
}
|
|
367
|
+
|
|
344
368
|
#emit(value: string): void {
|
|
345
369
|
for (let offset = 0; offset < value.length; offset += MAX_DELTA) {
|
|
346
370
|
if (this.#eventCount >= MAX_EVENTS) { this.#truncated = true; break; }
|