@osfactory/har 0.13.0 → 0.14.0
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 +225 -67
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23129,6 +23129,22 @@ var AgentSessionUsageSchema = external_exports.object({
|
|
|
23129
23129
|
var SyncUsageInputSchema = external_exports.object({
|
|
23130
23130
|
usage: external_exports.array(AgentSessionUsageSchema)
|
|
23131
23131
|
});
|
|
23132
|
+
var AgentSessionEventSchema = external_exports.object({
|
|
23133
|
+
sessionKey: external_exports.string().min(1),
|
|
23134
|
+
agentId: external_exports.number().int().min(HAR_AGENT_SLOT_MIN),
|
|
23135
|
+
agentTool: AgentToolSchema,
|
|
23136
|
+
eventName: external_exports.string().min(1),
|
|
23137
|
+
sequence: external_exports.number().int().nonnegative().default(0),
|
|
23138
|
+
timestamp: external_exports.string(),
|
|
23139
|
+
attributes: external_exports.record(external_exports.unknown()).optional(),
|
|
23140
|
+
promptText: external_exports.string().nullable().optional(),
|
|
23141
|
+
responseText: external_exports.string().nullable().optional(),
|
|
23142
|
+
rawTruncated: external_exports.string().nullable().optional(),
|
|
23143
|
+
source: external_exports.enum(["otel", "harvest"]).default("otel")
|
|
23144
|
+
});
|
|
23145
|
+
var SyncSessionEventsInputSchema = external_exports.object({
|
|
23146
|
+
events: external_exports.array(AgentSessionEventSchema)
|
|
23147
|
+
});
|
|
23132
23148
|
|
|
23133
23149
|
// src/harness/manifest.ts
|
|
23134
23150
|
var GENERATOR_VERSION = "0.4.0";
|
|
@@ -23367,7 +23383,7 @@ async function handleAgentSkills(options) {
|
|
|
23367
23383
|
const { repoPath, mode } = options;
|
|
23368
23384
|
if (options.enabled === false) return false;
|
|
23369
23385
|
let targets;
|
|
23370
|
-
if (options.agents
|
|
23386
|
+
if (typeof options.agents === "string") {
|
|
23371
23387
|
targets = parseAgentTargets(options.agents);
|
|
23372
23388
|
} else {
|
|
23373
23389
|
targets = detectAgentTargets(repoPath);
|
|
@@ -29915,6 +29931,18 @@ function createRemoteExecutor(apiUrl, apiKey) {
|
|
|
29915
29931
|
var fs33 = __toESM(require("fs"));
|
|
29916
29932
|
var os9 = __toESM(require("os"));
|
|
29917
29933
|
var path33 = __toESM(require("path"));
|
|
29934
|
+
var DEFAULT_SIGNALS_ON = {
|
|
29935
|
+
metrics: true,
|
|
29936
|
+
logs: true,
|
|
29937
|
+
prompts: false,
|
|
29938
|
+
traces: false
|
|
29939
|
+
};
|
|
29940
|
+
var DEFAULT_SIGNALS_OFF = {
|
|
29941
|
+
metrics: false,
|
|
29942
|
+
logs: false,
|
|
29943
|
+
prompts: false,
|
|
29944
|
+
traces: false
|
|
29945
|
+
};
|
|
29918
29946
|
function getPreferencePath() {
|
|
29919
29947
|
if (process.env.HAR_TELEMETRY_CONFIG_PATH) {
|
|
29920
29948
|
return path33.resolve(process.env.HAR_TELEMETRY_CONFIG_PATH);
|
|
@@ -29928,24 +29956,41 @@ function parseEnvOverride(raw) {
|
|
|
29928
29956
|
if (["1", "true", "on", "yes", "enabled"].includes(normalized)) return true;
|
|
29929
29957
|
return void 0;
|
|
29930
29958
|
}
|
|
29959
|
+
function normalizeSignals(enabled, raw) {
|
|
29960
|
+
if (!enabled) return { ...DEFAULT_SIGNALS_OFF };
|
|
29961
|
+
return {
|
|
29962
|
+
metrics: raw?.metrics !== false,
|
|
29963
|
+
logs: raw?.logs !== false,
|
|
29964
|
+
prompts: raw?.prompts === true,
|
|
29965
|
+
traces: raw?.traces === true
|
|
29966
|
+
};
|
|
29967
|
+
}
|
|
29931
29968
|
function readTelemetryPreference() {
|
|
29932
29969
|
const preferencePath = getPreferencePath();
|
|
29933
29970
|
try {
|
|
29934
29971
|
if (!fs33.existsSync(preferencePath)) {
|
|
29935
|
-
return { enabled: true };
|
|
29972
|
+
return { enabled: true, signals: { ...DEFAULT_SIGNALS_ON } };
|
|
29936
29973
|
}
|
|
29937
29974
|
const parsed = JSON.parse(fs33.readFileSync(preferencePath, "utf8"));
|
|
29975
|
+
const enabled = parsed.enabled !== false;
|
|
29938
29976
|
return {
|
|
29939
|
-
enabled
|
|
29977
|
+
enabled,
|
|
29978
|
+
signals: normalizeSignals(enabled, parsed.signals),
|
|
29940
29979
|
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : void 0
|
|
29941
29980
|
};
|
|
29942
29981
|
} catch {
|
|
29943
|
-
return { enabled: true };
|
|
29982
|
+
return { enabled: true, signals: { ...DEFAULT_SIGNALS_ON } };
|
|
29944
29983
|
}
|
|
29945
29984
|
}
|
|
29946
|
-
function writeTelemetryPreference(enabled) {
|
|
29985
|
+
function writeTelemetryPreference(enabled, signals) {
|
|
29986
|
+
const current = readTelemetryPreference();
|
|
29987
|
+
const nextSignals = normalizeSignals(enabled, {
|
|
29988
|
+
...current.signals,
|
|
29989
|
+
...signals
|
|
29990
|
+
});
|
|
29947
29991
|
const preference = {
|
|
29948
29992
|
enabled,
|
|
29993
|
+
signals: enabled ? nextSignals : { ...DEFAULT_SIGNALS_OFF },
|
|
29949
29994
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
29950
29995
|
};
|
|
29951
29996
|
const preferencePath = getPreferencePath();
|
|
@@ -29958,12 +30003,18 @@ function isTelemetryEnabled() {
|
|
|
29958
30003
|
if (envOverride !== void 0) return envOverride;
|
|
29959
30004
|
return readTelemetryPreference().enabled;
|
|
29960
30005
|
}
|
|
30006
|
+
function getTelemetrySignals() {
|
|
30007
|
+
if (!isTelemetryEnabled()) return { ...DEFAULT_SIGNALS_OFF };
|
|
30008
|
+
return readTelemetryPreference().signals;
|
|
30009
|
+
}
|
|
29961
30010
|
function getTelemetryPreferencePath() {
|
|
29962
30011
|
return getPreferencePath();
|
|
29963
30012
|
}
|
|
29964
30013
|
var TELEMETRY_SIGNALS = [
|
|
29965
|
-
"
|
|
29966
|
-
"
|
|
30014
|
+
"Metrics (default): tokens and estimated USD cost via OTEL metrics",
|
|
30015
|
+
"Logs/events (default): session events (tool calls, api_request) without prompt bodies",
|
|
30016
|
+
"Prompts (opt-in): user/assistant text via OTEL_LOG_USER_PROMPTS \u2014 har telemetry on --prompts",
|
|
30017
|
+
"Traces (opt-in): thin span ingest when CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1",
|
|
29967
30018
|
"Fallback: har control sync harvests local Claude/Codex session files when OTEL is missing"
|
|
29968
30019
|
];
|
|
29969
30020
|
|
|
@@ -30006,13 +30057,31 @@ function buildTelemetryEnvBlock(attrs, options) {
|
|
|
30006
30057
|
];
|
|
30007
30058
|
const injectOtel = isTelemetryEnabled() && options?.otelReady !== false;
|
|
30008
30059
|
if (injectOtel) {
|
|
30060
|
+
const signals = getTelemetrySignals();
|
|
30009
30061
|
lines.push(
|
|
30010
30062
|
"# HAR telemetry \u2192 Mission Control OTLP (disable: har telemetry off)",
|
|
30011
30063
|
"CLAUDE_CODE_ENABLE_TELEMETRY=1",
|
|
30012
|
-
"OTEL_METRICS_EXPORTER=otlp",
|
|
30013
30064
|
"OTEL_EXPORTER_OTLP_PROTOCOL=http/json",
|
|
30014
30065
|
`OTEL_EXPORTER_OTLP_ENDPOINT=${apiUrl}/api/otel`
|
|
30015
30066
|
);
|
|
30067
|
+
if (signals.metrics) {
|
|
30068
|
+
lines.push("OTEL_METRICS_EXPORTER=otlp");
|
|
30069
|
+
}
|
|
30070
|
+
if (signals.logs) {
|
|
30071
|
+
lines.push("OTEL_LOGS_EXPORTER=otlp");
|
|
30072
|
+
}
|
|
30073
|
+
if (signals.prompts) {
|
|
30074
|
+
lines.push(
|
|
30075
|
+
"OTEL_LOG_USER_PROMPTS=1",
|
|
30076
|
+
"OTEL_LOG_ASSISTANT_RESPONSES=1"
|
|
30077
|
+
);
|
|
30078
|
+
}
|
|
30079
|
+
if (signals.traces) {
|
|
30080
|
+
lines.push(
|
|
30081
|
+
"OTEL_TRACES_EXPORTER=otlp",
|
|
30082
|
+
"CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1"
|
|
30083
|
+
);
|
|
30084
|
+
}
|
|
30016
30085
|
}
|
|
30017
30086
|
return lines.join("\n") + "\n";
|
|
30018
30087
|
}
|
|
@@ -30111,19 +30180,12 @@ function extractClaudeUsageFromRecords(records) {
|
|
|
30111
30180
|
}
|
|
30112
30181
|
return { tokensInput, tokensOutput, tokensCacheRead, tokensCacheCreation, costUsd };
|
|
30113
30182
|
}
|
|
30114
|
-
function
|
|
30183
|
+
function findMatchingClaudeTranscripts(slot) {
|
|
30115
30184
|
const targets = [slot.workDir, slot.worktreePath].filter(Boolean);
|
|
30116
|
-
if (targets.length === 0) return
|
|
30185
|
+
if (targets.length === 0) return [];
|
|
30117
30186
|
const root = claudeProjectsRoot();
|
|
30118
|
-
if (!fs35.existsSync(root)) return
|
|
30119
|
-
const
|
|
30120
|
-
branch: slot.branch,
|
|
30121
|
-
agentId: slot.agentId,
|
|
30122
|
-
suffix: slot.suffix,
|
|
30123
|
-
createdAt: slot.sessionCreatedAt
|
|
30124
|
-
});
|
|
30125
|
-
let best = null;
|
|
30126
|
-
let bestMtime = 0;
|
|
30187
|
+
if (!fs35.existsSync(root)) return [];
|
|
30188
|
+
const matches = [];
|
|
30127
30189
|
for (const entry of fs35.readdirSync(root, { withFileTypes: true })) {
|
|
30128
30190
|
if (!entry.isDirectory()) continue;
|
|
30129
30191
|
const projectDir = path35.join(root, entry.name);
|
|
@@ -30143,16 +30205,70 @@ function harvestClaudeUsage(slot) {
|
|
|
30143
30205
|
}
|
|
30144
30206
|
}
|
|
30145
30207
|
if (!cwdHit) continue;
|
|
30146
|
-
|
|
30147
|
-
if (usage2.tokensInput + usage2.tokensOutput + usage2.tokensCacheRead === 0 && (usage2.costUsd == null || usage2.costUsd === 0)) {
|
|
30148
|
-
continue;
|
|
30149
|
-
}
|
|
30150
|
-
if (stat.mtimeMs >= bestMtime) {
|
|
30151
|
-
bestMtime = stat.mtimeMs;
|
|
30152
|
-
best = usage2;
|
|
30153
|
-
}
|
|
30208
|
+
matches.push({ filePath, records, mtimeMs: stat.mtimeMs });
|
|
30154
30209
|
}
|
|
30155
30210
|
}
|
|
30211
|
+
return matches.sort((a2, b2) => b2.mtimeMs - a2.mtimeMs);
|
|
30212
|
+
}
|
|
30213
|
+
function extractPromptEvents(records, sessionKey, slot) {
|
|
30214
|
+
const events = [];
|
|
30215
|
+
let sequence = 0;
|
|
30216
|
+
for (const record2 of records) {
|
|
30217
|
+
if (!record2 || typeof record2 !== "object") continue;
|
|
30218
|
+
const payload = record2;
|
|
30219
|
+
const typ = String(payload.type ?? "");
|
|
30220
|
+
const message = payload.message;
|
|
30221
|
+
const role = String(message?.role ?? payload.role ?? "");
|
|
30222
|
+
let text = null;
|
|
30223
|
+
const content = message?.content ?? payload.content;
|
|
30224
|
+
if (typeof content === "string") text = content;
|
|
30225
|
+
else if (Array.isArray(content)) {
|
|
30226
|
+
text = content.map((part) => {
|
|
30227
|
+
if (typeof part === "string") return part;
|
|
30228
|
+
if (part && typeof part === "object" && typeof part.text === "string") {
|
|
30229
|
+
return part.text;
|
|
30230
|
+
}
|
|
30231
|
+
return "";
|
|
30232
|
+
}).filter(Boolean).join("\n");
|
|
30233
|
+
}
|
|
30234
|
+
if (!text || text.trim().length === 0) continue;
|
|
30235
|
+
const isUser = typ === "user" || role === "user" || typ === "human" || Boolean(payload.userType);
|
|
30236
|
+
const isAssistant = typ === "assistant" || role === "assistant";
|
|
30237
|
+
if (!isUser && !isAssistant) continue;
|
|
30238
|
+
sequence += 1;
|
|
30239
|
+
const timestamp = typeof payload.timestamp === "string" ? payload.timestamp : typeof payload.ts === "string" ? payload.ts : (/* @__PURE__ */ new Date()).toISOString();
|
|
30240
|
+
events.push({
|
|
30241
|
+
sessionKey,
|
|
30242
|
+
agentId: slot.agentId,
|
|
30243
|
+
agentTool: "claude_code",
|
|
30244
|
+
eventName: isUser ? "claude_code.user_prompt" : "claude_code.assistant_response",
|
|
30245
|
+
sequence,
|
|
30246
|
+
timestamp,
|
|
30247
|
+
promptText: isUser ? text.slice(0, 8e3) : null,
|
|
30248
|
+
responseText: isAssistant ? text.slice(0, 8e3) : null,
|
|
30249
|
+
rawTruncated: text.slice(0, 4e3),
|
|
30250
|
+
source: "harvest"
|
|
30251
|
+
});
|
|
30252
|
+
}
|
|
30253
|
+
return events;
|
|
30254
|
+
}
|
|
30255
|
+
function harvestClaudeUsage(slot) {
|
|
30256
|
+
const matches = findMatchingClaudeTranscripts(slot);
|
|
30257
|
+
const sessionKey = buildSessionKey({
|
|
30258
|
+
branch: slot.branch,
|
|
30259
|
+
agentId: slot.agentId,
|
|
30260
|
+
suffix: slot.suffix,
|
|
30261
|
+
createdAt: slot.sessionCreatedAt
|
|
30262
|
+
});
|
|
30263
|
+
let best = null;
|
|
30264
|
+
for (const match of matches) {
|
|
30265
|
+
const usage2 = extractClaudeUsageFromRecords(match.records);
|
|
30266
|
+
if (usage2.tokensInput + usage2.tokensOutput + usage2.tokensCacheRead === 0 && (usage2.costUsd == null || usage2.costUsd === 0)) {
|
|
30267
|
+
continue;
|
|
30268
|
+
}
|
|
30269
|
+
best = usage2;
|
|
30270
|
+
break;
|
|
30271
|
+
}
|
|
30156
30272
|
if (!best) return null;
|
|
30157
30273
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
30158
30274
|
const tokensTotal = best.tokensInput + best.tokensOutput + best.tokensCacheRead + best.tokensCacheCreation;
|
|
@@ -30174,6 +30290,18 @@ function harvestClaudeUsage(slot) {
|
|
|
30174
30290
|
lastSeenAt: now
|
|
30175
30291
|
};
|
|
30176
30292
|
}
|
|
30293
|
+
function harvestClaudeEvents(slot) {
|
|
30294
|
+
if (!getTelemetrySignals().prompts) return [];
|
|
30295
|
+
const matches = findMatchingClaudeTranscripts(slot);
|
|
30296
|
+
if (matches.length === 0) return [];
|
|
30297
|
+
const sessionKey = buildSessionKey({
|
|
30298
|
+
branch: slot.branch,
|
|
30299
|
+
agentId: slot.agentId,
|
|
30300
|
+
suffix: slot.suffix,
|
|
30301
|
+
createdAt: slot.sessionCreatedAt
|
|
30302
|
+
});
|
|
30303
|
+
return extractPromptEvents(matches[0].records, sessionKey, slot).slice(-40);
|
|
30304
|
+
}
|
|
30177
30305
|
|
|
30178
30306
|
// src/core/usage-harvest/codex.ts
|
|
30179
30307
|
var fs36 = __toESM(require("fs"));
|
|
@@ -30300,6 +30428,9 @@ function harvestUsageForSlot(slot) {
|
|
|
30300
30428
|
if (codex) out.push(codex);
|
|
30301
30429
|
return out;
|
|
30302
30430
|
}
|
|
30431
|
+
function harvestEventsForSlot(slot) {
|
|
30432
|
+
return harvestClaudeEvents(slot);
|
|
30433
|
+
}
|
|
30303
30434
|
|
|
30304
30435
|
// src/core/control-sync.ts
|
|
30305
30436
|
async function postJson(url, body, dryRun) {
|
|
@@ -30454,6 +30585,21 @@ async function syncRepoRunsAndSlots(apiUrl, repoId, repoPath, dryRun) {
|
|
|
30454
30585
|
const usageBody = SyncUsageInputSchema.parse({ usage: usage2 });
|
|
30455
30586
|
await postJson(`${apiUrl}/api/repos/${repoId}/usage`, usageBody, dryRun);
|
|
30456
30587
|
}
|
|
30588
|
+
const events = status.slots.flatMap(
|
|
30589
|
+
(slot) => harvestEventsForSlot({
|
|
30590
|
+
agentId: slot.agentId,
|
|
30591
|
+
workDir: slot.workDir,
|
|
30592
|
+
worktreePath: slot.worktreePath,
|
|
30593
|
+
branch: slot.branch,
|
|
30594
|
+
suffix: slot.suffix,
|
|
30595
|
+
sessionCreatedAt: slot.sessionCreatedAt,
|
|
30596
|
+
repoPath
|
|
30597
|
+
})
|
|
30598
|
+
);
|
|
30599
|
+
if (events.length > 0) {
|
|
30600
|
+
const eventsBody = SyncSessionEventsInputSchema.parse({ events });
|
|
30601
|
+
await postJson(`${apiUrl}/api/repos/${repoId}/events`, eventsBody, dryRun);
|
|
30602
|
+
}
|
|
30457
30603
|
} catch (err) {
|
|
30458
30604
|
const message = err instanceof Error ? err.message : String(err);
|
|
30459
30605
|
process.stderr.write(`[har control] usage harvest skipped: ${message}
|
|
@@ -31109,19 +31255,14 @@ var envCommand = {
|
|
|
31109
31255
|
describe: "Auto-apply AGENT.md proposal without prompting (--auto only)"
|
|
31110
31256
|
}).option("cursor-rule", {
|
|
31111
31257
|
type: "boolean",
|
|
31112
|
-
default: false
|
|
31113
|
-
|
|
31114
|
-
|
|
31115
|
-
type: "boolean",
|
|
31116
|
-
default: false,
|
|
31117
|
-
describe: "Skip Cursor rule scaffolding"
|
|
31258
|
+
// No default: unset → prompt/auto-detect; --cursor-rule → true; --no-cursor-rule → false
|
|
31259
|
+
// (do not declare a separate --no-cursor-rule option — yargs negation owns that.)
|
|
31260
|
+
describe: "Create .cursor/rules/har-workflow.mdc without prompting (use --no-cursor-rule to skip)"
|
|
31118
31261
|
}).option("agents", {
|
|
31119
31262
|
type: "string",
|
|
31120
|
-
|
|
31121
|
-
|
|
31122
|
-
|
|
31123
|
-
default: false,
|
|
31124
|
-
describe: "Skip agent skills scaffolding"
|
|
31263
|
+
// --no-agents is yargs negation of this string option (sets agents=false). Do not
|
|
31264
|
+
// declare a separate --no-agents boolean — it collides and crashes parseAgentTargets.
|
|
31265
|
+
describe: "Scaffold agent skills for these targets (comma-separated: claude,cursor,codex); auto-detected when omitted; --no-agents to skip"
|
|
31125
31266
|
}),
|
|
31126
31267
|
handleInit
|
|
31127
31268
|
).command(
|
|
@@ -31140,19 +31281,11 @@ var envCommand = {
|
|
|
31140
31281
|
describe: "Adaptation summary to store in the manifest (--finalize only)"
|
|
31141
31282
|
}).option("cursor-rule", {
|
|
31142
31283
|
type: "boolean",
|
|
31143
|
-
default: false
|
|
31144
|
-
describe: "Create .cursor/rules/har-workflow.mdc without prompting"
|
|
31145
|
-
}).option("no-cursor-rule", {
|
|
31146
|
-
type: "boolean",
|
|
31147
|
-
default: false,
|
|
31148
|
-
describe: "Skip Cursor rule scaffolding"
|
|
31284
|
+
// No default: unset → prompt/auto-detect; --cursor-rule → true; --no-cursor-rule → false
|
|
31285
|
+
describe: "Create .cursor/rules/har-workflow.mdc without prompting (use --no-cursor-rule to skip)"
|
|
31149
31286
|
}).option("agents", {
|
|
31150
31287
|
type: "string",
|
|
31151
|
-
describe: "Scaffold agent skills for these targets (comma-separated: claude,cursor,codex); auto-detected when omitted"
|
|
31152
|
-
}).option("no-agents", {
|
|
31153
|
-
type: "boolean",
|
|
31154
|
-
default: false,
|
|
31155
|
-
describe: "Skip agent skills scaffolding"
|
|
31288
|
+
describe: "Scaffold agent skills for these targets (comma-separated: claude,cursor,codex); auto-detected when omitted; --no-agents to skip"
|
|
31156
31289
|
}),
|
|
31157
31290
|
handleMaintain
|
|
31158
31291
|
).command(
|
|
@@ -31328,14 +31461,13 @@ async function handleInit(argv) {
|
|
|
31328
31461
|
recordRepoForControlSync(repoPath);
|
|
31329
31462
|
await handleCursorRule({
|
|
31330
31463
|
repoPath,
|
|
31331
|
-
cursorRule: resolveCursorRuleFlag(argv.cursorRule
|
|
31464
|
+
cursorRule: resolveCursorRuleFlag(argv.cursorRule),
|
|
31332
31465
|
autoYes: argv.yes,
|
|
31333
31466
|
mode: "init"
|
|
31334
31467
|
});
|
|
31335
31468
|
await handleAgentSkills({
|
|
31336
31469
|
repoPath,
|
|
31337
|
-
|
|
31338
|
-
enabled: argv.noAgents ? false : void 0,
|
|
31470
|
+
...resolveAgentsScaffoldOptions(argv.agents),
|
|
31339
31471
|
autoYes: argv.yes,
|
|
31340
31472
|
force: argv.force,
|
|
31341
31473
|
mode: "init"
|
|
@@ -31401,14 +31533,13 @@ async function handleMaintain(argv) {
|
|
|
31401
31533
|
}
|
|
31402
31534
|
await handleCursorRule({
|
|
31403
31535
|
repoPath,
|
|
31404
|
-
cursorRule: resolveCursorRuleFlag(argv.cursorRule
|
|
31536
|
+
cursorRule: resolveCursorRuleFlag(argv.cursorRule),
|
|
31405
31537
|
autoYes: argv.yes,
|
|
31406
31538
|
mode: "maintain"
|
|
31407
31539
|
});
|
|
31408
31540
|
await handleAgentSkills({
|
|
31409
31541
|
repoPath,
|
|
31410
|
-
|
|
31411
|
-
enabled: argv.noAgents ? false : void 0,
|
|
31542
|
+
...resolveAgentsScaffoldOptions(argv.agents),
|
|
31412
31543
|
autoYes: argv.yes,
|
|
31413
31544
|
mode: "maintain"
|
|
31414
31545
|
});
|
|
@@ -31417,10 +31548,13 @@ async function handleMaintain(argv) {
|
|
|
31417
31548
|
process.exit(1);
|
|
31418
31549
|
}
|
|
31419
31550
|
}
|
|
31420
|
-
function resolveCursorRuleFlag(cursorRule
|
|
31421
|
-
|
|
31422
|
-
|
|
31423
|
-
|
|
31551
|
+
function resolveCursorRuleFlag(cursorRule) {
|
|
31552
|
+
return cursorRule;
|
|
31553
|
+
}
|
|
31554
|
+
function resolveAgentsScaffoldOptions(agents) {
|
|
31555
|
+
if (agents === false) return { enabled: false };
|
|
31556
|
+
if (typeof agents === "string") return { agents };
|
|
31557
|
+
return {};
|
|
31424
31558
|
}
|
|
31425
31559
|
function emitManualAdaptationPrompt(repoPath, mode, profile = "default", bundleReport) {
|
|
31426
31560
|
const prompt = mode === "init" ? buildInitAdaptationPrompt(repoPath, profile) : buildMaintainAdaptationPrompt(repoPath, bundleReport);
|
|
@@ -40163,18 +40297,20 @@ function printSignals() {
|
|
|
40163
40297
|
async function handleStatus3(argv) {
|
|
40164
40298
|
const preference = readTelemetryPreference();
|
|
40165
40299
|
const enabled = isTelemetryEnabled();
|
|
40300
|
+
const signals = getTelemetrySignals();
|
|
40166
40301
|
const apiUrl = getControlApiUrl();
|
|
40167
40302
|
const reachable = enabled ? await isControlApiReachable(apiUrl) : false;
|
|
40168
40303
|
const payload = {
|
|
40169
40304
|
enabled,
|
|
40170
40305
|
preferenceEnabled: preference.enabled,
|
|
40306
|
+
signals,
|
|
40171
40307
|
preferencePath: getTelemetryPreferencePath(),
|
|
40172
40308
|
updatedAt: preference.updatedAt ?? null,
|
|
40173
40309
|
envOverride: process.env.HAR_TELEMETRY ?? null,
|
|
40174
40310
|
controlApiUrl: apiUrl,
|
|
40175
40311
|
controlReachable: reachable,
|
|
40176
40312
|
otelEndpoint: `${apiUrl.replace(/\/$/, "")}/api/otel`,
|
|
40177
|
-
|
|
40313
|
+
signalDescriptions: [...TELEMETRY_SIGNALS]
|
|
40178
40314
|
};
|
|
40179
40315
|
if (argv.json) {
|
|
40180
40316
|
process.stdout.write(`${JSON.stringify(payload, null, 2)}
|
|
@@ -40184,21 +40320,33 @@ async function handleStatus3(argv) {
|
|
|
40184
40320
|
header("har telemetry status");
|
|
40185
40321
|
info(`Enabled: ${enabled ? "yes" : "no"}${process.env.HAR_TELEMETRY ? " (HAR_TELEMETRY override)" : ""}`);
|
|
40186
40322
|
info(`Preference: ${getTelemetryPreferencePath()}${preference.updatedAt ? ` (updated ${preference.updatedAt})` : " (default on)"}`);
|
|
40323
|
+
info(
|
|
40324
|
+
`Signals: metrics=${signals.metrics} logs=${signals.logs} prompts=${signals.prompts} traces=${signals.traces}`
|
|
40325
|
+
);
|
|
40187
40326
|
info(`Mission Control: ${apiUrl} (${reachable ? "reachable" : "not reachable"})`);
|
|
40188
40327
|
info(`OTLP endpoint: ${payload.otelEndpoint}`);
|
|
40189
40328
|
printSignals();
|
|
40190
40329
|
}
|
|
40191
|
-
async function handleOn() {
|
|
40330
|
+
async function handleOn(argv) {
|
|
40192
40331
|
header("har telemetry on");
|
|
40193
|
-
writeTelemetryPreference(true
|
|
40332
|
+
const preference = writeTelemetryPreference(true, {
|
|
40333
|
+
prompts: argv.prompts === true ? true : void 0,
|
|
40334
|
+
traces: argv.traces === true ? true : void 0
|
|
40335
|
+
});
|
|
40194
40336
|
success("Telemetry enabled (opt-out). Agent usage will be stored in local Mission Control.");
|
|
40337
|
+
info(
|
|
40338
|
+
`Signals: metrics=${preference.signals.metrics} logs=${preference.signals.logs} prompts=${preference.signals.prompts} traces=${preference.signals.traces}`
|
|
40339
|
+
);
|
|
40340
|
+
if (preference.signals.prompts) {
|
|
40341
|
+
warn("Prompt/response text will leave the agent machine for local Mission Control storage.");
|
|
40342
|
+
}
|
|
40195
40343
|
printSignals();
|
|
40196
40344
|
const result = await ensureTelemetryInfrastructure({ startIfNeeded: true });
|
|
40197
40345
|
if (result.message) success(result.message);
|
|
40198
40346
|
if (result.warning) warn(result.warning);
|
|
40199
40347
|
if (result.otelReady) {
|
|
40200
40348
|
info(`OTLP ingest: ${result.apiUrl.replace(/\/$/, "")}/api/otel`);
|
|
40201
|
-
info("Usage appears under Mission Control \u2192 Worktrees. Disable: har telemetry off");
|
|
40349
|
+
info("Usage appears under Mission Control \u2192 Worktrees / Usage. Disable: har telemetry off");
|
|
40202
40350
|
}
|
|
40203
40351
|
}
|
|
40204
40352
|
async function handleOff() {
|
|
@@ -40308,10 +40456,20 @@ var telemetryCommand = {
|
|
|
40308
40456
|
).command(
|
|
40309
40457
|
"on",
|
|
40310
40458
|
"Enable telemetry (default) and ensure Mission Control is running",
|
|
40311
|
-
() => {
|
|
40312
|
-
|
|
40313
|
-
|
|
40314
|
-
|
|
40459
|
+
(y2) => y2.option("prompts", {
|
|
40460
|
+
type: "boolean",
|
|
40461
|
+
default: false,
|
|
40462
|
+
describe: "Opt in to shipping user/assistant prompt text to Mission Control"
|
|
40463
|
+
}).option("traces", {
|
|
40464
|
+
type: "boolean",
|
|
40465
|
+
default: false,
|
|
40466
|
+
describe: "Opt in to thin OTEL traces ingest (Claude beta)"
|
|
40467
|
+
}),
|
|
40468
|
+
(argv) => {
|
|
40469
|
+
void handleOn({
|
|
40470
|
+
prompts: argv.prompts,
|
|
40471
|
+
traces: argv.traces
|
|
40472
|
+
});
|
|
40315
40473
|
}
|
|
40316
40474
|
).command(
|
|
40317
40475
|
"off",
|