@phyzess/pappra 0.1.0-beta.13 → 0.1.0-beta.18
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/README.md +134 -15
- package/assets/integrations/skills/pappra/SKILL.md +28 -7
- package/assets/integrations/skills/pappra/references/collaboration.md +633 -0
- package/assets/integrations/skills/pappra/references/environment.md +360 -0
- package/assets/integrations/skills/pappra/references/hosts.md +20 -0
- package/assets/integrations/skills/pappra/references/operations.md +36 -5
- package/dist/adapters/pi/recovery-extension.d.ts +65 -0
- package/dist/adapters/pi/recovery-extension.js +238 -0
- package/dist/adapters/pi/session-transition-extension.d.ts +30 -0
- package/dist/adapters/pi/session-transition-extension.js +265 -0
- package/dist/app/automatic-handoff-events.d.ts +26 -0
- package/dist/app/automatic-handoff-events.js +134 -0
- package/dist/app/bounded-file.d.ts +2 -0
- package/dist/app/bounded-file.js +2 -0
- package/dist/app/capability-evidence/claude.d.ts +37 -0
- package/dist/app/capability-evidence/claude.js +206 -0
- package/dist/app/capability-evidence/codex.d.ts +35 -0
- package/dist/app/capability-evidence/codex.js +193 -0
- package/dist/app/capability-evidence/index.d.ts +33 -0
- package/dist/app/capability-evidence/index.js +117 -0
- package/dist/app/capability-evidence/pi.d.ts +73 -0
- package/dist/app/capability-evidence/pi.js +669 -0
- package/dist/app/capability-evidence/shared.d.ts +69 -0
- package/dist/app/capability-evidence/shared.js +195 -0
- package/dist/app/collab-auto-handoff.d.ts +55 -0
- package/dist/app/collab-auto-handoff.js +384 -0
- package/dist/app/collab-bindings.d.ts +57 -0
- package/dist/app/collab-bindings.js +1006 -0
- package/dist/app/collab-bootstrap-transport.d.ts +163 -0
- package/dist/app/collab-bootstrap-transport.js +769 -0
- package/dist/app/collab-bootstrap.d.ts +137 -0
- package/dist/app/collab-bootstrap.js +3455 -0
- package/dist/app/collab-handoff.d.ts +12 -0
- package/dist/app/collab-handoff.js +511 -0
- package/dist/app/collab-messages.d.ts +2 -0
- package/dist/app/collab-messages.js +2 -0
- package/dist/app/collab-notify.d.ts +156 -0
- package/dist/app/collab-notify.js +1208 -0
- package/dist/app/collab-preflight.d.ts +34 -0
- package/dist/app/collab-preflight.js +96 -0
- package/dist/app/collab-recovery-executor.d.ts +161 -0
- package/dist/app/collab-recovery-executor.js +1153 -0
- package/dist/app/collab-recovery-projection.d.ts +103 -0
- package/dist/app/collab-recovery-projection.js +659 -0
- package/dist/app/collab-recovery.d.ts +25 -0
- package/dist/app/collab-recovery.js +429 -0
- package/dist/app/collab-resources.d.ts +16 -0
- package/dist/app/collab-resources.js +278 -0
- package/dist/app/collab-role-events.d.ts +22 -0
- package/dist/app/collab-role-events.js +329 -0
- package/dist/app/collab-role-orchestration.d.ts +53 -0
- package/dist/app/collab-role-orchestration.js +601 -0
- package/dist/app/collab-role-plan.d.ts +81 -0
- package/dist/app/collab-role-plan.js +504 -0
- package/dist/app/collab-role-repair.d.ts +109 -0
- package/dist/app/collab-role-repair.js +821 -0
- package/dist/app/collab-rollover.d.ts +263 -0
- package/dist/app/collab-rollover.js +1112 -0
- package/dist/app/collab-route.d.ts +64 -0
- package/dist/app/collab-route.js +240 -0
- package/dist/app/collab-session-transition.d.ts +221 -0
- package/dist/app/collab-session-transition.js +3334 -0
- package/dist/app/collab-state.d.ts +7 -0
- package/dist/app/collab-state.js +162 -0
- package/dist/app/collab-task-store.d.ts +22 -0
- package/dist/app/collab-task-store.js +204 -0
- package/dist/app/collab-work-execution.d.ts +127 -0
- package/dist/app/collab-work-execution.js +1027 -0
- package/dist/app/collab-work-plan.d.ts +87 -0
- package/dist/app/collab-work-plan.js +437 -0
- package/dist/app/collaboration.d.ts +8 -2
- package/dist/app/collaboration.js +101 -12
- package/dist/app/doctor.js +108 -5
- package/dist/app/host-mcp.js +34 -8
- package/dist/app/host-probe.js +4 -4
- package/dist/app/init.d.ts +58 -4
- package/dist/app/init.js +768 -155
- package/dist/app/managed-pi-bootstrap-admission.d.ts +14 -0
- package/dist/app/managed-pi-bootstrap-admission.js +104 -0
- package/dist/app/managed-pi-bootstrap-refresh.d.ts +10 -0
- package/dist/app/managed-pi-bootstrap-refresh.js +78 -0
- package/dist/app/managed-pi-delivery.d.ts +8 -0
- package/dist/app/managed-pi-delivery.js +110 -0
- package/dist/app/managed-pi-handoff-receiver.d.ts +15 -0
- package/dist/app/managed-pi-handoff-receiver.js +263 -0
- package/dist/app/managed-pi-handoff-reference.d.ts +3 -0
- package/dist/app/managed-pi-handoff-reference.js +60 -0
- package/dist/app/managed-pi-herdr.d.ts +21 -0
- package/dist/app/managed-pi-herdr.js +185 -0
- package/dist/app/managed-pi-initial-admission.d.ts +28 -0
- package/dist/app/managed-pi-initial-admission.js +416 -0
- package/dist/app/managed-pi-initial-launch.d.ts +5 -0
- package/dist/app/managed-pi-initial-launch.js +61 -0
- package/dist/app/managed-pi-native-observation.d.ts +36 -0
- package/dist/app/managed-pi-native-observation.js +191 -0
- package/dist/app/managed-pi-readiness.d.ts +29 -0
- package/dist/app/managed-pi-readiness.js +288 -0
- package/dist/app/managed-pi-repair-stop.d.ts +21 -0
- package/dist/app/managed-pi-repair-stop.js +371 -0
- package/dist/app/managed-pi-resume-admission.d.ts +32 -0
- package/dist/app/managed-pi-resume-admission.js +618 -0
- package/dist/app/managed-pi-retirement.d.ts +28 -0
- package/dist/app/managed-pi-retirement.js +112 -0
- package/dist/app/managed-pi-sdk-control.d.ts +7 -0
- package/dist/app/managed-pi-sdk-control.js +169 -0
- package/dist/app/managed-pi-sdk-runtime.d.ts +3 -0
- package/dist/app/managed-pi-sdk-runtime.js +483 -0
- package/dist/app/managed-pi-source-admission.d.ts +14 -0
- package/dist/app/managed-pi-source-admission.js +323 -0
- package/dist/app/managed-pi-transition-host.d.ts +36 -0
- package/dist/app/managed-pi-transition-host.js +292 -0
- package/dist/app/managed-pi.d.ts +54 -0
- package/dist/app/managed-pi.js +248 -0
- package/dist/app/shell-readiness.d.ts +66 -0
- package/dist/app/shell-readiness.js +368 -0
- package/dist/app/task-pin.d.ts +2 -23
- package/dist/app/task-pin.js +2 -113
- package/dist/cli/commands/collaboration-binding.d.ts +13 -0
- package/dist/cli/commands/collaboration-binding.js +118 -0
- package/dist/cli/commands/collaboration-bootstrap.d.ts +10 -0
- package/dist/cli/commands/collaboration-bootstrap.js +84 -0
- package/dist/cli/commands/collaboration-capabilities.d.ts +13 -0
- package/dist/cli/commands/collaboration-capabilities.js +127 -0
- package/dist/cli/commands/collaboration-handoff.d.ts +13 -0
- package/dist/cli/commands/collaboration-handoff.js +102 -0
- package/dist/cli/commands/collaboration-message.d.ts +17 -0
- package/dist/cli/commands/collaboration-message.js +177 -0
- package/dist/cli/commands/collaboration-plan.d.ts +8 -0
- package/dist/cli/commands/collaboration-plan.js +108 -0
- package/dist/cli/commands/collaboration-preflight.d.ts +10 -0
- package/dist/cli/commands/collaboration-preflight.js +167 -0
- package/dist/cli/commands/collaboration-recovery-run.d.ts +46 -0
- package/dist/cli/commands/collaboration-recovery-run.js +224 -0
- package/dist/cli/commands/collaboration-recovery.d.ts +11 -0
- package/dist/cli/commands/collaboration-recovery.js +104 -0
- package/dist/cli/commands/collaboration-resources.d.ts +11 -0
- package/dist/cli/commands/collaboration-resources.js +96 -0
- package/dist/cli/commands/collaboration-role-plan.d.ts +9 -0
- package/dist/cli/commands/collaboration-role-plan.js +69 -0
- package/dist/cli/commands/collaboration-role-run.d.ts +11 -0
- package/dist/cli/commands/collaboration-role-run.js +128 -0
- package/dist/cli/commands/collaboration-rollover.d.ts +10 -0
- package/dist/cli/commands/collaboration-rollover.js +103 -0
- package/dist/cli/commands/collaboration-state.d.ts +10 -0
- package/dist/cli/commands/collaboration-state.js +96 -0
- package/dist/cli/commands/collaboration-transition.d.ts +10 -0
- package/dist/cli/commands/collaboration-transition.js +75 -0
- package/dist/cli/commands/collaboration-work-run.d.ts +34 -0
- package/dist/cli/commands/collaboration-work-run.js +178 -0
- package/dist/cli/commands/collaboration.d.ts +4 -0
- package/dist/cli/commands/collaboration.js +39 -4
- package/dist/cli/commands/continuity.js +2 -6
- package/dist/cli/commands/docs.d.ts +2 -0
- package/dist/cli/commands/docs.js +89 -15
- package/dist/cli/commands/host.d.ts +7 -1
- package/dist/cli/commands/host.js +122 -7
- package/dist/cli/commands/init.d.ts +20 -3
- package/dist/cli/commands/init.js +897 -232
- package/dist/cli/commands/mcp.d.ts +1 -0
- package/dist/cli/commands/mcp.js +11 -5
- package/dist/cli/commands/repair.d.ts +12 -0
- package/dist/cli/commands/repair.js +41 -0
- package/dist/cli/commands/runtime.d.ts +1 -1
- package/dist/cli/commands/runtime.js +139 -38
- package/dist/cli/commands/session.d.ts +7 -0
- package/dist/cli/commands/session.js +82 -0
- package/dist/cli/commands/task.js +19 -5
- package/dist/cli/run.js +866 -24
- package/dist/code/identity.d.ts +7 -0
- package/dist/code/identity.js +7 -3
- package/dist/code/registration.js +7 -0
- package/dist/code/service.d.ts +9 -0
- package/dist/code/service.js +16 -3
- package/dist/code/text.js +19 -7
- package/dist/collab/admission.d.ts +91 -66
- package/dist/collab/admission.js +21 -6
- package/dist/collab/canonical.d.ts +1 -1
- package/dist/collab/canonical.js +44 -3
- package/dist/collab/envelope.d.ts +2 -2
- package/dist/collab/envelope.js +12 -12
- package/dist/collab/first-work.d.ts +3 -0
- package/dist/collab/first-work.js +15 -0
- package/dist/collab/handoff.d.ts +16 -0
- package/dist/collab/handoff.js +39 -5
- package/dist/collab/index.d.ts +97 -1
- package/dist/collab/index.js +9 -1
- package/dist/collab/messages.js +126 -3
- package/dist/collab/persisted-messages.d.ts +123 -0
- package/dist/collab/persisted-messages.js +496 -0
- package/dist/collab/preflight.d.ts +1 -1
- package/dist/collab/resources.d.ts +13 -3
- package/dist/collab/resources.js +37 -6
- package/dist/collab/rollover.d.ts +311 -0
- package/dist/collab/rollover.js +1024 -0
- package/dist/collab/store.d.ts +1 -0
- package/dist/collab/store.js +1 -4
- package/dist/collab/types.d.ts +2 -354
- package/dist/collab/validation.d.ts +2 -10
- package/dist/collab/validation.js +2 -303
- package/dist/collab/work-plan.d.ts +105 -0
- package/dist/collab/work-plan.js +843 -0
- package/dist/continuity/context.d.ts +11 -2
- package/dist/continuity/context.js +100 -13
- package/dist/continuity/handoff-bundle.d.ts +296 -0
- package/dist/continuity/handoff-bundle.js +477 -0
- package/dist/continuity/index.d.ts +2 -0
- package/dist/continuity/index.js +1 -0
- package/dist/continuity/paths.js +10 -2
- package/dist/continuity/service.js +91 -15
- package/dist/continuity/task-pin.d.ts +24 -0
- package/dist/continuity/task-pin.js +590 -0
- package/dist/doctor.d.ts +1 -0
- package/dist/doctor.js +6 -0
- package/dist/experimental/index.d.ts +13 -0
- package/dist/experimental/index.js +25 -0
- package/dist/experimental/pi.d.ts +4 -0
- package/dist/experimental/pi.js +12 -0
- package/dist/hosts/claude/native.js +1 -1
- package/dist/hosts/codex/native.js +1 -1
- package/dist/hosts/codex/protocol.js +1 -1
- package/dist/hosts/integration/bootstrap-config.d.ts +58 -0
- package/dist/hosts/integration/bootstrap-config.js +254 -0
- package/dist/hosts/integration/bundle-export.d.ts +44 -0
- package/dist/hosts/integration/bundle-export.js +366 -3
- package/dist/hosts/integration/bundle.js +3 -0
- package/dist/hosts/integration/hook.js +36 -9
- package/dist/hosts/integration/pappra-bootstrap-extension.mjs +80 -0
- package/dist/hosts/integration/pappra-extension-runtime.mjs +59 -24631
- package/dist/hosts/integration/pappra-hook.mjs +61 -24749
- package/dist/hosts/integration/pappra-recovery-extension.mjs +259 -0
- package/dist/hosts/integration/pappra-session-transition-extension.mjs +276 -0
- package/dist/hosts/integration/pi-bootstrap-extension.d.ts +36 -0
- package/dist/hosts/integration/pi-bootstrap-extension.js +101 -0
- package/dist/hosts/integration/pi-bootstrap-guard.d.ts +125 -0
- package/dist/hosts/integration/pi-bootstrap-guard.js +438 -0
- package/dist/hosts/integration/pi-bootstrap-runtime.d.ts +63 -0
- package/dist/hosts/integration/pi-bootstrap-runtime.js +223 -0
- package/dist/hosts/integration/pi-native-events.d.ts +112 -0
- package/dist/hosts/integration/pi-native-events.js +348 -0
- package/dist/hosts/integration/pi-rollover-extension.d.ts +166 -0
- package/dist/hosts/integration/pi-rollover-extension.js +431 -0
- package/dist/hosts/integration/recovery-config.d.ts +48 -0
- package/dist/hosts/integration/recovery-config.js +117 -0
- package/dist/hosts/integration/service.d.ts +6 -1
- package/dist/hosts/integration/service.js +485 -35
- package/dist/hosts/integration/support.d.ts +7 -0
- package/dist/hosts/integration/support.js +9 -1
- package/dist/hosts/integration/templates.d.ts +3 -0
- package/dist/hosts/integration/templates.js +26 -3
- package/dist/hosts/pi/managed-host-identity.d.ts +2 -0
- package/dist/hosts/pi/managed-host-identity.js +40 -0
- package/dist/hosts/pi/managed-provider-diagnostics.d.ts +6 -0
- package/dist/hosts/pi/managed-provider-diagnostics.js +184 -0
- package/dist/hosts/pi/managed-sdk-session.d.ts +335 -0
- package/dist/hosts/pi/managed-sdk-session.js +1639 -0
- package/dist/hosts/pi/managed-session-extension.d.ts +20 -0
- package/dist/hosts/pi/managed-session-extension.js +84 -0
- package/dist/hosts/pi/managed-session.d.ts +177 -0
- package/dist/hosts/pi/managed-session.js +1557 -0
- package/dist/hosts/pi/protocol.js +1 -1
- package/dist/hosts/pi/query-result.js +1 -1
- package/dist/hosts/pi/resume-capability.d.ts +41 -0
- package/dist/hosts/pi/resume-capability.js +33 -0
- package/dist/hosts/pi/rpc.d.ts +182 -134
- package/dist/hosts/pi/rpc.js +230 -37
- package/dist/hosts/pilot.d.ts +97 -74
- package/dist/hosts/pilot.js +5 -1
- package/dist/hosts/version.d.ts +3 -0
- package/dist/hosts/version.js +18 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/infra/bounded-file.d.ts +19 -0
- package/dist/infra/bounded-file.js +66 -0
- package/dist/infra/fs.js +10 -2
- package/dist/infra/git.d.ts +29 -0
- package/dist/infra/git.js +45 -9
- package/dist/infra/json-property.d.ts +2 -0
- package/dist/infra/json-property.js +69 -0
- package/dist/infra/json.d.ts +4 -0
- package/dist/infra/json.js +24 -0
- package/dist/infra/owned-process-group.js +1 -1
- package/dist/infra/private-lock.d.ts +16 -0
- package/dist/infra/private-lock.js +148 -0
- package/dist/infra/private-state.d.ts +7 -0
- package/dist/infra/private-state.js +146 -0
- package/dist/infra/process-identity.d.ts +12 -0
- package/dist/infra/process-identity.js +142 -0
- package/dist/infra/validation.d.ts +5 -0
- package/dist/infra/validation.js +15 -0
- package/dist/init.d.ts +1 -0
- package/dist/init.js +6 -0
- package/dist/install/apply.d.ts +9 -1
- package/dist/install/apply.js +176 -12
- package/dist/install/dependencies.d.ts +38 -0
- package/dist/install/dependencies.js +282 -0
- package/dist/install/ownership.js +30 -1
- package/dist/install/references.d.ts +31 -0
- package/dist/install/references.js +208 -0
- package/dist/install/repair.d.ts +37 -0
- package/dist/install/repair.js +798 -0
- package/dist/install/reset-local.d.ts +16 -0
- package/dist/install/reset-local.js +304 -0
- package/dist/install/rollback.d.ts +3 -0
- package/dist/install/rollback.js +9 -3
- package/dist/install/runtime.d.ts +10 -6
- package/dist/install/runtime.js +299 -59
- package/dist/install/source-fingerprint.d.ts +2 -0
- package/dist/install/source-fingerprint.js +103 -0
- package/dist/knowledge/catalog.d.ts +1 -0
- package/dist/knowledge/catalog.js +143 -10
- package/dist/knowledge/journal.js +17 -7
- package/dist/knowledge/paths.js +2 -1
- package/dist/knowledge/refs.js +4 -0
- package/dist/knowledge/register-batch.d.ts +4 -0
- package/dist/knowledge/register-batch.js +225 -0
- package/dist/knowledge/relocate.d.ts +5 -0
- package/dist/knowledge/relocate.js +92 -0
- package/dist/knowledge/scan.js +103 -47
- package/dist/knowledge/service.d.ts +3 -0
- package/dist/knowledge/service.js +33 -1
- package/dist/knowledge/write.d.ts +4 -1
- package/dist/knowledge/write.js +1 -1
- package/dist/mcp/server.d.ts +4 -2
- package/dist/mcp/server.js +87 -136
- package/dist/schemas/collaboration-state-validation.d.ts +6 -0
- package/dist/schemas/collaboration-state-validation.js +342 -0
- package/dist/schemas/collaboration-state.d.ts +436 -0
- package/dist/schemas/collaboration-state.js +1 -0
- package/dist/schemas/collaboration.d.ts +335 -0
- package/dist/schemas/collaboration.js +272 -0
- package/dist/schemas/continuity.d.ts +8 -0
- package/dist/schemas/continuity.js +13 -3
- package/dist/schemas/doctor.d.ts +1 -0
- package/dist/schemas/doctor.js +1 -0
- package/dist/schemas/document.d.ts +61 -0
- package/dist/schemas/document.js +9 -0
- package/dist/schemas/errors.d.ts +1 -0
- package/dist/schemas/errors.js +1 -0
- package/dist/schemas/host.d.ts +24 -0
- package/dist/schemas/host.js +19 -0
- package/dist/schemas/install.d.ts +8 -2
- package/dist/schemas/install.js +11 -1
- package/dist/schemas/managed-pi-execution.d.ts +16 -0
- package/dist/schemas/managed-pi-execution.js +2 -0
- package/dist/schemas/outcome.d.ts +9 -5
- package/dist/workspace/config-file.js +1 -3
- package/dist/workspace/documents.js +12 -2
- package/dist/workspace/repositories.d.ts +7 -0
- package/dist/workspace/repositories.js +14 -5
- package/package.json +35 -35
- package/skills/pappra/SKILL.md +28 -7
- package/skills/pappra/references/collaboration.md +633 -0
- package/skills/pappra/references/environment.md +360 -0
- package/skills/pappra/references/hosts.md +20 -0
- package/skills/pappra/references/operations.md +36 -5
- package/dist/app/collab-from.d.ts +0 -35
- package/dist/app/collab-from.js +0 -84
package/dist/hosts/pi/rpc.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { errorCode, object, parseJson } from '../../
|
|
1
|
+
import { errorCode, object, parseJson } from '../../infra/validation.js';
|
|
2
2
|
import { isAssignment } from '../../collab/contracts.js';
|
|
3
3
|
import { isPiRecord } from './protocol.js';
|
|
4
4
|
function errorDetail(error) {
|
|
@@ -15,6 +15,7 @@ import { admitLaunch, claimCovers, classifyIdentity, hasPendingCancellation, res
|
|
|
15
15
|
import { describeResource } from '../../collab/canonical.js';
|
|
16
16
|
import { buildMessage, sha256File } from '../../collab/envelope.js';
|
|
17
17
|
import { submitMessage } from '../../collab/messages.js';
|
|
18
|
+
import { readMessageFromTaskRoot } from '../../collab/persisted-messages.js';
|
|
18
19
|
import { findAttempt } from '../../collab/lifecycle.js';
|
|
19
20
|
import { createNonce, nowIso, readRecord } from '../../collab/store.js';
|
|
20
21
|
// Gated, owned Pi RPC lifecycle. One launch, one frozen prompt, repeated native queries and an
|
|
@@ -37,14 +38,19 @@ import { createNonce, nowIso, readRecord } from '../../collab/store.js';
|
|
|
37
38
|
const RPC_SCHEMA = 'harness-collab/pi-rpc/1';
|
|
38
39
|
const EXECUTION_SCHEMA = 'harness-collab/native-execution/1';
|
|
39
40
|
const DEFAULT_REQUEST_TIMEOUT_MS = 15000;
|
|
40
|
-
const DEFAULT_OPERATION_TIMEOUT_MS =
|
|
41
|
+
const DEFAULT_OPERATION_TIMEOUT_MS = 30 * 60 * 1000;
|
|
41
42
|
const DEFAULT_SHUTDOWN_TIMEOUT_MS = 5000;
|
|
42
43
|
const DEFAULT_SIGNAL_GRACE_MS = 2000;
|
|
43
44
|
const DEFAULT_STREAM_CLOSE_GRACE_MS = 500;
|
|
44
45
|
const DEFAULT_MAX_BYTES = 16 * 1024 * 1024;
|
|
46
|
+
const DEFAULT_MAX_LOG_BYTES = 16 * 1024 * 1024;
|
|
47
|
+
const MAX_CAPTURE_BYTES = 256 * 1024 * 1024;
|
|
48
|
+
const MAX_RETAINED_RECORDS = 256;
|
|
49
|
+
const MAX_RETAINED_BYTES = 1024 * 1024;
|
|
50
|
+
const MAX_REQUESTS = 4096;
|
|
45
51
|
const DEFAULT_MAX_STDERR_BYTES = 64 * 1024;
|
|
46
52
|
const MAX_REQUEST_TIMEOUT_MS = 60000;
|
|
47
|
-
const MAX_OPERATION_TIMEOUT_MS =
|
|
53
|
+
const MAX_OPERATION_TIMEOUT_MS = 24 * 60 * 60 * 1000;
|
|
48
54
|
const MAX_PROMPT_BYTES = 20000;
|
|
49
55
|
const HEADER_READ_BYTES = 64 * 1024;
|
|
50
56
|
const PHASES = new Set([
|
|
@@ -127,10 +133,16 @@ function attachTransport(child, options = {}) {
|
|
|
127
133
|
const decoder = new StringDecoder('utf8');
|
|
128
134
|
const records = [];
|
|
129
135
|
const pending = new Map();
|
|
136
|
+
const expiredRequests = new Map();
|
|
130
137
|
const eventWaiters = [];
|
|
131
138
|
let drainQueue = [];
|
|
132
139
|
let text = '';
|
|
133
140
|
let bytes = 0;
|
|
141
|
+
let recordCount = 0;
|
|
142
|
+
let retainedBytes = 0;
|
|
143
|
+
let historyTruncated = false;
|
|
144
|
+
let lateResponses = 0;
|
|
145
|
+
let lastSettled = null;
|
|
134
146
|
let stderrBytes = 0;
|
|
135
147
|
const stderrChunks = [];
|
|
136
148
|
let sequence = 0;
|
|
@@ -169,10 +181,16 @@ function attachTransport(child, options = {}) {
|
|
|
169
181
|
resolve();
|
|
170
182
|
}
|
|
171
183
|
function findRecord(predicate, fromOrdinal) {
|
|
172
|
-
for (
|
|
173
|
-
if (
|
|
174
|
-
|
|
184
|
+
for (const found of records) {
|
|
185
|
+
if (found.ordinal >= fromOrdinal &&
|
|
186
|
+
predicate(found.record, found.ordinal))
|
|
187
|
+
return found;
|
|
175
188
|
}
|
|
189
|
+
// The only awaited lifecycle event must survive noisy tool/token traffic.
|
|
190
|
+
if (lastSettled &&
|
|
191
|
+
lastSettled.ordinal >= fromOrdinal &&
|
|
192
|
+
predicate(lastSettled.record, lastSettled.ordinal))
|
|
193
|
+
return lastSettled;
|
|
176
194
|
return null;
|
|
177
195
|
}
|
|
178
196
|
function settleWaiters() {
|
|
@@ -197,6 +215,8 @@ function attachTransport(child, options = {}) {
|
|
|
197
215
|
}
|
|
198
216
|
}
|
|
199
217
|
function handleLine(line) {
|
|
218
|
+
if (fatal)
|
|
219
|
+
return;
|
|
200
220
|
const trimmed = line.endsWith('\r') ? line.slice(0, -1) : line;
|
|
201
221
|
if (!trimmed.length)
|
|
202
222
|
return;
|
|
@@ -221,10 +241,27 @@ function attachTransport(child, options = {}) {
|
|
|
221
241
|
fail('invalid', 'malformed_record', 'a stdout record is not a JSON object');
|
|
222
242
|
return;
|
|
223
243
|
}
|
|
224
|
-
|
|
244
|
+
const ordinal = recordCount++;
|
|
245
|
+
const recordBytes = Buffer.byteLength(trimmed);
|
|
246
|
+
records.push({ record, ordinal, bytes: recordBytes });
|
|
247
|
+
retainedBytes += recordBytes;
|
|
248
|
+
if (record.type === 'agent_settled')
|
|
249
|
+
lastSettled = { record: { type: 'agent_settled' }, ordinal };
|
|
250
|
+
while (records.length > MAX_RETAINED_RECORDS ||
|
|
251
|
+
retainedBytes > MAX_RETAINED_BYTES) {
|
|
252
|
+
retainedBytes -= records.shift().bytes;
|
|
253
|
+
historyTruncated = true;
|
|
254
|
+
}
|
|
225
255
|
if (record.type === 'response') {
|
|
226
256
|
const waiter = record.id !== undefined ? pending.get(record.id) : null;
|
|
227
257
|
if (!waiter) {
|
|
258
|
+
if (record.id !== undefined &&
|
|
259
|
+
expiredRequests.get(record.id) === record.command) {
|
|
260
|
+
expiredRequests.delete(record.id);
|
|
261
|
+
lateResponses++;
|
|
262
|
+
settleWaiters();
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
228
265
|
fail('invalid', record.command === 'parse'
|
|
229
266
|
? 'rpc_parse_error'
|
|
230
267
|
: 'unexpected_response_id', `a response arrived for ${record.id ?? 'no request id'}`);
|
|
@@ -299,19 +336,27 @@ function attachTransport(child, options = {}) {
|
|
|
299
336
|
child.stdin.on('drain', flushDrains);
|
|
300
337
|
child.stdout.on('data', (chunk) => {
|
|
301
338
|
bytes += chunk.length;
|
|
302
|
-
if (
|
|
303
|
-
fail('invalid', 'rpc_response_too_large', `${bytes} bytes of stdout exceeds ${maxBytes}`);
|
|
304
|
-
child.kill('SIGKILL');
|
|
339
|
+
if (fatal)
|
|
305
340
|
return;
|
|
306
|
-
}
|
|
307
341
|
text += decoder.write(chunk);
|
|
308
342
|
let index = text.indexOf('\n');
|
|
309
343
|
while (index !== -1) {
|
|
310
344
|
const line = text.slice(0, index);
|
|
311
345
|
text = text.slice(index + 1);
|
|
346
|
+
if (Buffer.byteLength(line) > maxBytes)
|
|
347
|
+
break;
|
|
312
348
|
handleLine(line);
|
|
349
|
+
if (fatal) {
|
|
350
|
+
text = '';
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
313
353
|
index = text.indexOf('\n');
|
|
314
354
|
}
|
|
355
|
+
if (index !== -1 || Buffer.byteLength(text) > maxBytes) {
|
|
356
|
+
fail('invalid', 'rpc_response_too_large', `one stdout record exceeds ${maxBytes} bytes`);
|
|
357
|
+
text = '';
|
|
358
|
+
child.kill('SIGKILL');
|
|
359
|
+
}
|
|
315
360
|
});
|
|
316
361
|
child.stderr.on('data', (chunk) => {
|
|
317
362
|
if (stderrBytes < maxStderrBytes)
|
|
@@ -346,11 +391,14 @@ function attachTransport(child, options = {}) {
|
|
|
346
391
|
return Promise.reject(fatal);
|
|
347
392
|
if (streamsClosed)
|
|
348
393
|
return Promise.reject(new PiRpcRefusal('rpc_exited_early', 'needs_input'));
|
|
394
|
+
if (sequence >= MAX_REQUESTS)
|
|
395
|
+
return Promise.reject(new PiRpcRefusal('rpc_request_limit', 'needs_input'));
|
|
349
396
|
const id = `pirpc-${nonce}-${sequence}`;
|
|
350
397
|
sequence += 1;
|
|
351
398
|
return new Promise((resolve, reject) => {
|
|
352
399
|
const timer = setTimeout(() => {
|
|
353
400
|
pending.delete(id);
|
|
401
|
+
expiredRequests.set(id, type);
|
|
354
402
|
reject(new PiRpcRefusal('rpc_response_deadline', 'needs_input', `no response to ${type} within ${timeoutMs}ms`));
|
|
355
403
|
}, timeoutMs);
|
|
356
404
|
pending.set(id, { type, resolve, reject, timer });
|
|
@@ -370,6 +418,8 @@ function attachTransport(child, options = {}) {
|
|
|
370
418
|
return Promise.reject(fatal);
|
|
371
419
|
if (streamsClosed)
|
|
372
420
|
return Promise.reject(new PiRpcRefusal('rpc_exited_early', 'needs_input'));
|
|
421
|
+
if (eventWaiters.length >= MAX_RETAINED_RECORDS)
|
|
422
|
+
return Promise.reject(new PiRpcRefusal('rpc_waiter_limit', 'needs_input'));
|
|
373
423
|
return new Promise((resolve, reject) => {
|
|
374
424
|
const timer = setTimeout(() => {
|
|
375
425
|
const index = eventWaiters.findIndex((waiter) => waiter.resolve === resolve);
|
|
@@ -441,8 +491,17 @@ function attachTransport(child, options = {}) {
|
|
|
441
491
|
};
|
|
442
492
|
}
|
|
443
493
|
return {
|
|
444
|
-
|
|
445
|
-
|
|
494
|
+
recordCount: () => recordCount,
|
|
495
|
+
capture: () => ({
|
|
496
|
+
stdout_bytes: bytes,
|
|
497
|
+
received_records: recordCount,
|
|
498
|
+
retained_records: records.length,
|
|
499
|
+
retained_bytes: retainedBytes,
|
|
500
|
+
history_truncated: historyTruncated,
|
|
501
|
+
late_responses: lateResponses,
|
|
502
|
+
stderr_bytes: stderrBytes,
|
|
503
|
+
stderr_truncated: stderrBytes > maxStderrBytes,
|
|
504
|
+
}),
|
|
446
505
|
fatal: () => fatal,
|
|
447
506
|
parentExited: () => declared(),
|
|
448
507
|
streamsDetached: () => streamsDetached,
|
|
@@ -652,6 +711,18 @@ export async function startOwnedPiRpc(options) {
|
|
|
652
711
|
stop_scope: 'owned RPC child only; no arbitrary background or descendant stop guarantee',
|
|
653
712
|
};
|
|
654
713
|
let namespaceLost = false;
|
|
714
|
+
let logBytes = 0;
|
|
715
|
+
let omittedLogRecords = 0;
|
|
716
|
+
const logCapture = () => ({
|
|
717
|
+
max_bytes: opts.maxLogBytes,
|
|
718
|
+
written_bytes: logBytes,
|
|
719
|
+
omitted_records: omittedLogRecords,
|
|
720
|
+
complete: omittedLogRecords === 0 &&
|
|
721
|
+
!namespaceLost &&
|
|
722
|
+
rpc.fatal() === null &&
|
|
723
|
+
rpc.parentExited() &&
|
|
724
|
+
!rpc.streamsDetached(),
|
|
725
|
+
});
|
|
655
726
|
const rpc = attachTransport(child, {
|
|
656
727
|
requestTimeoutMs: opts.requestTimeoutMs,
|
|
657
728
|
shutdownTimeoutMs: opts.shutdownTimeoutMs,
|
|
@@ -661,6 +732,11 @@ export async function startOwnedPiRpc(options) {
|
|
|
661
732
|
onRecord: (line) => {
|
|
662
733
|
if (namespaceLost)
|
|
663
734
|
return;
|
|
735
|
+
const lineBytes = Buffer.byteLength(line) + 1;
|
|
736
|
+
if (omittedLogRecords > 0 || logBytes + lineBytes > opts.maxLogBytes) {
|
|
737
|
+
omittedLogRecords++;
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
664
740
|
try {
|
|
665
741
|
assertNamespaceGuard(opts);
|
|
666
742
|
}
|
|
@@ -670,9 +746,11 @@ export async function startOwnedPiRpc(options) {
|
|
|
670
746
|
}
|
|
671
747
|
try {
|
|
672
748
|
fs.appendFileSync(artifacts.eventsFile, `${line}\n`);
|
|
749
|
+
logBytes += lineBytes;
|
|
673
750
|
}
|
|
674
|
-
catch {
|
|
751
|
+
catch (error) {
|
|
675
752
|
namespaceLost = true;
|
|
753
|
+
throw new PiRpcRefusal('evidence_write_failed', 'failed', errorDetail(error));
|
|
676
754
|
}
|
|
677
755
|
},
|
|
678
756
|
});
|
|
@@ -684,15 +762,18 @@ export async function startOwnedPiRpc(options) {
|
|
|
684
762
|
let lastPromptOrdinal = 0;
|
|
685
763
|
let operationError = null;
|
|
686
764
|
let finishPromise = null;
|
|
765
|
+
let operationTimer;
|
|
687
766
|
const setOperationError = (error) => {
|
|
688
767
|
operationError = operationError ?? error;
|
|
689
768
|
};
|
|
690
|
-
async function request(type, fields = {}) {
|
|
769
|
+
async function request(type, fields = {}, cleanup = false) {
|
|
691
770
|
const remaining = opts.deadlineAt - Date.now();
|
|
692
|
-
if (remaining <= 0)
|
|
771
|
+
if (!cleanup && remaining <= 0)
|
|
693
772
|
throw new PiRpcRefusal('operation_deadline', 'needs_input');
|
|
694
773
|
return rpc.request(type, fields, {
|
|
695
|
-
timeoutMs:
|
|
774
|
+
timeoutMs: cleanup
|
|
775
|
+
? opts.requestTimeoutMs
|
|
776
|
+
: Math.min(opts.requestTimeoutMs, remaining),
|
|
696
777
|
});
|
|
697
778
|
}
|
|
698
779
|
/** Bound an event wait by the remaining total operation budget as well as its own limit. */
|
|
@@ -776,13 +857,78 @@ export async function startOwnedPiRpc(options) {
|
|
|
776
857
|
}
|
|
777
858
|
}
|
|
778
859
|
}
|
|
860
|
+
async function verifyCancellationIntent(intent) {
|
|
861
|
+
if (intent === null ||
|
|
862
|
+
typeof intent !== 'object' ||
|
|
863
|
+
typeof intent.messageId !== 'string' ||
|
|
864
|
+
intent.messageId.trim() === '' ||
|
|
865
|
+
typeof intent.contentDigest !== 'string' ||
|
|
866
|
+
typeof intent.fileDigest !== 'string' ||
|
|
867
|
+
!/^sha256:[0-9a-f]{64}$/.test(intent.contentDigest) ||
|
|
868
|
+
!/^sha256:[0-9a-f]{64}$/.test(intent.fileDigest))
|
|
869
|
+
throw new PiRpcRefusal('cancel_intent_reference_invalid', 'needs_input');
|
|
870
|
+
assertNamespaceGuard(opts);
|
|
871
|
+
assertCurrentAuthority({ requireResources: false });
|
|
872
|
+
const registered = await readMessageFromTaskRoot(opts.taskRoot, intent.messageId);
|
|
873
|
+
if (!registered.ok)
|
|
874
|
+
throw new PiRpcRefusal('cancel_intent_not_registered', 'needs_input', registered.code);
|
|
875
|
+
assertNamespaceGuard(opts);
|
|
876
|
+
const { message, entry, digest } = registered.value;
|
|
877
|
+
const record = readRecord(opts.taskRoot);
|
|
878
|
+
const attempt = record
|
|
879
|
+
? findAttempt(record, opts.assignmentId, opts.attempt)
|
|
880
|
+
: null;
|
|
881
|
+
const coordinator = record?.coordinator ?? null;
|
|
882
|
+
const assignee = attempt?.assignee ?? null;
|
|
883
|
+
const sameIdentity = (left, right) => left !== null &&
|
|
884
|
+
left !== undefined &&
|
|
885
|
+
right !== null &&
|
|
886
|
+
right !== undefined &&
|
|
887
|
+
left.agent_id === right.agent_id &&
|
|
888
|
+
left.session_id === right.session_id &&
|
|
889
|
+
(left.harness ?? null) === (right.harness ?? null);
|
|
890
|
+
if (digest !== intent.fileDigest ||
|
|
891
|
+
message.message_id !== intent.messageId ||
|
|
892
|
+
message.content_digest !== intent.contentDigest ||
|
|
893
|
+
message.type !== 'CANCEL' ||
|
|
894
|
+
message.task_id !== opts.assignment.task_id ||
|
|
895
|
+
message.subtask_id !== opts.assignmentId ||
|
|
896
|
+
message.attempt !== opts.attempt ||
|
|
897
|
+
message.owner_epoch !== opts.assignment.coordinator.owner_epoch ||
|
|
898
|
+
message.owner_epoch !== protocol.ownerEpoch ||
|
|
899
|
+
entry === null ||
|
|
900
|
+
entry.message_id !== message.message_id ||
|
|
901
|
+
entry.type !== 'CANCEL' ||
|
|
902
|
+
entry.state !== 'applied' ||
|
|
903
|
+
entry.subtask_id !== message.subtask_id ||
|
|
904
|
+
entry.attempt !== message.attempt ||
|
|
905
|
+
entry.owner_epoch !== message.owner_epoch ||
|
|
906
|
+
entry.content_digest !== intent.contentDigest ||
|
|
907
|
+
!sameIdentity(entry.from, message.from) ||
|
|
908
|
+
!sameIdentity(entry.to, message.to) ||
|
|
909
|
+
record === null ||
|
|
910
|
+
record.task_id !== message.task_id ||
|
|
911
|
+
coordinator === null ||
|
|
912
|
+
coordinator.owner_epoch !== message.owner_epoch ||
|
|
913
|
+
!sameIdentity(coordinator, message.from) ||
|
|
914
|
+
!sameIdentity(coordinator, protocol.coordinator) ||
|
|
915
|
+
!sameIdentity(coordinator, opts.assignment.coordinator) ||
|
|
916
|
+
assignee === null ||
|
|
917
|
+
!sameIdentity(assignee, message.to) ||
|
|
918
|
+
!sameIdentity(assignee, opts.assignment.assignee) ||
|
|
919
|
+
!sameIdentity(assignee, protocol.assignee))
|
|
920
|
+
throw new PiRpcRefusal('cancel_intent_mismatch', 'needs_input');
|
|
921
|
+
assertNamespaceGuard(opts);
|
|
922
|
+
assertCurrentAuthority({ requireResources: false });
|
|
923
|
+
return { message, fileDigest: digest };
|
|
924
|
+
}
|
|
779
925
|
/**
|
|
780
926
|
* Read `get_state` and bind the exact native session file. The id alone is not enough: the
|
|
781
927
|
* reported file must exist, its header must carry the contracted id and cwd, and once bound it
|
|
782
928
|
* may not switch to a different path.
|
|
783
929
|
*/
|
|
784
|
-
async function assertIdentity({ requireBinding = false } = {}) {
|
|
785
|
-
const response = await request('get_state');
|
|
930
|
+
async function assertIdentity({ requireBinding = false, cleanup = false, } = {}) {
|
|
931
|
+
const response = await request('get_state', {}, cleanup);
|
|
786
932
|
const data = response.data;
|
|
787
933
|
if (!isObject(data) || typeof data.sessionId !== 'string')
|
|
788
934
|
throw new PiRpcRefusal('state_malformed');
|
|
@@ -956,7 +1102,7 @@ export async function startOwnedPiRpc(options) {
|
|
|
956
1102
|
}
|
|
957
1103
|
},
|
|
958
1104
|
/** Bounded wait for the run started by `prompt` to settle. Used by the run helper. */
|
|
959
|
-
async awaitSettled({ timeoutMs = opts.
|
|
1105
|
+
async awaitSettled({ timeoutMs = opts.operationTimeoutMs } = {}) {
|
|
960
1106
|
try {
|
|
961
1107
|
if (proof.prompt?.disposition === 'handled')
|
|
962
1108
|
return null;
|
|
@@ -975,11 +1121,25 @@ export async function startOwnedPiRpc(options) {
|
|
|
975
1121
|
* Explicit cancellation of this owned runtime. It never sends a prompt, never sends
|
|
976
1122
|
* CANCELLED and never releases claims: a caller must reconcile the stop externally.
|
|
977
1123
|
*/
|
|
978
|
-
async cancel(
|
|
1124
|
+
async cancel(options = {}) {
|
|
1125
|
+
const intent = options.intent;
|
|
979
1126
|
try {
|
|
980
1127
|
assertNamespaceGuard(opts);
|
|
1128
|
+
let verifiedIntent = intent === undefined ? null : await verifyCancellationIntent(intent);
|
|
1129
|
+
const reason = verifiedIntent &&
|
|
1130
|
+
typeof verifiedIntent.message.body.reason === 'string'
|
|
1131
|
+
? verifiedIntent.message.body.reason
|
|
1132
|
+
: (options.reason ?? 'bounded RPC cancellation request');
|
|
1133
|
+
if (verifiedIntent === null)
|
|
1134
|
+
assertCurrentAuthority({ requireResources: false });
|
|
1135
|
+
const before = await assertIdentity({
|
|
1136
|
+
requireBinding: true,
|
|
1137
|
+
cleanup: true,
|
|
1138
|
+
});
|
|
1139
|
+
if (intent !== undefined)
|
|
1140
|
+
verifiedIntent = await verifyCancellationIntent(intent);
|
|
1141
|
+
assertNamespaceGuard(opts);
|
|
981
1142
|
assertCurrentAuthority({ requireResources: false });
|
|
982
|
-
const before = await assertIdentity({ requireBinding: true });
|
|
983
1143
|
const ordinalBeforeAbort = rpc.recordCount();
|
|
984
1144
|
const entry = {
|
|
985
1145
|
at: nowIso(),
|
|
@@ -989,17 +1149,28 @@ export async function startOwnedPiRpc(options) {
|
|
|
989
1149
|
reconciliation_required: true,
|
|
990
1150
|
stop_scope: 'owned RPC child only; a native abort response is not proof that arbitrary descendants stopped',
|
|
991
1151
|
};
|
|
992
|
-
//
|
|
1152
|
+
// Record cancellation evidence before queue clearing or abort so partial failure remains inspectable.
|
|
993
1153
|
proof.cancel = entry;
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1154
|
+
if (verifiedIntent === null) {
|
|
1155
|
+
const cancel = protocolMessage({
|
|
1156
|
+
type: 'CANCEL',
|
|
1157
|
+
from: protocol.coordinator,
|
|
1158
|
+
to: protocol.assignee,
|
|
1159
|
+
owner_epoch: protocol.ownerEpoch,
|
|
1160
|
+
body: { reason },
|
|
1161
|
+
});
|
|
1162
|
+
entry.cancel_message_id = cancel.message_id;
|
|
1163
|
+
}
|
|
1164
|
+
else {
|
|
1165
|
+
entry.cancel_message_id = verifiedIntent.message.message_id;
|
|
1166
|
+
entry.cancel_intent = {
|
|
1167
|
+
content_digest: verifiedIntent.message.content_digest,
|
|
1168
|
+
file_digest: verifiedIntent.fileDigest,
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
assertNamespaceGuard(opts);
|
|
1172
|
+
assertCurrentAuthority({ requireResources: false });
|
|
1173
|
+
const clear = await request('clear_queue', {}, true);
|
|
1003
1174
|
entry.clear_queue = {
|
|
1004
1175
|
id: clear.id,
|
|
1005
1176
|
steering: Array.isArray(clear.data?.steering)
|
|
@@ -1009,7 +1180,7 @@ export async function startOwnedPiRpc(options) {
|
|
|
1009
1180
|
? clear.data.followUp
|
|
1010
1181
|
: [],
|
|
1011
1182
|
};
|
|
1012
|
-
const abort = await request('abort');
|
|
1183
|
+
const abort = await request('abort', {}, true);
|
|
1013
1184
|
entry.abort = {
|
|
1014
1185
|
id: abort.id,
|
|
1015
1186
|
success: abort.success === true,
|
|
@@ -1022,7 +1193,7 @@ export async function startOwnedPiRpc(options) {
|
|
|
1022
1193
|
// sufficient because retries/compaction/follow-ups can still follow it.
|
|
1023
1194
|
settledEvent = await rpc.waitForEvent((record) => record.type === 'agent_settled', {
|
|
1024
1195
|
fromOrdinal: ordinalBeforeAbort,
|
|
1025
|
-
timeoutMs:
|
|
1196
|
+
timeoutMs: opts.settleTimeoutMs,
|
|
1026
1197
|
});
|
|
1027
1198
|
}
|
|
1028
1199
|
catch (error) {
|
|
@@ -1033,7 +1204,10 @@ export async function startOwnedPiRpc(options) {
|
|
|
1033
1204
|
if (settledEvent)
|
|
1034
1205
|
entry.agent_settled = { ordinal: settledEvent.ordinal, at: nowIso() };
|
|
1035
1206
|
try {
|
|
1036
|
-
const after = await assertIdentity({
|
|
1207
|
+
const after = await assertIdentity({
|
|
1208
|
+
requireBinding: true,
|
|
1209
|
+
cleanup: true,
|
|
1210
|
+
});
|
|
1037
1211
|
entry.native_idle =
|
|
1038
1212
|
after.data.isStreaming === false &&
|
|
1039
1213
|
after.data.isCompacting === false &&
|
|
@@ -1069,6 +1243,7 @@ export async function startOwnedPiRpc(options) {
|
|
|
1069
1243
|
finish() {
|
|
1070
1244
|
if (finishPromise)
|
|
1071
1245
|
return finishPromise;
|
|
1246
|
+
clearTimeout(operationTimer);
|
|
1072
1247
|
finishPromise = (async () => {
|
|
1073
1248
|
let exit = null;
|
|
1074
1249
|
let shutdownError = null;
|
|
@@ -1143,6 +1318,8 @@ export async function startOwnedPiRpc(options) {
|
|
|
1143
1318
|
shutdown_timeout_ms: opts.shutdownTimeoutMs,
|
|
1144
1319
|
stream_close_grace_ms: opts.streamCloseGraceMs,
|
|
1145
1320
|
max_bytes: opts.maxBytes,
|
|
1321
|
+
max_log_bytes: opts.maxLogBytes,
|
|
1322
|
+
cancel_settle_timeout_ms: opts.settleTimeoutMs,
|
|
1146
1323
|
model_override: null,
|
|
1147
1324
|
effort_override: null,
|
|
1148
1325
|
},
|
|
@@ -1164,6 +1341,7 @@ export async function startOwnedPiRpc(options) {
|
|
|
1164
1341
|
},
|
|
1165
1342
|
planned_outcome: outcome,
|
|
1166
1343
|
rpc_child_pid: child.pid ?? null,
|
|
1344
|
+
rpc_capture: { ...rpc.capture(), log: logCapture() },
|
|
1167
1345
|
};
|
|
1168
1346
|
let namespaceError = null;
|
|
1169
1347
|
const checkNamespace = () => {
|
|
@@ -1212,7 +1390,7 @@ export async function startOwnedPiRpc(options) {
|
|
|
1212
1390
|
evidenceError === null &&
|
|
1213
1391
|
checkNamespace()) {
|
|
1214
1392
|
try {
|
|
1215
|
-
fs.writeFileSync(artifacts.proofFile, `${JSON.stringify({ ...proof, finished_at: finishedAt, exit }, null, 2)}\n`, { flag: 'wx', mode: 0o600 });
|
|
1393
|
+
fs.writeFileSync(artifacts.proofFile, `${JSON.stringify({ ...proof, finished_at: finishedAt, exit, rpc_capture: { ...rpc.capture(), log: logCapture() } }, null, 2)}\n`, { flag: 'wx', mode: 0o600 });
|
|
1216
1394
|
}
|
|
1217
1395
|
catch (error) {
|
|
1218
1396
|
evidenceError = errorDetail(error) ?? 'proof_write_failed';
|
|
@@ -1345,6 +1523,8 @@ export async function startOwnedPiRpc(options) {
|
|
|
1345
1523
|
evidence: {
|
|
1346
1524
|
evidence_dir: opts.evidenceDir,
|
|
1347
1525
|
events_file: artifacts.eventsFile,
|
|
1526
|
+
events_complete: logCapture().complete,
|
|
1527
|
+
events_omitted_records: omittedLogRecords,
|
|
1348
1528
|
execution_file: namespaceError === null && !evidenceError
|
|
1349
1529
|
? artifacts.executionFile
|
|
1350
1530
|
: null,
|
|
@@ -1368,6 +1548,12 @@ export async function startOwnedPiRpc(options) {
|
|
|
1368
1548
|
return finishPromise;
|
|
1369
1549
|
},
|
|
1370
1550
|
};
|
|
1551
|
+
operationTimer = setTimeout(() => {
|
|
1552
|
+
setOperationError(new PiRpcRefusal('operation_deadline', 'needs_input'));
|
|
1553
|
+
void session.finish().catch(() => { });
|
|
1554
|
+
}, Math.max(1, opts.deadlineAt - Date.now()));
|
|
1555
|
+
if (typeof operationTimer.unref === 'function')
|
|
1556
|
+
operationTimer.unref();
|
|
1371
1557
|
// Accepted alias for callers of the earlier revision; like `finish` it takes no arguments,
|
|
1372
1558
|
// so it cannot override the authoritative outcome.
|
|
1373
1559
|
// Bind the contracted identity and native session header before returning a live handle.
|
|
@@ -1375,6 +1561,7 @@ export async function startOwnedPiRpc(options) {
|
|
|
1375
1561
|
await assertIdentity({ requireBinding: false });
|
|
1376
1562
|
}
|
|
1377
1563
|
catch (error) {
|
|
1564
|
+
setOperationError(error);
|
|
1378
1565
|
const failure = await session.finish();
|
|
1379
1566
|
return {
|
|
1380
1567
|
ok: false,
|
|
@@ -1516,11 +1703,16 @@ function normalizeOwnedOptions(options) {
|
|
|
1516
1703
|
const streamCloseGraceMs = boundedTimeout(options.streamCloseGraceMs, DEFAULT_STREAM_CLOSE_GRACE_MS, MAX_REQUEST_TIMEOUT_MS, 'stream_close_grace_out_of_range');
|
|
1517
1704
|
const maxBytes = options.maxBytes === undefined
|
|
1518
1705
|
? DEFAULT_MAX_BYTES
|
|
1519
|
-
: Number.isSafeInteger(options.maxBytes) &&
|
|
1706
|
+
: Number.isSafeInteger(options.maxBytes) &&
|
|
1707
|
+
options.maxBytes > 0 &&
|
|
1708
|
+
options.maxBytes <= MAX_CAPTURE_BYTES
|
|
1520
1709
|
? options.maxBytes
|
|
1521
1710
|
: (() => {
|
|
1522
1711
|
throw new PiRpcRefusal('max_bytes_out_of_range');
|
|
1523
1712
|
})();
|
|
1713
|
+
const maxLogBytes = options.maxLogBytes === undefined
|
|
1714
|
+
? DEFAULT_MAX_LOG_BYTES
|
|
1715
|
+
: boundedTimeout(options.maxLogBytes, DEFAULT_MAX_LOG_BYTES, MAX_CAPTURE_BYTES, 'max_log_bytes_out_of_range');
|
|
1524
1716
|
const maxAgeMinutes = options.maxAgeMinutes === undefined ? 30 : options.maxAgeMinutes;
|
|
1525
1717
|
if (!Number.isFinite(maxAgeMinutes) || maxAgeMinutes < 0)
|
|
1526
1718
|
throw new PiRpcRefusal('invalid_max_age');
|
|
@@ -1554,6 +1746,7 @@ function normalizeOwnedOptions(options) {
|
|
|
1554
1746
|
signalGraceMs,
|
|
1555
1747
|
streamCloseGraceMs,
|
|
1556
1748
|
maxBytes,
|
|
1749
|
+
maxLogBytes,
|
|
1557
1750
|
maxAgeMinutes,
|
|
1558
1751
|
namespaceGuard: options.namespaceGuard,
|
|
1559
1752
|
deadlineAt: Date.now() + operationTimeoutMs,
|