@suwujs/codex-vault 0.5.1 → 0.5.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suwujs/codex-vault",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Persistent knowledge vault for LLM agents (Claude Code, Codex CLI)",
5
5
  "license": "MIT",
6
6
  "repository": {
package/plugin/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.1
1
+ 0.5.3
@@ -273,27 +273,30 @@ def main():
273
273
 
274
274
  if parts:
275
275
  context = "\n\n".join(parts)
276
+
277
+ # Build feedback label
278
+ matched = [s for s in SIGNALS if _match(s["patterns"], prompt.lower())]
279
+ feedback_parts = []
280
+ for s in matched:
281
+ feedback_parts.append(f"{s['name']} → {s['skill']}")
282
+ if is_session_end(prompt):
283
+ feedback_parts.append("SESSION END → /wrap-up")
284
+ icon = "🔄" if mode == "auto" else "💡"
285
+ label = ", ".join(feedback_parts) if feedback_parts else "intent detected"
286
+
287
+ # Hook trigger notification
288
+ print(f" {icon} vault: {label}")
289
+
276
290
  output = {
277
291
  "hookSpecificOutput": {
278
292
  "hookEventName": "UserPromptSubmit",
279
293
  "additionalContext": context
280
- }
294
+ },
295
+ "systemMessage": f"{icon} vault: {label}"
281
296
  }
282
297
  json.dump(output, sys.stdout)
283
298
  sys.stdout.flush()
284
299
 
285
- # Visible feedback to user terminal (stderr)
286
- matched = [s for s in SIGNALS if _match(s["patterns"], prompt.lower())]
287
- parts = []
288
- for s in matched:
289
- parts.append(f"{s['name']} → {s['skill']}")
290
- if is_session_end(prompt):
291
- parts.append("SESSION END → /wrap-up")
292
- if parts:
293
- label = ", ".join(parts)
294
- icon = "🔄" if mode == "auto" else "💡"
295
- print(f" {icon} vault: {label}", file=sys.stderr)
296
-
297
300
  sys.exit(0)
298
301
 
299
302
 
@@ -343,6 +343,23 @@ def _build_banner(vault_dir):
343
343
  # ── Main ───────────────────────────────────────────────────────────────
344
344
 
345
345
 
346
+ def _detect_platform():
347
+ """Detect whether we're running under Claude Code or Codex CLI."""
348
+ if os.environ.get("CLAUDE_PROJECT_DIR"):
349
+ return "claude"
350
+ if os.environ.get("CODEX_PROJECT_DIR") or os.environ.get("CODEX_HOME"):
351
+ return "codex"
352
+ # Fallback: check parent process name
353
+ try:
354
+ ppid = os.getppid()
355
+ cmdline = Path(f"/proc/{ppid}/cmdline").read_text() if os.path.exists(f"/proc/{ppid}/cmdline") else ""
356
+ if "codex" in cmdline.lower():
357
+ return "codex"
358
+ except Exception:
359
+ pass
360
+ return "claude" # default
361
+
362
+
346
363
  def main():
347
364
  vault_dir = _find_vault_root()
348
365
  if not vault_dir:
@@ -355,6 +372,13 @@ def main():
355
372
  json.dump(output, sys.stdout)
356
373
  sys.exit(0)
357
374
 
375
+ # Read hook input for session metadata
376
+ try:
377
+ event = json.load(sys.stdin)
378
+ except Exception:
379
+ event = {}
380
+
381
+ platform = _detect_platform()
358
382
  context = _build_context(vault_dir)
359
383
  banner = _build_banner(vault_dir)
360
384
 
@@ -363,9 +387,16 @@ def main():
363
387
  "hookEventName": "SessionStart",
364
388
  "additionalContext": context
365
389
  },
366
- "systemMessage": banner
367
390
  }
368
391
 
392
+ if platform == "claude":
393
+ # Claude Code renders systemMessage in terminal
394
+ output["systemMessage"] = banner
395
+ else:
396
+ # Codex CLI: systemMessage not rendered by TUI,
397
+ # use stderr for terminal visibility (best effort)
398
+ sys.stderr.write(banner + "\n")
399
+
369
400
  json.dump(output, sys.stdout)
370
401
  sys.stdout.flush()
371
402
  sys.exit(0)
@@ -94,23 +94,26 @@ def main():
94
94
 
95
95
  if warnings:
96
96
  hint_list = "\n".join(f" - {w}" for w in warnings)
97
+ count = len(warnings)
98
+ first = warnings[0]
99
+ if count == 1:
100
+ feedback = f"⚠️ vault: {basename} — {first}"
101
+ else:
102
+ feedback = f"⚠️ vault: {basename} — {first} (+{count - 1} more)"
103
+
104
+ # Hook trigger notification
105
+ print(f" {feedback}")
106
+
97
107
  output = {
98
108
  "hookSpecificOutput": {
99
109
  "hookEventName": "PostToolUse",
100
110
  "additionalContext": f"Vault warnings for `{basename}`:\n{hint_list}\nFix these before moving on."
101
- }
111
+ },
112
+ "systemMessage": feedback
102
113
  }
103
114
  json.dump(output, sys.stdout)
104
115
  sys.stdout.flush()
105
116
 
106
- # Visible feedback to user terminal (stderr)
107
- count = len(warnings)
108
- first = warnings[0]
109
- if count == 1:
110
- print(f" ⚠️ vault: {basename} — {first}", file=sys.stderr)
111
- else:
112
- print(f" ⚠️ vault: {basename} — {first} (+{count - 1} more)", file=sys.stderr)
113
-
114
117
  sys.exit(0)
