standout 0.5.35 → 0.5.37
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/dist/cli.js +217 -188
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2,17 +2,25 @@
|
|
|
2
2
|
var __toBinaryNode = Uint8Array.fromBase64 || ((base64) => new Uint8Array(Buffer.from(base64, "base64")));
|
|
3
3
|
|
|
4
4
|
// src/cli.ts
|
|
5
|
-
import
|
|
5
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
6
6
|
import chalk2 from "chalk";
|
|
7
7
|
import { writeFileSync } from "node:fs";
|
|
8
8
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
9
9
|
import { join as join6 } from "node:path";
|
|
10
10
|
import { createInterface as createInterface3 } from "readline";
|
|
11
11
|
|
|
12
|
+
// src/sources.ts
|
|
13
|
+
var SOURCES = ["claude_code", "cowork", "codex", "cursor"];
|
|
14
|
+
var SOURCE_LABELS = {
|
|
15
|
+
claude_code: "Claude Code",
|
|
16
|
+
cowork: "Cowork",
|
|
17
|
+
codex: "Codex",
|
|
18
|
+
cursor: "Cursor"
|
|
19
|
+
};
|
|
20
|
+
|
|
12
21
|
// src/payload.ts
|
|
13
22
|
var MAX_BODY_BYTES = 4e6;
|
|
14
23
|
var MAX_UPLOAD_EXCHANGES = 500;
|
|
15
|
-
var TOOLS = ["claude_code", "codex", "cursor"];
|
|
16
24
|
function byteLength(value) {
|
|
17
25
|
return Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
18
26
|
}
|
|
@@ -26,7 +34,7 @@ function exchangesOf(aiUsage, tool) {
|
|
|
26
34
|
function totalExchanges(payload) {
|
|
27
35
|
const aiUsage = asRecord(payload.ai_usage);
|
|
28
36
|
if (!aiUsage) return 0;
|
|
29
|
-
return
|
|
37
|
+
return SOURCES.reduce((n, t) => n + exchangesOf(aiUsage, t).length, 0);
|
|
30
38
|
}
|
|
31
39
|
function evenSample(arr, keep) {
|
|
32
40
|
if (arr.length <= keep) return arr;
|
|
@@ -38,7 +46,7 @@ function evenSample(arr, keep) {
|
|
|
38
46
|
function capExchangesInPlace(payload, maxTotal) {
|
|
39
47
|
const aiUsage = asRecord(payload.ai_usage);
|
|
40
48
|
if (!aiUsage) return;
|
|
41
|
-
const present =
|
|
49
|
+
const present = SOURCES.map((t) => ({
|
|
42
50
|
t,
|
|
43
51
|
n: exchangesOf(aiUsage, t).length
|
|
44
52
|
})).filter((x) => x.n > 0);
|
|
@@ -71,7 +79,7 @@ function capPayload(payload) {
|
|
|
71
79
|
}
|
|
72
80
|
const over = () => byteLength(p) > MAX_BODY_BYTES;
|
|
73
81
|
if (over()) {
|
|
74
|
-
for (const t of
|
|
82
|
+
for (const t of SOURCES) {
|
|
75
83
|
const tool = asRecord(aiUsage[t]);
|
|
76
84
|
if (tool && Array.isArray(tool.conversation_samples) && tool.conversation_samples.length) {
|
|
77
85
|
tool.conversation_samples = [];
|
|
@@ -82,7 +90,7 @@ function capPayload(payload) {
|
|
|
82
90
|
}
|
|
83
91
|
}
|
|
84
92
|
if (over()) {
|
|
85
|
-
for (const t of
|
|
93
|
+
for (const t of SOURCES) {
|
|
86
94
|
const tool = asRecord(aiUsage[t]);
|
|
87
95
|
if (tool && Array.isArray(tool.prompt_samples) && tool.prompt_samples.length) {
|
|
88
96
|
tool.prompt_samples = [];
|
|
@@ -110,7 +118,7 @@ function capPayload(payload) {
|
|
|
110
118
|
}
|
|
111
119
|
}
|
|
112
120
|
while (over() && totalExchanges(p) > 0) {
|
|
113
|
-
for (const t of
|
|
121
|
+
for (const t of SOURCES) {
|
|
114
122
|
const tool = asRecord(aiUsage[t]);
|
|
115
123
|
const ex = tool?.exchanges;
|
|
116
124
|
if (tool && Array.isArray(ex) && ex.length > 0) {
|
|
@@ -244,139 +252,15 @@ function boostProficiencyForDisplay(p) {
|
|
|
244
252
|
return { ...p, score, craft_bonus: Math.max(0, score - p.base) };
|
|
245
253
|
}
|
|
246
254
|
|
|
247
|
-
// ../../lib/
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
import { SpanStatusCode } from "@opentelemetry/api";
|
|
255
|
-
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
|
|
256
|
-
import { LangfuseSpanProcessor } from "@langfuse/otel";
|
|
257
|
-
import { setLangfuseTracerProvider } from "@langfuse/tracing";
|
|
258
|
-
import { CallbackHandler } from "@langfuse/langchain";
|
|
259
|
-
|
|
260
|
-
// ../../lib/llm/useCase.ts
|
|
261
|
-
var DEFAULT_RETRY_STRATEGY = {
|
|
262
|
-
maxRetries: 5,
|
|
263
|
-
initialDelaySeconds: 1,
|
|
264
|
-
maxDelaySeconds: 16,
|
|
265
|
-
retryAfterFloorMs: 500
|
|
266
|
-
};
|
|
267
|
-
function sleep(ms) {
|
|
268
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
269
|
-
}
|
|
270
|
-
var RetryingAnthropic = class extends Anthropic {
|
|
271
|
-
constructor(opts = {}) {
|
|
272
|
-
const strategy = {
|
|
273
|
-
...DEFAULT_RETRY_STRATEGY,
|
|
274
|
-
...opts.retryStrategy ?? {}
|
|
275
|
-
};
|
|
276
|
-
const { retryStrategy: _strategy, ...clientOpts } = opts;
|
|
277
|
-
super({
|
|
278
|
-
...clientOpts,
|
|
279
|
-
maxRetries: clientOpts.maxRetries ?? strategy.maxRetries
|
|
280
|
-
});
|
|
281
|
-
this.retryStrategy = strategy;
|
|
282
|
-
}
|
|
283
|
-
};
|
|
284
|
-
RetryingAnthropic.prototype.retryRequest = async function(options, retriesRemaining, requestLogID, responseHeaders) {
|
|
285
|
-
const strategy = this.retryStrategy;
|
|
286
|
-
let timeoutMillis;
|
|
287
|
-
const retryAfterMillisHeader = responseHeaders?.get("retry-after-ms");
|
|
288
|
-
if (retryAfterMillisHeader) {
|
|
289
|
-
const ms = parseFloat(retryAfterMillisHeader);
|
|
290
|
-
if (!Number.isNaN(ms)) timeoutMillis = ms;
|
|
291
|
-
}
|
|
292
|
-
const retryAfterHeader = responseHeaders?.get("retry-after");
|
|
293
|
-
if (retryAfterHeader && timeoutMillis === void 0) {
|
|
294
|
-
const seconds = parseFloat(retryAfterHeader);
|
|
295
|
-
if (!Number.isNaN(seconds)) {
|
|
296
|
-
timeoutMillis = seconds * 1e3;
|
|
297
|
-
} else {
|
|
298
|
-
timeoutMillis = Date.parse(retryAfterHeader) - Date.now();
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
if (timeoutMillis === void 0 || Number.isNaN(timeoutMillis)) {
|
|
302
|
-
const numRetries = strategy.maxRetries - retriesRemaining;
|
|
303
|
-
const sleepSeconds = Math.min(
|
|
304
|
-
strategy.initialDelaySeconds * Math.pow(2, numRetries),
|
|
305
|
-
strategy.maxDelaySeconds
|
|
306
|
-
);
|
|
307
|
-
const jitter = 1 - Math.random() * 0.25;
|
|
308
|
-
timeoutMillis = sleepSeconds * jitter * 1e3;
|
|
309
|
-
} else {
|
|
310
|
-
timeoutMillis = Math.max(timeoutMillis, strategy.retryAfterFloorMs);
|
|
311
|
-
}
|
|
312
|
-
await sleep(timeoutMillis);
|
|
313
|
-
const makeRequest = this.makeRequest;
|
|
314
|
-
return makeRequest.call(this, options, retriesRemaining - 1, requestLogID);
|
|
315
|
-
};
|
|
316
|
-
var RetryingOpenAI = class extends OpenAI {
|
|
317
|
-
constructor(opts = {}) {
|
|
318
|
-
const strategy = {
|
|
319
|
-
...DEFAULT_RETRY_STRATEGY,
|
|
320
|
-
...opts.retryStrategy ?? {}
|
|
321
|
-
};
|
|
322
|
-
const { retryStrategy: _strategy, ...clientOpts } = opts;
|
|
323
|
-
super({
|
|
324
|
-
...clientOpts,
|
|
325
|
-
maxRetries: clientOpts.maxRetries ?? strategy.maxRetries
|
|
326
|
-
});
|
|
327
|
-
this.retryStrategy = strategy;
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
|
-
RetryingOpenAI.prototype.retryRequest = async function(options, retriesRemaining, responseHeaders) {
|
|
331
|
-
const strategy = this.retryStrategy;
|
|
332
|
-
let timeoutMillis;
|
|
333
|
-
const retryAfterMillisHeader = responseHeaders?.get("retry-after-ms");
|
|
334
|
-
if (retryAfterMillisHeader) {
|
|
335
|
-
const ms = parseFloat(retryAfterMillisHeader);
|
|
336
|
-
if (!Number.isNaN(ms)) timeoutMillis = ms;
|
|
337
|
-
}
|
|
338
|
-
const retryAfterHeader = responseHeaders?.get("retry-after");
|
|
339
|
-
if (retryAfterHeader && timeoutMillis === void 0) {
|
|
340
|
-
const seconds = parseFloat(retryAfterHeader);
|
|
341
|
-
if (!Number.isNaN(seconds)) {
|
|
342
|
-
timeoutMillis = seconds * 1e3;
|
|
343
|
-
} else {
|
|
344
|
-
timeoutMillis = Date.parse(retryAfterHeader) - Date.now();
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
if (timeoutMillis === void 0 || Number.isNaN(timeoutMillis)) {
|
|
348
|
-
const numRetries = strategy.maxRetries - retriesRemaining;
|
|
349
|
-
const sleepSeconds = Math.min(
|
|
350
|
-
strategy.initialDelaySeconds * Math.pow(2, numRetries),
|
|
351
|
-
strategy.maxDelaySeconds
|
|
352
|
-
);
|
|
353
|
-
const jitter = 1 - Math.random() * 0.25;
|
|
354
|
-
timeoutMillis = sleepSeconds * jitter * 1e3;
|
|
355
|
-
} else {
|
|
356
|
-
timeoutMillis = Math.max(timeoutMillis, strategy.retryAfterFloorMs);
|
|
357
|
-
}
|
|
358
|
-
await sleep(timeoutMillis);
|
|
359
|
-
const makeRequest = this.makeRequest;
|
|
360
|
-
return makeRequest.call(this, options, retriesRemaining - 1);
|
|
361
|
-
};
|
|
362
|
-
|
|
363
|
-
// ../../lib/llm/disableLangsmith.ts
|
|
364
|
-
process.env.LANGSMITH_TRACING = "false";
|
|
365
|
-
process.env.LANGCHAIN_TRACING_V2 = "false";
|
|
366
|
-
process.env.LANGCHAIN_TRACING = "false";
|
|
367
|
-
delete process.env.LANGSMITH_API_KEY;
|
|
368
|
-
delete process.env.LANGCHAIN_API_KEY;
|
|
369
|
-
delete process.env.LANGSMITH_ENDPOINT;
|
|
370
|
-
delete process.env.LANGCHAIN_ENDPOINT;
|
|
371
|
-
delete process.env.LANGSMITH_PROJECT;
|
|
372
|
-
delete process.env.LANGCHAIN_PROJECT;
|
|
373
|
-
|
|
374
|
-
// ../../lib/llm/models.ts
|
|
375
|
-
import { ChatAnthropic } from "@langchain/anthropic";
|
|
376
|
-
import { ChatOpenAI } from "@langchain/openai";
|
|
255
|
+
// ../../lib/standout/wrapped/sources.ts
|
|
256
|
+
var WRAPPED_SOURCES = [
|
|
257
|
+
"claude_code",
|
|
258
|
+
"cowork",
|
|
259
|
+
"codex",
|
|
260
|
+
"cursor"
|
|
261
|
+
];
|
|
377
262
|
|
|
378
|
-
// ../../lib/standout/wrapped/
|
|
379
|
-
var SOURCES = ["claude_code", "codex", "cursor"];
|
|
263
|
+
// ../../lib/standout/wrapped/stat-pack.ts
|
|
380
264
|
var INFRA_FRAMEWORKS = /* @__PURE__ */ new Set([
|
|
381
265
|
"github-actions",
|
|
382
266
|
"terraform",
|
|
@@ -427,7 +311,7 @@ function buildStatPack(profile) {
|
|
|
427
311
|
const frameworkCounts = /* @__PURE__ */ new Map();
|
|
428
312
|
const languageCounts = /* @__PURE__ */ new Map();
|
|
429
313
|
const modelCounts = /* @__PURE__ */ new Map();
|
|
430
|
-
for (const src of
|
|
314
|
+
for (const src of WRAPPED_SOURCES) {
|
|
431
315
|
const stats = aiUsage[src];
|
|
432
316
|
if (!stats) continue;
|
|
433
317
|
const c = stats.concurrency;
|
|
@@ -525,7 +409,6 @@ function peakLabel(hour) {
|
|
|
525
409
|
}
|
|
526
410
|
|
|
527
411
|
// ../../lib/standout/wrapped/share-stats.ts
|
|
528
|
-
var SOURCES2 = ["claude_code", "codex", "cursor"];
|
|
529
412
|
var WRAPPED_COMMUNITY_BOOST = 1e3;
|
|
530
413
|
var boostCommunity = (n) => n > 0 ? n + WRAPPED_COMMUNITY_BOOST : 0;
|
|
531
414
|
var RETAIL_RATES = [
|
|
@@ -607,7 +490,7 @@ function computeTokens(aiUsage) {
|
|
|
607
490
|
let workTokens = 0;
|
|
608
491
|
let cacheTokens = 0;
|
|
609
492
|
let totalCost = 0;
|
|
610
|
-
for (const src of
|
|
493
|
+
for (const src of WRAPPED_SOURCES) {
|
|
611
494
|
const stats = aiUsage[src];
|
|
612
495
|
if (!stats) continue;
|
|
613
496
|
for (const b of stats.monthly_buckets ?? []) {
|
|
@@ -628,7 +511,7 @@ function computeTokens(aiUsage) {
|
|
|
628
511
|
function computeHours(aiUsage) {
|
|
629
512
|
let totalHours = 0;
|
|
630
513
|
let totalSessions = 0;
|
|
631
|
-
for (const src of
|
|
514
|
+
for (const src of WRAPPED_SOURCES) {
|
|
632
515
|
const stats = aiUsage[src];
|
|
633
516
|
if (!stats) continue;
|
|
634
517
|
totalHours += num2(stats.total_duration_hours);
|
|
@@ -638,7 +521,7 @@ function computeHours(aiUsage) {
|
|
|
638
521
|
}
|
|
639
522
|
function computeHistogram(aiUsage) {
|
|
640
523
|
const hours = new Array(24).fill(0);
|
|
641
|
-
for (const src of
|
|
524
|
+
for (const src of WRAPPED_SOURCES) {
|
|
642
525
|
const stats = aiUsage[src];
|
|
643
526
|
if (!stats) continue;
|
|
644
527
|
const allTime = stats.all_time;
|
|
@@ -1723,7 +1606,7 @@ async function renderWrappedCardLocally(prefetched, theme = "dark") {
|
|
|
1723
1606
|
|
|
1724
1607
|
// src/gather.ts
|
|
1725
1608
|
import { execSync as execSync2 } from "child_process";
|
|
1726
|
-
import { existsSync as existsSync5, readFileSync as
|
|
1609
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
|
|
1727
1610
|
import { join as join5 } from "path";
|
|
1728
1611
|
import { homedir as homedir5 } from "os";
|
|
1729
1612
|
|
|
@@ -1732,6 +1615,7 @@ import {
|
|
|
1732
1615
|
createReadStream,
|
|
1733
1616
|
existsSync as existsSync2,
|
|
1734
1617
|
readdirSync,
|
|
1618
|
+
readFileSync as readFileSync2,
|
|
1735
1619
|
realpathSync,
|
|
1736
1620
|
statSync
|
|
1737
1621
|
} from "fs";
|
|
@@ -2493,7 +2377,7 @@ function registerFile(raw, filePath) {
|
|
|
2493
2377
|
if (raw.filePaths.size > 5e3) return;
|
|
2494
2378
|
raw.filePaths.add(filePath);
|
|
2495
2379
|
}
|
|
2496
|
-
function recordSessionMeta(raw, sessionId, ts, cwd, model, version) {
|
|
2380
|
+
function recordSessionMeta(raw, sessionId, ts, cwd, model, version, projectLabel = null) {
|
|
2497
2381
|
const minute = Math.floor(ts / 6e4);
|
|
2498
2382
|
const existing = raw.sessions.get(sessionId);
|
|
2499
2383
|
if (existing) {
|
|
@@ -2501,6 +2385,8 @@ function recordSessionMeta(raw, sessionId, ts, cwd, model, version) {
|
|
|
2501
2385
|
if (ts > existing.lastTs) existing.lastTs = ts;
|
|
2502
2386
|
existing.eventTimestamps.add(minute);
|
|
2503
2387
|
if (!existing.cwd && cwd) existing.cwd = cwd;
|
|
2388
|
+
if (!existing.projectLabel && projectLabel)
|
|
2389
|
+
existing.projectLabel = projectLabel;
|
|
2504
2390
|
if (model) existing.models.add(model);
|
|
2505
2391
|
if (!existing.version && version) existing.version = version;
|
|
2506
2392
|
} else {
|
|
@@ -2509,6 +2395,7 @@ function recordSessionMeta(raw, sessionId, ts, cwd, model, version) {
|
|
|
2509
2395
|
lastTs: ts,
|
|
2510
2396
|
eventTimestamps: /* @__PURE__ */ new Set([minute]),
|
|
2511
2397
|
cwd,
|
|
2398
|
+
projectLabel,
|
|
2512
2399
|
models: model ? /* @__PURE__ */ new Set([model]) : /* @__PURE__ */ new Set(),
|
|
2513
2400
|
modelTurnCounts: /* @__PURE__ */ new Map(),
|
|
2514
2401
|
inputTokens: 0,
|
|
@@ -2594,6 +2481,93 @@ function listClaudeCodeFiles() {
|
|
|
2594
2481
|
}
|
|
2595
2482
|
return dedupeByRealpath(files);
|
|
2596
2483
|
}
|
|
2484
|
+
function coworkSessionsBaseDir() {
|
|
2485
|
+
const home = homedir2();
|
|
2486
|
+
if (process.platform === "darwin") {
|
|
2487
|
+
return join2(
|
|
2488
|
+
home,
|
|
2489
|
+
"Library",
|
|
2490
|
+
"Application Support",
|
|
2491
|
+
"Claude",
|
|
2492
|
+
"local-agent-mode-sessions"
|
|
2493
|
+
);
|
|
2494
|
+
}
|
|
2495
|
+
if (process.platform === "win32") {
|
|
2496
|
+
const appData = process.env.APPDATA;
|
|
2497
|
+
return appData ? join2(appData, "Claude", "local-agent-mode-sessions") : null;
|
|
2498
|
+
}
|
|
2499
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
2500
|
+
return join2(
|
|
2501
|
+
xdg || join2(home, ".config"),
|
|
2502
|
+
"Claude",
|
|
2503
|
+
"local-agent-mode-sessions"
|
|
2504
|
+
);
|
|
2505
|
+
}
|
|
2506
|
+
function listCoworkFiles() {
|
|
2507
|
+
const base = coworkSessionsBaseDir();
|
|
2508
|
+
if (!base || !existsSync2(base)) return [];
|
|
2509
|
+
const found = [];
|
|
2510
|
+
const safeReaddir = (dir) => {
|
|
2511
|
+
try {
|
|
2512
|
+
return readdirSync(dir);
|
|
2513
|
+
} catch {
|
|
2514
|
+
return [];
|
|
2515
|
+
}
|
|
2516
|
+
};
|
|
2517
|
+
const isDir = (p) => {
|
|
2518
|
+
try {
|
|
2519
|
+
return statSync(p).isDirectory();
|
|
2520
|
+
} catch {
|
|
2521
|
+
return false;
|
|
2522
|
+
}
|
|
2523
|
+
};
|
|
2524
|
+
for (const acct of safeReaddir(base)) {
|
|
2525
|
+
const acctDir = join2(base, acct);
|
|
2526
|
+
if (!isDir(acctDir)) continue;
|
|
2527
|
+
for (const org of safeReaddir(acctDir)) {
|
|
2528
|
+
const orgDir = join2(acctDir, org);
|
|
2529
|
+
if (!isDir(orgDir)) continue;
|
|
2530
|
+
for (const entry of safeReaddir(orgDir)) {
|
|
2531
|
+
if (!entry.startsWith("local_")) continue;
|
|
2532
|
+
const sessionDir = join2(orgDir, entry);
|
|
2533
|
+
if (!isDir(sessionDir)) continue;
|
|
2534
|
+
let title = "";
|
|
2535
|
+
try {
|
|
2536
|
+
const meta = JSON.parse(
|
|
2537
|
+
readFileSync2(join2(orgDir, `${entry}.json`), "utf-8")
|
|
2538
|
+
);
|
|
2539
|
+
if (typeof meta.title === "string") title = meta.title.trim();
|
|
2540
|
+
} catch {
|
|
2541
|
+
}
|
|
2542
|
+
const projectsDir = join2(sessionDir, ".claude", "projects");
|
|
2543
|
+
if (!existsSync2(projectsDir)) continue;
|
|
2544
|
+
for (const proj of safeReaddir(projectsDir)) {
|
|
2545
|
+
const projDir = join2(projectsDir, proj);
|
|
2546
|
+
if (!isDir(projDir)) continue;
|
|
2547
|
+
for (const file of safeReaddir(projDir)) {
|
|
2548
|
+
if (!file.endsWith(".jsonl")) continue;
|
|
2549
|
+
const filePath = join2(projDir, file);
|
|
2550
|
+
try {
|
|
2551
|
+
const stat = statSync(filePath);
|
|
2552
|
+
if (!stat.isFile()) continue;
|
|
2553
|
+
found.push({
|
|
2554
|
+
path: filePath,
|
|
2555
|
+
mtime: stat.mtimeMs,
|
|
2556
|
+
title: title || "Cowork session"
|
|
2557
|
+
});
|
|
2558
|
+
} catch {
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
const titleByPath = new Map(found.map((f) => [f.path, f.title]));
|
|
2566
|
+
return dedupeByRealpath(found).map((path2) => ({
|
|
2567
|
+
path: path2,
|
|
2568
|
+
title: titleByPath.get(path2) ?? "Cowork session"
|
|
2569
|
+
}));
|
|
2570
|
+
}
|
|
2597
2571
|
function listCodexFiles() {
|
|
2598
2572
|
const base = join2(homedir2(), ".codex", "sessions");
|
|
2599
2573
|
if (!existsSync2(base)) return [];
|
|
@@ -2640,7 +2614,9 @@ function makeTargets(targetInputs) {
|
|
|
2640
2614
|
seenUserPromptThisSession: false,
|
|
2641
2615
|
collectConversation: target.collectConversation ?? false,
|
|
2642
2616
|
sessionPromptCounts: /* @__PURE__ */ new Map(),
|
|
2643
|
-
pendingPrompt: /* @__PURE__ */ new Map()
|
|
2617
|
+
pendingPrompt: /* @__PURE__ */ new Map(),
|
|
2618
|
+
projectLabel: target.projectLabel ?? null,
|
|
2619
|
+
suppressFiles: target.suppressFiles ?? false
|
|
2644
2620
|
}));
|
|
2645
2621
|
}
|
|
2646
2622
|
async function parseClaudeCodeFileTargets(filePath, targetInputs) {
|
|
@@ -2684,12 +2660,28 @@ async function parseClaudeCodeFileTargets(filePath, targetInputs) {
|
|
|
2684
2660
|
}
|
|
2685
2661
|
}
|
|
2686
2662
|
if (shouldCount) {
|
|
2687
|
-
recordSessionMeta(
|
|
2663
|
+
recordSessionMeta(
|
|
2664
|
+
target.raw,
|
|
2665
|
+
sessionId,
|
|
2666
|
+
ts,
|
|
2667
|
+
cwd,
|
|
2668
|
+
null,
|
|
2669
|
+
version,
|
|
2670
|
+
target.projectLabel
|
|
2671
|
+
);
|
|
2688
2672
|
}
|
|
2689
2673
|
} else if (type === "assistant" && message) {
|
|
2690
2674
|
const model = typeof message.model === "string" ? message.model : null;
|
|
2691
2675
|
if (shouldCount) {
|
|
2692
|
-
recordSessionMeta(
|
|
2676
|
+
recordSessionMeta(
|
|
2677
|
+
target.raw,
|
|
2678
|
+
sessionId,
|
|
2679
|
+
ts,
|
|
2680
|
+
cwd,
|
|
2681
|
+
model,
|
|
2682
|
+
version,
|
|
2683
|
+
target.projectLabel
|
|
2684
|
+
);
|
|
2693
2685
|
}
|
|
2694
2686
|
const usage = message.usage;
|
|
2695
2687
|
const messageId = typeof message.id === "string" ? message.id : null;
|
|
@@ -2724,7 +2716,7 @@ async function parseClaudeCodeFileTargets(filePath, targetInputs) {
|
|
|
2724
2716
|
);
|
|
2725
2717
|
}
|
|
2726
2718
|
const input = item.input;
|
|
2727
|
-
if (input) {
|
|
2719
|
+
if (input && !target.suppressFiles) {
|
|
2728
2720
|
registerFile(
|
|
2729
2721
|
target.raw,
|
|
2730
2722
|
input.file_path
|
|
@@ -3048,8 +3040,10 @@ function finalize2(raw) {
|
|
|
3048
3040
|
if (s.lastTs > lastTs) lastTs = s.lastTs;
|
|
3049
3041
|
if (s.cwd) {
|
|
3050
3042
|
if (PARALLEL_WORKSPACE_RE.test(s.cwd)) parallelCwds.add(s.cwd);
|
|
3051
|
-
|
|
3052
|
-
|
|
3043
|
+
}
|
|
3044
|
+
const projectKey = s.projectLabel ?? (s.cwd ? compactCwd(s.cwd) : null);
|
|
3045
|
+
if (projectKey) {
|
|
3046
|
+
projectCounts.set(projectKey, (projectCounts.get(projectKey) || 0) + 1);
|
|
3053
3047
|
}
|
|
3054
3048
|
s.models.forEach((m) => {
|
|
3055
3049
|
if (m && !m.startsWith("<") && !m.includes("synthetic")) modelsSet.add(m);
|
|
@@ -3283,11 +3277,15 @@ function withAllTime(recent, allTime, previous = null) {
|
|
|
3283
3277
|
async function gatherAiUsage() {
|
|
3284
3278
|
const claudeFiles = listClaudeCodeFiles();
|
|
3285
3279
|
const codexFiles = listCodexFiles();
|
|
3280
|
+
const coworkFiles = listCoworkFiles();
|
|
3286
3281
|
const windowStartMs = Date.now() - USAGE_WINDOW_MS;
|
|
3287
3282
|
const previousWindowStartMs = windowStartMs - USAGE_WINDOW_MS;
|
|
3288
3283
|
const claudeRecentRaw = emptyRaw();
|
|
3289
3284
|
const claudePreviousRaw = emptyRaw();
|
|
3290
3285
|
const claudeAllRaw = emptyRaw();
|
|
3286
|
+
const coworkRecentRaw = emptyRaw();
|
|
3287
|
+
const coworkPreviousRaw = emptyRaw();
|
|
3288
|
+
const coworkAllRaw = emptyRaw();
|
|
3291
3289
|
const codexRecentRaw = emptyRaw();
|
|
3292
3290
|
const codexPreviousRaw = emptyRaw();
|
|
3293
3291
|
const codexAllRaw = emptyRaw();
|
|
@@ -3315,6 +3313,32 @@ async function gatherAiUsage() {
|
|
|
3315
3313
|
}
|
|
3316
3314
|
}
|
|
3317
3315
|
})(),
|
|
3316
|
+
(async () => {
|
|
3317
|
+
for (const { path: path2, title } of coworkFiles) {
|
|
3318
|
+
try {
|
|
3319
|
+
await parseClaudeCodeFileTargets(path2, [
|
|
3320
|
+
{
|
|
3321
|
+
raw: coworkRecentRaw,
|
|
3322
|
+
opts: { windowStartMs },
|
|
3323
|
+
collectConversation: true,
|
|
3324
|
+
projectLabel: title,
|
|
3325
|
+
suppressFiles: true
|
|
3326
|
+
},
|
|
3327
|
+
{
|
|
3328
|
+
raw: coworkPreviousRaw,
|
|
3329
|
+
opts: {
|
|
3330
|
+
windowStartMs: previousWindowStartMs,
|
|
3331
|
+
windowEndMs: windowStartMs
|
|
3332
|
+
},
|
|
3333
|
+
projectLabel: title,
|
|
3334
|
+
suppressFiles: true
|
|
3335
|
+
},
|
|
3336
|
+
{ raw: coworkAllRaw, projectLabel: title, suppressFiles: true }
|
|
3337
|
+
]);
|
|
3338
|
+
} catch {
|
|
3339
|
+
}
|
|
3340
|
+
}
|
|
3341
|
+
})(),
|
|
3318
3342
|
(async () => {
|
|
3319
3343
|
for (const file of codexFiles) {
|
|
3320
3344
|
try {
|
|
@@ -3344,6 +3368,11 @@ async function gatherAiUsage() {
|
|
|
3344
3368
|
finalize2(claudeAllRaw),
|
|
3345
3369
|
finalize2(claudePreviousRaw)
|
|
3346
3370
|
),
|
|
3371
|
+
cowork: withAllTime(
|
|
3372
|
+
finalize2(coworkRecentRaw),
|
|
3373
|
+
finalize2(coworkAllRaw),
|
|
3374
|
+
finalize2(coworkPreviousRaw)
|
|
3375
|
+
),
|
|
3347
3376
|
codex: withAllTime(
|
|
3348
3377
|
finalize2(codexRecentRaw),
|
|
3349
3378
|
finalize2(codexAllRaw),
|
|
@@ -3355,7 +3384,7 @@ async function gatherAiUsage() {
|
|
|
3355
3384
|
|
|
3356
3385
|
// src/dev-env.ts
|
|
3357
3386
|
import { execSync } from "child_process";
|
|
3358
|
-
import { existsSync as existsSync3, readFileSync as
|
|
3387
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
3359
3388
|
import { homedir as homedir3 } from "os";
|
|
3360
3389
|
import { join as join3 } from "path";
|
|
3361
3390
|
var INTERESTING_TOOLS = [
|
|
@@ -3403,7 +3432,7 @@ function execSafe(cmd, timeout = 5e3) {
|
|
|
3403
3432
|
}
|
|
3404
3433
|
function readFileSafe(path2, maxBytes = 3e3) {
|
|
3405
3434
|
try {
|
|
3406
|
-
const content =
|
|
3435
|
+
const content = readFileSync3(path2, "utf-8");
|
|
3407
3436
|
return content.length > maxBytes ? content.slice(0, maxBytes) : content;
|
|
3408
3437
|
} catch {
|
|
3409
3438
|
return null;
|
|
@@ -3430,7 +3459,7 @@ function collectAgentsMd() {
|
|
|
3430
3459
|
function summarizeClaudeSettingsFile(path2, displayPath) {
|
|
3431
3460
|
if (!existsSync3(path2)) return null;
|
|
3432
3461
|
try {
|
|
3433
|
-
const raw = JSON.parse(
|
|
3462
|
+
const raw = JSON.parse(readFileSync3(path2, "utf-8"));
|
|
3434
3463
|
const hooksObj = raw.hooks;
|
|
3435
3464
|
const hooks = hooksObj ? Object.keys(hooksObj) : [];
|
|
3436
3465
|
const mcpServersObj = raw.mcpServers;
|
|
@@ -3605,7 +3634,7 @@ import {
|
|
|
3605
3634
|
mkdirSync,
|
|
3606
3635
|
copyFileSync,
|
|
3607
3636
|
rmSync,
|
|
3608
|
-
readFileSync as
|
|
3637
|
+
readFileSync as readFileSync4
|
|
3609
3638
|
} from "fs";
|
|
3610
3639
|
import { homedir as homedir4, platform as platform2, tmpdir } from "os";
|
|
3611
3640
|
import { join as join4 } from "path";
|
|
@@ -3689,7 +3718,7 @@ async function waitForDebugPort(userDataDir, timeoutMs) {
|
|
|
3689
3718
|
while (Date.now() < deadline) {
|
|
3690
3719
|
if (existsSync4(portFile)) {
|
|
3691
3720
|
try {
|
|
3692
|
-
const [port] =
|
|
3721
|
+
const [port] = readFileSync4(portFile, "utf-8").trim().split("\n");
|
|
3693
3722
|
if (port && /^\d+$/.test(port)) return parseInt(port, 10);
|
|
3694
3723
|
} catch {
|
|
3695
3724
|
}
|
|
@@ -3957,6 +3986,7 @@ function emptyGatheredProfile(readiness = {
|
|
|
3957
3986
|
},
|
|
3958
3987
|
ai_usage: {
|
|
3959
3988
|
claude_code: null,
|
|
3989
|
+
cowork: null,
|
|
3960
3990
|
codex: null,
|
|
3961
3991
|
cursor: null
|
|
3962
3992
|
},
|
|
@@ -3975,7 +4005,9 @@ function emptyGatheredProfile(readiness = {
|
|
|
3975
4005
|
};
|
|
3976
4006
|
}
|
|
3977
4007
|
function hasAnyUsage(aiUsage) {
|
|
3978
|
-
return Boolean(
|
|
4008
|
+
return Boolean(
|
|
4009
|
+
aiUsage.claude_code || aiUsage.cowork || aiUsage.codex || aiUsage.cursor
|
|
4010
|
+
);
|
|
3979
4011
|
}
|
|
3980
4012
|
function gatherLog(options, message) {
|
|
3981
4013
|
if (options.verbose === false) return;
|
|
@@ -3996,6 +4028,7 @@ async function gatherUsageStats() {
|
|
|
3996
4028
|
return {
|
|
3997
4029
|
ai_usage: {
|
|
3998
4030
|
claude_code: null,
|
|
4031
|
+
cowork: null,
|
|
3999
4032
|
codex: null,
|
|
4000
4033
|
cursor: null
|
|
4001
4034
|
},
|
|
@@ -4089,7 +4122,7 @@ function readRepoReadme(repoPath) {
|
|
|
4089
4122
|
const p = join5(repoPath, name);
|
|
4090
4123
|
if (!existsSync5(p)) continue;
|
|
4091
4124
|
try {
|
|
4092
|
-
const text =
|
|
4125
|
+
const text = readFileSync5(p, "utf-8").trim();
|
|
4093
4126
|
if (text.length > 0) return redactSecrets(text).slice(0, 1200);
|
|
4094
4127
|
} catch {
|
|
4095
4128
|
}
|
|
@@ -4437,6 +4470,7 @@ async function gather(options = {}) {
|
|
|
4437
4470
|
const githubEnrichPromise = safeUsername && !localOnly ? enrichApi("github", safeUsername).catch(() => null) : Promise.resolve(null);
|
|
4438
4471
|
const aiUsagePromise = options.aiUsage ? Promise.resolve(options.aiUsage) : gatherAiUsage().catch(() => ({
|
|
4439
4472
|
claude_code: null,
|
|
4473
|
+
cowork: null,
|
|
4440
4474
|
codex: null,
|
|
4441
4475
|
cursor: null
|
|
4442
4476
|
}));
|
|
@@ -4659,7 +4693,7 @@ async function gather(options = {}) {
|
|
|
4659
4693
|
);
|
|
4660
4694
|
commitSubjects = subjectsRaw ? subjectsRaw.split("\n").map((s) => s.trim()).filter(Boolean).slice(0, 200).map((s) => redactSecrets(s).slice(0, 160)) : [];
|
|
4661
4695
|
}
|
|
4662
|
-
const claudeMd = existsSync5("CLAUDE.md") ?
|
|
4696
|
+
const claudeMd = existsSync5("CLAUDE.md") ? readFileSync5("CLAUDE.md", "utf-8").slice(0, 3e3) : null;
|
|
4663
4697
|
const claudeDirsRaw = execSafe2(
|
|
4664
4698
|
`find ${homedir5()} -maxdepth 3 -path "*/.claude" -type d | head -5`
|
|
4665
4699
|
);
|
|
@@ -4673,7 +4707,7 @@ async function gather(options = {}) {
|
|
|
4673
4707
|
}
|
|
4674
4708
|
let cursorrules = null;
|
|
4675
4709
|
if (existsSync5(".cursorrules")) {
|
|
4676
|
-
cursorrules =
|
|
4710
|
+
cursorrules = readFileSync5(".cursorrules", "utf-8").slice(0, 2e3);
|
|
4677
4711
|
}
|
|
4678
4712
|
const [aiUsage, devEnvironment, githubEnrichment] = await Promise.all([
|
|
4679
4713
|
aiUsagePromise,
|
|
@@ -4838,7 +4872,7 @@ Your first user message contains a <prefetched_profile> block with a full JSON d
|
|
|
4838
4872
|
- \`twitter\`: handle + optional enrichment
|
|
4839
4873
|
- \`local\`: local git repos, commit patterns, collaborators
|
|
4840
4874
|
- \`ai_coding\`: AI-assisted commit counts, CLAUDE.md contents, .claude dirs, other AI tool presence, .cursorrules
|
|
4841
|
-
- \`ai_usage\`: Claude Code + Codex session parsing \u2014 total sessions, active days, tool-call frequency, projects (cwd), models used, peak hour, weekend ratio, languages inferred from file extensions, frameworks inferred from file paths, sanitized first-line prompt samples
|
|
4875
|
+
- \`ai_usage\`: Claude Code + Cowork + Codex session parsing \u2014 total sessions, active days, tool-call frequency, projects (cwd), models used, peak hour, weekend ratio, languages inferred from file extensions, frameworks inferred from file paths, sanitized first-line prompt samples. \`cowork\` is Claude Cowork (Anthropic's knowledge-work agent) \u2014 treat it as knowledge work, not coding (its projects are session titles, and it has no languages/frameworks).
|
|
4842
4876
|
- \`dev_environment\`: AGENTS.md contents, Claude hooks/MCPs/commands, cursor rules, VSCode extensions, global npm/brew/pip packages, installed dev CLIs with versions
|
|
4843
4877
|
|
|
4844
4878
|
TREAT PREFETCHED DATA AS AUTHORITATIVE. Do not re-run git log, curl GitHub, scan local files, parse ~/.claude, etc. That work is done. Read the block and proceed.
|
|
@@ -5033,6 +5067,7 @@ The JSON should follow this structure:
|
|
|
5033
5067
|
},
|
|
5034
5068
|
"ai_usage": {
|
|
5035
5069
|
"claude_code": null,
|
|
5070
|
+
"cowork": null,
|
|
5036
5071
|
"codex": null,
|
|
5037
5072
|
"cursor": null
|
|
5038
5073
|
},
|
|
@@ -5176,7 +5211,7 @@ ${question}
|
|
|
5176
5211
|
});
|
|
5177
5212
|
});
|
|
5178
5213
|
}
|
|
5179
|
-
var
|
|
5214
|
+
var TOOLS = [
|
|
5180
5215
|
{
|
|
5181
5216
|
name: "bash",
|
|
5182
5217
|
description: "Execute a bash command in a read-only sandbox. Destructive commands (rm, mv, git push, sudo, etc.) are blocked. Use for reading files, git log, curl GET, find, ls, etc.",
|
|
@@ -5265,12 +5300,6 @@ async function executeTool(name, input, options = {}) {
|
|
|
5265
5300
|
// src/wrapped/aggregate.ts
|
|
5266
5301
|
var WRAPPED_COMMUNITY_BOOST2 = 1e3;
|
|
5267
5302
|
var boostCommunity2 = (n) => n > 0 ? n + WRAPPED_COMMUNITY_BOOST2 : 0;
|
|
5268
|
-
var SOURCES3 = ["claude_code", "codex", "cursor"];
|
|
5269
|
-
var TOOL_LABELS = {
|
|
5270
|
-
claude_code: "Claude Code",
|
|
5271
|
-
codex: "Codex",
|
|
5272
|
-
cursor: "Cursor"
|
|
5273
|
-
};
|
|
5274
5303
|
var RETAIL_RATES2 = [
|
|
5275
5304
|
{
|
|
5276
5305
|
match: /claude.*opus/i,
|
|
@@ -5435,7 +5464,7 @@ function aggregateView(args) {
|
|
|
5435
5464
|
const allTimeMonthly = /* @__PURE__ */ new Map();
|
|
5436
5465
|
const allTimeHourBuckets = new Array(24).fill(0);
|
|
5437
5466
|
let allTimeStreak = 0;
|
|
5438
|
-
for (const src of
|
|
5467
|
+
for (const src of SOURCES) {
|
|
5439
5468
|
const stats = aiUsage[src];
|
|
5440
5469
|
if (!stats) continue;
|
|
5441
5470
|
usageStatsSeen = true;
|
|
@@ -5686,7 +5715,7 @@ function computeTokens2(aiUsage) {
|
|
|
5686
5715
|
const cursorStats = aiUsage["cursor"];
|
|
5687
5716
|
const cursorEstimated = !!(cursorStats && (cursorStats.total_sessions ?? 0) >= CURSOR_MIN_SESSIONS);
|
|
5688
5717
|
let cursorTokens = 0;
|
|
5689
|
-
for (const src of
|
|
5718
|
+
for (const src of SOURCES) {
|
|
5690
5719
|
const stats = aiUsage[src];
|
|
5691
5720
|
if (!stats) continue;
|
|
5692
5721
|
const buckets = stats.monthly_buckets ?? [];
|
|
@@ -5696,7 +5725,7 @@ function computeTokens2(aiUsage) {
|
|
|
5696
5725
|
workTokens += work;
|
|
5697
5726
|
cacheTokens += cache;
|
|
5698
5727
|
if (src === "cursor") cursorTokens += work + cache;
|
|
5699
|
-
byTool[
|
|
5728
|
+
byTool[SOURCE_LABELS[src] ?? src] = (byTool[SOURCE_LABELS[src] ?? src] ?? 0) + work + cache;
|
|
5700
5729
|
const rate = rateForModel2(b.primary_model);
|
|
5701
5730
|
const cacheRead = b.cache_read_tokens ?? (b.cache_write_tokens === void 0 ? b.cache_tokens ?? 0 : 0);
|
|
5702
5731
|
const cacheWrite = b.cache_write_tokens ?? 0;
|
|
@@ -5741,7 +5770,7 @@ function computeTokens2(aiUsage) {
|
|
|
5741
5770
|
}
|
|
5742
5771
|
function computeToolRelationship(aiUsage) {
|
|
5743
5772
|
const monthMap = /* @__PURE__ */ new Map();
|
|
5744
|
-
for (const src of
|
|
5773
|
+
for (const src of SOURCES) {
|
|
5745
5774
|
const stats = aiUsage[src];
|
|
5746
5775
|
if (!stats) continue;
|
|
5747
5776
|
for (const b of stats.monthly_buckets ?? []) {
|
|
@@ -5761,7 +5790,7 @@ function computeToolRelationship(aiUsage) {
|
|
|
5761
5790
|
if (best) {
|
|
5762
5791
|
return {
|
|
5763
5792
|
kind: "loyalist",
|
|
5764
|
-
tool:
|
|
5793
|
+
tool: SOURCE_LABELS[best[0]] ?? best[0],
|
|
5765
5794
|
months_count: 1,
|
|
5766
5795
|
sessions_count: best[1]
|
|
5767
5796
|
};
|
|
@@ -5796,12 +5825,12 @@ function computeToolRelationship(aiUsage) {
|
|
|
5796
5825
|
if (switchIdx > 0) {
|
|
5797
5826
|
return {
|
|
5798
5827
|
kind: "switch",
|
|
5799
|
-
from_tool:
|
|
5800
|
-
to_tool:
|
|
5828
|
+
from_tool: SOURCE_LABELS[firstDominant] ?? firstDominant,
|
|
5829
|
+
to_tool: SOURCE_LABELS[lastDominant] ?? lastDominant,
|
|
5801
5830
|
switch_month: timeline[switchIdx].month,
|
|
5802
5831
|
timeline: timeline.map((t) => ({
|
|
5803
5832
|
month: t.month,
|
|
5804
|
-
dominant:
|
|
5833
|
+
dominant: SOURCE_LABELS[t.dominant] ?? t.dominant,
|
|
5805
5834
|
share: t.share
|
|
5806
5835
|
}))
|
|
5807
5836
|
};
|
|
@@ -5815,7 +5844,7 @@ function computeToolRelationship(aiUsage) {
|
|
|
5815
5844
|
}
|
|
5816
5845
|
return {
|
|
5817
5846
|
kind: "loyalist",
|
|
5818
|
-
tool:
|
|
5847
|
+
tool: SOURCE_LABELS[firstDominant] ?? firstDominant,
|
|
5819
5848
|
months_count: months.length,
|
|
5820
5849
|
sessions_count: totalSessions
|
|
5821
5850
|
};
|
|
@@ -5828,14 +5857,14 @@ function computeToolRelationship(aiUsage) {
|
|
|
5828
5857
|
}
|
|
5829
5858
|
const grandTotal = [...totalsByTool.values()].reduce((a, b) => a + b, 0);
|
|
5830
5859
|
const tools = [...totalsByTool.entries()].sort(([, a], [, b]) => b - a).map(([tool, n]) => ({
|
|
5831
|
-
tool:
|
|
5860
|
+
tool: SOURCE_LABELS[tool] ?? tool,
|
|
5832
5861
|
share: grandTotal > 0 ? n / grandTotal : 0
|
|
5833
5862
|
}));
|
|
5834
5863
|
return { kind: "polyglot", tools };
|
|
5835
5864
|
}
|
|
5836
5865
|
function computeModels(aiUsage) {
|
|
5837
5866
|
const allModelCounts = /* @__PURE__ */ new Map();
|
|
5838
|
-
for (const src of
|
|
5867
|
+
for (const src of SOURCES) {
|
|
5839
5868
|
const stats = aiUsage[src];
|
|
5840
5869
|
if (!stats?.model_session_counts) continue;
|
|
5841
5870
|
for (const [model, n] of Object.entries(stats.model_session_counts)) {
|
|
@@ -5905,7 +5934,7 @@ function computeCodeFootprint(aiCoding, totalCommits, line) {
|
|
|
5905
5934
|
function computeConcurrency2(aiUsage, line) {
|
|
5906
5935
|
let best = null;
|
|
5907
5936
|
let bestSessions = -1;
|
|
5908
|
-
for (const src of
|
|
5937
|
+
for (const src of SOURCES) {
|
|
5909
5938
|
const stats = aiUsage[src];
|
|
5910
5939
|
if (!stats?.concurrency) continue;
|
|
5911
5940
|
const sessions = stats.total_sessions ?? 0;
|
|
@@ -5927,7 +5956,7 @@ function computeConversation(aiUsage, line, themes) {
|
|
|
5927
5956
|
let totalPrompts = 0;
|
|
5928
5957
|
let questionWeighted = 0;
|
|
5929
5958
|
let charsWeighted = 0;
|
|
5930
|
-
for (const src of
|
|
5959
|
+
for (const src of SOURCES) {
|
|
5931
5960
|
const stats = aiUsage[src];
|
|
5932
5961
|
const c = stats?.conversation;
|
|
5933
5962
|
if (!c) continue;
|
|
@@ -6836,14 +6865,14 @@ function describeError(err) {
|
|
|
6836
6865
|
}
|
|
6837
6866
|
return parts.join(" <- ") || String(err);
|
|
6838
6867
|
}
|
|
6839
|
-
var
|
|
6868
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
6840
6869
|
function isReady(computed) {
|
|
6841
6870
|
if (!computed) return false;
|
|
6842
6871
|
return computed.status === "ready" || computed.archetype != null;
|
|
6843
6872
|
}
|
|
6844
6873
|
async function pollComputed(id) {
|
|
6845
6874
|
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
6846
|
-
await
|
|
6875
|
+
await sleep(POLL_INTERVAL_MS);
|
|
6847
6876
|
while (Date.now() < deadline) {
|
|
6848
6877
|
try {
|
|
6849
6878
|
const res = await fetch(`${STANDOUT_API_URL}/api/public/wrapped/${id}`, {
|
|
@@ -6856,7 +6885,7 @@ async function pollComputed(id) {
|
|
|
6856
6885
|
}
|
|
6857
6886
|
} catch {
|
|
6858
6887
|
}
|
|
6859
|
-
await
|
|
6888
|
+
await sleep(POLL_INTERVAL_MS);
|
|
6860
6889
|
}
|
|
6861
6890
|
return null;
|
|
6862
6891
|
}
|
|
@@ -6890,7 +6919,7 @@ async function createWrapped(args) {
|
|
|
6890
6919
|
break;
|
|
6891
6920
|
} catch (err) {
|
|
6892
6921
|
if (isPreConnectError(err) && attempt < MAX_ATTEMPTS) {
|
|
6893
|
-
await
|
|
6922
|
+
await sleep(RETRY_BASE_DELAY_MS * attempt);
|
|
6894
6923
|
continue;
|
|
6895
6924
|
}
|
|
6896
6925
|
const detail = describeError(err);
|
|
@@ -7261,7 +7290,7 @@ async function runAgent(jobId) {
|
|
|
7261
7290
|
console.log(` Applying to: ${STANDOUT_API_URL}/jobs/${jobId}
|
|
7262
7291
|
`);
|
|
7263
7292
|
}
|
|
7264
|
-
const client = new
|
|
7293
|
+
const client = new Anthropic({
|
|
7265
7294
|
apiKey: "proxied-by-standout",
|
|
7266
7295
|
baseURL: `${STANDOUT_API_URL}/api/public/agent-chat`,
|
|
7267
7296
|
defaultHeaders: {
|
|
@@ -7365,7 +7394,7 @@ async function runAgent(jobId) {
|
|
|
7365
7394
|
messages,
|
|
7366
7395
|
// Cache the entire tools array via cache_control on the last tool definition.
|
|
7367
7396
|
tools: [
|
|
7368
|
-
...
|
|
7397
|
+
...TOOLS,
|
|
7369
7398
|
{
|
|
7370
7399
|
type: "web_search_20250305",
|
|
7371
7400
|
name: "web_search",
|