@a5c-ai/babysitter-sdk 0.0.184 → 0.0.185
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/dist/cli/commands/instructions.d.ts.map +1 -1
- package/dist/cli/commands/instructions.js +41 -0
- package/dist/cli/main.js +2 -2
- package/dist/config/defaults.d.ts +11 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +55 -0
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +2 -1
- package/dist/harness/claudeCode.d.ts +2 -2
- package/dist/harness/claudeCode.d.ts.map +1 -1
- package/dist/harness/claudeCode.js +47 -72
- package/dist/harness/codex.d.ts.map +1 -1
- package/dist/harness/codex.js +10 -49
- package/dist/harness/cursor.d.ts.map +1 -1
- package/dist/harness/cursor.js +23 -34
- package/dist/harness/customAdapter.d.ts.map +1 -1
- package/dist/harness/customAdapter.js +8 -3
- package/dist/harness/discovery.js +7 -7
- package/dist/harness/geminiCli.d.ts.map +1 -1
- package/dist/harness/geminiCli.js +20 -27
- package/dist/harness/githubCopilot.d.ts.map +1 -1
- package/dist/harness/githubCopilot.js +17 -40
- package/dist/harness/index.d.ts +1 -0
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +3 -1
- package/dist/harness/installSupport.d.ts +1 -0
- package/dist/harness/installSupport.d.ts.map +1 -1
- package/dist/harness/installSupport.js +7 -3
- package/dist/harness/invoker.js +1 -1
- package/dist/harness/ohMyPi.d.ts +0 -14
- package/dist/harness/ohMyPi.d.ts.map +1 -1
- package/dist/harness/ohMyPi.js +163 -24
- package/dist/harness/opencode.d.ts +28 -0
- package/dist/harness/opencode.d.ts.map +1 -0
- package/dist/harness/opencode.js +578 -0
- package/dist/harness/pi.d.ts +1 -11
- package/dist/harness/pi.d.ts.map +1 -1
- package/dist/harness/pi.js +81 -105
- package/dist/harness/registry.d.ts.map +1 -1
- package/dist/harness/registry.js +2 -0
- package/dist/prompts/context.d.ts +9 -0
- package/dist/prompts/context.d.ts.map +1 -1
- package/dist/prompts/context.js +128 -20
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +2 -1
- package/dist/prompts/templates/completion-proof.md +8 -0
- package/dist/prompts/templates/critical-rules.md +5 -5
- package/dist/prompts/types.d.ts +4 -5
- package/dist/prompts/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/instructions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/instructions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAoBH,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,eAAe,GAAG,gBAAgB,GAAG,aAAa,GAAG,qBAAqB,CAAC;IACvF,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,IAAI,EAAE,OAAO,CAAC;CACf;AAmID;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAmFjB"}
|
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|
*/
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
11
|
exports.handleInstructionsCommand = handleInstructionsCommand;
|
|
12
|
+
const node_fs_1 = require("node:fs");
|
|
12
13
|
const prompts_1 = require("../../prompts");
|
|
13
14
|
const active_1 = require("../../processLibrary/active");
|
|
14
15
|
const registry_1 = require("../../harness/registry");
|
|
16
|
+
const parse_1 = require("../../session/parse");
|
|
15
17
|
/**
|
|
16
18
|
* Legacy fallback map — used only when an adapter does not implement
|
|
17
19
|
* `getPromptContext()`. New harnesses should add the method to their
|
|
@@ -103,6 +105,28 @@ async function tryResolveProcessLibraryRoot() {
|
|
|
103
105
|
}
|
|
104
106
|
return {};
|
|
105
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Detect whether the session-start hook has actually run by checking for the
|
|
110
|
+
* session state file it creates (`<stateDir>/<sessionId>.md`).
|
|
111
|
+
*
|
|
112
|
+
* Some adapters can resolve a session ID from env vars alone (e.g.
|
|
113
|
+
* GEMINI_SESSION_ID, CODEX_SESSION_ID) without the hook ever firing.
|
|
114
|
+
* The definitive signal is the state file — the hook writes it as a
|
|
115
|
+
* side effect of `babysitter hook:run --hook-type session-start`.
|
|
116
|
+
*/
|
|
117
|
+
function detectHooksActive(harness) {
|
|
118
|
+
const adapter = (0, registry_1.getAdapterByName)(harness);
|
|
119
|
+
if (!adapter)
|
|
120
|
+
return false;
|
|
121
|
+
const sessionId = adapter.resolveSessionId({});
|
|
122
|
+
if (!sessionId)
|
|
123
|
+
return false;
|
|
124
|
+
const stateDir = adapter.resolveStateDir({});
|
|
125
|
+
if (!stateDir)
|
|
126
|
+
return false;
|
|
127
|
+
const stateFile = (0, parse_1.getSessionFilePath)(stateDir, sessionId);
|
|
128
|
+
return (0, node_fs_1.existsSync)(stateFile);
|
|
129
|
+
}
|
|
106
130
|
/**
|
|
107
131
|
* Route and handle an `instructions:*` subcommand.
|
|
108
132
|
*/
|
|
@@ -137,9 +161,18 @@ async function handleInstructionsCommand(args) {
|
|
|
137
161
|
}
|
|
138
162
|
// Resolve the active process-library root before composing the prompt
|
|
139
163
|
const libraryInfo = await tryResolveProcessLibraryRoot();
|
|
164
|
+
// Detect whether hooks are actually active in this session.
|
|
165
|
+
// If the session-start hook never ran (no breadcrumb file), override
|
|
166
|
+
// hookDriven to false so the agent drives the loop in-turn.
|
|
167
|
+
const hooksActive = detectHooksActive(args.harness);
|
|
168
|
+
const hookOverride = {};
|
|
169
|
+
if (!hooksActive) {
|
|
170
|
+
hookOverride.hookDriven = false;
|
|
171
|
+
}
|
|
140
172
|
const ctx = factory({
|
|
141
173
|
interactive: args.interactive,
|
|
142
174
|
...libraryInfo,
|
|
175
|
+
...hookOverride,
|
|
143
176
|
});
|
|
144
177
|
const content = composer.fn(ctx);
|
|
145
178
|
if (args.json) {
|
|
@@ -147,11 +180,19 @@ async function handleInstructionsCommand(args) {
|
|
|
147
180
|
harness: args.harness,
|
|
148
181
|
interactive: args.interactive,
|
|
149
182
|
promptType: composer.promptType,
|
|
183
|
+
hookDriven: ctx.hookDriven,
|
|
184
|
+
hooksDetected: hooksActive,
|
|
150
185
|
content,
|
|
151
186
|
partsIncluded: composer.partsIncluded,
|
|
152
187
|
}, null, 2));
|
|
153
188
|
}
|
|
154
189
|
else {
|
|
190
|
+
if (!hooksActive && ctx.hookDriven !== false) {
|
|
191
|
+
// Context factory defaulted hookDriven to true, but we overrode it.
|
|
192
|
+
// This is a no-op because the override already happened, but it
|
|
193
|
+
// clarifies the JSON output. The text output is self-explanatory
|
|
194
|
+
// from the generated instructions.
|
|
195
|
+
}
|
|
155
196
|
console.log(content);
|
|
156
197
|
}
|
|
157
198
|
return 0;
|
package/dist/cli/main.js
CHANGED
|
@@ -334,7 +334,7 @@ function parseArgs(argv) {
|
|
|
334
334
|
// Session command flags
|
|
335
335
|
if (arg === "--session-id") {
|
|
336
336
|
// Tolerate empty/missing value — the harness adapter can auto-detect
|
|
337
|
-
// session ID from
|
|
337
|
+
// session ID from BABYSITTER_SESSION_ID env var or CLAUDE_ENV_FILE.
|
|
338
338
|
const next = rest[i + 1];
|
|
339
339
|
if (next && !next.startsWith("-")) {
|
|
340
340
|
parsed.sessionId = next;
|
|
@@ -1071,7 +1071,7 @@ async function handleRunCreate(parsed) {
|
|
|
1071
1071
|
harness: parsed.harness ?? adapter.name,
|
|
1072
1072
|
sessionId: "",
|
|
1073
1073
|
error: (adapter.getMissingSessionIdHint?.() ??
|
|
1074
|
-
"No session ID provided. Use --session-id or set
|
|
1074
|
+
"No session ID provided. Use --session-id or set BABYSITTER_SESSION_ID."),
|
|
1075
1075
|
};
|
|
1076
1076
|
}
|
|
1077
1077
|
}
|
|
@@ -111,6 +111,17 @@ export declare const CONFIG_ENV_VARS: {
|
|
|
111
111
|
* They can be overridden via environment variables or explicit config.
|
|
112
112
|
*/
|
|
113
113
|
export declare const DEFAULTS: Readonly<BabysitterConfig>;
|
|
114
|
+
/**
|
|
115
|
+
* Returns the global babysitter state directory (~/.a5c/state/).
|
|
116
|
+
*
|
|
117
|
+
* All harness adapters use this as the canonical default location for session
|
|
118
|
+
* state files. The directory is user-global (not workspace-relative or
|
|
119
|
+
* plugin-root-relative) so session state is discoverable regardless of the
|
|
120
|
+
* execution context (hook subprocess, Bash tool, CLI invocation, etc.).
|
|
121
|
+
*
|
|
122
|
+
* Override: set BABYSITTER_STATE_DIR to use a different path.
|
|
123
|
+
*/
|
|
124
|
+
export declare function getGlobalStateDir(): string;
|
|
114
125
|
/**
|
|
115
126
|
* Retrieves configuration with environment variable overrides merged in.
|
|
116
127
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,gBAAgB,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,QAAQ,EAAE,QAAQ,CAAC;IAEnB;;;OAGG;IACH,eAAe,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;;CASlB,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAwEtC,CAAC;AAEX;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAQ1C;AAiDD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,SAAS,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAqCjF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,sBAAsB,CA2E/E;AAED;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,QAAQ,CAAC,gBAAgB,CAAC,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAEjE"}
|
package/dist/config/defaults.js
CHANGED
|
@@ -6,12 +6,48 @@
|
|
|
6
6
|
* values used throughout the babysitter SDK. Import from here instead of using
|
|
7
7
|
* scattered magic numbers and strings.
|
|
8
8
|
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
9
42
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
43
|
exports.DEFAULTS = exports.CONFIG_ENV_VARS = void 0;
|
|
44
|
+
exports.getGlobalStateDir = getGlobalStateDir;
|
|
11
45
|
exports.getConfig = getConfig;
|
|
12
46
|
exports.validateConfig = validateConfig;
|
|
13
47
|
exports.getDefaults = getDefaults;
|
|
14
48
|
exports.isValidLogLevel = isValidLogLevel;
|
|
49
|
+
const path = __importStar(require("node:path"));
|
|
50
|
+
const os = __importStar(require("node:os"));
|
|
15
51
|
/**
|
|
16
52
|
* Environment variable names for configuration overrides
|
|
17
53
|
*/
|
|
@@ -93,6 +129,25 @@ exports.DEFAULTS = {
|
|
|
93
129
|
*/
|
|
94
130
|
largeResultPreviewLimit: 1024 * 1024,
|
|
95
131
|
};
|
|
132
|
+
/**
|
|
133
|
+
* Returns the global babysitter state directory (~/.a5c/state/).
|
|
134
|
+
*
|
|
135
|
+
* All harness adapters use this as the canonical default location for session
|
|
136
|
+
* state files. The directory is user-global (not workspace-relative or
|
|
137
|
+
* plugin-root-relative) so session state is discoverable regardless of the
|
|
138
|
+
* execution context (hook subprocess, Bash tool, CLI invocation, etc.).
|
|
139
|
+
*
|
|
140
|
+
* Override: set BABYSITTER_STATE_DIR to use a different path.
|
|
141
|
+
*/
|
|
142
|
+
function getGlobalStateDir() {
|
|
143
|
+
if (process.env.BABYSITTER_STATE_DIR) {
|
|
144
|
+
return path.resolve(process.env.BABYSITTER_STATE_DIR);
|
|
145
|
+
}
|
|
146
|
+
const globalRoot = process.env.BABYSITTER_GLOBAL_STATE_DIR?.trim()
|
|
147
|
+
? path.resolve(process.env.BABYSITTER_GLOBAL_STATE_DIR)
|
|
148
|
+
: path.join(os.homedir(), ".a5c");
|
|
149
|
+
return path.join(globalRoot, "state");
|
|
150
|
+
}
|
|
96
151
|
/**
|
|
97
152
|
* Valid log levels for validation
|
|
98
153
|
*/
|
package/dist/config/index.d.ts
CHANGED
|
@@ -21,5 +21,5 @@
|
|
|
21
21
|
* }
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
|
-
export { type LogLevel, type BabysitterConfig, type ConfigValidationResult, DEFAULTS, CONFIG_ENV_VARS, getConfig, validateConfig, getDefaults, isValidLogLevel, } from "./defaults";
|
|
24
|
+
export { type LogLevel, type BabysitterConfig, type ConfigValidationResult, DEFAULTS, CONFIG_ENV_VARS, getConfig, getGlobalStateDir, validateConfig, getDefaults, isValidLogLevel, } from "./defaults";
|
|
25
25
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAG3B,QAAQ,EACR,eAAe,EAGf,SAAS,EACT,cAAc,EACd,WAAW,EACX,eAAe,GAChB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAG3B,QAAQ,EACR,eAAe,EAGf,SAAS,EACT,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,eAAe,GAChB,MAAM,YAAY,CAAC"}
|
package/dist/config/index.js
CHANGED
|
@@ -23,13 +23,14 @@
|
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.isValidLogLevel = exports.getDefaults = exports.validateConfig = exports.getConfig = exports.CONFIG_ENV_VARS = exports.DEFAULTS = void 0;
|
|
26
|
+
exports.isValidLogLevel = exports.getDefaults = exports.validateConfig = exports.getGlobalStateDir = exports.getConfig = exports.CONFIG_ENV_VARS = exports.DEFAULTS = void 0;
|
|
27
27
|
var defaults_1 = require("./defaults");
|
|
28
28
|
// Constants
|
|
29
29
|
Object.defineProperty(exports, "DEFAULTS", { enumerable: true, get: function () { return defaults_1.DEFAULTS; } });
|
|
30
30
|
Object.defineProperty(exports, "CONFIG_ENV_VARS", { enumerable: true, get: function () { return defaults_1.CONFIG_ENV_VARS; } });
|
|
31
31
|
// Functions
|
|
32
32
|
Object.defineProperty(exports, "getConfig", { enumerable: true, get: function () { return defaults_1.getConfig; } });
|
|
33
|
+
Object.defineProperty(exports, "getGlobalStateDir", { enumerable: true, get: function () { return defaults_1.getGlobalStateDir; } });
|
|
33
34
|
Object.defineProperty(exports, "validateConfig", { enumerable: true, get: function () { return defaults_1.validateConfig; } });
|
|
34
35
|
Object.defineProperty(exports, "getDefaults", { enumerable: true, get: function () { return defaults_1.getDefaults; } });
|
|
35
36
|
Object.defineProperty(exports, "isValidLogLevel", { enumerable: true, get: function () { return defaults_1.isValidLogLevel; } });
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Claude Code harness adapter.
|
|
3
3
|
*
|
|
4
4
|
* Centralizes all Claude Code-specific behaviors:
|
|
5
|
-
* - Session ID resolution (
|
|
5
|
+
* - Session ID resolution (BABYSITTER_SESSION_ID via CLAUDE_ENV_FILE)
|
|
6
6
|
* - Plugin root resolution (CLAUDE_PLUGIN_ROOT)
|
|
7
|
-
* - State directory conventions (
|
|
7
|
+
* - State directory conventions (~/.a5c/state/)
|
|
8
8
|
* - Session binding (run:create → state file with run association)
|
|
9
9
|
* - Stop hook handler (approve/block decision)
|
|
10
10
|
* - Session-start hook handler (env file + baseline state file)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claudeCode.d.ts","sourceRoot":"","sources":["../../src/harness/claudeCode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA+BH,OAAO,KAAK,EACV,cAAc,EAMf,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"claudeCode.d.ts","sourceRoot":"","sources":["../../src/harness/claudeCode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA+BH,OAAO,KAAK,EACV,cAAc,EAMf,MAAM,SAAS,CAAC;AA+jCjB,wBAAgB,uBAAuB,IAAI,cAAc,CA4ExD"}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Claude Code harness adapter.
|
|
4
4
|
*
|
|
5
5
|
* Centralizes all Claude Code-specific behaviors:
|
|
6
|
-
* - Session ID resolution (
|
|
6
|
+
* - Session ID resolution (BABYSITTER_SESSION_ID via CLAUDE_ENV_FILE)
|
|
7
7
|
* - Plugin root resolution (CLAUDE_PLUGIN_ROOT)
|
|
8
|
-
* - State directory conventions (
|
|
8
|
+
* - State directory conventions (~/.a5c/state/)
|
|
9
9
|
* - Session binding (run:create → state file with run association)
|
|
10
10
|
* - Stop hook handler (approve/block decision)
|
|
11
11
|
* - Session-start hook handler (env file + baseline state file)
|
|
@@ -58,6 +58,7 @@ const skill_1 = require("../cli/commands/skill");
|
|
|
58
58
|
const session_1 = require("../session");
|
|
59
59
|
const session_2 = require("../cli/commands/session");
|
|
60
60
|
const context_1 = require("../prompts/context");
|
|
61
|
+
const config_1 = require("../config");
|
|
61
62
|
const config_loader_1 = require("../compression/config-loader");
|
|
62
63
|
const density_filter_1 = require("../compression/density-filter");
|
|
63
64
|
const library_cache_1 = require("../compression/library-cache");
|
|
@@ -179,16 +180,19 @@ async function cleanupSession(filePath) {
|
|
|
179
180
|
/**
|
|
180
181
|
* Resolve the current session ID from environment, independent of the hook
|
|
181
182
|
* payload. After `/clear`, the hook payload may carry a stale session ID while
|
|
182
|
-
*
|
|
183
|
+
* BABYSITTER_SESSION_ID (persisted via CLAUDE_ENV_FILE) reflects the actual
|
|
184
|
+
* active session.
|
|
183
185
|
*/
|
|
184
186
|
function resolveCurrentSessionIdFromEnv() {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
+
// Cross-harness standard env var (written by session-start hook to CLAUDE_ENV_FILE)
|
|
188
|
+
if (process.env.BABYSITTER_SESSION_ID)
|
|
189
|
+
return process.env.BABYSITTER_SESSION_ID;
|
|
190
|
+
// Fallback: read BABYSITTER_SESSION_ID from CLAUDE_ENV_FILE directly
|
|
187
191
|
const envFile = process.env.CLAUDE_ENV_FILE;
|
|
188
192
|
if (envFile) {
|
|
189
193
|
try {
|
|
190
194
|
const content = (0, node_fs_1.readFileSync)(envFile, "utf-8");
|
|
191
|
-
const match = content.match(/export
|
|
195
|
+
const match = content.match(/export BABYSITTER_SESSION_ID="([^"]+)"/);
|
|
192
196
|
if (match?.[1])
|
|
193
197
|
return match[1];
|
|
194
198
|
}
|
|
@@ -237,7 +241,7 @@ async function handleStopHookImpl(args) {
|
|
|
237
241
|
const resolvedPluginRoot = pluginRoot ? path.resolve(pluginRoot) : "";
|
|
238
242
|
const stateDir = args.stateDir
|
|
239
243
|
? path.resolve(args.stateDir)
|
|
240
|
-
: (
|
|
244
|
+
: (0, config_1.getGlobalStateDir)();
|
|
241
245
|
if (!stateDir) {
|
|
242
246
|
log.warn("Cannot determine state directory — allowing exit");
|
|
243
247
|
if (verbose) {
|
|
@@ -249,59 +253,42 @@ async function handleStopHookImpl(args) {
|
|
|
249
253
|
log.info(`Resolved pluginRoot: ${resolvedPluginRoot || "(empty)"}`);
|
|
250
254
|
log.info(`Resolved stateDir: ${stateDir}`);
|
|
251
255
|
const runsDir = (0, resolveInputPath_1.collapseDoubledA5cRuns)(path.resolve(args.runsDir || ".a5c/runs"));
|
|
252
|
-
// 3. Check iteration —
|
|
256
|
+
// 3. Check iteration — look up session state file in the resolved stateDir
|
|
253
257
|
let filePath = (0, session_1.getSessionFilePath)(stateDir, sessionId);
|
|
254
258
|
log.info(`Checking session file at: ${filePath}`);
|
|
255
259
|
let sessionFile;
|
|
256
260
|
try {
|
|
257
261
|
if (!(await (0, session_1.sessionFileExists)(filePath))) {
|
|
258
|
-
// Fallback:
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
if (
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const envSessionId = resolveCurrentSessionIdFromEnv();
|
|
271
|
-
if (envSessionId && envSessionId !== sessionId) {
|
|
272
|
-
log.info(`Payload session ${sessionId} is stale; current env session is ${envSessionId} — retrying lookup`);
|
|
273
|
-
const primaryRetry = (0, session_1.getSessionFilePath)(stateDir, envSessionId);
|
|
274
|
-
const fallbackRetry = (0, session_1.getSessionFilePath)(fallbackStateDir, envSessionId);
|
|
275
|
-
if (await (0, session_1.sessionFileExists)(primaryRetry)) {
|
|
276
|
-
filePath = primaryRetry;
|
|
277
|
-
sessionId = envSessionId;
|
|
278
|
-
log.setContext("session", sessionId);
|
|
279
|
-
log.info(`Found session file for env session at primary: ${filePath}`);
|
|
280
|
-
}
|
|
281
|
-
else if (await (0, session_1.sessionFileExists)(fallbackRetry)) {
|
|
282
|
-
filePath = fallbackRetry;
|
|
283
|
-
sessionId = envSessionId;
|
|
284
|
-
log.setContext("session", sessionId);
|
|
285
|
-
log.info(`Found session file for env session at fallback: ${filePath}`);
|
|
286
|
-
}
|
|
287
|
-
else {
|
|
288
|
-
log.info(`No active loop found for payload session ${sessionId} or env session ${envSessionId} — allowing exit`);
|
|
289
|
-
if (verbose) {
|
|
290
|
-
process.stderr.write(`[hook:run stop] No active loop found for session ${sessionId} or ${envSessionId}\n`);
|
|
291
|
-
}
|
|
292
|
-
process.stdout.write("{}\n");
|
|
293
|
-
return 0;
|
|
294
|
-
}
|
|
262
|
+
// Fallback: the hook payload may carry a stale session ID (e.g. after
|
|
263
|
+
// /clear). Try resolving the *current* session ID from BABYSITTER_SESSION_ID
|
|
264
|
+
// (persisted via CLAUDE_ENV_FILE) and retry the lookup if it differs.
|
|
265
|
+
const envSessionId = resolveCurrentSessionIdFromEnv();
|
|
266
|
+
if (envSessionId && envSessionId !== sessionId) {
|
|
267
|
+
log.info(`Payload session ${sessionId} is stale; current env session is ${envSessionId} — retrying lookup`);
|
|
268
|
+
const retryPath = (0, session_1.getSessionFilePath)(stateDir, envSessionId);
|
|
269
|
+
if (await (0, session_1.sessionFileExists)(retryPath)) {
|
|
270
|
+
filePath = retryPath;
|
|
271
|
+
sessionId = envSessionId;
|
|
272
|
+
log.setContext("session", sessionId);
|
|
273
|
+
log.info(`Found session file for env session: ${filePath}`);
|
|
295
274
|
}
|
|
296
275
|
else {
|
|
297
|
-
log.info(`No active loop found
|
|
276
|
+
log.info(`No active loop found for payload session ${sessionId} or env session ${envSessionId} — allowing exit`);
|
|
298
277
|
if (verbose) {
|
|
299
|
-
process.stderr.write(`[hook:run stop] No active loop found for session ${sessionId}\n`);
|
|
278
|
+
process.stderr.write(`[hook:run stop] No active loop found for session ${sessionId} or ${envSessionId}\n`);
|
|
300
279
|
}
|
|
301
280
|
process.stdout.write("{}\n");
|
|
302
281
|
return 0;
|
|
303
282
|
}
|
|
304
283
|
}
|
|
284
|
+
else {
|
|
285
|
+
log.info(`No active loop found for session ${sessionId} — allowing exit`);
|
|
286
|
+
if (verbose) {
|
|
287
|
+
process.stderr.write(`[hook:run stop] No active loop found for session ${sessionId}\n`);
|
|
288
|
+
}
|
|
289
|
+
process.stdout.write("{}\n");
|
|
290
|
+
return 0;
|
|
291
|
+
}
|
|
305
292
|
}
|
|
306
293
|
sessionFile = await (0, session_1.readSessionFile)(filePath);
|
|
307
294
|
}
|
|
@@ -728,12 +715,13 @@ async function handleSessionStartHookImpl(args) {
|
|
|
728
715
|
process.stdout.write("{}\n");
|
|
729
716
|
return 0;
|
|
730
717
|
}
|
|
731
|
-
// 2. If CLAUDE_ENV_FILE is set,
|
|
718
|
+
// 2. If CLAUDE_ENV_FILE is set, persist BABYSITTER_SESSION_ID so subsequent
|
|
719
|
+
// hooks (stop hook, Bash tool calls) can resolve it from the environment.
|
|
732
720
|
let envFilePersisted = false;
|
|
733
721
|
const envFile = process.env.CLAUDE_ENV_FILE;
|
|
734
722
|
if (envFile) {
|
|
735
723
|
try {
|
|
736
|
-
(0, node_fs_1.appendFileSync)(envFile, `export
|
|
724
|
+
(0, node_fs_1.appendFileSync)(envFile, `export BABYSITTER_SESSION_ID="${sessionId}"\n`);
|
|
737
725
|
envFilePersisted = true;
|
|
738
726
|
}
|
|
739
727
|
catch {
|
|
@@ -748,7 +736,7 @@ async function handleSessionStartHookImpl(args) {
|
|
|
748
736
|
const resolvedPluginRoot = pluginRoot ? path.resolve(pluginRoot) : "";
|
|
749
737
|
const stateDir = args.stateDir
|
|
750
738
|
? path.resolve(args.stateDir)
|
|
751
|
-
: (
|
|
739
|
+
: (0, config_1.getGlobalStateDir)();
|
|
752
740
|
let stateFilePersisted = false;
|
|
753
741
|
if (stateDir) {
|
|
754
742
|
const filePath = (0, session_1.getSessionFilePath)(stateDir, sessionId);
|
|
@@ -820,20 +808,9 @@ async function handleSessionStartHookImpl(args) {
|
|
|
820
808
|
// Session binding (run:create flow)
|
|
821
809
|
// ---------------------------------------------------------------------------
|
|
822
810
|
async function bindSessionImpl(opts) {
|
|
823
|
-
const { sessionId, runId, pluginRoot, runsDir, maxIterations = 256, prompt, verbose } = opts;
|
|
811
|
+
const { sessionId, runId, pluginRoot: _pluginRoot, runsDir, maxIterations = 256, prompt, verbose } = opts;
|
|
824
812
|
// Resolve state directory (always resolve to absolute paths)
|
|
825
|
-
const
|
|
826
|
-
let stateDir = opts.stateDir ? path.resolve(opts.stateDir) : "";
|
|
827
|
-
if (!stateDir && resolvedPluginRoot) {
|
|
828
|
-
stateDir = path.resolve(resolvedPluginRoot, "skills", "babysit", "state");
|
|
829
|
-
}
|
|
830
|
-
if (!stateDir) {
|
|
831
|
-
return {
|
|
832
|
-
harness: "claude-code",
|
|
833
|
-
sessionId,
|
|
834
|
-
error: "Cannot bind session: --state-dir or --plugin-root required for claude-code harness",
|
|
835
|
-
};
|
|
836
|
-
}
|
|
813
|
+
const stateDir = opts.stateDir ? path.resolve(opts.stateDir) : (0, config_1.getGlobalStateDir)();
|
|
837
814
|
const filePath = (0, session_1.getSessionFilePath)(stateDir, sessionId);
|
|
838
815
|
// Check for existing session (prevent re-entrant runs)
|
|
839
816
|
if (await (0, session_1.sessionFileExists)(filePath)) {
|
|
@@ -993,7 +970,7 @@ function createClaudeCodeAdapter() {
|
|
|
993
970
|
return {
|
|
994
971
|
name: "claude-code",
|
|
995
972
|
isActive() {
|
|
996
|
-
return !!(process.env.
|
|
973
|
+
return !!(process.env.BABYSITTER_SESSION_ID || process.env.CLAUDE_ENV_FILE);
|
|
997
974
|
},
|
|
998
975
|
autoResolvesSessionId() {
|
|
999
976
|
return true;
|
|
@@ -1001,14 +978,15 @@ function createClaudeCodeAdapter() {
|
|
|
1001
978
|
resolveSessionId(parsed) {
|
|
1002
979
|
if (parsed.sessionId)
|
|
1003
980
|
return parsed.sessionId;
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
981
|
+
// Cross-harness standard (written by session-start hook to CLAUDE_ENV_FILE)
|
|
982
|
+
if (process.env.BABYSITTER_SESSION_ID)
|
|
983
|
+
return process.env.BABYSITTER_SESSION_ID;
|
|
984
|
+
// Fallback: read BABYSITTER_SESSION_ID from CLAUDE_ENV_FILE directly
|
|
1007
985
|
const envFile = process.env.CLAUDE_ENV_FILE;
|
|
1008
986
|
if (envFile) {
|
|
1009
987
|
try {
|
|
1010
988
|
const content = (0, node_fs_1.readFileSync)(envFile, "utf-8");
|
|
1011
|
-
const match = content.match(/export
|
|
989
|
+
const match = content.match(/export BABYSITTER_SESSION_ID="([^"]+)"/);
|
|
1012
990
|
if (match?.[1])
|
|
1013
991
|
return match[1];
|
|
1014
992
|
}
|
|
@@ -1021,10 +999,7 @@ function createClaudeCodeAdapter() {
|
|
|
1021
999
|
resolveStateDir(args) {
|
|
1022
1000
|
if (args.stateDir)
|
|
1023
1001
|
return path.resolve(args.stateDir);
|
|
1024
|
-
|
|
1025
|
-
if (root)
|
|
1026
|
-
return path.resolve(root, "skills", "babysit", "state");
|
|
1027
|
-
return undefined;
|
|
1002
|
+
return (0, config_1.getGlobalStateDir)();
|
|
1028
1003
|
},
|
|
1029
1004
|
resolvePluginRoot(args) {
|
|
1030
1005
|
const root = args.pluginRoot || process.env.CLAUDE_PLUGIN_ROOT;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/harness/codex.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,OAAO,KAAK,EACV,cAAc,EAMf,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/harness/codex.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,OAAO,KAAK,EACV,cAAc,EAMf,MAAM,SAAS,CAAC;AAkRjB,wBAAgB,kBAAkB,IAAI,cAAc,CAuGnD"}
|
package/dist/harness/codex.js
CHANGED
|
@@ -43,8 +43,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
43
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
44
|
exports.createCodexAdapter = createCodexAdapter;
|
|
45
45
|
const path = __importStar(require("node:path"));
|
|
46
|
-
const node_fs_1 = require("node:fs");
|
|
47
46
|
const node_stream_1 = require("node:stream");
|
|
47
|
+
const config_1 = require("../config");
|
|
48
48
|
const claudeCode_1 = require("./claudeCode");
|
|
49
49
|
const session_1 = require("../session");
|
|
50
50
|
const context_1 = require("../prompts/context");
|
|
@@ -56,49 +56,20 @@ function resolveCodexPluginRoot(args = {}) {
|
|
|
56
56
|
function resolveCodexStateDir(args) {
|
|
57
57
|
if (args.stateDir)
|
|
58
58
|
return path.resolve(args.stateDir);
|
|
59
|
-
|
|
60
|
-
return path.resolve(process.env.BABYSITTER_STATE_DIR);
|
|
61
|
-
}
|
|
62
|
-
const pluginRoot = resolveCodexPluginRoot(args);
|
|
63
|
-
if (pluginRoot) {
|
|
64
|
-
const cwd = path.resolve(process.cwd());
|
|
65
|
-
const normalizedPluginRoot = path.resolve(pluginRoot);
|
|
66
|
-
// Workspace-local installs place ".codex" beside ".a5c", so derive from
|
|
67
|
-
// the plugin root only when that root lives under the active workspace.
|
|
68
|
-
if (normalizedPluginRoot === cwd ||
|
|
69
|
-
normalizedPluginRoot.startsWith(`${cwd}${path.sep}`)) {
|
|
70
|
-
return path.resolve(normalizedPluginRoot, "..", ".a5c");
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
if (pluginRoot) {
|
|
74
|
-
// Global Codex installs live under "~/.codex", but Babysitter run/session
|
|
75
|
-
// state must still default to the active workspace ".a5c".
|
|
76
|
-
// Falling through here keeps global skill installs honest.
|
|
77
|
-
return path.resolve(".a5c");
|
|
78
|
-
}
|
|
79
|
-
// Without any explicit state binding, Codex state belongs to the current
|
|
80
|
-
// workspace, not a user-global directory.
|
|
81
|
-
return path.resolve(".a5c");
|
|
59
|
+
return (0, config_1.getGlobalStateDir)();
|
|
82
60
|
}
|
|
83
61
|
function resolveCodexSessionId(parsed) {
|
|
84
62
|
if (parsed.sessionId)
|
|
85
63
|
return parsed.sessionId;
|
|
86
|
-
//
|
|
64
|
+
// Cross-harness standard
|
|
65
|
+
if (process.env.BABYSITTER_SESSION_ID)
|
|
66
|
+
return process.env.BABYSITTER_SESSION_ID;
|
|
67
|
+
// Codex-native env vars (auto-injected by Codex CLI into all hooks)
|
|
87
68
|
if (process.env.CODEX_THREAD_ID)
|
|
88
69
|
return process.env.CODEX_THREAD_ID;
|
|
89
70
|
if (process.env.CODEX_SESSION_ID)
|
|
90
71
|
return process.env.CODEX_SESSION_ID;
|
|
91
|
-
|
|
92
|
-
if (!envFile)
|
|
93
|
-
return undefined;
|
|
94
|
-
try {
|
|
95
|
-
const content = (0, node_fs_1.readFileSync)(envFile, "utf-8");
|
|
96
|
-
const match = content.match(/(?:^|\n)\s*(?:export\s+)?(?:CODEX_THREAD_ID|CODEX_SESSION_ID)="([^"]+)"/);
|
|
97
|
-
return match?.[1] || undefined;
|
|
98
|
-
}
|
|
99
|
-
catch {
|
|
100
|
-
return undefined;
|
|
101
|
-
}
|
|
72
|
+
return undefined;
|
|
102
73
|
}
|
|
103
74
|
function readStdin() {
|
|
104
75
|
return new Promise((resolve, reject) => {
|
|
@@ -205,17 +176,7 @@ async function handleCodexSessionStartHookImpl(args) {
|
|
|
205
176
|
process.stdout.write("{}\n");
|
|
206
177
|
return 0;
|
|
207
178
|
}
|
|
208
|
-
|
|
209
|
-
if (envFile) {
|
|
210
|
-
try {
|
|
211
|
-
(0, node_fs_1.appendFileSync)(envFile, `export CODEX_THREAD_ID="${sessionId}"\nexport CODEX_SESSION_ID="${sessionId}"\n`);
|
|
212
|
-
}
|
|
213
|
-
catch {
|
|
214
|
-
if (verbose) {
|
|
215
|
-
process.stderr.write(`[hook:run session-start] Failed to write to CODEX_ENV_FILE: ${envFile}\n`);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
179
|
+
// Codex auto-injects CODEX_THREAD_ID into all hooks — no env file write needed.
|
|
219
180
|
const stateDir = resolveCodexStateDir({
|
|
220
181
|
stateDir: args.stateDir,
|
|
221
182
|
pluginRoot: args.pluginRoot,
|
|
@@ -317,9 +278,9 @@ function createCodexAdapter() {
|
|
|
317
278
|
return {
|
|
318
279
|
name: "codex",
|
|
319
280
|
isActive() {
|
|
320
|
-
return !!(process.env.
|
|
281
|
+
return !!(process.env.BABYSITTER_SESSION_ID ||
|
|
282
|
+
process.env.CODEX_THREAD_ID ||
|
|
321
283
|
process.env.CODEX_SESSION_ID ||
|
|
322
|
-
process.env.CODEX_ENV_FILE ||
|
|
323
284
|
process.env.CODEX_PLUGIN_ROOT);
|
|
324
285
|
},
|
|
325
286
|
autoResolvesSessionId() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/harness/cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAsBH,OAAO,KAAK,EACV,cAAc,EAMf,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/harness/cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAsBH,OAAO,KAAK,EACV,cAAc,EAMf,MAAM,SAAS,CAAC;AAgwBjB,wBAAgB,mBAAmB,IAAI,cAAc,CAgIpD"}
|