115
118
 
116
119
 
@@ -273,27 +273,30 @@ def main():
273
273
 
274
274
  if parts:
275
275
  context = "\n\n".join(parts)
276
+
277
+ # Build feedback label
278
+ matched = [s for s in SIGNALS if _match(s["patterns"], prompt.lower())]
279
+ feedback_parts = []
280
+ for s in matched:
281
+ feedback_parts.append(f"{s['name']} → {s['skill']}")
282
+ if is_session_end(prompt):
283
+ feedback_parts.append("SESSION END → /wrap-up")
284
+ icon = "🔄" if mode == "auto" else "💡"
285
+ label = ", ".join(feedback_parts) if feedback_parts else "intent detected"
286
+
287
+ # Hook trigger notification
288
+ print(f" {icon} vault: {label}")
289
+
276
290
  output = {
277
291
  "hookSpecificOutput": {
278
292
  "hookEventName": "UserPromptSubmit",
279
293
  "additionalContext": context
280
- }
294
+ },
295
+ "systemMessage": f"{icon} vault: {label}"
281
296
  }
282
297
  json.dump(output, sys.stdout)
283
298
  sys.stdout.flush()
284
299
 
285
- # Visible feedback to user terminal (stderr)
286
- matched = [s for s in SIGNALS if _match(s["patterns"], prompt.lower())]
287
- parts = []
288
- for s in matched:
289
- parts.append(f"{s['name']} → {s['skill']}")
290
- if is_session_end(prompt):
291
- parts.append("SESSION END → /wrap-up")
292
- if parts:
293
- label = ", ".join(parts)
294
- icon = "🔄" if mode == "auto" else "💡"
295
- print(f" {icon} vault: {label}", file=sys.stderr)
296
-
297
300
  sys.exit(0)
298
301
 
299
302
 
@@ -343,6 +343,23 @@ def _build_banner(vault_dir):
343
343
  # ── Main ───────────────────────────────────────────────────────────────
344
344
 
345
345
 
346
+ def _detect_platform():
347
+ """Detect whether we're running under Claude Code or Codex CLI."""
348
+ if os.environ.get("CLAUDE_PROJECT_DIR"):
349
+ return "claude"
350
+ if os.environ.get("CODEX_PROJECT_DIR") or os.environ.get("CODEX_HOME"):
351
+ return "codex"
352
+ # Fallback: check parent process name
353
+ try:
354
+ ppid = os.getppid()
355
+ cmdline = Path(f"/proc/{ppid}/cmdline").read_text() if os.path.exists(f"/proc/{ppid}/cmdline") else ""
356
+ if "codex" in cmdline.lower():
357
+ return "codex"
358
+ except Exception:
359
+ pass
360
+ return "claude" # default
361
+
362
+
346
363
  def main():
347
364
  vault_dir = _find_vault_root()
348
365
  if not vault_dir:
@@ -355,6 +372,13 @@ def main():
355
372
  json.dump(output, sys.stdout)
356
373
  sys.exit(0)
357
374
 
375
+ # Read hook input for session metadata
376
+ try:
377
+ event = json.load(sys.stdin)
378
+ except Exception:
379
+ event = {}
380
+
381
+ platform = _detect_platform()
358
382
  context = _build_context(vault_dir)
359
383
  banner = _build_banner(vault_dir)
360
384
 
@@ -363,9 +387,16 @@ def main():
363
387
  "hookEventName": "SessionStart",
364
388
  "additionalContext": context
365
389
  },
366
- "systemMessage": banner
367
390
  }
368
391
 
392
+ if platform == "claude":
393
+ # Claude Code renders systemMessage in terminal
394
+ output["systemMessage"] = banner
395
+ else:
396
+ # Codex CLI: systemMessage not rendered by TUI,
397
+ # use stderr for terminal visibility (best effort)
398
+ sys.stderr.write(banner + "\n")
399
+
369
400
  json.dump(output, sys.stdout)
370
401
  sys.stdout.flush()
371
402
  sys.exit(0)
@@ -94,23 +94,26 @@ def main():
94
94
 
95
95
  if warnings:
96
96
  hint_list = "\n".join(f" - {w}" for w in warnings)
97
+ count = len(warnings)
98
+ first = warnings[0]
99
+ if count == 1:
100
+ feedback = f"⚠️ vault: {basename} — {first}"
101
+ else:
102
+ feedback = f"⚠️ vault: {basename} — {first} (+{count - 1} more)"
103
+
104
+ # Hook trigger notification
105
+ print(f" {feedback}")
106
+
97
107
  output = {
98
108
  "hookSpecificOutput": {
99
109
  "hookEventName": "PostToolUse",
100
110
  "additionalContext": f"Vault warnings for `{basename}`:\n{hint_list}\nFix these before moving on."
101
- }
111
+ },
112
+ "systemMessage": feedback
102
113
  }
103
114
  json.dump(output, sys.stdout)
104
115
  sys.stdout.flush()
105
116
 
106
- # Visible feedback to user terminal (stderr)
107
- count = len(warnings)
108
- first = warnings[0]
109
- if count == 1:
110
- print(f" ⚠️ vault: {basename} — {first}", file=sys.stderr)
111
- else:
112
- print(f" ⚠️ vault: {basename} — {first} (+{count - 1} more)", file=sys.stderr)
113
-
114
117
  sys.exit(0)
115
118
 
116
119