ccc-notifier 0.6.1 → 0.6.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.
@@ -246,6 +246,10 @@ var DEFAULT_BUDGET_USD = 400;
246
246
  function isPlainObject2(v) {
247
247
  return typeof v === "object" && v !== null && !Array.isArray(v);
248
248
  }
249
+ function maskWebhookUrl(url) {
250
+ if (url.length <= 40) return url;
251
+ return `${url.slice(0, 34)}\u2026${url.slice(-4)}`;
252
+ }
249
253
  function settingsPath() {
250
254
  return process.env.CCCN_CLAUDE_SETTINGS || join2(homedir(), ".claude", "settings.json");
251
255
  }
@@ -547,19 +551,36 @@ async function runInit(argv) {
547
551
  return 1;
548
552
  }
549
553
  if (channel === "both" || channel === "slack") {
550
- const webhook = await p.text({
551
- message: "Slack Incoming Webhook URL",
552
- placeholder: "https://hooks.slack.com/services/...",
553
- validate: (v) => !v || !v.startsWith("https://") ? "https:// \u3067\u59CB\u307E\u308B URL \u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044" : void 0
554
- });
555
- if (p.isCancel(webhook)) {
556
- p.cancel("\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F");
557
- return 1;
554
+ const existingSlack = cfg.notify.slack;
555
+ let webhookUrl;
556
+ if (existingSlack?.webhookUrl) {
557
+ const reuse = await p.confirm({
558
+ message: `\u8A2D\u5B9A\u6E08\u307F\u306E Slack Webhook URL(${maskWebhookUrl(existingSlack.webhookUrl)})\u3092\u305D\u306E\u307E\u307E\u4F7F\u3044\u307E\u3059\u304B?`,
559
+ initialValue: true
560
+ });
561
+ if (p.isCancel(reuse)) {
562
+ p.cancel("\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F");
563
+ return 1;
564
+ }
565
+ if (reuse) webhookUrl = existingSlack.webhookUrl;
566
+ }
567
+ if (webhookUrl === void 0) {
568
+ const webhook = await p.text({
569
+ message: "Slack Incoming Webhook URL",
570
+ placeholder: "https://hooks.slack.com/services/...",
571
+ validate: (v) => !v || !v.startsWith("https://") ? "https:// \u3067\u59CB\u307E\u308B URL \u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044" : void 0
572
+ });
573
+ if (p.isCancel(webhook)) {
574
+ p.cancel("\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F");
575
+ return 1;
576
+ }
577
+ webhookUrl = webhook;
558
578
  }
559
579
  cfg.notify.slack = {
560
- webhookUrl: webhook,
561
- promptChars: SLACK_PROMPT_CHARS,
562
- sendFullPrompt: false
580
+ webhookUrl,
581
+ // promptChars / sendFullPrompt は手動カスタマイズされていることがあるため再 init で維持する。
582
+ promptChars: existingSlack?.promptChars ?? SLACK_PROMPT_CHARS,
583
+ sendFullPrompt: existingSlack?.sendFullPrompt ?? false
563
584
  };
564
585
  cfg.notify.os = channel === "both";
565
586
  } else {
@@ -734,6 +755,7 @@ export {
734
755
  CODEX_HOOK_EVENTS,
735
756
  CODEX_HOOK_TIMEOUT_SECONDS,
736
757
  parseConfiguredOwnedCodexHookCommand,
758
+ maskWebhookUrl,
737
759
  matchesMarker,
738
760
  runInit,
739
761
  runUninstall
@@ -1143,7 +1143,7 @@ function renderDashboard(turns, opts, fullHistory) {
1143
1143
  const refreshMeta = reloadSec > 0 ? `<meta http-equiv="refresh" content="${reloadSec}">` : "";
1144
1144
  const updateTrigger = anyCodex ? "Claude Code / Codex \u306E\u5FDC\u7B54\u5B8C\u4E86\u6642" : "Claude Code \u306E\u5FDC\u7B54\u5B8C\u4E86\u6642";
1145
1145
  const autoUpdateFoot = reloadSec > 0 ? variant === "full" ? `<div class="foot">\u7D04 ${reloadSec} \u79D2\u3054\u3068\u306B\u30D5\u30A1\u30A4\u30EB\u3092\u518D\u8AAD\u8FBC(\u5168\u5C65\u6B74\u7248\u306E\u751F\u6210\u306F\u6B63\u5E38\u306A sweep \u5B8C\u4E86\u6642\u3001\u30ED\u30FC\u30AB\u30EB\u65E5\u3054\u3068\u3001\u307E\u305F\u306F\u624B\u52D5 dashboard --all)</div>` : `<div class="foot">\u7D04 ${reloadSec} \u79D2\u3054\u3068\u306B\u81EA\u52D5\u66F4\u65B0(\u6700\u65B0\u5316\u306F ${updateTrigger}\u3001\u307E\u305F\u306F\u6B63\u5E38\u306A sweep \u5B8C\u4E86\u6642)</div>` : "";
1146
- const variantNav = variant === "recent" ? `<div class="sub"><strong>${recentVariantLabel}</strong> \xB7 ${opts.peerAvailable ? `<a href="report-all.html">\u5168\u5C65\u6B74\u7248\u3078 / Full history</a>` : `<span aria-disabled="true">\u5168\u5C65\u6B74\u7248\u306F\u672A\u751F\u6210\u3067\u3059\uFF08dashboard --all \u3067\u751F\u6210\uFF09 / Full history not generated</span>`}</div>` : variant === "full" ? `<div class="sub"><strong>\u5168\u5C65\u6B74\u7248 / Full history</strong> \xB7 ${opts.peerAvailable ? `<a href="report.html">\u76F4\u8FD1\u7248\u3078 / Recent</a>` : `<span aria-disabled="true">\u76F4\u8FD1\u7248\u306F\u672A\u751F\u6210\u3067\u3059\uFF08dashboard \u3067\u751F\u6210\uFF09 / Recent not generated</span>`}</div><div class="sub muted">\u6700\u7D42\u751F\u6210 ${esc(generatedAt)}\u3002\u6B63\u5E38\u306A sweep \u5B8C\u4E86\u6642\u3001\u30ED\u30FC\u30AB\u30EB\u65E5\u306E\u6700\u521D\u306E\u6B63\u5E38\u306A\u30BF\u30FC\u30F3\u6642\u3001\u307E\u305F\u306F\u624B\u52D5\u306E dashboard --all \u3067\u66F4\u65B0\u3055\u308C\u307E\u3059\u3002</div>` : "";
1146
+ const variantNav = variant === "recent" ? `<div class="sub"><strong>${recentVariantLabel}</strong> \xB7 ${opts.peerAvailable ? `<a href="report-all.html">\u5168\u5C65\u6B74\u7248\u3078 / Full history</a>` : `<span aria-disabled="true">\u5168\u5C65\u6B74\u7248\u306F\u672A\u751F\u6210\u3067\u3059\uFF08dashboard --all \u3067\u751F\u6210\uFF09 / Full history not generated</span>`}</div>` : variant === "full" ? `<div class="sub"><strong>\u5168\u5C65\u6B74\u7248 / Full history</strong> \xB7 ${opts.peerAvailable ? `<a href="report.html">\u76F4\u8FD1\u7248\u3078 / Recent</a>` : `<span aria-disabled="true">\u76F4\u8FD1\u7248\u306F\u672A\u751F\u6210\u3067\u3059\uFF08dashboard \u3067\u751F\u6210\uFF09 / Recent not generated</span>`}</div><div class="sub muted">\u6700\u7D42\u751F\u6210 ${esc(generatedAt)}</div>` : "";
1147
1147
  const head = `<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="color-scheme" content="light dark">` + refreshMeta + `<title>ccc-notifier \u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9</title>` + STYLE + `</head><body><div class="wrap">`;
1148
1148
  const foot = autoUpdateFoot + `<div class="foot">ccc-notifier v${esc(version)} \xB7 \u30C7\u30FC\u30BF\u306F\u30ED\u30FC\u30AB\u30EB\u306E\u307F / all data stays local</div></div><div id="cccn-tip" class="cccn-tip" hidden></div><script id="cccn-data" type="application/json">${dataJson}</script>` + APP_JS + `</body></html>`;
1149
1149
  const budgetSection = budgetCard(budgetUSD, budgetMonth, cfg.fx.fallbackRate, anyCodex, limited);
package/dist/cli.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  CODEX_HOOK_TIMEOUT_SECONDS,
8
8
  matchesMarker,
9
9
  parseConfiguredOwnedCodexHookCommand
10
- } from "./chunk-CH34OJ7Q.js";
10
+ } from "./chunk-OXXDZZPJ.js";
11
11
  import {
12
12
  notifyOS,
13
13
  notifySlack,
@@ -908,7 +908,7 @@ function isCodexPassiveEvent(value) {
908
908
  async function runCodexPassiveHook(event, text) {
909
909
  try {
910
910
  if (event === "Stop") {
911
- const trackMod = await import("./track-WCP7446C.js");
911
+ const trackMod = await import("./track-RBLLR25M.js");
912
912
  await trackMod.runTrack(text, { codex: true });
913
913
  } else if (event === "UserPromptSubmit") {
914
914
  const activity = await import("./subagent-store-US4TJJQR.js");
@@ -993,18 +993,18 @@ async function main(argv) {
993
993
  const text = await readStdin();
994
994
  const codex = rest.includes("--codex");
995
995
  try {
996
- const trackMod = await import("./track-WCP7446C.js");
996
+ const trackMod = await import("./track-RBLLR25M.js");
997
997
  await trackMod.runTrack(text, { codex });
998
998
  } catch {
999
999
  }
1000
1000
  return 0;
1001
1001
  }
1002
1002
  case "init": {
1003
- const { runInit } = await import("./setup-3SRNQ5PG.js");
1003
+ const { runInit } = await import("./setup-I3JNGWZG.js");
1004
1004
  return await runInit(rest);
1005
1005
  }
1006
1006
  case "uninstall": {
1007
- const { runUninstall } = await import("./setup-3SRNQ5PG.js");
1007
+ const { runUninstall } = await import("./setup-I3JNGWZG.js");
1008
1008
  return await runUninstall(rest);
1009
1009
  }
1010
1010
  case "doctor":
@@ -1012,11 +1012,11 @@ async function main(argv) {
1012
1012
  case "report":
1013
1013
  return await runReport(rest);
1014
1014
  case "dashboard": {
1015
- const { runDashboard } = await import("./dashboard-VEKQ4TI3.js");
1015
+ const { runDashboard } = await import("./dashboard-O7LJLYM3.js");
1016
1016
  return await runDashboard(rest);
1017
1017
  }
1018
1018
  case "sweep": {
1019
- const { runSweep } = await import("./sweep-65D57PXU.js");
1019
+ const { runSweep } = await import("./sweep-CONNNBK7.js");
1020
1020
  return await runSweep(rest);
1021
1021
  }
1022
1022
  case "history": {
@@ -3,7 +3,7 @@ import {
3
3
  browserOpenPlan,
4
4
  runDashboard,
5
5
  writeDashboardHtml
6
- } from "./chunk-6UZXXO5J.js";
6
+ } from "./chunk-PYU7CAK2.js";
7
7
  import "./chunk-DGXUSPS4.js";
8
8
  import "./chunk-J5QAYTFE.js";
9
9
  import "./chunk-27SJELD2.js";
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ maskWebhookUrl,
3
4
  matchesMarker,
4
5
  runInit,
5
6
  runUninstall
6
- } from "./chunk-CH34OJ7Q.js";
7
+ } from "./chunk-OXXDZZPJ.js";
7
8
  import "./chunk-NV5UOHJA.js";
8
9
  import "./chunk-HTYUYKFW.js";
9
10
  import "./chunk-6HTETN26.js";
@@ -11,6 +12,7 @@ import "./chunk-DGXUSPS4.js";
11
12
  import "./chunk-J5QAYTFE.js";
12
13
  import "./chunk-OOAC5ULQ.js";
13
14
  export {
15
+ maskWebhookUrl,
14
16
  matchesMarker,
15
17
  runInit,
16
18
  runUninstall
@@ -20,7 +20,7 @@ import {
20
20
  } from "./chunk-6HTETN26.js";
21
21
  import {
22
22
  writeDashboardHtml
23
- } from "./chunk-6UZXXO5J.js";
23
+ } from "./chunk-PYU7CAK2.js";
24
24
  import "./chunk-DGXUSPS4.js";
25
25
  import {
26
26
  formatJPY,
@@ -17,7 +17,7 @@ import {
17
17
  } from "./chunk-6HTETN26.js";
18
18
  import {
19
19
  writeDashboardHtml
20
- } from "./chunk-6UZXXO5J.js";
20
+ } from "./chunk-PYU7CAK2.js";
21
21
  import "./chunk-DGXUSPS4.js";
22
22
  import "./chunk-J5QAYTFE.js";
23
23
  import {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccc-notifier",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "Claude Code Cost notifier (now also covers Codex CLI): per-prompt cost notifications (USD/JPY) with local history and HTML dashboard",
5
5
  "keywords": [
6
6
  "claude",