vibeusage 0.2.23 → 0.3.1
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 +25 -20
- package/README.zh-CN.md +7 -2
- package/node_modules/@insforge/sdk/LICENSE +201 -201
- package/node_modules/@insforge/sdk/README.md +326 -259
- package/node_modules/@insforge/sdk/dist/index.d.mts +377 -182
- package/node_modules/@insforge/sdk/dist/index.d.ts +377 -182
- package/node_modules/@insforge/sdk/dist/index.js +1172 -677
- package/node_modules/@insforge/sdk/dist/index.js.map +1 -1
- package/node_modules/@insforge/sdk/dist/index.mjs +1171 -677
- package/node_modules/@insforge/sdk/dist/index.mjs.map +1 -1
- package/node_modules/@insforge/sdk/package.json +68 -68
- package/node_modules/@insforge/shared-schemas/dist/ai-api.schema.d.ts +1120 -43
- package/node_modules/@insforge/shared-schemas/dist/ai-api.schema.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/ai-api.schema.js +179 -5
- package/node_modules/@insforge/shared-schemas/dist/ai-api.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/ai.schema.d.ts +25 -25
- package/node_modules/@insforge/shared-schemas/dist/ai.schema.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/ai.schema.js +2 -2
- package/node_modules/@insforge/shared-schemas/dist/ai.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/auth-api.schema.d.ts +197 -51
- package/node_modules/@insforge/shared-schemas/dist/auth-api.schema.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/auth-api.schema.js +87 -23
- package/node_modules/@insforge/shared-schemas/dist/auth-api.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/auth.schema.d.ts +32 -3
- package/node_modules/@insforge/shared-schemas/dist/auth.schema.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/auth.schema.js +21 -3
- package/node_modules/@insforge/shared-schemas/dist/auth.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/cloud-events.schema.d.ts +380 -0
- package/node_modules/@insforge/shared-schemas/dist/cloud-events.schema.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/cloud-events.schema.js +74 -0
- package/node_modules/@insforge/shared-schemas/dist/cloud-events.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/database-api.schema.d.ts +13 -13
- package/node_modules/@insforge/shared-schemas/dist/database-api.schema.js +1 -1
- package/node_modules/@insforge/shared-schemas/dist/database-api.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/deployments-api.schema.d.ts +735 -0
- package/node_modules/@insforge/shared-schemas/dist/deployments-api.schema.d.ts.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/deployments-api.schema.js +209 -0
- package/node_modules/@insforge/shared-schemas/dist/deployments-api.schema.js.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/deployments.schema.d.ts +37 -0
- package/node_modules/@insforge/shared-schemas/dist/deployments.schema.d.ts.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/deployments.schema.js +25 -0
- package/node_modules/@insforge/shared-schemas/dist/deployments.schema.js.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/docs.schema.d.ts +5 -1
- package/node_modules/@insforge/shared-schemas/dist/docs.schema.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/docs.schema.js +34 -4
- package/node_modules/@insforge/shared-schemas/dist/docs.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/email-api.schema.js +1 -1
- package/node_modules/@insforge/shared-schemas/dist/email-api.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/functions-api.schema.d.ts +186 -6
- package/node_modules/@insforge/shared-schemas/dist/functions-api.schema.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/functions-api.schema.js +21 -2
- package/node_modules/@insforge/shared-schemas/dist/functions-api.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/functions.schema.d.ts +5 -5
- package/node_modules/@insforge/shared-schemas/dist/functions.schema.js +1 -1
- package/node_modules/@insforge/shared-schemas/dist/functions.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/index.d.ts +24 -18
- package/node_modules/@insforge/shared-schemas/dist/index.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/index.js +24 -18
- package/node_modules/@insforge/shared-schemas/dist/index.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/logs-api.schema.js +1 -1
- package/node_modules/@insforge/shared-schemas/dist/logs-api.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/logs.schema.d.ts +43 -0
- package/node_modules/@insforge/shared-schemas/dist/logs.schema.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/logs.schema.js +11 -0
- package/node_modules/@insforge/shared-schemas/dist/logs.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/metadata.schema.d.ts +229 -172
- package/node_modules/@insforge/shared-schemas/dist/metadata.schema.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/metadata.schema.js +27 -7
- package/node_modules/@insforge/shared-schemas/dist/metadata.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/rate-limit-api.schema.d.ts +51 -0
- package/node_modules/@insforge/shared-schemas/dist/rate-limit-api.schema.d.ts.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/rate-limit-api.schema.js +31 -0
- package/node_modules/@insforge/shared-schemas/dist/rate-limit-api.schema.js.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/rate-limit.schema.d.ts +31 -0
- package/node_modules/@insforge/shared-schemas/dist/rate-limit.schema.d.ts.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/rate-limit.schema.js +12 -0
- package/node_modules/@insforge/shared-schemas/dist/rate-limit.schema.js.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/realtime-api.schema.d.ts +39 -20
- package/node_modules/@insforge/shared-schemas/dist/realtime-api.schema.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/realtime-api.schema.js +5 -1
- package/node_modules/@insforge/shared-schemas/dist/realtime-api.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/realtime.schema.d.ts +12 -4
- package/node_modules/@insforge/shared-schemas/dist/realtime.schema.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/realtime.schema.js +6 -0
- package/node_modules/@insforge/shared-schemas/dist/realtime.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/schedules-api.schema.d.ts +287 -0
- package/node_modules/@insforge/shared-schemas/dist/schedules-api.schema.d.ts.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/schedules-api.schema.js +81 -0
- package/node_modules/@insforge/shared-schemas/dist/schedules-api.schema.js.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/schedules.schema.d.ts +77 -0
- package/node_modules/@insforge/shared-schemas/dist/schedules.schema.d.ts.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/schedules.schema.js +36 -0
- package/node_modules/@insforge/shared-schemas/dist/schedules.schema.js.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/secrets-api.schema.d.ts +113 -0
- package/node_modules/@insforge/shared-schemas/dist/secrets-api.schema.d.ts.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/secrets-api.schema.js +31 -0
- package/node_modules/@insforge/shared-schemas/dist/secrets-api.schema.js.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/secrets.schema.d.ts +31 -0
- package/node_modules/@insforge/shared-schemas/dist/secrets.schema.d.ts.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/secrets.schema.js +13 -0
- package/node_modules/@insforge/shared-schemas/dist/secrets.schema.js.map +1 -0
- package/node_modules/@insforge/shared-schemas/dist/storage-api.schema.d.ts +27 -2
- package/node_modules/@insforge/shared-schemas/dist/storage-api.schema.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/storage-api.schema.js +9 -1
- package/node_modules/@insforge/shared-schemas/dist/storage-api.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/storage.schema.d.ts +17 -0
- package/node_modules/@insforge/shared-schemas/dist/storage.schema.d.ts.map +1 -1
- package/node_modules/@insforge/shared-schemas/dist/storage.schema.js +6 -0
- package/node_modules/@insforge/shared-schemas/dist/storage.schema.js.map +1 -1
- package/node_modules/@insforge/shared-schemas/package.json +2 -1
- package/package.json +5 -6
- package/src/cli.js +2 -2
- package/src/commands/init.js +20 -362
- package/src/commands/status.js +58 -51
- package/src/commands/sync.js +37 -25
- package/src/commands/uninstall.js +121 -104
- package/src/lib/claude-config.js +130 -35
- package/src/lib/diagnostics.js +88 -57
- package/src/lib/doctor.js +50 -0
- package/src/lib/insforge-client.js +13 -9
- package/src/lib/integrations/claude.js +106 -0
- package/src/lib/integrations/codex.js +88 -0
- package/src/lib/integrations/context.js +76 -0
- package/src/lib/integrations/every-code.js +88 -0
- package/src/lib/integrations/gemini.js +86 -0
- package/src/lib/integrations/index.js +85 -0
- package/src/lib/integrations/openclaw-legacy.js +123 -0
- package/src/lib/integrations/openclaw-session.js +132 -0
- package/src/lib/integrations/opencode.js +86 -0
- package/src/lib/integrations/utils.js +39 -0
- package/src/lib/opencode-sqlite.js +113 -0
- package/src/lib/opencode-usage-audit.js +3 -2
- package/src/lib/rollout.js +227 -1
- package/src/lib/runtime-config.js +7 -5
- package/src/lib/vibeusage-api.js +11 -7
- package/src/shared/copy-registry.cjs +142 -0
- package/src/shared/copy-registry.cjs.d.ts +33 -0
- package/src/shared/runtime-defaults.cjs +11 -0
- package/src/shared/runtime-defaults.cjs.d.ts +3 -0
- package/src/shared/vibeusage-function-contract.cjs +34 -0
- package/src/shared/vibeusage-function-contract.cjs.d.ts +4 -0
- package/src/commands/activate-if-needed.js +0 -41
- package/src/lib/activation-check.js +0 -341
package/src/lib/rollout.js
CHANGED
|
@@ -4,6 +4,7 @@ const path = require("node:path");
|
|
|
4
4
|
const readline = require("node:readline");
|
|
5
5
|
|
|
6
6
|
const { ensureDir } = require("./fs");
|
|
7
|
+
const { readOpencodeSqliteRows } = require("./opencode-sqlite");
|
|
7
8
|
const { hashRepoRoot, resolveGitHubPublicStatus } = require("./vibeusage-public-repo");
|
|
8
9
|
|
|
9
10
|
const DEFAULT_SOURCE = "codex";
|
|
@@ -398,12 +399,14 @@ async function parseGeminiIncremental({
|
|
|
398
399
|
|
|
399
400
|
async function parseOpencodeIncremental({
|
|
400
401
|
messageFiles,
|
|
402
|
+
opencodeDbPath,
|
|
401
403
|
cursors,
|
|
402
404
|
queuePath,
|
|
403
405
|
projectQueuePath,
|
|
404
406
|
onProgress,
|
|
405
407
|
source,
|
|
406
408
|
publicRepoResolver,
|
|
409
|
+
readSqliteRows,
|
|
407
410
|
}) {
|
|
408
411
|
await ensureDir(path.dirname(queuePath));
|
|
409
412
|
let filesProcessed = 0;
|
|
@@ -419,9 +422,13 @@ async function parseOpencodeIncremental({
|
|
|
419
422
|
const projectMetaCache = projectEnabled ? new Map() : null;
|
|
420
423
|
const publicRepoCache = projectEnabled ? new Map() : null;
|
|
421
424
|
const opencodeState = normalizeOpencodeState(cursors?.opencode);
|
|
425
|
+
const opencodeSqliteState = normalizeOpencodeSqliteState(cursors?.opencodeSqlite);
|
|
422
426
|
const messageIndex = opencodeState.messages;
|
|
423
427
|
const touchedBuckets = new Set();
|
|
424
428
|
const defaultSource = normalizeSourceInput(source) || "opencode";
|
|
429
|
+
let sqliteStatus = opencodeSqliteState.lastStatus || "never_checked";
|
|
430
|
+
let sqliteCheckedAt = opencodeSqliteState.lastCheckedAt || null;
|
|
431
|
+
let sqliteErrorCode = opencodeSqliteState.lastErrorCode || null;
|
|
425
432
|
|
|
426
433
|
if (!cursors.files || typeof cursors.files !== "object") {
|
|
427
434
|
cursors.files = {};
|
|
@@ -522,6 +529,90 @@ async function parseOpencodeIncremental({
|
|
|
522
529
|
}
|
|
523
530
|
}
|
|
524
531
|
|
|
532
|
+
if (typeof opencodeDbPath === "string" && opencodeDbPath.length > 0) {
|
|
533
|
+
const readRows =
|
|
534
|
+
typeof readSqliteRows === "function" ? readSqliteRows : readOpencodeSqliteRows;
|
|
535
|
+
const sqliteResult = await readRows({
|
|
536
|
+
dbPath: opencodeDbPath,
|
|
537
|
+
lastTimeCreated: opencodeSqliteState.lastTimeCreated,
|
|
538
|
+
expectedInode: opencodeSqliteState.inode,
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
sqliteStatus =
|
|
542
|
+
typeof sqliteResult?.status === "string" && sqliteResult.status.trim()
|
|
543
|
+
? sqliteResult.status.trim()
|
|
544
|
+
: "query-failed";
|
|
545
|
+
sqliteCheckedAt =
|
|
546
|
+
typeof sqliteResult?.checkedAt === "string" && sqliteResult.checkedAt.trim()
|
|
547
|
+
? sqliteResult.checkedAt.trim()
|
|
548
|
+
: new Date().toISOString();
|
|
549
|
+
sqliteErrorCode =
|
|
550
|
+
typeof sqliteResult?.errorCode === "string" && sqliteResult.errorCode.trim()
|
|
551
|
+
? sqliteResult.errorCode.trim()
|
|
552
|
+
: typeof sqliteResult?.error?.code === "string" && sqliteResult.error.code.trim()
|
|
553
|
+
? sqliteResult.error.code.trim()
|
|
554
|
+
: null;
|
|
555
|
+
|
|
556
|
+
opencodeSqliteState.lastStatus = sqliteStatus;
|
|
557
|
+
opencodeSqliteState.lastCheckedAt = sqliteCheckedAt;
|
|
558
|
+
opencodeSqliteState.lastErrorCode = sqliteErrorCode;
|
|
559
|
+
opencodeSqliteState.updatedAt = new Date().toISOString();
|
|
560
|
+
|
|
561
|
+
if (sqliteStatus === "ok") {
|
|
562
|
+
const sameDb =
|
|
563
|
+
!sqliteResult.cursorReset &&
|
|
564
|
+
opencodeSqliteState.inode &&
|
|
565
|
+
sqliteResult.inode &&
|
|
566
|
+
opencodeSqliteState.inode === sqliteResult.inode;
|
|
567
|
+
const prevProcessedIds = new Set(sameDb ? opencodeSqliteState.lastProcessedIds : []);
|
|
568
|
+
const rawRows = Array.isArray(sqliteResult.rows) ? sqliteResult.rows : [];
|
|
569
|
+
const rows = prevProcessedIds.size
|
|
570
|
+
? rawRows.filter((row) => !prevProcessedIds.has(row?.id))
|
|
571
|
+
: rawRows;
|
|
572
|
+
const knownMessageKeys = new Set([
|
|
573
|
+
...Object.keys(messageIndex || {}),
|
|
574
|
+
...Object.values(cursors.files || {})
|
|
575
|
+
.map((entry) => entry?.messageKey)
|
|
576
|
+
.filter((entry) => typeof entry === "string" && entry.trim()),
|
|
577
|
+
]);
|
|
578
|
+
|
|
579
|
+
for (const row of rows) {
|
|
580
|
+
const result = await parseOpencodeSqliteRow({
|
|
581
|
+
row,
|
|
582
|
+
messageIndex,
|
|
583
|
+
knownMessageKeys,
|
|
584
|
+
hourlyState,
|
|
585
|
+
touchedBuckets,
|
|
586
|
+
source: defaultSource,
|
|
587
|
+
projectState,
|
|
588
|
+
projectTouchedBuckets,
|
|
589
|
+
projectMetaCache,
|
|
590
|
+
publicRepoCache,
|
|
591
|
+
publicRepoResolver,
|
|
592
|
+
});
|
|
593
|
+
eventsAggregated += result.eventsAggregated;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
const lastTimeCreated = sameDb ? opencodeSqliteState.lastTimeCreated : 0;
|
|
597
|
+
const maxTime =
|
|
598
|
+
rawRows.length > 0
|
|
599
|
+
? Math.max(
|
|
600
|
+
lastTimeCreated,
|
|
601
|
+
...rawRows.map((row) =>
|
|
602
|
+
Number.isFinite(Number(row?.time_created)) ? Number(row.time_created) : 0,
|
|
603
|
+
),
|
|
604
|
+
)
|
|
605
|
+
: lastTimeCreated;
|
|
606
|
+
opencodeSqliteState.lastTimeCreated = maxTime;
|
|
607
|
+
opencodeSqliteState.lastProcessedIds = rawRows
|
|
608
|
+
.filter((row) => Number(row?.time_created) === maxTime)
|
|
609
|
+
.map((row) => row?.id)
|
|
610
|
+
.filter((value) => typeof value === "string" && value.trim());
|
|
611
|
+
opencodeSqliteState.inode = sqliteResult.inode || opencodeSqliteState.inode || 0;
|
|
612
|
+
}
|
|
613
|
+
cursors.opencodeSqlite = opencodeSqliteState;
|
|
614
|
+
}
|
|
615
|
+
|
|
525
616
|
const bucketsQueued = await enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets });
|
|
526
617
|
const projectBucketsQueued = projectEnabled
|
|
527
618
|
? await enqueueTouchedProjectBuckets({ projectQueuePath, projectState, projectTouchedBuckets })
|
|
@@ -535,7 +626,15 @@ async function parseOpencodeIncremental({
|
|
|
535
626
|
cursors.projectHourly = projectState;
|
|
536
627
|
}
|
|
537
628
|
|
|
538
|
-
return {
|
|
629
|
+
return {
|
|
630
|
+
filesProcessed,
|
|
631
|
+
eventsAggregated,
|
|
632
|
+
bucketsQueued,
|
|
633
|
+
projectBucketsQueued,
|
|
634
|
+
sqliteStatus,
|
|
635
|
+
sqliteCheckedAt,
|
|
636
|
+
sqliteErrorCode,
|
|
637
|
+
};
|
|
539
638
|
}
|
|
540
639
|
|
|
541
640
|
async function parseOpenclawIncremental({
|
|
@@ -1062,6 +1161,107 @@ async function parseOpencodeMessageFile({
|
|
|
1062
1161
|
return { messageKey, lastTotals: currentTotals, eventsAggregated: 1, shouldUpdate: true };
|
|
1063
1162
|
}
|
|
1064
1163
|
|
|
1164
|
+
async function parseOpencodeSqliteRow({
|
|
1165
|
+
row,
|
|
1166
|
+
messageIndex,
|
|
1167
|
+
knownMessageKeys,
|
|
1168
|
+
hourlyState,
|
|
1169
|
+
touchedBuckets,
|
|
1170
|
+
source,
|
|
1171
|
+
projectState,
|
|
1172
|
+
projectTouchedBuckets,
|
|
1173
|
+
projectMetaCache,
|
|
1174
|
+
publicRepoCache,
|
|
1175
|
+
publicRepoResolver,
|
|
1176
|
+
}) {
|
|
1177
|
+
if (!row || typeof row !== "object") {
|
|
1178
|
+
return { eventsAggregated: 0 };
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
let msg;
|
|
1182
|
+
try {
|
|
1183
|
+
msg = JSON.parse(String(row.data || ""));
|
|
1184
|
+
} catch (_e) {
|
|
1185
|
+
return { eventsAggregated: 0 };
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
const rowRole =
|
|
1189
|
+
normalizeMessageKeyPart(row.role) ||
|
|
1190
|
+
normalizeMessageKeyPart(msg?.role) ||
|
|
1191
|
+
normalizeMessageKeyPart(msg?.type);
|
|
1192
|
+
if (rowRole && rowRole !== "assistant") {
|
|
1193
|
+
return { eventsAggregated: 0 };
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
const messageKey = deriveOpencodeMessageKey(msg, null);
|
|
1197
|
+
if (!messageKey || knownMessageKeys.has(messageKey)) {
|
|
1198
|
+
return { eventsAggregated: 0 };
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
const currentTotals = normalizeOpencodeTokens(msg?.tokens);
|
|
1202
|
+
if (!currentTotals || isAllZeroUsage(currentTotals)) {
|
|
1203
|
+
return { eventsAggregated: 0 };
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
const timestampMs = coerceEpochMs(msg?.time?.completed) || coerceEpochMs(msg?.time?.created);
|
|
1207
|
+
if (!timestampMs) {
|
|
1208
|
+
return { eventsAggregated: 0 };
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
const bucketStart = toUtcHalfHourStart(new Date(timestampMs).toISOString());
|
|
1212
|
+
if (!bucketStart) {
|
|
1213
|
+
return { eventsAggregated: 0 };
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
const model = normalizeModelInput(msg?.modelID || msg?.model || msg?.modelId) || DEFAULT_MODEL;
|
|
1217
|
+
const bucket = getHourlyBucket(hourlyState, source, model, bucketStart);
|
|
1218
|
+
addTotals(bucket.totals, currentTotals);
|
|
1219
|
+
touchedBuckets.add(bucketKey(source, model, bucketStart));
|
|
1220
|
+
|
|
1221
|
+
const projectWorktree =
|
|
1222
|
+
typeof row.project_worktree === "string" && row.project_worktree.trim()
|
|
1223
|
+
? row.project_worktree.trim()
|
|
1224
|
+
: null;
|
|
1225
|
+
if (
|
|
1226
|
+
projectWorktree &&
|
|
1227
|
+
projectState &&
|
|
1228
|
+
projectTouchedBuckets &&
|
|
1229
|
+
projectMetaCache &&
|
|
1230
|
+
publicRepoCache
|
|
1231
|
+
) {
|
|
1232
|
+
const projectContext = await resolveProjectContextForPath({
|
|
1233
|
+
startDir: projectWorktree,
|
|
1234
|
+
projectMetaCache,
|
|
1235
|
+
publicRepoCache,
|
|
1236
|
+
publicRepoResolver,
|
|
1237
|
+
projectState,
|
|
1238
|
+
});
|
|
1239
|
+
const projectRef = projectContext?.projectRef || null;
|
|
1240
|
+
const projectKey = projectContext?.projectKey || null;
|
|
1241
|
+
if (projectKey) {
|
|
1242
|
+
const projectBucket = getProjectBucket(
|
|
1243
|
+
projectState,
|
|
1244
|
+
projectKey,
|
|
1245
|
+
source,
|
|
1246
|
+
bucketStart,
|
|
1247
|
+
projectRef,
|
|
1248
|
+
);
|
|
1249
|
+
addTotals(projectBucket.totals, currentTotals);
|
|
1250
|
+
projectTouchedBuckets.add(projectBucketKey(projectKey, source, bucketStart));
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
if (messageIndex && typeof messageIndex === "object") {
|
|
1255
|
+
messageIndex[messageKey] = {
|
|
1256
|
+
lastTotals: currentTotals,
|
|
1257
|
+
updatedAt: new Date().toISOString(),
|
|
1258
|
+
};
|
|
1259
|
+
}
|
|
1260
|
+
knownMessageKeys.add(messageKey);
|
|
1261
|
+
|
|
1262
|
+
return { eventsAggregated: 1 };
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1065
1265
|
async function enqueueTouchedBuckets({ queuePath, hourlyState, touchedBuckets }) {
|
|
1066
1266
|
if (!touchedBuckets || touchedBuckets.size === 0) return 0;
|
|
1067
1267
|
|
|
@@ -1559,6 +1759,32 @@ function normalizeOpencodeState(raw) {
|
|
|
1559
1759
|
};
|
|
1560
1760
|
}
|
|
1561
1761
|
|
|
1762
|
+
function normalizeOpencodeSqliteState(raw) {
|
|
1763
|
+
const state = raw && typeof raw === "object" ? raw : {};
|
|
1764
|
+
return {
|
|
1765
|
+
lastTimeCreated: Number.isFinite(Number(state.lastTimeCreated))
|
|
1766
|
+
? Number(state.lastTimeCreated)
|
|
1767
|
+
: 0,
|
|
1768
|
+
lastProcessedIds: Array.isArray(state.lastProcessedIds)
|
|
1769
|
+
? state.lastProcessedIds
|
|
1770
|
+
.filter((value) => typeof value === "string" && value.trim())
|
|
1771
|
+
.map((value) => value.trim())
|
|
1772
|
+
: [],
|
|
1773
|
+
inode: Number.isFinite(Number(state.inode)) ? Number(state.inode) : 0,
|
|
1774
|
+
updatedAt: typeof state.updatedAt === "string" ? state.updatedAt : null,
|
|
1775
|
+
lastStatus:
|
|
1776
|
+
typeof state.lastStatus === "string" && state.lastStatus.trim() ? state.lastStatus.trim() : null,
|
|
1777
|
+
lastCheckedAt:
|
|
1778
|
+
typeof state.lastCheckedAt === "string" && state.lastCheckedAt.trim()
|
|
1779
|
+
? state.lastCheckedAt.trim()
|
|
1780
|
+
: null,
|
|
1781
|
+
lastErrorCode:
|
|
1782
|
+
typeof state.lastErrorCode === "string" && state.lastErrorCode.trim()
|
|
1783
|
+
? state.lastErrorCode.trim()
|
|
1784
|
+
: null,
|
|
1785
|
+
};
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1562
1788
|
function normalizeMessageKeyPart(value) {
|
|
1563
1789
|
if (typeof value !== "string") return "";
|
|
1564
1790
|
return value.trim();
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const {
|
|
2
|
+
DEFAULT_INSFORGE_BASE_URL,
|
|
3
|
+
DEFAULT_DASHBOARD_URL,
|
|
4
|
+
DEFAULT_HTTP_TIMEOUT_MS,
|
|
5
|
+
} = require("../shared/runtime-defaults.cjs");
|
|
4
6
|
|
|
5
7
|
function resolveRuntimeConfig({ cli = {}, config = {}, env = process.env, defaults = {} } = {}) {
|
|
6
8
|
const baseUrl = pickString(
|
|
@@ -8,7 +10,7 @@ function resolveRuntimeConfig({ cli = {}, config = {}, env = process.env, defaul
|
|
|
8
10
|
config.baseUrl,
|
|
9
11
|
env?.VIBEUSAGE_INSFORGE_BASE_URL,
|
|
10
12
|
defaults.baseUrl,
|
|
11
|
-
|
|
13
|
+
DEFAULT_INSFORGE_BASE_URL,
|
|
12
14
|
);
|
|
13
15
|
const dashboardUrl = pickString(
|
|
14
16
|
cli.dashboardUrl,
|
|
@@ -125,7 +127,7 @@ function clampInt(value, min, max) {
|
|
|
125
127
|
}
|
|
126
128
|
|
|
127
129
|
module.exports = {
|
|
128
|
-
DEFAULT_BASE_URL,
|
|
130
|
+
DEFAULT_BASE_URL: DEFAULT_INSFORGE_BASE_URL,
|
|
129
131
|
DEFAULT_DASHBOARD_URL,
|
|
130
132
|
DEFAULT_HTTP_TIMEOUT_MS,
|
|
131
133
|
resolveRuntimeConfig,
|
package/src/lib/vibeusage-api.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
const { createInsforgeClient } = require("./insforge-client");
|
|
4
|
+
const {
|
|
5
|
+
BACKEND_RUNTIME_UNAVAILABLE_MESSAGE,
|
|
6
|
+
FUNCTION_SLUGS,
|
|
7
|
+
} = require("../shared/vibeusage-function-contract.cjs");
|
|
4
8
|
|
|
5
9
|
async function signInWithPassword({ baseUrl, email, password }) {
|
|
6
|
-
const client = createInsforgeClient({ baseUrl });
|
|
10
|
+
const client = await createInsforgeClient({ baseUrl });
|
|
7
11
|
const { data, error } = await client.auth.signInWithPassword({ email, password });
|
|
8
12
|
if (error) throw normalizeSdkError(error, "Sign-in failed");
|
|
9
13
|
|
|
@@ -19,7 +23,7 @@ async function issueDeviceToken({ baseUrl, accessToken, deviceName, platform = "
|
|
|
19
23
|
const data = await invokeFunction({
|
|
20
24
|
baseUrl,
|
|
21
25
|
accessToken,
|
|
22
|
-
slug:
|
|
26
|
+
slug: FUNCTION_SLUGS.deviceTokenIssue,
|
|
23
27
|
method: "POST",
|
|
24
28
|
body: { device_name: deviceName, platform },
|
|
25
29
|
errorPrefix: "Device token issue failed",
|
|
@@ -40,7 +44,7 @@ async function exchangeLinkCode({ baseUrl, linkCode, requestId, deviceName, plat
|
|
|
40
44
|
const data = await invokeFunction({
|
|
41
45
|
baseUrl,
|
|
42
46
|
accessToken: null,
|
|
43
|
-
slug:
|
|
47
|
+
slug: FUNCTION_SLUGS.linkCodeExchange,
|
|
44
48
|
method: "POST",
|
|
45
49
|
body: {
|
|
46
50
|
link_code: linkCode,
|
|
@@ -78,7 +82,7 @@ async function ingestHourly({
|
|
|
78
82
|
const data = await invokeFunctionWithRetry({
|
|
79
83
|
baseUrl,
|
|
80
84
|
accessToken: deviceToken,
|
|
81
|
-
slug:
|
|
85
|
+
slug: FUNCTION_SLUGS.ingest,
|
|
82
86
|
method: "POST",
|
|
83
87
|
body,
|
|
84
88
|
errorPrefix: "Ingest failed",
|
|
@@ -95,7 +99,7 @@ async function syncHeartbeat({ baseUrl, deviceToken }) {
|
|
|
95
99
|
const data = await invokeFunction({
|
|
96
100
|
baseUrl,
|
|
97
101
|
accessToken: deviceToken,
|
|
98
|
-
slug:
|
|
102
|
+
slug: FUNCTION_SLUGS.syncPing,
|
|
99
103
|
method: "POST",
|
|
100
104
|
body: {},
|
|
101
105
|
errorPrefix: "Sync heartbeat failed",
|
|
@@ -117,7 +121,7 @@ module.exports = {
|
|
|
117
121
|
};
|
|
118
122
|
|
|
119
123
|
async function invokeFunction({ baseUrl, accessToken, slug, method, body, errorPrefix }) {
|
|
120
|
-
const client = createInsforgeClient({ baseUrl, accessToken });
|
|
124
|
+
const client = await createInsforgeClient({ baseUrl, accessToken });
|
|
121
125
|
const { data, error } = await client.functions.invoke(slug, { method, body });
|
|
122
126
|
if (error) throw normalizeSdkError(error, errorPrefix);
|
|
123
127
|
return data;
|
|
@@ -174,7 +178,7 @@ function extractSdkErrorMessage(error) {
|
|
|
174
178
|
|
|
175
179
|
function normalizeBackendErrorMessage(message) {
|
|
176
180
|
if (!isBackendRuntimeDownMessage(message)) return String(message || "Unknown error");
|
|
177
|
-
return
|
|
181
|
+
return BACKEND_RUNTIME_UNAVAILABLE_MESSAGE;
|
|
178
182
|
}
|
|
179
183
|
|
|
180
184
|
function isBackendRuntimeDownMessage(message) {
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const REQUIRED_COPY_COLUMNS = ["key", "module", "page", "component", "slot", "text"];
|
|
4
|
+
|
|
5
|
+
function parseCsvRows(raw) {
|
|
6
|
+
const rows = [];
|
|
7
|
+
let row = [];
|
|
8
|
+
let field = "";
|
|
9
|
+
let inQuotes = false;
|
|
10
|
+
|
|
11
|
+
for (let i = 0; i < String(raw || "").length; i += 1) {
|
|
12
|
+
const ch = raw[i];
|
|
13
|
+
|
|
14
|
+
if (inQuotes) {
|
|
15
|
+
if (ch === '"') {
|
|
16
|
+
const next = raw[i + 1];
|
|
17
|
+
if (next === '"') {
|
|
18
|
+
field += '"';
|
|
19
|
+
i += 1;
|
|
20
|
+
} else {
|
|
21
|
+
inQuotes = false;
|
|
22
|
+
}
|
|
23
|
+
} else {
|
|
24
|
+
field += ch;
|
|
25
|
+
}
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (ch === '"') {
|
|
30
|
+
inQuotes = true;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (ch === ",") {
|
|
35
|
+
row.push(field);
|
|
36
|
+
field = "";
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (ch === "\n") {
|
|
41
|
+
row.push(field);
|
|
42
|
+
field = "";
|
|
43
|
+
if (!row.every((cell) => String(cell).trim() === "")) {
|
|
44
|
+
rows.push(row);
|
|
45
|
+
}
|
|
46
|
+
row = [];
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (ch === "\r") continue;
|
|
51
|
+
|
|
52
|
+
field += ch;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
row.push(field);
|
|
56
|
+
if (!row.every((cell) => String(cell).trim() === "")) {
|
|
57
|
+
rows.push(row);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return rows;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function buildCopyRegistry(raw) {
|
|
64
|
+
const rows = parseCsvRows(raw || "");
|
|
65
|
+
if (!rows.length) {
|
|
66
|
+
return {
|
|
67
|
+
header: [],
|
|
68
|
+
rows: [],
|
|
69
|
+
map: new Map(),
|
|
70
|
+
duplicates: new Map(),
|
|
71
|
+
missingColumns: [...REQUIRED_COPY_COLUMNS],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const header = rows[0].map((cell) => String(cell).trim());
|
|
76
|
+
const missingColumns = REQUIRED_COPY_COLUMNS.filter((col) => !header.includes(col));
|
|
77
|
+
if (missingColumns.length > 0) {
|
|
78
|
+
return {
|
|
79
|
+
header,
|
|
80
|
+
rows: [],
|
|
81
|
+
map: new Map(),
|
|
82
|
+
duplicates: new Map(),
|
|
83
|
+
missingColumns,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const indexByColumn = Object.fromEntries(header.map((col, index) => [col, index]));
|
|
88
|
+
const entries = [];
|
|
89
|
+
const map = new Map();
|
|
90
|
+
const duplicates = new Map();
|
|
91
|
+
|
|
92
|
+
rows.slice(1).forEach((cells, rowIndex) => {
|
|
93
|
+
const record = {
|
|
94
|
+
key: String(cells[indexByColumn.key] || "").trim(),
|
|
95
|
+
module: String(cells[indexByColumn.module] || "").trim(),
|
|
96
|
+
page: String(cells[indexByColumn.page] || "").trim(),
|
|
97
|
+
component: String(cells[indexByColumn.component] || "").trim(),
|
|
98
|
+
slot: String(cells[indexByColumn.slot] || "").trim(),
|
|
99
|
+
text: String(cells[indexByColumn.text] ?? "").trim(),
|
|
100
|
+
row: rowIndex + 2,
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
if (!record.key) return;
|
|
104
|
+
|
|
105
|
+
if (map.has(record.key)) {
|
|
106
|
+
const existingRows = duplicates.get(record.key) || [map.get(record.key).row];
|
|
107
|
+
existingRows.push(record.row);
|
|
108
|
+
duplicates.set(record.key, existingRows);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
map.set(record.key, record);
|
|
112
|
+
entries.push(record);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
header,
|
|
117
|
+
rows: entries,
|
|
118
|
+
map,
|
|
119
|
+
duplicates,
|
|
120
|
+
missingColumns: [],
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function normalizeCopyText(text) {
|
|
125
|
+
return String(text ?? "").replace(/\\n/g, "\n");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function interpolateCopyText(text, params) {
|
|
129
|
+
if (!params || typeof params !== "object") return text;
|
|
130
|
+
return String(text).replace(/\{\{(\w+)\}\}/g, (match, key) => {
|
|
131
|
+
if (params[key] == null) return match;
|
|
132
|
+
return String(params[key]);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
module.exports = {
|
|
137
|
+
REQUIRED_COPY_COLUMNS,
|
|
138
|
+
parseCsvRows,
|
|
139
|
+
buildCopyRegistry,
|
|
140
|
+
normalizeCopyText,
|
|
141
|
+
interpolateCopyText,
|
|
142
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const REQUIRED_COPY_COLUMNS: string[];
|
|
2
|
+
|
|
3
|
+
export function parseCsvRows(raw: string): string[][];
|
|
4
|
+
|
|
5
|
+
export function buildCopyRegistry(raw: string): {
|
|
6
|
+
header: string[];
|
|
7
|
+
rows: Array<{
|
|
8
|
+
key: string;
|
|
9
|
+
module: string;
|
|
10
|
+
page: string;
|
|
11
|
+
component: string;
|
|
12
|
+
slot: string;
|
|
13
|
+
text: string;
|
|
14
|
+
row: number;
|
|
15
|
+
}>;
|
|
16
|
+
map: Map<
|
|
17
|
+
string,
|
|
18
|
+
{
|
|
19
|
+
key: string;
|
|
20
|
+
module: string;
|
|
21
|
+
page: string;
|
|
22
|
+
component: string;
|
|
23
|
+
slot: string;
|
|
24
|
+
text: string;
|
|
25
|
+
row: number;
|
|
26
|
+
}
|
|
27
|
+
>;
|
|
28
|
+
duplicates: Map<string, number[]>;
|
|
29
|
+
missingColumns: string[];
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export function normalizeCopyText(text: unknown): string;
|
|
33
|
+
export function interpolateCopyText(text: string, params?: Record<string, unknown>): string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const DEFAULT_INSFORGE_BASE_URL = "https://5tmappuk.us-east.insforge.app";
|
|
4
|
+
const DEFAULT_DASHBOARD_URL = "https://www.vibeusage.cc";
|
|
5
|
+
const DEFAULT_HTTP_TIMEOUT_MS = 20_000;
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
DEFAULT_INSFORGE_BASE_URL,
|
|
9
|
+
DEFAULT_DASHBOARD_URL,
|
|
10
|
+
DEFAULT_HTTP_TIMEOUT_MS,
|
|
11
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const FUNCTION_PREFIX = "/functions";
|
|
4
|
+
const LEGACY_FUNCTION_PREFIX = "/api/functions";
|
|
5
|
+
const BACKEND_RUNTIME_UNAVAILABLE_MESSAGE =
|
|
6
|
+
"Backend runtime unavailable (InsForge). Please retry later.";
|
|
7
|
+
|
|
8
|
+
const FUNCTION_SLUGS = Object.freeze({
|
|
9
|
+
deviceTokenIssue: "vibeusage-device-token-issue",
|
|
10
|
+
ingest: "vibeusage-ingest",
|
|
11
|
+
syncPing: "vibeusage-sync-ping",
|
|
12
|
+
usageSummary: "vibeusage-usage-summary",
|
|
13
|
+
usageDaily: "vibeusage-usage-daily",
|
|
14
|
+
usageHourly: "vibeusage-usage-hourly",
|
|
15
|
+
usageMonthly: "vibeusage-usage-monthly",
|
|
16
|
+
usageHeatmap: "vibeusage-usage-heatmap",
|
|
17
|
+
usageModelBreakdown: "vibeusage-usage-model-breakdown",
|
|
18
|
+
projectUsageSummary: "vibeusage-project-usage-summary",
|
|
19
|
+
leaderboard: "vibeusage-leaderboard",
|
|
20
|
+
leaderboardProfile: "vibeusage-leaderboard-profile",
|
|
21
|
+
userStatus: "vibeusage-user-status",
|
|
22
|
+
viewerIdentity: "vibeusage-viewer-identity",
|
|
23
|
+
linkCodeInit: "vibeusage-link-code-init",
|
|
24
|
+
linkCodeExchange: "vibeusage-link-code-exchange",
|
|
25
|
+
publicViewProfile: "vibeusage-public-view-profile",
|
|
26
|
+
publicVisibility: "vibeusage-public-visibility",
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
module.exports = {
|
|
30
|
+
FUNCTION_PREFIX,
|
|
31
|
+
LEGACY_FUNCTION_PREFIX,
|
|
32
|
+
BACKEND_RUNTIME_UNAVAILABLE_MESSAGE,
|
|
33
|
+
FUNCTION_SLUGS,
|
|
34
|
+
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
const { checkAndActivate } = require("../lib/activation-check");
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 检测并激活未配置的 AI CLI 集成
|
|
5
|
-
* 用于 hooks 或其他触发器调用
|
|
6
|
-
*/
|
|
7
|
-
async function cmdActivateIfNeeded(argv) {
|
|
8
|
-
const opts = parseArgs(argv);
|
|
9
|
-
|
|
10
|
-
const results = await checkAndActivate({
|
|
11
|
-
silent: opts.silent,
|
|
12
|
-
autoConfigure: true,
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
if (!opts.silent) {
|
|
16
|
-
if (results.length === 0) {
|
|
17
|
-
console.log("所有 AI CLI 集成已配置完成");
|
|
18
|
-
} else {
|
|
19
|
-
for (const r of results) {
|
|
20
|
-
const icon = r.action === "configured" ? "✅" : "❌";
|
|
21
|
-
console.log(`${icon} ${r.displayName}: ${r.action}`);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// 如果有任何配置成功,返回 0,否则返回 1
|
|
27
|
-
const hasSuccess = results.some(r => r.action === "configured");
|
|
28
|
-
process.exitCode = hasSuccess ? 0 : 0; // 始终返回 0,不阻塞调用方
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function parseArgs(argv) {
|
|
32
|
-
const out = {
|
|
33
|
-
silent: false,
|
|
34
|
-
};
|
|
35
|
-
for (const a of argv) {
|
|
36
|
-
if (a === "--silent") out.silent = true;
|
|
37
|
-
}
|
|
38
|
-
return out;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
module.exports = { cmdActivateIfNeeded };
|