@inixiative/agent-session 0.3.0 → 0.3.1
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 +5 -0
- package/package.json +2 -2
- package/src/codex-primed.ts +31 -6
package/README.md
CHANGED
|
@@ -96,6 +96,11 @@ const result = await decisions.decide(
|
|
|
96
96
|
);
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
Run Codex decisions on a private `CODEX_HOME` that holds only the login (link
|
|
100
|
+
`auth.json` from the account's home; a copy forks its refresh token): Codex has no
|
|
101
|
+
setting that drops the user's own `AGENTS.md`, and a decision thread that reports
|
|
102
|
+
any instruction source is refused.
|
|
103
|
+
|
|
99
104
|
Codex hosts every key as a thread of one `app-server` process per account and
|
|
100
105
|
forks the primed thread per cycle; Claude forks a persisted primed session with
|
|
101
106
|
a pre-spawned spare. Measured on a ChatGPT login: warm Codex decisions 2.45 s
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inixiative/agent-session",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Drive coding-agent CLIs as persistent, streaming, event-captured sessions over interchangeable transports, with primed decision sessions, subscription pools, routing, limit polling and continuity.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"license": "MIT",
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@biomejs/biome": "2.5.2",
|
|
39
|
-
"@inixiative/config": "^0.5.
|
|
39
|
+
"@inixiative/config": "^0.5.41",
|
|
40
40
|
"@types/bun": "1.4.2",
|
|
41
41
|
"lefthook": "2.1.9",
|
|
42
42
|
"typescript": "6.0.3"
|
package/src/codex-primed.ts
CHANGED
|
@@ -75,15 +75,19 @@ export const CODEX_DECISION_DISABLED_FEATURES: readonly string[] = [
|
|
|
75
75
|
];
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
|
-
* Per-thread configuration for decisions: no notify hook, no
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
78
|
+
* Per-thread configuration for decisions: no notify hook, no project docs or skills,
|
|
79
|
+
* and none of the instruction surfaces that describe tools or the environment.
|
|
80
|
+
* Applied on thread/start and thread/fork (verified equivalent to launch-level `-c`
|
|
81
|
+
* overrides), so the launch argv carries only approval, web-search and feature flags
|
|
82
|
+
* that credential launchers accept.
|
|
83
|
+
*
|
|
84
|
+
* The user's own CODEX_HOME (its AGENTS.md, memories, MCP servers) is not a thread
|
|
85
|
+
* setting: run decisions on a private CODEX_HOME holding only the login. A thread
|
|
86
|
+
* that reports an instruction source is refused, and an MCP server that starts is a
|
|
87
|
+
* violation.
|
|
83
88
|
*/
|
|
84
89
|
export const CODEX_DECISION_THREAD_CONFIG: Readonly<Record<string, unknown>> = Object.freeze({
|
|
85
90
|
notify: [],
|
|
86
|
-
'mcp_servers.node_repl.enabled': false,
|
|
87
91
|
project_doc_max_bytes: 0,
|
|
88
92
|
'skills.enabled': false,
|
|
89
93
|
include_permissions_instructions: false,
|
|
@@ -213,6 +217,19 @@ interface Branch {
|
|
|
213
217
|
wake(): void;
|
|
214
218
|
}
|
|
215
219
|
|
|
220
|
+
/** Instruction files Codex loaded into a thread (the user's AGENTS.md, project docs); a decision allows none. */
|
|
221
|
+
const instructionSources = (response: Record<string, unknown> | undefined): string | undefined => {
|
|
222
|
+
const sources = response?.instructionSources;
|
|
223
|
+
return Array.isArray(sources) && sources.length ? sources.map(String).join(', ') : undefined;
|
|
224
|
+
};
|
|
225
|
+
const instructionLeak = (sources: string) =>
|
|
226
|
+
new DecisionError(
|
|
227
|
+
`Codex loaded instructions into a decision thread (${sources}); run decisions on a private CODEX_HOME`,
|
|
228
|
+
'violation',
|
|
229
|
+
'not-dispatched',
|
|
230
|
+
true,
|
|
231
|
+
);
|
|
232
|
+
|
|
216
233
|
const object = (value: unknown): Record<string, unknown> | undefined =>
|
|
217
234
|
value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
218
235
|
? (value as Record<string, unknown>)
|
|
@@ -1045,6 +1062,11 @@ export class CodexPrimedSessions implements PrimedSessions {
|
|
|
1045
1062
|
'not-dispatched',
|
|
1046
1063
|
true,
|
|
1047
1064
|
);
|
|
1065
|
+
const leaked = instructionSources(started);
|
|
1066
|
+
if (leaked) {
|
|
1067
|
+
void conn.request('thread/delete', { threadId: baseId }, 10_000).catch(() => undefined);
|
|
1068
|
+
throw instructionLeak(leaked);
|
|
1069
|
+
}
|
|
1048
1070
|
const branch = this._branch(conn, baseId, spec.key);
|
|
1049
1071
|
let ok = false;
|
|
1050
1072
|
try {
|
|
@@ -1287,6 +1309,8 @@ export class CodexPrimedSessions implements PrimedSessions {
|
|
|
1287
1309
|
);
|
|
1288
1310
|
const id = object(response?.thread)?.id;
|
|
1289
1311
|
if (typeof id !== 'string' || !id) throw Error('Codex returned no decision thread');
|
|
1312
|
+
const leaked = instructionSources(response);
|
|
1313
|
+
if (leaked) throw instructionLeak(leaked);
|
|
1290
1314
|
model ??= typeof response?.model === 'string' ? response.model : undefined;
|
|
1291
1315
|
return { threadId: id, branch: this._branch(conn, id, spec.key) };
|
|
1292
1316
|
};
|
|
@@ -1294,6 +1318,7 @@ export class CodexPrimedSessions implements PrimedSessions {
|
|
|
1294
1318
|
if (Date.now() >= deadline || signal?.aborted) throw expired();
|
|
1295
1319
|
const t1 = performance.now();
|
|
1296
1320
|
const opened = await openBranch().catch((error) => {
|
|
1321
|
+
if (error instanceof DecisionError) throw error;
|
|
1297
1322
|
// The runtime refusing the fork means the primed thread is gone: retire it and prime again off-path.
|
|
1298
1323
|
// A timeout proves nothing about the primed thread.
|
|
1299
1324
|
if (session && error instanceof JsonRpcError) this._retire(session, 'reprime');
|