vibeusage 0.2.20 → 0.2.22
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/README.md +306 -173
- package/README.old.md +324 -0
- package/README.zh-CN.md +304 -188
- package/package.json +32 -30
- package/src/cli.js +41 -37
- package/src/commands/activate-if-needed.js +41 -0
- package/src/commands/diagnostics.js +8 -9
- package/src/commands/doctor.js +31 -26
- package/src/commands/init.js +324 -208
- package/src/commands/status.js +86 -80
- package/src/commands/sync.js +182 -130
- package/src/commands/uninstall.js +69 -58
- package/src/lib/activation-check.js +290 -0
- package/src/lib/browser-auth.js +52 -54
- package/src/lib/claude-config.js +25 -25
- package/src/lib/cli-ui.js +35 -35
- package/src/lib/codex-config.js +40 -36
- package/src/lib/debug-flags.js +2 -2
- package/src/lib/diagnostics.js +73 -55
- package/src/lib/doctor.js +139 -132
- package/src/lib/fs.js +17 -17
- package/src/lib/gemini-config.js +44 -40
- package/src/lib/init-flow.js +16 -22
- package/src/lib/insforge-client.js +10 -10
- package/src/lib/insforge.js +9 -3
- package/src/lib/openclaw-hook.js +91 -67
- package/src/lib/openclaw-session-plugin.js +520 -0
- package/src/lib/opencode-config.js +31 -32
- package/src/lib/opencode-usage-audit.js +34 -31
- package/src/lib/progress.js +12 -13
- package/src/lib/project-usage-purge.js +23 -17
- package/src/lib/prompt.js +8 -4
- package/src/lib/rollout.js +342 -241
- package/src/lib/runtime-config.js +34 -22
- package/src/lib/subscriptions.js +94 -92
- package/src/lib/tracker-paths.js +6 -6
- package/src/lib/upload-throttle.js +35 -16
- package/src/lib/uploader.js +33 -29
- package/src/lib/vibeusage-api.js +72 -56
- package/src/lib/vibeusage-public-repo.js +41 -24
package/src/commands/status.js
CHANGED
|
@@ -1,51 +1,52 @@
|
|
|
1
|
-
const os = require(
|
|
2
|
-
const path = require(
|
|
3
|
-
const fs = require(
|
|
1
|
+
const os = require("node:os");
|
|
2
|
+
const path = require("node:path");
|
|
3
|
+
const fs = require("node:fs/promises");
|
|
4
4
|
|
|
5
|
-
const { readJson } = require(
|
|
6
|
-
const { readCodexNotify, readEveryCodeNotify } = require(
|
|
7
|
-
const { isClaudeHookConfigured, buildClaudeHookCommand } = require(
|
|
5
|
+
const { readJson } = require("../lib/fs");
|
|
6
|
+
const { readCodexNotify, readEveryCodeNotify } = require("../lib/codex-config");
|
|
7
|
+
const { isClaudeHookConfigured, buildClaudeHookCommand } = require("../lib/claude-config");
|
|
8
8
|
const {
|
|
9
9
|
resolveGeminiConfigDir,
|
|
10
10
|
resolveGeminiSettingsPath,
|
|
11
11
|
isGeminiHookConfigured,
|
|
12
|
-
buildGeminiHookCommand
|
|
13
|
-
} = require(
|
|
14
|
-
const { resolveOpencodeConfigDir, isOpencodePluginInstalled } = require(
|
|
15
|
-
const { collectLocalSubscriptions } = require(
|
|
16
|
-
const { normalizeState: normalizeUploadState } = require(
|
|
17
|
-
const { collectTrackerDiagnostics } = require(
|
|
18
|
-
const { probeOpenclawHookState } = require(
|
|
19
|
-
const {
|
|
12
|
+
buildGeminiHookCommand,
|
|
13
|
+
} = require("../lib/gemini-config");
|
|
14
|
+
const { resolveOpencodeConfigDir, isOpencodePluginInstalled } = require("../lib/opencode-config");
|
|
15
|
+
const { collectLocalSubscriptions } = require("../lib/subscriptions");
|
|
16
|
+
const { normalizeState: normalizeUploadState } = require("../lib/upload-throttle");
|
|
17
|
+
const { collectTrackerDiagnostics } = require("../lib/diagnostics");
|
|
18
|
+
const { probeOpenclawHookState } = require("../lib/openclaw-hook");
|
|
19
|
+
const { probeOpenclawSessionPluginState } = require("../lib/openclaw-session-plugin");
|
|
20
|
+
const { resolveTrackerPaths } = require("../lib/tracker-paths");
|
|
20
21
|
|
|
21
22
|
async function cmdStatus(argv = []) {
|
|
22
23
|
const opts = parseArgs(argv);
|
|
23
24
|
if (opts.diagnostics) {
|
|
24
25
|
const diagnostics = await collectTrackerDiagnostics();
|
|
25
|
-
process.stdout.write(JSON.stringify(diagnostics, null, 2) +
|
|
26
|
+
process.stdout.write(JSON.stringify(diagnostics, null, 2) + "\n");
|
|
26
27
|
return;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
const home = os.homedir();
|
|
30
31
|
const { trackerDir, binDir } = await resolveTrackerPaths({ home });
|
|
31
|
-
const configPath = path.join(trackerDir,
|
|
32
|
-
const queuePath = path.join(trackerDir,
|
|
33
|
-
const queueStatePath = path.join(trackerDir,
|
|
34
|
-
const cursorsPath = path.join(trackerDir,
|
|
35
|
-
const notifySignalPath = path.join(trackerDir,
|
|
36
|
-
const openclawSignalPath = path.join(trackerDir,
|
|
37
|
-
const throttlePath = path.join(trackerDir,
|
|
38
|
-
const uploadThrottlePath = path.join(trackerDir,
|
|
39
|
-
const autoRetryPath = path.join(trackerDir,
|
|
40
|
-
const codexHome = process.env.CODEX_HOME || path.join(home,
|
|
41
|
-
const codexConfigPath = path.join(codexHome,
|
|
42
|
-
const codeHome = process.env.CODE_HOME || path.join(home,
|
|
43
|
-
const codeConfigPath = path.join(codeHome,
|
|
44
|
-
const claudeSettingsPath = path.join(home,
|
|
32
|
+
const configPath = path.join(trackerDir, "config.json");
|
|
33
|
+
const queuePath = path.join(trackerDir, "queue.jsonl");
|
|
34
|
+
const queueStatePath = path.join(trackerDir, "queue.state.json");
|
|
35
|
+
const cursorsPath = path.join(trackerDir, "cursors.json");
|
|
36
|
+
const notifySignalPath = path.join(trackerDir, "notify.signal");
|
|
37
|
+
const openclawSignalPath = path.join(trackerDir, "openclaw.signal");
|
|
38
|
+
const throttlePath = path.join(trackerDir, "sync.throttle");
|
|
39
|
+
const uploadThrottlePath = path.join(trackerDir, "upload.throttle.json");
|
|
40
|
+
const autoRetryPath = path.join(trackerDir, "auto.retry.json");
|
|
41
|
+
const codexHome = process.env.CODEX_HOME || path.join(home, ".codex");
|
|
42
|
+
const codexConfigPath = path.join(codexHome, "config.toml");
|
|
43
|
+
const codeHome = process.env.CODE_HOME || path.join(home, ".code");
|
|
44
|
+
const codeConfigPath = path.join(codeHome, "config.toml");
|
|
45
|
+
const claudeSettingsPath = path.join(home, ".claude", "settings.json");
|
|
45
46
|
const geminiConfigDir = resolveGeminiConfigDir({ home, env: process.env });
|
|
46
47
|
const geminiSettingsPath = resolveGeminiSettingsPath({ configDir: geminiConfigDir });
|
|
47
48
|
const opencodeConfigDir = resolveOpencodeConfigDir({ home, env: process.env });
|
|
48
|
-
const notifyPath = path.join(binDir,
|
|
49
|
+
const notifyPath = path.join(binDir, "notify.cjs");
|
|
49
50
|
const claudeHookCommand = buildClaudeHookCommand(notifyPath);
|
|
50
51
|
const geminiHookCommand = buildGeminiHookCommand(notifyPath);
|
|
51
52
|
|
|
@@ -68,29 +69,36 @@ async function cmdStatus(argv = []) {
|
|
|
68
69
|
const everyCodeConfigured = Array.isArray(everyCodeNotify) && everyCodeNotify.length > 0;
|
|
69
70
|
const claudeHookConfigured = await isClaudeHookConfigured({
|
|
70
71
|
settingsPath: claudeSettingsPath,
|
|
71
|
-
hookCommand: claudeHookCommand
|
|
72
|
+
hookCommand: claudeHookCommand,
|
|
72
73
|
});
|
|
73
74
|
const geminiHookConfigured = await isGeminiHookConfigured({
|
|
74
75
|
settingsPath: geminiSettingsPath,
|
|
75
|
-
hookCommand: geminiHookCommand
|
|
76
|
+
hookCommand: geminiHookCommand,
|
|
77
|
+
});
|
|
78
|
+
const opencodePluginConfigured = await isOpencodePluginInstalled({
|
|
79
|
+
configDir: opencodeConfigDir,
|
|
80
|
+
});
|
|
81
|
+
const openclawSessionPluginState = await probeOpenclawSessionPluginState({
|
|
82
|
+
home,
|
|
83
|
+
trackerDir,
|
|
84
|
+
env: process.env,
|
|
76
85
|
});
|
|
77
|
-
const opencodePluginConfigured = await isOpencodePluginInstalled({ configDir: opencodeConfigDir });
|
|
78
86
|
const openclawHookState = await probeOpenclawHookState({ home, trackerDir, env: process.env });
|
|
79
87
|
|
|
80
88
|
const lastUpload = uploadThrottle.lastSuccessMs
|
|
81
89
|
? parseEpochMsToIso(uploadThrottle.lastSuccessMs)
|
|
82
|
-
: typeof queueState.updatedAt ===
|
|
90
|
+
: typeof queueState.updatedAt === "string"
|
|
83
91
|
? queueState.updatedAt
|
|
84
92
|
: null;
|
|
85
93
|
const nextUpload = parseEpochMsToIso(uploadThrottle.nextAllowedAtMs || null);
|
|
86
94
|
const backoffUntil = parseEpochMsToIso(uploadThrottle.backoffUntilMs || null);
|
|
87
95
|
const lastUploadError = uploadThrottle.lastError
|
|
88
|
-
? `${uploadThrottle.lastErrorAt ||
|
|
96
|
+
? `${uploadThrottle.lastErrorAt || "unknown"} ${uploadThrottle.lastError}`
|
|
89
97
|
: null;
|
|
90
98
|
const autoRetryAt = parseEpochMsToIso(autoRetry?.retryAtMs || null);
|
|
91
99
|
const autoRetryLine = autoRetryAt
|
|
92
|
-
? `- Auto retry after: ${autoRetryAt} (${autoRetry?.reason ||
|
|
93
|
-
autoRetry?.pendingBytes || 0
|
|
100
|
+
? `- Auto retry after: ${autoRetryAt} (${autoRetry?.reason || "scheduled"}, pending ${Number(
|
|
101
|
+
autoRetry?.pendingBytes || 0,
|
|
94
102
|
)} bytes)`
|
|
95
103
|
: null;
|
|
96
104
|
|
|
@@ -98,69 +106,68 @@ async function cmdStatus(argv = []) {
|
|
|
98
106
|
home,
|
|
99
107
|
env: process.env,
|
|
100
108
|
probeKeychain: opts.probeKeychain,
|
|
101
|
-
probeKeychainDetails: opts.probeKeychainDetails
|
|
109
|
+
probeKeychainDetails: opts.probeKeychainDetails,
|
|
102
110
|
});
|
|
103
111
|
const subscriptionLines =
|
|
104
|
-
subscriptions.length > 0
|
|
105
|
-
? subscriptions.map(formatSubscriptionLine)
|
|
106
|
-
: [];
|
|
112
|
+
subscriptions.length > 0 ? subscriptions.map(formatSubscriptionLine) : [];
|
|
107
113
|
|
|
108
114
|
process.stdout.write(
|
|
109
115
|
[
|
|
110
|
-
|
|
111
|
-
`- Base URL: ${config?.baseUrl ||
|
|
112
|
-
`- Device token: ${config?.deviceToken ?
|
|
116
|
+
"Status:",
|
|
117
|
+
`- Base URL: ${config?.baseUrl || "unset"}`,
|
|
118
|
+
`- Device token: ${config?.deviceToken ? "set" : "unset"}`,
|
|
113
119
|
`- Queue: ${pendingBytes} bytes pending`,
|
|
114
|
-
`- Last parse: ${cursors?.updatedAt ||
|
|
115
|
-
`- Last notify: ${lastNotify ||
|
|
116
|
-
`- Last OpenClaw-triggered sync: ${lastOpenclawSync ||
|
|
117
|
-
`- Last notify-triggered sync: ${lastNotifySpawn ||
|
|
118
|
-
`- Last upload: ${lastUpload ||
|
|
119
|
-
`- Next upload after: ${nextUpload ||
|
|
120
|
-
`- Backoff until: ${backoffUntil ||
|
|
120
|
+
`- Last parse: ${cursors?.updatedAt || "never"}`,
|
|
121
|
+
`- Last notify: ${lastNotify || "never"}`,
|
|
122
|
+
`- Last OpenClaw-triggered sync: ${lastOpenclawSync || "never"}`,
|
|
123
|
+
`- Last notify-triggered sync: ${lastNotifySpawn || "never"}`,
|
|
124
|
+
`- Last upload: ${lastUpload || "never"}`,
|
|
125
|
+
`- Next upload after: ${nextUpload || "never"}`,
|
|
126
|
+
`- Backoff until: ${backoffUntil || "never"}`,
|
|
121
127
|
lastUploadError ? `- Last upload error: ${lastUploadError}` : null,
|
|
122
128
|
autoRetryLine,
|
|
123
|
-
`- Codex notify: ${notifyConfigured ? JSON.stringify(codexNotify) :
|
|
124
|
-
`- Every Code notify: ${everyCodeConfigured ? JSON.stringify(everyCodeNotify) :
|
|
125
|
-
`- Claude hooks: ${claudeHookConfigured ?
|
|
126
|
-
`- Gemini hooks: ${geminiHookConfigured ?
|
|
127
|
-
`- Opencode plugin: ${opencodePluginConfigured ?
|
|
128
|
-
`- OpenClaw
|
|
129
|
+
`- Codex notify: ${notifyConfigured ? JSON.stringify(codexNotify) : "unset"}`,
|
|
130
|
+
`- Every Code notify: ${everyCodeConfigured ? JSON.stringify(everyCodeNotify) : "unset"}`,
|
|
131
|
+
`- Claude hooks: ${claudeHookConfigured ? "set" : "unset"}`,
|
|
132
|
+
`- Gemini hooks: ${geminiHookConfigured ? "set" : "unset"}`,
|
|
133
|
+
`- Opencode plugin: ${opencodePluginConfigured ? "set" : "unset"}`,
|
|
134
|
+
`- OpenClaw session plugin: ${openclawSessionPluginState?.configured ? "set" : "unset"}`,
|
|
135
|
+
`- OpenClaw hook (legacy): ${openclawHookState?.configured ? "set" : "unset"}`,
|
|
129
136
|
...subscriptionLines,
|
|
130
|
-
|
|
137
|
+
"",
|
|
131
138
|
]
|
|
132
139
|
.filter(Boolean)
|
|
133
|
-
.join(
|
|
140
|
+
.join("\n"),
|
|
134
141
|
);
|
|
135
142
|
}
|
|
136
143
|
|
|
137
144
|
function formatSubscriptionLine(entry = {}) {
|
|
138
|
-
const tool = String(entry.tool ||
|
|
139
|
-
const provider = String(entry.provider ||
|
|
140
|
-
const product = String(entry.product ||
|
|
141
|
-
const planType = String(entry.planType ||
|
|
142
|
-
const rateLimitTier = String(entry.rateLimitTier ||
|
|
145
|
+
const tool = String(entry.tool || "");
|
|
146
|
+
const provider = String(entry.provider || "");
|
|
147
|
+
const product = String(entry.product || "");
|
|
148
|
+
const planType = String(entry.planType || "");
|
|
149
|
+
const rateLimitTier = String(entry.rateLimitTier || "");
|
|
143
150
|
const toolLabel =
|
|
144
|
-
tool ===
|
|
145
|
-
?
|
|
146
|
-
: tool ===
|
|
147
|
-
?
|
|
148
|
-
: tool ===
|
|
149
|
-
?
|
|
151
|
+
tool === "codex"
|
|
152
|
+
? "Codex"
|
|
153
|
+
: tool === "opencode"
|
|
154
|
+
? "OpenCode"
|
|
155
|
+
: tool === "claude"
|
|
156
|
+
? "Claude Code"
|
|
150
157
|
: tool;
|
|
151
158
|
|
|
152
159
|
if (!planType) return null;
|
|
153
160
|
|
|
154
|
-
if (tool ===
|
|
155
|
-
const suffix = rateLimitTier ? ` (rate limit tier: ${rateLimitTier})` :
|
|
161
|
+
if (tool === "claude" && provider === "anthropic" && product === "subscription") {
|
|
162
|
+
const suffix = rateLimitTier ? ` (rate limit tier: ${rateLimitTier})` : "";
|
|
156
163
|
return `- ${toolLabel} subscription: ${planType}${suffix}`;
|
|
157
164
|
}
|
|
158
165
|
|
|
159
|
-
if (provider ===
|
|
166
|
+
if (provider === "openai" && product === "chatgpt") {
|
|
160
167
|
return `- ${toolLabel} ChatGPT plan: ${planType}`;
|
|
161
168
|
}
|
|
162
169
|
|
|
163
|
-
const productLabel = product ? product.replace(/_/g,
|
|
170
|
+
const productLabel = product ? product.replace(/_/g, " ") : "subscription";
|
|
164
171
|
return `- ${toolLabel} ${productLabel}: ${planType}`;
|
|
165
172
|
}
|
|
166
173
|
|
|
@@ -169,13 +176,12 @@ function parseArgs(argv) {
|
|
|
169
176
|
|
|
170
177
|
for (let i = 0; i < argv.length; i++) {
|
|
171
178
|
const a = argv[i];
|
|
172
|
-
if (a ===
|
|
173
|
-
else if (a ===
|
|
174
|
-
else if (a ===
|
|
179
|
+
if (a === "--diagnostics" || a === "--json") out.diagnostics = true;
|
|
180
|
+
else if (a === "--probe-keychain") out.probeKeychain = true;
|
|
181
|
+
else if (a === "--probe-keychain-details") {
|
|
175
182
|
out.probeKeychainDetails = true;
|
|
176
183
|
out.probeKeychain = true;
|
|
177
|
-
}
|
|
178
|
-
else throw new Error(`Unknown option: ${a}`);
|
|
184
|
+
} else throw new Error(`Unknown option: ${a}`);
|
|
179
185
|
}
|
|
180
186
|
|
|
181
187
|
return out;
|
|
@@ -192,7 +198,7 @@ async function safeStatSize(p) {
|
|
|
192
198
|
|
|
193
199
|
async function safeReadText(p) {
|
|
194
200
|
try {
|
|
195
|
-
return await fs.readFile(p,
|
|
201
|
+
return await fs.readFile(p, "utf8");
|
|
196
202
|
} catch (_e) {
|
|
197
203
|
return null;
|
|
198
204
|
}
|