tokentracker-cli 0.87.6 → 0.87.8
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/LICENSE +1 -1
- package/README.de.md +32 -32
- package/README.ja.md +31 -31
- package/README.ko.md +31 -31
- package/README.md +37 -36
- package/README.zh-CN.md +34 -33
- package/dashboard/dist/assets/{AchievementBadge-BRh6I-jK.js → AchievementBadge-CpxX02OK.js} +1 -1
- package/dashboard/dist/assets/{AchievementsPage-BsAJOqK8.js → AchievementsPage-CSms8IjI.js} +2 -2
- package/dashboard/dist/assets/{AchievementsSection-DebeB3vT.js → AchievementsSection-Sm43tnkh.js} +1 -1
- package/dashboard/dist/assets/{BadgeDetailModal-DniVJwrw.js → BadgeDetailModal-cSNqMLsK.js} +1 -1
- package/dashboard/dist/assets/{Card-DvKbmZEl.js → Card-wNwNRVSb.js} +1 -1
- package/dashboard/dist/assets/{ClawdAnimated-DCyXpvgK.js → ClawdAnimated-S8sIS2Ca.js} +1 -1
- package/dashboard/dist/assets/{CommandPalette-BadO9q-D.js → CommandPalette-DVeiwbPM.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-DzBeGuLk.js → CommunityStatsModal-g5P4j3um.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-BLppThU-.js → ConfirmModal-2P2D5iIp.js} +1 -1
- package/dashboard/dist/assets/{Controls-BBVOO6-V.js → Controls-CCaotoQP.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-DgV2-5pv.js → DashboardPage-DxPGTJpe.js} +1 -1
- package/dashboard/dist/assets/{DevicePage-BZ8Z3veC.js → DevicePage-_nLwNash.js} +1 -1
- package/dashboard/dist/assets/{DialogClose-Be7JwC-H.js → DialogClose-D0giFwO3.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-8veCvaUb.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-Bgr5ftrn.js → DialogTitle-JS_04eUC.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-Cc5Grbxc.js → FadeIn-tFzTWDkC.js} +1 -1
- package/dashboard/dist/assets/HeaderGithubStar-B2EUJUTH.js +1 -0
- package/dashboard/dist/assets/{HoverTooltip-BwRvWZqo.js → HoverTooltip-BJzHksPT.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-Ce4dWLI1.js → IpCheckPage-B8mA0mut.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-CuDfsomP.js → LandingPage-DmJZDKr9.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardAvatar-D50UCqhG.js → LeaderboardAvatar-CDeRQUCg.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-fXYjgVOH.js → LeaderboardPage-Dkgm89kY.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardProfileModal-DiIM1-8L.js → LeaderboardProfileModal-B6_kuR1z.js} +3 -3
- package/dashboard/dist/assets/{LeaderboardProfilePage-UzcVaHbK.js → LeaderboardProfilePage-BRs8sJBV.js} +2 -2
- package/dashboard/dist/assets/LimitsPage-DZ1s5NWV.js +4 -0
- package/dashboard/dist/assets/LocalOnlyNotice-Cu_hSnux.js +1 -0
- package/dashboard/dist/assets/{LoginCard-e4xbbFLq.js → LoginCard-yDZbGsHR.js} +1 -1
- package/dashboard/dist/assets/{LoginModal-CLxWc3FD.js → LoginModal-DEvzCUfQ.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-sf34MK6Q.js → LoginPage-DBySF9do.js} +1 -1
- package/dashboard/dist/assets/{PetPage-BA_BAFKG.js → PetPage-DnzH9t-r.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-BwFAXu-Z.js → PopoverPopup-DgFsEMax.js} +1 -1
- package/dashboard/dist/assets/{ProviderIcon-MRSlzNzV.js → ProviderIcon-BEixe-xP.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-DJAq2p4v.js → ResetPasswordPage-excKqsCL.js} +1 -1
- package/dashboard/dist/assets/{SegmentedControl-LWEqN03-.js → SegmentedControl-DDFkH64o.js} +1 -1
- package/dashboard/dist/assets/{Select-tkoxDrUN.js → Select-ChEPIuJf.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-bBnvuF48.js → SelectItemText--b7ISnJm.js} +1 -1
- package/dashboard/dist/assets/{ServiceStatusPage-DDGNQfQ1.js → ServiceStatusPage-DtAY-Qnn.js} +1 -1
- package/dashboard/dist/assets/{SessionsPage-x7-I3BLn.js → SessionsPage-CKFglvuj.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-ColZX8Yi.js → SettingsPage-s0605qWg.js} +1 -1
- package/dashboard/dist/assets/{SkillsPage-DELWPebQ.js → SkillsPage-DTsbCucq.js} +1 -1
- package/dashboard/dist/assets/{TokenGalaxy-Bz8Cto8i.js → TokenGalaxy-C_M7q8S4.js} +1 -1
- package/dashboard/dist/assets/{ToolbarRootContext-BvOVtmfA.js → ToolbarRootContext-CXQwpea-.js} +1 -1
- package/dashboard/dist/assets/{TrendMonitor-DuNGP2Rf.js → TrendMonitor-1Yhlplf0.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-CRGlX9WP.js → WidgetsPage-DC6pmtld.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-DQ3hLeL1.js → WrappedPage-DixoqR13.js} +1 -1
- package/dashboard/dist/assets/{__vite-browser-external-CGdlUam8.js → __vite-browser-external-5aLUeBkM.js} +6 -4
- package/dashboard/dist/assets/{agent-logos-FfNeyajM.js → agent-logos-DILTbPLg.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-BEQHH_0c.js → arrow-up-right-DgIDgjVW.js} +1 -1
- package/dashboard/dist/assets/{check-Bl_xgq6c.js → check-Bz6l09VH.js} +1 -1
- package/dashboard/dist/assets/{chevron-right-YO2OTiWy.js → chevron-right-EvGQXbI3.js} +1 -1
- package/dashboard/dist/assets/{copy-DtRgnD2D.js → copy-DbsB0OVy.js} +1 -1
- package/dashboard/dist/assets/{download-BiCrU4Wh.js → download-R8nUvXYh.js} +1 -1
- package/dashboard/dist/assets/{external-link-CVogXP9K.js → external-link-x0oNzGeq.js} +1 -1
- package/dashboard/dist/assets/{flame-GFlQvi3d.js → flame-Bo4IdG6k.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-BZrnF3-R.js → format-tokens-BSGC1-Gz.js} +1 -1
- package/dashboard/dist/assets/{icons-CzzsWeR-.js → icons-D0Okncmo.js} +1 -1
- package/dashboard/dist/assets/{index-mrU077Y8.js → index-BbOkC6wf.js} +1 -1
- package/dashboard/dist/assets/{index-CyOwnTlp.js → index-Bvvmei-I.js} +1 -1
- package/dashboard/dist/assets/{index-B1S00F5t.js → index-D6F8eNr_.js} +1 -1
- package/dashboard/dist/assets/{info-CL-k0W8L.js → info-DXXKNpLG.js} +1 -1
- package/dashboard/dist/assets/{limits-providers-DGKlD0uY.js → limits-providers-DYa4fdsE.js} +1 -1
- package/dashboard/dist/assets/{link-2-DOsRG9tT.js → link-2-C9mxEnT6.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-Da-W_cCG.js → loader-circle-Y8V8Mq9L.js} +1 -1
- package/dashboard/dist/assets/{maximize-2-CPp2Asek.js → maximize-2-QuP69Xcg.js} +1 -1
- package/dashboard/dist/assets/{modifiers.esm-B0cihd2s.js → modifiers.esm-B3SleRKs.js} +1 -1
- package/dashboard/dist/assets/{monitor-smartphone-CLMr7OcT.js → monitor-smartphone-B2LslYi7.js} +1 -1
- package/dashboard/dist/assets/{provider-display-h1GGY5sy.js → provider-display-DzBwrDZp.js} +2 -2
- package/dashboard/dist/assets/{react-BXj1W2tW.js → react-BooKG84W.js} +1 -1
- package/dashboard/dist/assets/{search-DTwQkbLa.js → search-zdYuHmL-.js} +1 -1
- package/dashboard/dist/assets/{skills-api-B7_r_5CR.js → skills-api-C2IkKfwE.js} +1 -1
- package/dashboard/dist/assets/{sortable.esm-Ba4_NOAf.js → sortable.esm-BHvl5vG5.js} +1 -1
- package/dashboard/dist/assets/{store-CZZj0fmU.js → store-BBP4jx0R.js} +1 -1
- package/dashboard/dist/assets/{terminal-Dd0uhXcN.js → terminal-C0nhFNQ0.js} +1 -1
- package/dashboard/dist/assets/{trash-2-CyBqbulx.js → trash-2-DNVSqbxA.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-D657285K.js → use-community-stats-BK070d1s.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-z0wBtxb1.js → use-limits-display-prefs-BXOUxblO.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-CiIuzdVF.js → use-ordered-list-0SVHZHaW.js} +1 -1
- package/dashboard/dist/assets/use-reduced-motion-abZbtoVS.js +1 -0
- package/dashboard/dist/assets/{use-session-efficiency-pref-BiHWvNJQ.js → use-session-efficiency-pref-eaUpwuLK.js} +1 -1
- package/dashboard/dist/assets/{use-transform-DcbCiXLq.js → use-transform-Bhar2U4w.js} +1 -1
- package/dashboard/dist/assets/{use-usage-limits-tUq-_GSd.js → use-usage-limits-BGGCMVzi.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-BlOEzUvV.js → useCurrency-gIJVmq3w.js} +1 -1
- package/dashboard/dist/assets/{useScrollLock-CFKQBf15.js → useScrollLock-BhFzeRtR.js} +1 -1
- package/dashboard/dist/assets/{useTokenFormat-ggxahHK0.js → useTokenFormat-BZ8WT-A6.js} +1 -1
- package/dashboard/dist/assets/{zap-De7YrxAq.js → zap-Dvc_Jt1t.js} +1 -1
- package/dashboard/dist/brand-logos/omp.svg +33 -0
- package/dashboard/dist/brand-logos/pi.svg +16 -0
- package/dashboard/dist/index.html +7 -7
- package/dashboard/dist/ip-check.html +1 -1
- package/dashboard/dist/leaderboard.html +1 -1
- package/dashboard/dist/llms.txt +4 -4
- package/dashboard/dist/share.html +2 -2
- package/package.json +3 -3
- package/src/commands/init.js +49 -8
- package/src/commands/status.js +12 -5
- package/src/commands/sync.js +1 -0
- package/src/commands/uninstall.js +36 -1
- package/src/lib/grok-hook.js +11 -2
- package/src/lib/omp-hook.js +589 -0
- package/src/lib/opencode-go-limits.js +59 -30
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/rollout.js +283 -68
- package/src/lib/star-cta.js +1 -1
- package/src/lib/usage-limits.js +3 -3
- package/dashboard/dist/assets/DialogDescription-fYPOWV-6.js +0 -1
- package/dashboard/dist/assets/HeaderGithubStar-BN1WZPnH.js +0 -1
- package/dashboard/dist/assets/LimitsPage-Clg8P5-M.js +0 -4
- package/dashboard/dist/assets/LocalOnlyNotice-rdNf4GvF.js +0 -1
- package/dashboard/dist/assets/use-reduced-motion-DXlYG36v.js +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tokentracker-cli",
|
|
3
|
-
"version": "0.87.
|
|
3
|
+
"version": "0.87.8",
|
|
4
4
|
"description": "Local-first AI coding token usage and cost tracker for 29 tools, with a dashboard, desktop pet, widgets, achievements, and native macOS/Windows apps.",
|
|
5
5
|
"main": "src/cli.js",
|
|
6
6
|
"bin": {
|
|
@@ -54,11 +54,11 @@
|
|
|
54
54
|
},
|
|
55
55
|
"repository": {
|
|
56
56
|
"type": "git",
|
|
57
|
-
"url": "git+https://github.com/
|
|
57
|
+
"url": "git+https://github.com/xiufengsun/TokenTracker.git"
|
|
58
58
|
},
|
|
59
59
|
"homepage": "https://www.tokentracker.cc",
|
|
60
60
|
"bugs": {
|
|
61
|
-
"url": "https://github.com/
|
|
61
|
+
"url": "https://github.com/xiufengsun/TokenTracker/issues"
|
|
62
62
|
},
|
|
63
63
|
"keywords": [
|
|
64
64
|
"token",
|
package/src/commands/init.js
CHANGED
|
@@ -56,6 +56,10 @@ const {
|
|
|
56
56
|
removeGrokHook,
|
|
57
57
|
GROK_HOOK_FILENAME
|
|
58
58
|
} = require("../lib/grok-hook");
|
|
59
|
+
const {
|
|
60
|
+
upsertOmpHook,
|
|
61
|
+
probeOmpHookState,
|
|
62
|
+
} = require("../lib/omp-hook");
|
|
59
63
|
const { resolveTrackerPaths } = require("../lib/tracker-paths");
|
|
60
64
|
const {
|
|
61
65
|
resolveOmpAgentDir,
|
|
@@ -361,6 +365,7 @@ async function runSetup({
|
|
|
361
365
|
trackerDir,
|
|
362
366
|
notifyPath,
|
|
363
367
|
notifyOriginalPath,
|
|
368
|
+
dryRun: Boolean(opts.dryRun),
|
|
364
369
|
});
|
|
365
370
|
|
|
366
371
|
return {
|
|
@@ -551,7 +556,13 @@ function buildIntegrationTargets({ home, trackerDir, notifyPath }) {
|
|
|
551
556
|
};
|
|
552
557
|
}
|
|
553
558
|
|
|
554
|
-
async function applyIntegrationSetup({
|
|
559
|
+
async function applyIntegrationSetup({
|
|
560
|
+
home,
|
|
561
|
+
trackerDir,
|
|
562
|
+
notifyPath,
|
|
563
|
+
notifyOriginalPath,
|
|
564
|
+
dryRun = false,
|
|
565
|
+
}) {
|
|
555
566
|
const context = buildIntegrationTargets({ home, trackerDir, notifyPath });
|
|
556
567
|
context.notifyOriginalPath = notifyOriginalPath;
|
|
557
568
|
|
|
@@ -642,15 +653,44 @@ async function applyIntegrationSetup({ home, trackerDir, notifyPath, notifyOrigi
|
|
|
642
653
|
}
|
|
643
654
|
}
|
|
644
655
|
|
|
645
|
-
// oh-my-pi: passive
|
|
646
|
-
//
|
|
656
|
+
// oh-my-pi: passive session scan always works; also install an optional
|
|
657
|
+
// notify extension so turn_end triggers sync --source omp near-real-time.
|
|
647
658
|
{
|
|
648
|
-
|
|
649
|
-
// win32 path resolver only yields a dir it can see) — null means "not
|
|
650
|
-
// installed", so skip rather than path.join(null, …) and crash.
|
|
659
|
+
const fssyncLocal = require("node:fs");
|
|
651
660
|
const ompAgentDir = resolveOmpAgentDir(process.env);
|
|
652
|
-
|
|
653
|
-
|
|
661
|
+
const ompSessions = ompAgentDir && fssyncLocal.existsSync(path.join(ompAgentDir, "sessions"));
|
|
662
|
+
if (ompAgentDir && (ompSessions || fssyncLocal.existsSync(ompAgentDir))) {
|
|
663
|
+
if (dryRun) {
|
|
664
|
+
const probe = await probeOmpHookState({ home, trackerDir, env: process.env });
|
|
665
|
+
summary.push({
|
|
666
|
+
label: "oh-my-pi",
|
|
667
|
+
status: "detected",
|
|
668
|
+
detail: probe.configured
|
|
669
|
+
? "Notify extension already installed (passive scan still runs)"
|
|
670
|
+
: "Will install notify extension + keep passive scan",
|
|
671
|
+
});
|
|
672
|
+
} else {
|
|
673
|
+
const result = await upsertOmpHook({ home, trackerDir, env: process.env });
|
|
674
|
+
if (result.written) {
|
|
675
|
+
summary.push({
|
|
676
|
+
label: "oh-my-pi",
|
|
677
|
+
status: "installed",
|
|
678
|
+
detail: `Notify extension → ${result.extensionPath} (passive scan still runs)`,
|
|
679
|
+
});
|
|
680
|
+
} else if (result.skippedReason === "unmanaged-extension-present") {
|
|
681
|
+
summary.push({
|
|
682
|
+
label: "oh-my-pi",
|
|
683
|
+
status: "skipped",
|
|
684
|
+
detail: "Existing unmanaged tokentracker-notify extension left untouched",
|
|
685
|
+
});
|
|
686
|
+
} else {
|
|
687
|
+
summary.push({
|
|
688
|
+
label: "oh-my-pi",
|
|
689
|
+
status: "detected",
|
|
690
|
+
detail: "Passive reader (notify extension not written)",
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
}
|
|
654
694
|
}
|
|
655
695
|
}
|
|
656
696
|
|
|
@@ -1904,6 +1944,7 @@ module.exports = {
|
|
|
1904
1944
|
installLocalTrackerApp,
|
|
1905
1945
|
repairCodexNotifyIntegration,
|
|
1906
1946
|
repairRuntimeIntegrations,
|
|
1947
|
+
applyIntegrationSetup,
|
|
1907
1948
|
};
|
|
1908
1949
|
|
|
1909
1950
|
async function probeFile(p) {
|
package/src/commands/status.js
CHANGED
|
@@ -84,6 +84,7 @@ const wsl = require("../lib/wsl-probe");
|
|
|
84
84
|
const { getWslMode, isInvalidWslMode, shouldProbeWsl, discoverWslHome } = wsl;
|
|
85
85
|
const { resolveInstallPaths } = require("../lib/install-resolver");
|
|
86
86
|
const { probeGrokHookState, resolveGrokHome } = require("../lib/grok-hook");
|
|
87
|
+
const { probeOmpHookState } = require("../lib/omp-hook");
|
|
87
88
|
|
|
88
89
|
function formatResolvedPaths(paths, filename) {
|
|
89
90
|
const active = [];
|
|
@@ -359,10 +360,11 @@ async function cmdStatus(argv = []) {
|
|
|
359
360
|
? fssync.existsSync(path.join(workbuddyHome, "workbuddy.db"))
|
|
360
361
|
: false;
|
|
361
362
|
|
|
362
|
-
// oh-my-pi — passive scan
|
|
363
|
+
// oh-my-pi — passive scan + optional notify extension.
|
|
363
364
|
const ompAgentDir = resolveOmpAgentDir(process.env);
|
|
364
365
|
const ompInstalled = Boolean(ompAgentDir) && fssync.existsSync(path.join(ompAgentDir, "sessions"));
|
|
365
366
|
const ompFiles = ompInstalled ? resolveOmpSessionFiles(process.env) : [];
|
|
367
|
+
const ompHookState = await probeOmpHookState({ home, trackerDir, env: process.env });
|
|
366
368
|
|
|
367
369
|
// pi (@mariozechner/pi-coding-agent) — passive scan only (no hooks).
|
|
368
370
|
// Skip when its agent dir collides with omp's; sync would dedupe anyway.
|
|
@@ -771,8 +773,13 @@ async function cmdStatus(argv = []) {
|
|
|
771
773
|
workbuddy: workbuddyInstalled
|
|
772
774
|
? { installed: true, files: workbuddyFiles.length }
|
|
773
775
|
: { installed: false },
|
|
774
|
-
omp: ompInstalled
|
|
775
|
-
? {
|
|
776
|
+
omp: ompInstalled || ompHookState.ompPresent
|
|
777
|
+
? {
|
|
778
|
+
installed: true,
|
|
779
|
+
files: ompFiles.length,
|
|
780
|
+
notify_extension: Boolean(ompHookState.configured),
|
|
781
|
+
notify_extension_path: ompHookState.extensionPath || null,
|
|
782
|
+
}
|
|
776
783
|
: { installed: false },
|
|
777
784
|
pi: piInstalled
|
|
778
785
|
? { installed: true, files: piFiles.length }
|
|
@@ -895,8 +902,8 @@ async function cmdStatus(argv = []) {
|
|
|
895
902
|
workbuddyInstalled
|
|
896
903
|
? `- WorkBuddy hooks: ${workbuddyHookConfigured ? "set" : "unset"} (${workbuddyFiles.length} session jsonl file${workbuddyFiles.length !== 1 ? "s" : ""} found, SQLite DB ${workbuddyDbExists ? "found" : "not found"})`
|
|
897
904
|
: null,
|
|
898
|
-
ompInstalled
|
|
899
|
-
? `- oh-my-pi: passive reader (${ompFiles.length} session jsonl file${ompFiles.length !== 1 ? "s" : ""} found)`
|
|
905
|
+
ompInstalled || ompHookState.ompPresent
|
|
906
|
+
? `- oh-my-pi: passive reader (${ompFiles.length} session jsonl file${ompFiles.length !== 1 ? "s" : ""} found${ompHookState.configured ? ", notify extension: yes" : ", notify extension: no"})`
|
|
900
907
|
: null,
|
|
901
908
|
piInstalled
|
|
902
909
|
? `- pi: passive reader (${piFiles.length} session jsonl file${piFiles.length !== 1 ? "s" : ""} found)`
|
package/src/commands/sync.js
CHANGED
|
@@ -1377,6 +1377,7 @@ async function cmdSync(argv, context = {}) {
|
|
|
1377
1377
|
settingsFiles: droidSettingsFiles,
|
|
1378
1378
|
cursors,
|
|
1379
1379
|
queuePath,
|
|
1380
|
+
projectQueuePath,
|
|
1380
1381
|
// Full-scan sync: drop cursor entries for any session whose
|
|
1381
1382
|
// settings.json has disappeared off disk so cursors.droid stays
|
|
1382
1383
|
// bounded by the actual on-disk session count.
|
|
@@ -24,6 +24,7 @@ const { resolveOpencodeConfigDir, removeOpencodePlugin } = require("../lib/openc
|
|
|
24
24
|
const { removeOpenclawHookConfig } = require("../lib/openclaw-hook");
|
|
25
25
|
const { removeOpenclawSessionPluginConfig } = require("../lib/openclaw-session-plugin");
|
|
26
26
|
const { removeGrokHook } = require("../lib/grok-hook");
|
|
27
|
+
const { removeOmpHook } = require("../lib/omp-hook");
|
|
27
28
|
const { resolveTrackerPaths } = require("../lib/tracker-paths");
|
|
28
29
|
|
|
29
30
|
async function cmdUninstall(argv) {
|
|
@@ -104,6 +105,7 @@ async function cmdUninstall(argv) {
|
|
|
104
105
|
});
|
|
105
106
|
const openclawHookRemove = await removeOpenclawHookConfig({ home, trackerDir, env: process.env });
|
|
106
107
|
const grokHookRemove = await removeGrokHook({ home, trackerDir, env: process.env });
|
|
108
|
+
const ompHookRemove = await removeOmpHook({ home, trackerDir, env: process.env });
|
|
107
109
|
|
|
108
110
|
// Remove installed notify handler.
|
|
109
111
|
await fs.unlink(notifyPath).catch(() => {});
|
|
@@ -195,6 +197,7 @@ async function cmdUninstall(argv) {
|
|
|
195
197
|
grokHookRemove?.removed
|
|
196
198
|
? `- Grok Build hook removed: ${grokHookRemove.hookPath}`
|
|
197
199
|
: "- Grok Build hook: no change",
|
|
200
|
+
formatOmpHookRemoveLine(ompHookRemove),
|
|
198
201
|
opts.purge ? `- Purged: ${path.join(home, ".tokentracker")}` : "- Purge: skipped (use --purge)",
|
|
199
202
|
...(machineIdSeedKept
|
|
200
203
|
? [`- Kept: ${machineIdSeedPath} (cloud device identity — a reinstall reuses the same device; delete it to fully reset)`]
|
|
@@ -204,6 +207,38 @@ async function cmdUninstall(argv) {
|
|
|
204
207
|
);
|
|
205
208
|
}
|
|
206
209
|
|
|
210
|
+
function formatOmpHookRemoveLine(ompHookRemove) {
|
|
211
|
+
if (ompHookRemove?.removed) {
|
|
212
|
+
return `- oh-my-pi notify extension removed: ${ompHookRemove.extensionPath}`;
|
|
213
|
+
}
|
|
214
|
+
const reason = ompHookRemove?.skippedReason;
|
|
215
|
+
const residualPath = ompHookRemove?.stagedPath || ompHookRemove?.extensionPath;
|
|
216
|
+
const residual = residualPath
|
|
217
|
+
? ` (left in place: ${residualPath})`
|
|
218
|
+
: "";
|
|
219
|
+
if (reason === "unmanaged") {
|
|
220
|
+
return `- oh-my-pi notify extension: skipped (unmanaged file)${residual}`;
|
|
221
|
+
}
|
|
222
|
+
if (reason === "unlink-failed") {
|
|
223
|
+
const detail = ompHookRemove?.error ? `: ${ompHookRemove.error}` : "";
|
|
224
|
+
return `- oh-my-pi notify extension: failed to remove${detail}${residual}`;
|
|
225
|
+
}
|
|
226
|
+
if (reason === "extension-read-failed") {
|
|
227
|
+
const detail = ompHookRemove?.error ? `: ${ompHookRemove.error}` : "";
|
|
228
|
+
return `- oh-my-pi notify extension: failed to read${detail}${residual}`;
|
|
229
|
+
}
|
|
230
|
+
if (reason === "identity-changed") {
|
|
231
|
+
return `- oh-my-pi notify extension: skipped (file changed during uninstall)${residual}`;
|
|
232
|
+
}
|
|
233
|
+
if (reason === "omp-agent-dir-unresolved") {
|
|
234
|
+
return "- oh-my-pi notify extension: skipped (omp agent dir unresolved)";
|
|
235
|
+
}
|
|
236
|
+
if (reason === "missing") {
|
|
237
|
+
return "- oh-my-pi notify extension: no change";
|
|
238
|
+
}
|
|
239
|
+
return "- oh-my-pi notify extension: no change";
|
|
240
|
+
}
|
|
241
|
+
|
|
207
242
|
function parseArgs(argv) {
|
|
208
243
|
const out = { purge: false };
|
|
209
244
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -214,7 +249,7 @@ function parseArgs(argv) {
|
|
|
214
249
|
return out;
|
|
215
250
|
}
|
|
216
251
|
|
|
217
|
-
module.exports = { cmdUninstall };
|
|
252
|
+
module.exports = { cmdUninstall, formatOmpHookRemoveLine };
|
|
218
253
|
|
|
219
254
|
async function isFile(p) {
|
|
220
255
|
try {
|
package/src/lib/grok-hook.js
CHANGED
|
@@ -31,10 +31,15 @@ function resolveLegacyTrackerBinDir(trackerDir) {
|
|
|
31
31
|
return path.join(trackerDir, "bin");
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
function buildGrokSessionEndHookJson(
|
|
34
|
+
function buildGrokSessionEndHookJson(
|
|
35
|
+
{ notifyGrokHandlerPath },
|
|
36
|
+
{ platform = process.platform, execPath = process.execPath } = {},
|
|
37
|
+
) {
|
|
35
38
|
// The command runs our dedicated handler.
|
|
36
39
|
// We pass the session id and cwd via environment variables that Grok already sets.
|
|
37
|
-
const cmd =
|
|
40
|
+
const cmd = platform === "win32"
|
|
41
|
+
? `${windowsCommandQuote(execPath)} ${windowsCommandQuote(notifyGrokHandlerPath)}`
|
|
42
|
+
: `/usr/bin/env node ${shellQuote(notifyGrokHandlerPath)}`;
|
|
38
43
|
return {
|
|
39
44
|
hooks: {
|
|
40
45
|
SessionEnd: [
|
|
@@ -56,6 +61,10 @@ function shellQuote(value) {
|
|
|
56
61
|
return `'${String(value).replace(/'/g, "'\\''")}'`;
|
|
57
62
|
}
|
|
58
63
|
|
|
64
|
+
function windowsCommandQuote(value) {
|
|
65
|
+
return `"${String(value).replace(/"/g, '""')}"`;
|
|
66
|
+
}
|
|
67
|
+
|
|
59
68
|
async function ensureGrokHookFiles({
|
|
60
69
|
grokHooksDir,
|
|
61
70
|
trackerDir,
|