@devness/useai-cli 0.4.13 → 0.4.14

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/dist/index.js +57 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ var SYSTEMD_SERVICE_PATH = join(homedir(), ".config", "systemd", "user", "useai-
30
30
  var WINDOWS_STARTUP_SCRIPT_PATH = join(process.env["APPDATA"] ?? join(homedir(), "AppData", "Roaming"), "Microsoft", "Windows", "Start Menu", "Programs", "Startup", "useai-daemon.vbs");
31
31
 
32
32
  // ../shared/dist/constants/version.js
33
- var VERSION = "0.4.13";
33
+ var VERSION = "0.4.14";
34
34
 
35
35
  // ../shared/dist/constants/defaults.js
36
36
  var DEFAULT_CONFIG = {
@@ -4881,6 +4881,7 @@ import { existsSync as existsSync7, readFileSync as readFileSync3, writeFileSync
4881
4881
  import { join as join3 } from "path";
4882
4882
  import { homedir as homedir3 } from "os";
4883
4883
  var STOP_GUARD_PATH = join3(USEAI_HOOKS_DIR, "stop-guard.js");
4884
+ var PROMPT_GUARD_PATH = join3(USEAI_HOOKS_DIR, "prompt-guard.js");
4884
4885
  var CLAUDE_SETTINGS_PATH = join3(homedir3(), ".claude", "settings.json");
4885
4886
  var STOP_GUARD_SCRIPT = `#!/usr/bin/env node
4886
4887
  'use strict';
@@ -4906,6 +4907,30 @@ process.stdin.on('end', () => {
4906
4907
  } catch { process.exit(0); }
4907
4908
  });
4908
4909
  `;
4910
+ var PROMPT_GUARD_SCRIPT = `#!/usr/bin/env node
4911
+ 'use strict';
4912
+ const { readFileSync } = require('node:fs');
4913
+ let input = '';
4914
+ process.stdin.setEncoding('utf-8');
4915
+ process.stdin.on('data', chunk => input += chunk);
4916
+ process.stdin.on('end', () => {
4917
+ try {
4918
+ const hook = JSON.parse(input);
4919
+ if (!hook.transcript_path) process.exit(0);
4920
+ let transcript;
4921
+ try { transcript = readFileSync(hook.transcript_path, 'utf-8'); } catch { process.exit(0); }
4922
+ var starts = (transcript.match(/useai_session_start/g) || []).length;
4923
+ var ends = (transcript.match(/useai_session_end/g) || []).length;
4924
+ if (starts > ends) process.exit(0);
4925
+ process.stdout.write(JSON.stringify({
4926
+ hookSpecificOutput: {
4927
+ hookEventName: 'UserPromptSubmit',
4928
+ additionalContext: 'UseAI: Call useai_session_start with the appropriate task_type before doing any work.'
4929
+ }
4930
+ }));
4931
+ } catch { process.exit(0); }
4932
+ });
4933
+ `;
4909
4934
  function readSettings() {
4910
4935
  if (!existsSync7(CLAUDE_SETTINGS_PATH))
4911
4936
  return {};
@@ -4922,15 +4947,32 @@ function writeSettings(settings) {
4922
4947
  function installClaudeCodeHooks() {
4923
4948
  mkdirSync3(USEAI_HOOKS_DIR, { recursive: true });
4924
4949
  writeFileSync3(STOP_GUARD_PATH, STOP_GUARD_SCRIPT);
4950
+ writeFileSync3(PROMPT_GUARD_PATH, PROMPT_GUARD_SCRIPT);
4925
4951
  try {
4926
4952
  chmodSync(STOP_GUARD_PATH, "755");
4927
4953
  } catch {
4928
4954
  }
4955
+ try {
4956
+ chmodSync(PROMPT_GUARD_PATH, "755");
4957
+ } catch {
4958
+ }
4929
4959
  const settings = readSettings();
4930
4960
  const hooks = settings["hooks"] ?? {};
4961
+ const promptCmd = `node "${PROMPT_GUARD_PATH}"`;
4931
4962
  const stopCmd = `node "${STOP_GUARD_PATH}"`;
4932
4963
  const sealCmd = `curl -sf -X POST http://127.0.0.1:${DAEMON_PORT}/api/seal-active --max-time 3 2>/dev/null || true`;
4933
4964
  let changed = false;
4965
+ if (!hooks["UserPromptSubmit"])
4966
+ hooks["UserPromptSubmit"] = [];
4967
+ const promptArr = hooks["UserPromptSubmit"];
4968
+ const hasPrompt = promptArr.some((g) => {
4969
+ const inner = g["hooks"];
4970
+ return inner?.some((h) => h["command"]?.includes("prompt-guard"));
4971
+ });
4972
+ if (!hasPrompt) {
4973
+ promptArr.push({ hooks: [{ type: "command", command: promptCmd, timeout: 10 }] });
4974
+ changed = true;
4975
+ }
4934
4976
  if (!hooks["Stop"])
4935
4977
  hooks["Stop"] = [];
4936
4978
  const stopArr = hooks["Stop"];
@@ -4963,6 +5005,14 @@ function removeClaudeCodeHooks() {
4963
5005
  const settings = readSettings();
4964
5006
  const hooks = settings["hooks"];
4965
5007
  if (hooks) {
5008
+ if (hooks["UserPromptSubmit"]) {
5009
+ hooks["UserPromptSubmit"] = hooks["UserPromptSubmit"].filter((g) => {
5010
+ const inner = g["hooks"];
5011
+ return !inner?.some((h) => h["command"]?.includes("prompt-guard"));
5012
+ });
5013
+ if (hooks["UserPromptSubmit"].length === 0)
5014
+ delete hooks["UserPromptSubmit"];
5015
+ }
4966
5016
  if (hooks["Stop"]) {
4967
5017
  hooks["Stop"] = hooks["Stop"].filter((g) => {
4968
5018
  const inner = g["hooks"];
@@ -4991,6 +5041,11 @@ function removeClaudeCodeHooks() {
4991
5041
  unlinkSync3(STOP_GUARD_PATH);
4992
5042
  } catch {
4993
5043
  }
5044
+ try {
5045
+ if (existsSync7(PROMPT_GUARD_PATH))
5046
+ unlinkSync3(PROMPT_GUARD_PATH);
5047
+ } catch {
5048
+ }
4994
5049
  }
4995
5050
 
4996
5051
  // src/services/tools.ts
@@ -5583,7 +5638,7 @@ async function daemonInstallFlow(tools, explicit) {
5583
5638
  try {
5584
5639
  const hooksInstalled = installClaudeCodeHooks();
5585
5640
  if (hooksInstalled) {
5586
- console.log(success("\u2713 Claude Code hooks installed (Stop + SessionEnd)"));
5641
+ console.log(success("\u2713 Claude Code hooks installed (UserPromptSubmit + Stop + SessionEnd)"));
5587
5642
  }
5588
5643
  } catch {
5589
5644
  console.log(chalk6.yellow(" \u26A0 Could not install Claude Code hooks"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devness/useai-cli",
3
- "version": "0.4.13",
3
+ "version": "0.4.14",
4
4
  "description": "CLI tool for useai.dev — stats, sync, publish your AI development workflow",
5
5
  "author": "nabeelkausari",
6
6
  "license": "MIT",