@ghl-ai/aw 0.1.37-beta.79 → 0.1.37-beta.80

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.
Files changed (2) hide show
  1. package/integrate.mjs +62 -13
  2. package/package.json +1 -1
package/integrate.mjs CHANGED
@@ -489,6 +489,8 @@ No active tasks. Tasks are created during workflow execution.
489
489
  export function installIdeHooks() {
490
490
  const home = homedir();
491
491
  const hooksDir = join(home, '.aw', 'hooks');
492
+ const codexHooksDir = join(hooksDir, 'codex');
493
+ const nodeExec = process.execPath;
492
494
 
493
495
  // ── Step 0: Write ~/.aw/config.json with API URL ───────────────────
494
496
  const awDir = join(home, '.aw');
@@ -511,7 +513,7 @@ export function installIdeHooks() {
511
513
  const pkgHooksDir = join(dirname(fileURLToPath(import.meta.url)), 'hooks');
512
514
 
513
515
  // New dispatcher-based hooks (Phase 1)
514
- const newHookDirs = ['shared', 'capabilities'];
516
+ const newHookDirs = ['shared', 'capabilities', 'codex'];
515
517
  const newHookFiles = [
516
518
  'manifest.mjs',
517
519
  'shared/dispatch.mjs',
@@ -544,6 +546,55 @@ export function installIdeHooks() {
544
546
  try { chmodSync(dest, 0o755); } catch { /* best effort */ }
545
547
  }
546
548
 
549
+ const codexWrapperScripts = {
550
+ 'session-start.sh': `#!/usr/bin/env bash
551
+ set -euo pipefail
552
+
553
+ NODE_BIN=${JSON.stringify(nodeExec)}
554
+ TARGET=${JSON.stringify(join(hooksDir, 'shared', 'session-start.mjs'))}
555
+ LOG_FILE=${JSON.stringify(join(home, '.aw', 'telemetry', 'codex-hook-errors.log'))}
556
+
557
+ mkdir -p "$(dirname "$LOG_FILE")"
558
+
559
+ if ! output="$("$NODE_BIN" "$TARGET" 2>>"$LOG_FILE")"; then
560
+ printf '%s\\n' '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":""}}'
561
+ exit 0
562
+ fi
563
+
564
+ if [[ -n "$output" ]]; then
565
+ printf '%s\\n' "$output"
566
+ else
567
+ printf '%s\\n' '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":""}}'
568
+ fi
569
+ `,
570
+ 'stop.sh': `#!/usr/bin/env bash
571
+ set -euo pipefail
572
+
573
+ NODE_BIN=${JSON.stringify(nodeExec)}
574
+ TARGET=${JSON.stringify(join(hooksDir, 'shared', 'stop.mjs'))}
575
+ LOG_FILE=${JSON.stringify(join(home, '.aw', 'telemetry', 'codex-hook-errors.log'))}
576
+
577
+ mkdir -p "$(dirname "$LOG_FILE")"
578
+
579
+ if ! output="$("$NODE_BIN" "$TARGET" 2>>"$LOG_FILE")"; then
580
+ printf '%s\\n' '{}'
581
+ exit 0
582
+ fi
583
+
584
+ if [[ -n "$output" ]]; then
585
+ printf '%s\\n' "$output"
586
+ else
587
+ printf '%s\\n' '{}'
588
+ fi
589
+ `,
590
+ };
591
+
592
+ for (const [file, content] of Object.entries(codexWrapperScripts)) {
593
+ const dest = join(codexHooksDir, file);
594
+ writeFileSync(dest, content);
595
+ try { chmodSync(dest, 0o755); } catch { /* best effort */ }
596
+ }
597
+
547
598
  // Dispatcher commands — one per hook event
548
599
  const dispatchers = {
549
600
  SessionStart: { cmd: `node "${join(hooksDir, 'shared', 'session-start.mjs')}"`, timeout: 10 },
@@ -552,6 +603,10 @@ export function installIdeHooks() {
552
603
  PreCompact: { cmd: `node "${join(hooksDir, 'shared', 'pre-compact.mjs')}"`, timeout: 20 },
553
604
  SessionEnd: { cmd: `node "${join(hooksDir, 'shared', 'session-end.mjs')}"`, timeout: 20 },
554
605
  };
606
+ const codexDispatchers = {
607
+ SessionStart: { cmd: `bash "${join(codexHooksDir, 'session-start.sh')}"`, timeout: 10 },
608
+ Stop: { cmd: `bash "${join(codexHooksDir, 'stop.sh')}"`, timeout: 15 },
609
+ };
555
610
 
556
611
  // ── Step 2: Claude Code — wire 4 events (merge, don't replace) ────
557
612
  const claudeDir = join(home, '.claude');
@@ -665,7 +720,7 @@ export function installIdeHooks() {
665
720
  if (!codexHooksFile.hooks) codexHooksFile.hooks = {};
666
721
 
667
722
  // Codex supports: SessionStart, Stop, PreToolUse, PostToolUse, UserPromptSubmit
668
- const codexEvents = { SessionStart: dispatchers.SessionStart, Stop: dispatchers.Stop };
723
+ const codexEvents = { SessionStart: codexDispatchers.SessionStart, Stop: codexDispatchers.Stop };
669
724
  for (const [event, { cmd, timeout }] of Object.entries(codexEvents)) {
670
725
  if (!codexHooksFile.hooks[event]) codexHooksFile.hooks[event] = [];
671
726
 
@@ -710,20 +765,14 @@ export function installIdeHooks() {
710
765
 
711
766
  writeFileSync(codexHooksPath, JSON.stringify(codexHooksFile, null, 2) + '\n');
712
767
 
713
- // Enable codex_hooks feature if not already set
714
768
  const codexConfigPath = join(codexDir, 'config.toml');
715
769
  if (existsSync(codexConfigPath)) {
716
770
  try {
717
- let toml = readFileSync(codexConfigPath, 'utf8');
718
- if (!toml.includes('codex_hooks')) {
719
- // Append under [features] if it exists, or add it
720
- if (toml.includes('[features]')) {
721
- toml = toml.replace('[features]', '[features]\ncodex_hooks = true');
722
- } else {
723
- toml += '\n[features]\ncodex_hooks = true\n';
724
- }
725
- writeFileSync(codexConfigPath, toml);
726
- }
771
+ const toml = readFileSync(codexConfigPath, 'utf8');
772
+ const cleaned = toml
773
+ .replace(/^\s*codex_hooks\s*=\s*(true|false)\s*$(\r?\n)?/m, '')
774
+ .replace(/\n{3,}/g, '\n\n');
775
+ if (cleaned !== toml) writeFileSync(codexConfigPath, cleaned);
727
776
  } catch { /* best effort */ }
728
777
  }
729
778
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghl-ai/aw",
3
- "version": "0.1.37-beta.79",
3
+ "version": "0.1.37-beta.80",
4
4
  "description": "Agentic Workspace CLI — pull, push & manage agents, skills and commands from the registry",
5
5
  "type": "module",
6
6
  "bin": "bin.js",