specrails-desktop 2.44.1 → 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/docs/internals/verification-handoff-regression.md +70 -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/background-windows-bootstrap.js +6 -3
- package/server/dist/core-execution.js +57 -3
- package/server/dist/core-node-runtime.js +12 -0
- package/server/dist/framework-manager.js +23 -4
- package/server/dist/loop-executors.js +47 -1
- package/server/dist/loop-factory.js +1 -1
- package/server/dist/loop-run-manager.js +76 -27
- 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,6 +1084,8 @@ 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 ?? '');
|
|
1087
|
+
const requiresCoreCompletion = node.data?.operation === 'core-implementation' || /\{\{\s*cmd:(?:implement|batch)\s*\}\}/.test(rawTemplate)
|
|
1088
|
+
|| /^\s*(?:\/specrails:|\/skill:specrails-|\$)(?:implement|batch-implement)(?:\s|$)/.test(rawTemplate);
|
|
1061
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);
|
|
1062
1090
|
const base = [(0, multi_repo_execution_store_1.executionManifestPrompt)(req.executionManifest), withReviewContinuationContext(expanded, rawTemplate, req.spec)].filter(Boolean).join('\n\n');
|
|
1063
1091
|
// Inject the cross-iteration history only when there's no live session
|
|
@@ -1094,7 +1122,7 @@ class LoopRunManager {
|
|
|
1094
1122
|
const effectiveTimeoutMs = Number.isFinite(remainingMs)
|
|
1095
1123
|
? Math.max(1, Math.min(aiStepTimeoutMs === 0 ? Infinity : (aiStepTimeoutMs ?? 15 * 60_000), remainingMs))
|
|
1096
1124
|
: aiStepTimeoutMs;
|
|
1097
|
-
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) };
|
|
1098
1126
|
const interactivePlan = this.executors.planInteractiveAiStep?.({
|
|
1099
1127
|
coreRun,
|
|
1100
1128
|
provider: nodeProvider,
|
|
@@ -1220,6 +1248,19 @@ class LoopRunManager {
|
|
|
1220
1248
|
settled = true;
|
|
1221
1249
|
break;
|
|
1222
1250
|
}
|
|
1251
|
+
if (!res.failed && !zeroWork && !this._cancelled.has(runId)
|
|
1252
|
+
&& requiresCoreCompletion
|
|
1253
|
+
&& this.executors.validateCoreCompletion) {
|
|
1254
|
+
const completion = this.executors.validateCoreCompletion({
|
|
1255
|
+
coreRun: { runId, spec: req.spec, goal: req.spec ? undefined : JSON.stringify({ loop: req.loopName, graph: req.graph }), repositoryId: req.repositoryId },
|
|
1256
|
+
provider: nodeProvider, model: nodeModel, effort: nodeEffort, profileName: req.profileName,
|
|
1257
|
+
cwd: req.cwd, repoDir: req.repoDir, executionManifest: req.executionManifest,
|
|
1258
|
+
});
|
|
1259
|
+
if (!completion.valid) {
|
|
1260
|
+
res = { ...res, failed: true, errorText: completion.reason ?? 'Core implementation is incomplete' };
|
|
1261
|
+
logLine(`✖ ${res.errorText}`, 'stderr');
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1223
1264
|
const blockedReason = aiStepBlockedReason(res.text);
|
|
1224
1265
|
const requiresVerification = node.data?.requireVerificationPass === true
|
|
1225
1266
|
|| /\{\{cmd:(?:verify|revision-verify|opsx:verify)\}\}/.test(rawTemplate);
|
|
@@ -1233,9 +1274,7 @@ class LoopRunManager {
|
|
|
1233
1274
|
? `blocked — ${blockedReason}`
|
|
1234
1275
|
: verificationFailed
|
|
1235
1276
|
? 'verification did not finish with VERIFICATION: PASS'
|
|
1236
|
-
: undefined);
|
|
1237
|
-
if (verificationFailed && !blockedReason)
|
|
1238
|
-
logLine(`✖ ${stepErrorText}`, 'stderr');
|
|
1277
|
+
: res.failed ? 'provider invocation failed without a reported reason' : undefined);
|
|
1239
1278
|
// Make the failure reason land visibly INSIDE the step's log
|
|
1240
1279
|
// segment (the interactive session already surfaced its own note at
|
|
1241
1280
|
// settle; the Template/Command flat-log lines are gone, so without
|
|
@@ -1243,6 +1282,14 @@ class LoopRunManager {
|
|
|
1243
1282
|
if (oneShotZeroWork) {
|
|
1244
1283
|
logLine(`✖ Zero work performed — the command never ran${res.text.trim() ? `: ${res.text.trim()}` : ''}`, 'stderr');
|
|
1245
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);
|
|
1246
1293
|
// Step tail marker — after the step's last streamed output (both the
|
|
1247
1294
|
// one-shot and interactive paths have fully persisted their frames by
|
|
1248
1295
|
// here: the session resolves inside onSettle, past its final writes).
|
|
@@ -1266,8 +1313,6 @@ class LoopRunManager {
|
|
|
1266
1313
|
else if (stepFailed)
|
|
1267
1314
|
aiSessionId = undefined;
|
|
1268
1315
|
history.push(`AI Step${stepFailed ? ` FAILED (${stepErrorText ?? 'provider invocation failed'})` : ''}: ${truncate(res.text)}`);
|
|
1269
|
-
record(`loop:${runId}`, { ...res, failed: stepFailed }, aiStepStart, aiRecoveryKey);
|
|
1270
|
-
this._activeStepRecovery.delete(runId);
|
|
1271
1316
|
if (blockedReason) {
|
|
1272
1317
|
const decision = await awaitHumanDecision(blockedReason);
|
|
1273
1318
|
if (decision.action === 'stop') {
|
|
@@ -1564,6 +1609,7 @@ class LoopRunManager {
|
|
|
1564
1609
|
// The ONLY way a persisted stream ends with an open step is a mid-flight
|
|
1565
1610
|
// dispose (shutdown/project removal), where this code never runs.
|
|
1566
1611
|
emitStepEnd({ status: 'failed' });
|
|
1612
|
+
let runtimeUsage = { present: false, costUnknown: false, tokensInUnknown: false, tokensOutUnknown: false };
|
|
1567
1613
|
// A traversal exception can bypass record(). Reconcile the staged step
|
|
1568
1614
|
// BEFORE writing aggregate job totals, while its jobs baseline is still
|
|
1569
1615
|
// valid. If reconciliation itself fails, finishLoopRunAndJob detects the
|
|
@@ -1571,6 +1617,8 @@ class LoopRunManager {
|
|
|
1571
1617
|
try {
|
|
1572
1618
|
const recoveredSteps = recoverOrphanLoopStepAccounting(this.db, new Date(this.now()).toISOString(), runId);
|
|
1573
1619
|
this._activeStepRecovery.delete(runId);
|
|
1620
|
+
runtimeUsage = programmaticUsageAvailability(this.db, runId);
|
|
1621
|
+
usageTelemetryAvailable ||= runtimeUsage.present;
|
|
1574
1622
|
const aggregate = this.db.prepare(`
|
|
1575
1623
|
SELECT COALESCE(SUM(total_cost_usd), 0) AS cost,
|
|
1576
1624
|
COALESCE(SUM(tokens_in), 0) AS tokens_in,
|
|
@@ -1602,19 +1650,17 @@ class LoopRunManager {
|
|
|
1602
1650
|
}
|
|
1603
1651
|
if (usageTelemetryAvailable) {
|
|
1604
1652
|
finalJobUsage = {
|
|
1605
|
-
tokensIn: aggregate.tokens_in,
|
|
1606
|
-
tokensOut: aggregate.tokens_out,
|
|
1607
|
-
tokensCacheRead: aggregate.cache_read,
|
|
1608
|
-
tokensCacheCreate: aggregate.cache_create,
|
|
1609
|
-
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,
|
|
1610
1658
|
};
|
|
1611
1659
|
}
|
|
1612
1660
|
}
|
|
1613
1661
|
catch (err) {
|
|
1614
1662
|
console.error(`[loop] staged accounting reconciliation failed for ${runId}:`, err);
|
|
1615
1663
|
}
|
|
1616
|
-
console.log(`[loop] settle run=${runId} outcome=${outcome} iterations=${iteration} ` +
|
|
1617
|
-
(usageTelemetryAvailable ? `cost=$${totalCost.toFixed(4)}` : 'usage=unavailable'));
|
|
1618
1664
|
// Execution and acceptance are separate facts. Persist the runtime's own
|
|
1619
1665
|
// terminal snapshot alongside counters so history does not depend on prose.
|
|
1620
1666
|
let coreCompletion = null;
|
|
@@ -1625,6 +1671,9 @@ class LoopRunManager {
|
|
|
1625
1671
|
const executionOutcome = outcome;
|
|
1626
1672
|
if (outcome === 'success' && coreCompletion && (coreCompletion.completion.implementation !== 'complete' || !['verified', 'with-exceptions'].includes(coreCompletion.completion.validation)))
|
|
1627
1673
|
outcome = 'blocked';
|
|
1674
|
+
const costAvailable = usageTelemetryAvailable && !runtimeUsage.costUnknown;
|
|
1675
|
+
console.log(`[loop] settle run=${runId} outcome=${outcome} iterations=${iteration} ` +
|
|
1676
|
+
(costAvailable ? `cost=$${totalCost.toFixed(4)}` : 'cost=unavailable'));
|
|
1628
1677
|
emitRunEvent('loop_completion', {
|
|
1629
1678
|
version: 1, execution: executionOutcome, steps: stepNum, deciderEvaluations: iteration,
|
|
1630
1679
|
turns: finalJobUsage.numTurns, costUsd: usageTelemetryAvailable ? totalCost : null,
|
|
@@ -1642,8 +1691,8 @@ class LoopRunManager {
|
|
|
1642
1691
|
// `≥` when any cost-bearing step ended unpriced (timeout/crash) — the figure
|
|
1643
1692
|
// is a lower bound, not exact. Providers without usage telemetry get an
|
|
1644
1693
|
// explicit unavailable marker, never a fabricated "$0.0000".
|
|
1645
|
-
logLine(`\n■ Loop execution finished: ${
|
|
1646
|
-
(
|
|
1694
|
+
logLine(`\n■ Loop execution finished: ${outcome} — ${stepNum} step${stepNum === 1 ? '' : 's'}, ${iteration} decider evaluation${iteration === 1 ? '' : 's'}, ${finalJobUsage.numTurns ?? 'unknown'} agent turns, ` +
|
|
1695
|
+
(costAvailable
|
|
1647
1696
|
? `${costUncertain ? '≥ ' : ''}$${totalCost.toFixed(4)}`
|
|
1648
1697
|
: 'usage/cost unavailable'));
|
|
1649
1698
|
if (coreCompletion)
|
|
@@ -1663,7 +1712,7 @@ class LoopRunManager {
|
|
|
1663
1712
|
job: {
|
|
1664
1713
|
exitCode: outcome === 'success' ? 0 : 1,
|
|
1665
1714
|
status: jobStatus,
|
|
1666
|
-
totalCostUsd:
|
|
1715
|
+
totalCostUsd: costAvailable ? totalCost : null,
|
|
1667
1716
|
tokensIn: finalJobUsage.tokensIn,
|
|
1668
1717
|
tokensOut: finalJobUsage.tokensOut,
|
|
1669
1718
|
tokensCacheRead: finalJobUsage.tokensCacheRead,
|
|
@@ -1684,7 +1733,7 @@ class LoopRunManager {
|
|
|
1684
1733
|
tokens_out: finalJobUsage.tokensOut,
|
|
1685
1734
|
tokens_cache_read: finalJobUsage.tokensCacheRead,
|
|
1686
1735
|
tokens_cache_create: finalJobUsage.tokensCacheCreate,
|
|
1687
|
-
total_cost_usd:
|
|
1736
|
+
total_cost_usd: costAvailable ? totalCost : null,
|
|
1688
1737
|
num_turns: finalJobUsage.numTurns,
|
|
1689
1738
|
},
|
|
1690
1739
|
timestamp: new Date(this.now()).toISOString(),
|
|
@@ -1701,7 +1750,7 @@ class LoopRunManager {
|
|
|
1701
1750
|
runId,
|
|
1702
1751
|
outcome,
|
|
1703
1752
|
iterations: iteration,
|
|
1704
|
-
totalCostUsd:
|
|
1753
|
+
totalCostUsd: costAvailable ? totalCost : null,
|
|
1705
1754
|
...(outcome === 'stalled' && stallReason ? { stallReason } : {}),
|
|
1706
1755
|
...(providerLimitHit ? { providerLimit: providerLimitHit } : {}),
|
|
1707
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};
|