clisponsor 1.0.4 → 1.0.6

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/bin/clisponsor.mjs +64 -17
  2. package/package.json +1 -1
@@ -15,6 +15,7 @@ const DEFAULT_SERVE_BASE_URL =
15
15
  const DEFAULT_BACKEND_BASE_URL = process.env.CLISPONSOR_BACKEND_BASE_URL || "https://backend.clisponsor.com";
16
16
  const HOOK_VERSION = "1.0.0";
17
17
  const NETWORK_TIMEOUT_MS = 3000;
18
+ const ANTIGRAVITY_EVENTS = ["PreInvocation", "UserPromptSubmit", "PostInvocation", "Stop"];
18
19
 
19
20
  function argValue(name) {
20
21
  const prefix = `${name}=`;
@@ -130,6 +131,23 @@ function chmodExecutable(file) {
130
131
  }
131
132
 
132
133
  function commandExists(command) {
134
+ const paths = String(process.env.PATH || "").split(path.delimiter).filter(Boolean);
135
+ const extensions = process.platform === "win32" ? String(process.env.PATHEXT || ".EXE;.CMD;.BAT").split(";") : [""];
136
+ for (const directory of paths) {
137
+ for (const extension of extensions) {
138
+ const candidate = path.join(directory, command + extension.toLowerCase());
139
+ try {
140
+ fs.accessSync(candidate, fs.constants.X_OK);
141
+ return true;
142
+ } catch {}
143
+ if (extension) {
144
+ try {
145
+ fs.accessSync(path.join(directory, command + extension.toUpperCase()), fs.constants.X_OK);
146
+ return true;
147
+ } catch {}
148
+ }
149
+ }
150
+ }
133
151
  try {
134
152
  execFileSync(command, ["--version"], { stdio: "ignore" });
135
153
  return true;
@@ -140,15 +158,15 @@ function commandExists(command) {
140
158
 
141
159
  function isClisponsorCommand(value) {
142
160
  return (
143
- typeof value === "string" &&
144
- (value.includes("clisponsor_claude_hook.mjs") ||
145
- value.includes("clisponsor_gemini_hook.mjs") ||
146
- value.includes("clisponsor_antigravity_hook.mjs") ||
147
- value.includes(`${path.sep}.clisponsor${path.sep}`) ||
148
- value.includes("/.clisponsor/") ||
149
- value.includes("\\.clisponsor\\"))
150
- );
151
- }
161
+ typeof value === "string" &&
162
+ (value.includes("clisponsor_claude_hook.mjs") ||
163
+ value.includes("clisponsor_gemini_hook.mjs") ||
164
+ value.includes("clisponsor_antigravity_hook.mjs") ||
165
+ value.includes(`${path.sep}.clisponsor${path.sep}`) ||
166
+ value.includes("/.clisponsor/") ||
167
+ value.includes("\\.clisponsor\\"))
168
+ );
169
+ }
152
170
 
153
171
  function isClisponsorHookEntry(entry) {
154
172
  if (!isPlainObject(entry)) return false;
@@ -245,6 +263,29 @@ function removeClaudeCommandHooks(settings) {
245
263
  return changed;
246
264
  }
247
265
 
266
+ function setAntigravityCommandHooks(settings, hookPath) {
267
+ removeClaudeCommandHooks(settings);
268
+ settings.clisponsor = Object.fromEntries(
269
+ ANTIGRAVITY_EVENTS.map((eventName) => [
270
+ eventName,
271
+ [
272
+ {
273
+ type: "command",
274
+ command: `node ${JSON.stringify(hookPath)} ${eventName}`,
275
+ timeout: 5,
276
+ },
277
+ ],
278
+ ]),
279
+ );
280
+ }
281
+
282
+ function removeAntigravityCommandHooks(settings) {
283
+ const removedLegacyHooks = removeClaudeCommandHooks(settings);
284
+ const removedNativeHooks = Object.hasOwn(settings, "clisponsor");
285
+ if (removedNativeHooks) delete settings.clisponsor;
286
+ return removedLegacyHooks || removedNativeHooks;
287
+ }
288
+
248
289
  async function registerDevice() {
249
290
  const email = positionalArg(3);
250
291
  if (!email) {
@@ -361,13 +402,15 @@ function installClaude() {
361
402
  console.log("Claude Code CLI hook installed.");
362
403
  }
363
404
 
364
- function agentHookSource(client) {
405
+ function agentHookSource(client, options = {}) {
406
+ const outputMode = options.outputMode || "systemMessage";
365
407
  return `#!/usr/bin/env node
366
408
  import fs from "node:fs";
367
409
  import crypto from "node:crypto";
368
410
  const cfg = JSON.parse(fs.readFileSync(${JSON.stringify(CONFIG_PATH)}, "utf8"));
369
411
  const event = process.argv[2] || "BeforeAgent";
370
- const placements = { SessionStart: "StartSession", BeforeAgent: "StartTurn", AfterAgent: "EndTurn", StartTurn: "StartTurn" };
412
+ const outputMode = ${JSON.stringify(outputMode)};
413
+ const placements = { SessionStart: "StartSession", PreInvocation: "StartSession", BeforeAgent: "StartTurn", UserPromptSubmit: "StartTurn", PreToolUse: "StartTurn", AfterAgent: "EndTurn", PostInvocation: "EndTurn", Stop: "EndTurn", StartTurn: "StartTurn" };
371
414
  const serveBaseUrl = cfg.serveBaseUrl || cfg.apiBaseUrl;
372
415
  function sponsoredLine(line) {
373
416
  return "[Sponsored] " + line;
@@ -395,7 +438,13 @@ try {
395
438
  });
396
439
  if (res.ok) {
397
440
  const ad = await res.json();
398
- if (ad.display_line) console.log(JSON.stringify({ systemMessage: sponsoredLine(ad.display_line) }));
441
+ if (outputMode === "antigravity") {
442
+ const payload = { decision: "allow" };
443
+ if (ad.display_line) payload.systemMessage = sponsoredLine(ad.display_line);
444
+ console.log(JSON.stringify(payload));
445
+ } else if (ad.display_line) {
446
+ console.log(JSON.stringify({ systemMessage: sponsoredLine(ad.display_line) }));
447
+ }
399
448
  }
400
449
  } catch {
401
450
  process.exit(0);
@@ -433,13 +482,11 @@ function installAntigravity() {
433
482
  const antigravityDir = path.join(CONFIG_DIR, "antigravity");
434
483
  fs.mkdirSync(antigravityDir, { recursive: true });
435
484
  const hookPath = path.join(antigravityDir, "clisponsor_antigravity_hook.mjs");
436
- fs.writeFileSync(hookPath, agentHookSource("Antigravity"), { mode: 0o755 });
485
+ fs.writeFileSync(hookPath, agentHookSource("Antigravity", { outputMode: "antigravity" }), { mode: 0o755 });
437
486
 
438
487
  const hooksPath = path.join(HOME, ".gemini", "config", "hooks.json");
439
488
  const hooksConfig = readEditableJson(hooksPath, {});
440
- addGeminiCommandHook(hooksConfig, "SessionStart", "startup", `node ${JSON.stringify(hookPath)} SessionStart`);
441
- addGeminiCommandHook(hooksConfig, "BeforeAgent", "*", `node ${JSON.stringify(hookPath)} BeforeAgent`);
442
- addGeminiCommandHook(hooksConfig, "AfterAgent", "*", `node ${JSON.stringify(hookPath)} AfterAgent`);
489
+ setAntigravityCommandHooks(hooksConfig, hookPath);
443
490
  writeJson(hooksPath, hooksConfig);
444
491
  console.log(`Updated ${hooksPath}`);
445
492
  console.log("Antigravity CLI hook installed.");
@@ -502,7 +549,7 @@ function uninstallGemini() {
502
549
  function uninstallAntigravity() {
503
550
  const hooksPath = path.join(HOME, ".gemini", "config", "hooks.json");
504
551
  const hooksConfig = readEditableJson(hooksPath, {});
505
- if (removeClaudeCommandHooks(hooksConfig)) {
552
+ if (removeAntigravityCommandHooks(hooksConfig)) {
506
553
  writeJson(hooksPath, hooksConfig);
507
554
  console.log(`Removed CLIsponsor hooks from ${hooksPath}`);
508
555
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clisponsor",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "CLIsponsor installer for Codex, Claude Code, and Gemini sponsored CLI placements.",
5
5
  "type": "module",
6
6
  "engines": {