@corca-org/ceal-host-win32-x64 1.0.7 → 1.0.9
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/bin/ceal-host.exe +0 -0
- package/libexec/ceal-host/claude-hook.mjs +147 -45
- package/libexec/ceal-host/claude-invocation-authentication.mjs +99 -124
- package/libexec/ceal-host/claude-producer.mjs +74 -23
- package/libexec/ceal-host/codex-hook.mjs +146 -46
- package/libexec/ceal-host/codex-invocation-authentication.mjs +132 -128
- package/libexec/ceal-host/codex-producer.mjs +134 -31
- package/libexec/ceal-host/control.mjs +154 -38
- package/libexec/ceal-host/relay.mjs +236 -55
- package/package.json +1 -1
- package/share/ceal-host/bundle-manifest.json +12 -12
- package/share/ceal-host/bundle-manifest.sigstore.json +1 -1
|
@@ -2108,11 +2108,28 @@ var client_wire_contract_default = {
|
|
|
2108
2108
|
],
|
|
2109
2109
|
bare_document_fields: [
|
|
2110
2110
|
"invocation",
|
|
2111
|
-
"
|
|
2111
|
+
"required_action_sequence",
|
|
2112
|
+
"entrypoints",
|
|
2112
2113
|
"common_concepts",
|
|
2113
2114
|
"operations",
|
|
2114
2115
|
"catalog_revision"
|
|
2115
2116
|
],
|
|
2117
|
+
prompt_field: "prompt",
|
|
2118
|
+
prompt_schema_version: "ceal.prompt.v1",
|
|
2119
|
+
focused_prompt_document_fields: [
|
|
2120
|
+
"catalog_revision",
|
|
2121
|
+
"prompt"
|
|
2122
|
+
],
|
|
2123
|
+
focused_prompt_continuation_document_fields: [
|
|
2124
|
+
"catalog_revision",
|
|
2125
|
+
"remaining_work",
|
|
2126
|
+
"prompt"
|
|
2127
|
+
],
|
|
2128
|
+
discovery_command: "discovery",
|
|
2129
|
+
discovery_manifest_schema_version: "ceal.discovery_manifest.v1",
|
|
2130
|
+
discovery_manifest_document_fields: [
|
|
2131
|
+
"discovery_manifest"
|
|
2132
|
+
],
|
|
2116
2133
|
exit_code_max: 125,
|
|
2117
2134
|
bare_document_max_bytes: 65536,
|
|
2118
2135
|
complete_max_bytes: 66019,
|
|
@@ -2139,8 +2156,15 @@ var CEAL_VERIFIED_ARTIFACT_MAX_BYTES = artifact.max_bytes;
|
|
|
2139
2156
|
var CEAL_VERIFIED_ARTIFACT_DESCRIPTOR_MAX_BYTES = artifact.envelope_max_bytes;
|
|
2140
2157
|
var CEAL_COMMAND_REQUEST_SCHEMA_VERSION = request.schema_version;
|
|
2141
2158
|
var CEAL_COMMAND_REQUEST_MAX_BYTES = request.absolute_transport_max_bytes;
|
|
2142
|
-
var CEAL_COMMAND_RESPONSE_BARE_DOCUMENT_FIELDS = response.bare_document_fields;
|
|
2143
2159
|
var CEAL_COMMAND_RESPONSE_BARE_DOCUMENT_MAX_BYTES = response.bare_document_max_bytes;
|
|
2160
|
+
var CEAL_COMMAND_RESPONSE_PROMPT_FIELD = response.prompt_field;
|
|
2161
|
+
var CEAL_COMMAND_RESPONSE_PROMPT_SCHEMA_VERSION = response.prompt_schema_version;
|
|
2162
|
+
var CEAL_COMMAND_RESPONSE_PROMPT_DOCUMENT_FIELDS = Object.freeze([...response.bare_document_fields, response.prompt_field]);
|
|
2163
|
+
var CEAL_COMMAND_RESPONSE_FOCUSED_PROMPT_DOCUMENT_FIELDS = Object.freeze([...response.focused_prompt_document_fields]);
|
|
2164
|
+
var CEAL_COMMAND_RESPONSE_FOCUSED_PROMPT_CONTINUATION_DOCUMENT_FIELDS = Object.freeze([...response.focused_prompt_continuation_document_fields]);
|
|
2165
|
+
var CEAL_COMMAND_RESPONSE_DISCOVERY_COMMAND = response.discovery_command;
|
|
2166
|
+
var CEAL_COMMAND_RESPONSE_DISCOVERY_MANIFEST_SCHEMA_VERSION = response.discovery_manifest_schema_version;
|
|
2167
|
+
var CEAL_COMMAND_RESPONSE_DISCOVERY_MANIFEST_DOCUMENT_FIELDS = Object.freeze([...response.discovery_manifest_document_fields]);
|
|
2144
2168
|
var CEAL_COMMAND_RESPONSE_MAX_BYTES = response.absolute_transport_max_bytes;
|
|
2145
2169
|
|
|
2146
2170
|
// packages/ceal-client-protocol/src/vocabulary.ts
|
|
@@ -2176,7 +2200,7 @@ var CEAL_OPERATION_RECOVERY_KINDS = vocabulary(["none", "reconcile", "compensate
|
|
|
2176
2200
|
var CEAL_OPERATION_RECOVERY_STATUSES = vocabulary(["not_started", "active", "completed"]);
|
|
2177
2201
|
var CEAL_OPERATION_PROVIDER_READBACK_AVAILABILITY = vocabulary(["not_started", "not_applicable", "not_available", "pending", "available"]);
|
|
2178
2202
|
var CEAL_OPERATION_OFFERED_HANDOFF_STATES = vocabulary(["accepted", "rejected", "unknown"]);
|
|
2179
|
-
var CEAL_OPERATION_RECEIPT_AUTHORITY_KEYS = Object.freeze(["instance_ref", "
|
|
2203
|
+
var CEAL_OPERATION_RECEIPT_AUTHORITY_KEYS = Object.freeze(["instance_ref", "access_group_ref", "principal_ref", "execution_subject_ref", "authority_revision_ref"]);
|
|
2180
2204
|
var CEAL_OPERATION_APPROVAL_DISPOSITIONS = vocabulary([
|
|
2181
2205
|
"approval_not_required_by_policy",
|
|
2182
2206
|
"interactive_pending",
|
|
@@ -2191,6 +2215,8 @@ var CEAL_CAPABILITY_READINESS_VALUES = vocabulary(["ready", "degraded", "unavail
|
|
|
2191
2215
|
var CEAL_TARGET_REQUIREMENTS = vocabulary(["required", "optional", "none"]);
|
|
2192
2216
|
var CEAL_AUDIT_OUTCOMES = vocabulary(["succeeded", "denied", "failed"]);
|
|
2193
2217
|
var CEAL_GATEWAY_PROVIDER_STEP_OUTCOMES = vocabulary(["completed", "rejected", "throttled", "failed"]);
|
|
2218
|
+
var CEAL_GATEWAY_READ_REUSE_DISPOSITIONS = vocabulary(["response_cache_hit", "corpus_hit", "corpus_hit_after_revalidation", "corpus_partial_provider_supplement", "provider_direct", "provider_continuation", "reuse_unavailable"]);
|
|
2219
|
+
var CEAL_GATEWAY_READ_REUSE_UNAVAILABLE_REASONS = vocabulary(["not_reported", "storage_unavailable", "coverage_incomplete", "freshness_refresh_required", "not_reusable", "bypassed"]);
|
|
2194
2220
|
var CEAL_POLICY_DECISIONS = vocabulary(["allowed", "denied", "not_evaluated"]);
|
|
2195
2221
|
var CEAL_CONNECTOR_ROUTE_PHASES = vocabulary(["scope_observation", "target_selection", "route_resolution"]);
|
|
2196
2222
|
var CEAL_CONNECTOR_ROUTE_CAUSES = vocabulary(["provider_throttled", "provider_unavailable", "binding_invalid", "scope_limit_exceeded"]);
|
|
@@ -2463,8 +2489,10 @@ function requireIsoTimestamp(value, message) {
|
|
|
2463
2489
|
var JSON_DESCRIPTION_CONTROL_CHARACTER = new RegExp("\\p{Cc}", "u");
|
|
2464
2490
|
|
|
2465
2491
|
// packages/ceal-client-protocol/src/operation-contract-validation.ts
|
|
2466
|
-
var CEAL_OPERATION_AUTHORITY_POLICY_KEYS = Object.freeze(["
|
|
2492
|
+
var CEAL_OPERATION_AUTHORITY_POLICY_KEYS = Object.freeze(["access_group", "instance_binding", "target", "admission_recheck"]);
|
|
2467
2493
|
var MAX_OPERATION_INPUT_RESOLVER_BINDINGS = 96;
|
|
2494
|
+
var CEAL_OPERATION_DESCRIPTOR_REQUIRED_ENVELOPE_KEYS = Object.freeze(["schema_version", "id", "input_contract", "result_contract", "policy"]);
|
|
2495
|
+
var CEAL_OPERATION_DESCRIPTOR_OPTIONAL_ENVELOPE_KEYS = Object.freeze(["input_resolution", "summary"]);
|
|
2468
2496
|
var CEAL_OPERATION_RESULT_KEYS = vocabulary(["ok", "operation_id", "operation_receipt", "schema_version", "value"]);
|
|
2469
2497
|
var CEAL_OPERATION_COMPACT_RESULT_KEYS = vocabulary(["ok", "operation_evidence", "operation_id", "schema_version", "value"]);
|
|
2470
2498
|
|
|
@@ -2538,6 +2566,7 @@ var CEAL_SCHEMA_LITERALS = [
|
|
|
2538
2566
|
"ceal.operation_descriptor.v1",
|
|
2539
2567
|
"ceal.operation_error.v1",
|
|
2540
2568
|
"ceal.operation_failure.v1",
|
|
2569
|
+
"ceal.operation_failure.compact.v1",
|
|
2541
2570
|
"ceal.operation_receipt.v1",
|
|
2542
2571
|
"ceal.operation_result.v1",
|
|
2543
2572
|
"ceal.operation_result.compact.v1",
|
|
@@ -2563,17 +2592,16 @@ var CEAL_BOUNDED_SERIES_CATALOG = Object.freeze({
|
|
|
2563
2592
|
engagement_signal: (root) => join(root, "runtime-state", "slack-feedback.jsonl"),
|
|
2564
2593
|
runtime_error: (root) => join(root, "runtime-state", "runtime-errors.jsonl"),
|
|
2565
2594
|
turn_bridge_request: (root) => join(root, ".ceal", "turn-bridge", "requests.jsonl"),
|
|
2566
|
-
channel_log: (root) => join(root, "log.jsonl"),
|
|
2567
2595
|
thread_run_events: (root) => join(root, "run-events.jsonl"),
|
|
2568
2596
|
bounded_store_sidecar: (root) => `${root}.jsonl`,
|
|
2569
2597
|
gateway_audit_archive: (root) => `${root}.jsonl`,
|
|
2570
2598
|
gateway_capability_audit: (root) => join(root, "capability-audit.jsonl"),
|
|
2571
2599
|
gateway_retrieval_waste_partition: (root) => `${root}.jsonl`,
|
|
2572
2600
|
gateway_access_policy_publication: (root) => join(root, "access-policy-publications.jsonl"),
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2601
|
+
gateway_access_group_connector_control_audit: (root) => `${root}.audit.jsonl`,
|
|
2602
|
+
gateway_access_group_connector_scope_audit: (root) => join(root, "profile-connector-scope-audit.jsonl"),
|
|
2603
|
+
gateway_access_group_connector_activity_scope_audit: (root) => join(root, "profile-connector-activity-scope-audit.jsonl"),
|
|
2604
|
+
gateway_access_group_connector_readiness_audit: (root) => join(root, "profile-connector-readiness.audit.jsonl"),
|
|
2577
2605
|
gateway_organization_audit_ledger: (root) => join(root, "organization-ledger.jsonl"),
|
|
2578
2606
|
gateway_personal_client_audit: (root) => join(root, "audit.jsonl"),
|
|
2579
2607
|
gateway_personal_client_access_audit: (root) => join(root, "access-audit.jsonl"),
|
|
@@ -2624,12 +2652,6 @@ var CEAL_AGENT_SESSION_COMMIT_KEYS = vocabulary(["attempt_ref", "expected_sessio
|
|
|
2624
2652
|
// packages/ceal-client-protocol/src/operation-next-actions.ts
|
|
2625
2653
|
var CALLER_RECOVERABLE_NEXT_ACTION_VALUES = [
|
|
2626
2654
|
"select_did_you_mean",
|
|
2627
|
-
// The graph, not the argument list, is what the caller must change: the
|
|
2628
|
-
// resolver that owns this input has no producing node upstream, and no edit
|
|
2629
|
-
// to the invocation can conjure one. `resolver_dependency_absent` carried no
|
|
2630
|
-
// remedy at all rather than borrow a word that means something else, so the
|
|
2631
|
-
// scorer read a fully-diagnosed, caller-fixable refusal as a failed run.
|
|
2632
|
-
"request.graph.append",
|
|
2633
2655
|
"choose_new_output_path",
|
|
2634
2656
|
"choose_new_idempotency_key",
|
|
2635
2657
|
"restart_search",
|
|
@@ -2681,8 +2703,6 @@ var NON_REMEDY_NEXT_ACTION_VALUES = [
|
|
|
2681
2703
|
"reconcile_occurrence",
|
|
2682
2704
|
"reduce_request_size",
|
|
2683
2705
|
"repair_or_adopt_session",
|
|
2684
|
-
"request.effect_approval.read",
|
|
2685
|
-
"request.run",
|
|
2686
2706
|
"retry",
|
|
2687
2707
|
// The owner -- a correlation hook, an approval hook -- is not serving right
|
|
2688
2708
|
// now. The caller changes nothing and the same call succeeds once the owner
|
|
@@ -2779,12 +2799,12 @@ var CEAL_REQUEST_JSON_SCHEMA = {
|
|
|
2779
2799
|
additionalProperties: false,
|
|
2780
2800
|
properties: {
|
|
2781
2801
|
instance_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
|
|
2782
|
-
|
|
2802
|
+
access_group_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
|
|
2783
2803
|
principal_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
|
|
2784
2804
|
execution_subject_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
|
|
2785
2805
|
authority_revision_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source }
|
|
2786
2806
|
},
|
|
2787
|
-
required: ["instance_ref", "
|
|
2807
|
+
required: ["instance_ref", "access_group_ref", "principal_ref", "execution_subject_ref", "authority_revision_ref"]
|
|
2788
2808
|
},
|
|
2789
2809
|
prompt_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
|
|
2790
2810
|
host_session_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
|
|
@@ -2917,7 +2937,7 @@ var CEAL_HOST_OBSERVATION_KINDS = vocabulary(["prompt", "session", "turn", "mode
|
|
|
2917
2937
|
function isCealHostPromptObservationValue(value) {
|
|
2918
2938
|
return isOperationRecord(value) && Object.keys(value).length === 1 && isCealDigest(value.body_sha256);
|
|
2919
2939
|
}
|
|
2920
|
-
var HOST_RESERVED_KEY = /^(?:admission|approval|audit|authorization|cancellation|capability|effect|grant|occurrence|operation|policy|profile|provider_readback|receipt|reconciliation|replay|target|write_request)(?:_|$)/iu;
|
|
2940
|
+
var HOST_RESERVED_KEY = /^(?:access_group|admission|approval|audit|authorization|cancellation|capability|effect|grant|occurrence|operation|policy|profile|provider_readback|receipt|reconciliation|replay|target|write_request)(?:_|$)/iu;
|
|
2921
2941
|
function assertHostObservationValue(value, kind) {
|
|
2922
2942
|
if (value === void 0) invalid("Ceal Host observation value is invalid.");
|
|
2923
2943
|
if (kind === "prompt" && !isCealHostPromptObservationValue(value)) invalid("Ceal Host prompt observation must contain only its body digest.");
|
|
@@ -2937,6 +2957,14 @@ function inspectHostKeys(value) {
|
|
|
2937
2957
|
}
|
|
2938
2958
|
}
|
|
2939
2959
|
|
|
2960
|
+
// packages/ceal-client-protocol/src/host-prompt-ref.ts
|
|
2961
|
+
var CEAL_HOST_PROMPT_DIGEST_PATTERN = "^[a-f0-9]{64}$";
|
|
2962
|
+
var PROMPT_DIGEST = new RegExp(CEAL_HOST_PROMPT_DIGEST_PATTERN, "u");
|
|
2963
|
+
function hostProducerPromptRef(promptSha256) {
|
|
2964
|
+
if (!PROMPT_DIGEST.test(promptSha256)) throw new TypeError("Canonical Host prompt digest is invalid.");
|
|
2965
|
+
return `ceal-host-prompt:${promptSha256}`;
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2940
2968
|
// packages/ceal-client-protocol/src/request-effect-approval.ts
|
|
2941
2969
|
var CEAL_EFFECT_APPROVAL_DECISION_CHECK_PHRASES = Object.freeze([
|
|
2942
2970
|
"observed after this approval was raised and before it expires",
|
|
@@ -2952,6 +2980,12 @@ var OWNER_WRITE_STATES = Object.freeze(["attempt_started", "provider_acknowledge
|
|
|
2952
2980
|
var OWNER_EFFECT_STATES = Object.freeze(["none", "applied", "failed", "unknown", "reconciled"]);
|
|
2953
2981
|
var OWNER_RECEIPT_STATES = Object.freeze(["pending", "available", "failed", "unknown", "reconciled"]);
|
|
2954
2982
|
|
|
2983
|
+
// packages/ceal-client-protocol/src/thread-excerpt.ts
|
|
2984
|
+
var CEAL_THREAD_RECENT_WINDOW = 6;
|
|
2985
|
+
var CEAL_THREAD_LAST_APP_MESSAGES_WINDOW = 3;
|
|
2986
|
+
var CEAL_THREAD_OLDER_SUMMARY_WINDOW = 4;
|
|
2987
|
+
var CEAL_FED_THREAD_MESSAGE_LIMIT = CEAL_THREAD_RECENT_WINDOW + CEAL_THREAD_OLDER_SUMMARY_WINDOW + CEAL_THREAD_LAST_APP_MESSAGES_WINDOW;
|
|
2988
|
+
|
|
2955
2989
|
// packages/ceal-client-protocol/src/request-graph-readiness.ts
|
|
2956
2990
|
var REQUEST_GRAPH_PRODUCER_TO_APPEND_SCHEMA = {
|
|
2957
2991
|
type: "object",
|
|
@@ -3031,6 +3065,14 @@ var CEAL_REQUEST_GRAPH_NODE_PREPARE_READINESS_JSON_SCHEMA = {
|
|
|
3031
3065
|
var REQUIRED_FIELDS = Object.freeze(["schema_version", "operation_id", "local_path", "content_json_pointer", "size_bytes", "sha256", "read_argv"]);
|
|
3032
3066
|
var FIELDS = /* @__PURE__ */ new Set([...REQUIRED_FIELDS, "local_result_root", "model_disclosure"]);
|
|
3033
3067
|
|
|
3068
|
+
// packages/ceal-client-protocol/src/session-start-affordance.ts
|
|
3069
|
+
var CEAL_SESSION_ENTRY_INVOCATION = "ceal";
|
|
3070
|
+
var CEAL_LINK_RESOURCE_PRECEDENCE = `When the user asks to use Ceal or provides a link to information that may be available through installed organizational capabilities, run bare \`${CEAL_SESSION_ENTRY_INVOCATION}\`. The Host supplies the current user prompt without exposing it to the client command, and the Gateway returns the applicable entry in that one response. Treat a supplied link as a candidate Ceal resource rather than a public web-search target. Reach for a generic web fetch or web search only when the Gateway offered nothing.`;
|
|
3071
|
+
var HOST_HOOK_TIMEOUT_SECONDS = 1;
|
|
3072
|
+
|
|
3073
|
+
// packages/ceal-client-protocol/src/discovery-manifest.ts
|
|
3074
|
+
var CEAL_DISCOVERY_MANIFEST_CONNECTOR_KINDS = vocabulary(["github", "google-workspace", "notion", "slack"]);
|
|
3075
|
+
|
|
3034
3076
|
// packages/ceal-client-protocol/src/conversation-contracts.ts
|
|
3035
3077
|
var CEAL_APPROVAL_POLICY_KINDS = vocabulary(["requester_only", "named_users", "role_based"]);
|
|
3036
3078
|
var CEAL_APPROVAL_TARGET_KINDS = vocabulary([
|
|
@@ -3247,7 +3289,7 @@ var CEAL_PRESENTATION_INTENTS = vocabulary(["progress", ...CEAL_FINAL_PRESENTATI
|
|
|
3247
3289
|
|
|
3248
3290
|
// packages/ceal-client-protocol/src/personal-client-vocabulary.ts
|
|
3249
3291
|
var CEAL_PERSONAL_CLIENT_BINDING_KEYS = vocabulary([
|
|
3250
|
-
"
|
|
3292
|
+
"access_group_ref",
|
|
3251
3293
|
"membership_ref",
|
|
3252
3294
|
"registration_ref",
|
|
3253
3295
|
"client_ref",
|
|
@@ -3443,7 +3485,6 @@ var HOST_PRODUCER_FRAME_SCHEMA = "ceal.host_producer_frame.v1";
|
|
|
3443
3485
|
var HOST_PRODUCER_MAX_JSON_BYTES = 262144;
|
|
3444
3486
|
var HOST_PRODUCER_FRAME_LENGTH_BYTES = Uint32Array.BYTES_PER_ELEMENT;
|
|
3445
3487
|
var SAFE_REF3 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
|
|
3446
|
-
var DIGEST2 = /^[a-f0-9]{64}$/u;
|
|
3447
3488
|
var PRODUCERS = /* @__PURE__ */ new Set(["codex", "claude"]);
|
|
3448
3489
|
var HOST_PRODUCER_FRAME_KINDS = ["session_started", "turn_started", "user_input", "turn_terminal", "producer_status"];
|
|
3449
3490
|
var FRAME_KINDS = new Set(HOST_PRODUCER_FRAME_KINDS);
|
|
@@ -3484,10 +3525,6 @@ function decodeHostProducerFrame(input) {
|
|
|
3484
3525
|
validateFrame(value);
|
|
3485
3526
|
return value;
|
|
3486
3527
|
}
|
|
3487
|
-
function hostProducerPromptRef(promptSha256) {
|
|
3488
|
-
if (!DIGEST2.test(promptSha256)) throw new TypeError("Canonical Host prompt digest is invalid.");
|
|
3489
|
-
return `ceal-host-prompt:${promptSha256}`;
|
|
3490
|
-
}
|
|
3491
3528
|
function opaqueHostSourceRef(value) {
|
|
3492
3529
|
return typeof value === "string" && SAFE_REF3.test(value) && !value.startsWith("ceal-host-source:");
|
|
3493
3530
|
}
|
|
@@ -3671,12 +3708,19 @@ var RELAY_QUARANTINE_MAX_BYTES = 16 * 1024 * 1024;
|
|
|
3671
3708
|
|
|
3672
3709
|
// host/relay/src/relay-admission-store.ts
|
|
3673
3710
|
var DEFAULT_LIMITS = { global_count: 8192, global_bytes: 64 * 1024 * 1024, producer_count: 4096, producer_bytes: 32 * 1024 * 1024 };
|
|
3711
|
+
var RETRY_SECONDS = [1, 2, 4, 8, 16, 32, 60];
|
|
3712
|
+
var MAX_RETRYABLE_ATTEMPTS = RETRY_SECONDS.length + 10;
|
|
3674
3713
|
|
|
3675
3714
|
// host/relay/src/relay-request-binding-store.ts
|
|
3676
3715
|
var MAX_STATE_BYTES = 8 * 1024 * 1024;
|
|
3677
3716
|
|
|
3678
3717
|
// host/relay/src/relay-ipc.ts
|
|
3679
3718
|
import { createConnection, createServer } from "node:net";
|
|
3719
|
+
|
|
3720
|
+
// host/relay/src/current-prompt-custody.ts
|
|
3721
|
+
var HOST_CURRENT_PROMPT_MAX_BYTES = 256 * 1024;
|
|
3722
|
+
|
|
3723
|
+
// host/relay/src/relay-ipc.ts
|
|
3680
3724
|
var HOST_RELAY_REQUEST_BINDING_KEYS = Object.freeze([
|
|
3681
3725
|
"schema_version",
|
|
3682
3726
|
"producer_id",
|
|
@@ -3693,6 +3737,8 @@ var HOST_RELAY_REQUEST_BINDING_KEYS = Object.freeze([
|
|
|
3693
3737
|
"host_input_ref"
|
|
3694
3738
|
]);
|
|
3695
3739
|
var HOST_RELAY_IPC_RESPONSE_SCHEMA = "ceal.host_relay_admission.v1";
|
|
3740
|
+
var HOST_RELAY_CURRENT_PROMPT_REGISTER_SCHEMA = "ceal.host_relay_current_prompt_register.v1";
|
|
3741
|
+
var HOST_RELAY_CURRENT_PROMPT_RESULT_SCHEMA = "ceal.host_relay_current_prompt_result.v1";
|
|
3696
3742
|
var HOST_RELAY_IPC_LENGTH_BYTES = Uint32Array.BYTES_PER_ELEMENT;
|
|
3697
3743
|
var HOST_RELAY_ADMISSION_RESPONSE_MAX_BYTES = 4096;
|
|
3698
3744
|
var HostRelayIpcError = class extends Error {
|
|
@@ -3715,22 +3761,42 @@ var HostRelayIpcAdmissionPort = class {
|
|
|
3715
3761
|
return { code: response2.code, admitted_through_sequence: response2.admitted_through_sequence, delivered_through_sequence: response2.delivered_through_sequence };
|
|
3716
3762
|
}
|
|
3717
3763
|
};
|
|
3764
|
+
var HostRelayCurrentPromptPort = class {
|
|
3765
|
+
endpoint;
|
|
3766
|
+
timeout_ms;
|
|
3767
|
+
constructor(endpoint, timeoutMs = 5e3) {
|
|
3768
|
+
this.endpoint = endpoint;
|
|
3769
|
+
this.timeout_ms = timeoutMs;
|
|
3770
|
+
}
|
|
3771
|
+
async register(input) {
|
|
3772
|
+
const request2 = { schema_version: HOST_RELAY_CURRENT_PROMPT_REGISTER_SCHEMA, ...input };
|
|
3773
|
+
const response2 = await exchange(this.endpoint, encodeLengthPrefixed(request2), this.timeout_ms, decodeCurrentPromptResponseBuffer);
|
|
3774
|
+
if (response2.status !== "registered") throw new HostRelayIpcError("relay_unavailable", response2.status);
|
|
3775
|
+
}
|
|
3776
|
+
};
|
|
3718
3777
|
function submitHostProducerFrame(endpoint, frame, timeoutMs = 5e3) {
|
|
3719
3778
|
return exchange(endpoint, encodeHostProducerFrame(frame), timeoutMs, decodeResponseBuffer);
|
|
3720
3779
|
}
|
|
3721
|
-
function exchange(endpoint, encoded, timeoutMs, decode) {
|
|
3780
|
+
function exchange(endpoint, encoded, timeoutMs, decode, signal) {
|
|
3722
3781
|
return new Promise((resolve, reject2) => {
|
|
3723
3782
|
const socket = createConnection(endpoint);
|
|
3724
3783
|
let buffer = Buffer.alloc(0);
|
|
3725
3784
|
let settled = false;
|
|
3785
|
+
const aborted = () => finish(new HostRelayIpcError("relay_unavailable", "Host Relay IPC was cancelled."));
|
|
3726
3786
|
const finish = (error, response2) => {
|
|
3727
3787
|
if (settled) return;
|
|
3728
3788
|
settled = true;
|
|
3789
|
+
signal?.removeEventListener("abort", aborted);
|
|
3729
3790
|
socket.destroy();
|
|
3730
3791
|
if (error !== null) reject2(error);
|
|
3731
3792
|
else if (response2 !== void 0) resolve(response2);
|
|
3732
3793
|
};
|
|
3733
|
-
socket.setTimeout(timeoutMs, () => finish(new HostRelayIpcError("relay_unavailable", "Host Relay IPC timed out.")));
|
|
3794
|
+
if (timeoutMs !== void 0) socket.setTimeout(timeoutMs, () => finish(new HostRelayIpcError("relay_unavailable", "Host Relay IPC timed out.")));
|
|
3795
|
+
if (signal?.aborted === true) {
|
|
3796
|
+
aborted();
|
|
3797
|
+
return;
|
|
3798
|
+
}
|
|
3799
|
+
signal?.addEventListener("abort", aborted, { once: true });
|
|
3734
3800
|
socket.once("error", () => finish(new HostRelayIpcError("relay_unavailable", "Host Relay IPC is unavailable.")));
|
|
3735
3801
|
socket.once("connect", () => socket.write(encoded));
|
|
3736
3802
|
socket.on("data", (chunk) => {
|
|
@@ -3783,6 +3849,34 @@ function decodeResponseBuffer(buffer) {
|
|
|
3783
3849
|
if (buffer.length !== length + HOST_RELAY_IPC_LENGTH_BYTES) throw new HostRelayIpcError("relay_unavailable", `Host Relay IPC returned trailing bytes: ${refusalFacts([{ name: "declared_bytes", value: length, expected: `the received message length minus ${HOST_RELAY_IPC_LENGTH_BYTES}` }, { name: "received_bytes", value: buffer.byteLength, expected: `exactly ${length + HOST_RELAY_IPC_LENGTH_BYTES}` }])}.`);
|
|
3784
3850
|
return decodeHostRelayIpcResponse(buffer);
|
|
3785
3851
|
}
|
|
3852
|
+
function decodeCurrentPromptResponseBuffer(buffer) {
|
|
3853
|
+
const value = decodeLengthPrefixedJson(buffer, HOST_RELAY_ADMISSION_RESPONSE_MAX_BYTES);
|
|
3854
|
+
if (value === null) return null;
|
|
3855
|
+
if (!record2(value) || !exactKeys2(value, ["schema_version", "status"]) || value.schema_version !== HOST_RELAY_CURRENT_PROMPT_RESULT_SCHEMA || value.status !== "registered" && value.status !== "current_prompt_unavailable") throw new HostRelayIpcError("relay_unavailable");
|
|
3856
|
+
return { schema_version: HOST_RELAY_CURRENT_PROMPT_RESULT_SCHEMA, status: value.status };
|
|
3857
|
+
}
|
|
3858
|
+
function decodeLengthPrefixedJson(input, maximum) {
|
|
3859
|
+
if (input.length < HOST_RELAY_IPC_LENGTH_BYTES) return null;
|
|
3860
|
+
const length = input.readUInt32BE(0);
|
|
3861
|
+
if (length === 0 || length > maximum) throw new HostRelayIpcError("relay_unavailable", `Host Relay IPC message length is invalid: ${refusalFact("declared_bytes", length, `between 1 and ${maximum}`)}.`);
|
|
3862
|
+
if (input.length < length + HOST_RELAY_IPC_LENGTH_BYTES) return null;
|
|
3863
|
+
if (input.length !== length + HOST_RELAY_IPC_LENGTH_BYTES) throw new HostRelayIpcError("relay_unavailable", `Host Relay IPC message has trailing bytes: ${refusalFacts([{ name: "declared_bytes", value: length, expected: `the received message length minus ${HOST_RELAY_IPC_LENGTH_BYTES}` }, { name: "received_bytes", value: input.byteLength, expected: `exactly ${length + HOST_RELAY_IPC_LENGTH_BYTES}` }])}.`);
|
|
3864
|
+
try {
|
|
3865
|
+
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(input.subarray(HOST_RELAY_IPC_LENGTH_BYTES)));
|
|
3866
|
+
} catch {
|
|
3867
|
+
throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC message is invalid.");
|
|
3868
|
+
}
|
|
3869
|
+
}
|
|
3870
|
+
function encodeLengthPrefixed(value) {
|
|
3871
|
+
const body = Buffer.from(JSON.stringify(value), "utf8");
|
|
3872
|
+
const output = Buffer.allocUnsafe(body.length + HOST_RELAY_IPC_LENGTH_BYTES);
|
|
3873
|
+
output.writeUInt32BE(body.length, 0);
|
|
3874
|
+
body.copy(output, HOST_RELAY_IPC_LENGTH_BYTES);
|
|
3875
|
+
return output;
|
|
3876
|
+
}
|
|
3877
|
+
function exactKeys2(value, keys) {
|
|
3878
|
+
return Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
3879
|
+
}
|
|
3786
3880
|
|
|
3787
3881
|
// host/claude/src/claude-producer.ts
|
|
3788
3882
|
import { mkdir as mkdir3, readFile as readFile2, rename as rename2, writeFile } from "node:fs/promises";
|
|
@@ -3817,7 +3911,7 @@ function invocationContextKey(identity) {
|
|
|
3817
3911
|
return cealRequestSha256({ host_source_ref: identity.host_source_ref, host_session_ref: identity.host_session_ref });
|
|
3818
3912
|
}
|
|
3819
3913
|
function hasHostInvocationIdentityKeys(value) {
|
|
3820
|
-
return
|
|
3914
|
+
return exactKeys3(value, HOST_INVOCATION_IDENTITY_KEYS);
|
|
3821
3915
|
}
|
|
3822
3916
|
function hasHostInvocationContextKeys(value, optional = []) {
|
|
3823
3917
|
return requiredKeys(value, HOST_INVOCATION_CONTEXT_REQUIRED_KEYS, optional);
|
|
@@ -3833,7 +3927,7 @@ function invocationContextFromTurn(identity, promptRef, expiresAt, descriptor2)
|
|
|
3833
3927
|
descriptor2.validate(context);
|
|
3834
3928
|
return Object.freeze(context);
|
|
3835
3929
|
}
|
|
3836
|
-
function
|
|
3930
|
+
function exactKeys3(value, keys) {
|
|
3837
3931
|
const actual = Object.keys(value);
|
|
3838
3932
|
return actual.length === keys.length && keys.every((key) => Object.hasOwn(value, key)) && actual.every((key) => keys.includes(key));
|
|
3839
3933
|
}
|
|
@@ -5517,6 +5611,8 @@ var CodexTranscriptWatcher = class {
|
|
|
5517
5611
|
now;
|
|
5518
5612
|
log;
|
|
5519
5613
|
retriedMalformedQuarantines = /* @__PURE__ */ new Set();
|
|
5614
|
+
producerInstallationRef;
|
|
5615
|
+
registerCurrentPrompt;
|
|
5520
5616
|
constructor(options) {
|
|
5521
5617
|
if (typeof options.outbox_dir !== "string" || options.outbox_dir.length === 0) throw new CodexHostAdapterError("configuration", "Codex transcript watcher outbox is invalid.");
|
|
5522
5618
|
this.store = new CodexOutboxStore(options.outbox_dir);
|
|
@@ -5526,6 +5622,8 @@ var CodexTranscriptWatcher = class {
|
|
|
5526
5622
|
process.stderr.write(`${line}
|
|
5527
5623
|
`);
|
|
5528
5624
|
});
|
|
5625
|
+
this.producerInstallationRef = options.producer_installation_ref;
|
|
5626
|
+
this.registerCurrentPrompt = options.register_current_prompt;
|
|
5529
5627
|
}
|
|
5530
5628
|
async scanOnce() {
|
|
5531
5629
|
const registrations = await this.store.listTranscriptRegistrations();
|
|
@@ -5670,10 +5768,15 @@ var CodexTranscriptWatcher = class {
|
|
|
5670
5768
|
created_at: record8.timestamp,
|
|
5671
5769
|
expires_at: expiration(this.now, this.outboxRetentionMs)
|
|
5672
5770
|
};
|
|
5771
|
+
await this.registerPrompt(origin, registration, activeTask, currentPromptRef, record8.prompt, envelope.expires_at);
|
|
5673
5772
|
await this.store.put(envelope);
|
|
5674
5773
|
if (origin) await this.store.activateInvocationContext(identity, promptRef, envelope.expires_at);
|
|
5675
5774
|
return { activeTask: { ...activeTask, origin_host_input_ref: activeTask.origin_host_input_ref ?? hostInputRef, prompt_ref: activeTask.prompt_ref ?? currentPromptRef }, enqueued: 1 };
|
|
5676
5775
|
}
|
|
5776
|
+
async registerPrompt(origin, registration, activeTask, promptRef, prompt, expiresAt) {
|
|
5777
|
+
if (!origin || this.producerInstallationRef === void 0 || this.registerCurrentPrompt === void 0) return;
|
|
5778
|
+
await this.registerCurrentPrompt({ producer_id: "codex", producer_installation_ref: this.producerInstallationRef, local_session_ref: registration.host_session_ref, local_turn_ref: activeTask.host_turn_ref, prompt_ref: promptRef, current_prompt: prompt, context_expires_at: expiresAt });
|
|
5779
|
+
}
|
|
5677
5780
|
async processTerminal(registration, activeTask, record8) {
|
|
5678
5781
|
if (activeTask === void 0 || activeTask.codex_turn_id !== record8.turn_id || activeTask.origin_host_input_ref === void 0 || activeTask.prompt_ref === void 0) return { ...activeTask === void 0 ? {} : { activeTask }, enqueued: 0 };
|
|
5679
5782
|
const identity = { host_source_ref: registration.host_source_ref, host_session_ref: registration.host_session_ref, host_turn_ref: activeTask.host_turn_ref };
|
|
@@ -5878,7 +5981,8 @@ function expiration(now, retentionMs) {
|
|
|
5878
5981
|
|
|
5879
5982
|
// host/codex/src/codex-producer-runtime.ts
|
|
5880
5983
|
async function drainCodexProducerOnce(options) {
|
|
5881
|
-
const
|
|
5984
|
+
const promptPort = new HostRelayCurrentPromptPort(options.relay_endpoint, options.timeout_ms);
|
|
5985
|
+
const scan = await new CodexTranscriptWatcher({ outbox_dir: options.outbox_dir, producer_installation_ref: options.producer_installation_ref, register_current_prompt: (input) => promptPort.register(input) }).scanOnce();
|
|
5882
5986
|
const producer = new CodexProducer({ outbox_dir: options.outbox_dir, producer_installation_ref: options.producer_installation_ref, relay: new HostRelayIpcAdmissionPort(options.relay_endpoint, options.timeout_ms), ...options.producer_epoch === void 0 ? {} : { producer_epoch: options.producer_epoch }, ...options.now === void 0 ? {} : { now: options.now } });
|
|
5883
5987
|
return { scanned: scan.enqueued, ...await producer.drainOutbox() };
|
|
5884
5988
|
}
|
|
@@ -6221,7 +6325,6 @@ import { homedir as homedir2 } from "node:os";
|
|
|
6221
6325
|
import { dirname as dirname5, isAbsolute as isAbsolute3, join as join8 } from "node:path";
|
|
6222
6326
|
|
|
6223
6327
|
// host/command-vector.ts
|
|
6224
|
-
var HOST_HOOK_TIMEOUT_SECONDS = 1;
|
|
6225
6328
|
var MAX_ARGUMENTS = 64;
|
|
6226
6329
|
var MAX_COMMAND_BYTES = 4096;
|
|
6227
6330
|
function validateHostCommandVector(vector) {
|
|
@@ -6755,12 +6858,15 @@ function normalizeHookGroups(entries) {
|
|
|
6755
6858
|
}
|
|
6756
6859
|
return groups;
|
|
6757
6860
|
}
|
|
6861
|
+
function ownedHookEntry(command, event) {
|
|
6862
|
+
return { type: "command", command: hookCommand(command, event, "posix"), commandWindows: hookCommand(command, event, "windows"), timeout: HOST_HOOK_TIMEOUT_SECONDS, async: false };
|
|
6863
|
+
}
|
|
6758
6864
|
function mergeOwnedHooks2(config, command) {
|
|
6759
6865
|
const hooks = isRecord7(config.hooks) ? { ...config.hooks } : {};
|
|
6760
6866
|
for (const event of CODEX_HOOK_EVENTS) {
|
|
6761
6867
|
const groups = Array.isArray(hooks[event]) ? normalizeHookGroups(hooks[event]) : [];
|
|
6762
6868
|
const retained = groups.map((group) => ({ ...group, hooks: group.hooks.filter((entry) => !ownedHookHandler(entry)) })).filter((group) => group.hooks.length > 0);
|
|
6763
|
-
retained.push({ hooks: [
|
|
6869
|
+
retained.push({ hooks: [ownedHookEntry(command, event)] });
|
|
6764
6870
|
hooks[event] = retained;
|
|
6765
6871
|
}
|
|
6766
6872
|
return { ...config, hooks };
|
|
@@ -6853,9 +6959,15 @@ function inspectHookCommands(config, command) {
|
|
|
6853
6959
|
const locations = ownedHookLocations(config, event);
|
|
6854
6960
|
if (locations.length !== 1) return [];
|
|
6855
6961
|
const handler = locations[0]?.handler;
|
|
6856
|
-
return handler
|
|
6962
|
+
return ownedHookEntryMatches(handler, ownedHookEntry(command, event)) ? [] : [`owned_hook_drifted:${event}`];
|
|
6857
6963
|
});
|
|
6858
6964
|
}
|
|
6965
|
+
function ownedHookEntryMatches(actual, expected) {
|
|
6966
|
+
if (actual === void 0) return false;
|
|
6967
|
+
const actualKeys = Object.keys(actual).sort();
|
|
6968
|
+
const expectedKeys = Object.keys(expected).sort();
|
|
6969
|
+
return actualKeys.length === expectedKeys.length && expectedKeys.every((key, index) => actualKeys[index] === key && actual[key] === expected[key]);
|
|
6970
|
+
}
|
|
6859
6971
|
async function readTrustConfig(configPath) {
|
|
6860
6972
|
try {
|
|
6861
6973
|
return await readCodexConfig(codexConfigPath(configPath));
|
|
@@ -7232,8 +7344,11 @@ var InstalledHostRuntimeHookAdapter = class {
|
|
|
7232
7344
|
const isInstalled = transition.target.components.includes(producer);
|
|
7233
7345
|
const entry = this.entry(producer, paths);
|
|
7234
7346
|
if (wasInstalled && !isInstalled) {
|
|
7235
|
-
await
|
|
7236
|
-
if (
|
|
7347
|
+
const entryState = await inspectHostEntryLinks(entry.entryRoot, entry.targets);
|
|
7348
|
+
if (entryState !== "drifted") {
|
|
7349
|
+
await uninstallProducerHooks(producer, this.homes);
|
|
7350
|
+
if (!remaining.has(entry.entryRoot)) await removeHostEntryLinks(entry.entryRoot);
|
|
7351
|
+
}
|
|
7237
7352
|
}
|
|
7238
7353
|
if (isInstalled) {
|
|
7239
7354
|
await installHostEntryLinks(entry.entryRoot, entry.targets);
|
|
@@ -8024,7 +8139,8 @@ function createLinuxUserSystemdAdapter(options) {
|
|
|
8024
8139
|
await ensurePrivateUnitDirectory(unitDirectory);
|
|
8025
8140
|
const ownedUnits = await ownedHostUnits(unitDirectory);
|
|
8026
8141
|
for (const service of target.services) await replaceOwnedUnit(unitDirectory, identity, service);
|
|
8027
|
-
|
|
8142
|
+
const removableUnits = target.services.length === 0 ? ownedUnits.filter((unit) => unit.identity === identity) : ownedUnits;
|
|
8143
|
+
for (const unit of removableUnits) {
|
|
8028
8144
|
if (unit.identity === identity && targetByComponent.has(unit.component)) continue;
|
|
8029
8145
|
await invokeSystemctl(run, systemctl, ["--user", "disable", "--now", unitName(unit.identity, unit.component)]);
|
|
8030
8146
|
await removeOwnedUnit(unitDirectory, unit.identity, unit.component);
|
|
@@ -8036,7 +8152,7 @@ function createLinuxUserSystemdAdapter(options) {
|
|
|
8036
8152
|
if (previousByComponent.has(service.component)) await invokeSystemctl(run, systemctl, ["--user", "restart", name]);
|
|
8037
8153
|
await requireExpectedReadback(run, systemctl, unitDirectory, identity, service, "running");
|
|
8038
8154
|
}
|
|
8039
|
-
for (const unit of
|
|
8155
|
+
for (const unit of removableUnits) if (unit.identity !== identity || !targetByComponent.has(unit.component)) await requireAbsentReadback(run, systemctl, unitDirectory, unit.identity, unit.component);
|
|
8040
8156
|
},
|
|
8041
8157
|
async restart({ target, service }) {
|
|
8042
8158
|
const identity = prefixIdentity(target.prefix);
|