@rallycry/conveyor-agent 11.0.48 → 11.0.49
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/{boot-KDC4OLVL.js → boot-GD5XMLPS.js} +2 -2
- package/dist/{chunk-F7XHSNU7.js → chunk-ATYCG6MT.js} +1 -1
- package/dist/{chunk-UL6DAPTX.js → chunk-K35YJK2U.js} +1 -1
- package/dist/{chunk-4RE6G2DZ.js → chunk-O3MXZHIS.js} +10 -0
- package/dist/{chunk-JUEHUVSD.js → chunk-RNE3JAF5.js} +223 -200
- package/dist/{chunk-EKTPDG3G.js → chunk-SXZS2R52.js} +27 -2
- package/dist/cli.js +21 -47
- package/dist/index.js +3 -3
- package/dist/{serve-boot-H72OIMFS.js → serve-boot-4QBD4LW4.js} +2 -2
- package/dist/{server-GJZKUVBE.js → server-FPDS4CT5.js} +2 -2
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
startWorkbenchServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ATYCG6MT.js";
|
|
4
4
|
import {
|
|
5
5
|
TOMBSTONE_MESSAGE,
|
|
6
6
|
isLegacyEntrypointLaunch
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
refreshSkillsAfterCheckout,
|
|
13
13
|
runPreReadyBinds
|
|
14
14
|
} from "./chunk-V5WR2F2P.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-SXZS2R52.js";
|
|
16
16
|
import {
|
|
17
17
|
GitPrepJob,
|
|
18
18
|
defaultGit,
|
|
@@ -3649,6 +3649,15 @@ function formatEvaluateQuestionsResult(res) {
|
|
|
3649
3649
|
);
|
|
3650
3650
|
return JSON.stringify({ model: res.model, results });
|
|
3651
3651
|
}
|
|
3652
|
+
function subProjectScopePaths(subProject) {
|
|
3653
|
+
return [
|
|
3654
|
+
...new Set(
|
|
3655
|
+
[subProject.rootPath, ...subProject.additionalAllowedPaths ?? []].filter(
|
|
3656
|
+
(path) => !!path
|
|
3657
|
+
)
|
|
3658
|
+
)
|
|
3659
|
+
];
|
|
3660
|
+
}
|
|
3652
3661
|
var MEETING_CHECKLIST_TITLE_MAX = 300;
|
|
3653
3662
|
var MEETING_TRANSCRIPT_MAX_CHARS = 2e6;
|
|
3654
3663
|
var MEETING_TITLE_MAX = 200;
|
|
@@ -5356,6 +5365,7 @@ export {
|
|
|
5356
5365
|
TAG_REASON_MAX,
|
|
5357
5366
|
CRITICAL_AUTOMATED_SOURCES,
|
|
5358
5367
|
formatEvaluateQuestionsResult,
|
|
5368
|
+
subProjectScopePaths,
|
|
5359
5369
|
AGENT_STATUS_REASON_USER_QUESTION,
|
|
5360
5370
|
TASK_CHAT_HISTORY_LIMIT,
|
|
5361
5371
|
PM_CHAT_HISTORY_LIMIT,
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
buildSpawnArgs,
|
|
13
13
|
cleanTerminalOutput,
|
|
14
14
|
ensureSessionTarget,
|
|
15
|
+
flattenTerminalText,
|
|
15
16
|
inheritedEnv,
|
|
16
17
|
killPtyWithEscalation,
|
|
17
18
|
needsRawReadyGate,
|
|
@@ -30,7 +31,7 @@ import {
|
|
|
30
31
|
spawnOptionsFingerprint,
|
|
31
32
|
transcriptSize,
|
|
32
33
|
turnOptionsFrom
|
|
33
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-SXZS2R52.js";
|
|
34
35
|
import {
|
|
35
36
|
AGENT_STATUS_REASON_USER_QUESTION,
|
|
36
37
|
AgentConnection,
|
|
@@ -95,9 +96,10 @@ import {
|
|
|
95
96
|
runQueryGrafanaLogs,
|
|
96
97
|
stageAndCommit,
|
|
97
98
|
statWorkspacePath,
|
|
99
|
+
subProjectScopePaths,
|
|
98
100
|
updateRemoteToken,
|
|
99
101
|
verifyGitCredential
|
|
100
|
-
} from "./chunk-
|
|
102
|
+
} from "./chunk-O3MXZHIS.js";
|
|
101
103
|
import {
|
|
102
104
|
reportBootMilestone
|
|
103
105
|
} from "./chunk-VIUZS7V4.js";
|
|
@@ -2600,12 +2602,11 @@ function conveyorCredentialsMarkerPath() {
|
|
|
2600
2602
|
function tokenFingerprint(accessToken) {
|
|
2601
2603
|
return createHash("sha256").update(accessToken).digest("hex");
|
|
2602
2604
|
}
|
|
2603
|
-
function buildCredentialsMarker(accessToken, now, previousHash,
|
|
2605
|
+
function buildCredentialsMarker(accessToken, now, previousHash, codingAgentKeyId) {
|
|
2604
2606
|
const accessTokenSha256 = tokenFingerprint(accessToken);
|
|
2605
2607
|
return JSON.stringify({
|
|
2606
2608
|
accessTokenSha256,
|
|
2607
2609
|
...previousHash && previousHash !== accessTokenSha256 ? { previousAccessTokenSha256: previousHash } : {},
|
|
2608
|
-
...refreshToken ? { refreshTokenSha256: tokenFingerprint(refreshToken) } : {},
|
|
2609
2610
|
...codingAgentKeyId ? { codingAgentKeyId } : {},
|
|
2610
2611
|
writtenAt: now
|
|
2611
2612
|
});
|
|
@@ -2686,9 +2687,6 @@ function parseClaudeOauthEnv(blob) {
|
|
|
2686
2687
|
const scopes = Array.isArray(record.scopes) ? record.scopes.filter((scope) => typeof scope === "string" && scope !== "") : [];
|
|
2687
2688
|
return {
|
|
2688
2689
|
access: record.access,
|
|
2689
|
-
refresh: typeof record.refresh === "string" && record.refresh ? record.refresh : void 0,
|
|
2690
|
-
expires: typeof record.expires === "number" ? record.expires : void 0,
|
|
2691
|
-
refreshExpires: typeof record.refreshExpires === "number" ? record.refreshExpires : void 0,
|
|
2692
2690
|
scopes: scopes.length > 0 ? scopes : void 0,
|
|
2693
2691
|
rateLimitTier: typeof record.rateLimitTier === "string" ? record.rateLimitTier : void 0
|
|
2694
2692
|
};
|
|
@@ -2714,13 +2712,10 @@ function parseClaudeAiOauth(raw) {
|
|
|
2714
2712
|
}
|
|
2715
2713
|
}
|
|
2716
2714
|
function buildCredentialsFile(material, now) {
|
|
2717
|
-
const refresh = material.refresh;
|
|
2718
2715
|
return JSON.stringify({
|
|
2719
2716
|
claudeAiOauth: {
|
|
2720
2717
|
accessToken: material.access,
|
|
2721
|
-
|
|
2722
|
-
expiresAt: refresh && material.expires ? material.expires : now + SYNTH_TOKEN_TTL_MS,
|
|
2723
|
-
...material.refreshExpires ? { refreshTokenExpiresAt: material.refreshExpires } : {},
|
|
2718
|
+
expiresAt: now + SYNTH_TOKEN_TTL_MS,
|
|
2724
2719
|
scopes: material.scopes?.length ? material.scopes : LEGACY_SCOPES,
|
|
2725
2720
|
...material.rateLimitTier ? { rateLimitTier: material.rateLimitTier } : {},
|
|
2726
2721
|
subscriptionType: "max"
|
|
@@ -2736,19 +2731,13 @@ function isConveyorOwnedCredentials(existing, markerHashes) {
|
|
|
2736
2731
|
if (typeof existing.accessToken !== "string") return false;
|
|
2737
2732
|
return markerHashes.includes(tokenFingerprint(existing.accessToken));
|
|
2738
2733
|
}
|
|
2739
|
-
function hasStableRefreshOwnership(existing, markerRaw) {
|
|
2740
|
-
return typeof existing.refreshToken === "string" && parseCredentialsRefreshMarker(markerRaw) === tokenFingerprint(existing.refreshToken);
|
|
2741
|
-
}
|
|
2742
2734
|
function isCurrentCredential(existing, material, now) {
|
|
2743
|
-
if (
|
|
2735
|
+
if (typeof existing.refreshToken === "string" && existing.refreshToken !== "") return false;
|
|
2744
2736
|
return existing.accessToken === material.access && typeof existing.expiresAt === "number" && existing.expiresAt > now + REFRESH_SKEW_MS;
|
|
2745
2737
|
}
|
|
2746
|
-
function needsMarkerUpgrade(input
|
|
2738
|
+
function needsMarkerUpgrade(input) {
|
|
2747
2739
|
if (!input.codingAgentKeyId) return false;
|
|
2748
|
-
|
|
2749
|
-
return Boolean(
|
|
2750
|
-
material.refresh && parseCredentialsRefreshMarker(input.markerRaw ?? null) !== tokenFingerprint(material.refresh)
|
|
2751
|
-
);
|
|
2740
|
+
return parseCredentialsMarkerKeyId(input.markerRaw ?? null) !== input.codingAgentKeyId;
|
|
2752
2741
|
}
|
|
2753
2742
|
function ownsExistingCredential(existing, markerRaw, markerHashes) {
|
|
2754
2743
|
if (isConveyorOwnedCredentials(existing, markerHashes)) return true;
|
|
@@ -2756,11 +2745,6 @@ function ownsExistingCredential(existing, markerRaw, markerHashes) {
|
|
|
2756
2745
|
const refreshToken = typeof existing.refreshToken === "string" ? existing.refreshToken : null;
|
|
2757
2746
|
return credentialMarkerMatches(markerRaw, accessToken, refreshToken);
|
|
2758
2747
|
}
|
|
2759
|
-
function cliRefreshedSameKey(input, material, existing, markerRaw) {
|
|
2760
|
-
if (!material.refresh || !input.codingAgentKeyId) return false;
|
|
2761
|
-
if (parseCredentialsMarkerKeyId(markerRaw) !== input.codingAgentKeyId) return false;
|
|
2762
|
-
return hasStableRefreshOwnership(existing, markerRaw) && existing.accessToken !== material.access;
|
|
2763
|
-
}
|
|
2764
2748
|
function planCredentialsWrite(input) {
|
|
2765
2749
|
if (!input.isCloud) return { action: "skip", reason: "not-cloud" };
|
|
2766
2750
|
const material = parseClaudeOauthEnv(input.oauthBlob) ?? (input.token ? { access: input.token } : null);
|
|
@@ -2772,7 +2756,6 @@ function planCredentialsWrite(input) {
|
|
|
2772
2756
|
material.access,
|
|
2773
2757
|
input.now,
|
|
2774
2758
|
markerHashes[0] ?? null,
|
|
2775
|
-
material.refresh,
|
|
2776
2759
|
input.codingAgentKeyId
|
|
2777
2760
|
);
|
|
2778
2761
|
const existing = parseClaudeAiOauth(input.existingRaw);
|
|
@@ -2780,13 +2763,10 @@ function planCredentialsWrite(input) {
|
|
|
2780
2763
|
if (!ownsExistingCredential(existing, markerRaw, markerHashes)) {
|
|
2781
2764
|
return { action: "skip", reason: "foreign-credentials" };
|
|
2782
2765
|
}
|
|
2783
|
-
if (cliRefreshedSameKey(input, material, existing, markerRaw)) {
|
|
2784
|
-
return { action: "skip", reason: "current" };
|
|
2785
|
-
}
|
|
2786
2766
|
if (!isCurrentCredential(existing, material, input.now)) {
|
|
2787
2767
|
return { action: "write", contents, marker };
|
|
2788
2768
|
}
|
|
2789
|
-
return needsMarkerUpgrade(input
|
|
2769
|
+
return needsMarkerUpgrade(input) ? { action: "mark", marker } : { action: "skip", reason: "current" };
|
|
2790
2770
|
}
|
|
2791
2771
|
|
|
2792
2772
|
// src/harness/pty/credentials.ts
|
|
@@ -7170,14 +7150,16 @@ ${context.projectDescription}` : "";
|
|
|
7170
7150
|
parts.push(`
|
|
7171
7151
|
## Project: ${context.projectName}${descLine}`);
|
|
7172
7152
|
}
|
|
7173
|
-
|
|
7153
|
+
const scopePaths = context.subProject ? subProjectScopePaths(context.subProject) : [];
|
|
7154
|
+
if (context.subProject && scopePaths.length > 0) {
|
|
7155
|
+
const folders = scopePaths.map((path) => `\`${path}\``).join(", ");
|
|
7174
7156
|
parts.push(
|
|
7175
7157
|
`
|
|
7176
7158
|
## Sub-project scope: ${context.subProject.name}`,
|
|
7177
|
-
`This task belongs to the "${context.subProject.name}" sub-project, which
|
|
7159
|
+
`This task belongs to the "${context.subProject.name}" sub-project, which allows changes under ${folders}.`,
|
|
7178
7160
|
`- Read and reference the whole repository freely.`,
|
|
7179
|
-
`- Substantive code changes belong under
|
|
7180
|
-
`- If the work genuinely requires substantive changes outside
|
|
7161
|
+
`- Substantive code changes belong under ${folders}. Trivial wiring elsewhere (exports, route registration) is fine when required.`,
|
|
7162
|
+
`- If the work genuinely requires substantive changes outside those folders, do NOT make them here \u2014 create a task on the parent project board (as part of a pack with this one) describing the needed change.`
|
|
7181
7163
|
);
|
|
7182
7164
|
}
|
|
7183
7165
|
if (context.description) {
|
|
@@ -14738,127 +14720,12 @@ var QueryBridge = class {
|
|
|
14738
14720
|
// src/execution/usage-sampler.ts
|
|
14739
14721
|
import { existsSync as existsSync2 } from "fs";
|
|
14740
14722
|
|
|
14741
|
-
// src/usage/
|
|
14742
|
-
|
|
14743
|
-
|
|
14744
|
-
const dtf = new Intl.DateTimeFormat("en-US", {
|
|
14745
|
-
timeZone: tz,
|
|
14746
|
-
hour12: false,
|
|
14747
|
-
year: "numeric",
|
|
14748
|
-
month: "2-digit",
|
|
14749
|
-
day: "2-digit",
|
|
14750
|
-
hour: "2-digit",
|
|
14751
|
-
minute: "2-digit",
|
|
14752
|
-
second: "2-digit"
|
|
14753
|
-
});
|
|
14754
|
-
const map = {};
|
|
14755
|
-
for (const part of dtf.formatToParts(new Date(utcMs))) {
|
|
14756
|
-
if (part.type !== "literal") map[part.type] = part.value;
|
|
14757
|
-
}
|
|
14758
|
-
const hour = map.hour === "24" ? 0 : Number(map.hour);
|
|
14759
|
-
const asUtc = Date.UTC(
|
|
14760
|
-
Number(map.year),
|
|
14761
|
-
Number(map.month) - 1,
|
|
14762
|
-
Number(map.day),
|
|
14763
|
-
hour,
|
|
14764
|
-
Number(map.minute),
|
|
14765
|
-
Number(map.second)
|
|
14766
|
-
);
|
|
14767
|
-
return asUtc - utcMs;
|
|
14768
|
-
}
|
|
14769
|
-
function zonedWallClockToUtc(y, mo, d, h, mi, tz) {
|
|
14770
|
-
if (tz === "UTC" || tz === "Etc/UTC") return Date.UTC(y, mo, d, h, mi);
|
|
14771
|
-
const naiveUtc = Date.UTC(y, mo, d, h, mi);
|
|
14772
|
-
const firstGuess = naiveUtc - tzOffsetMs(naiveUtc, tz);
|
|
14773
|
-
return naiveUtc - tzOffsetMs(firstGuess, tz);
|
|
14774
|
-
}
|
|
14775
|
-
function localTimeZone() {
|
|
14776
|
-
try {
|
|
14777
|
-
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
|
|
14778
|
-
} catch {
|
|
14779
|
-
return "UTC";
|
|
14780
|
-
}
|
|
14781
|
-
}
|
|
14782
|
-
function parseResetInstant(rowText, now, defaultTz = localTimeZone()) {
|
|
14783
|
-
const m = /resets\s+(?:by\s+)?(?:([a-z]{3})\s+(\d{1,2})(?:,|\s+at)?\s+)?(\d{1,2})(?::(\d{2}))?\s*(am|pm)(?:\s*\(([^)]+)\))?/i.exec(
|
|
14784
|
-
rowText
|
|
14785
|
-
);
|
|
14786
|
-
if (!m) return null;
|
|
14787
|
-
const [, monStr, dayStr, hourStr, minStr, meridiem, tzRaw] = m;
|
|
14788
|
-
const tz = tzRaw ? tzRaw.trim() : defaultTz;
|
|
14789
|
-
let hour = Number(hourStr) % 12;
|
|
14790
|
-
if (/pm/i.test(meridiem)) hour += 12;
|
|
14791
|
-
const minute = minStr ? Number(minStr) : 0;
|
|
14792
|
-
const nowDate = new Date(now);
|
|
14793
|
-
try {
|
|
14794
|
-
if (monStr && dayStr) {
|
|
14795
|
-
const month = MONTHS.indexOf(monStr.toLowerCase());
|
|
14796
|
-
if (month < 0) return null;
|
|
14797
|
-
const day = Number(dayStr);
|
|
14798
|
-
let utc2 = zonedWallClockToUtc(nowDate.getUTCFullYear(), month, day, hour, minute, tz);
|
|
14799
|
-
if (utc2 < now - 24 * 60 * 60 * 1e3) {
|
|
14800
|
-
utc2 = zonedWallClockToUtc(nowDate.getUTCFullYear() + 1, month, day, hour, minute, tz);
|
|
14801
|
-
}
|
|
14802
|
-
return new Date(utc2).toISOString();
|
|
14803
|
-
}
|
|
14804
|
-
let utc = zonedWallClockToUtc(
|
|
14805
|
-
nowDate.getUTCFullYear(),
|
|
14806
|
-
nowDate.getUTCMonth(),
|
|
14807
|
-
nowDate.getUTCDate(),
|
|
14808
|
-
hour,
|
|
14809
|
-
minute,
|
|
14810
|
-
tz
|
|
14811
|
-
);
|
|
14812
|
-
if (utc <= now) {
|
|
14813
|
-
utc = zonedWallClockToUtc(
|
|
14814
|
-
nowDate.getUTCFullYear(),
|
|
14815
|
-
nowDate.getUTCMonth(),
|
|
14816
|
-
nowDate.getUTCDate() + 1,
|
|
14817
|
-
hour,
|
|
14818
|
-
minute,
|
|
14819
|
-
tz
|
|
14820
|
-
);
|
|
14821
|
-
}
|
|
14822
|
-
return new Date(utc).toISOString();
|
|
14823
|
-
} catch {
|
|
14824
|
-
return null;
|
|
14825
|
-
}
|
|
14826
|
-
}
|
|
14827
|
-
|
|
14828
|
-
// src/usage/parse-usage.ts
|
|
14829
|
-
var ESC = "\\u001b";
|
|
14830
|
-
var ANSI_CSI = new RegExp(`${ESC}\\[[0-9;?]*[ -/]*[@-~]`, "g");
|
|
14831
|
-
var ANSI_OSC = new RegExp(`${ESC}\\][^\\u0007${ESC}]*(?:\\u0007|${ESC}\\\\)`, "g");
|
|
14832
|
-
var BAR_GLYPHS = /[─-▟]/g;
|
|
14833
|
-
function normalizeUsageText(stdout) {
|
|
14834
|
-
return stdout.replace(ANSI_CSI, "").replace(ANSI_OSC, "").replace(BAR_GLYPHS, " ").replace(/\r/g, "");
|
|
14835
|
-
}
|
|
14836
|
-
function parseUsageGauges(stdout, now = Date.now(), defaultTz) {
|
|
14837
|
-
const text = normalizeUsageText(stdout);
|
|
14838
|
-
const rows = [
|
|
14839
|
-
...text.matchAll(
|
|
14840
|
-
/Current (session|week)\s*(\([^)\n]*\))?[^%\n]*?(\d+(?:\.\d+)?)\s*%(?:\s*used)?([^\n]*?)(?=Current\s+(?:session|week)\b|\n|$)/gi
|
|
14841
|
-
)
|
|
14842
|
-
];
|
|
14843
|
-
const gauges = rows.map((m) => ({
|
|
14844
|
-
label: `Current ${m[1].toLowerCase()}${m[2] ? ` ${m[2]}` : ""}`,
|
|
14845
|
-
utilization: Number(m[3]) / 100,
|
|
14846
|
-
resetsAt: parseResetInstant(m[4] ?? "", now, defaultTz)
|
|
14847
|
-
}));
|
|
14848
|
-
const session = gauges.find((g) => g.label.startsWith("Current session"));
|
|
14849
|
-
const weekly = gauges.filter((g) => g.label.startsWith("Current week"));
|
|
14850
|
-
const weeklyResets = weekly.map((g) => g.resetsAt).filter((r) => r !== null);
|
|
14851
|
-
return {
|
|
14852
|
-
sessionUsage: session ? session.utilization : null,
|
|
14853
|
-
weeklyUsage: weekly.length ? Math.max(...weekly.map((g) => g.utilization)) : null,
|
|
14854
|
-
sessionResetsAt: session?.resetsAt ?? null,
|
|
14855
|
-
// Soonest weekly reset (all weekly rows share one instant in practice).
|
|
14856
|
-
weeklyResetsAt: weeklyResets.length ? new Date(Math.min(...weeklyResets.map((r) => new Date(r).getTime()))).toISOString() : null,
|
|
14857
|
-
gauges
|
|
14858
|
-
};
|
|
14859
|
-
}
|
|
14723
|
+
// src/usage/isolated-probe.ts
|
|
14724
|
+
import { mkdtemp as mkdtemp3, writeFile as writeFile10, copyFile, rm as rm5 } from "fs/promises";
|
|
14725
|
+
import { join as join21 } from "path";
|
|
14860
14726
|
|
|
14861
14727
|
// src/usage/run-probe.ts
|
|
14728
|
+
var logger8 = createServiceLogger("usage-probe");
|
|
14862
14729
|
var PROBE_TIMEOUT_MS = 3e4;
|
|
14863
14730
|
var FIRST_SEND_MS = 5e3;
|
|
14864
14731
|
var RESEND_INTERVAL_MS = 4e3;
|
|
@@ -14875,7 +14742,8 @@ function buildProbeEnv(env = process.env) {
|
|
|
14875
14742
|
return clean;
|
|
14876
14743
|
}
|
|
14877
14744
|
function panelRendering(buf) {
|
|
14878
|
-
|
|
14745
|
+
const text = flattenTerminalText(buf);
|
|
14746
|
+
return /Current\s*session/i.test(text) && /%/.test(text);
|
|
14879
14747
|
}
|
|
14880
14748
|
var UsageProbeRun = class {
|
|
14881
14749
|
constructor(resolve, timing) {
|
|
@@ -14899,7 +14767,7 @@ var UsageProbeRun = class {
|
|
|
14899
14767
|
this.childExited = true;
|
|
14900
14768
|
this.finishBestEffort();
|
|
14901
14769
|
});
|
|
14902
|
-
this.hardTimer = setTimeout(() => this.
|
|
14770
|
+
this.hardTimer = setTimeout(() => this.finishOnTimeout(), timeoutMs);
|
|
14903
14771
|
this.hardTimer.unref?.();
|
|
14904
14772
|
const first = setTimeout(() => this.trySend(), this.timing.firstSendMs);
|
|
14905
14773
|
first.unref?.();
|
|
@@ -14919,6 +14787,15 @@ var UsageProbeRun = class {
|
|
|
14919
14787
|
if (this.settleTimer || !panelRendering(this.buf)) return;
|
|
14920
14788
|
this.settleTimer = setTimeout(() => this.finish(this.buf), this.timing.settleMs);
|
|
14921
14789
|
}
|
|
14790
|
+
finishOnTimeout() {
|
|
14791
|
+
if (!this.settled && !panelRendering(this.buf)) {
|
|
14792
|
+
logger8.info("usage probe timed out before the panel rendered", {
|
|
14793
|
+
bufferLength: this.buf.length,
|
|
14794
|
+
sends: this.sends
|
|
14795
|
+
});
|
|
14796
|
+
}
|
|
14797
|
+
this.finishBestEffort();
|
|
14798
|
+
}
|
|
14922
14799
|
finishBestEffort() {
|
|
14923
14800
|
this.finish(panelRendering(this.buf) ? this.buf : cleanTerminalOutput(this.buf, 500));
|
|
14924
14801
|
}
|
|
@@ -14974,62 +14851,210 @@ async function runUsageProbe(deps = {}) {
|
|
|
14974
14851
|
});
|
|
14975
14852
|
}
|
|
14976
14853
|
|
|
14854
|
+
// src/usage/isolated-probe.ts
|
|
14855
|
+
var logger9 = createServiceLogger("isolated-probe");
|
|
14856
|
+
async function probeUsageIsolated(token, opts = {}) {
|
|
14857
|
+
let dir = null;
|
|
14858
|
+
try {
|
|
14859
|
+
dir = await mkdtemp3(join21(sessionTempBase(), "conveyor-usage-"));
|
|
14860
|
+
const credentials = buildSynthesizedCredentials(token, opts.now ?? Date.now());
|
|
14861
|
+
await writeFile10(join21(dir, ".credentials.json"), credentials, {
|
|
14862
|
+
encoding: "utf8",
|
|
14863
|
+
mode: 384
|
|
14864
|
+
});
|
|
14865
|
+
await copyFile(claudeJsonPath(), join21(dir, ".claude.json")).catch(() => {
|
|
14866
|
+
});
|
|
14867
|
+
return await runUsageProbe({ cwd: opts.cwd, env: { ...process.env, CLAUDE_CONFIG_DIR: dir } });
|
|
14868
|
+
} catch (error) {
|
|
14869
|
+
logger9.info("isolated usage probe failed", {
|
|
14870
|
+
error: error instanceof Error ? error.message : String(error)
|
|
14871
|
+
});
|
|
14872
|
+
return "";
|
|
14873
|
+
} finally {
|
|
14874
|
+
if (dir) await rm5(dir, { recursive: true, force: true }).catch(() => {
|
|
14875
|
+
});
|
|
14876
|
+
}
|
|
14877
|
+
}
|
|
14878
|
+
|
|
14879
|
+
// src/usage/reset-parse.ts
|
|
14880
|
+
var MONTHS = ["jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"];
|
|
14881
|
+
function tzOffsetMs(utcMs, tz) {
|
|
14882
|
+
const dtf = new Intl.DateTimeFormat("en-US", {
|
|
14883
|
+
timeZone: tz,
|
|
14884
|
+
hour12: false,
|
|
14885
|
+
year: "numeric",
|
|
14886
|
+
month: "2-digit",
|
|
14887
|
+
day: "2-digit",
|
|
14888
|
+
hour: "2-digit",
|
|
14889
|
+
minute: "2-digit",
|
|
14890
|
+
second: "2-digit"
|
|
14891
|
+
});
|
|
14892
|
+
const map = {};
|
|
14893
|
+
for (const part of dtf.formatToParts(new Date(utcMs))) {
|
|
14894
|
+
if (part.type !== "literal") map[part.type] = part.value;
|
|
14895
|
+
}
|
|
14896
|
+
const hour = map.hour === "24" ? 0 : Number(map.hour);
|
|
14897
|
+
const asUtc = Date.UTC(
|
|
14898
|
+
Number(map.year),
|
|
14899
|
+
Number(map.month) - 1,
|
|
14900
|
+
Number(map.day),
|
|
14901
|
+
hour,
|
|
14902
|
+
Number(map.minute),
|
|
14903
|
+
Number(map.second)
|
|
14904
|
+
);
|
|
14905
|
+
return asUtc - utcMs;
|
|
14906
|
+
}
|
|
14907
|
+
function zonedWallClockToUtc(y, mo, d, h, mi, tz) {
|
|
14908
|
+
if (tz === "UTC" || tz === "Etc/UTC") return Date.UTC(y, mo, d, h, mi);
|
|
14909
|
+
const naiveUtc = Date.UTC(y, mo, d, h, mi);
|
|
14910
|
+
const firstGuess = naiveUtc - tzOffsetMs(naiveUtc, tz);
|
|
14911
|
+
return naiveUtc - tzOffsetMs(firstGuess, tz);
|
|
14912
|
+
}
|
|
14913
|
+
function localTimeZone() {
|
|
14914
|
+
try {
|
|
14915
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
|
|
14916
|
+
} catch {
|
|
14917
|
+
return "UTC";
|
|
14918
|
+
}
|
|
14919
|
+
}
|
|
14920
|
+
function parseResetInstant(rowText, now, defaultTz = localTimeZone()) {
|
|
14921
|
+
const m = /resets\s*(?:by\s*)?(?:([a-z]{3})\s*(\d{1,2})(?:,|\s*at)?\s*)?(\d{1,2})(?::(\d{2}))?\s*(am|pm)(?:\s*\(([^)]+)\))?/i.exec(
|
|
14922
|
+
rowText
|
|
14923
|
+
);
|
|
14924
|
+
if (!m) return null;
|
|
14925
|
+
const [, monStr, dayStr, hourStr, minStr, meridiem, tzRaw] = m;
|
|
14926
|
+
const tz = tzRaw ? tzRaw.trim() : defaultTz;
|
|
14927
|
+
let hour = Number(hourStr) % 12;
|
|
14928
|
+
if (/pm/i.test(meridiem)) hour += 12;
|
|
14929
|
+
const minute = minStr ? Number(minStr) : 0;
|
|
14930
|
+
const nowDate = new Date(now);
|
|
14931
|
+
try {
|
|
14932
|
+
if (monStr && dayStr) {
|
|
14933
|
+
const month = MONTHS.indexOf(monStr.toLowerCase());
|
|
14934
|
+
if (month < 0) return null;
|
|
14935
|
+
const day = Number(dayStr);
|
|
14936
|
+
let utc2 = zonedWallClockToUtc(nowDate.getUTCFullYear(), month, day, hour, minute, tz);
|
|
14937
|
+
if (utc2 < now - 24 * 60 * 60 * 1e3) {
|
|
14938
|
+
utc2 = zonedWallClockToUtc(nowDate.getUTCFullYear() + 1, month, day, hour, minute, tz);
|
|
14939
|
+
}
|
|
14940
|
+
return new Date(utc2).toISOString();
|
|
14941
|
+
}
|
|
14942
|
+
let utc = zonedWallClockToUtc(
|
|
14943
|
+
nowDate.getUTCFullYear(),
|
|
14944
|
+
nowDate.getUTCMonth(),
|
|
14945
|
+
nowDate.getUTCDate(),
|
|
14946
|
+
hour,
|
|
14947
|
+
minute,
|
|
14948
|
+
tz
|
|
14949
|
+
);
|
|
14950
|
+
if (utc <= now) {
|
|
14951
|
+
utc = zonedWallClockToUtc(
|
|
14952
|
+
nowDate.getUTCFullYear(),
|
|
14953
|
+
nowDate.getUTCMonth(),
|
|
14954
|
+
nowDate.getUTCDate() + 1,
|
|
14955
|
+
hour,
|
|
14956
|
+
minute,
|
|
14957
|
+
tz
|
|
14958
|
+
);
|
|
14959
|
+
}
|
|
14960
|
+
return new Date(utc).toISOString();
|
|
14961
|
+
} catch {
|
|
14962
|
+
return null;
|
|
14963
|
+
}
|
|
14964
|
+
}
|
|
14965
|
+
|
|
14966
|
+
// src/usage/parse-usage.ts
|
|
14967
|
+
var BAR_GLYPHS = /[─-▟]/g;
|
|
14968
|
+
function normalizeUsageText(stdout) {
|
|
14969
|
+
return flattenTerminalText(stdout).replace(BAR_GLYPHS, " ").replace(/[\r\n]+/g, " ");
|
|
14970
|
+
}
|
|
14971
|
+
function parseUsageGauges(stdout, now = Date.now(), defaultTz) {
|
|
14972
|
+
const text = normalizeUsageText(stdout);
|
|
14973
|
+
const rows = [
|
|
14974
|
+
...text.matchAll(
|
|
14975
|
+
/Current\s*(session|week)\s*(\([^)\n]*\))?[^%\n]*?(\d+(?:\.\d+)?)\s*%(?:\s*used)?([^\n]*?)(?=Current\s*(?:session|week)|\n|$)/gi
|
|
14976
|
+
)
|
|
14977
|
+
];
|
|
14978
|
+
const gauges = rows.map((m) => ({
|
|
14979
|
+
label: `Current ${m[1].toLowerCase()}${m[2] ? ` ${m[2]}` : ""}`,
|
|
14980
|
+
utilization: Number(m[3]) / 100,
|
|
14981
|
+
resetsAt: parseResetInstant(m[4] ?? "", now, defaultTz)
|
|
14982
|
+
}));
|
|
14983
|
+
const session = gauges.find((g) => g.label.startsWith("Current session"));
|
|
14984
|
+
const weekly = gauges.filter((g) => g.label.startsWith("Current week"));
|
|
14985
|
+
const weeklyResets = weekly.map((g) => g.resetsAt).filter((r) => r !== null);
|
|
14986
|
+
return {
|
|
14987
|
+
sessionUsage: session ? session.utilization : null,
|
|
14988
|
+
weeklyUsage: weekly.length ? Math.max(...weekly.map((g) => g.utilization)) : null,
|
|
14989
|
+
sessionResetsAt: session?.resetsAt ?? null,
|
|
14990
|
+
// Soonest weekly reset (all weekly rows share one instant in practice).
|
|
14991
|
+
weeklyResetsAt: weeklyResets.length ? new Date(Math.min(...weeklyResets.map((r) => new Date(r).getTime()))).toISOString() : null,
|
|
14992
|
+
gauges
|
|
14993
|
+
};
|
|
14994
|
+
}
|
|
14995
|
+
|
|
14977
14996
|
// src/execution/usage-sampler.ts
|
|
14978
|
-
var
|
|
14997
|
+
var logger10 = createServiceLogger("usage-sampler");
|
|
14979
14998
|
var NO_SAMPLES = { samples: [], unmeasurable: null };
|
|
14980
14999
|
function usesNativeUsageReporting(env = process.env) {
|
|
14981
15000
|
return env.CONVEYOR_TUI === "codex";
|
|
14982
15001
|
}
|
|
14983
|
-
function isAttributable(identity
|
|
15002
|
+
function isAttributable(identity) {
|
|
14984
15003
|
if (!identity) return { ok: true };
|
|
14985
15004
|
if (identity.hasRefreshToken && !identity.isConveyorOwned) {
|
|
14986
15005
|
return { ok: false, reason: "manual-login-credentials" };
|
|
14987
15006
|
}
|
|
14988
|
-
if (!(identity.hasRefreshToken && identity.isConveyorOwned) && sessionToken && identity.accessToken && identity.accessToken !== sessionToken) {
|
|
14989
|
-
return { ok: false, reason: "credentials-token-mismatch" };
|
|
14990
|
-
}
|
|
14991
15007
|
return { ok: true };
|
|
14992
15008
|
}
|
|
14993
|
-
|
|
14994
|
-
|
|
15009
|
+
function samplesFromPanel(stdout) {
|
|
15010
|
+
const { sessionUsage, weeklyUsage, sessionResetsAt, weeklyResetsAt, gauges } = parseUsageGauges(stdout);
|
|
15011
|
+
const samples = [];
|
|
15012
|
+
if (sessionUsage !== null) {
|
|
15013
|
+
samples.push({
|
|
15014
|
+
rateLimitType: "five_hour",
|
|
15015
|
+
utilization: sessionUsage,
|
|
15016
|
+
status: "allowed",
|
|
15017
|
+
resetsAt: sessionResetsAt,
|
|
15018
|
+
gauges
|
|
15019
|
+
});
|
|
15020
|
+
}
|
|
15021
|
+
if (weeklyUsage !== null) {
|
|
15022
|
+
samples.push({
|
|
15023
|
+
rateLimitType: "seven_day",
|
|
15024
|
+
utilization: weeklyUsage,
|
|
15025
|
+
status: "allowed",
|
|
15026
|
+
resetsAt: weeklyResetsAt,
|
|
15027
|
+
gauges
|
|
15028
|
+
});
|
|
15029
|
+
}
|
|
15030
|
+
if (samples.length === 0) {
|
|
15031
|
+
logger10.info("usage sample produced no gauges", {
|
|
15032
|
+
stdoutLength: stdout.length,
|
|
15033
|
+
stdoutHead: stdout.slice(0, 200).replaceAll("\n", " ")
|
|
15034
|
+
});
|
|
15035
|
+
}
|
|
15036
|
+
return samples;
|
|
15037
|
+
}
|
|
15038
|
+
async function sampleKeyUsage(opts = {}) {
|
|
15039
|
+
const { token, cwd } = opts;
|
|
15040
|
+
const hasCredentialsFile = opts.hasCredentialsFile ?? (() => existsSync2(claudeCredentialsPath()));
|
|
15041
|
+
if (!token && !hasCredentialsFile()) return NO_SAMPLES;
|
|
14995
15042
|
try {
|
|
14996
|
-
|
|
15043
|
+
if (token) {
|
|
15044
|
+
const probeToken = opts.probeToken ?? ((own) => probeUsageIsolated(own, { cwd }));
|
|
15045
|
+
return { samples: samplesFromPanel(await probeToken(token)), unmeasurable: null };
|
|
15046
|
+
}
|
|
15047
|
+
const attributable = isAttributable(await (opts.readIdentity ?? readCredentialsIdentity)());
|
|
14997
15048
|
if (!attributable.ok) {
|
|
14998
|
-
|
|
15049
|
+
logger10.info("usage sample skipped \u2014 credentials not attributable to this session's key", {
|
|
14999
15050
|
reason: attributable.reason
|
|
15000
15051
|
});
|
|
15001
15052
|
return { samples: [], unmeasurable: { reason: attributable.reason ?? "unattributable" } };
|
|
15002
15053
|
}
|
|
15003
|
-
const
|
|
15004
|
-
|
|
15005
|
-
const samples = [];
|
|
15006
|
-
if (sessionUsage !== null) {
|
|
15007
|
-
samples.push({
|
|
15008
|
-
rateLimitType: "five_hour",
|
|
15009
|
-
utilization: sessionUsage,
|
|
15010
|
-
status: "allowed",
|
|
15011
|
-
resetsAt: sessionResetsAt,
|
|
15012
|
-
gauges
|
|
15013
|
-
});
|
|
15014
|
-
}
|
|
15015
|
-
if (weeklyUsage !== null) {
|
|
15016
|
-
samples.push({
|
|
15017
|
-
rateLimitType: "seven_day",
|
|
15018
|
-
utilization: weeklyUsage,
|
|
15019
|
-
status: "allowed",
|
|
15020
|
-
resetsAt: weeklyResetsAt,
|
|
15021
|
-
gauges
|
|
15022
|
-
});
|
|
15023
|
-
}
|
|
15024
|
-
if (samples.length === 0) {
|
|
15025
|
-
logger8.info("usage sample produced no gauges", {
|
|
15026
|
-
stdoutLength: stdout.length,
|
|
15027
|
-
stdoutHead: stdout.slice(0, 200).replaceAll("\n", " ")
|
|
15028
|
-
});
|
|
15029
|
-
}
|
|
15030
|
-
return { samples, unmeasurable: null };
|
|
15054
|
+
const probeFile = opts.probeCredentialsFile ?? (() => runUsageProbe({ cwd }));
|
|
15055
|
+
return { samples: samplesFromPanel(await probeFile()), unmeasurable: null };
|
|
15031
15056
|
} catch (error) {
|
|
15032
|
-
|
|
15057
|
+
logger10.info("usage sample failed", {
|
|
15033
15058
|
error: error instanceof Error ? error.message : String(error)
|
|
15034
15059
|
});
|
|
15035
15060
|
return NO_SAMPLES;
|
|
@@ -16398,10 +16423,10 @@ var SessionRunner = class _SessionRunner {
|
|
|
16398
16423
|
async sampleAndReportKeyUsage() {
|
|
16399
16424
|
if (this.stopped || usesNativeUsageReporting()) return;
|
|
16400
16425
|
const codingAgentKeyId = process.env.CONVEYOR_CODING_AGENT_KEY_ID;
|
|
16401
|
-
const { samples, unmeasurable } = await sampleKeyUsage(
|
|
16402
|
-
process.env.CLAUDE_CODE_OAUTH_TOKEN,
|
|
16403
|
-
|
|
16404
|
-
);
|
|
16426
|
+
const { samples, unmeasurable } = await sampleKeyUsage({
|
|
16427
|
+
token: process.env.CLAUDE_CODE_OAUTH_TOKEN,
|
|
16428
|
+
cwd: this.config.workspaceDir
|
|
16429
|
+
});
|
|
16405
16430
|
if (unmeasurable) {
|
|
16406
16431
|
this.connection.sendEvent(buildUnmeasurableEvent(unmeasurable.reason, codingAgentKeyId));
|
|
16407
16432
|
return;
|
|
@@ -16928,8 +16953,6 @@ function unshallowRepo(workspaceDir) {
|
|
|
16928
16953
|
|
|
16929
16954
|
export {
|
|
16930
16955
|
isPermissionDeniedError,
|
|
16931
|
-
buildSynthesizedCredentials,
|
|
16932
|
-
claudeJsonPath,
|
|
16933
16956
|
PtyHarness,
|
|
16934
16957
|
resolveTuiKindFromEnv,
|
|
16935
16958
|
resolveTuiAdapter,
|
|
@@ -16938,8 +16961,8 @@ export {
|
|
|
16938
16961
|
buildProjectTools,
|
|
16939
16962
|
resolvePlaywrightMcpServer,
|
|
16940
16963
|
resolveSessionStart,
|
|
16964
|
+
probeUsageIsolated,
|
|
16941
16965
|
parseUsageGauges,
|
|
16942
|
-
runUsageProbe,
|
|
16943
16966
|
usesNativeUsageReporting,
|
|
16944
16967
|
sampleKeyUsage,
|
|
16945
16968
|
buildRateLimitEvents,
|
|
@@ -46,9 +46,32 @@ function spawnOptionsFingerprint(input) {
|
|
|
46
46
|
if (input.effort) parts.push(input.effort);
|
|
47
47
|
return JSON.stringify(parts);
|
|
48
48
|
}
|
|
49
|
-
var
|
|
49
|
+
var ESC = String.fromCharCode(27);
|
|
50
|
+
var ANSI_CSI = new RegExp(`${ESC}\\[([0-9;?]*)([ -/]*)([@-~])`, "g");
|
|
51
|
+
var ANSI_OSC = new RegExp(`${ESC}\\][^\\u0007${ESC}]*(?:\\u0007|${ESC}\\\\)`, "g");
|
|
52
|
+
var MAX_CURSOR_FORWARD = 300;
|
|
53
|
+
function flattenTerminalText(raw) {
|
|
54
|
+
return raw.replace(ANSI_OSC, "").replace(ANSI_CSI, (_seq, params, inter, final) => {
|
|
55
|
+
if (inter || params.startsWith("?")) return "";
|
|
56
|
+
switch (final) {
|
|
57
|
+
case "C":
|
|
58
|
+
return " ".repeat(Math.min(Math.max(Number(params) || 1, 1), MAX_CURSOR_FORWARD));
|
|
59
|
+
case "G":
|
|
60
|
+
return " ";
|
|
61
|
+
case "A":
|
|
62
|
+
case "B":
|
|
63
|
+
case "E":
|
|
64
|
+
case "F":
|
|
65
|
+
case "H":
|
|
66
|
+
case "f":
|
|
67
|
+
return "\n";
|
|
68
|
+
default:
|
|
69
|
+
return "";
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
50
73
|
function cleanTerminalOutput(raw, maxChars = 1200) {
|
|
51
|
-
const noAnsi = raw
|
|
74
|
+
const noAnsi = flattenTerminalText(raw);
|
|
52
75
|
let out = "";
|
|
53
76
|
for (const ch of noAnsi) {
|
|
54
77
|
const code = ch.charCodeAt(0);
|
|
@@ -215,6 +238,7 @@ function inheritedEnv(socketPath) {
|
|
|
215
238
|
if (env.CLAUDE_CODE_OAUTH_TOKEN) {
|
|
216
239
|
delete env.ANTHROPIC_API_KEY;
|
|
217
240
|
}
|
|
241
|
+
delete env.CONVEYOR_CLAUDE_OAUTH;
|
|
218
242
|
if (ghHostsManagedByConveyor() && env.CONVEYOR_KEEP_GH_TOKEN_ENV !== "1") {
|
|
219
243
|
delete env.GH_TOKEN;
|
|
220
244
|
delete env.GITHUB_TOKEN;
|
|
@@ -272,6 +296,7 @@ export {
|
|
|
272
296
|
resolveClaudeBinary,
|
|
273
297
|
buildSpawnArgs,
|
|
274
298
|
spawnOptionsFingerprint,
|
|
299
|
+
flattenTerminalText,
|
|
275
300
|
cleanTerminalOutput,
|
|
276
301
|
buildExitErrors,
|
|
277
302
|
MAX_DIAGNOSTIC_OUTPUT,
|
package/dist/cli.js
CHANGED
|
@@ -7,33 +7,30 @@ import {
|
|
|
7
7
|
WorkspaceCommandSupervisor,
|
|
8
8
|
startWorkspaceCommandsAfterConnect,
|
|
9
9
|
stopWorkspaceCommands
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-K35YJK2U.js";
|
|
11
11
|
import {
|
|
12
12
|
PtyHarness,
|
|
13
13
|
SessionRunner,
|
|
14
14
|
buildProjectTools,
|
|
15
15
|
buildRateLimitEvents,
|
|
16
|
-
buildSynthesizedCredentials,
|
|
17
16
|
buildUnmeasurableEvent,
|
|
18
|
-
claudeJsonPath,
|
|
19
17
|
getEffortOverride,
|
|
20
18
|
getModelOverride,
|
|
21
19
|
isPermissionDeniedError,
|
|
22
20
|
parseUsageGauges,
|
|
21
|
+
probeUsageIsolated,
|
|
23
22
|
resolvePlaywrightMcpServer,
|
|
24
23
|
resolveSessionStart,
|
|
25
24
|
resolveTuiAdapter,
|
|
26
25
|
resolveTuiKindFromEnv,
|
|
27
|
-
runUsageProbe,
|
|
28
26
|
sampleKeyUsage,
|
|
29
27
|
usesNativeUsageReporting
|
|
30
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-RNE3JAF5.js";
|
|
31
29
|
import "./chunk-V5WR2F2P.js";
|
|
32
30
|
import {
|
|
33
31
|
inheritedEnv,
|
|
34
|
-
resolvePtySpawn
|
|
35
|
-
|
|
36
|
-
} from "./chunk-EKTPDG3G.js";
|
|
32
|
+
resolvePtySpawn
|
|
33
|
+
} from "./chunk-SXZS2R52.js";
|
|
37
34
|
import {
|
|
38
35
|
AgentConnection,
|
|
39
36
|
DEFAULT_LIFECYCLE_CONFIG,
|
|
@@ -44,7 +41,7 @@ import {
|
|
|
44
41
|
createServiceLogger,
|
|
45
42
|
loadAndAnnotateDiscoveredPorts,
|
|
46
43
|
loadConveyorConfig
|
|
47
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-O3MXZHIS.js";
|
|
48
45
|
import "./chunk-VIUZS7V4.js";
|
|
49
46
|
import "./chunk-W4LZ7R6Z.js";
|
|
50
47
|
import "./chunk-372R6E4C.js";
|
|
@@ -55,7 +52,7 @@ import "./chunk-6Q6LQBWO.js";
|
|
|
55
52
|
|
|
56
53
|
// src/cli.ts
|
|
57
54
|
import { readFileSync } from "fs";
|
|
58
|
-
import { join
|
|
55
|
+
import { join, dirname } from "path";
|
|
59
56
|
import { fileURLToPath } from "url";
|
|
60
57
|
|
|
61
58
|
// src/utils/session-identity.ts
|
|
@@ -238,10 +235,10 @@ var ProjectSessionRunner = class {
|
|
|
238
235
|
async sampleAndReportKeyUsage() {
|
|
239
236
|
if (this.stopped || usesNativeUsageReporting()) return;
|
|
240
237
|
const codingAgentKeyId = process.env.CONVEYOR_CODING_AGENT_KEY_ID;
|
|
241
|
-
const { samples, unmeasurable } = await sampleKeyUsage(
|
|
242
|
-
process.env.CLAUDE_CODE_OAUTH_TOKEN,
|
|
243
|
-
|
|
244
|
-
);
|
|
238
|
+
const { samples, unmeasurable } = await sampleKeyUsage({
|
|
239
|
+
token: process.env.CLAUDE_CODE_OAUTH_TOKEN,
|
|
240
|
+
cwd: this.config.workspaceDir
|
|
241
|
+
});
|
|
245
242
|
if (unmeasurable) {
|
|
246
243
|
this.connection.sendEvent(buildUnmeasurableEvent(unmeasurable.reason, codingAgentKeyId));
|
|
247
244
|
return;
|
|
@@ -259,8 +256,6 @@ var ProjectSessionRunner = class {
|
|
|
259
256
|
};
|
|
260
257
|
|
|
261
258
|
// src/usage/multi-key-probe.ts
|
|
262
|
-
import { mkdtemp, writeFile, copyFile, rm } from "fs/promises";
|
|
263
|
-
import { join } from "path";
|
|
264
259
|
var logger = createServiceLogger("multi-key-probe");
|
|
265
260
|
function gaugesToSamples(stdout) {
|
|
266
261
|
const { sessionUsage, weeklyUsage, sessionResetsAt, weeklyResetsAt, gauges } = parseUsageGauges(stdout);
|
|
@@ -285,30 +280,9 @@ function gaugesToSamples(stdout) {
|
|
|
285
280
|
}
|
|
286
281
|
return samples;
|
|
287
282
|
}
|
|
288
|
-
async function isolatedProbe(token, now, cwd) {
|
|
289
|
-
let dir = null;
|
|
290
|
-
try {
|
|
291
|
-
dir = await mkdtemp(join(sessionTempBase(), "conveyor-usage-"));
|
|
292
|
-
await writeFile(join(dir, ".credentials.json"), buildSynthesizedCredentials(token, now), {
|
|
293
|
-
encoding: "utf8",
|
|
294
|
-
mode: 384
|
|
295
|
-
});
|
|
296
|
-
await copyFile(claudeJsonPath(), join(dir, ".claude.json")).catch(() => {
|
|
297
|
-
});
|
|
298
|
-
return await runUsageProbe({ cwd, env: { ...process.env, CLAUDE_CONFIG_DIR: dir } });
|
|
299
|
-
} catch (error) {
|
|
300
|
-
logger.info("isolated usage probe failed", {
|
|
301
|
-
error: error instanceof Error ? error.message : String(error)
|
|
302
|
-
});
|
|
303
|
-
return "";
|
|
304
|
-
} finally {
|
|
305
|
-
if (dir) await rm(dir, { recursive: true, force: true }).catch(() => {
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
283
|
async function probeKeysUsage(keys, deps = {}) {
|
|
310
284
|
const now = deps.now ?? Date.now;
|
|
311
|
-
const probeOne = deps.probeOne ?? ((token) =>
|
|
285
|
+
const probeOne = deps.probeOne ?? ((token) => probeUsageIsolated(token, { now: now(), cwd: deps.cwd }));
|
|
312
286
|
const results = [];
|
|
313
287
|
for (const key of keys) {
|
|
314
288
|
if (!key.oauthToken) continue;
|
|
@@ -582,10 +556,10 @@ var AdhocSessionRunner = class {
|
|
|
582
556
|
async sampleAndReportOwnKey() {
|
|
583
557
|
if (this.stopped || usesNativeUsageReporting()) return;
|
|
584
558
|
const codingAgentKeyId = process.env.CONVEYOR_CODING_AGENT_KEY_ID;
|
|
585
|
-
const { samples, unmeasurable } = await sampleKeyUsage(
|
|
586
|
-
process.env.CLAUDE_CODE_OAUTH_TOKEN,
|
|
587
|
-
|
|
588
|
-
);
|
|
559
|
+
const { samples, unmeasurable } = await sampleKeyUsage({
|
|
560
|
+
token: process.env.CLAUDE_CODE_OAUTH_TOKEN,
|
|
561
|
+
cwd: this.config.workspaceDir
|
|
562
|
+
});
|
|
589
563
|
if (unmeasurable) {
|
|
590
564
|
this.connection.sendEvent(buildUnmeasurableEvent(unmeasurable.reason, codingAgentKeyId));
|
|
591
565
|
return;
|
|
@@ -1212,7 +1186,7 @@ function wireSpawnChildren(mode, connection, supervisors, logger7) {
|
|
|
1212
1186
|
|
|
1213
1187
|
// src/cli.ts
|
|
1214
1188
|
if (process.argv[2] === "boot") {
|
|
1215
|
-
const { runBoot } = await import("./boot-
|
|
1189
|
+
const { runBoot } = await import("./boot-GD5XMLPS.js");
|
|
1216
1190
|
process.exit(await runBoot(process.argv.slice(3)));
|
|
1217
1191
|
}
|
|
1218
1192
|
if (isLegacyEntrypointLaunch(process.env)) {
|
|
@@ -1222,7 +1196,7 @@ if (isLegacyEntrypointLaunch(process.env)) {
|
|
|
1222
1196
|
}
|
|
1223
1197
|
if (process.argv.includes("--version")) {
|
|
1224
1198
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
1225
|
-
const pkgPath =
|
|
1199
|
+
const pkgPath = join(__dirname, "..", "package.json");
|
|
1226
1200
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
1227
1201
|
process.stdout.write(pkg.version + "\n");
|
|
1228
1202
|
process.exit(0);
|
|
@@ -1281,7 +1255,7 @@ process.on("unhandledRejection", (reason) => {
|
|
|
1281
1255
|
process.exit(1);
|
|
1282
1256
|
});
|
|
1283
1257
|
if (process.env.CONVEYOR_MODE === "workbench") {
|
|
1284
|
-
const { startWorkbenchServer } = await import("./server-
|
|
1258
|
+
const { startWorkbenchServer } = await import("./server-FPDS4CT5.js");
|
|
1285
1259
|
const { oomWatchdogOptionsFromEnv } = await import("./oom-watchdog-PAC5OJJG.js");
|
|
1286
1260
|
const { DEFAULT_WORKBENCH_PORT } = await import("./protocol-QBCYO4GI.js");
|
|
1287
1261
|
const port = Number(process.env.CONVEYOR_WORKBENCH_PORT) || DEFAULT_WORKBENCH_PORT;
|
|
@@ -1291,7 +1265,7 @@ if (process.env.CONVEYOR_MODE === "workbench") {
|
|
|
1291
1265
|
process.exit(1);
|
|
1292
1266
|
}
|
|
1293
1267
|
const pkgDir = dirname(fileURLToPath(import.meta.url));
|
|
1294
|
-
const pkg = JSON.parse(readFileSync(
|
|
1268
|
+
const pkg = JSON.parse(readFileSync(join(pkgDir, "..", "package.json"), "utf-8"));
|
|
1295
1269
|
const handle = await startWorkbenchServer({
|
|
1296
1270
|
port,
|
|
1297
1271
|
token,
|
|
@@ -1423,7 +1397,7 @@ if (!RUNNER_MODES.includes(CONVEYOR_MODE)) {
|
|
|
1423
1397
|
process.exit(1);
|
|
1424
1398
|
}
|
|
1425
1399
|
if (CONVEYOR_MODE === "serving") {
|
|
1426
|
-
const { runServingSession } = await import("./serve-boot-
|
|
1400
|
+
const { runServingSession } = await import("./serve-boot-4QBD4LW4.js");
|
|
1427
1401
|
exitContext.runnerMode = "serving";
|
|
1428
1402
|
exitContext.sessionId = process.env.CONVEYOR_SESSION_ID ?? exitContext.sessionId;
|
|
1429
1403
|
const outcome = await runServingSession({
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SessionRunner,
|
|
3
3
|
unshallowRepo
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-RNE3JAF5.js";
|
|
5
5
|
import "./chunk-V5WR2F2P.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-SXZS2R52.js";
|
|
7
7
|
import {
|
|
8
8
|
AgentConnection,
|
|
9
9
|
GIT_TIMEOUT_MS,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
stageAndCommit,
|
|
18
18
|
updateRemoteToken,
|
|
19
19
|
workspacePathExists
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-O3MXZHIS.js";
|
|
21
21
|
import "./chunk-VIUZS7V4.js";
|
|
22
22
|
import {
|
|
23
23
|
runAuthTokenCommand,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
WorkspaceCommandSupervisor
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-K35YJK2U.js";
|
|
4
4
|
import {
|
|
5
5
|
AgentConnection,
|
|
6
6
|
DEFAULT_LIFECYCLE_CONFIG,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
ensureOnTaskBranch,
|
|
12
12
|
loadAndAnnotateDiscoveredPorts,
|
|
13
13
|
loadConveyorConfig
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-O3MXZHIS.js";
|
|
15
15
|
import "./chunk-VIUZS7V4.js";
|
|
16
16
|
import "./chunk-W4LZ7R6Z.js";
|
|
17
17
|
import "./chunk-IA45XHOA.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rallycry/conveyor-agent",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.0.49",
|
|
4
4
|
"description": "Conveyor Agent Runner v10 - PTY harness for the task chat (SDK harness for audit/project-chat). Agent-as-User architecture with BaseService patterns. Works locally too.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"test:watch": "vitest",
|
|
35
35
|
"lint": "oxlint -c ../../.oxlintrc.json src",
|
|
36
36
|
"lint:fix": "oxlint -c ../../.oxlintrc.json --fix src",
|
|
37
|
-
"typecheck": "
|
|
37
|
+
"typecheck": "bash ../../scripts/typecheck.sh"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@anthropic-ai/claude-agent-sdk": "^0.3.284",
|