vibeusage 0.3.1 → 0.3.2
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 +7 -5
- package/README.zh-CN.md +10 -8
- package/package.json +1 -1
- package/src/commands/status.js +0 -5
- package/src/commands/sync.js +67 -175
- package/src/commands/uninstall.js +0 -11
- package/src/lib/diagnostics.js +0 -9
- package/src/lib/doctor.js +1 -15
- package/src/lib/integrations/context.js +0 -6
- package/src/lib/integrations/index.js +0 -2
- package/src/lib/openclaw-session-plugin.js +48 -138
- package/src/lib/openclaw-usage-ledger.js +237 -0
- package/src/lib/rollout.js +6 -156
- package/src/lib/integrations/openclaw-legacy.js +0 -123
- package/src/lib/openclaw-hook.js +0 -420
package/README.md
CHANGED
|
@@ -209,7 +209,7 @@ graph LR
|
|
|
209
209
|
C[Gemini CLI] -->|Session Logs| G
|
|
210
210
|
D[Opencode] -->|SQLite DB| G
|
|
211
211
|
E[Claude Code] -->|Hook Output| G
|
|
212
|
-
F[OpenClaw] -->|Session Plugin| G
|
|
212
|
+
F[OpenClaw] -->|Session Plugin → Sanitized Ledger| G
|
|
213
213
|
G -->|AI Tokens| H{Core Relay}
|
|
214
214
|
H --> I[VibeUsage Dashboard]
|
|
215
215
|
H --> J[AI Analytics Engine]
|
|
@@ -236,7 +236,7 @@ graph LR
|
|
|
236
236
|
|
|
237
237
|
1. AI CLI tools generate logs during usage
|
|
238
238
|
2. Local `notify-handler` detects changes and triggers sync
|
|
239
|
-
3. CLI incrementally parses logs
|
|
239
|
+
3. CLI incrementally parses logs, SQLite state, and the OpenClaw sanitized ledger, extracting whitelist token counts only
|
|
240
240
|
4. Data aggregated into 30-minute UTC buckets locally
|
|
241
241
|
5. Batch upload to InsForge with idempotent deduplication
|
|
242
242
|
6. Dashboard queries aggregated results for visualization
|
|
@@ -250,7 +250,7 @@ graph LR
|
|
|
250
250
|
| **Gemini CLI** | `~/.gemini/tmp/**/chats/session-*.json` | `GEMINI_HOME` |
|
|
251
251
|
| **Opencode** | `~/.local/share/opencode/opencode.db` (legacy `storage/message/**/*.json` fallback) | `OPENCODE_HOME` |
|
|
252
252
|
| **Claude Code** | Parsed from hook output | - |
|
|
253
|
-
| **OpenClaw** | Session plugin
|
|
253
|
+
| **OpenClaw** | Session plugin → local sanitized usage ledger | - |
|
|
254
254
|
|
|
255
255
|
## ⚙️ Configuration
|
|
256
256
|
|
|
@@ -279,6 +279,8 @@ graph LR
|
|
|
279
279
|
|
|
280
280
|
</details>
|
|
281
281
|
|
|
282
|
+
See also: [`docs/openclaw-integration.md`](docs/openclaw-integration.md) for the OpenClaw single-path accounting contract.
|
|
283
|
+
|
|
282
284
|
## 🔧 Troubleshooting
|
|
283
285
|
|
|
284
286
|
<details>
|
|
@@ -380,8 +382,8 @@ This project uses **OpenSpec** for spec-driven development. Before making signif
|
|
|
380
382
|
|
|
381
383
|
1. Read [`openspec/project.md`](openspec/project.md) for project conventions
|
|
382
384
|
2. Check [`openspec/AGENTS.md`](openspec/AGENTS.md) for the full OpenSpec workflow
|
|
383
|
-
3. Run `openspec list` to see active changes
|
|
384
|
-
4. Run `openspec list --specs` to see existing specifications
|
|
385
|
+
3. Run `npx openspec list` to see active changes
|
|
386
|
+
4. Run `npx openspec list --specs` to see existing specifications
|
|
385
387
|
|
|
386
388
|
See [CLAUDE.md](CLAUDE.md) for detailed guidelines.
|
|
387
389
|
|
package/README.zh-CN.md
CHANGED
|
@@ -143,7 +143,7 @@ npx vibeusage init [选项]
|
|
|
143
143
|
| **Codex CLI** | `~/.codex/config.toml` | `notify` 钩子 |
|
|
144
144
|
| **Every Code** | `~/.code/config.toml`(或 `CODE_HOME`) | `notify` 钩子 |
|
|
145
145
|
| **Gemini CLI** | `~/.gemini/settings.json`(或 `GEMINI_HOME`) | `SessionEnd` 钩子 |
|
|
146
|
-
| **Opencode** |
|
|
146
|
+
| **Opencode** | OpenCode 配置/插件 | SQLite-first 解析插件 |
|
|
147
147
|
| **Claude Code** | `~/.claude/settings.json` | `Stop` + `SessionEnd` 钩子 |
|
|
148
148
|
| **OpenClaw** | 安装时自动链接 | Session plugin(需要重启) |
|
|
149
149
|
|
|
@@ -207,9 +207,9 @@ graph LR
|
|
|
207
207
|
A[Codex CLI] -->|Rollout 日志| G(Tracker CLI)
|
|
208
208
|
B[Every Code] -->|Rollout 日志| G
|
|
209
209
|
C[Gemini CLI] -->|会话日志| G
|
|
210
|
-
D[Opencode]
|
|
210
|
+
D[Opencode] -->|SQLite DB| G
|
|
211
211
|
E[Claude Code] -->|钩子输出| G
|
|
212
|
-
F[OpenClaw] -->|
|
|
212
|
+
F[OpenClaw] -->|Session Plugin → Sanitized Ledger| G
|
|
213
213
|
G -->|AI Tokens| H{核心中继}
|
|
214
214
|
H --> I[VibeUsage 控制台]
|
|
215
215
|
H --> J[AI 分析引擎]
|
|
@@ -236,7 +236,7 @@ graph LR
|
|
|
236
236
|
|
|
237
237
|
1. AI CLI 工具在使用过程中生成日志
|
|
238
238
|
2. 本地 `notify-handler` 检测更改并触发同步
|
|
239
|
-
3. CLI
|
|
239
|
+
3. CLI 增量解析日志、SQLite 状态以及 OpenClaw 的本地脱敏 usage ledger,只提取白名单 token 计数
|
|
240
240
|
4. 数据在本地聚合到 30 分钟 UTC 桶中
|
|
241
241
|
5. 批量上传到 InsForge,带幂等去重
|
|
242
242
|
6. 控制台查询聚合结果进行可视化
|
|
@@ -248,9 +248,9 @@ graph LR
|
|
|
248
248
|
| **Codex CLI** | `~/.codex/sessions/**/rollout-*.jsonl` | `CODEX_HOME` |
|
|
249
249
|
| **Every Code** | `~/.code/sessions/**/rollout-*.jsonl` | `CODE_HOME` |
|
|
250
250
|
| **Gemini CLI** | `~/.gemini/tmp/**/chats/session-*.json` | `GEMINI_HOME` |
|
|
251
|
-
| **Opencode** | `~/.opencode/
|
|
251
|
+
| **Opencode** | `~/.local/share/opencode/opencode.db`(旧版 `storage/message/**/*.json` 仅作回退) | `OPENCODE_HOME` |
|
|
252
252
|
| **Claude Code** | 从钩子输出解析 | - |
|
|
253
|
-
| **OpenClaw** |
|
|
253
|
+
| **OpenClaw** | Session plugin → 本地脱敏 usage ledger | - |
|
|
254
254
|
|
|
255
255
|
## ⚙️ 配置
|
|
256
256
|
|
|
@@ -278,6 +278,8 @@ graph LR
|
|
|
278
278
|
|
|
279
279
|
</details>
|
|
280
280
|
|
|
281
|
+
另见:[`docs/openclaw-integration.md`](docs/openclaw-integration.md),其中说明了 OpenClaw 单一路径 accounting 合同。
|
|
282
|
+
|
|
281
283
|
## 🔧 故障排查
|
|
282
284
|
|
|
283
285
|
<details>
|
|
@@ -374,8 +376,8 @@ npm run smoke
|
|
|
374
376
|
|
|
375
377
|
1. 阅读 [`openspec/project.md`](openspec/project.md) 了解项目约定
|
|
376
378
|
2. 查看 [`openspec/AGENTS.md`](openspec/AGENTS.md) 了解完整的 OpenSpec 工作流
|
|
377
|
-
3. 运行 `openspec list` 查看活跃的更改
|
|
378
|
-
4. 运行 `openspec list --specs` 查看现有规格
|
|
379
|
+
3. 运行 `npx openspec list` 查看活跃的更改
|
|
380
|
+
4. 运行 `npx openspec list --specs` 查看现有规格
|
|
379
381
|
|
|
380
382
|
详见 [CLAUDE.md](CLAUDE.md) 了解详细指南。
|
|
381
383
|
|
package/package.json
CHANGED
package/src/commands/status.js
CHANGED
|
@@ -81,7 +81,6 @@ async function cmdStatus(argv = []) {
|
|
|
81
81
|
const geminiProbe = probeByName.get("gemini");
|
|
82
82
|
const opencodeProbe = probeByName.get("opencode");
|
|
83
83
|
const openclawSessionProbe = probeByName.get("openclaw-session");
|
|
84
|
-
const openclawLegacyProbe = probeByName.get("openclaw-legacy");
|
|
85
84
|
const opencodeDbPresent = Boolean((await safeStat(opencodeDbPath))?.isFile?.());
|
|
86
85
|
const opencodeSqliteState =
|
|
87
86
|
cursors?.opencodeSqlite && typeof cursors.opencodeSqlite === "object"
|
|
@@ -118,10 +117,6 @@ async function cmdStatus(argv = []) {
|
|
|
118
117
|
descriptors.get("openclaw-session"),
|
|
119
118
|
openclawSessionProbe,
|
|
120
119
|
)}`,
|
|
121
|
-
`- OpenClaw hook (legacy): ${renderIntegrationStatus(
|
|
122
|
-
descriptors.get("openclaw-legacy"),
|
|
123
|
-
openclawLegacyProbe,
|
|
124
|
-
)}`,
|
|
125
120
|
...subscriptionLines,
|
|
126
121
|
"",
|
|
127
122
|
]
|
package/src/commands/sync.js
CHANGED
|
@@ -13,9 +13,15 @@ const {
|
|
|
13
13
|
parseClaudeIncremental,
|
|
14
14
|
parseGeminiIncremental,
|
|
15
15
|
parseOpencodeIncremental,
|
|
16
|
-
|
|
16
|
+
normalizeHourlyState,
|
|
17
|
+
getHourlyBucket,
|
|
18
|
+
addTotals,
|
|
19
|
+
bucketKey,
|
|
20
|
+
enqueueTouchedBuckets,
|
|
21
|
+
toUtcHalfHourStart,
|
|
17
22
|
} = require("../lib/rollout");
|
|
18
23
|
const { drainQueueToCloud } = require("../lib/uploader");
|
|
24
|
+
const { readOpenclawUsageLedger } = require("../lib/openclaw-usage-ledger");
|
|
19
25
|
const { collectLocalSubscriptions } = require("../lib/subscriptions");
|
|
20
26
|
const { createProgress, renderBar, formatNumber, formatBytes } = require("../lib/progress");
|
|
21
27
|
const { syncHeartbeat } = require("../lib/vibeusage-api");
|
|
@@ -70,13 +76,6 @@ async function cmdSync(argv) {
|
|
|
70
76
|
const opencodeStorageDir = path.join(opencodeHome, "storage");
|
|
71
77
|
const opencodeDbPath = path.join(opencodeHome, "opencode.db");
|
|
72
78
|
|
|
73
|
-
// OpenClaw session-plugin integration: allow a plugin-triggered sync to request incremental parsing
|
|
74
|
-
// for a single session jsonl. We still parse all regular sources so model/source attribution stays
|
|
75
|
-
// complete (e.g. Kimi sessions).
|
|
76
|
-
const openclawSignal = opts.fromOpenclaw
|
|
77
|
-
? resolveOpenclawSignal({ home, env: process.env })
|
|
78
|
-
: null;
|
|
79
|
-
|
|
80
79
|
const sources = [
|
|
81
80
|
{ source: "codex", sessionsDir: path.join(codexHome, "sessions") },
|
|
82
81
|
{ source: "every-code", sessionsDir: path.join(codeHome, "sessions") },
|
|
@@ -93,10 +92,6 @@ async function cmdSync(argv) {
|
|
|
93
92
|
}
|
|
94
93
|
}
|
|
95
94
|
|
|
96
|
-
const openclawFiles = openclawSignal?.sessionFile
|
|
97
|
-
? [{ path: openclawSignal.sessionFile, source: "openclaw" }]
|
|
98
|
-
: [];
|
|
99
|
-
|
|
100
95
|
if (progress?.enabled) {
|
|
101
96
|
progress.start(
|
|
102
97
|
`Parsing ${renderBar(0)} 0/${formatNumber(rolloutFiles.length)} files | buckets 0`,
|
|
@@ -119,28 +114,13 @@ async function cmdSync(argv) {
|
|
|
119
114
|
},
|
|
120
115
|
});
|
|
121
116
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
projectQueuePath,
|
|
130
|
-
source: "openclaw",
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const openclawFallback = await applyOpenclawTotalsFallback({
|
|
135
|
-
trackerDir,
|
|
136
|
-
signal: openclawSignal,
|
|
137
|
-
cursors,
|
|
138
|
-
queuePath,
|
|
139
|
-
projectQueuePath,
|
|
140
|
-
});
|
|
141
|
-
openclawResult.filesProcessed += openclawFallback.filesProcessed;
|
|
142
|
-
openclawResult.eventsAggregated += openclawFallback.eventsAggregated;
|
|
143
|
-
openclawResult.bucketsQueued += openclawFallback.bucketsQueued;
|
|
117
|
+
const openclawResult = opts.fromOpenclaw
|
|
118
|
+
? await parseOpenclawSanitizedLedger({
|
|
119
|
+
trackerDir,
|
|
120
|
+
cursors,
|
|
121
|
+
queuePath,
|
|
122
|
+
})
|
|
123
|
+
: { filesProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
|
|
144
124
|
|
|
145
125
|
const claudeFiles = await listClaudeProjectFiles(claudeProjectsDir);
|
|
146
126
|
let claudeResult = { filesProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
|
|
@@ -456,153 +436,65 @@ function parseArgs(argv) {
|
|
|
456
436
|
|
|
457
437
|
module.exports = { cmdSync };
|
|
458
438
|
|
|
459
|
-
function
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
439
|
+
async function parseOpenclawSanitizedLedger({ trackerDir, cursors, queuePath }) {
|
|
440
|
+
const ledgerCursor =
|
|
441
|
+
cursors?.openclawLedger && typeof cursors.openclawLedger === "object"
|
|
442
|
+
? cursors.openclawLedger
|
|
443
|
+
: {};
|
|
444
|
+
const offset = Math.max(0, Number(ledgerCursor.offset || 0));
|
|
445
|
+
const { events, endOffset } = await readOpenclawUsageLedger({ trackerDir, offset });
|
|
446
|
+
|
|
447
|
+
const hourlyState = normalizeHourlyState(cursors?.hourly);
|
|
448
|
+
const touchedBuckets = new Set();
|
|
449
|
+
let eventsAggregated = 0;
|
|
450
|
+
|
|
451
|
+
for (const event of events) {
|
|
452
|
+
if (!event || typeof event !== "object") continue;
|
|
453
|
+
const bucketStart = toUtcHalfHourStart(event.emittedAt);
|
|
454
|
+
if (!bucketStart) continue;
|
|
455
|
+
|
|
456
|
+
const model =
|
|
457
|
+
typeof event.model === "string" && event.model.trim() ? event.model.trim() : "unknown";
|
|
458
|
+
const source =
|
|
459
|
+
typeof event.source === "string" && event.source.trim() ? event.source.trim() : "openclaw";
|
|
460
|
+
const delta = {
|
|
461
|
+
input_tokens: Math.max(0, Number(event.inputTokens || 0)),
|
|
462
|
+
cached_input_tokens: Math.max(0, Number(event.cachedInputTokens || 0)),
|
|
463
|
+
output_tokens: Math.max(0, Number(event.outputTokens || 0)),
|
|
464
|
+
reasoning_output_tokens: Math.max(0, Number(event.reasoningOutputTokens || 0)),
|
|
465
|
+
total_tokens: Math.max(0, Number(event.totalTokens || 0)),
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
if (
|
|
469
|
+
delta.input_tokens === 0 &&
|
|
470
|
+
delta.cached_input_tokens === 0 &&
|
|
471
|
+
delta.output_tokens === 0 &&
|
|
472
|
+
delta.reasoning_output_tokens === 0 &&
|
|
473
|
+
delta.total_tokens === 0
|
|
474
|
+
) {
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
493
477
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
queuePath,
|
|
499
|
-
projectQueuePath,
|
|
500
|
-
}) {
|
|
501
|
-
const totalTokens = Number(signal?.prevTotals?.totalTokens || 0);
|
|
502
|
-
if (!trackerDir || !signal || totalTokens <= 0) {
|
|
503
|
-
return { filesProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
|
|
478
|
+
const bucket = getHourlyBucket(hourlyState, source, model, bucketStart);
|
|
479
|
+
addTotals(bucket.totals, delta);
|
|
480
|
+
touchedBuckets.add(bucketKey(source, model, bucketStart));
|
|
481
|
+
eventsAggregated += 1;
|
|
504
482
|
}
|
|
505
483
|
|
|
506
|
-
const
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
const current = {
|
|
515
|
-
totalTokens: normalizeNonNegativeInt(signal?.prevTotals?.totalTokens) || 0,
|
|
516
|
-
inputTokens: normalizeNonNegativeInt(signal?.prevTotals?.inputTokens) || 0,
|
|
517
|
-
outputTokens: normalizeNonNegativeInt(signal?.prevTotals?.outputTokens) || 0,
|
|
518
|
-
model: normalizeString(signal?.prevTotals?.model) || "unknown",
|
|
519
|
-
updatedAt: normalizeIsoOrEpoch(signal?.prevTotals?.updatedAt) || new Date().toISOString(),
|
|
520
|
-
seenAt: new Date().toISOString(),
|
|
484
|
+
const bucketsQueued = await enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets });
|
|
485
|
+
hourlyState.updatedAt = new Date().toISOString();
|
|
486
|
+
cursors.hourly = hourlyState;
|
|
487
|
+
cursors.openclawLedger = {
|
|
488
|
+
version: 1,
|
|
489
|
+
offset: endOffset,
|
|
490
|
+
updatedAt: new Date().toISOString(),
|
|
521
491
|
};
|
|
522
492
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
deltaTotal = Math.max(
|
|
528
|
-
0,
|
|
529
|
-
current.totalTokens - (normalizeNonNegativeInt(prev.totalTokens) || 0),
|
|
530
|
-
);
|
|
531
|
-
deltaInput = Math.max(
|
|
532
|
-
0,
|
|
533
|
-
current.inputTokens - (normalizeNonNegativeInt(prev.inputTokens) || 0),
|
|
534
|
-
);
|
|
535
|
-
deltaOutput = Math.max(
|
|
536
|
-
0,
|
|
537
|
-
current.outputTokens - (normalizeNonNegativeInt(prev.outputTokens) || 0),
|
|
538
|
-
);
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
if (deltaTotal > 0 && deltaInput + deltaOutput === 0) {
|
|
542
|
-
deltaInput = deltaTotal;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
sessions[sessionKey] = current;
|
|
546
|
-
state.version = 1;
|
|
547
|
-
state.sessions = sessions;
|
|
548
|
-
|
|
549
|
-
if (deltaTotal <= 0) {
|
|
550
|
-
await writeJson(statePath, state);
|
|
551
|
-
return { filesProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
await ensureDir(path.dirname(fallbackFilePath));
|
|
555
|
-
const syntheticMessage = {
|
|
556
|
-
type: "message",
|
|
557
|
-
timestamp: current.updatedAt,
|
|
558
|
-
message: {
|
|
559
|
-
role: "assistant",
|
|
560
|
-
model: current.model,
|
|
561
|
-
usage: {
|
|
562
|
-
input: deltaInput,
|
|
563
|
-
output: deltaOutput,
|
|
564
|
-
cacheRead: 0,
|
|
565
|
-
cacheWrite: 0,
|
|
566
|
-
totalTokens: deltaTotal,
|
|
567
|
-
},
|
|
568
|
-
},
|
|
493
|
+
return {
|
|
494
|
+
filesProcessed: endOffset > offset ? 1 : 0,
|
|
495
|
+
eventsAggregated,
|
|
496
|
+
bucketsQueued,
|
|
569
497
|
};
|
|
570
|
-
await fs.appendFile(fallbackFilePath, `${JSON.stringify(syntheticMessage)}\n`, "utf8");
|
|
571
|
-
await writeJson(statePath, state);
|
|
572
|
-
|
|
573
|
-
return parseOpenclawIncremental({
|
|
574
|
-
sessionFiles: [{ path: fallbackFilePath, source: "openclaw" }],
|
|
575
|
-
cursors,
|
|
576
|
-
queuePath,
|
|
577
|
-
projectQueuePath,
|
|
578
|
-
source: "openclaw",
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
function normalizeNonNegativeInt(value) {
|
|
583
|
-
const n = Number(value);
|
|
584
|
-
if (!Number.isFinite(n) || n < 0) return null;
|
|
585
|
-
return Math.floor(n);
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
function normalizeIsoOrEpoch(value) {
|
|
589
|
-
if (typeof value === "string") {
|
|
590
|
-
const trimmed = value.trim();
|
|
591
|
-
if (trimmed.length > 0 && !Number.isNaN(Date.parse(trimmed))) return trimmed;
|
|
592
|
-
const numeric = Number(trimmed);
|
|
593
|
-
if (Number.isFinite(numeric) && numeric > 0) {
|
|
594
|
-
const ms = numeric < 1e12 ? Math.floor(numeric * 1000) : Math.floor(numeric);
|
|
595
|
-
const iso = new Date(ms).toISOString();
|
|
596
|
-
if (!Number.isNaN(Date.parse(iso))) return iso;
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
const n = Number(value);
|
|
601
|
-
if (!Number.isFinite(n) || n <= 0) return null;
|
|
602
|
-
const ms = n < 1e12 ? Math.floor(n * 1000) : Math.floor(n);
|
|
603
|
-
const dt = new Date(ms);
|
|
604
|
-
if (Number.isNaN(dt.getTime())) return null;
|
|
605
|
-
return dt.toISOString();
|
|
606
498
|
}
|
|
607
499
|
|
|
608
500
|
async function safeStatSize(p) {
|
|
@@ -93,17 +93,6 @@ async function cmdUninstall(argv) {
|
|
|
93
93
|
unreadableText: (result) =>
|
|
94
94
|
`- OpenClaw session plugin: skipped (${result.detail || "openclaw config unreadable"})`,
|
|
95
95
|
}),
|
|
96
|
-
renderHookLine({
|
|
97
|
-
exists: true,
|
|
98
|
-
result: resultByName.get("openclaw-legacy"),
|
|
99
|
-
missingText: "- OpenClaw hook (legacy): skipped (openclaw config not found)",
|
|
100
|
-
removedText: (result) =>
|
|
101
|
-
`- OpenClaw hook (legacy) removed: ${result.detail || result.openclawConfigPath || "unknown"}`,
|
|
102
|
-
noChangeText: "- OpenClaw hook (legacy): no change",
|
|
103
|
-
skippedText: "- OpenClaw hook (legacy): no change",
|
|
104
|
-
unreadableText: (result) =>
|
|
105
|
-
`- OpenClaw hook (legacy): skipped (${result.detail || "openclaw config unreadable"})`,
|
|
106
|
-
}),
|
|
107
96
|
opts.purge ? `- Purged: ${path.join(home, ".vibeusage")}` : "- Purge: skipped (use --purge)",
|
|
108
97
|
"",
|
|
109
98
|
].join("\n"),
|
package/src/lib/diagnostics.js
CHANGED
|
@@ -61,7 +61,6 @@ async function collectTrackerDiagnostics({
|
|
|
61
61
|
const geminiProbe = probeByName.get("gemini");
|
|
62
62
|
const opencodeProbe = probeByName.get("opencode");
|
|
63
63
|
const openclawSessionProbe = probeByName.get("openclaw-session");
|
|
64
|
-
const openclawLegacyProbe = probeByName.get("openclaw-legacy");
|
|
65
64
|
|
|
66
65
|
const codexNotify = Array.isArray(codexProbe?.currentNotify)
|
|
67
66
|
? codexProbe.currentNotify.map((value) => redactValue(value, home))
|
|
@@ -156,14 +155,6 @@ async function collectTrackerDiagnostics({
|
|
|
156
155
|
typeof openclawSessionProbe?.detail === "string"
|
|
157
156
|
? redactError(openclawSessionProbe.detail, home)
|
|
158
157
|
: null,
|
|
159
|
-
openclaw_hook_status: openclawLegacyProbe?.status || "unknown",
|
|
160
|
-
openclaw_hook_configured: Boolean(openclawLegacyProbe?.configured),
|
|
161
|
-
openclaw_hook_linked: Boolean(openclawLegacyProbe?.linked),
|
|
162
|
-
openclaw_hook_enabled: Boolean(openclawLegacyProbe?.enabled),
|
|
163
|
-
openclaw_hook_detail:
|
|
164
|
-
typeof openclawLegacyProbe?.detail === "string"
|
|
165
|
-
? redactError(openclawLegacyProbe.detail, home)
|
|
166
|
-
: null,
|
|
167
158
|
},
|
|
168
159
|
upload: {
|
|
169
160
|
last_success_at: lastSuccessAt,
|
package/src/lib/doctor.js
CHANGED
|
@@ -313,8 +313,7 @@ function buildDiagnosticsChecks(diagnostics) {
|
|
|
313
313
|
notify.claude_hook_configured ||
|
|
314
314
|
notify.gemini_hook_configured ||
|
|
315
315
|
notify.opencode_plugin_configured ||
|
|
316
|
-
notify.openclaw_session_plugin_configured
|
|
317
|
-
notify.openclaw_hook_configured,
|
|
316
|
+
notify.openclaw_session_plugin_configured,
|
|
318
317
|
);
|
|
319
318
|
|
|
320
319
|
checks.push({
|
|
@@ -338,19 +337,6 @@ function buildDiagnosticsChecks(diagnostics) {
|
|
|
338
337
|
});
|
|
339
338
|
}
|
|
340
339
|
|
|
341
|
-
if (notify.openclaw_hook_status === "unreadable") {
|
|
342
|
-
checks.push({
|
|
343
|
-
id: "notify.openclaw_hook",
|
|
344
|
-
status: "warn",
|
|
345
|
-
detail: "OpenClaw hook config unreadable",
|
|
346
|
-
critical: false,
|
|
347
|
-
meta: {
|
|
348
|
-
status: notify.openclaw_hook_status,
|
|
349
|
-
detail: notify.openclaw_hook_detail || null,
|
|
350
|
-
},
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
|
|
354
340
|
const uploadError = diagnostics?.upload?.last_error || null;
|
|
355
341
|
checks.push({
|
|
356
342
|
id: "upload.last_error",
|
|
@@ -8,7 +8,6 @@ const {
|
|
|
8
8
|
buildGeminiHookCommand,
|
|
9
9
|
} = require("../gemini-config");
|
|
10
10
|
const { resolveOpencodeConfigDir } = require("../opencode-config");
|
|
11
|
-
const { resolveOpenclawHookPaths } = require("../openclaw-hook");
|
|
12
11
|
const { resolveOpenclawSessionPluginPaths } = require("../openclaw-session-plugin");
|
|
13
12
|
const { resolveTrackerPaths } = require("../tracker-paths");
|
|
14
13
|
|
|
@@ -63,11 +62,6 @@ async function createIntegrationContext({
|
|
|
63
62
|
trackerDir: resolvedTrackerPaths.trackerDir,
|
|
64
63
|
env,
|
|
65
64
|
}),
|
|
66
|
-
openclawLegacy: resolveOpenclawHookPaths({
|
|
67
|
-
home,
|
|
68
|
-
trackerDir: resolvedTrackerPaths.trackerDir,
|
|
69
|
-
env,
|
|
70
|
-
}),
|
|
71
65
|
};
|
|
72
66
|
}
|
|
73
67
|
|
|
@@ -5,7 +5,6 @@ const claude = require("./claude");
|
|
|
5
5
|
const gemini = require("./gemini");
|
|
6
6
|
const opencode = require("./opencode");
|
|
7
7
|
const openclawSession = require("./openclaw-session");
|
|
8
|
-
const openclawLegacy = require("./openclaw-legacy");
|
|
9
8
|
|
|
10
9
|
const INTEGRATIONS = [
|
|
11
10
|
codex,
|
|
@@ -14,7 +13,6 @@ const INTEGRATIONS = [
|
|
|
14
13
|
gemini,
|
|
15
14
|
opencode,
|
|
16
15
|
openclawSession,
|
|
17
|
-
openclawLegacy,
|
|
18
16
|
];
|
|
19
17
|
|
|
20
18
|
function listIntegrations() {
|