specrails-desktop 2.44.2 → 2.45.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/README.md +2 -0
- package/client/dist/assets/{ActivityFeedPage-CL1BUXoj.js → ActivityFeedPage-D3SQklu5.js} +1 -1
- package/client/dist/assets/AgentBrowserCapture-DNGxE33d.js +1 -0
- package/client/dist/assets/AgentModeAnalyticsPane-BUvZNoj0.js +2 -0
- package/client/dist/assets/AgentModeCodePane-YW717UvJ.js +2 -0
- package/client/dist/assets/{AgentModeJobsPane-C7ELTPC1.js → AgentModeJobsPane-Cxg_eNmd.js} +1 -1
- package/client/dist/assets/AgentsPage-B_DCByok.js +87 -0
- package/client/dist/assets/{AnalyticsPage-DTsg-N5z.js → AnalyticsPage-BqV6mM2O.js} +1 -1
- package/client/dist/assets/CodePage-PyZKCj1B.js +3 -0
- package/client/dist/assets/{DesktopAnalyticsPage-Y0Z1ryQr.js → DesktopAnalyticsPage-D6WNax3K.js} +1 -1
- package/client/dist/assets/{DocsDialog-KeCOxvGH.js → DocsDialog-68jKUH9f.js} +1 -1
- package/client/dist/assets/{DocsPage-Bt1PgYPO.js → DocsPage-BoGJgRpm.js} +1 -1
- package/client/dist/assets/{ExportDropdown-DczgU4at.js → ExportDropdown-B2C_XLGp.js} +1 -1
- package/client/dist/assets/InteractiveJobComposer-l8q-r5Yy.js +19 -0
- package/client/dist/assets/{JobDetailModal-DKA_DUHe.js → JobDetailModal-C-X2GI9j.js} +1 -1
- package/client/dist/assets/JobDetailPage-C6Jdm7S9.js +1 -0
- package/client/dist/assets/{JobsPage-Bwoe-Fb0.js → JobsPage-DycM6Vgp.js} +1 -1
- package/client/dist/assets/{LoopBuilderPage-CqC4hbXb.js → LoopBuilderPage-D21GxFmL.js} +2 -2
- package/client/dist/assets/{LoopPreviewModal-T0zuFv6y.js → LoopPreviewModal-Bo3fYFxN.js} +1 -1
- package/client/dist/assets/{LoopsPage-DrQGcZv2.js → LoopsPage-BcrBw1cg.js} +1 -1
- package/client/dist/assets/{MinimizedChatsContext-C843Y13h.js → MinimizedChatsContext-Dsv2eHf_.js} +1 -1
- package/client/dist/assets/PluginsPage-BbyTmSLx.js +2 -0
- package/client/dist/assets/ProjectSettingsDialog-B3lEXLv7.js +1 -0
- package/client/dist/assets/{RepositoryDeliveries-bgIHE8ep.js → RepositoryDeliveries-ok_Wo65C.js} +1 -1
- package/client/dist/assets/{RepositoryScopeSelector-CZ_U_R3U.js → RepositoryScopeSelector-DU6QwNaS.js} +1 -1
- package/client/dist/assets/{ReviewPacketPage-DbKO6pT8.js → ReviewPacketPage-BBCeHtgd.js} +1 -1
- package/client/dist/assets/TemplatePreviewModal-CfNmxS6O.js +1 -0
- package/client/dist/assets/{TicketDetailModalContext-BbRA6cb7.js → TicketDetailModalContext-DW3eQ0I7.js} +1 -1
- package/client/dist/assets/{Trans-mjFZpHw1.js → Trans-BHPMWkOw.js} +1 -1
- package/client/dist/assets/agentRuntime-14faDjWM.js +1 -0
- package/client/dist/assets/agentRuntime-BIokojkJ.js +1 -0
- package/client/dist/assets/agentRuntime-Bu4xEcRw.js +1 -0
- package/client/dist/assets/agentRuntime-Cz0ASixB.js +1 -0
- package/client/dist/assets/agentRuntime-DESdGXLV.js +1 -0
- package/client/dist/assets/agentRuntime-DhX5Xy5S.js +1 -0
- package/client/dist/assets/agentRuntime-Dpbh_gLp.js +1 -0
- package/client/dist/assets/agentRuntime-jS2lplFm.js +1 -0
- package/client/dist/assets/{formatDistanceToNow-BIL-HxGy.js → formatDistanceToNow-Bq8iptrG.js} +1 -1
- package/client/dist/assets/{getTimezoneOffsetInMilliseconds-Cs9z2sdO.js → getTimezoneOffsetInMilliseconds-BVFky3l_.js} +1 -1
- package/client/dist/assets/index-CBLYwPw6.css +2 -0
- package/client/dist/assets/index-DOKftX7y.js +76 -0
- package/client/dist/assets/{jira-api-B2BBZQTx.js → jira-api-zrRdZFBB.js} +1 -1
- package/client/dist/assets/{narration-C1Px0-0j.js → narration-BA8Yw5ZL.js} +1 -1
- package/client/dist/assets/{narration-DQ1l_Kq6.js → narration-BuMFUS7Q.js} +1 -1
- package/client/dist/assets/{narration-kwzfglQo.js → narration-Bv_iQQG5.js} +1 -1
- package/client/dist/assets/{narration-B-ynWTpn.js → narration-C6Ost9nL.js} +1 -1
- package/client/dist/assets/{narration-CAXhGbzM.js → narration-CIbjo2pA.js} +1 -1
- package/client/dist/assets/{narration-BxHpmMv_.js → narration-CNJ2-2-a.js} +1 -1
- package/client/dist/assets/{narration-Bj_laZwg.js → narration-OzsPJCXM.js} +1 -1
- package/client/dist/assets/{narration-XISXwqZd.js → narration-zCdgiuSU.js} +1 -1
- package/client/dist/assets/{project-repositories-xSqimlaj.js → project-repositories-CFRaB9UB.js} +1 -1
- package/client/dist/assets/{settings-BLOsrXEw.js → settings-CNiERE-R.js} +1 -1
- package/client/dist/assets/{settings-NSWQjY5B.js → settings-ChOCVjX_.js} +1 -1
- package/client/dist/assets/{settings-C6s9PtRD.js → settings-CrtCs5-B.js} +1 -1
- package/client/dist/assets/{settings-DPjNiUsS.js → settings-DJ2jl3hJ.js} +1 -1
- package/client/dist/assets/{settings-FIqwhTup.js → settings-DVRVybR_.js} +1 -1
- package/client/dist/assets/{settings-CCNZN5Q-.js → settings-DzXZCb1h.js} +1 -1
- package/client/dist/assets/{settings-2Yx_9yJM.js → settings-OOyDrZQo.js} +1 -1
- package/client/dist/assets/{settings-CpKwTew1.js → settings-a7NIODme.js} +1 -1
- package/client/dist/assets/{spending-DXOcv1tn.js → spending-lTZ-bm_y.js} +1 -1
- package/client/dist/assets/{useDesktop-gVGoWWiY.js → useDesktop-Duv5ddAa.js} +1 -1
- package/client/dist/assets/useSharedWebSocket-5mj2SMKn.js +2 -0
- package/client/dist/index.html +17 -16
- package/docs/README.md +1 -0
- package/docs/internals/README.md +2 -0
- package/docs/internals/agent-runtime-framework-evaluation.md +208 -0
- package/docs/internals/programmatic-agent-runtime-validation.md +72 -0
- package/docs/internals/programmatic-agent-runtime.md +129 -0
- package/package.json +1 -1
- package/server/dist/agent-runtime-accounting.js +73 -0
- package/server/dist/agent-runtime-bridge.js +183 -0
- package/server/dist/agent-runtime-controls-router.js +44 -0
- package/server/dist/agent-runtime-controls.js +277 -0
- package/server/dist/agent-runtime-loader.js +85 -0
- package/server/dist/agent-runtime-paths.js +12 -0
- package/server/dist/agent-runtime-settings-router.js +59 -0
- package/server/dist/agent-runtime-settings.js +135 -0
- package/server/dist/agent-runtime-verification-suggestions.js +119 -0
- package/server/dist/core-execution.js +17 -8
- package/server/dist/core-node-runtime.js +12 -0
- package/server/dist/loop-executors.js +42 -2
- package/server/dist/loop-factory.js +1 -1
- package/server/dist/loop-run-manager.js +60 -26
- package/server/dist/project-registry.js +9 -0
- package/server/dist/project-router-settings.js +4 -0
- package/server/dist/rail-isolated-launch.js +18 -0
- package/server/dist/rails-router.js +1 -0
- package/server/dist/schemas/agent-runtime.schema.json +55 -0
- package/client/dist/assets/AgentBrowserCapture-BQem50z4.js +0 -1
- package/client/dist/assets/AgentModeAnalyticsPane-BC_xbT_l.js +0 -2
- package/client/dist/assets/AgentModeCodePane-DK-q3K6Y.js +0 -2
- package/client/dist/assets/AgentsPage-DbLezyI6.js +0 -87
- package/client/dist/assets/CodePage-DwgbeqQ_.js +0 -3
- package/client/dist/assets/InteractiveJobComposer-BcR6xlHU.js +0 -19
- package/client/dist/assets/JobDetailPage-vaOcE-cI.js +0 -1
- package/client/dist/assets/PluginsPage-CTUHX_Lu.js +0 -2
- package/client/dist/assets/ProjectSettingsDialog-DeL8md1s.js +0 -1
- package/client/dist/assets/TemplatePreviewModal-_CgCCV7L.js +0 -1
- package/client/dist/assets/index-Bfj8HvX1.css +0 -2
- package/client/dist/assets/index-UnaJTMIy.js +0 -76
- package/client/dist/assets/useSharedWebSocket-DbGL_YOt.js +0 -2
|
@@ -19,6 +19,7 @@ const ai_invocations_1 = require("./ai-invocations");
|
|
|
19
19
|
const provider_limit_1 = require("./provider-limit");
|
|
20
20
|
const ids_1 = require("./ids");
|
|
21
21
|
const providers_1 = require("./providers");
|
|
22
|
+
const agent_runtime_accounting_1 = require("./agent-runtime-accounting");
|
|
22
23
|
const runtime_1 = require("./providers/runtime");
|
|
23
24
|
const result_event_1 = require("./result-event");
|
|
24
25
|
const rails_store_1 = require("./rails-store");
|
|
@@ -137,6 +138,13 @@ function extractChangeId(text) {
|
|
|
137
138
|
const m = CHANGE_ID_RE.exec(text);
|
|
138
139
|
return m ? m[1] : undefined;
|
|
139
140
|
}
|
|
141
|
+
function programmaticUsageAvailability(db, runId) {
|
|
142
|
+
const row = db.prepare(`SELECT COUNT(*) AS count,
|
|
143
|
+
MAX(total_cost_usd IS NULL) AS cost_unknown,
|
|
144
|
+
MAX(tokens_in IS NULL) AS input_unknown, MAX(tokens_out IS NULL) AS output_unknown
|
|
145
|
+
FROM ai_invocations WHERE surface = 'loop' AND loop_run_id = ? AND provider = 'agent-runtime'`).get(runId);
|
|
146
|
+
return { present: row.count > 0, costUnknown: Boolean(row.cost_unknown), tokensInUnknown: Boolean(row.input_unknown), tokensOutUnknown: Boolean(row.output_unknown) };
|
|
147
|
+
}
|
|
140
148
|
function insertLoopInvocation(db, payload, result, finishedAt) {
|
|
141
149
|
const ticketIds = Array.isArray(payload.ticketIds)
|
|
142
150
|
? [...new Set(payload.ticketIds)]
|
|
@@ -193,14 +201,15 @@ function insertLoopInvocation(db, payload, result, finishedAt) {
|
|
|
193
201
|
FROM ai_invocations
|
|
194
202
|
WHERE surface = 'loop' AND loop_run_id = ?
|
|
195
203
|
`).get(payload.runId);
|
|
196
|
-
const
|
|
204
|
+
const runtimeUsage = programmaticUsageAvailability(db, payload.runId);
|
|
205
|
+
const usageTelemetryAvailable = runtimeUsage.present || (0, providers_1.getAdapter)(payload.provider).capabilities.reportsUsage !== false;
|
|
197
206
|
db.prepare(`
|
|
198
207
|
UPDATE jobs
|
|
199
208
|
SET total_cost_usd = ?, tokens_in = ?, tokens_out = ?,
|
|
200
209
|
tokens_cache_read = ?, tokens_cache_create = ?,
|
|
201
210
|
duration_ms = ?, num_turns = ?
|
|
202
211
|
WHERE id = ? AND owner = 'loop'
|
|
203
|
-
`).run(usageTelemetryAvailable ? aggregate.cost : null, usageTelemetryAvailable ? aggregate.tokens_in : null, usageTelemetryAvailable ? aggregate.tokens_out : null, usageTelemetryAvailable ? aggregate.cache_read : null, usageTelemetryAvailable ? aggregate.cache_create : null, aggregate.duration, usageTelemetryAvailable ? aggregate.turns : null, payload.runId);
|
|
212
|
+
`).run(usageTelemetryAvailable && !runtimeUsage.costUnknown ? aggregate.cost : null, usageTelemetryAvailable && !runtimeUsage.tokensInUnknown ? aggregate.tokens_in : null, usageTelemetryAvailable && !runtimeUsage.tokensOutUnknown ? aggregate.tokens_out : null, usageTelemetryAvailable && !runtimeUsage.present ? aggregate.cache_read : null, usageTelemetryAvailable && !runtimeUsage.present ? aggregate.cache_create : null, aggregate.duration, usageTelemetryAvailable && !runtimeUsage.present ? aggregate.turns : null, payload.runId);
|
|
204
213
|
}
|
|
205
214
|
/** Recover every AI/decider step that was staged before provider spawn but did
|
|
206
215
|
* not atomically land its invocation. Completed interactive turns are the jobs
|
|
@@ -266,6 +275,23 @@ function recoverOrphanLoopStepAccounting(db, finishedAt = new Date().toISOString
|
|
|
266
275
|
WHERE job_id = ? AND seq > ? AND source = 'stdout'
|
|
267
276
|
ORDER BY seq
|
|
268
277
|
`).all(payload.runId, payload.completedEventSeq ?? -1);
|
|
278
|
+
const programmatic = (0, agent_runtime_accounting_1.parseProgrammaticUsage)(rawRows.map(row => row.payload)) ?? (payload.provider === 'agent-runtime'
|
|
279
|
+
? { provider: 'agent-runtime', model: 'per-role', estimated: true, failed: true }
|
|
280
|
+
: undefined);
|
|
281
|
+
if (programmatic) {
|
|
282
|
+
const durationMs = boundedInflightDurationMs(payload, finishedAt);
|
|
283
|
+
const didRecover = (0, loop_runs_store_1.completeLoopStepRecovery)(db, payload.runId, payload.stepKey, stable => {
|
|
284
|
+
insertLoopInvocation(db, stable, { ...programmatic, durationMs }, finishedAt);
|
|
285
|
+
const aggregate = (0, loop_runs_store_1.readLoopJobUsage)(db, payload.runId);
|
|
286
|
+
const duration = (payload.loopDurationBaseline ?? 0) + durationMs;
|
|
287
|
+
db.prepare(`UPDATE loop_runs SET total_cost_usd = ?, total_tokens = ?, total_duration_ms = ?, iteration_count = MAX(iteration_count, COALESCE(?, iteration_count)) WHERE id = ?`)
|
|
288
|
+
.run(aggregate.totalCostUsd, aggregate.tokensIn + aggregate.tokensOut, duration, stable.iterationCount ?? null, payload.runId);
|
|
289
|
+
db.prepare(`UPDATE jobs SET duration_ms = ? WHERE id = ? AND owner = 'loop'`).run(duration, payload.runId);
|
|
290
|
+
});
|
|
291
|
+
if (didRecover)
|
|
292
|
+
recovered += 1;
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
269
295
|
const adapter = (0, providers_1.getAdapter)(payload.provider);
|
|
270
296
|
const usageTelemetryAvailable = adapter.capabilities.reportsUsage !== false;
|
|
271
297
|
const events = rawRows
|
|
@@ -560,7 +586,7 @@ class LoopRunManager {
|
|
|
560
586
|
if (req.graph.nodes.some((node) => node.type === 'decider')) {
|
|
561
587
|
(0, providers_1.requireToolPolicy)(adapter, 'read-only');
|
|
562
588
|
}
|
|
563
|
-
|
|
589
|
+
let usageTelemetryAvailable = adapter.capabilities.reportsUsage !== false;
|
|
564
590
|
const neverAfterDispose = () => new Promise(() => { });
|
|
565
591
|
const runId = req.runId ?? (0, ids_1.newId)();
|
|
566
592
|
const maxIterations = req.graph.config.maxIterations;
|
|
@@ -828,20 +854,20 @@ class LoopRunManager {
|
|
|
828
854
|
// The REAL turn-start instant, captured before the step/decider await. The
|
|
829
855
|
// row is bucketed/ordered by started_at, so it must be the start, not finish.
|
|
830
856
|
startedAt, stepKey) => {
|
|
857
|
+
if (r.provider === 'agent-runtime')
|
|
858
|
+
usageTelemetryAvailable = true;
|
|
831
859
|
if (usageTelemetryAvailable)
|
|
832
860
|
totalCost += r.cost ?? 0;
|
|
833
|
-
//
|
|
834
|
-
//
|
|
835
|
-
//
|
|
836
|
-
// tokens streamed, but cost (and tokens) are dropped, so the step bills $0.
|
|
837
|
-
// Flag the run total as a lower bound and say so, per occurrence.
|
|
861
|
+
// Missing pricing does not identify the failure cause or prove zero spend:
|
|
862
|
+
// providers can omit billing after a successful call or reject a request
|
|
863
|
+
// before model work starts. Retain known costs and flag the incomplete sum.
|
|
838
864
|
const costBearingButUnpriced = usageTelemetryAvailable
|
|
839
865
|
&& r.cost == null
|
|
840
866
|
&& (r.failed === true || (r.tokens ?? 0) > 0);
|
|
841
867
|
if (costBearingButUnpriced) {
|
|
842
868
|
costUncertain = true;
|
|
843
869
|
costUnknownWarned = true; // this line already carries the cap caveat below
|
|
844
|
-
logLine(`⚠️ Step cost unknown —
|
|
870
|
+
logLine(`⚠️ Step cost unknown — this step did not report a priced cost. The reported loop total includes known costs only.${maxCostUsd !== undefined ? ' The cost cap may under-count.' : ''}`, 'stderr');
|
|
845
871
|
}
|
|
846
872
|
// Honest cost-cap caveat: a cost-bearing step that reports no figure means
|
|
847
873
|
// the cap can't be enforced precisely from here on. Warn once (live).
|
|
@@ -1058,7 +1084,7 @@ class LoopRunManager {
|
|
|
1058
1084
|
// --yes`, codex `$implement #<id> --yes`) — then resolve `{{spec.*}}`
|
|
1059
1085
|
// data tokens and finally `{{const:*}}` library constants.
|
|
1060
1086
|
const rawTemplate = String(node.data?.prompt ?? '');
|
|
1061
|
-
const requiresCoreCompletion = /\{\{\s*cmd:(?:implement|batch)\s*\}\}/.test(rawTemplate)
|
|
1087
|
+
const requiresCoreCompletion = node.data?.operation === 'core-implementation' || /\{\{\s*cmd:(?:implement|batch)\s*\}\}/.test(rawTemplate)
|
|
1062
1088
|
|| /^\s*(?:\/specrails:|\/skill:specrails-|\$)(?:implement|batch-implement)(?:\s|$)/.test(rawTemplate);
|
|
1063
1089
|
const expanded = (0, loop_constants_1.resolveConstants)(resolveRunVars((0, loop_graph_1.interpolateSpec)((0, loop_command_catalog_1.expandCommands)(rawTemplate, { provider: nodeProvider, ticketIds: req.spec?.ticketIds, specId: req.spec?.id }), req.spec), runVars), constMap);
|
|
1064
1090
|
const base = [(0, multi_repo_execution_store_1.executionManifestPrompt)(req.executionManifest), withReviewContinuationContext(expanded, rawTemplate, req.spec)].filter(Boolean).join('\n\n');
|
|
@@ -1096,7 +1122,7 @@ class LoopRunManager {
|
|
|
1096
1122
|
const effectiveTimeoutMs = Number.isFinite(remainingMs)
|
|
1097
1123
|
? Math.max(1, Math.min(aiStepTimeoutMs === 0 ? Infinity : (aiStepTimeoutMs ?? 15 * 60_000), remainingMs))
|
|
1098
1124
|
: aiStepTimeoutMs;
|
|
1099
|
-
const coreRun = { runId, spec: req.spec, goal: req.spec ? undefined : JSON.stringify({ loop: req.loopName, graph: req.graph }), repositoryId: req.repositoryId, verificationStep: node.data?.requireVerificationPass === true || /\{\{\s*cmd:(?:verify|revision-verify|opsx:verify)\s*\}\}/.test(rawTemplate) };
|
|
1125
|
+
const coreRun = { runId, implementation: requiresCoreCompletion, spec: req.spec, goal: req.spec ? undefined : JSON.stringify({ loop: req.loopName, graph: req.graph }), repositoryId: req.repositoryId, verificationStep: node.data?.requireVerificationPass === true || /\{\{\s*cmd:(?:verify|revision-verify|opsx:verify)\s*\}\}/.test(rawTemplate) };
|
|
1100
1126
|
const interactivePlan = this.executors.planInteractiveAiStep?.({
|
|
1101
1127
|
coreRun,
|
|
1102
1128
|
provider: nodeProvider,
|
|
@@ -1248,9 +1274,7 @@ class LoopRunManager {
|
|
|
1248
1274
|
? `blocked — ${blockedReason}`
|
|
1249
1275
|
: verificationFailed
|
|
1250
1276
|
? 'verification did not finish with VERIFICATION: PASS'
|
|
1251
|
-
: undefined);
|
|
1252
|
-
if (verificationFailed && !blockedReason)
|
|
1253
|
-
logLine(`✖ ${stepErrorText}`, 'stderr');
|
|
1277
|
+
: res.failed ? 'provider invocation failed without a reported reason' : undefined);
|
|
1254
1278
|
// Make the failure reason land visibly INSIDE the step's log
|
|
1255
1279
|
// segment (the interactive session already surfaced its own note at
|
|
1256
1280
|
// settle; the Template/Command flat-log lines are gone, so without
|
|
@@ -1258,6 +1282,14 @@ class LoopRunManager {
|
|
|
1258
1282
|
if (oneShotZeroWork) {
|
|
1259
1283
|
logLine(`✖ Zero work performed — the command never ran${res.text.trim() ? `: ${res.text.trim()}` : ''}`, 'stderr');
|
|
1260
1284
|
}
|
|
1285
|
+
else if (stepFailed && stepErrorText) {
|
|
1286
|
+
// Executors can return a structured failure without streaming any
|
|
1287
|
+
// text (configuration rejection, missing CLI, provider startup).
|
|
1288
|
+
// Persist its reason before the step closes, including early stops.
|
|
1289
|
+
logLine(`✖ ${stepErrorText}`, 'stderr');
|
|
1290
|
+
}
|
|
1291
|
+
record(`loop:${runId}`, { ...res, failed: stepFailed }, aiStepStart, aiRecoveryKey);
|
|
1292
|
+
this._activeStepRecovery.delete(runId);
|
|
1261
1293
|
// Step tail marker — after the step's last streamed output (both the
|
|
1262
1294
|
// one-shot and interactive paths have fully persisted their frames by
|
|
1263
1295
|
// here: the session resolves inside onSettle, past its final writes).
|
|
@@ -1281,8 +1313,6 @@ class LoopRunManager {
|
|
|
1281
1313
|
else if (stepFailed)
|
|
1282
1314
|
aiSessionId = undefined;
|
|
1283
1315
|
history.push(`AI Step${stepFailed ? ` FAILED (${stepErrorText ?? 'provider invocation failed'})` : ''}: ${truncate(res.text)}`);
|
|
1284
|
-
record(`loop:${runId}`, { ...res, failed: stepFailed }, aiStepStart, aiRecoveryKey);
|
|
1285
|
-
this._activeStepRecovery.delete(runId);
|
|
1286
1316
|
if (blockedReason) {
|
|
1287
1317
|
const decision = await awaitHumanDecision(blockedReason);
|
|
1288
1318
|
if (decision.action === 'stop') {
|
|
@@ -1579,6 +1609,7 @@ class LoopRunManager {
|
|
|
1579
1609
|
// The ONLY way a persisted stream ends with an open step is a mid-flight
|
|
1580
1610
|
// dispose (shutdown/project removal), where this code never runs.
|
|
1581
1611
|
emitStepEnd({ status: 'failed' });
|
|
1612
|
+
let runtimeUsage = { present: false, costUnknown: false, tokensInUnknown: false, tokensOutUnknown: false };
|
|
1582
1613
|
// A traversal exception can bypass record(). Reconcile the staged step
|
|
1583
1614
|
// BEFORE writing aggregate job totals, while its jobs baseline is still
|
|
1584
1615
|
// valid. If reconciliation itself fails, finishLoopRunAndJob detects the
|
|
@@ -1586,6 +1617,8 @@ class LoopRunManager {
|
|
|
1586
1617
|
try {
|
|
1587
1618
|
const recoveredSteps = recoverOrphanLoopStepAccounting(this.db, new Date(this.now()).toISOString(), runId);
|
|
1588
1619
|
this._activeStepRecovery.delete(runId);
|
|
1620
|
+
runtimeUsage = programmaticUsageAvailability(this.db, runId);
|
|
1621
|
+
usageTelemetryAvailable ||= runtimeUsage.present;
|
|
1589
1622
|
const aggregate = this.db.prepare(`
|
|
1590
1623
|
SELECT COALESCE(SUM(total_cost_usd), 0) AS cost,
|
|
1591
1624
|
COALESCE(SUM(tokens_in), 0) AS tokens_in,
|
|
@@ -1617,11 +1650,11 @@ class LoopRunManager {
|
|
|
1617
1650
|
}
|
|
1618
1651
|
if (usageTelemetryAvailable) {
|
|
1619
1652
|
finalJobUsage = {
|
|
1620
|
-
tokensIn: aggregate.tokens_in,
|
|
1621
|
-
tokensOut: aggregate.tokens_out,
|
|
1622
|
-
tokensCacheRead: aggregate.cache_read,
|
|
1623
|
-
tokensCacheCreate: aggregate.cache_create,
|
|
1624
|
-
numTurns: aggregate.turns,
|
|
1653
|
+
tokensIn: runtimeUsage.tokensInUnknown ? null : aggregate.tokens_in,
|
|
1654
|
+
tokensOut: runtimeUsage.tokensOutUnknown ? null : aggregate.tokens_out,
|
|
1655
|
+
tokensCacheRead: runtimeUsage.present ? null : aggregate.cache_read,
|
|
1656
|
+
tokensCacheCreate: runtimeUsage.present ? null : aggregate.cache_create,
|
|
1657
|
+
numTurns: runtimeUsage.present ? null : aggregate.turns,
|
|
1625
1658
|
};
|
|
1626
1659
|
}
|
|
1627
1660
|
}
|
|
@@ -1638,8 +1671,9 @@ class LoopRunManager {
|
|
|
1638
1671
|
const executionOutcome = outcome;
|
|
1639
1672
|
if (outcome === 'success' && coreCompletion && (coreCompletion.completion.implementation !== 'complete' || !['verified', 'with-exceptions'].includes(coreCompletion.completion.validation)))
|
|
1640
1673
|
outcome = 'blocked';
|
|
1674
|
+
const costAvailable = usageTelemetryAvailable && !runtimeUsage.costUnknown;
|
|
1641
1675
|
console.log(`[loop] settle run=${runId} outcome=${outcome} iterations=${iteration} ` +
|
|
1642
|
-
(
|
|
1676
|
+
(costAvailable ? `cost=$${totalCost.toFixed(4)}` : 'cost=unavailable'));
|
|
1643
1677
|
emitRunEvent('loop_completion', {
|
|
1644
1678
|
version: 1, execution: executionOutcome, steps: stepNum, deciderEvaluations: iteration,
|
|
1645
1679
|
turns: finalJobUsage.numTurns, costUsd: usageTelemetryAvailable ? totalCost : null,
|
|
@@ -1658,7 +1692,7 @@ class LoopRunManager {
|
|
|
1658
1692
|
// is a lower bound, not exact. Providers without usage telemetry get an
|
|
1659
1693
|
// explicit unavailable marker, never a fabricated "$0.0000".
|
|
1660
1694
|
logLine(`\n■ Loop execution finished: ${outcome} — ${stepNum} step${stepNum === 1 ? '' : 's'}, ${iteration} decider evaluation${iteration === 1 ? '' : 's'}, ${finalJobUsage.numTurns ?? 'unknown'} agent turns, ` +
|
|
1661
|
-
(
|
|
1695
|
+
(costAvailable
|
|
1662
1696
|
? `${costUncertain ? '≥ ' : ''}$${totalCost.toFixed(4)}`
|
|
1663
1697
|
: 'usage/cost unavailable'));
|
|
1664
1698
|
if (coreCompletion)
|
|
@@ -1678,7 +1712,7 @@ class LoopRunManager {
|
|
|
1678
1712
|
job: {
|
|
1679
1713
|
exitCode: outcome === 'success' ? 0 : 1,
|
|
1680
1714
|
status: jobStatus,
|
|
1681
|
-
totalCostUsd:
|
|
1715
|
+
totalCostUsd: costAvailable ? totalCost : null,
|
|
1682
1716
|
tokensIn: finalJobUsage.tokensIn,
|
|
1683
1717
|
tokensOut: finalJobUsage.tokensOut,
|
|
1684
1718
|
tokensCacheRead: finalJobUsage.tokensCacheRead,
|
|
@@ -1699,7 +1733,7 @@ class LoopRunManager {
|
|
|
1699
1733
|
tokens_out: finalJobUsage.tokensOut,
|
|
1700
1734
|
tokens_cache_read: finalJobUsage.tokensCacheRead,
|
|
1701
1735
|
tokens_cache_create: finalJobUsage.tokensCacheCreate,
|
|
1702
|
-
total_cost_usd:
|
|
1736
|
+
total_cost_usd: costAvailable ? totalCost : null,
|
|
1703
1737
|
num_turns: finalJobUsage.numTurns,
|
|
1704
1738
|
},
|
|
1705
1739
|
timestamp: new Date(this.now()).toISOString(),
|
|
@@ -1716,7 +1750,7 @@ class LoopRunManager {
|
|
|
1716
1750
|
runId,
|
|
1717
1751
|
outcome,
|
|
1718
1752
|
iterations: iteration,
|
|
1719
|
-
totalCostUsd:
|
|
1753
|
+
totalCostUsd: costAvailable ? totalCost : null,
|
|
1720
1754
|
...(outcome === 'stalled' && stallReason ? { stallReason } : {}),
|
|
1721
1755
|
...(providerLimitHit ? { providerLimit: providerLimitHit } : {}),
|
|
1722
1756
|
};
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.ProjectRegistry = void 0;
|
|
7
7
|
exports.emitRecoveredPrDelivery = emitRecoveredPrDelivery;
|
|
8
8
|
exports.reprojectActivePrDeliveries = reprojectActivePrDeliveries;
|
|
9
|
+
const agent_runtime_controls_router_1 = require("./agent-runtime-controls-router");
|
|
9
10
|
const path_1 = __importDefault(require("path"));
|
|
10
11
|
const fs_1 = __importDefault(require("fs"));
|
|
11
12
|
const os_1 = __importDefault(require("os"));
|
|
@@ -305,6 +306,10 @@ class ProjectRegistry {
|
|
|
305
306
|
// Loop engine teardown: dispose any resident interactive step sessions
|
|
306
307
|
// (SIGTERM, no settle) + kill in-flight one-shot loop children — BEFORE
|
|
307
308
|
// db.close() so a late close handler can't write to the closed handle.
|
|
309
|
+
try {
|
|
310
|
+
(0, agent_runtime_controls_router_1.shutdownAgentRuntimeControls)(ctx);
|
|
311
|
+
}
|
|
312
|
+
catch { /* ignore */ }
|
|
308
313
|
try {
|
|
309
314
|
ctx.loopRunManager.shutdown();
|
|
310
315
|
}
|
|
@@ -540,6 +545,10 @@ class ProjectRegistry {
|
|
|
540
545
|
catch { /* ignore */ }
|
|
541
546
|
// Loop engine: dispose resident interactive step sessions + kill in-flight
|
|
542
547
|
// one-shot loop children so a quit mid-run doesn't orphan claude processes.
|
|
548
|
+
try {
|
|
549
|
+
(0, agent_runtime_controls_router_1.shutdownAgentRuntimeControls)(ctx);
|
|
550
|
+
}
|
|
551
|
+
catch { /* ignore */ }
|
|
543
552
|
try {
|
|
544
553
|
ctx.loopRunManager.shutdown();
|
|
545
554
|
}
|
|
@@ -19,7 +19,11 @@ const terminal_settings_1 = require("./terminal-settings");
|
|
|
19
19
|
const terminal_marks_store_1 = require("./terminal-marks-store");
|
|
20
20
|
const project_router_helpers_1 = require("./project-router-helpers");
|
|
21
21
|
const install_config_path_1 = require("./install-config-path");
|
|
22
|
+
const agent_runtime_settings_router_1 = require("./agent-runtime-settings-router");
|
|
23
|
+
const agent_runtime_controls_router_1 = require("./agent-runtime-controls-router");
|
|
22
24
|
function registerSettingsRoutes(deps) {
|
|
25
|
+
(0, agent_runtime_settings_router_1.registerAgentRuntimeSettingsRoutes)(deps);
|
|
26
|
+
(0, agent_runtime_controls_router_1.registerAgentRuntimeControlRoutes)(deps);
|
|
23
27
|
const { router, registry, ctx, ticketPath } = deps;
|
|
24
28
|
// ─── Project settings (pipeline telemetry) ───────────────────────────────────
|
|
25
29
|
router.get('/:projectId/settings', (req, res) => {
|
|
@@ -67,6 +67,7 @@ const artifact_registry_1 = require("./artifact-registry");
|
|
|
67
67
|
const ids_1 = require("./ids");
|
|
68
68
|
const loop_constants_1 = require("./loop-constants");
|
|
69
69
|
const worktree_manager_1 = require("./worktree-manager");
|
|
70
|
+
const agent_runtime_paths_1 = require("./agent-runtime-paths");
|
|
70
71
|
const rail_worktrees_store_1 = require("./rail-worktrees-store");
|
|
71
72
|
const pr_naming_1 = require("./pr-naming");
|
|
72
73
|
const jira_db_1 = require("./jira/jira-db");
|
|
@@ -1015,6 +1016,19 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
1015
1016
|
callbackFailure = errorDetail(err);
|
|
1016
1017
|
console.error(`[rail-isolated] terminal callback failed for ${a.runId}: ${callbackFailure}`);
|
|
1017
1018
|
}
|
|
1019
|
+
// A paused/interrupted programmatic workflow owns unfinished changes and
|
|
1020
|
+
// verification evidence in this exact mount. Keep them available for
|
|
1021
|
+
// explicit Core recovery, including a currently clean worktree.
|
|
1022
|
+
if (implementationOutcome === 'failed' && (0, agent_runtime_paths_1.hasAgentRuntimeRequest)(ctx.project, a.runId)) {
|
|
1023
|
+
markWorktree(a, 'needs-review');
|
|
1024
|
+
return {
|
|
1025
|
+
run: a, implementationOutcome, deliveryOutcome: 'blocked',
|
|
1026
|
+
initialSha: a.initialSha, finalSha: await readHeadSha(git, a.handle.worktreePath),
|
|
1027
|
+
failureCode: 'settlement_interrupted',
|
|
1028
|
+
failureDetail: 'Programmatic workflow needs attention. Resume it from Agent Runtime settings in its original worktree.',
|
|
1029
|
+
safeToRelease: false,
|
|
1030
|
+
};
|
|
1031
|
+
}
|
|
1018
1032
|
// The engine may have edited a copied overlay file. Re-authenticate only
|
|
1019
1033
|
// automatic-cleanup authority. Allocation-time paths remain conservative
|
|
1020
1034
|
// NEVER-COMMIT exclusions, while a modified copy is preserved in the
|
|
@@ -1828,6 +1842,10 @@ async function reconcileRailWorktrees(db, repoDir, io = {}) {
|
|
|
1828
1842
|
const run = row.run_id
|
|
1829
1843
|
? db.prepare('SELECT status, final_outcome FROM loop_runs WHERE id = ?').get(row.run_id)
|
|
1830
1844
|
: undefined;
|
|
1845
|
+
if (row.run_id && run?.final_outcome !== 'success' && (0, agent_runtime_paths_1.hasAgentRuntimeRequest)({ path: io.primaryRepoDir ?? repoDir }, row.run_id)) {
|
|
1846
|
+
(0, rail_worktrees_store_1.updateRailWorktreeState)(db, row.id, 'needs-review');
|
|
1847
|
+
continue;
|
|
1848
|
+
}
|
|
1831
1849
|
const inspection = await inspectRecoveryWorktree(git, repoDir, row);
|
|
1832
1850
|
if (run?.status === 'completed' && run.final_outcome === 'success') {
|
|
1833
1851
|
if (inspection.safe && inspection.sha) {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://specrails.dev/schemas/agent-runtime.schema.json",
|
|
4
|
+
"title": "Specrails programmatic agent runtime",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["schemaVersion", "enabled", "providers", "agents", "verification"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schemaVersion": { "const": 1 },
|
|
10
|
+
"enabled": { "type": "boolean" },
|
|
11
|
+
"providers": { "type": "array", "items": { "oneOf": [
|
|
12
|
+
{ "type": "object", "additionalProperties": false, "required": ["id", "kind", "cli"], "properties": {
|
|
13
|
+
"id": { "$ref": "#/definitions/id" }, "kind": { "const": "cli" }, "cli": { "enum": ["claude", "codex", "gemini", "kimi"] }
|
|
14
|
+
} },
|
|
15
|
+
{ "type": "object", "additionalProperties": false, "required": ["id", "kind", "baseUrl"], "properties": {
|
|
16
|
+
"id": { "$ref": "#/definitions/id" }, "kind": { "const": "openai-compatible" },
|
|
17
|
+
"baseUrl": { "type": "string", "pattern": "^https?://[^/?#@]+(?:/[^?#]*)?$" },
|
|
18
|
+
"apiKeyEnv": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }
|
|
19
|
+
} }
|
|
20
|
+
] } },
|
|
21
|
+
"agents": { "type": "object", "additionalProperties": false, "required": ["architect", "developer", "reviewer"], "properties": {
|
|
22
|
+
"architect": { "$ref": "#/definitions/agent" }, "developer": { "$ref": "#/definitions/agent" }, "reviewer": { "$ref": "#/definitions/agent" }
|
|
23
|
+
} },
|
|
24
|
+
"limits": { "type": "object", "additionalProperties": false, "properties": {
|
|
25
|
+
"maxAttempts": { "$ref": "#/definitions/positiveInteger" }, "maxTokens": { "$ref": "#/definitions/positiveInteger" },
|
|
26
|
+
"maxCostUsd": { "type": "number", "exclusiveMinimum": 0 }, "timeoutMs": { "$ref": "#/definitions/positiveInteger" }
|
|
27
|
+
} },
|
|
28
|
+
"verification": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["repositoryId", "command", "args"], "properties": {
|
|
29
|
+
"repositoryId": { "$ref": "#/definitions/id" }, "command": { "type": "string", "minLength": 1 },
|
|
30
|
+
"args": { "type": "array", "items": { "type": "string" } }, "cwd": { "type": "string", "minLength": 1 },
|
|
31
|
+
"env": { "type": "object", "propertyNames": { "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" }, "additionalProperties": { "type": "string" } },
|
|
32
|
+
"timeoutMs": { "$ref": "#/definitions/positiveInteger" }
|
|
33
|
+
} } },
|
|
34
|
+
"approvalBeforeArchive": { "type": "boolean" },
|
|
35
|
+
"review": { "type": "object", "additionalProperties": false, "description": "Review gate thresholds; unset fields keep Core's defaults (score 70, security 75, other aspects 60).", "properties": {
|
|
36
|
+
"minScore": { "$ref": "#/definitions/score" },
|
|
37
|
+
"aspects": { "type": "object", "additionalProperties": false, "properties": {
|
|
38
|
+
"type_correctness": { "$ref": "#/definitions/score" }, "pattern_adherence": { "$ref": "#/definitions/score" }, "test_coverage": { "$ref": "#/definitions/score" },
|
|
39
|
+
"security": { "$ref": "#/definitions/score" }, "architectural_alignment": { "$ref": "#/definitions/score" }
|
|
40
|
+
} }
|
|
41
|
+
} },
|
|
42
|
+
"architect": { "type": "object", "additionalProperties": false, "properties": {
|
|
43
|
+
"onLowConfidence": { "enum": ["ask", "proceed"], "description": "After one autonomous investigation pass, a still-low design either pauses with its question (ask, default) or proceeds on stated assumptions (proceed)." }
|
|
44
|
+
} }
|
|
45
|
+
},
|
|
46
|
+
"definitions": {
|
|
47
|
+
"id": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$" },
|
|
48
|
+
"positiveInteger": { "type": "integer", "minimum": 1 },
|
|
49
|
+
"score": { "type": "number", "minimum": 0, "maximum": 100 },
|
|
50
|
+
"agent": { "type": "object", "additionalProperties": false, "required": ["provider"], "properties": {
|
|
51
|
+
"provider": { "$ref": "#/definitions/id" }, "model": { "type": "string", "minLength": 1, "maxLength": 256, "pattern": "^[^-\\r\\n\\u0000][^\\r\\n\\u0000]*$" },
|
|
52
|
+
"maxTurns": { "$ref": "#/definitions/positiveInteger" }
|
|
53
|
+
} }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{n as t,t as n}from"./jsx-runtime-zu2_FqZY.js";import{d as r,f as i,m as a,u as o}from"./TicketDetailModalContext-BbRA6cb7.js";import{n as s}from"./createLucideIcon-Bjbbp_KS.js";import{s as c}from"./useDesktop-gVGoWWiY.js";import{$ as l,Bt as u,Ht as d,P as f,W as p,X as m,v as h}from"./index-UnaJTMIy.js";var g=e(t(),1),_=n();function v({projectId:e,conversationId:t}){let{t:n}=s(`agent`),{error:v}=d(),y=l(t??`__new-mission__`),{closeBrowser:b,queueCapture:x,browserOwnerId:S,browserUrl:C,setBrowserUrl:w}=p(),{materializeDraftConversation:T}=f(),[E,D]=(0,g.useState)(!1),[O,k]=(0,g.useState)(!1),[A,j]=(0,g.useState)(`probing`);(0,g.useEffect)(()=>{if(t&&(E||O||A===`screencast`))return m(t)},[t,E,O,A]);let M=(0,g.useMemo)(()=>{if(C)return C;try{return i(localStorage.getItem(`specrails-desktop:agent-browser-url:${e}`)??``)??`about:blank`}catch{return`about:blank`}},[e]);(0,g.useEffect)(()=>{let e=!0;return r().then(t=>{e&&j(t?`native`:`screencast`)}),()=>{e=!1}},[]);let N=(0,g.useMemo)(()=>`agent-${t??`home`}-${Math.round(performance.now())}`,[t]),P=async e=>{k(!0);try{let r=await u(t??(await T()).id,a(e.screenshotDataUrl,`capture-${Date.now()}.png`));x(r),c.success(n(`workspace.browserCaptured`)),b()}catch(e){throw c.error(n(`workspace.uploadFailed`),{description:e instanceof Error?e.message:void 0}),e}finally{k(!1)}};return A===`probing`?null:A===`native`?(0,_.jsx)(o,{ownerId:S??void 0,leaseRevision:y,onBusyChange:D,transferError:v,url:M,onClose:b,onFallback:()=>j(`screencast`),onUrlChange:t=>{if(w(t),i(t)&&t!==`about:blank`)try{localStorage.setItem(`specrails-desktop:agent-browser-url:${e}`,t)}catch{}},confirmLabel:n(`workspace.browserConfirm`),selectLabel:n(`workspace.browserSelectStart`),onCaptured:P}):(0,_.jsx)(h,{open:!0,onClose:b,projectId:e,pendingSpecId:N,confirmLabel:n(`workspace.browserConfirm`),selectLabel:n(`workspace.browserSelectStart`),onCaptured:P})}export{v as AgentBrowserCapture};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/AnalyticsPage-DTsg-N5z.js","assets/rolldown-runtime-CNC7AqOf.js","assets/jsx-runtime-zu2_FqZY.js","assets/chunk-KS7C4IRE-DEKu087k.js","assets/preload-helper-Czpn1I53.js","assets/useSharedWebSocket-DbGL_YOt.js","assets/activity-DiyjsgQV.js","assets/addspec-D2YIQ0GU.js","assets/agent-Bh9K7iEt.js","assets/agents-ms7TwG16.js","assets/agentstudio-CN2pokQu.js","assets/aiedit-iIjz2_Qk.js","assets/analytics-BMzCvrCU.js","assets/attachments-B53PG733.js","assets/browser-CG0PE1j_.js","assets/builder-BTiGnPT0.js","assets/chat-BGD7MXAy.js","assets/code-DaZ-ZwCT.js","assets/commands-BAWSYHjQ.js","assets/common-BrlwEnL7.js","assets/dashboard-BfBir_6o.js","assets/explore-DgBACn39.js","assets/integrations-mB-7zoyT.js","assets/jira-CKJg3HZd.js","assets/jobs-DMPU64ms.js","assets/loops-B7YpGizO.js","assets/mcp-CUAN6ORK.js","assets/narration-B-ynWTpn.js","assets/nav-Ch-zHBG5.js","assets/packet-Cx-zRuWn.js","assets/settings-CCNZN5Q-.js","assets/setup-Ba11l2JA.js","assets/specs-DII0C8gw.js","assets/terminal-BAzpHtpY.js","assets/tickets-W6pBmbrX.js","assets/createLucideIcon-Bjbbp_KS.js","assets/Trans-mjFZpHw1.js","assets/useDesktop-gVGoWWiY.js","assets/react-dom-DiWzBDP9.js","assets/spending-DXOcv1tn.js","assets/clsx-CjueKrWZ.js","assets/formatDistanceToNow-BIL-HxGy.js","assets/getTimezoneOffsetInMilliseconds-Cs9z2sdO.js","assets/provider-capabilities-B-wOHfLP.js","assets/index-UnaJTMIy.js","assets/TicketDetailModalContext-BbRA6cb7.js","assets/save-B6wGWwBR.js","assets/MinimizedChatsContext-C843Y13h.js","assets/sparkles-DrY8hb0X.js","assets/x-CBMI9ejn.js","assets/file-text-BcLCfcWZ.js","assets/circle-x-CMYsN4ZH.js","assets/download-CFHyyHcw.js","assets/git-branch-BRM0F5GN.js","assets/loader-circle-DcygOQpC.js","assets/pencil-C9RkrIPZ.js","assets/square-Ci-PFcFe.js","assets/plus-CsnjfkmX.js","assets/search-Cq_gE3Ik.js","assets/trash-2-BOU3WdZZ.js","assets/triangle-alert-H9T4jAmh.js","assets/jira-api-B2BBZQTx.js","assets/zap-CHo3aCD1.js","assets/dialog-xXB2q5HJ.js","assets/utils-BC4DHlz2.js","assets/lib-CGdyxIWg.js","assets/button-Ccc9Dc-D.js","assets/RepositoryScopeSelector-CZ_U_R3U.js","assets/project-repositories-xSqimlaj.js","assets/core-B3mKBIh5.js","assets/RepositoryDeliveries-bgIHE8ep.js","assets/event-Bt7f3wXe.js","assets/index-Bfj8HvX1.css","assets/ExportDropdown-DczgU4at.js","assets/BarChart-nBOMNfiy.js","assets/value-s-gzBeyF.js"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{n as t,t as n}from"./jsx-runtime-zu2_FqZY.js";import{t as r}from"./preload-helper-Czpn1I53.js";import{n as i}from"./createLucideIcon-Bjbbp_KS.js";import{t as a}from"./loader-circle-DcygOQpC.js";import{t as o}from"./x-CBMI9ejn.js";import{t as s}from"./utils-BC4DHlz2.js";import{W as c,_t as l,gt as u}from"./index-UnaJTMIy.js";var d=e(t(),1),f=n(),p=(0,d.lazy)(()=>r(()=>import(`./AnalyticsPage-DTsg-N5z.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75]))),m=420,h=560;function g(){let{t:e}=i(`agent`),{closeAnalyticsPane:t}=c(),[n,r]=(0,d.useState)(h),[g,_]=(0,d.useState)(!1),v=(0,d.useCallback)(e=>{let t=e.clientX,i=n,a=window.innerWidth-m;try{e.currentTarget.setPointerCapture(e.pointerId)}catch{}let o=e=>{let n=Math.min(Math.max(i+(t-e.clientX),m),a);r(n)},s=()=>{window.removeEventListener(`pointermove`,o),window.removeEventListener(`pointerup`,s),window.removeEventListener(`pointercancel`,s)};window.addEventListener(`pointermove`,o),window.addEventListener(`pointerup`,s),window.addEventListener(`pointercancel`,s)},[n]);return(0,f.jsxs)(`div`,{className:s(`flex h-full flex-col overflow-hidden border-l border-border bg-background`,g&&`absolute inset-0 z-30 border-l-0`),style:g?void 0:{width:n,flexShrink:0},"data-testid":`agent-analytics-pane`,children:[(0,f.jsx)(`div`,{className:`relative flex items-center`,children:!g&&(0,f.jsx)(`div`,{role:`separator`,"aria-orientation":`vertical`,onPointerDown:v,className:`absolute left-0 top-0 h-full w-1.5 -translate-x-full cursor-col-resize select-none touch-none hover:bg-accent-primary/20`,title:e(`workspace.resizeAnalytics`)})}),(0,f.jsxs)(`div`,{className:`flex items-center gap-2 border-b border-border/60 bg-surface/40 px-3 py-1.5`,children:[(0,f.jsx)(`span`,{className:`text-xs font-medium text-foreground/70`,children:e(`workspace.analytics`)}),(0,f.jsxs)(`div`,{className:`ml-auto flex items-center gap-1`,children:[(0,f.jsx)(`button`,{type:`button`,onClick:()=>_(e=>!e),"aria-label":e(g?`restore`:`maximize`),title:e(g?`restore`:`maximize`),className:`rounded-md p-1 text-foreground/60 hover:bg-surface hover:text-foreground`,children:g?(0,f.jsx)(u,{className:`h-4 w-4`}):(0,f.jsx)(l,{className:`h-4 w-4`})}),(0,f.jsx)(`button`,{type:`button`,onClick:t,"aria-label":e(`workspace.closeAnalytics`),title:e(`workspace.closeAnalytics`),className:`rounded-md p-1 text-foreground/60 hover:bg-surface hover:text-foreground`,children:(0,f.jsx)(o,{className:`h-4 w-4`})})]})]}),(0,f.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto`,children:(0,f.jsx)(d.Suspense,{fallback:(0,f.jsx)(`div`,{className:`flex h-24 items-center justify-center text-muted-foreground`,children:(0,f.jsx)(a,{className:`h-4 w-4 animate-spin`})}),children:(0,f.jsx)(p,{})})})]})}export{g as AgentModeAnalyticsPane};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/CodePage-DwgbeqQ_.js","assets/rolldown-runtime-CNC7AqOf.js","assets/jsx-runtime-zu2_FqZY.js","assets/react-dom-DiWzBDP9.js","assets/preload-helper-Czpn1I53.js","assets/chunk-KS7C4IRE-DEKu087k.js","assets/TicketDetailModalContext-BbRA6cb7.js","assets/useSharedWebSocket-DbGL_YOt.js","assets/activity-DiyjsgQV.js","assets/addspec-D2YIQ0GU.js","assets/agent-Bh9K7iEt.js","assets/agents-ms7TwG16.js","assets/agentstudio-CN2pokQu.js","assets/aiedit-iIjz2_Qk.js","assets/analytics-BMzCvrCU.js","assets/attachments-B53PG733.js","assets/browser-CG0PE1j_.js","assets/builder-BTiGnPT0.js","assets/chat-BGD7MXAy.js","assets/code-DaZ-ZwCT.js","assets/commands-BAWSYHjQ.js","assets/common-BrlwEnL7.js","assets/dashboard-BfBir_6o.js","assets/explore-DgBACn39.js","assets/integrations-mB-7zoyT.js","assets/jira-CKJg3HZd.js","assets/jobs-DMPU64ms.js","assets/loops-B7YpGizO.js","assets/mcp-CUAN6ORK.js","assets/narration-B-ynWTpn.js","assets/nav-Ch-zHBG5.js","assets/packet-Cx-zRuWn.js","assets/settings-CCNZN5Q-.js","assets/setup-Ba11l2JA.js","assets/specs-DII0C8gw.js","assets/terminal-BAzpHtpY.js","assets/tickets-W6pBmbrX.js","assets/createLucideIcon-Bjbbp_KS.js","assets/Trans-mjFZpHw1.js","assets/useDesktop-gVGoWWiY.js","assets/save-B6wGWwBR.js","assets/spending-DXOcv1tn.js","assets/MinimizedChatsContext-C843Y13h.js","assets/sparkles-DrY8hb0X.js","assets/x-CBMI9ejn.js","assets/file-text-BcLCfcWZ.js","assets/circle-x-CMYsN4ZH.js","assets/download-CFHyyHcw.js","assets/git-branch-BRM0F5GN.js","assets/loader-circle-DcygOQpC.js","assets/pencil-C9RkrIPZ.js","assets/square-Ci-PFcFe.js","assets/plus-CsnjfkmX.js","assets/search-Cq_gE3Ik.js","assets/trash-2-BOU3WdZZ.js","assets/triangle-alert-H9T4jAmh.js","assets/jira-api-B2BBZQTx.js","assets/zap-CHo3aCD1.js","assets/dialog-xXB2q5HJ.js","assets/utils-BC4DHlz2.js","assets/clsx-CjueKrWZ.js","assets/lib-CGdyxIWg.js","assets/formatDistanceToNow-BIL-HxGy.js","assets/getTimezoneOffsetInMilliseconds-Cs9z2sdO.js","assets/button-Ccc9Dc-D.js","assets/RepositoryScopeSelector-CZ_U_R3U.js","assets/project-repositories-xSqimlaj.js","assets/provider-capabilities-B-wOHfLP.js","assets/index-UnaJTMIy.js","assets/core-B3mKBIh5.js","assets/RepositoryDeliveries-bgIHE8ep.js","assets/event-Bt7f3wXe.js","assets/index-Bfj8HvX1.css"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{n as t,t as n}from"./jsx-runtime-zu2_FqZY.js";import{t as r}from"./preload-helper-Czpn1I53.js";import{n as i}from"./createLucideIcon-Bjbbp_KS.js";import{t as a}from"./x-CBMI9ejn.js";import{Q as o,W as s,Z as c,_t as l,gt as u}from"./index-UnaJTMIy.js";var d=e(t(),1),f=n(),p=(0,d.lazy)(()=>r(()=>import(`./CodePage-DwgbeqQ_.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72]))),m=420,h=560;function g({projectId:e,conversationId:t}){let{t:n}=i(`agent`),{closeCodePane:r}=s(),[g,_]=(0,d.useState)(h),[v,y]=(0,d.useState)(()=>window.innerWidth),[b,x]=(0,d.useState)(!1),S=(0,d.useRef)(null),C=(0,d.useRef)(null),w=Math.max(0,v-Math.min(m,v/2)),T=Math.min(m,w),E=Math.min(w,Math.max(T,g)),D=(0,d.useCallback)(e=>Math.min(w,Math.max(T,e)),[w,T]),O=`${e}:${t}`,k=(0,d.useCallback)(n=>{o(e,t,{path:n})},[e,t]);(0,d.useLayoutEffect)(()=>{let e=S.current,t=e?.parentElement;if(!e||!t)return;let n=()=>{let n=t.getBoundingClientRect().width||t.clientWidth||window.innerWidth,r=0;for(let n of t.children){if(n===e||!(n instanceof HTMLElement))continue;let t=getComputedStyle(n);t.display===`none`||t.position===`absolute`||t.position===`fixed`||Number(t.flexGrow)>0||(r+=n.getBoundingClientRect().width)}y(Math.max(0,n-r))},r=new ResizeObserver(n),i=()=>{r.disconnect(),r.observe(t);for(let n of t.children)n!==e&&r.observe(n);n()},a=new MutationObserver(i);return a.observe(t,{childList:!0}),i(),window.addEventListener(`resize`,n),()=>{r.disconnect(),a.disconnect(),window.removeEventListener(`resize`,n)}},[O]),(0,d.useEffect)(()=>()=>{C.current?.()},[O,b,w]);let A=(0,d.useCallback)(e=>{if(e.button!==0)return;e.preventDefault(),C.current?.();let t=e.clientX,n=E,r=e.pointerId,i=e.currentTarget;try{i.setPointerCapture(r)}catch{}let a=e=>{e.pointerId===r&&_(D(n+t-e.clientX))},o=()=>{window.removeEventListener(`pointermove`,a),window.removeEventListener(`pointerup`,s),window.removeEventListener(`pointercancel`,s),window.removeEventListener(`blur`,o),i.removeEventListener(`lostpointercapture`,o);try{i.hasPointerCapture(r)&&i.releasePointerCapture(r)}catch{}C.current=null},s=e=>{e.pointerId===r&&o()};C.current=o,window.addEventListener(`pointermove`,a),window.addEventListener(`pointerup`,s),window.addEventListener(`pointercancel`,s),window.addEventListener(`blur`,o),i.addEventListener(`lostpointercapture`,o)},[E,D]);return(0,f.jsxs)(`div`,{ref:S,className:`flex h-full min-w-0 flex-col overflow-hidden border-l border-border bg-background${b?` absolute inset-0 z-30 border-l-0`:` relative`}`,style:b?void 0:{width:E,maxWidth:`100%`,flexShrink:0},"data-testid":`agent-code-pane`,children:[!b&&(0,f.jsx)(`div`,{role:`separator`,"aria-orientation":`vertical`,onPointerDown:A,tabIndex:0,"aria-label":n(`workspace.resizeCode`),"aria-valuemin":Math.round(T),"aria-valuemax":Math.round(w),"aria-valuenow":Math.round(E),onKeyDown:e=>{let t=e.key===`ArrowLeft`?E+32:e.key===`ArrowRight`?E-32:e.key===`Home`?T:e.key===`End`?w:null;t!==null&&(e.preventDefault(),_(D(t)))},className:`absolute inset-y-0 left-0 z-20 w-1.5 cursor-col-resize select-none touch-none hover:bg-accent-primary/20 focus-visible:bg-accent-primary/30 focus-visible:outline-none`,title:n(`workspace.resizeCode`)}),(0,f.jsxs)(`div`,{className:`flex items-center gap-2 border-b border-border/60 bg-surface/40 px-3 py-1.5`,children:[(0,f.jsx)(`span`,{className:`text-xs font-medium text-foreground/70`,children:n(`workspace.files`)}),(0,f.jsxs)(`div`,{className:`ml-auto flex items-center gap-1`,children:[(0,f.jsx)(`button`,{type:`button`,onClick:()=>{C.current?.(),x(e=>!e)},"aria-label":n(b?`restore`:`maximize`),title:n(b?`restore`:`maximize`),className:`rounded-md p-1 text-foreground/60 hover:bg-surface hover:text-foreground`,children:b?(0,f.jsx)(u,{className:`h-4 w-4`}):(0,f.jsx)(l,{className:`h-4 w-4`})}),(0,f.jsx)(`button`,{type:`button`,onClick:()=>{C.current?.(),r()},"aria-label":n(`workspace.closeFiles`),title:n(`workspace.closeFiles`),className:`rounded-md p-1 text-foreground/60 hover:bg-surface hover:text-foreground`,children:(0,f.jsx)(a,{className:`h-4 w-4`})})]})]}),(0,f.jsx)(`div`,{className:`min-h-0 flex-1 overflow-hidden`,children:(0,f.jsx)(d.Suspense,{fallback:(0,f.jsx)(`div`,{className:`flex h-full items-center justify-center text-sm text-muted-foreground`,children:`…`}),children:(0,f.jsx)(p,{embedded:!0,initialRepositoryId:c(e,t).repositoryId,onRepositoryChange:n=>o(e,t,{repositoryId:n}),initialPath:c(e,t).path,onSelectedPathChange:k},O)})})]},O)}export{g as AgentModeCodePane};
|