@corca-org/ceal-host-linux-arm64 1.0.8 → 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 +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
package/bin/ceal-host
CHANGED
|
Binary file
|
|
@@ -110,11 +110,28 @@ var client_wire_contract_default = {
|
|
|
110
110
|
],
|
|
111
111
|
bare_document_fields: [
|
|
112
112
|
"invocation",
|
|
113
|
-
"
|
|
113
|
+
"required_action_sequence",
|
|
114
|
+
"entrypoints",
|
|
114
115
|
"common_concepts",
|
|
115
116
|
"operations",
|
|
116
117
|
"catalog_revision"
|
|
117
118
|
],
|
|
119
|
+
prompt_field: "prompt",
|
|
120
|
+
prompt_schema_version: "ceal.prompt.v1",
|
|
121
|
+
focused_prompt_document_fields: [
|
|
122
|
+
"catalog_revision",
|
|
123
|
+
"prompt"
|
|
124
|
+
],
|
|
125
|
+
focused_prompt_continuation_document_fields: [
|
|
126
|
+
"catalog_revision",
|
|
127
|
+
"remaining_work",
|
|
128
|
+
"prompt"
|
|
129
|
+
],
|
|
130
|
+
discovery_command: "discovery",
|
|
131
|
+
discovery_manifest_schema_version: "ceal.discovery_manifest.v1",
|
|
132
|
+
discovery_manifest_document_fields: [
|
|
133
|
+
"discovery_manifest"
|
|
134
|
+
],
|
|
118
135
|
exit_code_max: 125,
|
|
119
136
|
bare_document_max_bytes: 65536,
|
|
120
137
|
complete_max_bytes: 66019,
|
|
@@ -141,8 +158,15 @@ var CEAL_VERIFIED_ARTIFACT_MAX_BYTES = artifact.max_bytes;
|
|
|
141
158
|
var CEAL_VERIFIED_ARTIFACT_DESCRIPTOR_MAX_BYTES = artifact.envelope_max_bytes;
|
|
142
159
|
var CEAL_COMMAND_REQUEST_SCHEMA_VERSION = request.schema_version;
|
|
143
160
|
var CEAL_COMMAND_REQUEST_MAX_BYTES = request.absolute_transport_max_bytes;
|
|
144
|
-
var CEAL_COMMAND_RESPONSE_BARE_DOCUMENT_FIELDS = response.bare_document_fields;
|
|
145
161
|
var CEAL_COMMAND_RESPONSE_BARE_DOCUMENT_MAX_BYTES = response.bare_document_max_bytes;
|
|
162
|
+
var CEAL_COMMAND_RESPONSE_PROMPT_FIELD = response.prompt_field;
|
|
163
|
+
var CEAL_COMMAND_RESPONSE_PROMPT_SCHEMA_VERSION = response.prompt_schema_version;
|
|
164
|
+
var CEAL_COMMAND_RESPONSE_PROMPT_DOCUMENT_FIELDS = Object.freeze([...response.bare_document_fields, response.prompt_field]);
|
|
165
|
+
var CEAL_COMMAND_RESPONSE_FOCUSED_PROMPT_DOCUMENT_FIELDS = Object.freeze([...response.focused_prompt_document_fields]);
|
|
166
|
+
var CEAL_COMMAND_RESPONSE_FOCUSED_PROMPT_CONTINUATION_DOCUMENT_FIELDS = Object.freeze([...response.focused_prompt_continuation_document_fields]);
|
|
167
|
+
var CEAL_COMMAND_RESPONSE_DISCOVERY_COMMAND = response.discovery_command;
|
|
168
|
+
var CEAL_COMMAND_RESPONSE_DISCOVERY_MANIFEST_SCHEMA_VERSION = response.discovery_manifest_schema_version;
|
|
169
|
+
var CEAL_COMMAND_RESPONSE_DISCOVERY_MANIFEST_DOCUMENT_FIELDS = Object.freeze([...response.discovery_manifest_document_fields]);
|
|
146
170
|
var CEAL_COMMAND_RESPONSE_MAX_BYTES = response.absolute_transport_max_bytes;
|
|
147
171
|
|
|
148
172
|
// packages/ceal-client-protocol/src/vocabulary.ts
|
|
@@ -178,7 +202,7 @@ var CEAL_OPERATION_RECOVERY_KINDS = vocabulary(["none", "reconcile", "compensate
|
|
|
178
202
|
var CEAL_OPERATION_RECOVERY_STATUSES = vocabulary(["not_started", "active", "completed"]);
|
|
179
203
|
var CEAL_OPERATION_PROVIDER_READBACK_AVAILABILITY = vocabulary(["not_started", "not_applicable", "not_available", "pending", "available"]);
|
|
180
204
|
var CEAL_OPERATION_OFFERED_HANDOFF_STATES = vocabulary(["accepted", "rejected", "unknown"]);
|
|
181
|
-
var CEAL_OPERATION_RECEIPT_AUTHORITY_KEYS = Object.freeze(["instance_ref", "
|
|
205
|
+
var CEAL_OPERATION_RECEIPT_AUTHORITY_KEYS = Object.freeze(["instance_ref", "access_group_ref", "principal_ref", "execution_subject_ref", "authority_revision_ref"]);
|
|
182
206
|
var CEAL_OPERATION_APPROVAL_DISPOSITIONS = vocabulary([
|
|
183
207
|
"approval_not_required_by_policy",
|
|
184
208
|
"interactive_pending",
|
|
@@ -193,6 +217,8 @@ var CEAL_CAPABILITY_READINESS_VALUES = vocabulary(["ready", "degraded", "unavail
|
|
|
193
217
|
var CEAL_TARGET_REQUIREMENTS = vocabulary(["required", "optional", "none"]);
|
|
194
218
|
var CEAL_AUDIT_OUTCOMES = vocabulary(["succeeded", "denied", "failed"]);
|
|
195
219
|
var CEAL_GATEWAY_PROVIDER_STEP_OUTCOMES = vocabulary(["completed", "rejected", "throttled", "failed"]);
|
|
220
|
+
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"]);
|
|
221
|
+
var CEAL_GATEWAY_READ_REUSE_UNAVAILABLE_REASONS = vocabulary(["not_reported", "storage_unavailable", "coverage_incomplete", "freshness_refresh_required", "not_reusable", "bypassed"]);
|
|
196
222
|
var CEAL_POLICY_DECISIONS = vocabulary(["allowed", "denied", "not_evaluated"]);
|
|
197
223
|
var CEAL_CONNECTOR_ROUTE_PHASES = vocabulary(["scope_observation", "target_selection", "route_resolution"]);
|
|
198
224
|
var CEAL_CONNECTOR_ROUTE_CAUSES = vocabulary(["provider_throttled", "provider_unavailable", "binding_invalid", "scope_limit_exceeded"]);
|
|
@@ -465,8 +491,10 @@ function requireIsoTimestamp(value, message) {
|
|
|
465
491
|
var JSON_DESCRIPTION_CONTROL_CHARACTER = new RegExp("\\p{Cc}", "u");
|
|
466
492
|
|
|
467
493
|
// packages/ceal-client-protocol/src/operation-contract-validation.ts
|
|
468
|
-
var CEAL_OPERATION_AUTHORITY_POLICY_KEYS = Object.freeze(["
|
|
494
|
+
var CEAL_OPERATION_AUTHORITY_POLICY_KEYS = Object.freeze(["access_group", "instance_binding", "target", "admission_recheck"]);
|
|
469
495
|
var MAX_OPERATION_INPUT_RESOLVER_BINDINGS = 96;
|
|
496
|
+
var CEAL_OPERATION_DESCRIPTOR_REQUIRED_ENVELOPE_KEYS = Object.freeze(["schema_version", "id", "input_contract", "result_contract", "policy"]);
|
|
497
|
+
var CEAL_OPERATION_DESCRIPTOR_OPTIONAL_ENVELOPE_KEYS = Object.freeze(["input_resolution", "summary"]);
|
|
470
498
|
var CEAL_OPERATION_RESULT_KEYS = vocabulary(["ok", "operation_id", "operation_receipt", "schema_version", "value"]);
|
|
471
499
|
var CEAL_OPERATION_COMPACT_RESULT_KEYS = vocabulary(["ok", "operation_evidence", "operation_id", "schema_version", "value"]);
|
|
472
500
|
|
|
@@ -540,6 +568,7 @@ var CEAL_SCHEMA_LITERALS = [
|
|
|
540
568
|
"ceal.operation_descriptor.v1",
|
|
541
569
|
"ceal.operation_error.v1",
|
|
542
570
|
"ceal.operation_failure.v1",
|
|
571
|
+
"ceal.operation_failure.compact.v1",
|
|
543
572
|
"ceal.operation_receipt.v1",
|
|
544
573
|
"ceal.operation_result.v1",
|
|
545
574
|
"ceal.operation_result.compact.v1",
|
|
@@ -565,17 +594,16 @@ var CEAL_BOUNDED_SERIES_CATALOG = Object.freeze({
|
|
|
565
594
|
engagement_signal: (root) => join(root, "runtime-state", "slack-feedback.jsonl"),
|
|
566
595
|
runtime_error: (root) => join(root, "runtime-state", "runtime-errors.jsonl"),
|
|
567
596
|
turn_bridge_request: (root) => join(root, ".ceal", "turn-bridge", "requests.jsonl"),
|
|
568
|
-
channel_log: (root) => join(root, "log.jsonl"),
|
|
569
597
|
thread_run_events: (root) => join(root, "run-events.jsonl"),
|
|
570
598
|
bounded_store_sidecar: (root) => `${root}.jsonl`,
|
|
571
599
|
gateway_audit_archive: (root) => `${root}.jsonl`,
|
|
572
600
|
gateway_capability_audit: (root) => join(root, "capability-audit.jsonl"),
|
|
573
601
|
gateway_retrieval_waste_partition: (root) => `${root}.jsonl`,
|
|
574
602
|
gateway_access_policy_publication: (root) => join(root, "access-policy-publications.jsonl"),
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
603
|
+
gateway_access_group_connector_control_audit: (root) => `${root}.audit.jsonl`,
|
|
604
|
+
gateway_access_group_connector_scope_audit: (root) => join(root, "profile-connector-scope-audit.jsonl"),
|
|
605
|
+
gateway_access_group_connector_activity_scope_audit: (root) => join(root, "profile-connector-activity-scope-audit.jsonl"),
|
|
606
|
+
gateway_access_group_connector_readiness_audit: (root) => join(root, "profile-connector-readiness.audit.jsonl"),
|
|
579
607
|
gateway_organization_audit_ledger: (root) => join(root, "organization-ledger.jsonl"),
|
|
580
608
|
gateway_personal_client_audit: (root) => join(root, "audit.jsonl"),
|
|
581
609
|
gateway_personal_client_access_audit: (root) => join(root, "access-audit.jsonl"),
|
|
@@ -626,12 +654,6 @@ var CEAL_AGENT_SESSION_COMMIT_KEYS = vocabulary(["attempt_ref", "expected_sessio
|
|
|
626
654
|
// packages/ceal-client-protocol/src/operation-next-actions.ts
|
|
627
655
|
var CALLER_RECOVERABLE_NEXT_ACTION_VALUES = [
|
|
628
656
|
"select_did_you_mean",
|
|
629
|
-
// The graph, not the argument list, is what the caller must change: the
|
|
630
|
-
// resolver that owns this input has no producing node upstream, and no edit
|
|
631
|
-
// to the invocation can conjure one. `resolver_dependency_absent` carried no
|
|
632
|
-
// remedy at all rather than borrow a word that means something else, so the
|
|
633
|
-
// scorer read a fully-diagnosed, caller-fixable refusal as a failed run.
|
|
634
|
-
"request.graph.append",
|
|
635
657
|
"choose_new_output_path",
|
|
636
658
|
"choose_new_idempotency_key",
|
|
637
659
|
"restart_search",
|
|
@@ -683,8 +705,6 @@ var NON_REMEDY_NEXT_ACTION_VALUES = [
|
|
|
683
705
|
"reconcile_occurrence",
|
|
684
706
|
"reduce_request_size",
|
|
685
707
|
"repair_or_adopt_session",
|
|
686
|
-
"request.effect_approval.read",
|
|
687
|
-
"request.run",
|
|
688
708
|
"retry",
|
|
689
709
|
// The owner -- a correlation hook, an approval hook -- is not serving right
|
|
690
710
|
// now. The caller changes nothing and the same call succeeds once the owner
|
|
@@ -781,12 +801,12 @@ var CEAL_REQUEST_JSON_SCHEMA = {
|
|
|
781
801
|
additionalProperties: false,
|
|
782
802
|
properties: {
|
|
783
803
|
instance_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
|
|
784
|
-
|
|
804
|
+
access_group_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
|
|
785
805
|
principal_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
|
|
786
806
|
execution_subject_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
|
|
787
807
|
authority_revision_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source }
|
|
788
808
|
},
|
|
789
|
-
required: ["instance_ref", "
|
|
809
|
+
required: ["instance_ref", "access_group_ref", "principal_ref", "execution_subject_ref", "authority_revision_ref"]
|
|
790
810
|
},
|
|
791
811
|
prompt_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
|
|
792
812
|
host_session_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
|
|
@@ -918,7 +938,7 @@ var CEAL_HOST_OBSERVATION_KINDS = vocabulary(["prompt", "session", "turn", "mode
|
|
|
918
938
|
function isCealHostPromptObservationValue(value) {
|
|
919
939
|
return isOperationRecord(value) && Object.keys(value).length === 1 && isCealDigest(value.body_sha256);
|
|
920
940
|
}
|
|
921
|
-
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;
|
|
941
|
+
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;
|
|
922
942
|
function assertHostObservationValue(value, kind) {
|
|
923
943
|
if (value === void 0) invalid("Ceal Host observation value is invalid.");
|
|
924
944
|
if (kind === "prompt" && !isCealHostPromptObservationValue(value)) invalid("Ceal Host prompt observation must contain only its body digest.");
|
|
@@ -938,6 +958,14 @@ function inspectHostKeys(value) {
|
|
|
938
958
|
}
|
|
939
959
|
}
|
|
940
960
|
|
|
961
|
+
// packages/ceal-client-protocol/src/host-prompt-ref.ts
|
|
962
|
+
var CEAL_HOST_PROMPT_DIGEST_PATTERN = "^[a-f0-9]{64}$";
|
|
963
|
+
var PROMPT_DIGEST = new RegExp(CEAL_HOST_PROMPT_DIGEST_PATTERN, "u");
|
|
964
|
+
function hostProducerPromptRef(promptSha256) {
|
|
965
|
+
if (!PROMPT_DIGEST.test(promptSha256)) throw new TypeError("Canonical Host prompt digest is invalid.");
|
|
966
|
+
return `ceal-host-prompt:${promptSha256}`;
|
|
967
|
+
}
|
|
968
|
+
|
|
941
969
|
// packages/ceal-client-protocol/src/request-effect-approval.ts
|
|
942
970
|
var CEAL_EFFECT_APPROVAL_DECISION_CHECK_PHRASES = Object.freeze([
|
|
943
971
|
"observed after this approval was raised and before it expires",
|
|
@@ -953,6 +981,12 @@ var OWNER_WRITE_STATES = Object.freeze(["attempt_started", "provider_acknowledge
|
|
|
953
981
|
var OWNER_EFFECT_STATES = Object.freeze(["none", "applied", "failed", "unknown", "reconciled"]);
|
|
954
982
|
var OWNER_RECEIPT_STATES = Object.freeze(["pending", "available", "failed", "unknown", "reconciled"]);
|
|
955
983
|
|
|
984
|
+
// packages/ceal-client-protocol/src/thread-excerpt.ts
|
|
985
|
+
var CEAL_THREAD_RECENT_WINDOW = 6;
|
|
986
|
+
var CEAL_THREAD_LAST_APP_MESSAGES_WINDOW = 3;
|
|
987
|
+
var CEAL_THREAD_OLDER_SUMMARY_WINDOW = 4;
|
|
988
|
+
var CEAL_FED_THREAD_MESSAGE_LIMIT = CEAL_THREAD_RECENT_WINDOW + CEAL_THREAD_OLDER_SUMMARY_WINDOW + CEAL_THREAD_LAST_APP_MESSAGES_WINDOW;
|
|
989
|
+
|
|
956
990
|
// packages/ceal-client-protocol/src/request-graph-readiness.ts
|
|
957
991
|
var REQUEST_GRAPH_PRODUCER_TO_APPEND_SCHEMA = {
|
|
958
992
|
type: "object",
|
|
@@ -1032,6 +1066,13 @@ var CEAL_REQUEST_GRAPH_NODE_PREPARE_READINESS_JSON_SCHEMA = {
|
|
|
1032
1066
|
var REQUIRED_FIELDS = Object.freeze(["schema_version", "operation_id", "local_path", "content_json_pointer", "size_bytes", "sha256", "read_argv"]);
|
|
1033
1067
|
var FIELDS = /* @__PURE__ */ new Set([...REQUIRED_FIELDS, "local_result_root", "model_disclosure"]);
|
|
1034
1068
|
|
|
1069
|
+
// packages/ceal-client-protocol/src/session-start-affordance.ts
|
|
1070
|
+
var CEAL_SESSION_ENTRY_INVOCATION = "ceal";
|
|
1071
|
+
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.`;
|
|
1072
|
+
|
|
1073
|
+
// packages/ceal-client-protocol/src/discovery-manifest.ts
|
|
1074
|
+
var CEAL_DISCOVERY_MANIFEST_CONNECTOR_KINDS = vocabulary(["github", "google-workspace", "notion", "slack"]);
|
|
1075
|
+
|
|
1035
1076
|
// packages/ceal-client-protocol/src/conversation-contracts.ts
|
|
1036
1077
|
var CEAL_APPROVAL_POLICY_KINDS = vocabulary(["requester_only", "named_users", "role_based"]);
|
|
1037
1078
|
var CEAL_APPROVAL_TARGET_KINDS = vocabulary([
|
|
@@ -1248,7 +1289,7 @@ var CEAL_PRESENTATION_INTENTS = vocabulary(["progress", ...CEAL_FINAL_PRESENTATI
|
|
|
1248
1289
|
|
|
1249
1290
|
// packages/ceal-client-protocol/src/personal-client-vocabulary.ts
|
|
1250
1291
|
var CEAL_PERSONAL_CLIENT_BINDING_KEYS = vocabulary([
|
|
1251
|
-
"
|
|
1292
|
+
"access_group_ref",
|
|
1252
1293
|
"membership_ref",
|
|
1253
1294
|
"registration_ref",
|
|
1254
1295
|
"client_ref",
|
|
@@ -1396,7 +1437,6 @@ var HOST_PRODUCER_FRAME_SCHEMA = "ceal.host_producer_frame.v1";
|
|
|
1396
1437
|
var HOST_PRODUCER_MAX_JSON_BYTES = 262144;
|
|
1397
1438
|
var HOST_PRODUCER_FRAME_LENGTH_BYTES = Uint32Array.BYTES_PER_ELEMENT;
|
|
1398
1439
|
var SAFE_REF2 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
|
|
1399
|
-
var DIGEST2 = /^[a-f0-9]{64}$/u;
|
|
1400
1440
|
var PRODUCERS = /* @__PURE__ */ new Set(["codex", "claude"]);
|
|
1401
1441
|
var HOST_PRODUCER_FRAME_KINDS = ["session_started", "turn_started", "user_input", "turn_terminal", "producer_status"];
|
|
1402
1442
|
var FRAME_KINDS = new Set(HOST_PRODUCER_FRAME_KINDS);
|
|
@@ -1437,10 +1477,6 @@ function decodeHostProducerFrame(input) {
|
|
|
1437
1477
|
validateFrame(value);
|
|
1438
1478
|
return value;
|
|
1439
1479
|
}
|
|
1440
|
-
function hostProducerPromptRef(promptSha256) {
|
|
1441
|
-
if (!DIGEST2.test(promptSha256)) throw new TypeError("Canonical Host prompt digest is invalid.");
|
|
1442
|
-
return `ceal-host-prompt:${promptSha256}`;
|
|
1443
|
-
}
|
|
1444
1480
|
function validateFrame(value) {
|
|
1445
1481
|
if (!record2(value)) throw new HostProducerFrameError("invalid_frame_shape");
|
|
1446
1482
|
if (value.schema_version !== HOST_PRODUCER_FRAME_SCHEMA) throw new HostProducerFrameError("unsupported_frame_schema", `unsupported_frame_schema: ${refusalFact("schema_version", value.schema_version, HOST_PRODUCER_FRAME_SCHEMA)}`);
|
|
@@ -1621,12 +1657,19 @@ var RELAY_QUARANTINE_MAX_BYTES = 16 * 1024 * 1024;
|
|
|
1621
1657
|
|
|
1622
1658
|
// host/relay/src/relay-admission-store.ts
|
|
1623
1659
|
var DEFAULT_LIMITS = { global_count: 8192, global_bytes: 64 * 1024 * 1024, producer_count: 4096, producer_bytes: 32 * 1024 * 1024 };
|
|
1660
|
+
var RETRY_SECONDS = [1, 2, 4, 8, 16, 32, 60];
|
|
1661
|
+
var MAX_RETRYABLE_ATTEMPTS = RETRY_SECONDS.length + 10;
|
|
1624
1662
|
|
|
1625
1663
|
// host/relay/src/relay-request-binding-store.ts
|
|
1626
1664
|
var MAX_STATE_BYTES = 8 * 1024 * 1024;
|
|
1627
1665
|
|
|
1628
1666
|
// host/relay/src/relay-ipc.ts
|
|
1629
1667
|
import { createConnection, createServer } from "node:net";
|
|
1668
|
+
|
|
1669
|
+
// host/relay/src/current-prompt-custody.ts
|
|
1670
|
+
var HOST_CURRENT_PROMPT_MAX_BYTES = 256 * 1024;
|
|
1671
|
+
|
|
1672
|
+
// host/relay/src/relay-ipc.ts
|
|
1630
1673
|
var HOST_RELAY_REQUEST_BINDING_KEYS = Object.freeze([
|
|
1631
1674
|
"schema_version",
|
|
1632
1675
|
"producer_id",
|
|
@@ -1643,6 +1686,8 @@ var HOST_RELAY_REQUEST_BINDING_KEYS = Object.freeze([
|
|
|
1643
1686
|
"host_input_ref"
|
|
1644
1687
|
]);
|
|
1645
1688
|
var HOST_RELAY_IPC_RESPONSE_SCHEMA = "ceal.host_relay_admission.v1";
|
|
1689
|
+
var HOST_RELAY_CURRENT_PROMPT_REGISTER_SCHEMA = "ceal.host_relay_current_prompt_register.v1";
|
|
1690
|
+
var HOST_RELAY_CURRENT_PROMPT_RESULT_SCHEMA = "ceal.host_relay_current_prompt_result.v1";
|
|
1646
1691
|
var HOST_RELAY_IPC_LENGTH_BYTES = Uint32Array.BYTES_PER_ELEMENT;
|
|
1647
1692
|
var HOST_RELAY_ADMISSION_RESPONSE_MAX_BYTES = 4096;
|
|
1648
1693
|
var HostRelayIpcError = class extends Error {
|
|
@@ -1665,22 +1710,42 @@ var HostRelayIpcAdmissionPort = class {
|
|
|
1665
1710
|
return { code: response2.code, admitted_through_sequence: response2.admitted_through_sequence, delivered_through_sequence: response2.delivered_through_sequence };
|
|
1666
1711
|
}
|
|
1667
1712
|
};
|
|
1713
|
+
var HostRelayCurrentPromptPort = class {
|
|
1714
|
+
endpoint;
|
|
1715
|
+
timeout_ms;
|
|
1716
|
+
constructor(endpoint, timeoutMs = 5e3) {
|
|
1717
|
+
this.endpoint = endpoint;
|
|
1718
|
+
this.timeout_ms = timeoutMs;
|
|
1719
|
+
}
|
|
1720
|
+
async register(input) {
|
|
1721
|
+
const request2 = { schema_version: HOST_RELAY_CURRENT_PROMPT_REGISTER_SCHEMA, ...input };
|
|
1722
|
+
const response2 = await exchange(this.endpoint, encodeLengthPrefixed(request2), this.timeout_ms, decodeCurrentPromptResponseBuffer);
|
|
1723
|
+
if (response2.status !== "registered") throw new HostRelayIpcError("relay_unavailable", response2.status);
|
|
1724
|
+
}
|
|
1725
|
+
};
|
|
1668
1726
|
function submitHostProducerFrame(endpoint, frame, timeoutMs = 5e3) {
|
|
1669
1727
|
return exchange(endpoint, encodeHostProducerFrame(frame), timeoutMs, decodeResponseBuffer);
|
|
1670
1728
|
}
|
|
1671
|
-
function exchange(endpoint, encoded, timeoutMs, decode) {
|
|
1729
|
+
function exchange(endpoint, encoded, timeoutMs, decode, signal) {
|
|
1672
1730
|
return new Promise((resolve, reject) => {
|
|
1673
1731
|
const socket = createConnection(endpoint);
|
|
1674
1732
|
let buffer = Buffer.alloc(0);
|
|
1675
1733
|
let settled = false;
|
|
1734
|
+
const aborted = () => finish(new HostRelayIpcError("relay_unavailable", "Host Relay IPC was cancelled."));
|
|
1676
1735
|
const finish = (error, response2) => {
|
|
1677
1736
|
if (settled) return;
|
|
1678
1737
|
settled = true;
|
|
1738
|
+
signal?.removeEventListener("abort", aborted);
|
|
1679
1739
|
socket.destroy();
|
|
1680
1740
|
if (error !== null) reject(error);
|
|
1681
1741
|
else if (response2 !== void 0) resolve(response2);
|
|
1682
1742
|
};
|
|
1683
|
-
socket.setTimeout(timeoutMs, () => finish(new HostRelayIpcError("relay_unavailable", "Host Relay IPC timed out.")));
|
|
1743
|
+
if (timeoutMs !== void 0) socket.setTimeout(timeoutMs, () => finish(new HostRelayIpcError("relay_unavailable", "Host Relay IPC timed out.")));
|
|
1744
|
+
if (signal?.aborted === true) {
|
|
1745
|
+
aborted();
|
|
1746
|
+
return;
|
|
1747
|
+
}
|
|
1748
|
+
signal?.addEventListener("abort", aborted, { once: true });
|
|
1684
1749
|
socket.once("error", () => finish(new HostRelayIpcError("relay_unavailable", "Host Relay IPC is unavailable.")));
|
|
1685
1750
|
socket.once("connect", () => socket.write(encoded));
|
|
1686
1751
|
socket.on("data", (chunk) => {
|
|
@@ -1733,6 +1798,34 @@ function decodeResponseBuffer(buffer) {
|
|
|
1733
1798
|
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}` }])}.`);
|
|
1734
1799
|
return decodeHostRelayIpcResponse(buffer);
|
|
1735
1800
|
}
|
|
1801
|
+
function decodeCurrentPromptResponseBuffer(buffer) {
|
|
1802
|
+
const value = decodeLengthPrefixedJson(buffer, HOST_RELAY_ADMISSION_RESPONSE_MAX_BYTES);
|
|
1803
|
+
if (value === null) return null;
|
|
1804
|
+
if (!record3(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");
|
|
1805
|
+
return { schema_version: HOST_RELAY_CURRENT_PROMPT_RESULT_SCHEMA, status: value.status };
|
|
1806
|
+
}
|
|
1807
|
+
function decodeLengthPrefixedJson(input, maximum) {
|
|
1808
|
+
if (input.length < HOST_RELAY_IPC_LENGTH_BYTES) return null;
|
|
1809
|
+
const length = input.readUInt32BE(0);
|
|
1810
|
+
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}`)}.`);
|
|
1811
|
+
if (input.length < length + HOST_RELAY_IPC_LENGTH_BYTES) return null;
|
|
1812
|
+
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}` }])}.`);
|
|
1813
|
+
try {
|
|
1814
|
+
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(input.subarray(HOST_RELAY_IPC_LENGTH_BYTES)));
|
|
1815
|
+
} catch {
|
|
1816
|
+
throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC message is invalid.");
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
function encodeLengthPrefixed(value) {
|
|
1820
|
+
const body = Buffer.from(JSON.stringify(value), "utf8");
|
|
1821
|
+
const output = Buffer.allocUnsafe(body.length + HOST_RELAY_IPC_LENGTH_BYTES);
|
|
1822
|
+
output.writeUInt32BE(body.length, 0);
|
|
1823
|
+
body.copy(output, HOST_RELAY_IPC_LENGTH_BYTES);
|
|
1824
|
+
return output;
|
|
1825
|
+
}
|
|
1826
|
+
function exactKeys2(value, keys) {
|
|
1827
|
+
return Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
1828
|
+
}
|
|
1736
1829
|
|
|
1737
1830
|
// host/invocation-context.ts
|
|
1738
1831
|
var HOST_INVOCATION_IDENTITY_KEYS = ["host_session_ref", "host_turn_ref", "host_source_ref"];
|
|
@@ -1741,7 +1834,7 @@ function invocationContextKey(identity) {
|
|
|
1741
1834
|
return cealRequestSha256({ host_source_ref: identity.host_source_ref, host_session_ref: identity.host_session_ref });
|
|
1742
1835
|
}
|
|
1743
1836
|
function hasHostInvocationIdentityKeys(value) {
|
|
1744
|
-
return
|
|
1837
|
+
return exactKeys3(value, HOST_INVOCATION_IDENTITY_KEYS);
|
|
1745
1838
|
}
|
|
1746
1839
|
function hasHostInvocationContextKeys(value, optional = []) {
|
|
1747
1840
|
return requiredKeys(value, HOST_INVOCATION_CONTEXT_REQUIRED_KEYS, optional);
|
|
@@ -1757,7 +1850,7 @@ function invocationContextFromTurn(identity, promptRef, expiresAt, descriptor) {
|
|
|
1757
1850
|
descriptor.validate(context);
|
|
1758
1851
|
return Object.freeze(context);
|
|
1759
1852
|
}
|
|
1760
|
-
function
|
|
1853
|
+
function exactKeys3(value, keys) {
|
|
1761
1854
|
const actual = Object.keys(value);
|
|
1762
1855
|
return actual.length === keys.length && keys.every((key) => Object.hasOwn(value, key)) && actual.every((key) => keys.includes(key));
|
|
1763
1856
|
}
|
|
@@ -1969,6 +2062,8 @@ var ClaudeHookAdapter = class {
|
|
|
1969
2062
|
this.store = new ClaudeOutboxStore(options.outbox_dir);
|
|
1970
2063
|
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
1971
2064
|
this.optionsSourceRef = options.host_source_ref ?? "claude-host:local";
|
|
2065
|
+
this.producerInstallationRef = options.producer_installation_ref;
|
|
2066
|
+
this.registerCurrentPrompt = options.register_current_prompt;
|
|
1972
2067
|
}
|
|
1973
2068
|
async handle(event, raw) {
|
|
1974
2069
|
let input;
|
|
@@ -1981,6 +2076,10 @@ var ClaudeHookAdapter = class {
|
|
|
1981
2076
|
const sessionRef = claudeLocalSessionRef(input.session_id);
|
|
1982
2077
|
const turnRef = input.prompt_id === void 0 ? void 0 : claudeLocalTurnRef(input.session_id, input.prompt_id);
|
|
1983
2078
|
const frames = mapFrames(input, occurredAt);
|
|
2079
|
+
if (input.hook_event_name === "UserPromptSubmit" && turnRef !== void 0 && this.producerInstallationRef !== void 0 && this.registerCurrentPrompt !== void 0) {
|
|
2080
|
+
const promptRef = hostProducerPromptRef(createHash3("sha256").update(input.prompt, "utf8").digest("hex"));
|
|
2081
|
+
await this.registerCurrentPrompt({ producer_id: "claude", producer_installation_ref: this.producerInstallationRef, local_session_ref: sessionRef, local_turn_ref: turnRef, prompt_ref: promptRef, current_prompt: input.prompt, context_expires_at: new Date(Date.parse(occurredAt) + 24 * 60 * 60 * 1e3).toISOString() });
|
|
2082
|
+
}
|
|
1984
2083
|
const batchRef = `claude-batch:${cealRequestSha256({ event, session_ref: sessionRef, turn_ref: turnRef ?? null, occurred_at: occurredAt, frames })}`;
|
|
1985
2084
|
const batch = { schema_version: CLAUDE_OUTBOX_SCHEMA, batch_ref: batchRef, hook_event: event, local_session_ref: sessionRef, ...turnRef === void 0 ? {} : { local_turn_ref: turnRef }, occurred_at: occurredAt, frames };
|
|
1986
2085
|
await this.store.put(batch);
|
|
@@ -2001,6 +2100,8 @@ var ClaudeHookAdapter = class {
|
|
|
2001
2100
|
await this.store.activateInvocationContext(identity, hostProducerPromptRef(promptValue.body_sha256), expiresAt, input.cwd);
|
|
2002
2101
|
}
|
|
2003
2102
|
optionsSourceRef;
|
|
2103
|
+
producerInstallationRef;
|
|
2104
|
+
registerCurrentPrompt;
|
|
2004
2105
|
};
|
|
2005
2106
|
function mapFrames(input, at) {
|
|
2006
2107
|
if (input.hook_event_name === "SessionStart") return sessionFrames(input, at);
|
|
@@ -2171,12 +2272,6 @@ async function drainClaudeProducerOnce(options) {
|
|
|
2171
2272
|
import { homedir } from "node:os";
|
|
2172
2273
|
import { join as join4 } from "node:path";
|
|
2173
2274
|
|
|
2174
|
-
// host/session-start-affordance.ts
|
|
2175
|
-
var HOST_ENTRY_AFFORDANCE = "When the user asks to use Ceal or provides a link to information that may be available through installed organizational capabilities, first run the bare `ceal` shell command with no arguments; treat that link as a candidate Ceal resource rather than a public web-search target, and let the current Profile capability result supply the exact next steps.";
|
|
2176
|
-
function hostSessionStartEntryAffordance(hostName) {
|
|
2177
|
-
return `${HOST_ENTRY_AFFORDANCE} This text is the Ceal ${hostName} Host's own SessionStart hook running in this ${hostName} session. The Host owns this session's Request identity, and the generic client authenticates each call automatically; follow the required_action_sequence returned by bare \`ceal\`. Never run \`ceal request create\`, and never type, guess, or reuse --host-session-ref, --host-turn-ref, --prompt-ref, or any other session or turn reference.`;
|
|
2178
|
-
}
|
|
2179
|
-
|
|
2180
2275
|
// host/producer-service.ts
|
|
2181
2276
|
import { constants } from "node:fs";
|
|
2182
2277
|
import { lstat as lstat2, open as open3 } from "node:fs/promises";
|
|
@@ -2357,10 +2452,6 @@ var CLAUDE_PRODUCER_DESCRIPTOR = {
|
|
|
2357
2452
|
|
|
2358
2453
|
// host/claude/src/claude-hook-runner.ts
|
|
2359
2454
|
var MAX_STDIN_BYTES = 256 * 1024;
|
|
2360
|
-
var CLAUDE_SESSION_START_ENTRY_AFFORDANCE = hostSessionStartEntryAffordance("Claude");
|
|
2361
|
-
function claudeSessionStartHookOutput() {
|
|
2362
|
-
return { suppressOutput: true, hookSpecificOutput: { hookEventName: "SessionStart", additionalContext: CLAUDE_SESSION_START_ENTRY_AFFORDANCE } };
|
|
2363
|
-
}
|
|
2364
2455
|
async function runClaudeHookFromStdin(event, stdin, options) {
|
|
2365
2456
|
return new ClaudeHookAdapter(options).handle(event, await readStdin(stdin));
|
|
2366
2457
|
}
|
|
@@ -2371,11 +2462,21 @@ function claudeHookEventFromArgs(args) {
|
|
|
2371
2462
|
async function runClaudeHookProcess(args, stdin, options) {
|
|
2372
2463
|
const event = claudeHookEventFromArgs(args);
|
|
2373
2464
|
if (event === null) return 0;
|
|
2374
|
-
|
|
2375
|
-
|
|
2465
|
+
try {
|
|
2466
|
+
const result = await runClaudeHookFromStdin(event, stdin, options);
|
|
2467
|
+
if (result.disposition === "rejected") writeClaudeHookDiagnostic(result);
|
|
2468
|
+
return 0;
|
|
2469
|
+
} catch (error) {
|
|
2470
|
+
writeClaudeHookDiagnostic({ event, disposition: "rejected", reason: error instanceof Error ? error.message.slice(0, 128) : "claude_hook_failed" });
|
|
2471
|
+
return 0;
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
function writeClaudeHookDiagnostic(result) {
|
|
2475
|
+
try {
|
|
2476
|
+
process.stderr.write(`${JSON.stringify({ schema_version: "ceal.claude_sessionstart_diagnostic.v1", event: result.event, disposition: result.disposition, ...result.reason === void 0 ? {} : { reason: result.reason } })}
|
|
2376
2477
|
`);
|
|
2377
|
-
|
|
2378
|
-
|
|
2478
|
+
} catch {
|
|
2479
|
+
}
|
|
2379
2480
|
}
|
|
2380
2481
|
async function runClaudeHookCli() {
|
|
2381
2482
|
const args = process.argv.slice(2);
|
|
@@ -2384,7 +2485,8 @@ async function runClaudeHookCli() {
|
|
|
2384
2485
|
}
|
|
2385
2486
|
async function installedClaudeHookRunnerOptions(args) {
|
|
2386
2487
|
const config = await readHostProducerConfig(CLAUDE_PRODUCER_DESCRIPTOR, parseHostProducerConfigFlag(args));
|
|
2387
|
-
const
|
|
2488
|
+
const port = new HostRelayCurrentPromptPort(config.relay_endpoint, config.ipc_timeout_ms);
|
|
2489
|
+
const options = { outbox_dir: config.outbox_dir, producer_installation_ref: config.producer_installation_ref, register_current_prompt: (input) => port.register(input) };
|
|
2388
2490
|
Object.defineProperty(options, "host_source_ref", { value: config.host_source_ref, enumerable: false });
|
|
2389
2491
|
return options;
|
|
2390
2492
|
}
|