@osfactory/har 0.64.1 → 0.64.3
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/index.js +725 -480
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -593,8 +593,8 @@ var init_parseUtil = __esm({
|
|
|
593
593
|
init_errors();
|
|
594
594
|
init_en();
|
|
595
595
|
makeIssue = (params) => {
|
|
596
|
-
const { data, path:
|
|
597
|
-
const fullPath = [...
|
|
596
|
+
const { data, path: path69, errorMaps, issueData } = params;
|
|
597
|
+
const fullPath = [...path69, ...issueData.path || []];
|
|
598
598
|
const fullIssue = {
|
|
599
599
|
...issueData,
|
|
600
600
|
path: fullPath
|
|
@@ -902,11 +902,11 @@ var init_types = __esm({
|
|
|
902
902
|
init_parseUtil();
|
|
903
903
|
init_util();
|
|
904
904
|
ParseInputLazyPath = class {
|
|
905
|
-
constructor(parent, value,
|
|
905
|
+
constructor(parent, value, path69, key) {
|
|
906
906
|
this._cachedPath = [];
|
|
907
907
|
this.parent = parent;
|
|
908
908
|
this.data = value;
|
|
909
|
-
this._path =
|
|
909
|
+
this._path = path69;
|
|
910
910
|
this._key = key;
|
|
911
911
|
}
|
|
912
912
|
get path() {
|
|
@@ -4288,7 +4288,7 @@ var init_zod = __esm({
|
|
|
4288
4288
|
});
|
|
4289
4289
|
|
|
4290
4290
|
// packages/schemas/src/schema.ts
|
|
4291
|
-
var HAR_STAGE_KINDS, HAR_AGENT_SLOT_MIN, AgentSkillTargetSchema, ScaffoldedAgentFileSchema, HarnessManifestSchema, HarnessStageKindSchema, HarnessArtifactKindSchema, HarnessArtifactSchema, HarnessStageIdSchema, HarnessStageSchema, HarnessAgentSlotsSchema, CommitGateConfigSchema, OnboardingPreferencesSchema, HarnessStageRegistrySchema, HarnessVerificationStepSchema, ShellRunOutputSchema, HarnessVerificationResultSchema, HarnessStageRunStatusSchema, HarnessStageLogSchema, HarnessStageUrlSchema, HarnessStageRunResultSchema, StageKindSchema, VerificationResultSchema, StageResultSchema, RunRecordTriggerSchema, WorkUnitIdSchema, WorkAttemptIdSchema, WorkUnitRelatedLinkSchema, WorkUnitMetadataSchema, WorkUnitOutcomeSchema, WorkUnitRecordSchema, WorkAttemptRecordSchema, RunRecordSchema, SlotRegistryEntrySchema, AgentSlotHarnessUsageSchema, PreflightBlockerSchema, SlotReadinessSchema, AgentSlotStatusSchema, EnvironmentStatusSchema, RegisterRepoInputSchema, UnregisterRepoInputSchema, UnregisterWorktreeResultSchema, UnregisterRepoResultSchema, ResetMissionControlInputSchema, HarnessScrubResultSchema, ResetMissionControlResultSchema, DeleteWorktreesInputSchema, DeleteWorktreeResultSchema, DeleteWorktreesResultSchema, SyncRunsInputSchema, SyncSlotsInputSchema, SyncWorkUnitsInputSchema, ChangedFileStatusSchema, ChangedFileSchema, ValidationRecordSchema, SyncValidationsInputSchema, ValidationBindingRecordSchema, SyncValidationBindingsInputSchema, AgentToolSchema, UsageSourceSchema, AgentTrajectorySourceSchema, AgentTrajectoryContentDisclosureSchema, AgentTrajectoryRecordV1Schema, AgentTrajectoryRecordSchema, AgentSessionUsageSchema, SyncUsageInputSchema, AgentSessionEventSchema, SyncSessionEventsInputSchema;
|
|
4291
|
+
var HAR_STAGE_KINDS, HAR_AGENT_SLOT_MIN, AgentSkillTargetSchema, ScaffoldedAgentFileSchema, HarnessManifestSchema, HarnessStageKindSchema, HarnessArtifactKindSchema, HarnessArtifactSchema, HarnessStageIdSchema, HarnessStageSchema, HarnessAgentSlotsSchema, CommitGateConfigSchema, OnboardingPreferencesSchema, HarnessStageRegistrySchema, HarnessVerificationStepSchema, ShellRunOutputSchema, HarnessVerificationResultSchema, HarnessStageRunStatusSchema, HarnessStageLogSchema, HarnessStageUrlSchema, HarnessStageRunResultSchema, StageKindSchema, VerificationResultSchema, StageResultSchema, RunRecordTriggerSchema, WorkUnitIdSchema, WorkAttemptIdSchema, WorkUnitRelatedLinkSchema, WorkUnitMetadataSchema, WorkUnitOutcomeSchema, WorkUnitRecordSchema, WorkAttemptRecordSchema, RunRecordSchema, SlotRegistryEntrySchema, AgentSlotHarnessUsageSchema, PreflightBlockerSchema, SlotReadinessSchema, AgentSlotStatusSchema, EnvironmentStatusSchema, RegisterRepoInputSchema, UnregisterRepoInputSchema, UnregisterWorktreeResultSchema, UnregisterRepoResultSchema, ResetMissionControlInputSchema, HarnessScrubResultSchema, ResetMissionControlResultSchema, DeleteWorktreesInputSchema, DeleteWorktreeResultSchema, DeleteWorktreesResultSchema, SyncRunsInputSchema, SyncSlotsInputSchema, SyncWorkUnitsInputSchema, ChangedFileStatusSchema, ChangedFileSchema, ValidationRecordSchema, SyncValidationsInputSchema, ValidationBindingRecordSchema, SyncValidationBindingsInputSchema, AgentToolSchema, UsageSourceSchema, AgentTrajectorySourceSchema, AgentTrajectoryContentDisclosureSchema, AgentTrajectoryRecordV1Schema, AgentTrajectoryRecordSchema, USAGE_HARVEST_VERSION, PRE_DEDUPE_HARVEST_VERSION, AgentSessionUsageSchema, SyncUsageInputSchema, AgentSessionEventSchema, SyncSessionEventsInputSchema;
|
|
4292
4292
|
var init_schema = __esm({
|
|
4293
4293
|
"packages/schemas/src/schema.ts"() {
|
|
4294
4294
|
"use strict";
|
|
@@ -4774,6 +4774,8 @@ var init_schema = __esm({
|
|
|
4774
4774
|
attemptId: WorkAttemptIdSchema.optional()
|
|
4775
4775
|
}).passthrough();
|
|
4776
4776
|
AgentTrajectoryRecordSchema = AgentTrajectoryRecordV1Schema;
|
|
4777
|
+
USAGE_HARVEST_VERSION = 2;
|
|
4778
|
+
PRE_DEDUPE_HARVEST_VERSION = 0;
|
|
4777
4779
|
AgentSessionUsageSchema = external_exports.object({
|
|
4778
4780
|
sessionKey: external_exports.string().min(1),
|
|
4779
4781
|
agentId: external_exports.number().int().min(HAR_AGENT_SLOT_MIN),
|
|
@@ -4792,6 +4794,7 @@ var init_schema = __esm({
|
|
|
4792
4794
|
costUsd: external_exports.number().nonnegative().nullable().optional(),
|
|
4793
4795
|
modelBreakdown: external_exports.record(external_exports.unknown()).optional(),
|
|
4794
4796
|
sources: external_exports.array(UsageSourceSchema).default([]),
|
|
4797
|
+
harvestVersion: external_exports.number().int().nonnegative().default(PRE_DEDUPE_HARVEST_VERSION),
|
|
4795
4798
|
firstSeenAt: external_exports.string(),
|
|
4796
4799
|
lastSeenAt: external_exports.string()
|
|
4797
4800
|
});
|
|
@@ -4819,6 +4822,31 @@ var init_schema = __esm({
|
|
|
4819
4822
|
}
|
|
4820
4823
|
});
|
|
4821
4824
|
|
|
4825
|
+
// packages/schemas/src/usage-authority.ts
|
|
4826
|
+
function usageHarvestVersion(row) {
|
|
4827
|
+
const version2 = Number(row?.harvestVersion ?? PRE_DEDUPE_HARVEST_VERSION);
|
|
4828
|
+
return Number.isFinite(version2) && version2 > 0 ? Math.floor(version2) : PRE_DEDUPE_HARVEST_VERSION;
|
|
4829
|
+
}
|
|
4830
|
+
function includesSource(row, source) {
|
|
4831
|
+
return (row?.sources ?? []).includes(source);
|
|
4832
|
+
}
|
|
4833
|
+
function harvestSupersedes(existing, incoming) {
|
|
4834
|
+
if (!existing || !incoming) return false;
|
|
4835
|
+
if (includesSource(existing, "otel") || includesSource(incoming, "otel")) return false;
|
|
4836
|
+
return usageHarvestVersion(incoming) > usageHarvestVersion(existing);
|
|
4837
|
+
}
|
|
4838
|
+
function mergedHarvestVersion(existing, incoming) {
|
|
4839
|
+
if (!includesSource(existing, "harvest")) return usageHarvestVersion(incoming);
|
|
4840
|
+
if (!includesSource(incoming, "harvest")) return usageHarvestVersion(existing);
|
|
4841
|
+
return Math.min(usageHarvestVersion(existing), usageHarvestVersion(incoming));
|
|
4842
|
+
}
|
|
4843
|
+
var init_usage_authority = __esm({
|
|
4844
|
+
"packages/schemas/src/usage-authority.ts"() {
|
|
4845
|
+
"use strict";
|
|
4846
|
+
init_schema();
|
|
4847
|
+
}
|
|
4848
|
+
});
|
|
4849
|
+
|
|
4822
4850
|
// node_modules/@pydantic/genai-prices/dist/index.js
|
|
4823
4851
|
function h() {
|
|
4824
4852
|
return U;
|
|
@@ -28215,10 +28243,8 @@ function toGenaiPricesUsage(totals) {
|
|
|
28215
28243
|
const rawInput = num(totals.tokensInput);
|
|
28216
28244
|
const cacheRead = num(totals.tokensCacheRead);
|
|
28217
28245
|
const cacheWrite = num(totals.tokensCacheCreation);
|
|
28218
|
-
const uncached = rawInput >= cacheRead ? rawInput - cacheRead : rawInput;
|
|
28219
|
-
const inclusiveInput = uncached + cacheRead + cacheWrite;
|
|
28220
28246
|
return {
|
|
28221
|
-
input_tokens:
|
|
28247
|
+
input_tokens: rawInput + cacheRead + cacheWrite,
|
|
28222
28248
|
output_tokens: num(totals.tokensOutput),
|
|
28223
28249
|
cache_read_tokens: cacheRead,
|
|
28224
28250
|
cache_write_tokens: cacheWrite
|
|
@@ -28294,6 +28320,7 @@ var init_schema2 = __esm({
|
|
|
28294
28320
|
"src/harness/schema.ts"() {
|
|
28295
28321
|
"use strict";
|
|
28296
28322
|
init_schema();
|
|
28323
|
+
init_usage_authority();
|
|
28297
28324
|
init_usage_pricing();
|
|
28298
28325
|
}
|
|
28299
28326
|
});
|
|
@@ -28704,7 +28731,7 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
|
|
|
28704
28731
|
const stream = options.stream ?? false;
|
|
28705
28732
|
const echoStdout = stream && (options.streamStdout ?? true);
|
|
28706
28733
|
const { stream: _stream, streamStdout: _streamStdout, ...spawnOptions } = options;
|
|
28707
|
-
return new Promise((
|
|
28734
|
+
return new Promise((resolve52) => {
|
|
28708
28735
|
const proc = (0, import_child_process.spawn)("bash", [scriptPath, ...args], {
|
|
28709
28736
|
...spawnOptions,
|
|
28710
28737
|
stdio: ["inherit", "pipe", "pipe"]
|
|
@@ -28719,14 +28746,14 @@ function runScriptCapture(scriptPath, args = [], options = {}) {
|
|
|
28719
28746
|
stderr += d;
|
|
28720
28747
|
if (stream) process.stderr.write(d);
|
|
28721
28748
|
});
|
|
28722
|
-
proc.on("close", (code) =>
|
|
28749
|
+
proc.on("close", (code) => resolve52({ stdout, stderr, code: code ?? 0 }));
|
|
28723
28750
|
});
|
|
28724
28751
|
}
|
|
28725
28752
|
function runShellCommand(command2, options = {}) {
|
|
28726
28753
|
const stream = options.stream ?? false;
|
|
28727
28754
|
const echoStdout = stream && (options.streamStdout ?? true);
|
|
28728
28755
|
const { stream: _stream, streamStdout: _streamStdout, ...spawnOptions } = options;
|
|
28729
|
-
return new Promise((
|
|
28756
|
+
return new Promise((resolve52) => {
|
|
28730
28757
|
const proc = (0, import_child_process.spawn)("bash", ["-lc", command2], {
|
|
28731
28758
|
...spawnOptions,
|
|
28732
28759
|
stdio: ["inherit", "pipe", "pipe"]
|
|
@@ -28741,7 +28768,7 @@ function runShellCommand(command2, options = {}) {
|
|
|
28741
28768
|
stderr += d;
|
|
28742
28769
|
if (stream) process.stderr.write(d);
|
|
28743
28770
|
});
|
|
28744
|
-
proc.on("close", (code) =>
|
|
28771
|
+
proc.on("close", (code) => resolve52({ stdout, stderr, code: code ?? 0 }));
|
|
28745
28772
|
});
|
|
28746
28773
|
}
|
|
28747
28774
|
var import_child_process;
|
|
@@ -31541,17 +31568,17 @@ function listWorkUnits(harnessRoot) {
|
|
|
31541
31568
|
).sort((a, b2) => b2.updatedAt.localeCompare(a.updatedAt));
|
|
31542
31569
|
}
|
|
31543
31570
|
function createWorkAttempt(harnessRoot, input) {
|
|
31544
|
-
const
|
|
31571
|
+
const attempt2 = WorkAttemptRecordSchema.parse({
|
|
31545
31572
|
...input,
|
|
31546
31573
|
version: 1,
|
|
31547
31574
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
31548
31575
|
});
|
|
31549
31576
|
ensureWorkEvidenceIgnored(harnessRoot);
|
|
31550
31577
|
writeRecord2(
|
|
31551
|
-
hashedRecordPath(harnessRoot, WORK_ATTEMPTS_DIR,
|
|
31552
|
-
|
|
31578
|
+
hashedRecordPath(harnessRoot, WORK_ATTEMPTS_DIR, attempt2.attemptId),
|
|
31579
|
+
attempt2
|
|
31553
31580
|
);
|
|
31554
|
-
return
|
|
31581
|
+
return attempt2;
|
|
31555
31582
|
}
|
|
31556
31583
|
function listWorkAttempts(harnessRoot) {
|
|
31557
31584
|
return listRecords(
|
|
@@ -32285,6 +32312,33 @@ var init_workspace_path_match = __esm({
|
|
|
32285
32312
|
}
|
|
32286
32313
|
});
|
|
32287
32314
|
|
|
32315
|
+
// src/core/usage-harvest/record-time-range.ts
|
|
32316
|
+
function recordTimestamp(record2) {
|
|
32317
|
+
if (!record2 || typeof record2 !== "object") return null;
|
|
32318
|
+
const payload = record2;
|
|
32319
|
+
const raw = typeof payload.timestamp === "string" ? payload.timestamp : payload.ts;
|
|
32320
|
+
if (typeof raw !== "string") return null;
|
|
32321
|
+
const ms = Date.parse(raw);
|
|
32322
|
+
return Number.isFinite(ms) ? ms : null;
|
|
32323
|
+
}
|
|
32324
|
+
function recordTimeRange(records) {
|
|
32325
|
+
let first = null;
|
|
32326
|
+
let last = null;
|
|
32327
|
+
for (const record2 of records) {
|
|
32328
|
+
const ms = recordTimestamp(record2);
|
|
32329
|
+
if (ms === null) continue;
|
|
32330
|
+
if (first === null || ms < first) first = ms;
|
|
32331
|
+
if (last === null || ms > last) last = ms;
|
|
32332
|
+
}
|
|
32333
|
+
if (first === null || last === null) return null;
|
|
32334
|
+
return { firstAt: new Date(first).toISOString(), lastAt: new Date(last).toISOString() };
|
|
32335
|
+
}
|
|
32336
|
+
var init_record_time_range = __esm({
|
|
32337
|
+
"src/core/usage-harvest/record-time-range.ts"() {
|
|
32338
|
+
"use strict";
|
|
32339
|
+
}
|
|
32340
|
+
});
|
|
32341
|
+
|
|
32288
32342
|
// src/core/usage-harvest/claude.ts
|
|
32289
32343
|
function claudeProjectsRoot() {
|
|
32290
32344
|
return process.env.HAR_CLAUDE_PROJECTS_DIR ? path25.resolve(process.env.HAR_CLAUDE_PROJECTS_DIR) : path25.join(os11.homedir(), ".claude", "projects");
|
|
@@ -32311,8 +32365,12 @@ function extractClaudeUsageFromRecords(records) {
|
|
|
32311
32365
|
let tokensOutput = 0;
|
|
32312
32366
|
let tokensCacheRead = 0;
|
|
32313
32367
|
let tokensCacheCreation = 0;
|
|
32314
|
-
let costUsd = null;
|
|
32315
32368
|
const modelBreakdown = {};
|
|
32369
|
+
let resultInput = 0;
|
|
32370
|
+
let resultOutput = 0;
|
|
32371
|
+
let resultCacheRead = 0;
|
|
32372
|
+
let resultCacheCreation = 0;
|
|
32373
|
+
let resultCostUsd = null;
|
|
32316
32374
|
const billed = /* @__PURE__ */ new Map();
|
|
32317
32375
|
const unkeyed = [];
|
|
32318
32376
|
for (const record2 of records) {
|
|
@@ -32320,11 +32378,13 @@ function extractClaudeUsageFromRecords(records) {
|
|
|
32320
32378
|
const payload = record2;
|
|
32321
32379
|
if (payload.type === "result") {
|
|
32322
32380
|
const usage2 = payload.usage ?? {};
|
|
32323
|
-
|
|
32324
|
-
|
|
32325
|
-
|
|
32326
|
-
|
|
32327
|
-
if (payload.total_cost_usd != null)
|
|
32381
|
+
resultInput += Number(usage2.input_tokens ?? 0);
|
|
32382
|
+
resultOutput += Number(usage2.output_tokens ?? 0);
|
|
32383
|
+
resultCacheRead += Number(usage2.cache_read_input_tokens ?? 0);
|
|
32384
|
+
resultCacheCreation += Number(usage2.cache_creation_input_tokens ?? 0);
|
|
32385
|
+
if (payload.total_cost_usd != null) {
|
|
32386
|
+
resultCostUsd = (resultCostUsd ?? 0) + Number(payload.total_cost_usd);
|
|
32387
|
+
}
|
|
32328
32388
|
}
|
|
32329
32389
|
const message = payload.message;
|
|
32330
32390
|
const nestedUsage = payload.usage ?? message?.usage;
|
|
@@ -32359,7 +32419,21 @@ function extractClaudeUsageFromRecords(records) {
|
|
|
32359
32419
|
totals.tokensTotal += i + o + cr + cc;
|
|
32360
32420
|
}
|
|
32361
32421
|
}
|
|
32362
|
-
|
|
32422
|
+
const resultTotal = resultInput + resultOutput + resultCacheRead + resultCacheCreation;
|
|
32423
|
+
if (resultTotal > 0) {
|
|
32424
|
+
tokensInput = resultInput;
|
|
32425
|
+
tokensOutput = resultOutput;
|
|
32426
|
+
tokensCacheRead = resultCacheRead;
|
|
32427
|
+
tokensCacheCreation = resultCacheCreation;
|
|
32428
|
+
}
|
|
32429
|
+
return {
|
|
32430
|
+
tokensInput,
|
|
32431
|
+
tokensOutput,
|
|
32432
|
+
tokensCacheRead,
|
|
32433
|
+
tokensCacheCreation,
|
|
32434
|
+
costUsd: resultCostUsd,
|
|
32435
|
+
modelBreakdown
|
|
32436
|
+
};
|
|
32363
32437
|
}
|
|
32364
32438
|
function findMatchingClaudeTranscripts(slot) {
|
|
32365
32439
|
const primaryTargets = [slot.workDir, slot.worktreePath].filter(Boolean);
|
|
@@ -32456,11 +32530,13 @@ function harvestClaudeUsage(slot) {
|
|
|
32456
32530
|
});
|
|
32457
32531
|
const own = matches.filter((match) => match.primary);
|
|
32458
32532
|
const usable = own.length > 0 ? own : matches;
|
|
32459
|
-
const
|
|
32533
|
+
const records = usable.flatMap((match) => match.records);
|
|
32534
|
+
const usage2 = extractClaudeUsageFromRecords(records);
|
|
32460
32535
|
if (usage2.tokensInput + usage2.tokensOutput + usage2.tokensCacheRead === 0 && (usage2.costUsd == null || usage2.costUsd === 0)) {
|
|
32461
32536
|
return null;
|
|
32462
32537
|
}
|
|
32463
32538
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
32539
|
+
const seen = recordTimeRange(records);
|
|
32464
32540
|
const tokensTotal = usage2.tokensInput + usage2.tokensOutput + usage2.tokensCacheRead + usage2.tokensCacheCreation;
|
|
32465
32541
|
return {
|
|
32466
32542
|
sessionKey,
|
|
@@ -32477,8 +32553,9 @@ function harvestClaudeUsage(slot) {
|
|
|
32477
32553
|
costUsd: usage2.costUsd,
|
|
32478
32554
|
...Object.keys(usage2.modelBreakdown).length > 0 ? { modelBreakdown: usage2.modelBreakdown } : {},
|
|
32479
32555
|
sources: ["harvest"],
|
|
32480
|
-
|
|
32481
|
-
|
|
32556
|
+
harvestVersion: USAGE_HARVEST_VERSION,
|
|
32557
|
+
firstSeenAt: seen?.firstAt ?? slot.sessionCreatedAt ?? now,
|
|
32558
|
+
lastSeenAt: seen?.lastAt ?? now
|
|
32482
32559
|
};
|
|
32483
32560
|
}
|
|
32484
32561
|
function harvestClaudeEvents(slot) {
|
|
@@ -32500,9 +32577,11 @@ var init_claude = __esm({
|
|
|
32500
32577
|
fs23 = __toESM(require("fs"));
|
|
32501
32578
|
os11 = __toESM(require("os"));
|
|
32502
32579
|
path25 = __toESM(require("path"));
|
|
32580
|
+
init_schema2();
|
|
32503
32581
|
init_telemetry_config();
|
|
32504
32582
|
init_telemetry_env();
|
|
32505
32583
|
init_workspace_path_match();
|
|
32584
|
+
init_record_time_range();
|
|
32506
32585
|
}
|
|
32507
32586
|
});
|
|
32508
32587
|
|
|
@@ -32563,7 +32642,7 @@ function extractCodexTokens(records) {
|
|
|
32563
32642
|
tokensCacheRead = Math.max(tokensCacheRead, Number(payload.cached_token_count ?? 0));
|
|
32564
32643
|
}
|
|
32565
32644
|
}
|
|
32566
|
-
return { tokensInput, tokensOutput, tokensCacheRead, cwd };
|
|
32645
|
+
return { tokensInput, tokensOutput, tokensCacheRead, cwd, seen: recordTimeRange(records) };
|
|
32567
32646
|
}
|
|
32568
32647
|
function harvestCodexUsage(slot) {
|
|
32569
32648
|
const primaryTargets = [slot.workDir, slot.worktreePath].filter(Boolean);
|
|
@@ -32618,8 +32697,9 @@ function harvestCodexUsage(slot) {
|
|
|
32618
32697
|
tokensTotal,
|
|
32619
32698
|
costUsd: null,
|
|
32620
32699
|
sources: ["harvest"],
|
|
32621
|
-
|
|
32622
|
-
|
|
32700
|
+
harvestVersion: USAGE_HARVEST_VERSION,
|
|
32701
|
+
firstSeenAt: best.seen?.firstAt ?? slot.sessionCreatedAt ?? now,
|
|
32702
|
+
lastSeenAt: best.seen?.lastAt ?? now
|
|
32623
32703
|
};
|
|
32624
32704
|
}
|
|
32625
32705
|
var fs24, os12, path26;
|
|
@@ -32629,8 +32709,10 @@ var init_codex = __esm({
|
|
|
32629
32709
|
fs24 = __toESM(require("fs"));
|
|
32630
32710
|
os12 = __toESM(require("os"));
|
|
32631
32711
|
path26 = __toESM(require("path"));
|
|
32712
|
+
init_schema2();
|
|
32632
32713
|
init_telemetry_env();
|
|
32633
32714
|
init_workspace_path_match();
|
|
32715
|
+
init_record_time_range();
|
|
32634
32716
|
}
|
|
32635
32717
|
});
|
|
32636
32718
|
|
|
@@ -32758,25 +32840,85 @@ var init_portal_watermark = __esm({
|
|
|
32758
32840
|
}
|
|
32759
32841
|
});
|
|
32760
32842
|
|
|
32761
|
-
// src/core/control-
|
|
32762
|
-
|
|
32843
|
+
// src/core/control-api-read.ts
|
|
32844
|
+
function numberFromEnv(name, fallback) {
|
|
32845
|
+
const raw = Number(process.env[name]);
|
|
32846
|
+
return Number.isFinite(raw) && raw > 0 ? raw : fallback;
|
|
32847
|
+
}
|
|
32848
|
+
async function attempt(url) {
|
|
32763
32849
|
try {
|
|
32764
32850
|
const response = await fetch(url, {
|
|
32765
32851
|
method: "GET",
|
|
32766
|
-
signal: AbortSignal.timeout(
|
|
32852
|
+
signal: AbortSignal.timeout(numberFromEnv("HAR_CONTROL_READ_TIMEOUT_MS", DEFAULT_TIMEOUT_MS))
|
|
32767
32853
|
});
|
|
32768
|
-
if (!response.ok)
|
|
32769
|
-
|
|
32770
|
-
|
|
32771
|
-
|
|
32772
|
-
|
|
32854
|
+
if (!response.ok) {
|
|
32855
|
+
return {
|
|
32856
|
+
read: { ok: false, error: `HTTP ${response.status}` },
|
|
32857
|
+
retryable: response.status >= 500
|
|
32858
|
+
};
|
|
32859
|
+
}
|
|
32860
|
+
return { read: { ok: true, data: await response.json() }, retryable: false };
|
|
32861
|
+
} catch (err) {
|
|
32862
|
+
return {
|
|
32863
|
+
read: { ok: false, error: err instanceof Error ? err.message : String(err) },
|
|
32864
|
+
retryable: true
|
|
32865
|
+
};
|
|
32866
|
+
}
|
|
32867
|
+
}
|
|
32868
|
+
async function readControlJson(url) {
|
|
32869
|
+
const first = await attempt(url);
|
|
32870
|
+
if (first.read.ok || !first.retryable) return first.read;
|
|
32871
|
+
await new Promise((resolve52) => setTimeout(resolve52, RETRY_DELAY_MS));
|
|
32872
|
+
return (await attempt(url)).read;
|
|
32873
|
+
}
|
|
32874
|
+
async function readControlPages(options) {
|
|
32875
|
+
const limit = numberFromEnv("HAR_CONTROL_READ_PAGE_SIZE", DEFAULT_PAGE_SIZE);
|
|
32876
|
+
const collected = [];
|
|
32877
|
+
let since = options.since;
|
|
32878
|
+
let sinceId = null;
|
|
32879
|
+
for (let page = 0; page < MAX_PAGES; page++) {
|
|
32880
|
+
const query = new URLSearchParams({ limit: String(limit) });
|
|
32881
|
+
if (since) query.set("since", since);
|
|
32882
|
+
if (sinceId) query.set("sinceId", sinceId);
|
|
32883
|
+
const read = await readControlJson(`${options.url}?${query.toString()}`);
|
|
32884
|
+
if (!read.ok) return { ok: false, error: read.error };
|
|
32885
|
+
const rows = options.rows(read.data);
|
|
32886
|
+
collected.push(...rows);
|
|
32887
|
+
if (rows.length < limit) return { ok: true, rows: collected, truncated: false };
|
|
32888
|
+
const last = options.cursor(rows[rows.length - 1]);
|
|
32889
|
+
const nextSince = last.createdAt ?? null;
|
|
32890
|
+
const nextSinceId = last.id ?? null;
|
|
32891
|
+
if (!nextSince || nextSince === since && nextSinceId === sinceId) {
|
|
32892
|
+
return { ok: true, rows: collected, truncated: false };
|
|
32893
|
+
}
|
|
32894
|
+
since = nextSince;
|
|
32895
|
+
sinceId = nextSinceId;
|
|
32896
|
+
}
|
|
32897
|
+
return { ok: true, rows: collected, truncated: true };
|
|
32773
32898
|
}
|
|
32774
32899
|
async function resolveControlRepoId(apiUrl, repoPath) {
|
|
32775
|
-
const repos = await
|
|
32776
|
-
if (!
|
|
32900
|
+
const repos = await readControlJson(`${apiUrl}/api/repos`);
|
|
32901
|
+
if (!repos.ok) return repos;
|
|
32902
|
+
if (!Array.isArray(repos.data)) return { ok: false, error: "unexpected /api/repos payload" };
|
|
32777
32903
|
const target = path28.resolve(repoPath);
|
|
32778
|
-
return
|
|
32904
|
+
return {
|
|
32905
|
+
ok: true,
|
|
32906
|
+
data: repos.data.find((repo) => path28.resolve(repo.path) === target)?.id ?? null
|
|
32907
|
+
};
|
|
32779
32908
|
}
|
|
32909
|
+
var path28, DEFAULT_TIMEOUT_MS, RETRY_DELAY_MS, DEFAULT_PAGE_SIZE, MAX_PAGES;
|
|
32910
|
+
var init_control_api_read = __esm({
|
|
32911
|
+
"src/core/control-api-read.ts"() {
|
|
32912
|
+
"use strict";
|
|
32913
|
+
path28 = __toESM(require("path"));
|
|
32914
|
+
DEFAULT_TIMEOUT_MS = 1e4;
|
|
32915
|
+
RETRY_DELAY_MS = 250;
|
|
32916
|
+
DEFAULT_PAGE_SIZE = 1e3;
|
|
32917
|
+
MAX_PAGES = 20;
|
|
32918
|
+
}
|
|
32919
|
+
});
|
|
32920
|
+
|
|
32921
|
+
// src/core/control-persisted-usage.ts
|
|
32780
32922
|
function optionalString(value) {
|
|
32781
32923
|
return value == null ? void 0 : value;
|
|
32782
32924
|
}
|
|
@@ -32802,6 +32944,7 @@ function normalizeUsage(row) {
|
|
|
32802
32944
|
costUsd: row.costUsd == null ? null : Number(row.costUsd),
|
|
32803
32945
|
...row.modelBreakdown ? { modelBreakdown: row.modelBreakdown } : {},
|
|
32804
32946
|
sources: toSources(row.sources),
|
|
32947
|
+
harvestVersion: Number(row.harvestVersion ?? 0),
|
|
32805
32948
|
firstSeenAt: row.firstSeenAt,
|
|
32806
32949
|
lastSeenAt: row.lastSeenAt
|
|
32807
32950
|
};
|
|
@@ -32829,50 +32972,54 @@ function maxTimestamp(a, b2) {
|
|
|
32829
32972
|
return a > b2 ? a : b2;
|
|
32830
32973
|
}
|
|
32831
32974
|
async function fetchPersistedPortalTelemetry(repoPath, apiUrl, options) {
|
|
32832
|
-
const
|
|
32833
|
-
|
|
32975
|
+
const empty = { usage: [], events: [], maxSyncedAt: null, failures: [], truncated: [] };
|
|
32976
|
+
const repo = await resolveControlRepoId(apiUrl, repoPath);
|
|
32977
|
+
if (!repo.ok) {
|
|
32978
|
+
return { ...empty, failures: [{ channel: "repos", reason: repo.error }] };
|
|
32979
|
+
}
|
|
32980
|
+
if (!repo.data) return empty;
|
|
32834
32981
|
const since = options?.since ?? null;
|
|
32835
|
-
const [
|
|
32836
|
-
|
|
32837
|
-
|
|
32982
|
+
const [usageRead, eventsRead] = await Promise.all([
|
|
32983
|
+
readControlJson(`${apiUrl}/api/repos/${repo.data}/usage`),
|
|
32984
|
+
readControlPages({
|
|
32985
|
+
url: `${apiUrl}/api/repos/${repo.data}/events`,
|
|
32986
|
+
since,
|
|
32987
|
+
rows: (data) => data?.events ?? [],
|
|
32988
|
+
cursor: (row) => ({ createdAt: row.createdAt, id: row.id })
|
|
32989
|
+
})
|
|
32838
32990
|
]);
|
|
32839
|
-
const
|
|
32840
|
-
const
|
|
32991
|
+
const failures = [];
|
|
32992
|
+
const truncated = [];
|
|
32993
|
+
if (!usageRead.ok) failures.push({ channel: "usage", reason: usageRead.error });
|
|
32994
|
+
if (!eventsRead.ok) failures.push({ channel: "events", reason: eventsRead.error });
|
|
32995
|
+
else if (eventsRead.truncated) truncated.push("events");
|
|
32996
|
+
const usage2 = selectSince(
|
|
32997
|
+
usageRead.ok ? usageRead.data?.usage ?? [] : [],
|
|
32998
|
+
since,
|
|
32999
|
+
(row) => row.updatedAt ?? row.lastSeenAt
|
|
33000
|
+
);
|
|
33001
|
+
const events = selectSince(
|
|
33002
|
+
eventsRead.ok ? eventsRead.rows : [],
|
|
33003
|
+
since,
|
|
33004
|
+
(row) => row.createdAt ?? row.timestamp
|
|
33005
|
+
);
|
|
32841
33006
|
return {
|
|
32842
33007
|
usage: usage2.selected.map(normalizeUsage),
|
|
32843
33008
|
events: events.selected.map(normalizeEvent),
|
|
32844
|
-
maxSyncedAt: maxTimestamp(usage2.maxSyncedAt, events.maxSyncedAt)
|
|
33009
|
+
maxSyncedAt: maxTimestamp(usage2.maxSyncedAt, events.maxSyncedAt),
|
|
33010
|
+
failures,
|
|
33011
|
+
truncated
|
|
32845
33012
|
};
|
|
32846
33013
|
}
|
|
32847
|
-
var path28, FETCH_TIMEOUT_MS;
|
|
32848
33014
|
var init_control_persisted_usage = __esm({
|
|
32849
33015
|
"src/core/control-persisted-usage.ts"() {
|
|
32850
33016
|
"use strict";
|
|
32851
|
-
path28 = __toESM(require("path"));
|
|
32852
33017
|
init_portal_watermark();
|
|
32853
|
-
|
|
33018
|
+
init_control_api_read();
|
|
32854
33019
|
}
|
|
32855
33020
|
});
|
|
32856
33021
|
|
|
32857
33022
|
// src/core/control-persisted-trajectory.ts
|
|
32858
|
-
async function getJson2(url) {
|
|
32859
|
-
try {
|
|
32860
|
-
const response = await fetch(url, {
|
|
32861
|
-
method: "GET",
|
|
32862
|
-
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS2)
|
|
32863
|
-
});
|
|
32864
|
-
if (!response.ok) return null;
|
|
32865
|
-
return await response.json();
|
|
32866
|
-
} catch {
|
|
32867
|
-
return null;
|
|
32868
|
-
}
|
|
32869
|
-
}
|
|
32870
|
-
async function resolveControlRepoId2(apiUrl, repoPath) {
|
|
32871
|
-
const repos = await getJson2(`${apiUrl}/api/repos`);
|
|
32872
|
-
if (!Array.isArray(repos)) return null;
|
|
32873
|
-
const target = path29.resolve(repoPath);
|
|
32874
|
-
return repos.find((repo) => path29.resolve(repo.path) === target)?.id ?? null;
|
|
32875
|
-
}
|
|
32876
33023
|
function optional(value) {
|
|
32877
33024
|
return value == null ? void 0 : value;
|
|
32878
33025
|
}
|
|
@@ -32928,24 +33075,44 @@ async function fetchPersistedTrajectory(repoPath, apiUrl, request) {
|
|
|
32928
33075
|
records: [],
|
|
32929
33076
|
spans: [],
|
|
32930
33077
|
recordsMaxSyncedAt: null,
|
|
32931
|
-
spansMaxSyncedAt: null
|
|
33078
|
+
spansMaxSyncedAt: null,
|
|
33079
|
+
failures: [],
|
|
33080
|
+
truncated: []
|
|
32932
33081
|
};
|
|
32933
33082
|
if (!request.records && !request.spans) return empty;
|
|
32934
|
-
const
|
|
32935
|
-
if (!
|
|
32936
|
-
|
|
32937
|
-
|
|
32938
|
-
|
|
32939
|
-
|
|
32940
|
-
|
|
33083
|
+
const repo = await resolveControlRepoId(apiUrl, repoPath);
|
|
33084
|
+
if (!repo.ok) return { ...empty, failures: [{ channel: "repos", reason: repo.error }] };
|
|
33085
|
+
if (!repo.data) return empty;
|
|
33086
|
+
const [trajectoryRead, spansRead] = await Promise.all([
|
|
33087
|
+
request.records ? readControlPages({
|
|
33088
|
+
url: `${apiUrl}/api/repos/${repo.data}/trajectory`,
|
|
33089
|
+
since: request.records.since,
|
|
33090
|
+
rows: (data) => data?.records ?? [],
|
|
33091
|
+
cursor: (row) => ({ createdAt: row.createdAt, id: row.id })
|
|
33092
|
+
}) : null,
|
|
33093
|
+
request.spans ? readControlPages({
|
|
33094
|
+
url: `${apiUrl}/api/repos/${repo.data}/spans`,
|
|
33095
|
+
since: request.spans.since,
|
|
33096
|
+
rows: (data) => data?.spans ?? [],
|
|
33097
|
+
cursor: (row) => ({ createdAt: row.createdAt, id: row.id })
|
|
33098
|
+
}) : null
|
|
32941
33099
|
]);
|
|
33100
|
+
const failures = [];
|
|
33101
|
+
const truncated = [];
|
|
33102
|
+
if (trajectoryRead && !trajectoryRead.ok) {
|
|
33103
|
+
failures.push({ channel: "trajectory", reason: trajectoryRead.error });
|
|
33104
|
+
} else if (trajectoryRead?.ok && trajectoryRead.truncated) {
|
|
33105
|
+
truncated.push("trajectory");
|
|
33106
|
+
}
|
|
33107
|
+
if (spansRead && !spansRead.ok) failures.push({ channel: "spans", reason: spansRead.error });
|
|
33108
|
+
else if (spansRead?.ok && spansRead.truncated) truncated.push("spans");
|
|
32942
33109
|
const trajectory = selectSince(
|
|
32943
|
-
|
|
33110
|
+
trajectoryRead?.ok ? trajectoryRead.rows : [],
|
|
32944
33111
|
request.records ? request.records.since : null,
|
|
32945
33112
|
(row) => row.createdAt ?? null
|
|
32946
33113
|
);
|
|
32947
33114
|
const spans = selectSince(
|
|
32948
|
-
|
|
33115
|
+
spansRead?.ok ? spansRead.rows : [],
|
|
32949
33116
|
request.spans ? request.spans.since : null,
|
|
32950
33117
|
(row) => row.createdAt ?? null
|
|
32951
33118
|
);
|
|
@@ -32956,17 +33123,17 @@ async function fetchPersistedTrajectory(repoPath, apiUrl, request) {
|
|
|
32956
33123
|
}),
|
|
32957
33124
|
spans: spans.selected.map(toPortalSpan),
|
|
32958
33125
|
recordsMaxSyncedAt: trajectory.maxSyncedAt,
|
|
32959
|
-
spansMaxSyncedAt: spans.maxSyncedAt
|
|
33126
|
+
spansMaxSyncedAt: spans.maxSyncedAt,
|
|
33127
|
+
failures,
|
|
33128
|
+
truncated
|
|
32960
33129
|
};
|
|
32961
33130
|
}
|
|
32962
|
-
var path29, FETCH_TIMEOUT_MS2;
|
|
32963
33131
|
var init_control_persisted_trajectory = __esm({
|
|
32964
33132
|
"src/core/control-persisted-trajectory.ts"() {
|
|
32965
33133
|
"use strict";
|
|
32966
|
-
path29 = __toESM(require("path"));
|
|
32967
33134
|
init_schema2();
|
|
32968
33135
|
init_portal_watermark();
|
|
32969
|
-
|
|
33136
|
+
init_control_api_read();
|
|
32970
33137
|
}
|
|
32971
33138
|
});
|
|
32972
33139
|
|
|
@@ -33007,10 +33174,34 @@ function mergeModelBreakdown(a, b2) {
|
|
|
33007
33174
|
}
|
|
33008
33175
|
return out;
|
|
33009
33176
|
}
|
|
33010
|
-
function
|
|
33177
|
+
function replaceCounters(row) {
|
|
33178
|
+
return {
|
|
33179
|
+
tokensInput: num2(row.tokensInput),
|
|
33180
|
+
tokensOutput: num2(row.tokensOutput),
|
|
33181
|
+
tokensCacheRead: num2(row.tokensCacheRead),
|
|
33182
|
+
tokensCacheCreation: num2(row.tokensCacheCreation),
|
|
33183
|
+
tokensTotal: num2(row.tokensTotal),
|
|
33184
|
+
costUsd: row.costUsd ?? null,
|
|
33185
|
+
modelBreakdown: row.modelBreakdown,
|
|
33186
|
+
harvestVersion: usageHarvestVersion(row)
|
|
33187
|
+
};
|
|
33188
|
+
}
|
|
33189
|
+
function maxCounters(a, b2) {
|
|
33011
33190
|
const costA = a.costUsd ?? null;
|
|
33012
33191
|
const costB = b2.costUsd ?? null;
|
|
33013
|
-
|
|
33192
|
+
return {
|
|
33193
|
+
tokensInput: Math.max(num2(a.tokensInput), num2(b2.tokensInput)),
|
|
33194
|
+
tokensOutput: Math.max(num2(a.tokensOutput), num2(b2.tokensOutput)),
|
|
33195
|
+
tokensCacheRead: Math.max(num2(a.tokensCacheRead), num2(b2.tokensCacheRead)),
|
|
33196
|
+
tokensCacheCreation: Math.max(num2(a.tokensCacheCreation), num2(b2.tokensCacheCreation)),
|
|
33197
|
+
tokensTotal: Math.max(num2(a.tokensTotal), num2(b2.tokensTotal)),
|
|
33198
|
+
costUsd: costA != null || costB != null ? Math.max(num2(costA), num2(costB)) : a.costUsd ?? b2.costUsd,
|
|
33199
|
+
modelBreakdown: mergeModelBreakdown(a.modelBreakdown, b2.modelBreakdown),
|
|
33200
|
+
harvestVersion: mergedHarvestVersion(a, b2)
|
|
33201
|
+
};
|
|
33202
|
+
}
|
|
33203
|
+
function mergeUsageRow(a, b2) {
|
|
33204
|
+
const counters = harvestSupersedes(a, b2) ? replaceCounters(b2) : harvestSupersedes(b2, a) ? replaceCounters(a) : maxCounters(a, b2);
|
|
33014
33205
|
return {
|
|
33015
33206
|
...a,
|
|
33016
33207
|
...b2,
|
|
@@ -33019,13 +33210,7 @@ function mergeUsageRow(a, b2) {
|
|
|
33019
33210
|
suffix: b2.suffix ?? a.suffix,
|
|
33020
33211
|
workUnitId: b2.workUnitId ?? a.workUnitId,
|
|
33021
33212
|
attemptId: b2.attemptId ?? a.attemptId,
|
|
33022
|
-
|
|
33023
|
-
tokensOutput: Math.max(num2(a.tokensOutput), num2(b2.tokensOutput)),
|
|
33024
|
-
tokensCacheRead: Math.max(num2(a.tokensCacheRead), num2(b2.tokensCacheRead)),
|
|
33025
|
-
tokensCacheCreation: Math.max(num2(a.tokensCacheCreation), num2(b2.tokensCacheCreation)),
|
|
33026
|
-
tokensTotal: Math.max(num2(a.tokensTotal), num2(b2.tokensTotal)),
|
|
33027
|
-
costUsd,
|
|
33028
|
-
modelBreakdown: mergeModelBreakdown(a.modelBreakdown, b2.modelBreakdown),
|
|
33213
|
+
...counters,
|
|
33029
33214
|
sources: [.../* @__PURE__ */ new Set([...a.sources ?? [], ...b2.sources ?? []])],
|
|
33030
33215
|
firstSeenAt: earlier(a.firstSeenAt, b2.firstSeenAt),
|
|
33031
33216
|
lastSeenAt: later(a.lastSeenAt, b2.lastSeenAt)
|
|
@@ -33052,6 +33237,7 @@ var KEY_SEP;
|
|
|
33052
33237
|
var init_portal_usage_merge = __esm({
|
|
33053
33238
|
"src/core/portal-usage-merge.ts"() {
|
|
33054
33239
|
"use strict";
|
|
33240
|
+
init_schema2();
|
|
33055
33241
|
KEY_SEP = "\0";
|
|
33056
33242
|
}
|
|
33057
33243
|
});
|
|
@@ -33161,13 +33347,13 @@ function describeFetchFailure(url, bodyBytes, err) {
|
|
|
33161
33347
|
}
|
|
33162
33348
|
async function postForResponse(url, headers, payload) {
|
|
33163
33349
|
let lastErr;
|
|
33164
|
-
for (let
|
|
33350
|
+
for (let attempt2 = 1; attempt2 <= MAX_FETCH_ATTEMPTS; attempt2++) {
|
|
33165
33351
|
try {
|
|
33166
33352
|
return await fetch(url, { method: "POST", headers, body: payload });
|
|
33167
33353
|
} catch (err) {
|
|
33168
33354
|
lastErr = err;
|
|
33169
|
-
if (
|
|
33170
|
-
await new Promise((
|
|
33355
|
+
if (attempt2 < MAX_FETCH_ATTEMPTS) {
|
|
33356
|
+
await new Promise((resolve52) => setTimeout(resolve52, attempt2 * 100));
|
|
33171
33357
|
}
|
|
33172
33358
|
}
|
|
33173
33359
|
}
|
|
@@ -33262,8 +33448,17 @@ function modelsFromBreakdown(breakdown) {
|
|
|
33262
33448
|
...totals && typeof totals === "object" ? totals : {}
|
|
33263
33449
|
}));
|
|
33264
33450
|
}
|
|
33451
|
+
function describeReadFailures(repoPath, failures) {
|
|
33452
|
+
const detail = failures.map((f) => `${f.channel} (${f.reason})`).join(", ");
|
|
33453
|
+
return `${path29.basename(repoPath)}: could not read ${detail} from Mission Control \u2014 that telemetry is missing from this sync and its watermark is held, so the next sync retries it.`;
|
|
33454
|
+
}
|
|
33455
|
+
function describeTruncatedReads(repoPath, channels) {
|
|
33456
|
+
return `${path29.basename(repoPath)}: ${channels.join(", ")} hit the read page cap \u2014 the remainder syncs on the next run.`;
|
|
33457
|
+
}
|
|
33265
33458
|
async function collectPortalTelemetry(repoPath, slots, controlApiUrl, since, portal) {
|
|
33266
|
-
if (!isTelemetryEnabled())
|
|
33459
|
+
if (!isTelemetryEnabled()) {
|
|
33460
|
+
return { usage: [], events: [], maxSyncedAt: null, failures: [], truncated: [] };
|
|
33461
|
+
}
|
|
33267
33462
|
try {
|
|
33268
33463
|
const userEmail = resolvePortalUserEmail(portal);
|
|
33269
33464
|
const fallbackAgentId = slots.length > 0 ? Math.min(...slots.map((slot) => slot.agentId)) : null;
|
|
@@ -33322,9 +33517,23 @@ async function collectPortalTelemetry(repoPath, slots, controlApiUrl, since, por
|
|
|
33322
33517
|
const events = dedupePortalEvents(harvestedEvents, persisted.events).map(
|
|
33323
33518
|
(event) => dropNullFields({ ...event })
|
|
33324
33519
|
);
|
|
33325
|
-
return {
|
|
33326
|
-
|
|
33327
|
-
|
|
33520
|
+
return {
|
|
33521
|
+
usage: usage2,
|
|
33522
|
+
events,
|
|
33523
|
+
maxSyncedAt: persisted.maxSyncedAt,
|
|
33524
|
+
failures: persisted.failures,
|
|
33525
|
+
truncated: persisted.truncated
|
|
33526
|
+
};
|
|
33527
|
+
} catch (err) {
|
|
33528
|
+
return {
|
|
33529
|
+
usage: [],
|
|
33530
|
+
events: [],
|
|
33531
|
+
maxSyncedAt: null,
|
|
33532
|
+
failures: [
|
|
33533
|
+
{ channel: "telemetry", reason: err instanceof Error ? err.message : String(err) }
|
|
33534
|
+
],
|
|
33535
|
+
truncated: []
|
|
33536
|
+
};
|
|
33328
33537
|
}
|
|
33329
33538
|
}
|
|
33330
33539
|
async function buildPortalPayload(repoPath, controlApiUrl, since, full = false, portal) {
|
|
@@ -33338,16 +33547,16 @@ async function buildPortalPayload(repoPath, controlApiUrl, since, full = false,
|
|
|
33338
33547
|
const attempts = listWorkAttempts(harnessRoot);
|
|
33339
33548
|
const validationBindings = listValidationBindings(harnessRoot);
|
|
33340
33549
|
const userEmail = resolvePortalUserEmail(portal);
|
|
33341
|
-
const { usage: usage2, events, maxSyncedAt } = await collectPortalTelemetry(
|
|
33550
|
+
const { usage: usage2, events, maxSyncedAt, failures, truncated } = await collectPortalTelemetry(
|
|
33342
33551
|
repoPath,
|
|
33343
33552
|
status.slots,
|
|
33344
33553
|
controlApiUrl,
|
|
33345
33554
|
since,
|
|
33346
33555
|
portal
|
|
33347
33556
|
);
|
|
33348
|
-
if (full && isTelemetryEnabled() && usage2.length === 0 && runs.some((r) => r.agentId != null)) {
|
|
33557
|
+
if (full && isTelemetryEnabled() && failures.length === 0 && usage2.length === 0 && runs.some((r) => r.agentId != null)) {
|
|
33349
33558
|
warn(
|
|
33350
|
-
`${
|
|
33559
|
+
`${path29.basename(repoPath)}: agent runs found but no usage harvested \u2014 attribution will be missing. This happens when agent sessions ran outside the har worktree slot (e.g. in the main checkout). Run agents inside \`har env launch\`.`
|
|
33351
33560
|
);
|
|
33352
33561
|
}
|
|
33353
33562
|
const syncBody = {
|
|
@@ -33367,7 +33576,7 @@ async function buildPortalPayload(repoPath, controlApiUrl, since, full = false,
|
|
|
33367
33576
|
...usage2.length > 0 ? { usage: usage2 } : {}
|
|
33368
33577
|
};
|
|
33369
33578
|
const runsPayload = userEmail ? runs.map((run2) => ({ ...run2, userEmail })) : runs;
|
|
33370
|
-
return { syncBody, runs: runsPayload, events, maxSyncedAt };
|
|
33579
|
+
return { syncBody, runs: runsPayload, events, maxSyncedAt, failures, truncated };
|
|
33371
33580
|
}
|
|
33372
33581
|
async function isControlApiReachable(apiUrl = getControlApiUrl()) {
|
|
33373
33582
|
try {
|
|
@@ -33384,7 +33593,7 @@ async function waitForControlApi(apiUrl = getControlApiUrl(), timeoutMs = 6e4, i
|
|
|
33384
33593
|
const deadline = Date.now() + timeoutMs;
|
|
33385
33594
|
while (Date.now() < deadline) {
|
|
33386
33595
|
if (await isControlApiReachable(apiUrl)) return true;
|
|
33387
|
-
await new Promise((
|
|
33596
|
+
await new Promise((resolve52) => setTimeout(resolve52, intervalMs));
|
|
33388
33597
|
}
|
|
33389
33598
|
return false;
|
|
33390
33599
|
}
|
|
@@ -33401,13 +33610,14 @@ async function syncReposWithControl(options) {
|
|
|
33401
33610
|
const results = [];
|
|
33402
33611
|
let synced = 0;
|
|
33403
33612
|
let failed = 0;
|
|
33613
|
+
let incomplete = 0;
|
|
33404
33614
|
for (const repoPath of options.repoPaths) {
|
|
33405
33615
|
const destinationAliases = destinationAliasesForSync(repoPath, options.portalTargets);
|
|
33406
33616
|
if (destinationAliases.length > 1) {
|
|
33407
33617
|
const targetResults = [];
|
|
33408
33618
|
for (const alias of destinationAliases) {
|
|
33409
33619
|
try {
|
|
33410
|
-
await withTimeout(
|
|
33620
|
+
const outcome = await withTimeout(
|
|
33411
33621
|
syncRepoWithControl({
|
|
33412
33622
|
repoPath,
|
|
33413
33623
|
apiUrl,
|
|
@@ -33419,7 +33629,11 @@ async function syncReposWithControl(options) {
|
|
|
33419
33629
|
EXPLICIT_SYNC_TIMEOUT_MS,
|
|
33420
33630
|
"control sync"
|
|
33421
33631
|
);
|
|
33422
|
-
targetResults.push({
|
|
33632
|
+
targetResults.push({
|
|
33633
|
+
alias,
|
|
33634
|
+
ok: true,
|
|
33635
|
+
...outcome.warnings.length > 0 ? { warnings: outcome.warnings } : {}
|
|
33636
|
+
});
|
|
33423
33637
|
} catch (err) {
|
|
33424
33638
|
targetResults.push({
|
|
33425
33639
|
alias,
|
|
@@ -33431,11 +33645,12 @@ async function syncReposWithControl(options) {
|
|
|
33431
33645
|
const ok = targetResults.every((entry) => entry.ok);
|
|
33432
33646
|
if (ok) synced++;
|
|
33433
33647
|
else failed++;
|
|
33648
|
+
if (ok && targetResults.some((entry) => entry.warnings)) incomplete++;
|
|
33434
33649
|
results.push({ repoPath, ok, targets: targetResults, error: ok ? void 0 : "one or more targets failed" });
|
|
33435
33650
|
continue;
|
|
33436
33651
|
}
|
|
33437
33652
|
try {
|
|
33438
|
-
await withTimeout(
|
|
33653
|
+
const outcome = await withTimeout(
|
|
33439
33654
|
syncRepoWithControl({
|
|
33440
33655
|
repoPath,
|
|
33441
33656
|
apiUrl,
|
|
@@ -33448,13 +33663,18 @@ async function syncReposWithControl(options) {
|
|
|
33448
33663
|
"control sync"
|
|
33449
33664
|
);
|
|
33450
33665
|
synced++;
|
|
33451
|
-
|
|
33666
|
+
if (outcome.warnings.length > 0) incomplete++;
|
|
33667
|
+
results.push({
|
|
33668
|
+
repoPath,
|
|
33669
|
+
ok: true,
|
|
33670
|
+
...outcome.warnings.length > 0 ? { warnings: outcome.warnings } : {}
|
|
33671
|
+
});
|
|
33452
33672
|
} catch (err) {
|
|
33453
33673
|
failed++;
|
|
33454
33674
|
results.push({ repoPath, ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
33455
33675
|
}
|
|
33456
33676
|
}
|
|
33457
|
-
return { synced, failed, results };
|
|
33677
|
+
return { synced, failed, incomplete, results };
|
|
33458
33678
|
}
|
|
33459
33679
|
function destinationAliasesForSync(repoPath, explicit) {
|
|
33460
33680
|
if (explicit && explicit.length > 0) return explicit;
|
|
@@ -33519,7 +33739,7 @@ async function syncRepoWithLocalControl(options) {
|
|
|
33519
33739
|
const listResponse = await fetch(`${apiUrl}/api/repos`);
|
|
33520
33740
|
if (!listResponse.ok) throw new Error("Failed to list repos from Control API");
|
|
33521
33741
|
const repos = await listResponse.json();
|
|
33522
|
-
const existing = repos.find((r) =>
|
|
33742
|
+
const existing = repos.find((r) => path29.resolve(r.path) === repoPath);
|
|
33523
33743
|
if (!existing) {
|
|
33524
33744
|
return;
|
|
33525
33745
|
}
|
|
@@ -33531,7 +33751,7 @@ async function syncRepoWithLocalControl(options) {
|
|
|
33531
33751
|
}
|
|
33532
33752
|
}
|
|
33533
33753
|
async function syncRepoWithPortal(options, controlApiUrl, portal) {
|
|
33534
|
-
if (!isRepoPortalSyncEnabled(options.repoPath)) return;
|
|
33754
|
+
if (!isRepoPortalSyncEnabled(options.repoPath)) return [];
|
|
33535
33755
|
const { repoPath, dryRun, full } = options;
|
|
33536
33756
|
const watermarkKey = watermarkKeyForTarget(portal);
|
|
33537
33757
|
const since = full ? null : readPortalWatermarkForTarget(repoPath, portal);
|
|
@@ -33544,7 +33764,7 @@ async function syncRepoWithPortal(options, controlApiUrl, portal) {
|
|
|
33544
33764
|
}
|
|
33545
33765
|
}
|
|
33546
33766
|
const runsSince = rewindSince(stored?.lastSyncedAt ?? null);
|
|
33547
|
-
const { syncBody, runs, events, maxSyncedAt } = await buildPortalPayload(
|
|
33767
|
+
const { syncBody, runs, events, maxSyncedAt, failures, truncated } = await buildPortalPayload(
|
|
33548
33768
|
repoPath,
|
|
33549
33769
|
controlApiUrl,
|
|
33550
33770
|
since,
|
|
@@ -33567,18 +33787,25 @@ async function syncRepoWithPortal(options, controlApiUrl, portal) {
|
|
|
33567
33787
|
for (const batch of chunkBySerializedSize(events, maxSyncBatchBytes())) {
|
|
33568
33788
|
await postPortal(portal, "/api/otel", { path: repoPath, events: batch }, dryRun);
|
|
33569
33789
|
}
|
|
33570
|
-
if (!dryRun && maxSyncedAt) {
|
|
33790
|
+
if (!dryRun && maxSyncedAt && failures.length === 0) {
|
|
33571
33791
|
writePortalWatermark(repoPath, watermarkKey, maxSyncedAt);
|
|
33572
33792
|
}
|
|
33573
|
-
|
|
33793
|
+
const warnings = [];
|
|
33794
|
+
if (failures.length > 0) warnings.push(describeReadFailures(repoPath, failures));
|
|
33795
|
+
if (truncated.length > 0) warnings.push(describeTruncatedReads(repoPath, truncated));
|
|
33796
|
+
warnings.push(
|
|
33797
|
+
...await syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun, full)
|
|
33798
|
+
);
|
|
33799
|
+
for (const message of warnings) warn(message);
|
|
33800
|
+
return warnings;
|
|
33574
33801
|
}
|
|
33575
33802
|
async function syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun, full) {
|
|
33576
33803
|
const wantRecords = isPortalTrajectoryEnabledForTarget(portal);
|
|
33577
33804
|
const wantSpans = isTelemetryEnabled();
|
|
33578
|
-
if (!wantRecords && !wantSpans) return;
|
|
33805
|
+
if (!wantRecords && !wantSpans) return [];
|
|
33579
33806
|
const recordsTarget = trajectoryWatermarkTarget(portal);
|
|
33580
33807
|
const spansTarget = spansWatermarkTarget(portal);
|
|
33581
|
-
const { records, spans, recordsMaxSyncedAt, spansMaxSyncedAt } = await fetchPersistedTrajectory(repoPath, controlApiUrl, {
|
|
33808
|
+
const { records, spans, recordsMaxSyncedAt, spansMaxSyncedAt, failures, truncated } = await fetchPersistedTrajectory(repoPath, controlApiUrl, {
|
|
33582
33809
|
records: wantRecords ? {
|
|
33583
33810
|
since: full ? null : readScopedPortalWatermark(
|
|
33584
33811
|
repoPath,
|
|
@@ -33594,10 +33821,11 @@ async function syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun,
|
|
|
33594
33821
|
)
|
|
33595
33822
|
} : false
|
|
33596
33823
|
});
|
|
33824
|
+
const failedChannel = (channel) => failures.some((failure) => failure.channel === channel || failure.channel === "repos");
|
|
33597
33825
|
for (const batch of chunkBySerializedSize(spans, maxSyncBatchBytes())) {
|
|
33598
33826
|
await postPortal(portal, "/api/otel", { path: repoPath, spans: batch }, dryRun);
|
|
33599
33827
|
}
|
|
33600
|
-
if (!dryRun && spansMaxSyncedAt) {
|
|
33828
|
+
if (!dryRun && spansMaxSyncedAt && !failedChannel("spans")) {
|
|
33601
33829
|
writePortalWatermark(repoPath, spansTarget, spansMaxSyncedAt);
|
|
33602
33830
|
}
|
|
33603
33831
|
let recordsLanded = true;
|
|
@@ -33611,14 +33839,18 @@ async function syncTrajectoryWithPortal(portal, repoPath, controlApiUrl, dryRun,
|
|
|
33611
33839
|
if (!supported) {
|
|
33612
33840
|
recordsLanded = false;
|
|
33613
33841
|
warn(
|
|
33614
|
-
`${
|
|
33842
|
+
`${path29.basename(repoPath)}: this har-portal has no /api/trajectory endpoint \u2014 trajectory forwarding skipped (upgrade the portal; records are kept for the next sync).`
|
|
33615
33843
|
);
|
|
33616
33844
|
break;
|
|
33617
33845
|
}
|
|
33618
33846
|
}
|
|
33619
|
-
if (!dryRun && recordsLanded && recordsMaxSyncedAt) {
|
|
33847
|
+
if (!dryRun && recordsLanded && recordsMaxSyncedAt && !failedChannel("trajectory")) {
|
|
33620
33848
|
writePortalWatermark(repoPath, recordsTarget, recordsMaxSyncedAt);
|
|
33621
33849
|
}
|
|
33850
|
+
return [
|
|
33851
|
+
...failures.length > 0 ? [describeReadFailures(repoPath, failures)] : [],
|
|
33852
|
+
...truncated.length > 0 ? [describeTruncatedReads(repoPath, truncated)] : []
|
|
33853
|
+
];
|
|
33622
33854
|
}
|
|
33623
33855
|
async function syncRepoWithControl(options) {
|
|
33624
33856
|
const repoPath = canonicalizeControlRepoPath(options.repoPath);
|
|
@@ -33650,19 +33882,20 @@ async function syncRepoWithControl(options) {
|
|
|
33650
33882
|
if (!response.ok) {
|
|
33651
33883
|
throw new Error(`Cloud sync failed: ${response.status}`);
|
|
33652
33884
|
}
|
|
33653
|
-
return;
|
|
33885
|
+
return { warnings: [] };
|
|
33654
33886
|
}
|
|
33655
33887
|
await syncRepoWithLocalControl({ ...options, repoPath, apiUrl });
|
|
33656
|
-
if (!isRepoPortalSyncEnabled(repoPath)) return;
|
|
33888
|
+
if (!isRepoPortalSyncEnabled(repoPath)) return { warnings: [] };
|
|
33657
33889
|
const resolved = resolvePortalTargetsForRepo({
|
|
33658
33890
|
repoPath,
|
|
33659
33891
|
explicitTargets: options.portalTargets
|
|
33660
33892
|
});
|
|
33661
|
-
if (!resolved) return;
|
|
33893
|
+
if (!resolved) return { warnings: [] };
|
|
33894
|
+
const warnings = [];
|
|
33662
33895
|
const failures = [];
|
|
33663
33896
|
for (const portal of resolved.targets) {
|
|
33664
33897
|
try {
|
|
33665
|
-
await syncRepoWithPortal({ ...options, repoPath }, apiUrl, portal);
|
|
33898
|
+
warnings.push(...await syncRepoWithPortal({ ...options, repoPath }, apiUrl, portal));
|
|
33666
33899
|
} catch (err) {
|
|
33667
33900
|
failures.push({
|
|
33668
33901
|
alias: portal.alias ?? portal.identityKey,
|
|
@@ -33670,7 +33903,7 @@ async function syncRepoWithControl(options) {
|
|
|
33670
33903
|
});
|
|
33671
33904
|
}
|
|
33672
33905
|
}
|
|
33673
|
-
if (failures.length === 0) return;
|
|
33906
|
+
if (failures.length === 0) return { warnings };
|
|
33674
33907
|
if (failures.length === resolved.targets.length && failures.length === 1) {
|
|
33675
33908
|
throw new Error(failures[0].error);
|
|
33676
33909
|
}
|
|
@@ -33810,7 +34043,7 @@ async function syncRunWithLocalControl(repoPath, run2, apiUrl) {
|
|
|
33810
34043
|
const listResponse = await fetch(`${apiUrl}/api/repos`);
|
|
33811
34044
|
if (!listResponse.ok) return;
|
|
33812
34045
|
const repos = await listResponse.json();
|
|
33813
|
-
repoId = repos.find((r) =>
|
|
34046
|
+
repoId = repos.find((r) => path29.resolve(r.path) === repoPath)?.id;
|
|
33814
34047
|
}
|
|
33815
34048
|
if (!repoId) return;
|
|
33816
34049
|
const runsBody = SyncRunsInputSchema.parse({ runs: [run2] });
|
|
@@ -33843,11 +34076,11 @@ async function syncRunWithControlAsync(repoPath, run2) {
|
|
|
33843
34076
|
}
|
|
33844
34077
|
}
|
|
33845
34078
|
}
|
|
33846
|
-
var
|
|
34079
|
+
var path29, DEFAULT_MAX_BATCH_BYTES, DEFAULT_SYNC_OVERLAP_MS, MAX_FETCH_ATTEMPTS, SYNC_TIMEOUT_MS, EXPLICIT_SYNC_TIMEOUT_MS;
|
|
33847
34080
|
var init_control_sync = __esm({
|
|
33848
34081
|
"src/core/control-sync.ts"() {
|
|
33849
34082
|
"use strict";
|
|
33850
|
-
|
|
34083
|
+
path29 = __toESM(require("path"));
|
|
33851
34084
|
init_manifest();
|
|
33852
34085
|
init_stages();
|
|
33853
34086
|
init_schema2();
|
|
@@ -33882,7 +34115,7 @@ var init_control_sync = __esm({
|
|
|
33882
34115
|
// src/core/sync-context.ts
|
|
33883
34116
|
function markDirty(repoPath) {
|
|
33884
34117
|
if (!repoPath) return;
|
|
33885
|
-
dirtyRepos.add(
|
|
34118
|
+
dirtyRepos.add(path30.resolve(repoPath));
|
|
33886
34119
|
}
|
|
33887
34120
|
function markAllRegisteredDirty() {
|
|
33888
34121
|
syncAllRegistered = true;
|
|
@@ -33907,11 +34140,11 @@ async function syncDirtyRepos() {
|
|
|
33907
34140
|
} catch {
|
|
33908
34141
|
}
|
|
33909
34142
|
}
|
|
33910
|
-
var
|
|
34143
|
+
var path30, dirtyRepos, syncAllRegistered;
|
|
33911
34144
|
var init_sync_context = __esm({
|
|
33912
34145
|
"src/core/sync-context.ts"() {
|
|
33913
34146
|
"use strict";
|
|
33914
|
-
|
|
34147
|
+
path30 = __toESM(require("path"));
|
|
33915
34148
|
dirtyRepos = /* @__PURE__ */ new Set();
|
|
33916
34149
|
syncAllRegistered = false;
|
|
33917
34150
|
}
|
|
@@ -35009,15 +35242,15 @@ var require_route = __commonJS({
|
|
|
35009
35242
|
};
|
|
35010
35243
|
}
|
|
35011
35244
|
function wrapConversion(toModel, graph) {
|
|
35012
|
-
const
|
|
35245
|
+
const path69 = [graph[toModel].parent, toModel];
|
|
35013
35246
|
let fn = conversions[graph[toModel].parent][toModel];
|
|
35014
35247
|
let cur = graph[toModel].parent;
|
|
35015
35248
|
while (graph[cur].parent) {
|
|
35016
|
-
|
|
35249
|
+
path69.unshift(graph[cur].parent);
|
|
35017
35250
|
fn = link(conversions[graph[cur].parent][cur], fn);
|
|
35018
35251
|
cur = graph[cur].parent;
|
|
35019
35252
|
}
|
|
35020
|
-
fn.conversion =
|
|
35253
|
+
fn.conversion = path69;
|
|
35021
35254
|
return fn;
|
|
35022
35255
|
}
|
|
35023
35256
|
module2.exports = function(fromModel) {
|
|
@@ -41511,7 +41744,7 @@ var require_lib2 = __commonJS({
|
|
|
41511
41744
|
return matches;
|
|
41512
41745
|
};
|
|
41513
41746
|
exports2.analyse = analyse;
|
|
41514
|
-
var detectFile = (filepath, opts = {}) => new Promise((
|
|
41747
|
+
var detectFile = (filepath, opts = {}) => new Promise((resolve52, reject) => {
|
|
41515
41748
|
let fd;
|
|
41516
41749
|
const fs54 = (0, node_1.default)();
|
|
41517
41750
|
const handler = (err, buffer) => {
|
|
@@ -41521,7 +41754,7 @@ var require_lib2 = __commonJS({
|
|
|
41521
41754
|
if (err) {
|
|
41522
41755
|
reject(err);
|
|
41523
41756
|
} else if (buffer) {
|
|
41524
|
-
|
|
41757
|
+
resolve52((0, exports2.detect)(buffer));
|
|
41525
41758
|
} else {
|
|
41526
41759
|
reject(new Error("No error and no buffer received"));
|
|
41527
41760
|
}
|
|
@@ -46070,7 +46303,7 @@ var require_Observable = __commonJS({
|
|
|
46070
46303
|
Observable2.prototype.forEach = function(next, promiseCtor) {
|
|
46071
46304
|
var _this = this;
|
|
46072
46305
|
promiseCtor = getPromiseCtor(promiseCtor);
|
|
46073
|
-
return new promiseCtor(function(
|
|
46306
|
+
return new promiseCtor(function(resolve52, reject) {
|
|
46074
46307
|
var subscriber = new Subscriber_1.SafeSubscriber({
|
|
46075
46308
|
next: function(value) {
|
|
46076
46309
|
try {
|
|
@@ -46081,7 +46314,7 @@ var require_Observable = __commonJS({
|
|
|
46081
46314
|
}
|
|
46082
46315
|
},
|
|
46083
46316
|
error: reject,
|
|
46084
|
-
complete:
|
|
46317
|
+
complete: resolve52
|
|
46085
46318
|
});
|
|
46086
46319
|
_this.subscribe(subscriber);
|
|
46087
46320
|
});
|
|
@@ -46103,14 +46336,14 @@ var require_Observable = __commonJS({
|
|
|
46103
46336
|
Observable2.prototype.toPromise = function(promiseCtor) {
|
|
46104
46337
|
var _this = this;
|
|
46105
46338
|
promiseCtor = getPromiseCtor(promiseCtor);
|
|
46106
|
-
return new promiseCtor(function(
|
|
46339
|
+
return new promiseCtor(function(resolve52, reject) {
|
|
46107
46340
|
var value;
|
|
46108
46341
|
_this.subscribe(function(x) {
|
|
46109
46342
|
return value = x;
|
|
46110
46343
|
}, function(err) {
|
|
46111
46344
|
return reject(err);
|
|
46112
46345
|
}, function() {
|
|
46113
|
-
return
|
|
46346
|
+
return resolve52(value);
|
|
46114
46347
|
});
|
|
46115
46348
|
});
|
|
46116
46349
|
};
|
|
@@ -48206,11 +48439,11 @@ var require_innerFrom = __commonJS({
|
|
|
48206
48439
|
"use strict";
|
|
48207
48440
|
var __awaiter = exports2 && exports2.__awaiter || function(thisArg, _arguments, P2, generator) {
|
|
48208
48441
|
function adopt(value) {
|
|
48209
|
-
return value instanceof P2 ? value : new P2(function(
|
|
48210
|
-
|
|
48442
|
+
return value instanceof P2 ? value : new P2(function(resolve52) {
|
|
48443
|
+
resolve52(value);
|
|
48211
48444
|
});
|
|
48212
48445
|
}
|
|
48213
|
-
return new (P2 || (P2 = Promise))(function(
|
|
48446
|
+
return new (P2 || (P2 = Promise))(function(resolve52, reject) {
|
|
48214
48447
|
function fulfilled(value) {
|
|
48215
48448
|
try {
|
|
48216
48449
|
step(generator.next(value));
|
|
@@ -48226,7 +48459,7 @@ var require_innerFrom = __commonJS({
|
|
|
48226
48459
|
}
|
|
48227
48460
|
}
|
|
48228
48461
|
function step(result) {
|
|
48229
|
-
result.done ?
|
|
48462
|
+
result.done ? resolve52(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
48230
48463
|
}
|
|
48231
48464
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
48232
48465
|
});
|
|
@@ -48308,14 +48541,14 @@ var require_innerFrom = __commonJS({
|
|
|
48308
48541
|
}, i);
|
|
48309
48542
|
function verb(n) {
|
|
48310
48543
|
i[n] = o[n] && function(v2) {
|
|
48311
|
-
return new Promise(function(
|
|
48312
|
-
v2 = o[n](v2), settle(
|
|
48544
|
+
return new Promise(function(resolve52, reject) {
|
|
48545
|
+
v2 = o[n](v2), settle(resolve52, reject, v2.done, v2.value);
|
|
48313
48546
|
});
|
|
48314
48547
|
};
|
|
48315
48548
|
}
|
|
48316
|
-
function settle(
|
|
48549
|
+
function settle(resolve52, reject, d, v2) {
|
|
48317
48550
|
Promise.resolve(v2).then(function(v3) {
|
|
48318
|
-
|
|
48551
|
+
resolve52({ value: v3, done: d });
|
|
48319
48552
|
}, reject);
|
|
48320
48553
|
}
|
|
48321
48554
|
};
|
|
@@ -48934,7 +49167,7 @@ var require_lastValueFrom = __commonJS({
|
|
|
48934
49167
|
var EmptyError_1 = require_EmptyError();
|
|
48935
49168
|
function lastValueFrom2(source, config2) {
|
|
48936
49169
|
var hasConfig = typeof config2 === "object";
|
|
48937
|
-
return new Promise(function(
|
|
49170
|
+
return new Promise(function(resolve52, reject) {
|
|
48938
49171
|
var _hasValue = false;
|
|
48939
49172
|
var _value;
|
|
48940
49173
|
source.subscribe({
|
|
@@ -48945,9 +49178,9 @@ var require_lastValueFrom = __commonJS({
|
|
|
48945
49178
|
error: reject,
|
|
48946
49179
|
complete: function() {
|
|
48947
49180
|
if (_hasValue) {
|
|
48948
|
-
|
|
49181
|
+
resolve52(_value);
|
|
48949
49182
|
} else if (hasConfig) {
|
|
48950
|
-
|
|
49183
|
+
resolve52(config2.defaultValue);
|
|
48951
49184
|
} else {
|
|
48952
49185
|
reject(new EmptyError_1.EmptyError());
|
|
48953
49186
|
}
|
|
@@ -48969,16 +49202,16 @@ var require_firstValueFrom = __commonJS({
|
|
|
48969
49202
|
var Subscriber_1 = require_Subscriber();
|
|
48970
49203
|
function firstValueFrom(source, config2) {
|
|
48971
49204
|
var hasConfig = typeof config2 === "object";
|
|
48972
|
-
return new Promise(function(
|
|
49205
|
+
return new Promise(function(resolve52, reject) {
|
|
48973
49206
|
var subscriber = new Subscriber_1.SafeSubscriber({
|
|
48974
49207
|
next: function(value) {
|
|
48975
|
-
|
|
49208
|
+
resolve52(value);
|
|
48976
49209
|
subscriber.unsubscribe();
|
|
48977
49210
|
},
|
|
48978
49211
|
error: reject,
|
|
48979
49212
|
complete: function() {
|
|
48980
49213
|
if (hasConfig) {
|
|
48981
|
-
|
|
49214
|
+
resolve52(config2.defaultValue);
|
|
48982
49215
|
} else {
|
|
48983
49216
|
reject(new EmptyError_1.EmptyError());
|
|
48984
49217
|
}
|
|
@@ -54770,14 +55003,14 @@ var require_run_async = __commonJS({
|
|
|
54770
55003
|
return function() {
|
|
54771
55004
|
var args = arguments;
|
|
54772
55005
|
var originalThis = this;
|
|
54773
|
-
var promise = new Promise(function(
|
|
55006
|
+
var promise = new Promise(function(resolve52, reject) {
|
|
54774
55007
|
var resolved = false;
|
|
54775
55008
|
const wrappedResolve = function(value) {
|
|
54776
55009
|
if (resolved) {
|
|
54777
55010
|
console.warn("Run-async promise already resolved.");
|
|
54778
55011
|
}
|
|
54779
55012
|
resolved = true;
|
|
54780
|
-
|
|
55013
|
+
resolve52(value);
|
|
54781
55014
|
};
|
|
54782
55015
|
var rejected = false;
|
|
54783
55016
|
const wrappedReject = function(value) {
|
|
@@ -54885,25 +55118,25 @@ __export(otel_hooks_exports, {
|
|
|
54885
55118
|
});
|
|
54886
55119
|
function getOtelHooksHome() {
|
|
54887
55120
|
if (process.env.HAR_OTEL_HOOKS_HOME) {
|
|
54888
|
-
return
|
|
55121
|
+
return path53.resolve(process.env.HAR_OTEL_HOOKS_HOME);
|
|
54889
55122
|
}
|
|
54890
|
-
return
|
|
55123
|
+
return path53.join(os19.homedir(), ".har", "otel-hooks");
|
|
54891
55124
|
}
|
|
54892
55125
|
function getOtelHooksConfigPath(hooksHome = getOtelHooksHome()) {
|
|
54893
|
-
return
|
|
55126
|
+
return path53.join(hooksHome, "otel_config.json");
|
|
54894
55127
|
}
|
|
54895
55128
|
function getOtelHooksWrapperPath(hooksHome = getOtelHooksHome()) {
|
|
54896
|
-
return
|
|
55129
|
+
return path53.join(hooksHome, "run-otel-hook.sh");
|
|
54897
55130
|
}
|
|
54898
55131
|
function getOtelHooksStateDir(hooksHome = getOtelHooksHome()) {
|
|
54899
|
-
return
|
|
55132
|
+
return path53.join(hooksHome, "state");
|
|
54900
55133
|
}
|
|
54901
55134
|
function localOtelHookBin(hooksHome) {
|
|
54902
|
-
return
|
|
55135
|
+
return path53.join(hooksHome, "node_modules", ".bin", "otel-hook");
|
|
54903
55136
|
}
|
|
54904
55137
|
function installedPackageVersion(hooksHome) {
|
|
54905
55138
|
try {
|
|
54906
|
-
const pkgPath =
|
|
55139
|
+
const pkgPath = path53.join(
|
|
54907
55140
|
hooksHome,
|
|
54908
55141
|
"node_modules",
|
|
54909
55142
|
"@osfactory",
|
|
@@ -55050,9 +55283,9 @@ function uninstallLegacyPythonHooks(hooksHome) {
|
|
|
55050
55283
|
}
|
|
55051
55284
|
function removeLegacyPythonArtifacts(hooksHome) {
|
|
55052
55285
|
const legacyPaths = [
|
|
55053
|
-
|
|
55054
|
-
|
|
55055
|
-
|
|
55286
|
+
path53.join(hooksHome, ".venv"),
|
|
55287
|
+
path53.join(hooksHome, "otel_config.yaml"),
|
|
55288
|
+
path53.join(hooksHome, "venv")
|
|
55056
55289
|
];
|
|
55057
55290
|
for (const target of legacyPaths) {
|
|
55058
55291
|
try {
|
|
@@ -55198,14 +55431,14 @@ function pruneLegacyCursorHookEvents(filePath, wrapperPath) {
|
|
|
55198
55431
|
function rewriteKnownHookRegistrations(wrapperPath) {
|
|
55199
55432
|
const home = os19.homedir();
|
|
55200
55433
|
const candidates = [
|
|
55201
|
-
|
|
55202
|
-
|
|
55203
|
-
|
|
55434
|
+
path53.join(home, ".cursor", "hooks.json"),
|
|
55435
|
+
path53.join(home, ".claude", "settings.json"),
|
|
55436
|
+
path53.join(home, ".codex", "hooks.json")
|
|
55204
55437
|
];
|
|
55205
55438
|
for (const filePath of candidates) {
|
|
55206
55439
|
try {
|
|
55207
55440
|
rewriteHookCommandsToWrapper(filePath, wrapperPath);
|
|
55208
|
-
if (filePath.endsWith(`${
|
|
55441
|
+
if (filePath.endsWith(`${path53.sep}.cursor${path53.sep}hooks.json`)) {
|
|
55209
55442
|
pruneLegacyCursorHookEvents(filePath, wrapperPath);
|
|
55210
55443
|
}
|
|
55211
55444
|
} catch {
|
|
@@ -55315,14 +55548,14 @@ function ensureOtelHooks(options) {
|
|
|
55315
55548
|
function disableOtelHooksExport() {
|
|
55316
55549
|
return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
|
|
55317
55550
|
}
|
|
55318
|
-
var import_child_process14, fs46, os19,
|
|
55551
|
+
var import_child_process14, fs46, os19, path53, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
|
|
55319
55552
|
var init_otel_hooks = __esm({
|
|
55320
55553
|
"src/core/otel-hooks.ts"() {
|
|
55321
55554
|
"use strict";
|
|
55322
55555
|
import_child_process14 = require("child_process");
|
|
55323
55556
|
fs46 = __toESM(require("fs"));
|
|
55324
55557
|
os19 = __toESM(require("os"));
|
|
55325
|
-
|
|
55558
|
+
path53 = __toESM(require("path"));
|
|
55326
55559
|
init_control_config();
|
|
55327
55560
|
init_telemetry_config();
|
|
55328
55561
|
OTEL_HOOKS_PACKAGE = "@osfactory/otel-hook@0.2.0";
|
|
@@ -58297,7 +58530,7 @@ var require_compile = __commonJS({
|
|
|
58297
58530
|
const schOrFunc = root.refs[ref];
|
|
58298
58531
|
if (schOrFunc)
|
|
58299
58532
|
return schOrFunc;
|
|
58300
|
-
let _sch =
|
|
58533
|
+
let _sch = resolve52.call(this, root, ref);
|
|
58301
58534
|
if (_sch === void 0) {
|
|
58302
58535
|
const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref];
|
|
58303
58536
|
const { schemaId } = this.opts;
|
|
@@ -58324,7 +58557,7 @@ var require_compile = __commonJS({
|
|
|
58324
58557
|
function sameSchemaEnv(s1, s2) {
|
|
58325
58558
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
58326
58559
|
}
|
|
58327
|
-
function
|
|
58560
|
+
function resolve52(root, ref) {
|
|
58328
58561
|
let sch;
|
|
58329
58562
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
58330
58563
|
ref = sch;
|
|
@@ -58542,8 +58775,8 @@ var require_utils2 = __commonJS({
|
|
|
58542
58775
|
}
|
|
58543
58776
|
return ind;
|
|
58544
58777
|
}
|
|
58545
|
-
function removeDotSegments(
|
|
58546
|
-
let input =
|
|
58778
|
+
function removeDotSegments(path69) {
|
|
58779
|
+
let input = path69;
|
|
58547
58780
|
const output = [];
|
|
58548
58781
|
let nextSlash = -1;
|
|
58549
58782
|
let len = 0;
|
|
@@ -58795,8 +59028,8 @@ var require_schemes = __commonJS({
|
|
|
58795
59028
|
wsComponent.secure = void 0;
|
|
58796
59029
|
}
|
|
58797
59030
|
if (wsComponent.resourceName) {
|
|
58798
|
-
const [
|
|
58799
|
-
wsComponent.path =
|
|
59031
|
+
const [path69, query] = wsComponent.resourceName.split("?");
|
|
59032
|
+
wsComponent.path = path69 && path69 !== "/" ? path69 : void 0;
|
|
58800
59033
|
wsComponent.query = query;
|
|
58801
59034
|
wsComponent.resourceName = void 0;
|
|
58802
59035
|
}
|
|
@@ -58955,7 +59188,7 @@ var require_fast_uri = __commonJS({
|
|
|
58955
59188
|
}
|
|
58956
59189
|
return uri;
|
|
58957
59190
|
}
|
|
58958
|
-
function
|
|
59191
|
+
function resolve52(baseURI, relativeURI, options) {
|
|
58959
59192
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
58960
59193
|
const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
58961
59194
|
schemelessOptions.skipEscape = true;
|
|
@@ -59213,7 +59446,7 @@ var require_fast_uri = __commonJS({
|
|
|
59213
59446
|
var fastUri = {
|
|
59214
59447
|
SCHEMES,
|
|
59215
59448
|
normalize: normalize3,
|
|
59216
|
-
resolve:
|
|
59449
|
+
resolve: resolve52,
|
|
59217
59450
|
resolveComponent,
|
|
59218
59451
|
equal,
|
|
59219
59452
|
serialize,
|
|
@@ -63478,11 +63711,11 @@ var parser = new YargsParser({
|
|
|
63478
63711
|
resolve: import_path2.resolve,
|
|
63479
63712
|
// TODO: figure out a way to combine ESM and CJS coverage, such that
|
|
63480
63713
|
// we can exercise all the lines below:
|
|
63481
|
-
require: (
|
|
63714
|
+
require: (path69) => {
|
|
63482
63715
|
if (typeof require !== "undefined") {
|
|
63483
|
-
return require(
|
|
63484
|
-
} else if (
|
|
63485
|
-
return JSON.parse((0, import_fs2.readFileSync)(
|
|
63716
|
+
return require(path69);
|
|
63717
|
+
} else if (path69.match(/\.json$/)) {
|
|
63718
|
+
return JSON.parse((0, import_fs2.readFileSync)(path69, "utf8"));
|
|
63486
63719
|
} else {
|
|
63487
63720
|
throw Error("only .json config files are supported in ESM");
|
|
63488
63721
|
}
|
|
@@ -66008,12 +66241,12 @@ var YargsInstance = class {
|
|
|
66008
66241
|
async getCompletion(args, done) {
|
|
66009
66242
|
argsert("<array> [function]", [args, done], arguments.length);
|
|
66010
66243
|
if (!done) {
|
|
66011
|
-
return new Promise((
|
|
66244
|
+
return new Promise((resolve52, reject) => {
|
|
66012
66245
|
__classPrivateFieldGet(this, _YargsInstance_completion, "f").getCompletion(args, (err, completions) => {
|
|
66013
66246
|
if (err)
|
|
66014
66247
|
reject(err);
|
|
66015
66248
|
else
|
|
66016
|
-
|
|
66249
|
+
resolve52(completions);
|
|
66017
66250
|
});
|
|
66018
66251
|
});
|
|
66019
66252
|
} else {
|
|
@@ -67058,33 +67291,33 @@ init_telemetry_config();
|
|
|
67058
67291
|
init_sync_context();
|
|
67059
67292
|
|
|
67060
67293
|
// src/cli/commands/agents.ts
|
|
67061
|
-
var
|
|
67294
|
+
var path33 = __toESM(require("path"));
|
|
67062
67295
|
|
|
67063
67296
|
// src/harness/agent-skills.ts
|
|
67064
67297
|
var fs27 = __toESM(require("fs"));
|
|
67065
67298
|
var os14 = __toESM(require("os"));
|
|
67066
|
-
var
|
|
67299
|
+
var path32 = __toESM(require("path"));
|
|
67067
67300
|
var readline = __toESM(require("readline"));
|
|
67068
67301
|
init_file_ops();
|
|
67069
67302
|
init_logging();
|
|
67070
67303
|
|
|
67071
67304
|
// src/utils/paths.ts
|
|
67072
67305
|
var fs26 = __toESM(require("fs"));
|
|
67073
|
-
var
|
|
67306
|
+
var path31 = __toESM(require("path"));
|
|
67074
67307
|
function resolveTemplatesDir() {
|
|
67075
67308
|
const candidates = [
|
|
67076
|
-
|
|
67077
|
-
|
|
67078
|
-
|
|
67309
|
+
path31.join(__dirname, "templates"),
|
|
67310
|
+
path31.join(__dirname, "..", "templates"),
|
|
67311
|
+
path31.join(__dirname, "..", "harness", "templates")
|
|
67079
67312
|
];
|
|
67080
67313
|
for (const dir of candidates) {
|
|
67081
|
-
if (fs26.existsSync(
|
|
67314
|
+
if (fs26.existsSync(path31.join(dir, "har-boilerplate"))) return dir;
|
|
67082
67315
|
}
|
|
67083
67316
|
throw new Error("Templates directory not found. Run npm run build.");
|
|
67084
67317
|
}
|
|
67085
67318
|
function resolveTemplateFile(name) {
|
|
67086
67319
|
const dir = resolveTemplatesDir();
|
|
67087
|
-
const filePath =
|
|
67320
|
+
const filePath = path31.join(dir, name);
|
|
67088
67321
|
return fs26.existsSync(filePath) ? filePath : null;
|
|
67089
67322
|
}
|
|
67090
67323
|
|
|
@@ -67093,18 +67326,18 @@ init_manifest();
|
|
|
67093
67326
|
var AGENT_SKILL_TARGETS = ["claude", "cursor", "codex"];
|
|
67094
67327
|
var MANAGED_HEADER = "<!-- managed by har \u2014 regenerated by `har agents install` / `har env maintain`; edit at your own risk -->";
|
|
67095
67328
|
function agentSkillsTemplateDir() {
|
|
67096
|
-
const dir =
|
|
67329
|
+
const dir = path32.join(resolveTemplatesDir(), "agent-skills");
|
|
67097
67330
|
if (!fs27.existsSync(dir)) {
|
|
67098
67331
|
throw new Error("Agent skills templates not found (templates/agent-skills). Run npm run build.");
|
|
67099
67332
|
}
|
|
67100
67333
|
return dir;
|
|
67101
67334
|
}
|
|
67102
67335
|
function readSkillsManifest() {
|
|
67103
|
-
const manifestPath =
|
|
67336
|
+
const manifestPath = path32.join(agentSkillsTemplateDir(), "skills.manifest.json");
|
|
67104
67337
|
return JSON.parse(fs27.readFileSync(manifestPath, "utf8"));
|
|
67105
67338
|
}
|
|
67106
67339
|
function readSkillBody(entry) {
|
|
67107
|
-
return fs27.readFileSync(
|
|
67340
|
+
return fs27.readFileSync(path32.join(agentSkillsTemplateDir(), entry.body), "utf8");
|
|
67108
67341
|
}
|
|
67109
67342
|
function renderYamlValue(value) {
|
|
67110
67343
|
if (typeof value === "string") return JSON.stringify(value);
|
|
@@ -67136,7 +67369,7 @@ function renderSkillFiles(agents) {
|
|
|
67136
67369
|
agent: "claude",
|
|
67137
67370
|
skill: entry.id,
|
|
67138
67371
|
scope: "repo",
|
|
67139
|
-
relPath:
|
|
67372
|
+
relPath: path32.join(".claude", "skills", entry.id, "SKILL.md"),
|
|
67140
67373
|
content: renderClaudeSkill(entry, body)
|
|
67141
67374
|
});
|
|
67142
67375
|
}
|
|
@@ -67145,7 +67378,7 @@ function renderSkillFiles(agents) {
|
|
|
67145
67378
|
agent: "cursor",
|
|
67146
67379
|
skill: entry.id,
|
|
67147
67380
|
scope: "repo",
|
|
67148
|
-
relPath:
|
|
67381
|
+
relPath: path32.join(".cursor", "commands", `${entry.id}.md`),
|
|
67149
67382
|
content: renderPlainSkill(body)
|
|
67150
67383
|
});
|
|
67151
67384
|
}
|
|
@@ -67154,7 +67387,7 @@ function renderSkillFiles(agents) {
|
|
|
67154
67387
|
agent: "codex",
|
|
67155
67388
|
skill: entry.id,
|
|
67156
67389
|
scope: "global",
|
|
67157
|
-
relPath:
|
|
67390
|
+
relPath: path32.posix.join("~", ".codex", "prompts", `${entry.codex.promptName}.md`),
|
|
67158
67391
|
content: renderPlainSkill(body)
|
|
67159
67392
|
});
|
|
67160
67393
|
}
|
|
@@ -67163,9 +67396,9 @@ function renderSkillFiles(agents) {
|
|
|
67163
67396
|
}
|
|
67164
67397
|
function resolveScaffoldPath(repoPath, file) {
|
|
67165
67398
|
if (file.scope === "global") {
|
|
67166
|
-
return
|
|
67399
|
+
return path32.join(os14.homedir(), file.relPath.replace(/^~\//, ""));
|
|
67167
67400
|
}
|
|
67168
|
-
return
|
|
67401
|
+
return path32.join(repoPath, file.relPath);
|
|
67169
67402
|
}
|
|
67170
67403
|
function isHarManaged(filePath) {
|
|
67171
67404
|
return fs27.readFileSync(filePath, "utf8").includes(MANAGED_HEADER);
|
|
@@ -67217,7 +67450,7 @@ function removeAgentSkills(repoPath, agents) {
|
|
|
67217
67450
|
}
|
|
67218
67451
|
fs27.rmSync(destPath);
|
|
67219
67452
|
removed.push(file.relPath);
|
|
67220
|
-
const parent =
|
|
67453
|
+
const parent = path32.dirname(destPath);
|
|
67221
67454
|
if (fs27.existsSync(parent) && fs27.readdirSync(parent).length === 0) {
|
|
67222
67455
|
fs27.rmdirSync(parent);
|
|
67223
67456
|
}
|
|
@@ -67238,9 +67471,9 @@ function detectAgentTargets(repoPath) {
|
|
|
67238
67471
|
const manifest = readManifest(repoPath);
|
|
67239
67472
|
const scaffolded = new Set((manifest?.scaffoldedAgentFiles ?? []).map((entry) => entry.agent));
|
|
67240
67473
|
const detected = new Set(scaffolded);
|
|
67241
|
-
if (fs27.existsSync(
|
|
67242
|
-
if (fs27.existsSync(
|
|
67243
|
-
if (fs27.existsSync(
|
|
67474
|
+
if (fs27.existsSync(path32.join(repoPath, ".claude"))) detected.add("claude");
|
|
67475
|
+
if (fs27.existsSync(path32.join(repoPath, ".cursor"))) detected.add("cursor");
|
|
67476
|
+
if (fs27.existsSync(path32.join(os14.homedir(), ".codex"))) detected.add("codex");
|
|
67244
67477
|
return AGENT_SKILL_TARGETS.filter((agent) => detected.has(agent));
|
|
67245
67478
|
}
|
|
67246
67479
|
function parseAgentTargets(raw) {
|
|
@@ -67284,16 +67517,16 @@ async function handleAgentSkills(options) {
|
|
|
67284
67517
|
}
|
|
67285
67518
|
async function askYesNo(question) {
|
|
67286
67519
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
67287
|
-
return new Promise((
|
|
67520
|
+
return new Promise((resolve52) => {
|
|
67288
67521
|
process.stderr.write(`${question} `);
|
|
67289
67522
|
rl.once("line", (answer) => {
|
|
67290
67523
|
rl.close();
|
|
67291
67524
|
const trimmed = answer.trim();
|
|
67292
67525
|
if (trimmed === "") {
|
|
67293
|
-
|
|
67526
|
+
resolve52(true);
|
|
67294
67527
|
return;
|
|
67295
67528
|
}
|
|
67296
|
-
|
|
67529
|
+
resolve52(/^y(es)?$/i.test(trimmed));
|
|
67297
67530
|
});
|
|
67298
67531
|
});
|
|
67299
67532
|
}
|
|
@@ -67327,7 +67560,7 @@ var agentsCommand = {
|
|
|
67327
67560
|
}
|
|
67328
67561
|
};
|
|
67329
67562
|
function handleInstall(argv) {
|
|
67330
|
-
const repoPath =
|
|
67563
|
+
const repoPath = path33.resolve(argv.repo);
|
|
67331
67564
|
header("har agents install");
|
|
67332
67565
|
try {
|
|
67333
67566
|
const targets = resolveTargets(argv, repoPath);
|
|
@@ -67353,7 +67586,7 @@ function handleInstall(argv) {
|
|
|
67353
67586
|
}
|
|
67354
67587
|
}
|
|
67355
67588
|
function handleRemove(argv) {
|
|
67356
|
-
const repoPath =
|
|
67589
|
+
const repoPath = path33.resolve(argv.repo);
|
|
67357
67590
|
header("har agents remove");
|
|
67358
67591
|
try {
|
|
67359
67592
|
const targets = resolveTargets(argv, repoPath);
|
|
@@ -67373,7 +67606,7 @@ function handleRemove(argv) {
|
|
|
67373
67606
|
}
|
|
67374
67607
|
|
|
67375
67608
|
// src/cli/commands/env.ts
|
|
67376
|
-
var
|
|
67609
|
+
var path57 = __toESM(require("path"));
|
|
67377
67610
|
|
|
67378
67611
|
// src/cli/finish-command.ts
|
|
67379
67612
|
init_sync_context();
|
|
@@ -67384,23 +67617,23 @@ async function finishCommand(code) {
|
|
|
67384
67617
|
|
|
67385
67618
|
// src/core/harness.ts
|
|
67386
67619
|
var fs42 = __toESM(require("fs"));
|
|
67387
|
-
var
|
|
67620
|
+
var path48 = __toESM(require("path"));
|
|
67388
67621
|
|
|
67389
67622
|
// src/harness/generator.ts
|
|
67390
67623
|
var fs32 = __toESM(require("fs"));
|
|
67391
|
-
var
|
|
67624
|
+
var path38 = __toESM(require("path"));
|
|
67392
67625
|
init_file_ops();
|
|
67393
67626
|
init_logging();
|
|
67394
67627
|
|
|
67395
67628
|
// src/core/gitignore.ts
|
|
67396
67629
|
var fs28 = __toESM(require("fs"));
|
|
67397
|
-
var
|
|
67630
|
+
var path34 = __toESM(require("path"));
|
|
67398
67631
|
var HARNESS_ROOT_GITIGNORE_PATTERNS = [
|
|
67399
67632
|
".env.agent.*",
|
|
67400
67633
|
"ecosystem.agent.*.config.cjs"
|
|
67401
67634
|
];
|
|
67402
67635
|
function ensureRootGitignorePatterns(checkoutDir) {
|
|
67403
|
-
const gitignorePath =
|
|
67636
|
+
const gitignorePath = path34.join(checkoutDir, ".gitignore");
|
|
67404
67637
|
const content = fs28.existsSync(gitignorePath) ? fs28.readFileSync(gitignorePath, "utf8") : "";
|
|
67405
67638
|
const lines = content.split("\n").map((line) => line.trim());
|
|
67406
67639
|
const missing = HARNESS_ROOT_GITIGNORE_PATTERNS.filter((pattern) => !lines.includes(pattern));
|
|
@@ -67415,7 +67648,7 @@ function ensureRootGitignorePatterns(checkoutDir) {
|
|
|
67415
67648
|
|
|
67416
67649
|
// src/harness/gitignore-template.ts
|
|
67417
67650
|
var fs29 = __toESM(require("fs"));
|
|
67418
|
-
var
|
|
67651
|
+
var path35 = __toESM(require("path"));
|
|
67419
67652
|
var HARNESS_GITIGNORE_TEMPLATE = "gitignore.template";
|
|
67420
67653
|
var HARNESS_GITIGNORE_FILE = ".gitignore";
|
|
67421
67654
|
function harnessFileForTemplate(templateFile) {
|
|
@@ -67425,16 +67658,16 @@ function templateFileForHarness(harnessFile) {
|
|
|
67425
67658
|
return harnessFile === HARNESS_GITIGNORE_FILE ? HARNESS_GITIGNORE_TEMPLATE : harnessFile;
|
|
67426
67659
|
}
|
|
67427
67660
|
function resolveGitignoreTemplateSource(boilerplateDir) {
|
|
67428
|
-
const primary =
|
|
67661
|
+
const primary = path35.join(boilerplateDir, HARNESS_GITIGNORE_TEMPLATE);
|
|
67429
67662
|
if (fs29.existsSync(primary)) return primary;
|
|
67430
|
-
const legacy =
|
|
67663
|
+
const legacy = path35.join(boilerplateDir, HARNESS_GITIGNORE_FILE);
|
|
67431
67664
|
if (fs29.existsSync(legacy)) return legacy;
|
|
67432
67665
|
return null;
|
|
67433
67666
|
}
|
|
67434
67667
|
function writeHarnessGitignore(harnessDir, boilerplateDir) {
|
|
67435
67668
|
const src = resolveGitignoreTemplateSource(boilerplateDir);
|
|
67436
67669
|
if (!src) return;
|
|
67437
|
-
fs29.writeFileSync(
|
|
67670
|
+
fs29.writeFileSync(path35.join(harnessDir, HARNESS_GITIGNORE_FILE), fs29.readFileSync(src, "utf8"));
|
|
67438
67671
|
}
|
|
67439
67672
|
function isExpectedHarnessOnlyFile(harnessFile, templateFiles) {
|
|
67440
67673
|
return harnessFile === HARNESS_GITIGNORE_FILE && templateFiles.includes(HARNESS_GITIGNORE_TEMPLATE);
|
|
@@ -67445,7 +67678,7 @@ init_manifest();
|
|
|
67445
67678
|
|
|
67446
67679
|
// src/harness/plugin-ledger.ts
|
|
67447
67680
|
var fs30 = __toESM(require("fs"));
|
|
67448
|
-
var
|
|
67681
|
+
var path36 = __toESM(require("path"));
|
|
67449
67682
|
init_zod();
|
|
67450
67683
|
init_file_ops();
|
|
67451
67684
|
init_manifest();
|
|
@@ -67468,7 +67701,7 @@ var PluginLedgerSchema = external_exports.object({
|
|
|
67468
67701
|
plugins: external_exports.array(PluginLedgerEntrySchema).default([])
|
|
67469
67702
|
});
|
|
67470
67703
|
function getPluginLedgerPath(repoPath) {
|
|
67471
|
-
return
|
|
67704
|
+
return path36.join(path36.resolve(repoPath), DEFAULT_HAR_DIR, "plugins.json");
|
|
67472
67705
|
}
|
|
67473
67706
|
function readPluginLedger(repoPath) {
|
|
67474
67707
|
const ledgerPath = getPluginLedgerPath(repoPath);
|
|
@@ -67483,7 +67716,7 @@ function readPluginLedger(repoPath) {
|
|
|
67483
67716
|
}
|
|
67484
67717
|
function writePluginLedger(repoPath, ledger) {
|
|
67485
67718
|
const ledgerPath = getPluginLedgerPath(repoPath);
|
|
67486
|
-
const harnessDir =
|
|
67719
|
+
const harnessDir = path36.dirname(ledgerPath);
|
|
67487
67720
|
if (!fs30.existsSync(harnessDir)) {
|
|
67488
67721
|
fs30.mkdirSync(harnessDir, { recursive: true });
|
|
67489
67722
|
}
|
|
@@ -67521,7 +67754,7 @@ function ensurePluginLedgerScaffold(repoPath, options) {
|
|
|
67521
67754
|
|
|
67522
67755
|
// src/harness/profiles.ts
|
|
67523
67756
|
var fs31 = __toESM(require("fs"));
|
|
67524
|
-
var
|
|
67757
|
+
var path37 = __toESM(require("path"));
|
|
67525
67758
|
init_zod();
|
|
67526
67759
|
var HARNESS_PROFILES = ["default", "cli", "ios"];
|
|
67527
67760
|
var ProfileBundleRefSchema = external_exports.object({
|
|
@@ -67574,7 +67807,7 @@ var PROFILE_DIRS = {
|
|
|
67574
67807
|
};
|
|
67575
67808
|
function readProfileManifest(profile) {
|
|
67576
67809
|
const templates = resolveTemplatesDir();
|
|
67577
|
-
const manifestPath =
|
|
67810
|
+
const manifestPath = path37.join(templates, "profiles", profile, "profile.manifest.json");
|
|
67578
67811
|
if (fs31.existsSync(manifestPath)) {
|
|
67579
67812
|
const parsed = ProfileManifestSchema.safeParse(
|
|
67580
67813
|
JSON.parse(fs31.readFileSync(manifestPath, "utf8"))
|
|
@@ -67590,7 +67823,7 @@ function readProfileManifest(profile) {
|
|
|
67590
67823
|
return PROFILE_COMPOSITIONS[profile];
|
|
67591
67824
|
}
|
|
67592
67825
|
function resolveProfileBundleDir(bundle) {
|
|
67593
|
-
const dir =
|
|
67826
|
+
const dir = path37.join(resolveTemplatesDir(), bundle.path);
|
|
67594
67827
|
if (!fs31.existsSync(dir)) {
|
|
67595
67828
|
throw new Error(`Profile bundle not found: ${bundle.id} (${bundle.path}). Run npm run build.`);
|
|
67596
67829
|
}
|
|
@@ -67606,20 +67839,20 @@ var CLI_PRUNE_FILES = [
|
|
|
67606
67839
|
];
|
|
67607
67840
|
function pruneCliProfile(harnessDir) {
|
|
67608
67841
|
for (const file of CLI_PRUNE_FILES) {
|
|
67609
|
-
const filePath =
|
|
67842
|
+
const filePath = path38.join(harnessDir, file);
|
|
67610
67843
|
if (fs32.existsSync(filePath)) {
|
|
67611
67844
|
fs32.unlinkSync(filePath);
|
|
67612
67845
|
}
|
|
67613
67846
|
}
|
|
67614
67847
|
}
|
|
67615
67848
|
function scaffoldHarnessBoilerplate(repoPath, options = {}) {
|
|
67616
|
-
const harnessDir =
|
|
67617
|
-
const projectName =
|
|
67849
|
+
const harnessDir = path38.join(repoPath, DEFAULT_HAR_DIR);
|
|
67850
|
+
const projectName = path38.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
|
|
67618
67851
|
const profile = options.profile ?? "default";
|
|
67619
67852
|
const profileManifest = readProfileManifest(profile);
|
|
67620
67853
|
const bundleIds = profileManifest.bundles.map((b2) => b2.id);
|
|
67621
67854
|
const primaryOverlay = PROFILE_DIRS[profile];
|
|
67622
|
-
const boilerplateDir =
|
|
67855
|
+
const boilerplateDir = path38.join(resolveTemplatesDir(), primaryOverlay);
|
|
67623
67856
|
if (fs32.existsSync(harnessDir) && !options.force) {
|
|
67624
67857
|
throw new Error(
|
|
67625
67858
|
'.har/ already exists. Use --force to overwrite or run "har env maintain" to update in place.'
|
|
@@ -67641,7 +67874,7 @@ function scaffoldHarnessBoilerplate(repoPath, options = {}) {
|
|
|
67641
67874
|
pruneCliProfile(harnessDir);
|
|
67642
67875
|
}
|
|
67643
67876
|
syncAgentSlotsToHarnessEnv(repoPath);
|
|
67644
|
-
const harnessEnvPath =
|
|
67877
|
+
const harnessEnvPath = path38.join(harnessDir, "harness.env");
|
|
67645
67878
|
if (fs32.existsSync(harnessEnvPath)) {
|
|
67646
67879
|
let content = fs32.readFileSync(harnessEnvPath, "utf8");
|
|
67647
67880
|
content = content.replace(/__PROJECT_NAME__/g, projectName).replace(/template___PROJECT_NAME__/g, `template_${projectName}`);
|
|
@@ -67670,7 +67903,7 @@ function finalizeHarness(repoPath, adaptationSummary, stack) {
|
|
|
67670
67903
|
|
|
67671
67904
|
// src/harness/agent-md.ts
|
|
67672
67905
|
var fs34 = __toESM(require("fs"));
|
|
67673
|
-
var
|
|
67906
|
+
var path41 = __toESM(require("path"));
|
|
67674
67907
|
init_file_ops();
|
|
67675
67908
|
init_logging();
|
|
67676
67909
|
init_manifest();
|
|
@@ -67678,7 +67911,7 @@ init_manifest();
|
|
|
67678
67911
|
// src/harness/instruction-files.ts
|
|
67679
67912
|
var fs33 = __toESM(require("fs"));
|
|
67680
67913
|
var os16 = __toESM(require("os"));
|
|
67681
|
-
var
|
|
67914
|
+
var path40 = __toESM(require("path"));
|
|
67682
67915
|
|
|
67683
67916
|
// node_modules/@inquirer/core/dist/esm/lib/key.js
|
|
67684
67917
|
var isUpKey = (key, keybindings = []) => (
|
|
@@ -68712,13 +68945,13 @@ var PromisePolyfill = class extends Promise {
|
|
|
68712
68945
|
// Available starting from Node 22
|
|
68713
68946
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
|
|
68714
68947
|
static withResolver() {
|
|
68715
|
-
let
|
|
68948
|
+
let resolve52;
|
|
68716
68949
|
let reject;
|
|
68717
68950
|
const promise = new Promise((res, rej) => {
|
|
68718
|
-
|
|
68951
|
+
resolve52 = res;
|
|
68719
68952
|
reject = rej;
|
|
68720
68953
|
});
|
|
68721
|
-
return { promise, resolve:
|
|
68954
|
+
return { promise, resolve: resolve52, reject };
|
|
68722
68955
|
}
|
|
68723
68956
|
};
|
|
68724
68957
|
|
|
@@ -68752,7 +68985,7 @@ function createPrompt(view) {
|
|
|
68752
68985
|
output
|
|
68753
68986
|
});
|
|
68754
68987
|
const screen = new ScreenManager(rl);
|
|
68755
|
-
const { promise, resolve:
|
|
68988
|
+
const { promise, resolve: resolve52, reject } = PromisePolyfill.withResolver();
|
|
68756
68989
|
const cancel = () => reject(new CancelPromptError());
|
|
68757
68990
|
if (signal) {
|
|
68758
68991
|
const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
|
|
@@ -68779,7 +69012,7 @@ function createPrompt(view) {
|
|
|
68779
69012
|
cycle(() => {
|
|
68780
69013
|
try {
|
|
68781
69014
|
const nextView = view(config2, (value) => {
|
|
68782
|
-
setImmediate(() =>
|
|
69015
|
+
setImmediate(() => resolve52(value));
|
|
68783
69016
|
});
|
|
68784
69017
|
if (nextView === void 0) {
|
|
68785
69018
|
const callerFilename = callSites[1]?.getFileName();
|
|
@@ -70088,9 +70321,9 @@ var import_rxjs = __toESM(require_cjs(), 1);
|
|
|
70088
70321
|
var import_run_async = __toESM(require_run_async(), 1);
|
|
70089
70322
|
var import_mute_stream2 = __toESM(require_lib(), 1);
|
|
70090
70323
|
var _ = {
|
|
70091
|
-
set: (obj,
|
|
70324
|
+
set: (obj, path69 = "", value) => {
|
|
70092
70325
|
let pointer = obj;
|
|
70093
|
-
|
|
70326
|
+
path69.split(".").forEach((key, index, arr) => {
|
|
70094
70327
|
if (key === "__proto__" || key === "constructor")
|
|
70095
70328
|
return;
|
|
70096
70329
|
if (index === arr.length - 1) {
|
|
@@ -70101,8 +70334,8 @@ var _ = {
|
|
|
70101
70334
|
pointer = pointer[key];
|
|
70102
70335
|
});
|
|
70103
70336
|
},
|
|
70104
|
-
get: (obj,
|
|
70105
|
-
const travel = (regexp) => String.prototype.split.call(
|
|
70337
|
+
get: (obj, path69 = "", defaultValue) => {
|
|
70338
|
+
const travel = (regexp) => String.prototype.split.call(path69, regexp).filter(Boolean).reduce(
|
|
70106
70339
|
// @ts-expect-error implicit any on res[key]
|
|
70107
70340
|
(res, key) => res == null ? res : res[key],
|
|
70108
70341
|
obj
|
|
@@ -70220,7 +70453,7 @@ var PromptsRunner = class {
|
|
|
70220
70453
|
throw new Error(`Prompt for type ${question.type} not found`);
|
|
70221
70454
|
}
|
|
70222
70455
|
let cleanupSignal;
|
|
70223
|
-
const promptFn = isPromptConstructor(prompt2) ? (q, opt) => new Promise((
|
|
70456
|
+
const promptFn = isPromptConstructor(prompt2) ? (q, opt) => new Promise((resolve52, reject) => {
|
|
70224
70457
|
const { signal: signal2 } = opt;
|
|
70225
70458
|
if (signal2.aborted) {
|
|
70226
70459
|
reject(new AbortPromptError({ cause: signal2.reason }));
|
|
@@ -70257,7 +70490,7 @@ var PromptsRunner = class {
|
|
|
70257
70490
|
signal2.removeEventListener("abort", abort);
|
|
70258
70491
|
cleanupSignal = void 0;
|
|
70259
70492
|
};
|
|
70260
|
-
activePrompt.run().then(
|
|
70493
|
+
activePrompt.run().then(resolve52, reject).finally(cleanup);
|
|
70261
70494
|
}) : prompt2;
|
|
70262
70495
|
let cleanupModuleSignal;
|
|
70263
70496
|
const { signal: moduleSignal } = this.opt;
|
|
@@ -70427,12 +70660,12 @@ function outsideContentShrinkMessage(beforeLines, afterLines) {
|
|
|
70427
70660
|
}
|
|
70428
70661
|
function detectInstructionFiles(repoPath) {
|
|
70429
70662
|
return {
|
|
70430
|
-
agentsMd: fs33.existsSync(
|
|
70431
|
-
agentMd: fs33.existsSync(
|
|
70432
|
-
claudeMd: fs33.existsSync(
|
|
70433
|
-
cursorDir: fs33.existsSync(
|
|
70434
|
-
claudeDir: fs33.existsSync(
|
|
70435
|
-
codexHome: fs33.existsSync(
|
|
70663
|
+
agentsMd: fs33.existsSync(path40.join(repoPath, AGENTS_MD)),
|
|
70664
|
+
agentMd: fs33.existsSync(path40.join(repoPath, LEGACY_AGENT_MD)),
|
|
70665
|
+
claudeMd: fs33.existsSync(path40.join(repoPath, CLAUDE_MD)),
|
|
70666
|
+
cursorDir: fs33.existsSync(path40.join(repoPath, ".cursor")),
|
|
70667
|
+
claudeDir: fs33.existsSync(path40.join(repoPath, ".claude")),
|
|
70668
|
+
codexHome: fs33.existsSync(path40.join(os16.homedir(), ".codex"))
|
|
70436
70669
|
};
|
|
70437
70670
|
}
|
|
70438
70671
|
function formatDetectionReport(detection) {
|
|
@@ -70533,7 +70766,7 @@ function mergeAgentsMdContent(existing, incoming) {
|
|
|
70533
70766
|
return content;
|
|
70534
70767
|
}
|
|
70535
70768
|
function upsertAgentsMdHarSection(repoPath, options = {}) {
|
|
70536
|
-
const dest =
|
|
70769
|
+
const dest = path40.join(repoPath, AGENTS_MD);
|
|
70537
70770
|
const section = loadHarAgentsSectionFromTemplate();
|
|
70538
70771
|
if (!fs33.existsSync(dest)) {
|
|
70539
70772
|
writeFileSafe(dest, loadAgentsMdTemplate());
|
|
@@ -70564,8 +70797,8 @@ function upsertAgentsMdHarSection(repoPath, options = {}) {
|
|
|
70564
70797
|
return action;
|
|
70565
70798
|
}
|
|
70566
70799
|
function migrateLegacyAgentMd(repoPath) {
|
|
70567
|
-
const legacyPath =
|
|
70568
|
-
const agentsPath =
|
|
70800
|
+
const legacyPath = path40.join(repoPath, LEGACY_AGENT_MD);
|
|
70801
|
+
const agentsPath = path40.join(repoPath, AGENTS_MD);
|
|
70569
70802
|
if (!fs33.existsSync(legacyPath)) return false;
|
|
70570
70803
|
const legacy = fs33.readFileSync(legacyPath, "utf8");
|
|
70571
70804
|
if (!fs33.existsSync(agentsPath)) {
|
|
@@ -70606,8 +70839,8 @@ This repository uses a \`.har/\` harness. Read [AGENTS.md](./AGENTS.md) and
|
|
|
70606
70839
|
[\`.har/README.md\`](./.har/README.md) before making changes.
|
|
70607
70840
|
${CLAUDE_HAR_SECTION_END}`;
|
|
70608
70841
|
function ensureClaudeMdPointer(repoPath, options = {}) {
|
|
70609
|
-
const dest =
|
|
70610
|
-
const projectName =
|
|
70842
|
+
const dest = path40.join(repoPath, CLAUDE_MD);
|
|
70843
|
+
const projectName = path40.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
|
|
70611
70844
|
const thin = loadClaudeMdTemplate(projectName);
|
|
70612
70845
|
if (!fs33.existsSync(dest)) {
|
|
70613
70846
|
writeFileSafe(dest, thin);
|
|
@@ -70762,10 +70995,10 @@ var AGENT_MD_PROPOSAL = "AGENT.md.proposed";
|
|
|
70762
70995
|
var AGENT_MD_PROPOSAL_META = "AGENT.md.proposed.meta.json";
|
|
70763
70996
|
function readAgentMdProposal(repoPath) {
|
|
70764
70997
|
const harnessDir = getHarnessDir(repoPath);
|
|
70765
|
-
const proposalPath =
|
|
70766
|
-
const metaPath =
|
|
70767
|
-
const legacyProposalPath =
|
|
70768
|
-
const legacyMetaPath =
|
|
70998
|
+
const proposalPath = path41.join(harnessDir, AGENTS_MD_PROPOSAL);
|
|
70999
|
+
const metaPath = path41.join(harnessDir, AGENTS_MD_PROPOSAL_META);
|
|
71000
|
+
const legacyProposalPath = path41.join(harnessDir, AGENT_MD_PROPOSAL);
|
|
71001
|
+
const legacyMetaPath = path41.join(harnessDir, AGENT_MD_PROPOSAL_META);
|
|
70769
71002
|
const resolvedProposal = fs34.existsSync(proposalPath) ? proposalPath : fs34.existsSync(legacyProposalPath) ? legacyProposalPath : null;
|
|
70770
71003
|
if (!resolvedProposal) return null;
|
|
70771
71004
|
const resolvedMeta = resolvedProposal === proposalPath ? metaPath : legacyMetaPath;
|
|
@@ -70791,7 +71024,7 @@ function clearAgentMdProposal(repoPath) {
|
|
|
70791
71024
|
AGENT_MD_PROPOSAL,
|
|
70792
71025
|
AGENT_MD_PROPOSAL_META
|
|
70793
71026
|
]) {
|
|
70794
|
-
const p =
|
|
71027
|
+
const p = path41.join(harnessDir, file);
|
|
70795
71028
|
if (fs34.existsSync(p)) fs34.unlinkSync(p);
|
|
70796
71029
|
}
|
|
70797
71030
|
}
|
|
@@ -70805,7 +71038,7 @@ function wouldProposalShrinkExisting(existing, proposal) {
|
|
|
70805
71038
|
function applyAgentMdProposalMerge(repoPath, options = {}) {
|
|
70806
71039
|
const proposal = readAgentMdProposal(repoPath);
|
|
70807
71040
|
if (!proposal) return false;
|
|
70808
|
-
const agentsMdPath =
|
|
71041
|
+
const agentsMdPath = path41.join(repoPath, AGENTS_MD);
|
|
70809
71042
|
if (fs34.existsSync(agentsMdPath)) {
|
|
70810
71043
|
const existing = fs34.readFileSync(agentsMdPath, "utf8");
|
|
70811
71044
|
if (wouldProposalShrinkExisting(existing, proposal.content)) {
|
|
@@ -70831,7 +71064,7 @@ function finalizeAgentsMdInstructionFiles(repoPath) {
|
|
|
70831
71064
|
|
|
70832
71065
|
// src/harness/validator.ts
|
|
70833
71066
|
var fs35 = __toESM(require("fs"));
|
|
70834
|
-
var
|
|
71067
|
+
var path42 = __toESM(require("path"));
|
|
70835
71068
|
init_shell();
|
|
70836
71069
|
init_manifest();
|
|
70837
71070
|
init_stages();
|
|
@@ -70893,13 +71126,13 @@ function validateHarness(repoPath) {
|
|
|
70893
71126
|
};
|
|
70894
71127
|
}
|
|
70895
71128
|
for (const file of getRequiredFiles(repoPath)) {
|
|
70896
|
-
const filePath =
|
|
71129
|
+
const filePath = path42.join(harnessDir, file);
|
|
70897
71130
|
if (!fs35.existsSync(filePath)) {
|
|
70898
71131
|
issues.push({ file, message: "Required file missing", severity: "error" });
|
|
70899
71132
|
}
|
|
70900
71133
|
}
|
|
70901
71134
|
for (const script of SHELL_SCRIPTS) {
|
|
70902
|
-
const scriptPath =
|
|
71135
|
+
const scriptPath = path42.join(harnessDir, script);
|
|
70903
71136
|
if (!fs35.existsSync(scriptPath)) continue;
|
|
70904
71137
|
const stat = fs35.statSync(scriptPath);
|
|
70905
71138
|
if (!(stat.mode & 73)) {
|
|
@@ -70916,7 +71149,7 @@ function validateHarness(repoPath) {
|
|
|
70916
71149
|
}
|
|
70917
71150
|
const manifest = readManifest(repoPath);
|
|
70918
71151
|
const profile = manifest?.profile ?? "default";
|
|
70919
|
-
const ecosystemPath =
|
|
71152
|
+
const ecosystemPath = path42.join(harnessDir, "ecosystem.agent.template.cjs");
|
|
70920
71153
|
if (profile !== "cli" && fs35.existsSync(ecosystemPath)) {
|
|
70921
71154
|
const content = fs35.readFileSync(ecosystemPath, "utf8");
|
|
70922
71155
|
if (!content.includes("module.exports")) {
|
|
@@ -70927,7 +71160,7 @@ function validateHarness(repoPath) {
|
|
|
70927
71160
|
});
|
|
70928
71161
|
}
|
|
70929
71162
|
}
|
|
70930
|
-
const harnessEnvPath =
|
|
71163
|
+
const harnessEnvPath = path42.join(harnessDir, "harness.env");
|
|
70931
71164
|
if (fs35.existsSync(harnessEnvPath)) {
|
|
70932
71165
|
const content = fs35.readFileSync(harnessEnvPath, "utf8");
|
|
70933
71166
|
if (content.includes("TODO: set migrate command")) {
|
|
@@ -70937,14 +71170,14 @@ function validateHarness(repoPath) {
|
|
|
70937
71170
|
issues.push({ file: "harness.env", message: "Seed command still has TODO", severity: "warning" });
|
|
70938
71171
|
}
|
|
70939
71172
|
}
|
|
70940
|
-
const verifyPath =
|
|
71173
|
+
const verifyPath = path42.join(harnessDir, "verify.sh");
|
|
70941
71174
|
if (fs35.existsSync(verifyPath)) {
|
|
70942
71175
|
const content = fs35.readFileSync(verifyPath, "utf8");
|
|
70943
71176
|
if (content.includes("echo 'TODO:")) {
|
|
70944
71177
|
issues.push({ file: "verify.sh", message: "Verification steps still have TODO placeholders", severity: "warning" });
|
|
70945
71178
|
}
|
|
70946
71179
|
}
|
|
70947
|
-
const stagesPath =
|
|
71180
|
+
const stagesPath = path42.join(harnessDir, "stages.json");
|
|
70948
71181
|
if (fs35.existsSync(stagesPath)) {
|
|
70949
71182
|
try {
|
|
70950
71183
|
JSON.parse(fs35.readFileSync(stagesPath, "utf8"));
|
|
@@ -70962,7 +71195,7 @@ function validateHarness(repoPath) {
|
|
|
70962
71195
|
} else {
|
|
70963
71196
|
issues.push({ file: "stages.json", message: "Stage registry missing", severity: "warning" });
|
|
70964
71197
|
}
|
|
70965
|
-
const readmePath =
|
|
71198
|
+
const readmePath = path42.join(harnessDir, "README.md");
|
|
70966
71199
|
if (fs35.existsSync(readmePath)) {
|
|
70967
71200
|
const content = fs35.readFileSync(readmePath, "utf8");
|
|
70968
71201
|
if (!content.includes(".har")) {
|
|
@@ -70978,7 +71211,7 @@ function validateHarness(repoPath) {
|
|
|
70978
71211
|
async function smokeTestHarness(repoPath) {
|
|
70979
71212
|
const harnessDir = getHarnessDir(repoPath);
|
|
70980
71213
|
const issues = [];
|
|
70981
|
-
const setupScript =
|
|
71214
|
+
const setupScript = path42.join(harnessDir, "setup-infra.sh");
|
|
70982
71215
|
if (fs35.existsSync(setupScript)) {
|
|
70983
71216
|
const result = run(`bash "${setupScript}"`, { cwd: repoPath });
|
|
70984
71217
|
if (result.code !== 0) {
|
|
@@ -70995,7 +71228,7 @@ async function smokeTestHarness(repoPath) {
|
|
|
70995
71228
|
|
|
70996
71229
|
// src/harness/drift.ts
|
|
70997
71230
|
var fs36 = __toESM(require("fs"));
|
|
70998
|
-
var
|
|
71231
|
+
var path43 = __toESM(require("path"));
|
|
70999
71232
|
init_env();
|
|
71000
71233
|
init_manifest();
|
|
71001
71234
|
init_stages();
|
|
@@ -71065,12 +71298,12 @@ function listBoilerplateFiles(boilerplateDir) {
|
|
|
71065
71298
|
return fs36.readdirSync(boilerplateDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
|
|
71066
71299
|
}
|
|
71067
71300
|
function compareHarnessToTemplate(repoPath) {
|
|
71068
|
-
const resolved =
|
|
71301
|
+
const resolved = path43.resolve(repoPath);
|
|
71069
71302
|
const manifest = readManifest(resolved);
|
|
71070
71303
|
const profile = manifest?.profile ?? "default";
|
|
71071
71304
|
const harnessDir = getHarnessDir(resolved);
|
|
71072
|
-
const projectName =
|
|
71073
|
-
const boilerplateDir =
|
|
71305
|
+
const projectName = path43.basename(resolved).toLowerCase().replace(/[^a-z0-9]/g, "_");
|
|
71306
|
+
const boilerplateDir = path43.join(resolveTemplatesDir(), PROFILE_DIRS[profile]);
|
|
71074
71307
|
const templateFiles = listBoilerplateFiles(boilerplateDir);
|
|
71075
71308
|
const missing = [];
|
|
71076
71309
|
const checksumMismatch = [];
|
|
@@ -71078,8 +71311,8 @@ function compareHarnessToTemplate(repoPath) {
|
|
|
71078
71311
|
const unchanged = [];
|
|
71079
71312
|
for (const file of templateFiles) {
|
|
71080
71313
|
const harnessFile = harnessFileForTemplate(file);
|
|
71081
|
-
const templatePath =
|
|
71082
|
-
const harnessPath =
|
|
71314
|
+
const templatePath = path43.join(boilerplateDir, file);
|
|
71315
|
+
const harnessPath = path43.join(harnessDir, harnessFile);
|
|
71083
71316
|
let templateContent = fs36.readFileSync(templatePath, "utf8");
|
|
71084
71317
|
if (file === "harness.env") {
|
|
71085
71318
|
templateContent = substituteProjectName(templateContent, projectName);
|
|
@@ -71098,7 +71331,7 @@ function compareHarnessToTemplate(repoPath) {
|
|
|
71098
71331
|
}
|
|
71099
71332
|
if (fs36.existsSync(harnessDir)) {
|
|
71100
71333
|
for (const file of fs36.readdirSync(harnessDir)) {
|
|
71101
|
-
const full =
|
|
71334
|
+
const full = path43.join(harnessDir, file);
|
|
71102
71335
|
if (!fs36.statSync(full).isFile()) continue;
|
|
71103
71336
|
if (file === "manifest.json" || file === "plugins.json" || file.startsWith("ADAPT-PROMPT")) {
|
|
71104
71337
|
continue;
|
|
@@ -71128,19 +71361,19 @@ function compareHarnessToTemplate(repoPath) {
|
|
|
71128
71361
|
// src/harness/maintain-bundle.ts
|
|
71129
71362
|
var fs41 = __toESM(require("fs"));
|
|
71130
71363
|
var os18 = __toESM(require("os"));
|
|
71131
|
-
var
|
|
71364
|
+
var path47 = __toESM(require("path"));
|
|
71132
71365
|
init_file_ops();
|
|
71133
71366
|
init_shell();
|
|
71134
71367
|
init_manifest();
|
|
71135
71368
|
|
|
71136
71369
|
// src/harness/plugin-drift.ts
|
|
71137
71370
|
var fs40 = __toESM(require("fs"));
|
|
71138
|
-
var
|
|
71371
|
+
var path46 = __toESM(require("path"));
|
|
71139
71372
|
init_manifest();
|
|
71140
71373
|
|
|
71141
71374
|
// src/harness/plugins.ts
|
|
71142
71375
|
var fs39 = __toESM(require("fs"));
|
|
71143
|
-
var
|
|
71376
|
+
var path45 = __toESM(require("path"));
|
|
71144
71377
|
init_zod();
|
|
71145
71378
|
init_logging();
|
|
71146
71379
|
|
|
@@ -71155,12 +71388,12 @@ function harnessExists(repoPath) {
|
|
|
71155
71388
|
var import_child_process11 = require("child_process");
|
|
71156
71389
|
var fs38 = __toESM(require("fs"));
|
|
71157
71390
|
var os17 = __toESM(require("os"));
|
|
71158
|
-
var
|
|
71391
|
+
var path44 = __toESM(require("path"));
|
|
71159
71392
|
function hasManifest(dir) {
|
|
71160
|
-
return fs38.existsSync(
|
|
71393
|
+
return fs38.existsSync(path44.join(dir, "template.manifest.json"));
|
|
71161
71394
|
}
|
|
71162
71395
|
function readPackageVersion(dir) {
|
|
71163
|
-
const pkgPath =
|
|
71396
|
+
const pkgPath = path44.join(dir, "package.json");
|
|
71164
71397
|
if (!fs38.existsSync(pkgPath)) return void 0;
|
|
71165
71398
|
try {
|
|
71166
71399
|
const pkg = JSON.parse(fs38.readFileSync(pkgPath, "utf8"));
|
|
@@ -71170,7 +71403,7 @@ function readPackageVersion(dir) {
|
|
|
71170
71403
|
}
|
|
71171
71404
|
}
|
|
71172
71405
|
function readManifestId(dir) {
|
|
71173
|
-
const manifestPath =
|
|
71406
|
+
const manifestPath = path44.join(dir, "template.manifest.json");
|
|
71174
71407
|
if (!fs38.existsSync(manifestPath)) return void 0;
|
|
71175
71408
|
try {
|
|
71176
71409
|
const raw = JSON.parse(fs38.readFileSync(manifestPath, "utf8"));
|
|
@@ -71191,24 +71424,24 @@ function looksLikeNpm(spec) {
|
|
|
71191
71424
|
return /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*(@.+)?$/i.test(spec);
|
|
71192
71425
|
}
|
|
71193
71426
|
function resolveBundledDir(pluginId) {
|
|
71194
|
-
const dir =
|
|
71427
|
+
const dir = path44.join(resolveTemplatesDir(), "plugins", pluginId);
|
|
71195
71428
|
return hasManifest(dir) ? dir : null;
|
|
71196
71429
|
}
|
|
71197
71430
|
function expandHome(p) {
|
|
71198
|
-
if (p.startsWith("~/")) return
|
|
71431
|
+
if (p.startsWith("~/")) return path44.join(os17.homedir(), p.slice(2));
|
|
71199
71432
|
if (p === "~") return os17.homedir();
|
|
71200
71433
|
return p;
|
|
71201
71434
|
}
|
|
71202
71435
|
function resolvePathSpec(spec) {
|
|
71203
71436
|
const raw = spec.startsWith("file:") ? spec.slice("file:".length) : spec;
|
|
71204
|
-
const dir =
|
|
71437
|
+
const dir = path44.resolve(expandHome(raw));
|
|
71205
71438
|
if (!fs38.existsSync(dir) || !fs38.statSync(dir).isDirectory()) {
|
|
71206
71439
|
throw new Error(`Plugin path not found: ${spec}`);
|
|
71207
71440
|
}
|
|
71208
71441
|
if (!hasManifest(dir)) {
|
|
71209
71442
|
throw new Error(`No template.manifest.json in ${dir}`);
|
|
71210
71443
|
}
|
|
71211
|
-
const id = readManifestId(dir) ??
|
|
71444
|
+
const id = readManifestId(dir) ?? path44.basename(dir);
|
|
71212
71445
|
return {
|
|
71213
71446
|
id,
|
|
71214
71447
|
kind: "path",
|
|
@@ -71219,7 +71452,7 @@ function resolvePathSpec(spec) {
|
|
|
71219
71452
|
};
|
|
71220
71453
|
}
|
|
71221
71454
|
function makeTempDir(prefix) {
|
|
71222
|
-
return fs38.mkdtempSync(
|
|
71455
|
+
return fs38.mkdtempSync(path44.join(os17.tmpdir(), prefix));
|
|
71223
71456
|
}
|
|
71224
71457
|
function resolveNpmSpec(spec) {
|
|
71225
71458
|
const tmp = makeTempDir("har-plugin-npm-");
|
|
@@ -71234,16 +71467,16 @@ function resolveNpmSpec(spec) {
|
|
|
71234
71467
|
if (tarballs.length === 0) {
|
|
71235
71468
|
throw new Error(`npm pack produced no tarball for ${spec}`);
|
|
71236
71469
|
}
|
|
71237
|
-
const extractDir =
|
|
71470
|
+
const extractDir = path44.join(tmp, "extract");
|
|
71238
71471
|
fs38.mkdirSync(extractDir);
|
|
71239
|
-
(0, import_child_process11.execFileSync)("tar", ["-xzf",
|
|
71472
|
+
(0, import_child_process11.execFileSync)("tar", ["-xzf", path44.join(tmp, tarballs[0]), "-C", extractDir], {
|
|
71240
71473
|
encoding: "utf8",
|
|
71241
71474
|
stdio: ["ignore", "pipe", "pipe"]
|
|
71242
71475
|
});
|
|
71243
|
-
const packageDir =
|
|
71476
|
+
const packageDir = path44.join(extractDir, "package");
|
|
71244
71477
|
let dir = packageDir;
|
|
71245
71478
|
if (!hasManifest(dir)) {
|
|
71246
|
-
const nested = fs38.readdirSync(extractDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) =>
|
|
71479
|
+
const nested = fs38.readdirSync(extractDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path44.join(extractDir, e.name)).find((d) => hasManifest(d));
|
|
71247
71480
|
if (!nested) {
|
|
71248
71481
|
throw new Error(
|
|
71249
71482
|
`npm package ${spec} has no template.manifest.json (not a HAR plugin bundle)`
|
|
@@ -71271,7 +71504,7 @@ function resolveNpmSpec(spec) {
|
|
|
71271
71504
|
function resolveGitSpec(spec) {
|
|
71272
71505
|
const tmp = makeTempDir("har-plugin-git-");
|
|
71273
71506
|
const cleanupDirs = [tmp];
|
|
71274
|
-
const cloneDir =
|
|
71507
|
+
const cloneDir = path44.join(tmp, "repo");
|
|
71275
71508
|
try {
|
|
71276
71509
|
let url = spec;
|
|
71277
71510
|
if (spec.startsWith("github:")) {
|
|
@@ -71290,16 +71523,16 @@ function resolveGitSpec(spec) {
|
|
|
71290
71523
|
});
|
|
71291
71524
|
let dir = cloneDir;
|
|
71292
71525
|
if (!hasManifest(dir)) {
|
|
71293
|
-
const pluginsRoot =
|
|
71526
|
+
const pluginsRoot = path44.join(cloneDir, "plugins");
|
|
71294
71527
|
if (fs38.existsSync(pluginsRoot)) {
|
|
71295
|
-
const child = fs38.readdirSync(pluginsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) =>
|
|
71528
|
+
const child = fs38.readdirSync(pluginsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path44.join(pluginsRoot, e.name)).find((d) => hasManifest(d));
|
|
71296
71529
|
if (child) dir = child;
|
|
71297
71530
|
}
|
|
71298
71531
|
}
|
|
71299
71532
|
if (!hasManifest(dir)) {
|
|
71300
71533
|
throw new Error(`Git repo ${spec} has no template.manifest.json (not a HAR plugin bundle)`);
|
|
71301
71534
|
}
|
|
71302
|
-
const id = readManifestId(dir) ??
|
|
71535
|
+
const id = readManifestId(dir) ?? path44.basename(url.replace(/\.git$/, ""));
|
|
71303
71536
|
return {
|
|
71304
71537
|
id,
|
|
71305
71538
|
kind: "git",
|
|
@@ -71358,9 +71591,9 @@ function resolvePluginSource(spec) {
|
|
|
71358
71591
|
);
|
|
71359
71592
|
}
|
|
71360
71593
|
function listBundledPluginIds() {
|
|
71361
|
-
const root =
|
|
71594
|
+
const root = path44.join(resolveTemplatesDir(), "plugins");
|
|
71362
71595
|
if (!fs38.existsSync(root)) return [];
|
|
71363
|
-
return fs38.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => hasManifest(
|
|
71596
|
+
return fs38.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => hasManifest(path44.join(root, name))).sort();
|
|
71364
71597
|
}
|
|
71365
71598
|
function cleanupResolvedPlugin(source) {
|
|
71366
71599
|
for (const dir of source.cleanupDirs) {
|
|
@@ -71416,14 +71649,14 @@ function primaryStageId(manifest) {
|
|
|
71416
71649
|
return manifest.stageId ?? stages[0].id;
|
|
71417
71650
|
}
|
|
71418
71651
|
function resolveBundledPluginDir(pluginId) {
|
|
71419
|
-
const dir =
|
|
71652
|
+
const dir = path45.join(resolveTemplatesDir(), "plugins", pluginId);
|
|
71420
71653
|
if (!fs39.existsSync(dir)) {
|
|
71421
71654
|
throw new Error(`Plugin not found: ${pluginId}. Run npm run build.`);
|
|
71422
71655
|
}
|
|
71423
71656
|
return dir;
|
|
71424
71657
|
}
|
|
71425
71658
|
function readPluginManifestFromDir(pluginDir, expectedId) {
|
|
71426
|
-
const manifestPath =
|
|
71659
|
+
const manifestPath = path45.join(pluginDir, "template.manifest.json");
|
|
71427
71660
|
if (!fs39.existsSync(manifestPath)) {
|
|
71428
71661
|
throw new Error(`No template.manifest.json in ${pluginDir}`);
|
|
71429
71662
|
}
|
|
@@ -71442,14 +71675,14 @@ function readPluginManifest(pluginId) {
|
|
|
71442
71675
|
return readPluginManifestFromDir(resolveBundledPluginDir(pluginId), pluginId);
|
|
71443
71676
|
}
|
|
71444
71677
|
function ensureParentDir(filePath) {
|
|
71445
|
-
const parent =
|
|
71678
|
+
const parent = path45.dirname(filePath);
|
|
71446
71679
|
if (!fs39.existsSync(parent)) {
|
|
71447
71680
|
fs39.mkdirSync(parent, { recursive: true });
|
|
71448
71681
|
}
|
|
71449
71682
|
}
|
|
71450
71683
|
function copyPluginFile(pluginDir, file, repoPath, force) {
|
|
71451
|
-
const srcPath =
|
|
71452
|
-
const destPath =
|
|
71684
|
+
const srcPath = path45.join(pluginDir, file.src);
|
|
71685
|
+
const destPath = path45.join(repoPath, file.dest);
|
|
71453
71686
|
if (!fs39.existsSync(srcPath)) {
|
|
71454
71687
|
throw new Error(`Plugin file missing: ${file.src}`);
|
|
71455
71688
|
}
|
|
@@ -71466,11 +71699,11 @@ function copyPluginFile(pluginDir, file, repoPath, force) {
|
|
|
71466
71699
|
return { written: true, path: file.dest };
|
|
71467
71700
|
}
|
|
71468
71701
|
function mergePackageJson(repoPath, pluginDir, fragmentRelPath, warnings) {
|
|
71469
|
-
const packagePath =
|
|
71702
|
+
const packagePath = path45.join(repoPath, "package.json");
|
|
71470
71703
|
if (!fs39.existsSync(packagePath)) {
|
|
71471
71704
|
throw new Error("No package.json in repo root. Add one before applying this plugin.");
|
|
71472
71705
|
}
|
|
71473
|
-
const fragmentPath =
|
|
71706
|
+
const fragmentPath = path45.join(pluginDir, fragmentRelPath);
|
|
71474
71707
|
if (!fs39.existsSync(fragmentPath)) {
|
|
71475
71708
|
throw new Error(`Package fragment missing: ${fragmentRelPath}`);
|
|
71476
71709
|
}
|
|
@@ -71532,7 +71765,7 @@ function assertStagesNotPresent(repoPath, stageIds, force) {
|
|
|
71532
71765
|
if (force) return;
|
|
71533
71766
|
const registry2 = readStageRegistry(repoPath);
|
|
71534
71767
|
for (const stageId of stageIds) {
|
|
71535
|
-
const scriptPath =
|
|
71768
|
+
const scriptPath = path45.join(repoPath, ".har", "stages", `${stageId}.sh`);
|
|
71536
71769
|
if (fs39.existsSync(scriptPath)) {
|
|
71537
71770
|
throw new Error(
|
|
71538
71771
|
`Stage script already exists: .har/stages/${stageId}.sh. Use --force to overwrite.`
|
|
@@ -71546,7 +71779,7 @@ function assertStagesNotPresent(repoPath, stageIds, force) {
|
|
|
71546
71779
|
}
|
|
71547
71780
|
}
|
|
71548
71781
|
function applyPluginFromDir(repoPath, pluginDir, options, meta) {
|
|
71549
|
-
const resolved =
|
|
71782
|
+
const resolved = path45.resolve(repoPath);
|
|
71550
71783
|
const force = options.force ?? false;
|
|
71551
71784
|
const warnings = [];
|
|
71552
71785
|
const filesWritten = [];
|
|
@@ -71566,7 +71799,7 @@ function applyPluginFromDir(repoPath, pluginDir, options, meta) {
|
|
|
71566
71799
|
if (file.skipFlag === "skipCi" && options.skipCi) {
|
|
71567
71800
|
continue;
|
|
71568
71801
|
}
|
|
71569
|
-
if (fs39.existsSync(
|
|
71802
|
+
if (fs39.existsSync(path45.join(resolved, file.dest)) && !force) {
|
|
71570
71803
|
warnings.push(`Skipped optional file (exists): ${file.dest}`);
|
|
71571
71804
|
continue;
|
|
71572
71805
|
}
|
|
@@ -71632,12 +71865,12 @@ function listPluginIds() {
|
|
|
71632
71865
|
init_stages();
|
|
71633
71866
|
var PACKAGE_SECTIONS = ["scripts", "devDependencies"];
|
|
71634
71867
|
function detectInstalledPlugins(repoPath) {
|
|
71635
|
-
const resolved =
|
|
71868
|
+
const resolved = path46.resolve(repoPath);
|
|
71636
71869
|
const ledger = readPluginLedger(resolved);
|
|
71637
71870
|
if (ledger && ledger.plugins.length > 0) {
|
|
71638
71871
|
return ledger.plugins.map((p) => p.id).sort();
|
|
71639
71872
|
}
|
|
71640
|
-
const registryPath =
|
|
71873
|
+
const registryPath = path46.join(resolved, ".har", "stages.json");
|
|
71641
71874
|
if (!fs40.existsSync(registryPath)) return [];
|
|
71642
71875
|
const registry2 = readStageRegistry(resolved);
|
|
71643
71876
|
const stageIds = new Set(registry2.stages.map((stage) => stage.id));
|
|
@@ -71655,7 +71888,7 @@ function detectInstalledPlugins(repoPath) {
|
|
|
71655
71888
|
return installed.sort();
|
|
71656
71889
|
}
|
|
71657
71890
|
function pluginTemplatePath(pluginId, srcRel) {
|
|
71658
|
-
return
|
|
71891
|
+
return path46.join(resolveTemplatesDir(), "plugins", pluginId, srcRel);
|
|
71659
71892
|
}
|
|
71660
71893
|
function resolvePluginTemplateDir(repoPath, pluginId) {
|
|
71661
71894
|
const ledger = readPluginLedger(repoPath);
|
|
@@ -71667,8 +71900,8 @@ function resolvePluginTemplateDir(repoPath, pluginId) {
|
|
|
71667
71900
|
} catch {
|
|
71668
71901
|
}
|
|
71669
71902
|
}
|
|
71670
|
-
const bundled =
|
|
71671
|
-
if (fs40.existsSync(
|
|
71903
|
+
const bundled = path46.join(resolveTemplatesDir(), "plugins", pluginId);
|
|
71904
|
+
if (fs40.existsSync(path46.join(bundled, "template.manifest.json"))) {
|
|
71672
71905
|
return bundled;
|
|
71673
71906
|
}
|
|
71674
71907
|
return null;
|
|
@@ -71682,7 +71915,7 @@ function listPluginDestPaths(pluginId, repoPath) {
|
|
|
71682
71915
|
const paths = manifest.files.map((file) => file.dest);
|
|
71683
71916
|
if (manifest.optionalFiles) {
|
|
71684
71917
|
for (const file of manifest.optionalFiles) {
|
|
71685
|
-
if (fs40.existsSync(
|
|
71918
|
+
if (fs40.existsSync(path46.join(repoPath, file.dest))) {
|
|
71686
71919
|
paths.push(file.dest);
|
|
71687
71920
|
}
|
|
71688
71921
|
}
|
|
@@ -71741,7 +71974,7 @@ function readTemplatePluginFile(pluginId, dest) {
|
|
|
71741
71974
|
return null;
|
|
71742
71975
|
}
|
|
71743
71976
|
function readInstalledPluginFile(repoPath, pluginId, dest) {
|
|
71744
|
-
const installedPath =
|
|
71977
|
+
const installedPath = path46.join(path46.resolve(repoPath), dest);
|
|
71745
71978
|
if (!fs40.existsSync(installedPath)) return null;
|
|
71746
71979
|
const content = fs40.readFileSync(installedPath, "utf8");
|
|
71747
71980
|
const manifest = readPluginManifest(pluginId);
|
|
@@ -71762,7 +71995,7 @@ function pluginActionHint(pluginId, dest, kind) {
|
|
|
71762
71995
|
}
|
|
71763
71996
|
function comparePluginToTemplate(repoPath, pluginId) {
|
|
71764
71997
|
const manifest = readPluginManifest(pluginId);
|
|
71765
|
-
const resolved =
|
|
71998
|
+
const resolved = path46.resolve(repoPath);
|
|
71766
71999
|
const destPaths = listPluginDestPaths(pluginId, resolved);
|
|
71767
72000
|
const missing = [];
|
|
71768
72001
|
const checksumMismatch = [];
|
|
@@ -71777,7 +72010,7 @@ function comparePluginToTemplate(repoPath, pluginId) {
|
|
|
71777
72010
|
}
|
|
71778
72011
|
if (dest === "package.json") {
|
|
71779
72012
|
const fragmentRel = manifest.merge?.[dest];
|
|
71780
|
-
const installedPath =
|
|
72013
|
+
const installedPath = path46.join(resolved, dest);
|
|
71781
72014
|
const installedRaw = fs40.readFileSync(installedPath, "utf8");
|
|
71782
72015
|
if (fragmentRel && pluginKeysMatch(installedRaw, readBundledPluginFile(pluginId, fragmentRel))) {
|
|
71783
72016
|
unchanged.push(dest);
|
|
@@ -71804,7 +72037,7 @@ function comparePluginToTemplate(repoPath, pluginId) {
|
|
|
71804
72037
|
}
|
|
71805
72038
|
function compareInstalledPluginsToTemplate(repoPath) {
|
|
71806
72039
|
return detectInstalledPlugins(repoPath).filter((pluginId) => {
|
|
71807
|
-
const bundled =
|
|
72040
|
+
const bundled = path46.join(resolveTemplatesDir(), "plugins", pluginId, "template.manifest.json");
|
|
71808
72041
|
return fs40.existsSync(bundled);
|
|
71809
72042
|
}).map((pluginId) => comparePluginToTemplate(repoPath, pluginId));
|
|
71810
72043
|
}
|
|
@@ -71843,13 +72076,13 @@ function substituteProjectName2(content, projectName) {
|
|
|
71843
72076
|
return content.replace(/__PROJECT_NAME__/g, projectName).replace(/template___PROJECT_NAME__/g, `template_${projectName}`);
|
|
71844
72077
|
}
|
|
71845
72078
|
function projectNameFromRepo(repoPath) {
|
|
71846
|
-
return
|
|
72079
|
+
return path47.basename(repoPath).toLowerCase().replace(/[^a-z0-9]/g, "_");
|
|
71847
72080
|
}
|
|
71848
72081
|
function boilerplateDirForProfile(profile) {
|
|
71849
|
-
return
|
|
72082
|
+
return path47.join(resolveTemplatesDir(), PROFILE_DIRS[profile]);
|
|
71850
72083
|
}
|
|
71851
72084
|
function readBundledTemplateContent(repoPath, profile, file) {
|
|
71852
|
-
const templatePath =
|
|
72085
|
+
const templatePath = path47.join(boilerplateDirForProfile(profile), templateFileForHarness(file));
|
|
71853
72086
|
let content = fs41.readFileSync(templatePath, "utf8");
|
|
71854
72087
|
if (file === "harness.env") {
|
|
71855
72088
|
content = substituteProjectName2(content, projectNameFromRepo(repoPath));
|
|
@@ -71881,10 +72114,10 @@ function actionHint(file, kind) {
|
|
|
71881
72114
|
return `Read maintain/diffs/${file}.diff and merge into .har/${file}.`;
|
|
71882
72115
|
}
|
|
71883
72116
|
function createUnifiedDiff(installedContent, templateContent, installedLabel, templateLabel) {
|
|
71884
|
-
const tmpDir = fs41.mkdtempSync(
|
|
72117
|
+
const tmpDir = fs41.mkdtempSync(path47.join(os18.tmpdir(), "har-maintain-diff-"));
|
|
71885
72118
|
try {
|
|
71886
|
-
const installedPath =
|
|
71887
|
-
const templatePath =
|
|
72119
|
+
const installedPath = path47.join(tmpDir, "installed");
|
|
72120
|
+
const templatePath = path47.join(tmpDir, "template");
|
|
71888
72121
|
fs41.writeFileSync(installedPath, installedContent);
|
|
71889
72122
|
fs41.writeFileSync(templatePath, templateContent);
|
|
71890
72123
|
const result = run(`diff -u "${installedPath}" "${templatePath}"`);
|
|
@@ -71910,7 +72143,7 @@ function buildActions(repoPath, profile, drift) {
|
|
|
71910
72143
|
});
|
|
71911
72144
|
}
|
|
71912
72145
|
for (const file of drift.checksumMismatch) {
|
|
71913
|
-
const installedPath =
|
|
72146
|
+
const installedPath = path47.join(harnessDir, file);
|
|
71914
72147
|
const installedRel = `maintain/installed/${file}`;
|
|
71915
72148
|
const templateRel = `maintain/templates/${file}`;
|
|
71916
72149
|
const diffRel = `maintain/diffs/${file}.diff`;
|
|
@@ -72070,16 +72303,16 @@ function buildReadme(report) {
|
|
|
72070
72303
|
}
|
|
72071
72304
|
function writeBundleArtifacts(repoPath, profile, drift, report) {
|
|
72072
72305
|
const harnessDir = getHarnessDir(repoPath);
|
|
72073
|
-
const bundleDir =
|
|
72306
|
+
const bundleDir = path47.join(harnessDir, MAINTAIN_DIR);
|
|
72074
72307
|
if (fs41.existsSync(bundleDir)) {
|
|
72075
72308
|
fs41.rmSync(bundleDir, { recursive: true, force: true });
|
|
72076
72309
|
}
|
|
72077
72310
|
const dirs = [
|
|
72078
72311
|
bundleDir,
|
|
72079
|
-
|
|
72080
|
-
|
|
72081
|
-
|
|
72082
|
-
|
|
72312
|
+
path47.join(bundleDir, "templates"),
|
|
72313
|
+
path47.join(bundleDir, "installed"),
|
|
72314
|
+
path47.join(bundleDir, "diffs"),
|
|
72315
|
+
path47.join(bundleDir, "stale")
|
|
72083
72316
|
];
|
|
72084
72317
|
for (const dir of dirs) {
|
|
72085
72318
|
fs41.mkdirSync(dir, { recursive: true });
|
|
@@ -72087,11 +72320,11 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
|
|
|
72087
72320
|
const affectedFiles = [...drift.missing, ...drift.checksumMismatch];
|
|
72088
72321
|
for (const file of affectedFiles) {
|
|
72089
72322
|
const templateContent = readBundledTemplateContent(repoPath, profile, file);
|
|
72090
|
-
writeFileSafe(
|
|
72091
|
-
const harnessPath =
|
|
72323
|
+
writeFileSafe(path47.join(bundleDir, "templates", file), templateContent);
|
|
72324
|
+
const harnessPath = path47.join(harnessDir, file);
|
|
72092
72325
|
if (fs41.existsSync(harnessPath)) {
|
|
72093
72326
|
const installedContent = fs41.readFileSync(harnessPath, "utf8");
|
|
72094
|
-
writeFileSafe(
|
|
72327
|
+
writeFileSafe(path47.join(bundleDir, "installed", file), installedContent);
|
|
72095
72328
|
const diff = createUnifiedDiff(
|
|
72096
72329
|
installedContent,
|
|
72097
72330
|
templateContent,
|
|
@@ -72099,14 +72332,14 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
|
|
|
72099
72332
|
`templates/${file}`
|
|
72100
72333
|
);
|
|
72101
72334
|
if (diff) {
|
|
72102
|
-
writeFileSafe(
|
|
72335
|
+
writeFileSafe(path47.join(bundleDir, "diffs", `${file}.diff`), diff);
|
|
72103
72336
|
}
|
|
72104
72337
|
}
|
|
72105
72338
|
}
|
|
72106
|
-
writeFileSafe(
|
|
72107
|
-
writeFileSafe(
|
|
72339
|
+
writeFileSafe(path47.join(bundleDir, "README.md"), buildReadme(report));
|
|
72340
|
+
writeFileSafe(path47.join(bundleDir, "drift-report.json"), JSON.stringify(report, null, 2) + "\n");
|
|
72108
72341
|
writeFileSafe(
|
|
72109
|
-
|
|
72342
|
+
path47.join(bundleDir, "validation.json"),
|
|
72110
72343
|
JSON.stringify(report.validation, null, 2) + "\n"
|
|
72111
72344
|
);
|
|
72112
72345
|
if (report.stale.length > 0) {
|
|
@@ -72118,12 +72351,12 @@ function writeBundleArtifacts(repoPath, profile, drift, report) {
|
|
|
72118
72351
|
...report.stale.map((s) => `- **${s.file}** \u2014 ${s.hint}`),
|
|
72119
72352
|
""
|
|
72120
72353
|
];
|
|
72121
|
-
writeFileSafe(
|
|
72354
|
+
writeFileSafe(path47.join(bundleDir, "stale", "MANIFEST.md"), staleLines.join("\n"));
|
|
72122
72355
|
}
|
|
72123
72356
|
return bundleDir;
|
|
72124
72357
|
}
|
|
72125
72358
|
function ensureParentDir2(filePath) {
|
|
72126
|
-
const parent =
|
|
72359
|
+
const parent = path47.dirname(filePath);
|
|
72127
72360
|
if (!fs41.existsSync(parent)) {
|
|
72128
72361
|
fs41.mkdirSync(parent, { recursive: true });
|
|
72129
72362
|
}
|
|
@@ -72131,21 +72364,21 @@ function ensureParentDir2(filePath) {
|
|
|
72131
72364
|
function writePluginBundleArtifacts(repoPath, bundleDir, report) {
|
|
72132
72365
|
if (report.pluginActions.length === 0) return;
|
|
72133
72366
|
for (const action of report.pluginActions) {
|
|
72134
|
-
const pluginRoot =
|
|
72135
|
-
const templatesDir =
|
|
72136
|
-
const installedDir =
|
|
72137
|
-
const diffsDir =
|
|
72367
|
+
const pluginRoot = path47.join(bundleDir, "plugins", action.pluginId);
|
|
72368
|
+
const templatesDir = path47.join(pluginRoot, "templates");
|
|
72369
|
+
const installedDir = path47.join(pluginRoot, "installed");
|
|
72370
|
+
const diffsDir = path47.join(pluginRoot, "diffs");
|
|
72138
72371
|
for (const dir of [templatesDir, installedDir, diffsDir]) {
|
|
72139
72372
|
fs41.mkdirSync(dir, { recursive: true });
|
|
72140
72373
|
}
|
|
72141
72374
|
const templateContent = readTemplatePluginFile(action.pluginId, action.file);
|
|
72142
72375
|
if (templateContent === null) continue;
|
|
72143
|
-
const templatePath =
|
|
72376
|
+
const templatePath = path47.join(templatesDir, action.file);
|
|
72144
72377
|
ensureParentDir2(templatePath);
|
|
72145
72378
|
writeFileSafe(templatePath, templateContent);
|
|
72146
72379
|
const installedContent = readInstalledPluginFile(repoPath, action.pluginId, action.file);
|
|
72147
72380
|
if (installedContent !== null) {
|
|
72148
|
-
const installedPath =
|
|
72381
|
+
const installedPath = path47.join(installedDir, action.file);
|
|
72149
72382
|
ensureParentDir2(installedPath);
|
|
72150
72383
|
writeFileSafe(installedPath, installedContent);
|
|
72151
72384
|
const diff = createUnifiedDiff(
|
|
@@ -72155,7 +72388,7 @@ function writePluginBundleArtifacts(repoPath, bundleDir, report) {
|
|
|
72155
72388
|
`templates/${action.file}`
|
|
72156
72389
|
);
|
|
72157
72390
|
if (diff) {
|
|
72158
|
-
const diffPath =
|
|
72391
|
+
const diffPath = path47.join(diffsDir, `${action.file}.diff`);
|
|
72159
72392
|
ensureParentDir2(diffPath);
|
|
72160
72393
|
writeFileSafe(diffPath, diff);
|
|
72161
72394
|
}
|
|
@@ -72190,7 +72423,7 @@ function buildMaintainBundle(repoPath, validation2, drift) {
|
|
|
72190
72423
|
return { bundleDir, report };
|
|
72191
72424
|
}
|
|
72192
72425
|
function removeMaintainBundle(repoPath) {
|
|
72193
|
-
const bundleDir =
|
|
72426
|
+
const bundleDir = path47.join(getHarnessDir(repoPath), MAINTAIN_DIR);
|
|
72194
72427
|
if (fs41.existsSync(bundleDir)) {
|
|
72195
72428
|
fs41.rmSync(bundleDir, { recursive: true, force: true });
|
|
72196
72429
|
}
|
|
@@ -72285,7 +72518,7 @@ function listHarnessScripts(repoPath) {
|
|
|
72285
72518
|
return fs42.readdirSync(harnessDir).filter((name) => name.endsWith(".sh")).sort();
|
|
72286
72519
|
}
|
|
72287
72520
|
function describeProject(repoPath) {
|
|
72288
|
-
const resolved =
|
|
72521
|
+
const resolved = path48.resolve(repoPath);
|
|
72289
72522
|
const manifest = readManifest(resolved);
|
|
72290
72523
|
const present = harnessExists(resolved);
|
|
72291
72524
|
return {
|
|
@@ -72305,7 +72538,7 @@ function describeProject(repoPath) {
|
|
|
72305
72538
|
};
|
|
72306
72539
|
}
|
|
72307
72540
|
async function initHarness(options) {
|
|
72308
|
-
const repoPath =
|
|
72541
|
+
const repoPath = path48.resolve(options.repoPath);
|
|
72309
72542
|
if (!fs42.existsSync(repoPath)) {
|
|
72310
72543
|
throw new Error(`Path not found: ${repoPath}`);
|
|
72311
72544
|
}
|
|
@@ -72326,7 +72559,7 @@ async function initHarness(options) {
|
|
|
72326
72559
|
};
|
|
72327
72560
|
}
|
|
72328
72561
|
async function maintainHarness(options) {
|
|
72329
|
-
const repoPath =
|
|
72562
|
+
const repoPath = path48.resolve(options.repoPath);
|
|
72330
72563
|
const harnessDir = getHarnessDir(repoPath);
|
|
72331
72564
|
if (!fs42.existsSync(harnessDir)) {
|
|
72332
72565
|
throw new Error('No .har/ found. Run "har env init" first.');
|
|
@@ -72364,12 +72597,12 @@ function addPlugin(repoPath, pluginId, options = {}) {
|
|
|
72364
72597
|
|
|
72365
72598
|
// src/harness/custom-stage.ts
|
|
72366
72599
|
var fs43 = __toESM(require("fs"));
|
|
72367
|
-
var
|
|
72600
|
+
var path49 = __toESM(require("path"));
|
|
72368
72601
|
init_schema2();
|
|
72369
72602
|
init_stages();
|
|
72370
72603
|
var STAGE_ID_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
|
|
72371
72604
|
function addCustomStage(repoPath, options) {
|
|
72372
|
-
const resolved =
|
|
72605
|
+
const resolved = path49.resolve(repoPath);
|
|
72373
72606
|
if (!harnessExists(resolved)) {
|
|
72374
72607
|
throw new Error('No .har/ harness found. Run "har env init" first.');
|
|
72375
72608
|
}
|
|
@@ -72406,18 +72639,18 @@ function addCustomStage(repoPath, options) {
|
|
|
72406
72639
|
if (options.command) {
|
|
72407
72640
|
stage.command = options.command;
|
|
72408
72641
|
} else {
|
|
72409
|
-
const scriptRel =
|
|
72410
|
-
const scriptAbs =
|
|
72642
|
+
const scriptRel = path49.join("stages", `${id}.sh`);
|
|
72643
|
+
const scriptAbs = path49.join(resolved, ".har", scriptRel);
|
|
72411
72644
|
if (fs43.existsSync(scriptAbs) && !options.force) {
|
|
72412
72645
|
throw new Error(`Stage script already exists: .har/${scriptRel}. Use --force to overwrite.`);
|
|
72413
72646
|
}
|
|
72414
|
-
const skeletonPath =
|
|
72647
|
+
const skeletonPath = path49.join(
|
|
72415
72648
|
resolveTemplatesDir(),
|
|
72416
72649
|
"plugins",
|
|
72417
72650
|
"custom-stage-skeleton.sh"
|
|
72418
72651
|
);
|
|
72419
72652
|
const skeleton = fs43.readFileSync(skeletonPath, "utf8").replace(/__STAGE_ID__/g, id).replace(/__STAGE_KIND__/g, kind).replace(/__STAGE_DESCRIPTION__/g, stage.description);
|
|
72420
|
-
fs43.mkdirSync(
|
|
72653
|
+
fs43.mkdirSync(path49.dirname(scriptAbs), { recursive: true });
|
|
72421
72654
|
fs43.writeFileSync(scriptAbs, skeleton);
|
|
72422
72655
|
fs43.chmodSync(scriptAbs, 493);
|
|
72423
72656
|
filesWritten.push(`.har/${scriptRel}`);
|
|
@@ -72468,7 +72701,7 @@ function addCustomStage(repoPath, options) {
|
|
|
72468
72701
|
|
|
72469
72702
|
// src/harness/adaptation-prompt.ts
|
|
72470
72703
|
var fs44 = __toESM(require("fs"));
|
|
72471
|
-
var
|
|
72704
|
+
var path50 = __toESM(require("path"));
|
|
72472
72705
|
var readline5 = __toESM(require("readline"));
|
|
72473
72706
|
|
|
72474
72707
|
// src/utils/clipboard.ts
|
|
@@ -72580,7 +72813,7 @@ function buildMaintainAdaptationPrompt(_repoPath, bundleReport) {
|
|
|
72580
72813
|
}
|
|
72581
72814
|
function writeAdaptationPrompt(repoPath, content) {
|
|
72582
72815
|
const harnessDir = getHarnessDir(repoPath);
|
|
72583
|
-
const filePath =
|
|
72816
|
+
const filePath = path50.join(harnessDir, ADAPTATION_PROMPT_FILE);
|
|
72584
72817
|
writeFileSafe(filePath, content);
|
|
72585
72818
|
return filePath;
|
|
72586
72819
|
}
|
|
@@ -72599,12 +72832,12 @@ function printAdaptationPrompt(content) {
|
|
|
72599
72832
|
}
|
|
72600
72833
|
function askYesNo2(question) {
|
|
72601
72834
|
const rl = readline5.createInterface({ input: process.stdin, output: process.stderr });
|
|
72602
|
-
return new Promise((
|
|
72835
|
+
return new Promise((resolve52) => {
|
|
72603
72836
|
process.stderr.write(`${question} `);
|
|
72604
72837
|
rl.once("line", (answer) => {
|
|
72605
72838
|
rl.close();
|
|
72606
72839
|
const trimmed = answer.trim();
|
|
72607
|
-
|
|
72840
|
+
resolve52(trimmed === "" || /^y(es)?$/i.test(trimmed));
|
|
72608
72841
|
});
|
|
72609
72842
|
});
|
|
72610
72843
|
}
|
|
@@ -72636,16 +72869,16 @@ async function offerAdaptationPromptClipboard(content, options = {}) {
|
|
|
72636
72869
|
|
|
72637
72870
|
// src/harness/cursor-rule.ts
|
|
72638
72871
|
var fs45 = __toESM(require("fs"));
|
|
72639
|
-
var
|
|
72872
|
+
var path51 = __toESM(require("path"));
|
|
72640
72873
|
var readline6 = __toESM(require("readline"));
|
|
72641
72874
|
init_file_ops();
|
|
72642
72875
|
init_logging();
|
|
72643
72876
|
var CURSOR_RULE_RELATIVE_PATH = ".cursor/rules/har-workflow.mdc";
|
|
72644
72877
|
function getCursorRulePath(repoPath) {
|
|
72645
|
-
return
|
|
72878
|
+
return path51.join(repoPath, CURSOR_RULE_RELATIVE_PATH);
|
|
72646
72879
|
}
|
|
72647
72880
|
function isCursorWorkspace(repoPath) {
|
|
72648
|
-
return fs45.existsSync(
|
|
72881
|
+
return fs45.existsSync(path51.join(repoPath, ".cursor"));
|
|
72649
72882
|
}
|
|
72650
72883
|
function cursorRuleExists(repoPath) {
|
|
72651
72884
|
return fs45.existsSync(getCursorRulePath(repoPath));
|
|
@@ -72693,16 +72926,16 @@ async function promptScaffoldCursorRule(exists) {
|
|
|
72693
72926
|
}
|
|
72694
72927
|
async function askYesNo3(question) {
|
|
72695
72928
|
const rl = readline6.createInterface({ input: process.stdin, output: process.stderr });
|
|
72696
|
-
return new Promise((
|
|
72929
|
+
return new Promise((resolve52) => {
|
|
72697
72930
|
process.stderr.write(`${question} `);
|
|
72698
72931
|
rl.once("line", (answer) => {
|
|
72699
72932
|
rl.close();
|
|
72700
72933
|
const trimmed = answer.trim();
|
|
72701
72934
|
if (trimmed === "") {
|
|
72702
|
-
|
|
72935
|
+
resolve52(true);
|
|
72703
72936
|
return;
|
|
72704
72937
|
}
|
|
72705
|
-
|
|
72938
|
+
resolve52(/^y(es)?$/i.test(trimmed));
|
|
72706
72939
|
});
|
|
72707
72940
|
});
|
|
72708
72941
|
}
|
|
@@ -72745,7 +72978,7 @@ init_control_config();
|
|
|
72745
72978
|
|
|
72746
72979
|
// src/core/control-lifecycle.ts
|
|
72747
72980
|
var import_child_process13 = require("child_process");
|
|
72748
|
-
var
|
|
72981
|
+
var path52 = __toESM(require("path"));
|
|
72749
72982
|
|
|
72750
72983
|
// src/core/control-image.ts
|
|
72751
72984
|
init_package_version();
|
|
@@ -72772,10 +73005,10 @@ var CONTROL_DATA_VOLUME = "har_control_data";
|
|
|
72772
73005
|
var CONTROL_CONTAINER_PORT = 3847;
|
|
72773
73006
|
var CONTROL_DATA_DB_URL = "file:/data/har_control.db";
|
|
72774
73007
|
function resolveControlDir() {
|
|
72775
|
-
return
|
|
73008
|
+
return path52.resolve(__dirname, "..", "control");
|
|
72776
73009
|
}
|
|
72777
73010
|
function resolveControlBuildContext() {
|
|
72778
|
-
return
|
|
73011
|
+
return path52.resolve(resolveControlDir(), "..");
|
|
72779
73012
|
}
|
|
72780
73013
|
function buildDockerRunArgs(options) {
|
|
72781
73014
|
const name = options.containerName ?? CONTROL_CONTAINER_NAME;
|
|
@@ -72831,7 +73064,7 @@ async function startMissionControl(options) {
|
|
|
72831
73064
|
"-t",
|
|
72832
73065
|
imageRef,
|
|
72833
73066
|
"-f",
|
|
72834
|
-
|
|
73067
|
+
path52.join(resolveControlDir(), "Dockerfile"),
|
|
72835
73068
|
resolveControlBuildContext()
|
|
72836
73069
|
]);
|
|
72837
73070
|
if (buildCode !== 0) {
|
|
@@ -72978,7 +73211,7 @@ async function ensureTelemetryInfrastructure(options) {
|
|
|
72978
73211
|
// src/core/run-service.ts
|
|
72979
73212
|
init_telemetry_config();
|
|
72980
73213
|
init_telemetry_env();
|
|
72981
|
-
var
|
|
73214
|
+
var path54 = __toESM(require("path"));
|
|
72982
73215
|
init_local_executor();
|
|
72983
73216
|
function extractShellOutput(result) {
|
|
72984
73217
|
const stdout = result.logs?.find((log) => log.stream === "stdout")?.content ?? result.logs?.find((log) => !log.stream)?.content ?? "";
|
|
@@ -73184,12 +73417,12 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
|
|
|
73184
73417
|
suffix: session.suffix,
|
|
73185
73418
|
createdAt: session.createdAt
|
|
73186
73419
|
});
|
|
73187
|
-
const envFile =
|
|
73420
|
+
const envFile = path54.join(session.workDir, `.env.agent.${options.agentId}`);
|
|
73188
73421
|
try {
|
|
73189
73422
|
appendTelemetryEnvToFile(envFile, {
|
|
73190
73423
|
sessionKey,
|
|
73191
73424
|
agentId: options.agentId,
|
|
73192
|
-
repoPath:
|
|
73425
|
+
repoPath: path54.resolve(options.repoPath),
|
|
73193
73426
|
workDir: session.workDir,
|
|
73194
73427
|
branch: session.branch,
|
|
73195
73428
|
suffix: session.suffix,
|
|
@@ -73428,7 +73661,7 @@ init_slot_status();
|
|
|
73428
73661
|
// src/core/cleanup-service.ts
|
|
73429
73662
|
var fs47 = __toESM(require("fs"));
|
|
73430
73663
|
var os20 = __toESM(require("os"));
|
|
73431
|
-
var
|
|
73664
|
+
var path55 = __toESM(require("path"));
|
|
73432
73665
|
var import_child_process15 = require("child_process");
|
|
73433
73666
|
init_control_sync();
|
|
73434
73667
|
init_control_repo_path();
|
|
@@ -73437,9 +73670,9 @@ init_manifest();
|
|
|
73437
73670
|
var DEFAULT_STALE_DAYS = 7;
|
|
73438
73671
|
function getWorktreesRoot() {
|
|
73439
73672
|
if (process.env.HAR_WORKTREES_ROOT) {
|
|
73440
|
-
return
|
|
73673
|
+
return path55.resolve(process.env.HAR_WORKTREES_ROOT);
|
|
73441
73674
|
}
|
|
73442
|
-
return
|
|
73675
|
+
return path55.join(process.env.HOME || os20.homedir(), "worktrees");
|
|
73443
73676
|
}
|
|
73444
73677
|
function runGit3(cwd, args) {
|
|
73445
73678
|
try {
|
|
@@ -73453,7 +73686,7 @@ function runGit3(cwd, args) {
|
|
|
73453
73686
|
}
|
|
73454
73687
|
}
|
|
73455
73688
|
function basenameRepo(repoPath) {
|
|
73456
|
-
return
|
|
73689
|
+
return path55.basename(canonicalizeControlRepoPath(repoPath));
|
|
73457
73690
|
}
|
|
73458
73691
|
function ageDaysFrom(iso) {
|
|
73459
73692
|
if (!iso) return void 0;
|
|
@@ -73465,12 +73698,12 @@ function matchesKeep(candidate, keep) {
|
|
|
73465
73698
|
if (!keep?.length) return false;
|
|
73466
73699
|
for (const pin of keep) {
|
|
73467
73700
|
if (pin.worktreePath && candidate.worktreePath) {
|
|
73468
|
-
if (
|
|
73701
|
+
if (path55.resolve(pin.worktreePath) === path55.resolve(candidate.worktreePath)) return true;
|
|
73469
73702
|
}
|
|
73470
73703
|
if (pin.repoPath && pin.agentId !== void 0 && candidate.agentId !== void 0) {
|
|
73471
73704
|
const repo = canonicalizeControlRepoPath(pin.repoPath);
|
|
73472
|
-
const candidateRepo =
|
|
73473
|
-
if ((repo === candidateRepo ||
|
|
73705
|
+
const candidateRepo = path55.resolve(candidate.repoPath);
|
|
73706
|
+
if ((repo === candidateRepo || path55.resolve(pin.repoPath) === candidateRepo) && pin.agentId === candidate.agentId) {
|
|
73474
73707
|
return true;
|
|
73475
73708
|
}
|
|
73476
73709
|
}
|
|
@@ -73528,7 +73761,7 @@ function resolveRepoForWorktree(worktreePath) {
|
|
|
73528
73761
|
if (!fs47.existsSync(worktreePath)) return void 0;
|
|
73529
73762
|
const commonDir = runGit3(worktreePath, "rev-parse --git-common-dir");
|
|
73530
73763
|
if (!commonDir) return void 0;
|
|
73531
|
-
const gitRoot =
|
|
73764
|
+
const gitRoot = path55.resolve(worktreePath, commonDir, "..");
|
|
73532
73765
|
if (!readManifest(gitRoot)) return void 0;
|
|
73533
73766
|
return canonicalizeControlRepoPath(gitRoot);
|
|
73534
73767
|
}
|
|
@@ -73538,7 +73771,7 @@ function discoverOrphanWorktrees(knownPaths) {
|
|
|
73538
73771
|
const orphans = [];
|
|
73539
73772
|
for (const entry of fs47.readdirSync(worktreesRoot, { withFileTypes: true })) {
|
|
73540
73773
|
if (!entry.isDirectory() || !entry.name.includes("-har-agent-")) continue;
|
|
73541
|
-
const worktreePath =
|
|
73774
|
+
const worktreePath = path55.resolve(path55.join(worktreesRoot, entry.name));
|
|
73542
73775
|
if (knownPaths.has(worktreePath)) continue;
|
|
73543
73776
|
const repoPath = resolveRepoForWorktree(worktreePath) ?? worktreesRoot;
|
|
73544
73777
|
const porcelain = runGit3(worktreePath, "status --porcelain");
|
|
@@ -73569,8 +73802,8 @@ async function discoverCleanupCandidates(options = {}) {
|
|
|
73569
73802
|
const status = collectEnvironmentStatus(harnessRoot);
|
|
73570
73803
|
const projectName = basenameRepo(harnessRoot);
|
|
73571
73804
|
for (const slot of status.slots) {
|
|
73572
|
-
if (slot.worktreePath) knownWorktreePaths.add(
|
|
73573
|
-
if (slot.workDir) knownWorktreePaths.add(
|
|
73805
|
+
if (slot.worktreePath) knownWorktreePaths.add(path55.resolve(slot.worktreePath));
|
|
73806
|
+
if (slot.workDir) knownWorktreePaths.add(path55.resolve(slot.workDir));
|
|
73574
73807
|
const candidate = classifySlotCandidate(canonicalRepo, projectName, slot, {
|
|
73575
73808
|
staleDays: options.staleDays,
|
|
73576
73809
|
keep: options.keep
|
|
@@ -73630,8 +73863,8 @@ async function askYesNo4(question) {
|
|
|
73630
73863
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
73631
73864
|
const readline8 = await import("readline");
|
|
73632
73865
|
const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
|
|
73633
|
-
const answer = await new Promise((
|
|
73634
|
-
rl.question(question,
|
|
73866
|
+
const answer = await new Promise((resolve52) => {
|
|
73867
|
+
rl.question(question, resolve52);
|
|
73635
73868
|
});
|
|
73636
73869
|
rl.close();
|
|
73637
73870
|
return /^[Yy]$/.test(answer.trim());
|
|
@@ -73714,7 +73947,7 @@ function parseCleanupKeepPins(values) {
|
|
|
73714
73947
|
}
|
|
73715
73948
|
if (raw.startsWith("/") || raw.startsWith("~")) {
|
|
73716
73949
|
return {
|
|
73717
|
-
worktreePath: raw.startsWith("~") ?
|
|
73950
|
+
worktreePath: raw.startsWith("~") ? path55.join(process.env.HOME || os20.homedir(), raw.slice(2)) : path55.resolve(raw)
|
|
73718
73951
|
};
|
|
73719
73952
|
}
|
|
73720
73953
|
return { repoPath: raw };
|
|
@@ -73728,12 +73961,12 @@ init_stages();
|
|
|
73728
73961
|
init_logging();
|
|
73729
73962
|
function askYesNo5(question) {
|
|
73730
73963
|
const rl = readline7.createInterface({ input: process.stdin, output: process.stderr });
|
|
73731
|
-
return new Promise((
|
|
73964
|
+
return new Promise((resolve52) => {
|
|
73732
73965
|
process.stderr.write(`${question} `);
|
|
73733
73966
|
rl.once("line", (answer) => {
|
|
73734
73967
|
rl.close();
|
|
73735
73968
|
const trimmed = answer.trim();
|
|
73736
|
-
|
|
73969
|
+
resolve52(trimmed === "" || /^y(es)?$/i.test(trimmed));
|
|
73737
73970
|
});
|
|
73738
73971
|
});
|
|
73739
73972
|
}
|
|
@@ -73836,13 +74069,13 @@ function warnIfDockerUnavailable(status = detectDockerStatus()) {
|
|
|
73836
74069
|
// src/core/onboarding-preferences.ts
|
|
73837
74070
|
var fs48 = __toESM(require("fs"));
|
|
73838
74071
|
var os21 = __toESM(require("os"));
|
|
73839
|
-
var
|
|
74072
|
+
var path56 = __toESM(require("path"));
|
|
73840
74073
|
init_schema2();
|
|
73841
74074
|
function getOnboardingPreferencesPath() {
|
|
73842
74075
|
if (process.env.HAR_PREFERENCES_PATH) {
|
|
73843
|
-
return
|
|
74076
|
+
return path56.resolve(process.env.HAR_PREFERENCES_PATH);
|
|
73844
74077
|
}
|
|
73845
|
-
return
|
|
74078
|
+
return path56.join(os21.homedir(), ".har", "preferences.json");
|
|
73846
74079
|
}
|
|
73847
74080
|
function readOnboardingPreferences() {
|
|
73848
74081
|
const preferencePath = getOnboardingPreferencesPath();
|
|
@@ -73873,7 +74106,7 @@ function writeOnboardingPreferences(overrides) {
|
|
|
73873
74106
|
};
|
|
73874
74107
|
const parsed = OnboardingPreferencesSchema.parse(preference);
|
|
73875
74108
|
const preferencePath = getOnboardingPreferencesPath();
|
|
73876
|
-
fs48.mkdirSync(
|
|
74109
|
+
fs48.mkdirSync(path56.dirname(preferencePath), { recursive: true });
|
|
73877
74110
|
fs48.writeFileSync(preferencePath, `${JSON.stringify(parsed, null, 2)}
|
|
73878
74111
|
`);
|
|
73879
74112
|
return parsed;
|
|
@@ -74219,7 +74452,7 @@ var envCommand = {
|
|
|
74219
74452
|
}
|
|
74220
74453
|
};
|
|
74221
74454
|
async function handleInit(argv) {
|
|
74222
|
-
const repoPath =
|
|
74455
|
+
const repoPath = path57.resolve(argv.repo);
|
|
74223
74456
|
const onboarding = resolveOnboardingOptions(argv);
|
|
74224
74457
|
header("har env init");
|
|
74225
74458
|
info(`Repository: ${repoPath}`);
|
|
@@ -74266,7 +74499,7 @@ async function handleInit(argv) {
|
|
|
74266
74499
|
}
|
|
74267
74500
|
}
|
|
74268
74501
|
async function handleMaintain(argv) {
|
|
74269
|
-
const repoPath =
|
|
74502
|
+
const repoPath = path57.resolve(argv.repo);
|
|
74270
74503
|
const onboarding = resolveOnboardingOptions(argv);
|
|
74271
74504
|
header("har env maintain");
|
|
74272
74505
|
info(`Repository: ${repoPath}`);
|
|
@@ -74397,7 +74630,7 @@ async function applyAgentIntegrations(options) {
|
|
|
74397
74630
|
}
|
|
74398
74631
|
}
|
|
74399
74632
|
async function handleAddPlugin(argv) {
|
|
74400
|
-
const repoPath =
|
|
74633
|
+
const repoPath = path57.resolve(argv.repo);
|
|
74401
74634
|
const available = listPluginIds();
|
|
74402
74635
|
if (argv.list) {
|
|
74403
74636
|
for (const id of available) {
|
|
@@ -74437,7 +74670,7 @@ async function handleAddPlugin(argv) {
|
|
|
74437
74670
|
}
|
|
74438
74671
|
}
|
|
74439
74672
|
async function handleAddStage(argv) {
|
|
74440
|
-
const repoPath =
|
|
74673
|
+
const repoPath = path57.resolve(argv.repo);
|
|
74441
74674
|
const available = listPluginIds();
|
|
74442
74675
|
if (argv.list) {
|
|
74443
74676
|
warn("har env add-stage --list is deprecated; prefer: har env add-plugin --list");
|
|
@@ -74503,7 +74736,7 @@ async function handleAddStage(argv) {
|
|
|
74503
74736
|
});
|
|
74504
74737
|
}
|
|
74505
74738
|
async function handlePreflight(argv) {
|
|
74506
|
-
const repo =
|
|
74739
|
+
const repo = path57.resolve(argv.repo);
|
|
74507
74740
|
const agentId = validateAgentId(argv.id, repo);
|
|
74508
74741
|
const result = await preflightEnvironment({
|
|
74509
74742
|
repoPath: repo,
|
|
@@ -74519,7 +74752,7 @@ async function handlePreflight(argv) {
|
|
|
74519
74752
|
return finishCommand(result.code);
|
|
74520
74753
|
}
|
|
74521
74754
|
async function handleLaunch(argv) {
|
|
74522
|
-
const repo =
|
|
74755
|
+
const repo = path57.resolve(argv.repo);
|
|
74523
74756
|
const agentId = validateAgentId(argv.id, repo);
|
|
74524
74757
|
if (!argv.resume) {
|
|
74525
74758
|
const guard = checkLaunchGuard2(repo, agentId, { worktree: argv.worktree });
|
|
@@ -74568,7 +74801,7 @@ async function handleWorkLink(argv) {
|
|
|
74568
74801
|
error("Provide --link or both --source and --url");
|
|
74569
74802
|
return finishCommand(1);
|
|
74570
74803
|
}
|
|
74571
|
-
const harnessRoot = resolveHarnessRoot(
|
|
74804
|
+
const harnessRoot = resolveHarnessRoot(path57.resolve(argv.repo));
|
|
74572
74805
|
const links = argv.link ? [parseWorkLinkSpec(argv.link)] : [{ source: argv.source, url: argv.url, label: argv.label }];
|
|
74573
74806
|
try {
|
|
74574
74807
|
const record2 = addWorkUnitLinks(harnessRoot, argv.workId, links);
|
|
@@ -74594,7 +74827,7 @@ async function handleRecover(argv) {
|
|
|
74594
74827
|
});
|
|
74595
74828
|
}
|
|
74596
74829
|
async function handleVerify(argv) {
|
|
74597
|
-
const repo =
|
|
74830
|
+
const repo = path57.resolve(argv.repo);
|
|
74598
74831
|
const agentId = validateAgentId(argv.id, repo);
|
|
74599
74832
|
const result = await runVerification({
|
|
74600
74833
|
repoPath: repo,
|
|
@@ -74623,7 +74856,7 @@ async function handleVerify(argv) {
|
|
|
74623
74856
|
return finishCommand(result.code);
|
|
74624
74857
|
}
|
|
74625
74858
|
async function handleTeardown(argv) {
|
|
74626
|
-
const repo =
|
|
74859
|
+
const repo = path57.resolve(argv.repo);
|
|
74627
74860
|
const agentId = validateAgentId(argv.id, repo);
|
|
74628
74861
|
const result = await teardownEnvironment({
|
|
74629
74862
|
repoPath: repo,
|
|
@@ -74634,7 +74867,7 @@ async function handleTeardown(argv) {
|
|
|
74634
74867
|
return finishCommand(result.code);
|
|
74635
74868
|
}
|
|
74636
74869
|
async function handleComplete(argv) {
|
|
74637
|
-
const repo =
|
|
74870
|
+
const repo = path57.resolve(argv.repo);
|
|
74638
74871
|
const agentId = validateAgentId(argv.id, repo);
|
|
74639
74872
|
const result = await completeEnvironment({
|
|
74640
74873
|
repoPath: repo,
|
|
@@ -74655,7 +74888,7 @@ async function handleComplete(argv) {
|
|
|
74655
74888
|
return finishCommand(result.code);
|
|
74656
74889
|
}
|
|
74657
74890
|
async function handleStatus(argv) {
|
|
74658
|
-
const repoPath =
|
|
74891
|
+
const repoPath = path57.resolve(argv.repo);
|
|
74659
74892
|
if (argv.json) {
|
|
74660
74893
|
const status = collectEnvironmentStatus(repoPath);
|
|
74661
74894
|
const output = EnvironmentStatusSchema.parse(status);
|
|
@@ -74670,7 +74903,7 @@ async function handleStatus(argv) {
|
|
|
74670
74903
|
async function handleCleanup(argv) {
|
|
74671
74904
|
const keepValues = argv.keep?.split(",").map((value) => value.trim()).filter(Boolean);
|
|
74672
74905
|
const keep = parseCleanupKeepPins(keepValues);
|
|
74673
|
-
const repoPaths = argv.repo ? [
|
|
74906
|
+
const repoPaths = argv.repo ? [path57.resolve(argv.repo)] : void 0;
|
|
74674
74907
|
const plan = await discoverCleanupCandidates({
|
|
74675
74908
|
cwd: process.cwd(),
|
|
74676
74909
|
repoPaths,
|
|
@@ -74719,7 +74952,7 @@ async function handleCleanup(argv) {
|
|
|
74719
74952
|
return finishCommand(failed > 0 ? 1 : 0);
|
|
74720
74953
|
}
|
|
74721
74954
|
async function handleRunsList(argv) {
|
|
74722
|
-
const repoPath =
|
|
74955
|
+
const repoPath = path57.resolve(argv.repo);
|
|
74723
74956
|
const runs = listRuns(repoPath, { stageId: argv.stage, limit: argv.limit });
|
|
74724
74957
|
if (argv.json) {
|
|
74725
74958
|
process.stdout.write(JSON.stringify({ runs }, null, 2) + "\n");
|
|
@@ -74736,7 +74969,7 @@ async function handleRunsList(argv) {
|
|
|
74736
74969
|
}
|
|
74737
74970
|
}
|
|
74738
74971
|
async function handleRunsGet(argv) {
|
|
74739
|
-
const run2 = getRun(
|
|
74972
|
+
const run2 = getRun(path57.resolve(argv.repo), argv.runId);
|
|
74740
74973
|
if (!run2) {
|
|
74741
74974
|
error(`Run not found: ${argv.runId}`);
|
|
74742
74975
|
return finishCommand(1);
|
|
@@ -74813,7 +75046,7 @@ function printNextSteps() {
|
|
|
74813
75046
|
}
|
|
74814
75047
|
|
|
74815
75048
|
// src/cli/commands/control.ts
|
|
74816
|
-
var
|
|
75049
|
+
var path62 = __toESM(require("path"));
|
|
74817
75050
|
init_control_config();
|
|
74818
75051
|
init_portal_targets();
|
|
74819
75052
|
|
|
@@ -74822,7 +75055,7 @@ init_control_config();
|
|
|
74822
75055
|
|
|
74823
75056
|
// src/core/portal-connect.ts
|
|
74824
75057
|
var fs49 = __toESM(require("fs"));
|
|
74825
|
-
var
|
|
75058
|
+
var path58 = __toESM(require("path"));
|
|
74826
75059
|
var import_crypto2 = require("crypto");
|
|
74827
75060
|
init_control_repo_path();
|
|
74828
75061
|
init_control_registry();
|
|
@@ -74868,7 +75101,7 @@ async function loginViaBrowser(portalUrl, openUrlOrOptions = openBrowser) {
|
|
|
74868
75101
|
const options = typeof openUrlOrOptions === "function" ? { openUrl: openUrlOrOptions } : openUrlOrOptions;
|
|
74869
75102
|
const openUrl = options.openUrl ?? openBrowser;
|
|
74870
75103
|
const state = (0, import_crypto.randomUUID)();
|
|
74871
|
-
return new Promise((
|
|
75104
|
+
return new Promise((resolve52, reject) => {
|
|
74872
75105
|
let timer;
|
|
74873
75106
|
const server = http.createServer((req, res) => {
|
|
74874
75107
|
const requestUrl = new URL(req.url ?? "", "http://127.0.0.1");
|
|
@@ -74896,7 +75129,7 @@ async function loginViaBrowser(portalUrl, openUrlOrOptions = openBrowser) {
|
|
|
74896
75129
|
res.end("<h1>Logged in</h1><p>You can close this tab and return to the terminal.</p>");
|
|
74897
75130
|
cleanup();
|
|
74898
75131
|
const targets = parseCliTargetsParam(requestUrl.searchParams.get("targets"));
|
|
74899
|
-
|
|
75132
|
+
resolve52({
|
|
74900
75133
|
portalUrl,
|
|
74901
75134
|
token,
|
|
74902
75135
|
workspace: workspaceSlug ?? workspace,
|
|
@@ -74991,7 +75224,7 @@ function remainingConnections(connections, usedAliases) {
|
|
|
74991
75224
|
// src/core/portal-connect.ts
|
|
74992
75225
|
init_portal_targets();
|
|
74993
75226
|
function attachRepoIfPresent(alias, repoPath) {
|
|
74994
|
-
const resolved =
|
|
75227
|
+
const resolved = path58.resolve(repoPath ?? ".");
|
|
74995
75228
|
if (!fs49.existsSync(resolved)) return null;
|
|
74996
75229
|
const canonical = canonicalizeControlRepoPath(resolved);
|
|
74997
75230
|
attachRepoPortalTarget(canonical, alias);
|
|
@@ -75059,7 +75292,7 @@ async function runPortalConnect(input) {
|
|
|
75059
75292
|
return { record: record2, attachedRepo, extraAttached, mappedInBrowser: true };
|
|
75060
75293
|
}
|
|
75061
75294
|
function listRegisteredReposForConnect(repoPath) {
|
|
75062
|
-
const resolved = repoPath ?
|
|
75295
|
+
const resolved = repoPath ? path58.resolve(repoPath) : null;
|
|
75063
75296
|
const current = resolved && fs49.existsSync(resolved) ? canonicalizeControlRepoPath(resolved) : null;
|
|
75064
75297
|
return [.../* @__PURE__ */ new Set([...current ? [current] : [], ...listRegisteredRepos()])];
|
|
75065
75298
|
}
|
|
@@ -75378,13 +75611,13 @@ init_control_sync();
|
|
|
75378
75611
|
// src/core/control-sync-selection.ts
|
|
75379
75612
|
var fs50 = __toESM(require("fs"));
|
|
75380
75613
|
var os22 = __toESM(require("os"));
|
|
75381
|
-
var
|
|
75614
|
+
var path59 = __toESM(require("path"));
|
|
75382
75615
|
init_control_repo_path();
|
|
75383
75616
|
function getSelectionPath() {
|
|
75384
75617
|
if (process.env.HAR_CONTROL_SYNC_SELECTION_PATH) {
|
|
75385
|
-
return
|
|
75618
|
+
return path59.resolve(process.env.HAR_CONTROL_SYNC_SELECTION_PATH);
|
|
75386
75619
|
}
|
|
75387
|
-
return
|
|
75620
|
+
return path59.join(os22.homedir(), ".har", "sync-selection.json");
|
|
75388
75621
|
}
|
|
75389
75622
|
function readSyncSelection() {
|
|
75390
75623
|
const selectionPath = getSelectionPath();
|
|
@@ -75400,7 +75633,7 @@ function readSyncSelection() {
|
|
|
75400
75633
|
function writeSyncSelection(repos) {
|
|
75401
75634
|
const selectionPath = getSelectionPath();
|
|
75402
75635
|
const canonical = Array.from(new Set(repos.map((repoPath) => canonicalizeControlRepoPath(repoPath))));
|
|
75403
|
-
fs50.mkdirSync(
|
|
75636
|
+
fs50.mkdirSync(path59.dirname(selectionPath), { recursive: true });
|
|
75404
75637
|
fs50.writeFileSync(selectionPath, JSON.stringify({ repos: canonical }, null, 2) + "\n");
|
|
75405
75638
|
}
|
|
75406
75639
|
function resolveSyncSelection(input) {
|
|
@@ -75429,7 +75662,7 @@ function resolveSyncSelection(input) {
|
|
|
75429
75662
|
|
|
75430
75663
|
// src/core/control-unregister.ts
|
|
75431
75664
|
var fs51 = __toESM(require("fs"));
|
|
75432
|
-
var
|
|
75665
|
+
var path60 = __toESM(require("path"));
|
|
75433
75666
|
init_control_repo_path();
|
|
75434
75667
|
init_control_registry();
|
|
75435
75668
|
init_control_config();
|
|
@@ -75439,7 +75672,7 @@ function listUnregisterWorktreeCandidates(repoPath) {
|
|
|
75439
75672
|
const harnessRoot = canonicalizeControlRepoPath(repoPath);
|
|
75440
75673
|
const byPath = /* @__PURE__ */ new Map();
|
|
75441
75674
|
const add = (partial2) => {
|
|
75442
|
-
const resolved =
|
|
75675
|
+
const resolved = path60.resolve(partial2.worktreePath);
|
|
75443
75676
|
if (!resolved || resolved === harnessRoot) return;
|
|
75444
75677
|
const exists = partial2.exists ?? fs51.existsSync(resolved);
|
|
75445
75678
|
const prev = byPath.get(resolved);
|
|
@@ -75492,8 +75725,8 @@ async function askYesNo6(question) {
|
|
|
75492
75725
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
75493
75726
|
const readline8 = await import("readline");
|
|
75494
75727
|
const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
|
|
75495
|
-
const answer = await new Promise((
|
|
75496
|
-
rl.question(question,
|
|
75728
|
+
const answer = await new Promise((resolve52) => {
|
|
75729
|
+
rl.question(question, resolve52);
|
|
75497
75730
|
});
|
|
75498
75731
|
rl.close();
|
|
75499
75732
|
return /^[Yy]$/.test(answer.trim());
|
|
@@ -75640,15 +75873,15 @@ init_control_registry();
|
|
|
75640
75873
|
|
|
75641
75874
|
// src/core/harness-scrub.ts
|
|
75642
75875
|
var fs52 = __toESM(require("fs"));
|
|
75643
|
-
var
|
|
75876
|
+
var path61 = __toESM(require("path"));
|
|
75644
75877
|
var HARNESS_SCRUB_DIRS = ["runs", "validations", "state", "slots"];
|
|
75645
75878
|
function scrubLocalHarnessDirs(repoPath) {
|
|
75646
75879
|
const results = [];
|
|
75647
|
-
const resolved =
|
|
75880
|
+
const resolved = path61.resolve(repoPath);
|
|
75648
75881
|
if (!fs52.existsSync(resolved)) {
|
|
75649
75882
|
for (const directory of HARNESS_SCRUB_DIRS) {
|
|
75650
75883
|
results.push({
|
|
75651
|
-
path:
|
|
75884
|
+
path: path61.join(resolved, ".har", directory),
|
|
75652
75885
|
directory,
|
|
75653
75886
|
deleted: false,
|
|
75654
75887
|
error: "repository path does not exist"
|
|
@@ -75657,7 +75890,7 @@ function scrubLocalHarnessDirs(repoPath) {
|
|
|
75657
75890
|
return results;
|
|
75658
75891
|
}
|
|
75659
75892
|
for (const directory of HARNESS_SCRUB_DIRS) {
|
|
75660
|
-
const target =
|
|
75893
|
+
const target = path61.join(resolved, ".har", directory);
|
|
75661
75894
|
if (!fs52.existsSync(target)) {
|
|
75662
75895
|
results.push({ path: target, directory, deleted: true });
|
|
75663
75896
|
continue;
|
|
@@ -75685,7 +75918,7 @@ function scrubLocalHarnessForRepos(repoPaths) {
|
|
|
75685
75918
|
const results = [];
|
|
75686
75919
|
const seen = /* @__PURE__ */ new Set();
|
|
75687
75920
|
for (const repoPath of repoPaths) {
|
|
75688
|
-
const key =
|
|
75921
|
+
const key = path61.resolve(repoPath);
|
|
75689
75922
|
if (seen.has(key)) continue;
|
|
75690
75923
|
seen.add(key);
|
|
75691
75924
|
results.push(...scrubLocalHarnessDirs(key));
|
|
@@ -75698,8 +75931,8 @@ async function askYesNo7(question) {
|
|
|
75698
75931
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
75699
75932
|
const readline8 = await import("readline");
|
|
75700
75933
|
const rl = readline8.createInterface({ input: process.stdin, output: process.stderr });
|
|
75701
|
-
const answer = await new Promise((
|
|
75702
|
-
rl.question(question,
|
|
75934
|
+
const answer = await new Promise((resolve52) => {
|
|
75935
|
+
rl.question(question, resolve52);
|
|
75703
75936
|
});
|
|
75704
75937
|
rl.close();
|
|
75705
75938
|
return /^[Yy]$/.test(answer.trim());
|
|
@@ -75978,7 +76211,7 @@ async function handleDown() {
|
|
|
75978
76211
|
return finishCommand(code);
|
|
75979
76212
|
}
|
|
75980
76213
|
async function handleRegister(argv) {
|
|
75981
|
-
const repoPath =
|
|
76214
|
+
const repoPath = path62.resolve(argv.repo);
|
|
75982
76215
|
header("har control register");
|
|
75983
76216
|
info(`Repository: ${repoPath}`);
|
|
75984
76217
|
try {
|
|
@@ -76076,7 +76309,7 @@ async function handleReset(argv) {
|
|
|
76076
76309
|
}
|
|
76077
76310
|
}
|
|
76078
76311
|
async function handleUnregister(argv) {
|
|
76079
|
-
const repoPath =
|
|
76312
|
+
const repoPath = path62.resolve(argv.repo);
|
|
76080
76313
|
const worktrees = listUnregisterWorktreeCandidates(repoPath);
|
|
76081
76314
|
try {
|
|
76082
76315
|
let deleteWorktrees = argv.deleteWorktrees;
|
|
@@ -76214,7 +76447,7 @@ async function handleSync(argv) {
|
|
|
76214
76447
|
);
|
|
76215
76448
|
}
|
|
76216
76449
|
}
|
|
76217
|
-
const { synced, failed, results } = await syncReposWithControl({
|
|
76450
|
+
const { synced, failed, incomplete, results } = await syncReposWithControl({
|
|
76218
76451
|
repoPaths,
|
|
76219
76452
|
apiUrl: argv.apiUrl,
|
|
76220
76453
|
dryRun: argv.dryRun,
|
|
@@ -76223,7 +76456,9 @@ async function handleSync(argv) {
|
|
|
76223
76456
|
portalTargets
|
|
76224
76457
|
});
|
|
76225
76458
|
if (argv.json) {
|
|
76226
|
-
process.stdout.write(
|
|
76459
|
+
process.stdout.write(
|
|
76460
|
+
JSON.stringify({ ok: failed === 0, synced, failed, incomplete, results }, null, 2) + "\n"
|
|
76461
|
+
);
|
|
76227
76462
|
if (failed > 0) return finishCommand(1);
|
|
76228
76463
|
return;
|
|
76229
76464
|
}
|
|
@@ -76232,22 +76467,32 @@ async function handleSync(argv) {
|
|
|
76232
76467
|
for (const target of result.targets) {
|
|
76233
76468
|
const record2 = findPortalTargetRecord(target.alias);
|
|
76234
76469
|
const label = record2 ? displayPortalTargetLabel(record2) : target.alias;
|
|
76235
|
-
if (target.ok) {
|
|
76236
|
-
success(`Synced ${result.repoPath} \u2192 ${label}`);
|
|
76237
|
-
} else {
|
|
76470
|
+
if (!target.ok) {
|
|
76238
76471
|
warn(`Failed ${result.repoPath} \u2192 ${label}: ${target.error}`);
|
|
76472
|
+
} else if (target.warnings && target.warnings.length > 0) {
|
|
76473
|
+
warn(`Synced ${result.repoPath} \u2192 ${label} \u2014 incomplete`);
|
|
76474
|
+
} else {
|
|
76475
|
+
success(`Synced ${result.repoPath} \u2192 ${label}`);
|
|
76239
76476
|
}
|
|
76240
76477
|
}
|
|
76241
76478
|
continue;
|
|
76242
76479
|
}
|
|
76243
|
-
if (result.ok) {
|
|
76244
|
-
success(`Synced ${result.repoPath}`);
|
|
76245
|
-
} else {
|
|
76480
|
+
if (!result.ok) {
|
|
76246
76481
|
warn(`Failed ${result.repoPath}: ${result.error}`);
|
|
76482
|
+
} else if (result.warnings && result.warnings.length > 0) {
|
|
76483
|
+
warn(`Synced ${result.repoPath} \u2014 incomplete`);
|
|
76484
|
+
} else {
|
|
76485
|
+
success(`Synced ${result.repoPath}`);
|
|
76247
76486
|
}
|
|
76248
76487
|
}
|
|
76249
|
-
if (synced >
|
|
76250
|
-
|
|
76488
|
+
if (synced > incomplete) {
|
|
76489
|
+
const complete = synced - incomplete;
|
|
76490
|
+
success(`Synced ${complete} ${complete === 1 ? "repository" : "repositories"}`);
|
|
76491
|
+
}
|
|
76492
|
+
if (incomplete > 0) {
|
|
76493
|
+
warn(
|
|
76494
|
+
`${incomplete} ${incomplete === 1 ? "repository" : "repositories"} synced with incomplete telemetry \u2014 see the warnings above`
|
|
76495
|
+
);
|
|
76251
76496
|
}
|
|
76252
76497
|
if (failed > 0) {
|
|
76253
76498
|
warn(`${failed} ${failed === 1 ? "repository" : "repositories"} could not be synced`);
|
|
@@ -76345,12 +76590,12 @@ async function handleTrajectory(argv) {
|
|
|
76345
76590
|
}
|
|
76346
76591
|
|
|
76347
76592
|
// src/cli/commands/hooks.ts
|
|
76348
|
-
var
|
|
76593
|
+
var path64 = __toESM(require("path"));
|
|
76349
76594
|
init_hooks();
|
|
76350
76595
|
|
|
76351
76596
|
// src/core/claude-hooks.ts
|
|
76352
76597
|
var fs53 = __toESM(require("fs"));
|
|
76353
|
-
var
|
|
76598
|
+
var path63 = __toESM(require("path"));
|
|
76354
76599
|
var CLAUDE_GUARD_RELATIVE_PATH = ".har/hooks/claude-worktree-guard.sh";
|
|
76355
76600
|
var CLAUDE_SETTINGS_RELATIVE_PATH = ".claude/settings.json";
|
|
76356
76601
|
var GUARD_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
|
|
@@ -76371,7 +76616,7 @@ function readSettings(settingsPath) {
|
|
|
76371
76616
|
return parsed;
|
|
76372
76617
|
}
|
|
76373
76618
|
function writeSettings(settingsPath, settings) {
|
|
76374
|
-
fs53.mkdirSync(
|
|
76619
|
+
fs53.mkdirSync(path63.dirname(settingsPath), { recursive: true });
|
|
76375
76620
|
fs53.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
76376
76621
|
}
|
|
76377
76622
|
function installClaudeGuard(repoPath) {
|
|
@@ -76379,11 +76624,11 @@ function installClaudeGuard(repoPath) {
|
|
|
76379
76624
|
if (!templatePath) {
|
|
76380
76625
|
throw new Error("Guard template not found (claude-worktree-guard.sh.template). Run npm run build.");
|
|
76381
76626
|
}
|
|
76382
|
-
const guardScript =
|
|
76383
|
-
fs53.mkdirSync(
|
|
76627
|
+
const guardScript = path63.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
|
|
76628
|
+
fs53.mkdirSync(path63.dirname(guardScript), { recursive: true });
|
|
76384
76629
|
fs53.copyFileSync(templatePath, guardScript);
|
|
76385
76630
|
fs53.chmodSync(guardScript, 493);
|
|
76386
|
-
const settingsPath =
|
|
76631
|
+
const settingsPath = path63.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
76387
76632
|
const settings = readSettings(settingsPath);
|
|
76388
76633
|
const hooks = settings.hooks ?? {};
|
|
76389
76634
|
const preToolUse = (hooks.PreToolUse ?? []).filter((entry) => !isHarGuardEntry(entry));
|
|
@@ -76397,14 +76642,14 @@ function installClaudeGuard(repoPath) {
|
|
|
76397
76642
|
}
|
|
76398
76643
|
function uninstallClaudeGuard(repoPath) {
|
|
76399
76644
|
let removed = false;
|
|
76400
|
-
const guardScript =
|
|
76645
|
+
const guardScript = path63.join(repoPath, CLAUDE_GUARD_RELATIVE_PATH);
|
|
76401
76646
|
if (fs53.existsSync(guardScript)) {
|
|
76402
76647
|
fs53.rmSync(guardScript);
|
|
76403
76648
|
removed = true;
|
|
76404
|
-
const parent =
|
|
76649
|
+
const parent = path63.dirname(guardScript);
|
|
76405
76650
|
if (fs53.existsSync(parent) && fs53.readdirSync(parent).length === 0) fs53.rmdirSync(parent);
|
|
76406
76651
|
}
|
|
76407
|
-
const settingsPath =
|
|
76652
|
+
const settingsPath = path63.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
76408
76653
|
if (fs53.existsSync(settingsPath)) {
|
|
76409
76654
|
const settings = readSettings(settingsPath);
|
|
76410
76655
|
const preToolUse = settings.hooks?.PreToolUse;
|
|
@@ -76430,7 +76675,7 @@ function uninstallClaudeGuard(repoPath) {
|
|
|
76430
76675
|
return { removed };
|
|
76431
76676
|
}
|
|
76432
76677
|
function claudeGuardInstalled(repoPath) {
|
|
76433
|
-
const settingsPath =
|
|
76678
|
+
const settingsPath = path63.join(repoPath, CLAUDE_SETTINGS_RELATIVE_PATH);
|
|
76434
76679
|
if (!fs53.existsSync(settingsPath)) return false;
|
|
76435
76680
|
try {
|
|
76436
76681
|
const settings = readSettings(settingsPath);
|
|
@@ -76448,7 +76693,7 @@ function repoOption(y) {
|
|
|
76448
76693
|
function handleInstall2(argv) {
|
|
76449
76694
|
try {
|
|
76450
76695
|
if (argv.claude) {
|
|
76451
|
-
const result2 = installClaudeGuard(
|
|
76696
|
+
const result2 = installClaudeGuard(path64.resolve(argv.repo));
|
|
76452
76697
|
success("Claude Code worktree guard installed.");
|
|
76453
76698
|
info(`Guard script: ${result2.guardScript}`);
|
|
76454
76699
|
info(`Settings: ${result2.settingsPath} (PreToolUse: Edit|Write|MultiEdit|NotebookEdit)`);
|
|
@@ -76456,7 +76701,7 @@ function handleInstall2(argv) {
|
|
|
76456
76701
|
info("Commit both files so the guard travels with the repo.");
|
|
76457
76702
|
return;
|
|
76458
76703
|
}
|
|
76459
|
-
const result = installHooks({ repoPath:
|
|
76704
|
+
const result = installHooks({ repoPath: path64.resolve(argv.repo), force: argv.force });
|
|
76460
76705
|
success(`Commit gate installed in ${result.hooksDir}`);
|
|
76461
76706
|
info(`pre-commit: ${result.preCommit}, post-commit: ${result.postCommit}`);
|
|
76462
76707
|
info("Commits of unverified change batches will be blocked in agent worktrees.");
|
|
@@ -76469,7 +76714,7 @@ function handleInstall2(argv) {
|
|
|
76469
76714
|
function handleUninstall(argv) {
|
|
76470
76715
|
try {
|
|
76471
76716
|
if (argv.claude) {
|
|
76472
|
-
const result2 = uninstallClaudeGuard(
|
|
76717
|
+
const result2 = uninstallClaudeGuard(path64.resolve(argv.repo));
|
|
76473
76718
|
if (result2.removed) {
|
|
76474
76719
|
success("Claude Code worktree guard removed.");
|
|
76475
76720
|
} else {
|
|
@@ -76477,7 +76722,7 @@ function handleUninstall(argv) {
|
|
|
76477
76722
|
}
|
|
76478
76723
|
return;
|
|
76479
76724
|
}
|
|
76480
|
-
const result = uninstallHooks(
|
|
76725
|
+
const result = uninstallHooks(path64.resolve(argv.repo));
|
|
76481
76726
|
if (result.removed) {
|
|
76482
76727
|
success(`Commit gate removed from ${result.hooksDir}`);
|
|
76483
76728
|
} else {
|
|
@@ -76490,7 +76735,7 @@ function handleUninstall(argv) {
|
|
|
76490
76735
|
}
|
|
76491
76736
|
function handleStatus2(argv) {
|
|
76492
76737
|
try {
|
|
76493
|
-
const status = getHooksStatus(
|
|
76738
|
+
const status = getHooksStatus(path64.resolve(argv.repo));
|
|
76494
76739
|
if (argv.json) {
|
|
76495
76740
|
process.stdout.write(`${JSON.stringify(status, null, 2)}
|
|
76496
76741
|
`);
|
|
@@ -76508,7 +76753,7 @@ function handleStatus2(argv) {
|
|
|
76508
76753
|
);
|
|
76509
76754
|
info(`Effective: ${status.effectiveMode} (in this checkout)`);
|
|
76510
76755
|
info(
|
|
76511
|
-
`Claude guard: ${claudeGuardInstalled(
|
|
76756
|
+
`Claude guard: ${claudeGuardInstalled(path64.resolve(argv.repo)) ? `installed (${CLAUDE_GUARD_RELATIVE_PATH})` : "not installed"}`
|
|
76512
76757
|
);
|
|
76513
76758
|
} catch (err) {
|
|
76514
76759
|
error(err instanceof Error ? err.message : String(err));
|
|
@@ -76769,10 +77014,10 @@ function assignProp(target, prop, value) {
|
|
|
76769
77014
|
configurable: true
|
|
76770
77015
|
});
|
|
76771
77016
|
}
|
|
76772
|
-
function getElementAtPath(obj,
|
|
76773
|
-
if (!
|
|
77017
|
+
function getElementAtPath(obj, path69) {
|
|
77018
|
+
if (!path69)
|
|
76774
77019
|
return obj;
|
|
76775
|
-
return
|
|
77020
|
+
return path69.reduce((acc, key) => acc?.[key], obj);
|
|
76776
77021
|
}
|
|
76777
77022
|
function promiseAllObject(promisesObj) {
|
|
76778
77023
|
const keys = Object.keys(promisesObj);
|
|
@@ -77092,11 +77337,11 @@ function aborted(x, startIndex = 0) {
|
|
|
77092
77337
|
}
|
|
77093
77338
|
return false;
|
|
77094
77339
|
}
|
|
77095
|
-
function prefixIssues(
|
|
77340
|
+
function prefixIssues(path69, issues) {
|
|
77096
77341
|
return issues.map((iss) => {
|
|
77097
77342
|
var _a2;
|
|
77098
77343
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
77099
|
-
iss.path.unshift(
|
|
77344
|
+
iss.path.unshift(path69);
|
|
77100
77345
|
return iss;
|
|
77101
77346
|
});
|
|
77102
77347
|
}
|
|
@@ -82419,7 +82664,7 @@ var Protocol = class {
|
|
|
82419
82664
|
return;
|
|
82420
82665
|
}
|
|
82421
82666
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
82422
|
-
await new Promise((
|
|
82667
|
+
await new Promise((resolve52) => setTimeout(resolve52, pollInterval));
|
|
82423
82668
|
options?.signal?.throwIfAborted();
|
|
82424
82669
|
}
|
|
82425
82670
|
} catch (error3) {
|
|
@@ -82436,7 +82681,7 @@ var Protocol = class {
|
|
|
82436
82681
|
*/
|
|
82437
82682
|
request(request, resultSchema, options) {
|
|
82438
82683
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
82439
|
-
return new Promise((
|
|
82684
|
+
return new Promise((resolve52, reject) => {
|
|
82440
82685
|
const earlyReject = (error3) => {
|
|
82441
82686
|
reject(error3);
|
|
82442
82687
|
};
|
|
@@ -82514,7 +82759,7 @@ var Protocol = class {
|
|
|
82514
82759
|
if (!parseResult.success) {
|
|
82515
82760
|
reject(parseResult.error);
|
|
82516
82761
|
} else {
|
|
82517
|
-
|
|
82762
|
+
resolve52(parseResult.data);
|
|
82518
82763
|
}
|
|
82519
82764
|
} catch (error3) {
|
|
82520
82765
|
reject(error3);
|
|
@@ -82775,12 +83020,12 @@ var Protocol = class {
|
|
|
82775
83020
|
}
|
|
82776
83021
|
} catch {
|
|
82777
83022
|
}
|
|
82778
|
-
return new Promise((
|
|
83023
|
+
return new Promise((resolve52, reject) => {
|
|
82779
83024
|
if (signal.aborted) {
|
|
82780
83025
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
82781
83026
|
return;
|
|
82782
83027
|
}
|
|
82783
|
-
const timeoutId = setTimeout(
|
|
83028
|
+
const timeoutId = setTimeout(resolve52, interval);
|
|
82784
83029
|
signal.addEventListener("abort", () => {
|
|
82785
83030
|
clearTimeout(timeoutId);
|
|
82786
83031
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -83570,7 +83815,7 @@ var Server = class extends Protocol {
|
|
|
83570
83815
|
};
|
|
83571
83816
|
|
|
83572
83817
|
// src/mcp/server.ts
|
|
83573
|
-
var
|
|
83818
|
+
var path65 = __toESM(require("path"));
|
|
83574
83819
|
|
|
83575
83820
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
83576
83821
|
var import_node_process3 = __toESM(require("node:process"), 1);
|
|
@@ -83653,12 +83898,12 @@ var StdioServerTransport = class {
|
|
|
83653
83898
|
this.onclose?.();
|
|
83654
83899
|
}
|
|
83655
83900
|
send(message) {
|
|
83656
|
-
return new Promise((
|
|
83901
|
+
return new Promise((resolve52) => {
|
|
83657
83902
|
const json = serializeMessage(message);
|
|
83658
83903
|
if (this._stdout.write(json)) {
|
|
83659
|
-
|
|
83904
|
+
resolve52();
|
|
83660
83905
|
} else {
|
|
83661
|
-
this._stdout.once("drain",
|
|
83906
|
+
this._stdout.once("drain", resolve52);
|
|
83662
83907
|
}
|
|
83663
83908
|
});
|
|
83664
83909
|
}
|
|
@@ -84297,7 +84542,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
84297
84542
|
const input = ControlUpInputSchema.parse({ ...args, repo });
|
|
84298
84543
|
const result = await startControlAndSync({
|
|
84299
84544
|
detach: input.detach,
|
|
84300
|
-
cwd:
|
|
84545
|
+
cwd: path65.resolve(input.repo)
|
|
84301
84546
|
});
|
|
84302
84547
|
if (result.code !== 0) {
|
|
84303
84548
|
return {
|
|
@@ -84361,11 +84606,11 @@ var mcpCommand = {
|
|
|
84361
84606
|
};
|
|
84362
84607
|
|
|
84363
84608
|
// src/cli/commands/onboard.ts
|
|
84364
|
-
var
|
|
84609
|
+
var path67 = __toESM(require("path"));
|
|
84365
84610
|
init_stages();
|
|
84366
84611
|
|
|
84367
84612
|
// src/core/onboarding.ts
|
|
84368
|
-
var
|
|
84613
|
+
var path66 = __toESM(require("path"));
|
|
84369
84614
|
init_control_config();
|
|
84370
84615
|
init_control_sync();
|
|
84371
84616
|
init_otel_hooks();
|
|
@@ -84509,7 +84754,7 @@ async function defaultEnsureControl(options) {
|
|
|
84509
84754
|
return { started: true, apiUrl: result.apiUrl };
|
|
84510
84755
|
}
|
|
84511
84756
|
async function runOnboarding(options, deps = {}) {
|
|
84512
|
-
const repoPath =
|
|
84757
|
+
const repoPath = path66.resolve(options.repoPath);
|
|
84513
84758
|
const applyTelemetry = deps.applyTelemetry ?? applyOnboardingTelemetry;
|
|
84514
84759
|
const ensureControl = deps.ensureControl ?? defaultEnsureControl;
|
|
84515
84760
|
const init = deps.initHarness ?? initHarness;
|
|
@@ -84707,7 +84952,7 @@ async function promptChoices(args, docker) {
|
|
|
84707
84952
|
};
|
|
84708
84953
|
}
|
|
84709
84954
|
const pluginChoices = listPluginChoices();
|
|
84710
|
-
const repoPath =
|
|
84955
|
+
const repoPath = path67.resolve(args.repo);
|
|
84711
84956
|
const alreadyPresent = harnessExists(repoPath);
|
|
84712
84957
|
const needProfile = !alreadyPresent && !args.skipInit && args.profile === void 0;
|
|
84713
84958
|
const needAgentSlots = shouldConfigureSlots && flaggedSlots === void 0;
|
|
@@ -84828,7 +85073,7 @@ function printSummary(result) {
|
|
|
84828
85073
|
console.error("");
|
|
84829
85074
|
}
|
|
84830
85075
|
async function handleOnboard(argv) {
|
|
84831
|
-
const repoPath =
|
|
85076
|
+
const repoPath = path67.resolve(argv.repo);
|
|
84832
85077
|
header("har onboard");
|
|
84833
85078
|
info(`Repository: ${repoPath}`);
|
|
84834
85079
|
try {
|
|
@@ -85062,7 +85307,7 @@ var preferencesCommand = {
|
|
|
85062
85307
|
};
|
|
85063
85308
|
|
|
85064
85309
|
// src/cli/commands/telemetry.ts
|
|
85065
|
-
var
|
|
85310
|
+
var path68 = __toESM(require("path"));
|
|
85066
85311
|
init_control_config();
|
|
85067
85312
|
init_control_sync();
|
|
85068
85313
|
init_manifest();
|
|
@@ -85155,7 +85400,7 @@ async function handleOff() {
|
|
|
85155
85400
|
info("Mission Control will not auto-start. Existing usage rows are kept.");
|
|
85156
85401
|
}
|
|
85157
85402
|
async function handleWriteEnv(argv) {
|
|
85158
|
-
const repoPath =
|
|
85403
|
+
const repoPath = path68.resolve(argv.repo);
|
|
85159
85404
|
const harnessRoot = resolveHarnessRoot(repoPath);
|
|
85160
85405
|
const session = readSlotRegistry(harnessRoot, argv.agentId);
|
|
85161
85406
|
const workDir = argv.workDir ?? session?.workDir ?? repoPath;
|
|
@@ -85167,7 +85412,7 @@ async function handleWriteEnv(argv) {
|
|
|
85167
85412
|
suffix,
|
|
85168
85413
|
createdAt: session?.createdAt
|
|
85169
85414
|
});
|
|
85170
|
-
const envFile = argv.envFile ??
|
|
85415
|
+
const envFile = argv.envFile ?? path68.join(workDir, `.env.agent.${argv.agentId}`);
|
|
85171
85416
|
const attrs = {
|
|
85172
85417
|
sessionKey,
|
|
85173
85418
|
agentId: argv.agentId,
|
|
@@ -85183,7 +85428,7 @@ async function handleWriteEnv(argv) {
|
|
|
85183
85428
|
success(`Wrote session attribution to ${envFile}`);
|
|
85184
85429
|
}
|
|
85185
85430
|
function handlePrintEnv(argv) {
|
|
85186
|
-
const repoPath =
|
|
85431
|
+
const repoPath = path68.resolve(argv.repo);
|
|
85187
85432
|
const workDir = argv.workDir ?? repoPath;
|
|
85188
85433
|
const sessionKey = buildSessionKey({
|
|
85189
85434
|
branch: argv.branch,
|