@makaio/client-codex 1.0.0-dev-1783973359164 → 1.0.0-dev-1784806252593
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 +27 -7
- package/dist/{codex-client-session-service-B-E98xgY.mjs → codex-client-session-service-CTJ576Q4.mjs} +510 -32
- package/dist/definition.d.ts +7 -1
- package/dist/index.mjs +2 -2
- package/dist/runtime/codex-client-session-service.d.ts +40 -5
- package/dist/runtime/hook-response-composer.d.ts +15 -0
- package/dist/runtime/hook-response-contracts.d.ts +103 -0
- package/dist/runtime/namespace.d.ts +2 -2
- package/dist/runtime/package.d.ts +14 -0
- package/dist/runtime/package.mjs +22 -3
- package/dist/runtime/wiring.d.ts +2 -0
- package/dist/server.mjs +1 -1
- package/dist/{src-CXxq1vvn.mjs → src-DXsdjc9S.mjs} +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -41,13 +41,31 @@ is preserved without overwriting a concurrently changed canonical credential.
|
|
|
41
41
|
|
|
42
42
|
### Hook Events
|
|
43
43
|
|
|
44
|
-
| Hook Name | Framework Subject |
|
|
45
|
-
|
|
46
|
-
| `SessionStart` | `client.session.started` |
|
|
47
|
-
| `UserPromptSubmit` | `client.session.userPrompt.submitted` |
|
|
48
|
-
| `PreToolUse` | `client.session.tool.pre` |
|
|
49
|
-
| `PostToolUse` | `client.session.tool.post` |
|
|
50
|
-
| `Stop` | `client.session.turn.completed` |
|
|
44
|
+
| Hook Name | Framework Subject | Response Capabilities |
|
|
45
|
+
|-----------|------------------|----------------------|
|
|
46
|
+
| `SessionStart` | `client.session.started` | `context.append`, `openai.codex-hook-response.block` |
|
|
47
|
+
| `UserPromptSubmit` | `client.session.userPrompt.submitted` | `context.append`, `openai.codex-hook-response.block` |
|
|
48
|
+
| `PreToolUse` | `client.session.tool.pre` | `context.append`, `openai.codex-hook-response.block`, `openai.codex-hook-response.permission.deny`, `openai.codex-hook-response.input.update` |
|
|
49
|
+
| `PostToolUse` | `client.session.tool.post` | `context.append`, `openai.codex-hook-response.block` |
|
|
50
|
+
| `Stop` | `client.session.turn.completed` | `openai.codex-hook-response.block` |
|
|
51
|
+
|
|
52
|
+
All five events synchronously consume JSON output in the pinned upstream source tag `rust-v0.144.1`. Live CLI probes remain pending; the contract only exposes source-accepted fields.
|
|
53
|
+
|
|
54
|
+
### Hook Response Contract (`openai.codex-hook-response@1`)
|
|
55
|
+
|
|
56
|
+
The `./runtime` entrypoint registers a `ProviderContractCatalogEntry` that defines how contributions are validated for Codex:
|
|
57
|
+
|
|
58
|
+
| Field | Value |
|
|
59
|
+
|-------|-------|
|
|
60
|
+
| `contractId` | `openai.codex-hook-response` |
|
|
61
|
+
| `version` | `1.1.0` |
|
|
62
|
+
| `supportedInteractions` | `SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, `Stop` |
|
|
63
|
+
|
|
64
|
+
**Blockability:** All five events support blocking responses. SessionStart uses `continue: false` with `stopReason`; the other events use their event-specific block form.
|
|
65
|
+
|
|
66
|
+
**Composition:** Contributions are collected deterministically. Context appends render as `hookSpecificOutput.additionalContext`; blocks use `decision: "block"` with a non-empty reason; PreToolUse additionally supports `permissionDecision: "deny"` and an allowed `updatedInput` rewrite.
|
|
67
|
+
|
|
68
|
+
See [Client Hook Response Pipeline](../../docs/architecture/client-hook-responses.md) for the full architecture.
|
|
51
69
|
|
|
52
70
|
## Native Tools
|
|
53
71
|
|
|
@@ -106,6 +124,8 @@ Capabilities are sourced from `codexCapabilityMap` in `@makaio/contracts`, keepi
|
|
|
106
124
|
| `CodexClientSubjects` | namespace subjects | Typed bus subjects for `client:codex.*` |
|
|
107
125
|
| `CODEX_CLIENT_NAMESPACE` | `string` | Fully-qualified namespace domain (`'client:codex'`) |
|
|
108
126
|
| `normalizeCodexHook` | function | Normalizes a raw Codex hook payload into a `CodexNormalizedEvent` |
|
|
127
|
+
| `codexProviderContractCatalog` | `ProviderContractCatalogEntry` | Provider contract catalog entry for the `openai.codex-hook-response` contract |
|
|
128
|
+
| `composeCodexHookResponse` | function | Collects and renders source-verified synchronous hook responses |
|
|
109
129
|
|
|
110
130
|
### Server entrypoint (`./server`)
|
|
111
131
|
|
package/dist/{codex-client-session-service-B-E98xgY.mjs → codex-client-session-service-CTJ576Q4.mjs}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { codexCapabilityMap, createClientDefinition } from "@makaio/framework/contracts";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { AbsolutePathSchema, BinaryNotFoundError, ClientSubjects, ClientWiringApplyResponseSchema, ClientWiringListResponseSchema, ClientWiringRemoveResponseSchema, assertAbsoluteProjectDir, atomicModifyFile, buildHookCommand, createClientNamespace, deriveSessionEventDescriptors, pickNonEmptyString } from "@makaio/framework/clients";
|
|
3
|
+
import { AbsolutePathSchema, BinaryNotFoundError, ClientSubjects, ClientWiringApplyResponseSchema, ClientWiringListResponseSchema, ClientWiringRemoveResponseSchema, DEFAULT_HOOK_HANDLE_TIMEOUT_MS, NOOP_HOOK_HANDLE_RESPONSE, assertAbsoluteProjectDir, atomicModifyFile, buildClientCommand, buildHookCommand, collectContributions, createClientNamespace, deriveSessionEventDescriptors, pickNonEmptyString } from "@makaio/framework/clients";
|
|
4
4
|
import { MakaioBus, RequestError } from "@makaio/framework/bus";
|
|
5
5
|
import { BaseService } from "@makaio/framework/service-base";
|
|
6
6
|
import * as fs$1 from "node:fs/promises";
|
|
@@ -10,6 +10,7 @@ import path from "node:path";
|
|
|
10
10
|
import * as os$1 from "node:os";
|
|
11
11
|
import os from "node:os";
|
|
12
12
|
import { createHash, randomUUID } from "node:crypto";
|
|
13
|
+
import { isDeepStrictEqual } from "node:util";
|
|
13
14
|
import { ClientConfigPrimeSchema, SessionConfigSetupRequestSchema, SessionConfigSetupResponseSchema, SessionConfigTeardownRequestSchema, SessionConfigTeardownResponseSchema } from "@makaio/framework/contracts/client";
|
|
14
15
|
import { parse } from "smol-toml";
|
|
15
16
|
import { lock } from "proper-lockfile";
|
|
@@ -24,6 +25,12 @@ import { lock } from "proper-lockfile";
|
|
|
24
25
|
* capability taxonomy in a single canonical location.
|
|
25
26
|
* @packageDocumentation
|
|
26
27
|
*/
|
|
28
|
+
/** Namespaced Codex hook-response capabilities exposed to contributors. */
|
|
29
|
+
const CODEX_HOOK_RESPONSE_CAPABILITIES = Object.freeze({
|
|
30
|
+
block: "openai.codex-hook-response.block",
|
|
31
|
+
permissionDeny: "openai.codex-hook-response.permission.deny",
|
|
32
|
+
inputUpdate: "openai.codex-hook-response.input.update"
|
|
33
|
+
});
|
|
27
34
|
/**
|
|
28
35
|
* Static client definition for `@makaio/client-codex`.
|
|
29
36
|
*
|
|
@@ -101,23 +108,33 @@ const clientDefinition = createClientDefinition({
|
|
|
101
108
|
hookEvents: [
|
|
102
109
|
{
|
|
103
110
|
name: "SessionStart",
|
|
104
|
-
frameworkSubject: "client.session.started"
|
|
111
|
+
frameworkSubject: "client.session.started",
|
|
112
|
+
responseCapabilities: ["context.append", CODEX_HOOK_RESPONSE_CAPABILITIES.block]
|
|
105
113
|
},
|
|
106
114
|
{
|
|
107
115
|
name: "UserPromptSubmit",
|
|
108
|
-
frameworkSubject: "client.session.userPrompt.submitted"
|
|
116
|
+
frameworkSubject: "client.session.userPrompt.submitted",
|
|
117
|
+
responseCapabilities: ["context.append", CODEX_HOOK_RESPONSE_CAPABILITIES.block]
|
|
109
118
|
},
|
|
110
119
|
{
|
|
111
120
|
name: "PreToolUse",
|
|
112
|
-
frameworkSubject: "client.session.tool.pre"
|
|
121
|
+
frameworkSubject: "client.session.tool.pre",
|
|
122
|
+
responseCapabilities: [
|
|
123
|
+
"context.append",
|
|
124
|
+
CODEX_HOOK_RESPONSE_CAPABILITIES.block,
|
|
125
|
+
CODEX_HOOK_RESPONSE_CAPABILITIES.permissionDeny,
|
|
126
|
+
CODEX_HOOK_RESPONSE_CAPABILITIES.inputUpdate
|
|
127
|
+
]
|
|
113
128
|
},
|
|
114
129
|
{
|
|
115
130
|
name: "PostToolUse",
|
|
116
|
-
frameworkSubject: "client.session.tool.post"
|
|
131
|
+
frameworkSubject: "client.session.tool.post",
|
|
132
|
+
responseCapabilities: ["context.append", CODEX_HOOK_RESPONSE_CAPABILITIES.block]
|
|
117
133
|
},
|
|
118
134
|
{
|
|
119
135
|
name: "Stop",
|
|
120
|
-
frameworkSubject: "client.session.turn.completed"
|
|
136
|
+
frameworkSubject: "client.session.turn.completed",
|
|
137
|
+
responseCapabilities: [CODEX_HOOK_RESPONSE_CAPABILITIES.block]
|
|
121
138
|
}
|
|
122
139
|
]
|
|
123
140
|
}
|
|
@@ -993,17 +1010,7 @@ function extractToolName(payload) {
|
|
|
993
1010
|
* @returns Tool call ID string, or `undefined` when absent
|
|
994
1011
|
*/
|
|
995
1012
|
function extractToolCallId(payload) {
|
|
996
|
-
return pickNonEmptyString(payload, "
|
|
997
|
-
}
|
|
998
|
-
/**
|
|
999
|
-
* Extract optional tool execution outcome from a raw Codex post-tool payload.
|
|
1000
|
-
*
|
|
1001
|
-
* Codex reports whether the tool call succeeded under `success`.
|
|
1002
|
-
* @param payload - Raw hook payload object
|
|
1003
|
-
* @returns Boolean success flag, or `undefined` when absent
|
|
1004
|
-
*/
|
|
1005
|
-
function extractSuccess(payload) {
|
|
1006
|
-
return typeof payload["success"] === "boolean" ? payload["success"] : void 0;
|
|
1013
|
+
return pickNonEmptyString(payload, "tool_use_id");
|
|
1007
1014
|
}
|
|
1008
1015
|
/**
|
|
1009
1016
|
* Extract optional prompt text from a raw Codex user-prompt payload.
|
|
@@ -1068,14 +1075,410 @@ function normalizeCodexHook(raw, machineId) {
|
|
|
1068
1075
|
payload: {
|
|
1069
1076
|
...base,
|
|
1070
1077
|
toolName: extractToolName(raw.payload),
|
|
1071
|
-
toolCallId: extractToolCallId(raw.payload)
|
|
1072
|
-
success: extractSuccess(raw.payload)
|
|
1078
|
+
toolCallId: extractToolCallId(raw.payload)
|
|
1073
1079
|
}
|
|
1074
1080
|
};
|
|
1075
1081
|
default: return null;
|
|
1076
1082
|
}
|
|
1077
1083
|
}
|
|
1078
1084
|
|
|
1085
|
+
//#endregion
|
|
1086
|
+
//#region src/runtime/schemas.ts
|
|
1087
|
+
/**
|
|
1088
|
+
* Hook events emitted by Codex that map to the v1 observed-semantics set.
|
|
1089
|
+
*
|
|
1090
|
+
* These are the events the normalizer translates into `client.session.*` bus
|
|
1091
|
+
* emissions. Any event NOT listed here is left as raw `client:codex`
|
|
1092
|
+
* namespace data only.
|
|
1093
|
+
*/
|
|
1094
|
+
const CODEX_HOOK_SESSION_START = "SessionStart";
|
|
1095
|
+
const CODEX_HOOK_USER_PROMPT_SUBMIT = "UserPromptSubmit";
|
|
1096
|
+
const CODEX_HOOK_PRE_TOOL_USE = "PreToolUse";
|
|
1097
|
+
const CODEX_HOOK_POST_TOOL_USE = "PostToolUse";
|
|
1098
|
+
const CODEX_HOOK_STOP = "Stop";
|
|
1099
|
+
|
|
1100
|
+
//#endregion
|
|
1101
|
+
//#region src/runtime/hook-response-contracts.ts
|
|
1102
|
+
const CODEX_CLIENT_ID = "codex";
|
|
1103
|
+
const CODEX_CONTRACT_ID = "openai.codex-hook-response";
|
|
1104
|
+
const CODEX_CONTRACT_VERSION = "1.1.0";
|
|
1105
|
+
/**
|
|
1106
|
+
* Build a frozen Codex provider envelope.
|
|
1107
|
+
* @param effects - Provider-native effect record.
|
|
1108
|
+
* @returns A frozen Codex contribution envelope.
|
|
1109
|
+
*/
|
|
1110
|
+
function envelope(effects) {
|
|
1111
|
+
return Object.freeze({
|
|
1112
|
+
clientId: CODEX_CLIENT_ID,
|
|
1113
|
+
contractId: CODEX_CONTRACT_ID,
|
|
1114
|
+
effects: Object.freeze(effects)
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
/**
|
|
1118
|
+
* Builds a SessionStart context response.
|
|
1119
|
+
* @param value - Context appended when the session starts.
|
|
1120
|
+
* @returns A Codex SessionStart context envelope.
|
|
1121
|
+
*/
|
|
1122
|
+
function createCodexSessionStartContextEffect(value) {
|
|
1123
|
+
return envelope({ additionalContext: value });
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* Builds a SessionStart stop response.
|
|
1127
|
+
* @param reason - Reason for stopping session startup.
|
|
1128
|
+
* @returns A Codex SessionStart block envelope.
|
|
1129
|
+
*/
|
|
1130
|
+
function createCodexSessionStartBlockEffect(reason) {
|
|
1131
|
+
return envelope({
|
|
1132
|
+
decision: "block",
|
|
1133
|
+
reason
|
|
1134
|
+
});
|
|
1135
|
+
}
|
|
1136
|
+
/**
|
|
1137
|
+
* Builds a UserPromptSubmit context response.
|
|
1138
|
+
* @param value - Context appended to the submitted prompt.
|
|
1139
|
+
* @returns A Codex UserPromptSubmit context envelope.
|
|
1140
|
+
*/
|
|
1141
|
+
function createCodexUserPromptSubmitContextEffect(value) {
|
|
1142
|
+
return envelope({ additionalContext: value });
|
|
1143
|
+
}
|
|
1144
|
+
/**
|
|
1145
|
+
* Builds a UserPromptSubmit block response.
|
|
1146
|
+
* @param reason - Reason for blocking the submitted prompt.
|
|
1147
|
+
* @returns A Codex UserPromptSubmit block envelope.
|
|
1148
|
+
*/
|
|
1149
|
+
function createCodexUserPromptSubmitBlockEffect(reason) {
|
|
1150
|
+
return envelope({
|
|
1151
|
+
decision: "block",
|
|
1152
|
+
reason
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
/**
|
|
1156
|
+
* Builds a PreToolUse block response.
|
|
1157
|
+
* @param reason - Reason for blocking the tool invocation.
|
|
1158
|
+
* @returns A Codex PreToolUse block envelope.
|
|
1159
|
+
*/
|
|
1160
|
+
function createCodexPreToolUseBlockEffect(reason) {
|
|
1161
|
+
return envelope({
|
|
1162
|
+
decision: "block",
|
|
1163
|
+
reason
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Builds a PreToolUse deny-permission response.
|
|
1168
|
+
* @param reason - Reason for denying the tool invocation.
|
|
1169
|
+
* @returns A Codex PreToolUse permission-denial envelope.
|
|
1170
|
+
*/
|
|
1171
|
+
function createCodexPreToolUseDenyEffect(reason) {
|
|
1172
|
+
return envelope({
|
|
1173
|
+
permissionDecision: "deny",
|
|
1174
|
+
permissionDecisionReason: reason
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
/**
|
|
1178
|
+
* Builds additional model context for PreToolUse.
|
|
1179
|
+
* @param value - Context appended before the tool invocation.
|
|
1180
|
+
* @returns A Codex PreToolUse context envelope.
|
|
1181
|
+
*/
|
|
1182
|
+
function createCodexPreToolUseContextEffect(value) {
|
|
1183
|
+
return envelope({ additionalContext: value });
|
|
1184
|
+
}
|
|
1185
|
+
/**
|
|
1186
|
+
* Builds a PreToolUse allowed input update.
|
|
1187
|
+
* @param updatedInput - JSON value that replaces the native tool input.
|
|
1188
|
+
* @returns A Codex PreToolUse input-update envelope.
|
|
1189
|
+
*/
|
|
1190
|
+
function createCodexPreToolUseUpdateEffect(updatedInput) {
|
|
1191
|
+
return envelope({
|
|
1192
|
+
permissionDecision: "allow",
|
|
1193
|
+
updatedInput
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
/**
|
|
1197
|
+
* Builds a PostToolUse context response.
|
|
1198
|
+
* @param value - Context appended after the tool invocation.
|
|
1199
|
+
* @returns A Codex PostToolUse context envelope.
|
|
1200
|
+
*/
|
|
1201
|
+
function createCodexPostToolUseContextEffect(value) {
|
|
1202
|
+
return envelope({ additionalContext: value });
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* Builds a PostToolUse block response.
|
|
1206
|
+
* @param reason - Reason for blocking after the tool invocation.
|
|
1207
|
+
* @returns A Codex PostToolUse block envelope.
|
|
1208
|
+
*/
|
|
1209
|
+
function createCodexPostToolUseBlockEffect(reason) {
|
|
1210
|
+
return envelope({
|
|
1211
|
+
decision: "block",
|
|
1212
|
+
reason
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Builds a Stop block response.
|
|
1217
|
+
* @param reason - Reason for requesting another turn.
|
|
1218
|
+
* @returns A Codex Stop block envelope.
|
|
1219
|
+
*/
|
|
1220
|
+
function createCodexStopBlockEffect(reason) {
|
|
1221
|
+
return envelope({
|
|
1222
|
+
decision: "block",
|
|
1223
|
+
reason
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1226
|
+
const CODEX_RESPONSE_CAPABILITIES = Object.freeze([
|
|
1227
|
+
"context.append",
|
|
1228
|
+
CODEX_HOOK_RESPONSE_CAPABILITIES.block,
|
|
1229
|
+
CODEX_HOOK_RESPONSE_CAPABILITIES.permissionDeny,
|
|
1230
|
+
CODEX_HOOK_RESPONSE_CAPABILITIES.inputUpdate
|
|
1231
|
+
]);
|
|
1232
|
+
const CODEX_SUPPORTED_INTERACTIONS = Object.freeze([
|
|
1233
|
+
CODEX_HOOK_SESSION_START,
|
|
1234
|
+
CODEX_HOOK_USER_PROMPT_SUBMIT,
|
|
1235
|
+
CODEX_HOOK_PRE_TOOL_USE,
|
|
1236
|
+
CODEX_HOOK_POST_TOOL_USE,
|
|
1237
|
+
CODEX_HOOK_STOP,
|
|
1238
|
+
...CODEX_RESPONSE_CAPABILITIES
|
|
1239
|
+
]);
|
|
1240
|
+
const CODEX_INTERACTION_BLOCKABILITY = Object.freeze(CODEX_SUPPORTED_INTERACTIONS.map((interaction) => Object.freeze({
|
|
1241
|
+
interaction,
|
|
1242
|
+
blockable: interaction === CODEX_HOOK_RESPONSE_CAPABILITIES.block || interaction === CODEX_HOOK_RESPONSE_CAPABILITIES.permissionDeny || interaction === CODEX_HOOK_RESPONSE_CAPABILITIES.inputUpdate || interaction === "SessionStart" || interaction === "UserPromptSubmit" || interaction === "PreToolUse" || interaction === "PostToolUse" || interaction === "Stop"
|
|
1243
|
+
})));
|
|
1244
|
+
/**
|
|
1245
|
+
* Determine whether a runtime value is losslessly representable as JSON.
|
|
1246
|
+
* @param value - Runtime value to inspect.
|
|
1247
|
+
* @param ancestors - Objects already visited on the current recursion path.
|
|
1248
|
+
* @returns Whether the value is an acyclic JSON value.
|
|
1249
|
+
*/
|
|
1250
|
+
function isJsonValue(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
1251
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
1252
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
1253
|
+
if (typeof value !== "object") return false;
|
|
1254
|
+
if (ancestors.has(value)) return false;
|
|
1255
|
+
const nextAncestors = new Set(ancestors).add(value);
|
|
1256
|
+
if (Array.isArray(value)) return value.every((entry) => isJsonValue(entry, nextAncestors));
|
|
1257
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return false;
|
|
1258
|
+
return Object.values(value).every((entry) => isJsonValue(entry, nextAncestors));
|
|
1259
|
+
}
|
|
1260
|
+
const EVENT_EFFECTS = Object.freeze({
|
|
1261
|
+
[CODEX_HOOK_SESSION_START]: new Set(["context", "block"]),
|
|
1262
|
+
[CODEX_HOOK_USER_PROMPT_SUBMIT]: new Set(["context", "block"]),
|
|
1263
|
+
[CODEX_HOOK_PRE_TOOL_USE]: new Set([
|
|
1264
|
+
"context",
|
|
1265
|
+
"block",
|
|
1266
|
+
"deny",
|
|
1267
|
+
"update"
|
|
1268
|
+
]),
|
|
1269
|
+
[CODEX_HOOK_POST_TOOL_USE]: new Set(["context", "block"]),
|
|
1270
|
+
[CODEX_HOOK_STOP]: new Set(["block"])
|
|
1271
|
+
});
|
|
1272
|
+
/**
|
|
1273
|
+
* Classify an exact provider-native Codex effects record.
|
|
1274
|
+
* @param effects - Provider-native effects to classify.
|
|
1275
|
+
* @returns The recognized effect kind, or `undefined` for an invalid shape.
|
|
1276
|
+
*/
|
|
1277
|
+
function classifyEffects(effects) {
|
|
1278
|
+
const keys = Object.keys(effects);
|
|
1279
|
+
if (keys.length === 1 && typeof effects.additionalContext === "string") return "context";
|
|
1280
|
+
if (keys.length !== 2) return void 0;
|
|
1281
|
+
if (effects.decision === "block" && typeof effects.reason === "string" && effects.reason.trim() !== "") return "block";
|
|
1282
|
+
if (effects.permissionDecision === "deny" && typeof effects.permissionDecisionReason === "string" && effects.permissionDecisionReason.trim() !== "") return "deny";
|
|
1283
|
+
if (effects.permissionDecision === "allow" && "updatedInput" in effects && effects.updatedInput !== null && isJsonValue(effects.updatedInput)) return "update";
|
|
1284
|
+
}
|
|
1285
|
+
/**
|
|
1286
|
+
* Extract and validate the provider-native effects record.
|
|
1287
|
+
* @param output - Contributor response to inspect.
|
|
1288
|
+
* @returns The effects record, `undefined` for an empty response, or a diagnostic string.
|
|
1289
|
+
*/
|
|
1290
|
+
function extractEffects(output) {
|
|
1291
|
+
if (output === void 0 || output === null) return void 0;
|
|
1292
|
+
if (typeof output !== "object" || Array.isArray(output)) return "Contributor response must be an object or undefined";
|
|
1293
|
+
const response = output;
|
|
1294
|
+
if (Object.keys(response).some((key) => key !== "providerEnvelope")) return "Codex provider responses may contain only providerEnvelope";
|
|
1295
|
+
if (response.providerEnvelope === void 0) return void 0;
|
|
1296
|
+
if (typeof response.providerEnvelope !== "object" || response.providerEnvelope === null || Array.isArray(response.providerEnvelope)) return "providerEnvelope must be an object";
|
|
1297
|
+
const envelope = response.providerEnvelope;
|
|
1298
|
+
const unsupportedField = Object.keys(envelope).find((key) => key !== "clientId" && key !== "contractId" && key !== "effects");
|
|
1299
|
+
if (unsupportedField !== void 0) return `Unsupported Codex providerEnvelope field '${unsupportedField}'`;
|
|
1300
|
+
if (envelope.clientId !== "codex" || envelope.contractId !== "openai.codex-hook-response") return "providerEnvelope clientId and contractId must target the Codex contract";
|
|
1301
|
+
if (typeof envelope.effects !== "object" || envelope.effects === null || Array.isArray(envelope.effects)) return "providerEnvelope.effects must be an object";
|
|
1302
|
+
return envelope.effects;
|
|
1303
|
+
}
|
|
1304
|
+
/**
|
|
1305
|
+
* Validate a provider response against the event-specific Codex parser surface.
|
|
1306
|
+
* @param output - Contributor response to validate.
|
|
1307
|
+
* @param ctx - Current provider validation context.
|
|
1308
|
+
* @returns `true` when valid, otherwise a diagnostic string.
|
|
1309
|
+
*/
|
|
1310
|
+
function validateCodexContractOutput(output, ctx) {
|
|
1311
|
+
const effects = extractEffects(output);
|
|
1312
|
+
if (effects === void 0) return true;
|
|
1313
|
+
if (typeof effects === "string") return effects;
|
|
1314
|
+
const effectKind = classifyEffects(effects);
|
|
1315
|
+
if (effectKind !== void 0 && EVENT_EFFECTS[String(ctx.eventName)]?.has(effectKind)) return true;
|
|
1316
|
+
return `Unsupported Codex response effects for '${String(ctx.eventName)}'`;
|
|
1317
|
+
}
|
|
1318
|
+
const codexProviderContractCatalog = Object.freeze({
|
|
1319
|
+
clientId: CODEX_CLIENT_ID,
|
|
1320
|
+
contractId: CODEX_CONTRACT_ID,
|
|
1321
|
+
version: CODEX_CONTRACT_VERSION,
|
|
1322
|
+
supportedInteractions: CODEX_SUPPORTED_INTERACTIONS,
|
|
1323
|
+
blockability: CODEX_INTERACTION_BLOCKABILITY,
|
|
1324
|
+
validate: validateCodexContractOutput
|
|
1325
|
+
});
|
|
1326
|
+
|
|
1327
|
+
//#endregion
|
|
1328
|
+
//#region src/runtime/hook-response-composer.ts
|
|
1329
|
+
/** Deterministic Codex 0.144.1 hook-response composition. @packageDocumentation */
|
|
1330
|
+
/**
|
|
1331
|
+
* Resolve the declared response capabilities for one Codex event.
|
|
1332
|
+
* @param eventName - Native Codex hook event name.
|
|
1333
|
+
* @returns Declared capabilities for the event.
|
|
1334
|
+
*/
|
|
1335
|
+
function capabilities(eventName) {
|
|
1336
|
+
return clientDefinition.runtimeCapabilities.hookEvents.find((event) => event.name === eventName)?.responseCapabilities ?? [];
|
|
1337
|
+
}
|
|
1338
|
+
const FIRST_BLOCK_EVENTS = new Set([
|
|
1339
|
+
CODEX_HOOK_SESSION_START,
|
|
1340
|
+
CODEX_HOOK_USER_PROMPT_SUBMIT,
|
|
1341
|
+
CODEX_HOOK_PRE_TOOL_USE
|
|
1342
|
+
]);
|
|
1343
|
+
/**
|
|
1344
|
+
* Collect one provider-native effect into its composition bucket.
|
|
1345
|
+
* @param collected - Mutable composition buckets for this request.
|
|
1346
|
+
* @param effect - Provider contribution envelope to inspect.
|
|
1347
|
+
* @param supportsContext - Whether the current event accepts additional context.
|
|
1348
|
+
*/
|
|
1349
|
+
function collectProviderEffect(collected, effect, supportsContext) {
|
|
1350
|
+
if (effect.clientId !== "codex" || effect.contractId !== "openai.codex-hook-response") return;
|
|
1351
|
+
const value = effect.effects;
|
|
1352
|
+
if (supportsContext && typeof value.additionalContext === "string") collected.contexts.push(value.additionalContext);
|
|
1353
|
+
if (value.decision === "block" && typeof value.reason === "string") collected.blocks.push(value.reason);
|
|
1354
|
+
if (value.permissionDecision === "deny" && typeof value.permissionDecisionReason === "string") collected.denyReasons.push(value.permissionDecisionReason);
|
|
1355
|
+
if (value.permissionDecision === "allow" && "updatedInput" in value) collected.updates.push(value.updatedInput);
|
|
1356
|
+
}
|
|
1357
|
+
/**
|
|
1358
|
+
* Collect canonical and provider-native effects for one event.
|
|
1359
|
+
* @param eventName - Native Codex hook event name.
|
|
1360
|
+
* @param effects - Deterministically ordered effects to collect.
|
|
1361
|
+
* @returns Effects grouped by native output behavior.
|
|
1362
|
+
*/
|
|
1363
|
+
function collectEffects(eventName, effects) {
|
|
1364
|
+
const collected = {
|
|
1365
|
+
contexts: [],
|
|
1366
|
+
blocks: [],
|
|
1367
|
+
denyReasons: [],
|
|
1368
|
+
updates: []
|
|
1369
|
+
};
|
|
1370
|
+
const supportsContext = capabilities(eventName).includes("context.append");
|
|
1371
|
+
for (const effect of effects) if ("kind" in effect) {
|
|
1372
|
+
if (supportsContext && effect.kind === "context.append") collected.contexts.push(effect.value);
|
|
1373
|
+
} else collectProviderEffect(collected, effect, supportsContext);
|
|
1374
|
+
return collected;
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* Select the native block reason according to the pinned event rule.
|
|
1378
|
+
* @param eventName - Native Codex hook event name.
|
|
1379
|
+
* @param blocks - Ordered block reasons.
|
|
1380
|
+
* @returns The selected reason, or `undefined` when no block was contributed.
|
|
1381
|
+
*/
|
|
1382
|
+
function selectBlockReason(eventName, blocks) {
|
|
1383
|
+
if (blocks.length === 0) return void 0;
|
|
1384
|
+
return FIRST_BLOCK_EVENTS.has(eventName) ? blocks[0] : blocks.join("\n\n");
|
|
1385
|
+
}
|
|
1386
|
+
/**
|
|
1387
|
+
* Serialize a native Codex response.
|
|
1388
|
+
* @param body - Native JSON response body.
|
|
1389
|
+
* @returns Hook handle response with the serialized body on stdout.
|
|
1390
|
+
*/
|
|
1391
|
+
function serialize(body) {
|
|
1392
|
+
return {
|
|
1393
|
+
exitCode: 0,
|
|
1394
|
+
stdout: JSON.stringify(body),
|
|
1395
|
+
stderr: ""
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* Render a blocking native response outside PreToolUse.
|
|
1400
|
+
* @param eventName - Native Codex hook event name.
|
|
1401
|
+
* @param reason - Selected block reason.
|
|
1402
|
+
* @param hookSpecificOutput - Event-specific context output.
|
|
1403
|
+
* @param hasContext - Whether context was contributed.
|
|
1404
|
+
* @returns Blocking native response.
|
|
1405
|
+
*/
|
|
1406
|
+
function renderBlock(eventName, reason, hookSpecificOutput, hasContext) {
|
|
1407
|
+
const context = hasContext ? { hookSpecificOutput } : {};
|
|
1408
|
+
if (eventName === "SessionStart") return serialize({
|
|
1409
|
+
continue: false,
|
|
1410
|
+
stopReason: reason,
|
|
1411
|
+
...context
|
|
1412
|
+
});
|
|
1413
|
+
return serialize({
|
|
1414
|
+
decision: "block",
|
|
1415
|
+
reason,
|
|
1416
|
+
...context
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
/**
|
|
1420
|
+
* Render the precedence-sensitive PreToolUse response.
|
|
1421
|
+
* @param collected - Effects grouped by native behavior.
|
|
1422
|
+
* @param blockReason - Selected block reason, if any.
|
|
1423
|
+
* @param hookSpecificOutput - Mutable native event-specific output.
|
|
1424
|
+
* @returns A terminal response, or `undefined` when only context remains to render.
|
|
1425
|
+
*/
|
|
1426
|
+
function renderPreToolUse(collected, blockReason, hookSpecificOutput) {
|
|
1427
|
+
if (blockReason !== void 0) return serialize({
|
|
1428
|
+
decision: "block",
|
|
1429
|
+
reason: blockReason,
|
|
1430
|
+
...collected.contexts.length ? { hookSpecificOutput } : {}
|
|
1431
|
+
});
|
|
1432
|
+
if (collected.denyReasons.length > 0) {
|
|
1433
|
+
hookSpecificOutput.permissionDecision = "deny";
|
|
1434
|
+
hookSpecificOutput.permissionDecisionReason = collected.denyReasons.join("\n");
|
|
1435
|
+
} else if (collected.updates.length > 0) {
|
|
1436
|
+
hookSpecificOutput.permissionDecision = "allow";
|
|
1437
|
+
hookSpecificOutput.updatedInput = collected.updates[0];
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
/**
|
|
1441
|
+
* Reduce ordered effects into one provider-valid Codex response.
|
|
1442
|
+
* @param eventName - Native Codex hook event name.
|
|
1443
|
+
* @param effects - Deterministically ordered effects to reduce.
|
|
1444
|
+
* @returns The terminal native hook response.
|
|
1445
|
+
*/
|
|
1446
|
+
function output(eventName, effects) {
|
|
1447
|
+
const collected = collectEffects(eventName, effects);
|
|
1448
|
+
if (collected.updates.length > 1 && collected.updates.some((candidate) => !isDeepStrictEqual(candidate, collected.updates[0]))) throw new Error("Conflicting Codex PreToolUse input.update effects");
|
|
1449
|
+
const hookSpecificOutput = { hookEventName: eventName };
|
|
1450
|
+
if (collected.contexts.length) hookSpecificOutput.additionalContext = collected.contexts.join("\n");
|
|
1451
|
+
const blockReason = selectBlockReason(eventName, collected.blocks);
|
|
1452
|
+
if (eventName === "PreToolUse") {
|
|
1453
|
+
const response = renderPreToolUse(collected, blockReason, hookSpecificOutput);
|
|
1454
|
+
if (response !== void 0) return response;
|
|
1455
|
+
} else if (blockReason !== void 0) return renderBlock(eventName, blockReason, hookSpecificOutput, collected.contexts.length > 0);
|
|
1456
|
+
if (!collected.contexts.length && collected.denyReasons.length === 0 && collected.updates.length === 0) return NOOP_HOOK_HANDLE_RESPONSE;
|
|
1457
|
+
return serialize({ hookSpecificOutput });
|
|
1458
|
+
}
|
|
1459
|
+
/**
|
|
1460
|
+
* Compose one terminal Codex native hook response.
|
|
1461
|
+
* @param registry - Active response contributor registry.
|
|
1462
|
+
* @param payload - Normalized native hook payload.
|
|
1463
|
+
* @param options - Request deadline, cancellation, and diagnostics hooks.
|
|
1464
|
+
* @returns The composed native response envelope.
|
|
1465
|
+
*/
|
|
1466
|
+
async function composeCodexHookResponse(registry, payload, options) {
|
|
1467
|
+
const snapshot = registry.snapshot(CODEX_CLIENT_ID, CODEX_CONTRACT_ID, payload.eventName, capabilities(payload.eventName));
|
|
1468
|
+
if (!snapshot.length) return NOOP_HOOK_HANDLE_RESPONSE;
|
|
1469
|
+
const result = await collectContributions(snapshot, CODEX_CLIENT_ID, options?.deadline, options?.signal, payload.eventName, payload.payload, codexProviderContractCatalog);
|
|
1470
|
+
if (result.diagnostics.length) options?.onDiagnostics?.(result.diagnostics);
|
|
1471
|
+
if (result.closedFailure) return output(payload.eventName, [{
|
|
1472
|
+
clientId: CODEX_CLIENT_ID,
|
|
1473
|
+
contractId: CODEX_CONTRACT_ID,
|
|
1474
|
+
effects: {
|
|
1475
|
+
decision: "block",
|
|
1476
|
+
reason: result.closedFailure.detail
|
|
1477
|
+
}
|
|
1478
|
+
}]);
|
|
1479
|
+
return output(payload.eventName, result.outcomes.flatMap((outcome) => outcome.effects ?? []));
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1079
1482
|
//#endregion
|
|
1080
1483
|
//#region src/runtime/namespace.ts
|
|
1081
1484
|
/**
|
|
@@ -2167,6 +2570,8 @@ function mergeOperationErrors(existing, next, message) {
|
|
|
2167
2570
|
* the `commandContains` filter in {@link removeCodexWiring}.
|
|
2168
2571
|
*/
|
|
2169
2572
|
const CODEX_HOOK_COMMAND_SENTINEL = "hook received codex";
|
|
2573
|
+
/** Sentinel for synchronous Codex hook responses. */
|
|
2574
|
+
const CODEX_HOOK_HANDLE_COMMAND_SENTINEL = "hook handle codex";
|
|
2170
2575
|
/**
|
|
2171
2576
|
* Descriptors for all session-events hooks derived from the client definition.
|
|
2172
2577
|
*
|
|
@@ -2188,8 +2593,8 @@ const SESSION_EVENTS = deriveSessionEventDescriptors(clientDefinition);
|
|
|
2188
2593
|
*/
|
|
2189
2594
|
async function buildCodexWiringList(settings, makaioCommand, projectDir) {
|
|
2190
2595
|
const { effective } = await settings.listHooks(projectDir !== void 0 ? { projectDir } : {});
|
|
2191
|
-
return { entries: SESSION_EVENTS.map(({ eventName }) => {
|
|
2192
|
-
const command =
|
|
2596
|
+
return { entries: SESSION_EVENTS.map(({ eventName, mode }) => {
|
|
2597
|
+
const command = buildModeCommand(makaioCommand, eventName, mode);
|
|
2193
2598
|
return {
|
|
2194
2599
|
group: "session-events",
|
|
2195
2600
|
name: eventName,
|
|
@@ -2218,9 +2623,9 @@ async function applyCodexWiring(settings, scope, makaioCommand, projectDir) {
|
|
|
2218
2623
|
let skipped = 0;
|
|
2219
2624
|
const { perScope } = await settings.listHooks(projectDir !== void 0 ? { projectDir } : {});
|
|
2220
2625
|
const scopeHooks = perScope.find((s) => s.scope === scope)?.hooks ?? [];
|
|
2221
|
-
for (const { eventName } of SESSION_EVENTS) {
|
|
2222
|
-
const sentinel = `${CODEX_HOOK_COMMAND_SENTINEL} ${eventName}`;
|
|
2223
|
-
const command =
|
|
2626
|
+
for (const { eventName, mode } of SESSION_EVENTS) {
|
|
2627
|
+
const sentinel = `${mode === "request" ? CODEX_HOOK_HANDLE_COMMAND_SENTINEL : CODEX_HOOK_COMMAND_SENTINEL} ${eventName}`;
|
|
2628
|
+
const command = buildModeCommand(makaioCommand, eventName, mode);
|
|
2224
2629
|
const existingEntry = scopeHooks.find((entry) => entry.event === eventName && entry.command.includes(sentinel));
|
|
2225
2630
|
if (existingEntry !== void 0) {
|
|
2226
2631
|
if (existingEntry.command === command) {
|
|
@@ -2261,17 +2666,33 @@ async function applyCodexWiring(settings, scope, makaioCommand, projectDir) {
|
|
|
2261
2666
|
*/
|
|
2262
2667
|
async function removeCodexWiring(settings, scope, projectDir) {
|
|
2263
2668
|
let removed = 0;
|
|
2264
|
-
for (const { eventName } of SESSION_EVENTS) {
|
|
2669
|
+
for (const { eventName } of SESSION_EVENTS) for (const sentinel of [CODEX_HOOK_COMMAND_SENTINEL, CODEX_HOOK_HANDLE_COMMAND_SENTINEL]) {
|
|
2265
2670
|
const result = await settings.removeHook({
|
|
2266
2671
|
scope,
|
|
2267
2672
|
event: eventName,
|
|
2268
|
-
match: { commandContains: `${
|
|
2673
|
+
match: { commandContains: `${sentinel} ${eventName}` },
|
|
2269
2674
|
...projectDir !== void 0 ? { projectDir } : {}
|
|
2270
2675
|
});
|
|
2271
2676
|
removed += result.removed;
|
|
2272
2677
|
}
|
|
2273
2678
|
return { removed };
|
|
2274
2679
|
}
|
|
2680
|
+
/**
|
|
2681
|
+
* Build the managed command for one capability-derived hook mode.
|
|
2682
|
+
* @param makaioCommand - Makaio CLI executable.
|
|
2683
|
+
* @param eventName - Native Codex event name.
|
|
2684
|
+
* @param mode - Capability-derived transport mode.
|
|
2685
|
+
* @returns Shell-safe managed hook command.
|
|
2686
|
+
*/
|
|
2687
|
+
function buildModeCommand(makaioCommand, eventName, mode) {
|
|
2688
|
+
return mode === "request" ? buildClientCommand(makaioCommand, [
|
|
2689
|
+
"--no-launch",
|
|
2690
|
+
...CODEX_HOOK_HANDLE_COMMAND_SENTINEL.split(" "),
|
|
2691
|
+
eventName,
|
|
2692
|
+
"--timeout",
|
|
2693
|
+
String(DEFAULT_HOOK_HANDLE_TIMEOUT_MS)
|
|
2694
|
+
]) : buildHookCommand(makaioCommand, CODEX_HOOK_COMMAND_SENTINEL, eventName, void 0, ["--debounce-failure"]);
|
|
2695
|
+
}
|
|
2275
2696
|
|
|
2276
2697
|
//#endregion
|
|
2277
2698
|
//#region src/runtime/codex-client-session-service.ts
|
|
@@ -2333,6 +2754,16 @@ var CodexClientSessionService = class extends BaseService {
|
|
|
2333
2754
|
*/
|
|
2334
2755
|
managedAdapterSessionIds = /* @__PURE__ */ new Set();
|
|
2335
2756
|
/**
|
|
2757
|
+
* Optional provider contract registry for registering and unregistering
|
|
2758
|
+
* the Codex hook response contract during the service lifecycle.
|
|
2759
|
+
*
|
|
2760
|
+
* When `undefined`, contract registration is skipped — this allows
|
|
2761
|
+
* lightweight test construction without requiring a full clients-core
|
|
2762
|
+
* dependency.
|
|
2763
|
+
*/
|
|
2764
|
+
providerContractRegistry;
|
|
2765
|
+
hookResponseRegistry;
|
|
2766
|
+
/**
|
|
2336
2767
|
* Creates a new Codex client session service.
|
|
2337
2768
|
* @param bus - Bus instance used for subscribing and emitting events
|
|
2338
2769
|
* @param settings - Optional {@link CodexClientSettings} instance for tests
|
|
@@ -2342,22 +2773,37 @@ var CodexClientSessionService = class extends BaseService {
|
|
|
2342
2773
|
* caller-supplied from the extension context. Omit in tests or when the
|
|
2343
2774
|
* identity is unavailable.
|
|
2344
2775
|
* @param sessionConfigHandler - Optional native auth lease handler override.
|
|
2776
|
+
* @param providerContractRegistry - Optional provider contract registry
|
|
2777
|
+
* from clients-core for registering the Codex hook response contract.
|
|
2778
|
+
* Omit in tests that do not exercise the response pipeline.
|
|
2779
|
+
* @param hookResponseRegistry - Optional contributor registry used by the terminal composer.
|
|
2345
2780
|
*/
|
|
2346
|
-
constructor(bus = MakaioBus, settings, machineId, sessionConfigHandler = new CodexSessionConfigHandler()) {
|
|
2781
|
+
constructor(bus = MakaioBus, settings, machineId, sessionConfigHandler = new CodexSessionConfigHandler(), providerContractRegistry, hookResponseRegistry) {
|
|
2347
2782
|
super(bus);
|
|
2348
2783
|
this.settingsOverride = settings;
|
|
2349
2784
|
this.machineId = machineId;
|
|
2350
2785
|
this.sessionConfigHandler = sessionConfigHandler;
|
|
2786
|
+
this.providerContractRegistry = providerContractRegistry;
|
|
2787
|
+
this.hookResponseRegistry = hookResponseRegistry;
|
|
2351
2788
|
}
|
|
2352
2789
|
/**
|
|
2353
|
-
* Register the raw hook ingress handler,
|
|
2354
|
-
*
|
|
2355
|
-
*
|
|
2790
|
+
* Register the raw hook ingress handler, the `hook.handle` request handler,
|
|
2791
|
+
* config management request handlers, wiring management request handlers,
|
|
2792
|
+
* the config-prime lifecycle handler, and the session config
|
|
2793
|
+
* setup/teardown handlers on the bus.
|
|
2356
2794
|
*
|
|
2357
2795
|
* Also subscribes to `client.runtime.started` to track adapter-managed
|
|
2358
2796
|
* sessions for the {@link handleHookReceived} suppression gate.
|
|
2797
|
+
*
|
|
2798
|
+
* When a {@link ClientHookProviderContractRegistry} was supplied at
|
|
2799
|
+
* construction time, the Codex provider contract is registered so that
|
|
2800
|
+
* contributors can be validated against it during extension activation.
|
|
2359
2801
|
*/
|
|
2360
2802
|
onInit() {
|
|
2803
|
+
if (this.providerContractRegistry !== void 0) {
|
|
2804
|
+
this.providerContractRegistry.registerProviderContract("codex.runtime", codexProviderContractCatalog);
|
|
2805
|
+
this.addCleanup(() => this.providerContractRegistry?.unregisterProviderContract("codex.runtime", codexProviderContractCatalog.clientId, codexProviderContractCatalog.contractId));
|
|
2806
|
+
}
|
|
2361
2807
|
this.registerHandler(ClientSubjects.runtime.started, ({ payload }) => {
|
|
2362
2808
|
this.handleRuntimeStarted(payload);
|
|
2363
2809
|
});
|
|
@@ -2367,6 +2813,7 @@ var CodexClientSessionService = class extends BaseService {
|
|
|
2367
2813
|
this.registerHandler(CodexClientSubjects.hook.received, async ({ payload }) => {
|
|
2368
2814
|
await this.handleHookReceived(payload);
|
|
2369
2815
|
});
|
|
2816
|
+
this.registerHookHandleHandler();
|
|
2370
2817
|
this.registerHandler(CodexClientSubjects.config.hooks.list, async (ctx) => {
|
|
2371
2818
|
ctx.setResult(await (await this.createSettings()).listHooks(ctx.payload));
|
|
2372
2819
|
});
|
|
@@ -2401,13 +2848,44 @@ var CodexClientSessionService = class extends BaseService {
|
|
|
2401
2848
|
});
|
|
2402
2849
|
}
|
|
2403
2850
|
/**
|
|
2404
|
-
* Clear the adapter-managed session ID set on teardown.
|
|
2851
|
+
* Clear the adapter-managed session ID set and config cache on teardown.
|
|
2852
|
+
*
|
|
2853
|
+
* Provider contract unregistration is handled via {@link addCleanup} in
|
|
2854
|
+
* {@link onInit}, so it runs automatically during the base-class destroy
|
|
2855
|
+
* sequence alongside handler unsubscription.
|
|
2405
2856
|
*/
|
|
2406
2857
|
onDestroy() {
|
|
2407
2858
|
this.managedAdapterSessionIds.clear();
|
|
2408
2859
|
this.cachedConfigDir = void 0;
|
|
2409
2860
|
}
|
|
2410
2861
|
/**
|
|
2862
|
+
* Register the `hook.handle` request handler.
|
|
2863
|
+
*
|
|
2864
|
+
* The handler receives request-mode hook payloads and returns a
|
|
2865
|
+
* {@link ClientHookHandleResponse} composed by
|
|
2866
|
+
* {@link composeCodexHookResponse}. The pinned Codex `0.144.1` source
|
|
2867
|
+
* parses synchronous responses for all five declared events.
|
|
2868
|
+
*
|
|
2869
|
+
* Extracted from {@link onInit} to keep the init method concise.
|
|
2870
|
+
*/
|
|
2871
|
+
registerHookHandleHandler() {
|
|
2872
|
+
this.registerHandler(CodexClientSubjects.hook.handle, (ctx) => {
|
|
2873
|
+
if (!this.hookResponseRegistry) {
|
|
2874
|
+
ctx.setResult({
|
|
2875
|
+
exitCode: 0,
|
|
2876
|
+
stdout: "",
|
|
2877
|
+
stderr: ""
|
|
2878
|
+
});
|
|
2879
|
+
return;
|
|
2880
|
+
}
|
|
2881
|
+
return composeCodexHookResponse(this.hookResponseRegistry, ctx.payload, {
|
|
2882
|
+
deadline: ctx.deadline,
|
|
2883
|
+
signal: ctx.signal,
|
|
2884
|
+
onDiagnostics: (diagnostics) => diagnostics.forEach((diagnostic) => console.warn(`[CodexClientSessionService] Hook contributor '${diagnostic.contributorId}': ${diagnostic.message}`))
|
|
2885
|
+
}).then((response) => ctx.setResult(response));
|
|
2886
|
+
});
|
|
2887
|
+
}
|
|
2888
|
+
/**
|
|
2411
2889
|
* Create a settings delegate for the active Codex config root.
|
|
2412
2890
|
* @returns Settings instance bound to the managed config dir when available.
|
|
2413
2891
|
*/
|
|
@@ -2550,4 +3028,4 @@ function isResolveBinaryMissingGlobalBinary(error) {
|
|
|
2550
3028
|
}
|
|
2551
3029
|
|
|
2552
3030
|
//#endregion
|
|
2553
|
-
export {
|
|
3031
|
+
export { CodexConfigHooksAddResponseSchema as A, CodexScopeHookRecordSchema as B, createCodexStopBlockEffect as C, CodexWiringSchemas as D, normalizeCodexHook as E, CodexConfigSchemas as F, CODEX_HOOK_RESPONSE_CAPABILITIES as H, CodexHookEntrySchema as I, CodexNativeCommandHookSchema as L, CodexConfigHooksListResponseSchema as M, CodexConfigHooksRemoveRequestSchema as N, AbsolutePathSchema as O, CodexConfigHooksRemoveResponseSchema as P, CodexNativeHookMatcherGroupSchema as R, createCodexSessionStartContextEffect as S, createCodexUserPromptSubmitContextEffect as T, clientDefinition as U, CodexScopeSchema as V, createCodexPreToolUseBlockEffect as _, CODEX_CLIENT_NAMESPACE as a, createCodexPreToolUseUpdateEffect as b, CODEX_CLIENT_ID as c, CODEX_INTERACTION_BLOCKABILITY as d, CODEX_RESPONSE_CAPABILITIES as f, createCodexPostToolUseContextEffect as g, createCodexPostToolUseBlockEffect as h, withCodexNativeAuthSourceLock as i, CodexConfigHooksListRequestSchema as j, CodexConfigHooksAddRequestSchema as k, CODEX_CONTRACT_ID as l, codexProviderContractCatalog as m, buildCodexNativeAuthSourceLockPath as n, CodexClientSubjects as o, CODEX_SUPPORTED_INTERACTIONS as p, executeCodexNativeAuthSourceLock as r, composeCodexHookResponse as s, CodexClientSessionService as t, CODEX_CONTRACT_VERSION as u, createCodexPreToolUseContextEffect as v, createCodexUserPromptSubmitBlockEffect as w, createCodexSessionStartBlockEffect as x, createCodexPreToolUseDenyEffect as y, CodexNativeHooksFileSchema as z };
|
package/dist/definition.d.ts
CHANGED
|
@@ -7,6 +7,12 @@
|
|
|
7
7
|
* capability taxonomy in a single canonical location.
|
|
8
8
|
* @packageDocumentation
|
|
9
9
|
*/
|
|
10
|
+
/** Namespaced Codex hook-response capabilities exposed to contributors. */
|
|
11
|
+
export declare const CODEX_HOOK_RESPONSE_CAPABILITIES: Readonly<{
|
|
12
|
+
readonly block: 'openai.codex-hook-response.block';
|
|
13
|
+
readonly permissionDeny: 'openai.codex-hook-response.permission.deny';
|
|
14
|
+
readonly inputUpdate: 'openai.codex-hook-response.input.update';
|
|
15
|
+
}>;
|
|
10
16
|
/**
|
|
11
17
|
* Static client definition for `@makaio/client-codex`.
|
|
12
18
|
*
|
|
@@ -79,7 +85,7 @@ export declare const clientDefinition: {
|
|
|
79
85
|
hookEvents: {
|
|
80
86
|
name: string;
|
|
81
87
|
frameworkSubject?: string | undefined;
|
|
82
|
-
|
|
88
|
+
responseCapabilities: readonly string[];
|
|
83
89
|
}[];
|
|
84
90
|
};
|
|
85
91
|
managedInstall?: {
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as codexPackage } from "./src-
|
|
1
|
+
import { A as CodexConfigHooksAddResponseSchema, B as CodexScopeHookRecordSchema, D as CodexWiringSchemas, F as CodexConfigSchemas, I as CodexHookEntrySchema, L as CodexNativeCommandHookSchema, M as CodexConfigHooksListResponseSchema, N as CodexConfigHooksRemoveRequestSchema, O as AbsolutePathSchema, P as CodexConfigHooksRemoveResponseSchema, R as CodexNativeHookMatcherGroupSchema, U as clientDefinition, V as CodexScopeSchema, j as CodexConfigHooksListRequestSchema, k as CodexConfigHooksAddRequestSchema, o as CodexClientSubjects, t as CodexClientSessionService, z as CodexNativeHooksFileSchema } from "./codex-client-session-service-CTJ576Q4.mjs";
|
|
2
|
+
import { t as codexPackage } from "./src-DXsdjc9S.mjs";
|
|
3
3
|
|
|
4
4
|
export { AbsolutePathSchema, CodexClientSessionService, CodexClientSubjects, CodexConfigHooksAddRequestSchema, CodexConfigHooksAddResponseSchema, CodexConfigHooksListRequestSchema, CodexConfigHooksListResponseSchema, CodexConfigHooksRemoveRequestSchema, CodexConfigHooksRemoveResponseSchema, CodexConfigSchemas, CodexHookEntrySchema, CodexNativeCommandHookSchema, CodexNativeHookMatcherGroupSchema, CodexNativeHooksFileSchema, CodexScopeHookRecordSchema, CodexScopeSchema, CodexWiringSchemas, clientDefinition, codexPackage };
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
* @packageDocumentation
|
|
40
40
|
*/
|
|
41
41
|
import type { IMakaioBus } from '@makaio/framework/bus';
|
|
42
|
+
import type { ClientHookProviderContractRegistry, ClientHookResponseRegistry } from '@makaio/framework/clients';
|
|
42
43
|
import { BaseService } from '@makaio/framework/service-base';
|
|
43
44
|
import { CodexClientSettings } from './client-settings.js';
|
|
44
45
|
import { CodexSessionConfigHandler } from './session-config-handler.js';
|
|
@@ -97,6 +98,16 @@ export declare class CodexClientSessionService extends BaseService {
|
|
|
97
98
|
* emissions for sessions that the adapter path already covers.
|
|
98
99
|
*/
|
|
99
100
|
private readonly managedAdapterSessionIds;
|
|
101
|
+
/**
|
|
102
|
+
* Optional provider contract registry for registering and unregistering
|
|
103
|
+
* the Codex hook response contract during the service lifecycle.
|
|
104
|
+
*
|
|
105
|
+
* When `undefined`, contract registration is skipped — this allows
|
|
106
|
+
* lightweight test construction without requiring a full clients-core
|
|
107
|
+
* dependency.
|
|
108
|
+
*/
|
|
109
|
+
private readonly providerContractRegistry;
|
|
110
|
+
private readonly hookResponseRegistry;
|
|
100
111
|
/**
|
|
101
112
|
* Creates a new Codex client session service.
|
|
102
113
|
* @param bus - Bus instance used for subscribing and emitting events
|
|
@@ -107,21 +118,45 @@ export declare class CodexClientSessionService extends BaseService {
|
|
|
107
118
|
* caller-supplied from the extension context. Omit in tests or when the
|
|
108
119
|
* identity is unavailable.
|
|
109
120
|
* @param sessionConfigHandler - Optional native auth lease handler override.
|
|
121
|
+
* @param providerContractRegistry - Optional provider contract registry
|
|
122
|
+
* from clients-core for registering the Codex hook response contract.
|
|
123
|
+
* Omit in tests that do not exercise the response pipeline.
|
|
124
|
+
* @param hookResponseRegistry - Optional contributor registry used by the terminal composer.
|
|
110
125
|
*/
|
|
111
|
-
constructor(bus?: IMakaioBus, settings?: CodexClientSettings, machineId?: string, sessionConfigHandler?: CodexSessionConfigHandler);
|
|
126
|
+
constructor(bus?: IMakaioBus, settings?: CodexClientSettings, machineId?: string, sessionConfigHandler?: CodexSessionConfigHandler, providerContractRegistry?: ClientHookProviderContractRegistry, hookResponseRegistry?: ClientHookResponseRegistry);
|
|
112
127
|
/**
|
|
113
|
-
* Register the raw hook ingress handler,
|
|
114
|
-
*
|
|
115
|
-
*
|
|
128
|
+
* Register the raw hook ingress handler, the `hook.handle` request handler,
|
|
129
|
+
* config management request handlers, wiring management request handlers,
|
|
130
|
+
* the config-prime lifecycle handler, and the session config
|
|
131
|
+
* setup/teardown handlers on the bus.
|
|
116
132
|
*
|
|
117
133
|
* Also subscribes to `client.runtime.started` to track adapter-managed
|
|
118
134
|
* sessions for the {@link handleHookReceived} suppression gate.
|
|
135
|
+
*
|
|
136
|
+
* When a {@link ClientHookProviderContractRegistry} was supplied at
|
|
137
|
+
* construction time, the Codex provider contract is registered so that
|
|
138
|
+
* contributors can be validated against it during extension activation.
|
|
119
139
|
*/
|
|
120
140
|
protected onInit(): void;
|
|
121
141
|
/**
|
|
122
|
-
* Clear the adapter-managed session ID set on teardown.
|
|
142
|
+
* Clear the adapter-managed session ID set and config cache on teardown.
|
|
143
|
+
*
|
|
144
|
+
* Provider contract unregistration is handled via {@link addCleanup} in
|
|
145
|
+
* {@link onInit}, so it runs automatically during the base-class destroy
|
|
146
|
+
* sequence alongside handler unsubscription.
|
|
123
147
|
*/
|
|
124
148
|
protected onDestroy(): void;
|
|
149
|
+
/**
|
|
150
|
+
* Register the `hook.handle` request handler.
|
|
151
|
+
*
|
|
152
|
+
* The handler receives request-mode hook payloads and returns a
|
|
153
|
+
* {@link ClientHookHandleResponse} composed by
|
|
154
|
+
* {@link composeCodexHookResponse}. The pinned Codex `0.144.1` source
|
|
155
|
+
* parses synchronous responses for all five declared events.
|
|
156
|
+
*
|
|
157
|
+
* Extracted from {@link onInit} to keep the init method concise.
|
|
158
|
+
*/
|
|
159
|
+
private registerHookHandleHandler;
|
|
125
160
|
private createSettings;
|
|
126
161
|
/**
|
|
127
162
|
* Return the cached config directory promise, resolving it on first access.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ClientHookHandleResponse, type ClientHookResponseRegistry, type CollectionDiagnostic } from '@makaio/framework/clients';
|
|
2
|
+
import { type RawClientHookPayload } from './schemas.js';
|
|
3
|
+
export interface ComposeCodexHookResponseOptions {
|
|
4
|
+
readonly deadline?: number;
|
|
5
|
+
readonly signal?: AbortSignal;
|
|
6
|
+
readonly onDiagnostics?: (diagnostics: readonly CollectionDiagnostic[]) => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Compose one terminal Codex native hook response.
|
|
10
|
+
* @param registry - Active response contributor registry.
|
|
11
|
+
* @param payload - Normalized native hook payload.
|
|
12
|
+
* @param options - Request deadline, cancellation, and diagnostics hooks.
|
|
13
|
+
* @returns The composed native response envelope.
|
|
14
|
+
*/
|
|
15
|
+
export declare function composeCodexHookResponse(registry: ClientHookResponseRegistry, payload: RawClientHookPayload, options?: ComposeCodexHookResponseOptions): Promise<ClientHookHandleResponse>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/** Codex 0.144.1 synchronous hook-response contract. @packageDocumentation */
|
|
2
|
+
import type { InteractionBlockability, ProviderContractCatalogEntry, ProviderContributionEnvelope } from '@makaio/framework/contracts/client';
|
|
3
|
+
export declare const CODEX_CLIENT_ID = "codex";
|
|
4
|
+
export declare const CODEX_CONTRACT_ID = "openai.codex-hook-response";
|
|
5
|
+
export declare const CODEX_CONTRACT_VERSION = "1.1.0";
|
|
6
|
+
export type CodexBlockEffects = Readonly<{
|
|
7
|
+
decision: 'block';
|
|
8
|
+
reason: string;
|
|
9
|
+
}> & Record<string, unknown>;
|
|
10
|
+
export type CodexContextEffects = Readonly<{
|
|
11
|
+
additionalContext: string;
|
|
12
|
+
}> & Record<string, unknown>;
|
|
13
|
+
export type CodexPermissionDenyEffects = Readonly<{
|
|
14
|
+
permissionDecision: 'deny';
|
|
15
|
+
permissionDecisionReason: string;
|
|
16
|
+
}> & Record<string, unknown>;
|
|
17
|
+
/** JSON value accepted by Codex's `serde_json::Value` hook parser. */
|
|
18
|
+
export type CodexJsonValue = string | number | boolean | null | readonly CodexJsonValue[] | {
|
|
19
|
+
readonly [key: string]: CodexJsonValue;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* JSON input accepted as a Codex `updated_input` replacement.
|
|
23
|
+
*
|
|
24
|
+
* The pinned Rust hook contract represents the field as `Option<Value>`:
|
|
25
|
+
* a top-level JSON `null` therefore deserializes as an absent value, while
|
|
26
|
+
* nested null values remain valid JSON within a present replacement.
|
|
27
|
+
*/
|
|
28
|
+
export type CodexUpdatedInput = Exclude<CodexJsonValue, null>;
|
|
29
|
+
export type CodexInputUpdateEffects = Readonly<{
|
|
30
|
+
permissionDecision: 'allow';
|
|
31
|
+
updatedInput: CodexUpdatedInput;
|
|
32
|
+
}> & Record<string, unknown>;
|
|
33
|
+
export type CodexEffects = CodexBlockEffects | CodexContextEffects | CodexPermissionDenyEffects | CodexInputUpdateEffects;
|
|
34
|
+
/**
|
|
35
|
+
* Builds a SessionStart context response.
|
|
36
|
+
* @param value - Context appended when the session starts.
|
|
37
|
+
* @returns A Codex SessionStart context envelope.
|
|
38
|
+
*/
|
|
39
|
+
export declare function createCodexSessionStartContextEffect(value: string): ProviderContributionEnvelope<CodexContextEffects>;
|
|
40
|
+
/**
|
|
41
|
+
* Builds a SessionStart stop response.
|
|
42
|
+
* @param reason - Reason for stopping session startup.
|
|
43
|
+
* @returns A Codex SessionStart block envelope.
|
|
44
|
+
*/
|
|
45
|
+
export declare function createCodexSessionStartBlockEffect(reason: string): ProviderContributionEnvelope<CodexBlockEffects>;
|
|
46
|
+
/**
|
|
47
|
+
* Builds a UserPromptSubmit context response.
|
|
48
|
+
* @param value - Context appended to the submitted prompt.
|
|
49
|
+
* @returns A Codex UserPromptSubmit context envelope.
|
|
50
|
+
*/
|
|
51
|
+
export declare function createCodexUserPromptSubmitContextEffect(value: string): ProviderContributionEnvelope<CodexContextEffects>;
|
|
52
|
+
/**
|
|
53
|
+
* Builds a UserPromptSubmit block response.
|
|
54
|
+
* @param reason - Reason for blocking the submitted prompt.
|
|
55
|
+
* @returns A Codex UserPromptSubmit block envelope.
|
|
56
|
+
*/
|
|
57
|
+
export declare function createCodexUserPromptSubmitBlockEffect(reason: string): ProviderContributionEnvelope<CodexBlockEffects>;
|
|
58
|
+
/**
|
|
59
|
+
* Builds a PreToolUse block response.
|
|
60
|
+
* @param reason - Reason for blocking the tool invocation.
|
|
61
|
+
* @returns A Codex PreToolUse block envelope.
|
|
62
|
+
*/
|
|
63
|
+
export declare function createCodexPreToolUseBlockEffect(reason: string): ProviderContributionEnvelope<CodexBlockEffects>;
|
|
64
|
+
/**
|
|
65
|
+
* Builds a PreToolUse deny-permission response.
|
|
66
|
+
* @param reason - Reason for denying the tool invocation.
|
|
67
|
+
* @returns A Codex PreToolUse permission-denial envelope.
|
|
68
|
+
*/
|
|
69
|
+
export declare function createCodexPreToolUseDenyEffect(reason: string): ProviderContributionEnvelope<CodexPermissionDenyEffects>;
|
|
70
|
+
/**
|
|
71
|
+
* Builds additional model context for PreToolUse.
|
|
72
|
+
* @param value - Context appended before the tool invocation.
|
|
73
|
+
* @returns A Codex PreToolUse context envelope.
|
|
74
|
+
*/
|
|
75
|
+
export declare function createCodexPreToolUseContextEffect(value: string): ProviderContributionEnvelope<CodexContextEffects>;
|
|
76
|
+
/**
|
|
77
|
+
* Builds a PreToolUse allowed input update.
|
|
78
|
+
* @param updatedInput - JSON value that replaces the native tool input.
|
|
79
|
+
* @returns A Codex PreToolUse input-update envelope.
|
|
80
|
+
*/
|
|
81
|
+
export declare function createCodexPreToolUseUpdateEffect(updatedInput: CodexUpdatedInput): ProviderContributionEnvelope<CodexInputUpdateEffects>;
|
|
82
|
+
/**
|
|
83
|
+
* Builds a PostToolUse context response.
|
|
84
|
+
* @param value - Context appended after the tool invocation.
|
|
85
|
+
* @returns A Codex PostToolUse context envelope.
|
|
86
|
+
*/
|
|
87
|
+
export declare function createCodexPostToolUseContextEffect(value: string): ProviderContributionEnvelope<CodexContextEffects>;
|
|
88
|
+
/**
|
|
89
|
+
* Builds a PostToolUse block response.
|
|
90
|
+
* @param reason - Reason for blocking after the tool invocation.
|
|
91
|
+
* @returns A Codex PostToolUse block envelope.
|
|
92
|
+
*/
|
|
93
|
+
export declare function createCodexPostToolUseBlockEffect(reason: string): ProviderContributionEnvelope<CodexBlockEffects>;
|
|
94
|
+
/**
|
|
95
|
+
* Builds a Stop block response.
|
|
96
|
+
* @param reason - Reason for requesting another turn.
|
|
97
|
+
* @returns A Codex Stop block envelope.
|
|
98
|
+
*/
|
|
99
|
+
export declare function createCodexStopBlockEffect(reason: string): ProviderContributionEnvelope<CodexBlockEffects>;
|
|
100
|
+
export declare const CODEX_RESPONSE_CAPABILITIES: readonly string[];
|
|
101
|
+
export declare const CODEX_SUPPORTED_INTERACTIONS: readonly string[];
|
|
102
|
+
export declare const CODEX_INTERACTION_BLOCKABILITY: readonly InteractionBlockability[];
|
|
103
|
+
export declare const codexProviderContractCatalog: ProviderContractCatalogEntry;
|
|
@@ -47,7 +47,7 @@ export declare const CodexClientSubjects: import("@makaio/framework/core").BusSu
|
|
|
47
47
|
payload: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
48
48
|
metadata: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
49
49
|
}, import("zod/v4/core").$strip>;
|
|
50
|
-
'hook.handle': {
|
|
50
|
+
'hook.handle': import("@makaio/framework/core").HostLocalRequestSubjectSchema<{
|
|
51
51
|
request: import("zod").ZodObject<{
|
|
52
52
|
eventName: import("zod").ZodString;
|
|
53
53
|
receivedAt: import("zod").ZodNumber;
|
|
@@ -59,7 +59,7 @@ export declare const CodexClientSubjects: import("@makaio/framework/core").BusSu
|
|
|
59
59
|
stdout: import("zod").ZodDefault<import("zod").ZodString>;
|
|
60
60
|
stderr: import("zod").ZodDefault<import("zod").ZodString>;
|
|
61
61
|
}, import("zod/v4/core").$strip>;
|
|
62
|
-
}
|
|
62
|
+
}>;
|
|
63
63
|
} & {
|
|
64
64
|
'config.hooks.list': {
|
|
65
65
|
request: import("zod").ZodObject<{
|
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Exports the {@link MakaioExtension} manifest for the Codex client runtime and
|
|
5
5
|
* re-exports the namespace subjects for client-native integrations.
|
|
6
|
+
*
|
|
7
|
+
* The `create()` factory resolves the `clients-core` service via
|
|
8
|
+
* {@link ClientsCoreToken} and passes its
|
|
9
|
+
* {@link ClientHookProviderContractRegistry} to the
|
|
10
|
+
* {@link CodexClientSessionService} so the Codex provider contract is
|
|
11
|
+
* registered and unregistered alongside the service lifecycle.
|
|
6
12
|
* @packageDocumentation
|
|
7
13
|
*/
|
|
8
14
|
import type { IMakaioBus } from '@makaio/framework/bus';
|
|
@@ -13,11 +19,19 @@ export { normalizeCodexHook } from './hook-normalizer.js';
|
|
|
13
19
|
export type { CodexNormalizedEvent, CodexNormalizedSubject } from './hook-normalizer.js';
|
|
14
20
|
export { buildCodexNativeAuthSourceLockPath, executeCodexNativeAuthSourceLock, withCodexNativeAuthSourceLock, } from './native-auth-source-lock.js';
|
|
15
21
|
export type { CodexNativeAuthSourceLockExecution } from './native-auth-source-lock.js';
|
|
22
|
+
export { CODEX_HOOK_RESPONSE_CAPABILITIES } from '../definition.js';
|
|
23
|
+
export { codexProviderContractCatalog, CODEX_CLIENT_ID, CODEX_CONTRACT_ID, CODEX_CONTRACT_VERSION, CODEX_SUPPORTED_INTERACTIONS, CODEX_RESPONSE_CAPABILITIES, CODEX_INTERACTION_BLOCKABILITY, createCodexSessionStartContextEffect, createCodexSessionStartBlockEffect, createCodexUserPromptSubmitContextEffect, createCodexUserPromptSubmitBlockEffect, createCodexPreToolUseBlockEffect, createCodexPreToolUseContextEffect, createCodexPreToolUseDenyEffect, createCodexPreToolUseUpdateEffect, createCodexPostToolUseContextEffect, createCodexPostToolUseBlockEffect, createCodexStopBlockEffect, } from './hook-response-contracts.js';
|
|
24
|
+
export type { CodexEffects, CodexJsonValue } from './hook-response-contracts.js';
|
|
25
|
+
export { composeCodexHookResponse } from './hook-response-composer.js';
|
|
16
26
|
/**
|
|
17
27
|
* MakaioExtension manifest for the Codex client session normalization service.
|
|
18
28
|
*
|
|
19
29
|
* Creates a {@link CodexClientSessionService} that bridges raw
|
|
20
30
|
* `client:codex.hook.received` events into normalized `client.session.*`
|
|
21
31
|
* observations when the Codex descriptor server entry activates.
|
|
32
|
+
*
|
|
33
|
+
* The `create()` factory requires the `clients-core` service so provider
|
|
34
|
+
* contract registration and terminal hook composition cannot silently start
|
|
35
|
+
* in a non-functional state.
|
|
22
36
|
*/
|
|
23
37
|
export declare const codexClientRuntimePackage: MakaioNodeExtension<IMakaioBus>;
|
package/dist/runtime/package.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { a as CODEX_CLIENT_NAMESPACE, i as withCodexNativeAuthSourceLock, n as buildCodexNativeAuthSourceLockPath, o as CodexClientSubjects, r as executeCodexNativeAuthSourceLock, s as
|
|
1
|
+
import { C as createCodexStopBlockEffect, E as normalizeCodexHook, H as CODEX_HOOK_RESPONSE_CAPABILITIES, S as createCodexSessionStartContextEffect, T as createCodexUserPromptSubmitContextEffect, _ as createCodexPreToolUseBlockEffect, a as CODEX_CLIENT_NAMESPACE, b as createCodexPreToolUseUpdateEffect, c as CODEX_CLIENT_ID, d as CODEX_INTERACTION_BLOCKABILITY, f as CODEX_RESPONSE_CAPABILITIES, g as createCodexPostToolUseContextEffect, h as createCodexPostToolUseBlockEffect, i as withCodexNativeAuthSourceLock, l as CODEX_CONTRACT_ID, m as codexProviderContractCatalog, n as buildCodexNativeAuthSourceLockPath, o as CodexClientSubjects, p as CODEX_SUPPORTED_INTERACTIONS, r as executeCodexNativeAuthSourceLock, s as composeCodexHookResponse, t as CodexClientSessionService, u as CODEX_CONTRACT_VERSION, v as createCodexPreToolUseContextEffect, w as createCodexUserPromptSubmitBlockEffect, x as createCodexSessionStartBlockEffect, y as createCodexPreToolUseDenyEffect } from "../codex-client-session-service-CTJ576Q4.mjs";
|
|
2
2
|
import { dep } from "@makaio/framework/contracts";
|
|
3
|
+
import { ClientsCoreToken } from "@makaio/framework/clients";
|
|
3
4
|
|
|
4
5
|
//#region src/runtime/package.ts
|
|
5
6
|
/**
|
|
@@ -7,6 +8,12 @@ import { dep } from "@makaio/framework/contracts";
|
|
|
7
8
|
*
|
|
8
9
|
* Exports the {@link MakaioExtension} manifest for the Codex client runtime and
|
|
9
10
|
* re-exports the namespace subjects for client-native integrations.
|
|
11
|
+
*
|
|
12
|
+
* The `create()` factory resolves the `clients-core` service via
|
|
13
|
+
* {@link ClientsCoreToken} and passes its
|
|
14
|
+
* {@link ClientHookProviderContractRegistry} to the
|
|
15
|
+
* {@link CodexClientSessionService} so the Codex provider contract is
|
|
16
|
+
* registered and unregistered alongside the service lifecycle.
|
|
10
17
|
* @packageDocumentation
|
|
11
18
|
*/
|
|
12
19
|
/**
|
|
@@ -15,6 +22,10 @@ import { dep } from "@makaio/framework/contracts";
|
|
|
15
22
|
* Creates a {@link CodexClientSessionService} that bridges raw
|
|
16
23
|
* `client:codex.hook.received` events into normalized `client.session.*`
|
|
17
24
|
* observations when the Codex descriptor server entry activates.
|
|
25
|
+
*
|
|
26
|
+
* The `create()` factory requires the `clients-core` service so provider
|
|
27
|
+
* contract registration and terminal hook composition cannot silently start
|
|
28
|
+
* in a non-functional state.
|
|
18
29
|
*/
|
|
19
30
|
const codexClientRuntimePackage = {
|
|
20
31
|
name: "codex.runtime",
|
|
@@ -23,11 +34,19 @@ const codexClientRuntimePackage = {
|
|
|
23
34
|
dependencies: [dep("makaio.clients-core")],
|
|
24
35
|
/**
|
|
25
36
|
* Create the Codex client session service bound to the runtime bus.
|
|
37
|
+
*
|
|
38
|
+
* Resolves the clients-core service via {@link ClientsCoreToken} to
|
|
39
|
+
* obtain the {@link ClientHookProviderContractRegistry} for provider
|
|
40
|
+
* contract registration during the service lifecycle.
|
|
26
41
|
* @param ctx - Runtime package context
|
|
27
42
|
* @returns Uninitialized Codex client session service
|
|
28
43
|
*/
|
|
29
|
-
create: (ctx) =>
|
|
44
|
+
create: (ctx) => {
|
|
45
|
+
const clientsCore = ctx.getService(ClientsCoreToken);
|
|
46
|
+
if (!clientsCore) throw new Error("codex.runtime requires makaio.clients-core");
|
|
47
|
+
return new CodexClientSessionService(ctx.bus, void 0, ctx.machineId, void 0, clientsCore.providerContractRegistry, clientsCore.hookResponseRegistry);
|
|
48
|
+
}
|
|
30
49
|
};
|
|
31
50
|
|
|
32
51
|
//#endregion
|
|
33
|
-
export { CODEX_CLIENT_NAMESPACE, CodexClientSessionService, CodexClientSubjects, buildCodexNativeAuthSourceLockPath, codexClientRuntimePackage, executeCodexNativeAuthSourceLock, normalizeCodexHook, withCodexNativeAuthSourceLock };
|
|
52
|
+
export { CODEX_CLIENT_ID, CODEX_CLIENT_NAMESPACE, CODEX_CONTRACT_ID, CODEX_CONTRACT_VERSION, CODEX_HOOK_RESPONSE_CAPABILITIES, CODEX_INTERACTION_BLOCKABILITY, CODEX_RESPONSE_CAPABILITIES, CODEX_SUPPORTED_INTERACTIONS, CodexClientSessionService, CodexClientSubjects, buildCodexNativeAuthSourceLockPath, codexClientRuntimePackage, codexProviderContractCatalog, composeCodexHookResponse, createCodexPostToolUseBlockEffect, createCodexPostToolUseContextEffect, createCodexPreToolUseBlockEffect, createCodexPreToolUseContextEffect, createCodexPreToolUseDenyEffect, createCodexPreToolUseUpdateEffect, createCodexSessionStartBlockEffect, createCodexSessionStartContextEffect, createCodexStopBlockEffect, createCodexUserPromptSubmitBlockEffect, createCodexUserPromptSubmitContextEffect, executeCodexNativeAuthSourceLock, normalizeCodexHook, withCodexNativeAuthSourceLock };
|
package/dist/runtime/wiring.d.ts
CHANGED
|
@@ -41,6 +41,8 @@ export interface CodexWiringSettings {
|
|
|
41
41
|
* the `commandContains` filter in {@link removeCodexWiring}.
|
|
42
42
|
*/
|
|
43
43
|
export declare const CODEX_HOOK_COMMAND_SENTINEL = "hook received codex";
|
|
44
|
+
/** Sentinel for synchronous Codex hook responses. */
|
|
45
|
+
export declare const CODEX_HOOK_HANDLE_COMMAND_SENTINEL = "hook handle codex";
|
|
44
46
|
/**
|
|
45
47
|
* Build the wiring entry list, annotated with installation status, by
|
|
46
48
|
* comparing the expected entries against the currently installed Codex hooks.
|
package/dist/server.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@makaio/client-codex",
|
|
3
|
-
"version": "1.0.0-dev-
|
|
3
|
+
"version": "1.0.0-dev-1784806252593",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.mjs",
|
|
6
6
|
"exports": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@napi-rs/keyring": "^1.2.0",
|
|
29
29
|
"proper-lockfile": "^4.1.2",
|
|
30
|
-
"smol-toml": "^1.
|
|
30
|
+
"smol-toml": "^1.7.0",
|
|
31
31
|
"zod": "4.4.3"
|
|
32
32
|
},
|
|
33
33
|
"files": [
|