pantheon-opencode 1.3.5 → 1.3.6
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 +33 -1
- package/package.json +3 -3
- package/scripts/_pantheon_paths.py +0 -1
- package/scripts/build-agents-md.mjs +4 -2
- package/scripts/code_mode_server.py +307 -21
- package/scripts/doctor.mjs +26 -13
- package/scripts/hooks/format-multi-language.sh +6 -3
- package/scripts/hooks/log-session-start.sh +6 -0
- package/scripts/hooks/on-subagent-delegation-start.sh +22 -6
- package/scripts/hooks/validate-post-conditions.sh +1 -1
- package/scripts/hooks/validate-tool-safety.sh +5 -2
- package/scripts/install/agents-md.mjs +3 -1
- package/scripts/install/cli-ui.mjs +24 -4
- package/scripts/install/interactive.mjs +18 -7
- package/scripts/install/migrate-config.mjs +13 -19
- package/scripts/install/migrate.mjs +8 -5
- package/scripts/install/model-picker.mjs +4 -1
- package/scripts/install/opencode.mjs +2 -0
- package/scripts/install/shared.mjs +6 -4
- package/scripts/install/state.mjs +9 -6
- package/scripts/mcp_persistence_server.py +23 -22
- package/scripts/mcp_resources_server.py +60 -1
- package/scripts/memory_mcp_server.py +80 -4
- package/scripts/postinstall.mjs +27 -25
- package/scripts/prune.mjs +1 -1
- package/scripts/redaction-gate.mjs +3 -1
- package/scripts/uninstall.mjs +0 -2
- package/scripts/validation-policy.mjs +6 -1
- package/scripts/version-check.mjs +9 -4
- package/src/agents/aphrodite.md +1 -1
- package/src/agents/demeter.md +1 -1
- package/src/agents/hephaestus.md +1 -1
- package/src/agents/hermes.md +1 -1
- package/src/agents/themis.md +4 -0
- package/src/mcp/code_mode_server.py +304 -18
- package/src/mcp/eval_store.py +233 -0
- package/src/mcp/mcp_persistence_server.py +23 -22
- package/src/mcp/mcp_resources_server.py +58 -0
- package/src/mcp/memory_mcp_server.py +80 -3
- package/src/pantheon/auto-wake.ts +2 -4
- package/src/pantheon/background-job-board.ts +17 -4
- package/src/pantheon/comment-checker.ts +48 -0
- package/src/pantheon/delegation-classifier.ts +307 -0
- package/src/pantheon/delegation-enforce.ts +21 -21
- package/src/pantheon/delegation-finalize.ts +44 -4
- package/src/pantheon/delegation.ts +403 -23
- package/src/pantheon/dispatch-guard.ts +2 -0
- package/src/pantheon/file-persistence.ts +7 -3
- package/src/pantheon/permission-eval.ts +284 -0
- package/src/pantheon/permission-globs.ts +86 -0
- package/src/pantheon/presets.d.mts +41 -0
- package/src/pantheon/presets.mjs +134 -0
- package/src/pantheon/retry-policy.ts +212 -0
- package/src/pantheon/session-guard.ts +1 -3
- package/src/pantheon/step-cap.ts +110 -0
- package/src/pantheon/vision.ts +7 -5
- package/src/pantheon/zeus-delegate-with-retry.ts +81 -12
- package/src/plugin.ts +28 -3
- package/src/plugins/hook-runner.ts +1 -1
- package/src/plugins/pantheon-hooks.ts +1 -1
- package/src/plugins/tui/dist/tui.d.ts +1 -1
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +19 -14
- package/src/plugins/tui/dist/tui.tsx +52 -18
- package/src/plugins/tui/package.json +1 -1
- package/src/plugins/tui/src/index.tsx +52 -18
- package/src/plugins/tui/tsdown.config.ts +1 -1
- package/src/routing.yml +42 -0
|
@@ -677,25 +677,25 @@ function parseConfig(raw: string): UsageBarConfig {
|
|
|
677
677
|
const root = asTable(toml.parse(raw))
|
|
678
678
|
const cfg = defaultConfig()
|
|
679
679
|
|
|
680
|
-
const ui = asTable(root
|
|
681
|
-
cfg.showBars = bool(ui
|
|
682
|
-
cfg.showStatus = bool(ui
|
|
683
|
-
const rawWidth = ui
|
|
680
|
+
const ui = asTable(root.ui)
|
|
681
|
+
cfg.showBars = bool(ui.show_bars, cfg.showBars)
|
|
682
|
+
cfg.showStatus = bool(ui.show_status, cfg.showStatus)
|
|
683
|
+
const rawWidth = ui.bar_width
|
|
684
684
|
if (typeof rawWidth === 'number' && Number.isFinite(rawWidth) && rawWidth >= 1)
|
|
685
685
|
cfg.barWidth = Math.min(40, Math.floor(rawWidth))
|
|
686
686
|
|
|
687
687
|
for (const id of ['anthropic', 'openai', 'opencodego'] as ProviderId[]) {
|
|
688
688
|
const t = asTable(root[id])
|
|
689
689
|
const p = cfg.providers[id]
|
|
690
|
-
p.enabled = bool(t
|
|
691
|
-
p.show['5h'] = bool(t
|
|
692
|
-
p.show['7d'] = bool(t
|
|
693
|
-
p.show['1m'] = bool(t
|
|
694
|
-
p.show.model = bool(t
|
|
690
|
+
p.enabled = bool(t.enabled, p.enabled)
|
|
691
|
+
p.show['5h'] = bool(t.show_5h, p.show['5h'])
|
|
692
|
+
p.show['7d'] = bool(t.show_7d, p.show['7d'])
|
|
693
|
+
p.show['1m'] = bool(t.show_1m, p.show['1m'])
|
|
694
|
+
p.show.model = bool(t.show_model, p.show.model)
|
|
695
695
|
// Assign only when present — keeps `exactOptionalPropertyTypes` happy.
|
|
696
|
-
const credentialsPath = str(t
|
|
696
|
+
const credentialsPath = str(t.credentials_path)
|
|
697
697
|
if (credentialsPath !== undefined) p.credentialsPath = credentialsPath
|
|
698
|
-
const codexAuthPath = str(t
|
|
698
|
+
const codexAuthPath = str(t.codex_auth_path)
|
|
699
699
|
if (codexAuthPath !== undefined) p.codexAuthPath = codexAuthPath
|
|
700
700
|
}
|
|
701
701
|
return cfg
|
|
@@ -942,7 +942,7 @@ export type DelegationEntry = {
|
|
|
942
942
|
taskID?: string
|
|
943
943
|
/** Agent name, e.g. "apollo". */
|
|
944
944
|
agent: string
|
|
945
|
-
state: 'running' | 'completed' | 'error' | 'cancelled'
|
|
945
|
+
state: 'running' | 'completed' | 'error' | 'startup_failed' | 'startup_unknown' | 'cancelled'
|
|
946
946
|
/** Epoch ms of the `Started` header. */
|
|
947
947
|
startedAt: number
|
|
948
948
|
/** Epoch ms of the `Finalized` header — null while still running. */
|
|
@@ -1052,6 +1052,8 @@ export function parseDelegationMarkdown(
|
|
|
1052
1052
|
normalized !== 'running' &&
|
|
1053
1053
|
normalized !== 'completed' &&
|
|
1054
1054
|
normalized !== 'error' &&
|
|
1055
|
+
normalized !== 'startup_failed' &&
|
|
1056
|
+
normalized !== 'startup_unknown' &&
|
|
1055
1057
|
normalized !== 'cancelled'
|
|
1056
1058
|
) {
|
|
1057
1059
|
return null
|
|
@@ -1221,7 +1223,12 @@ export type DelegationActivity =
|
|
|
1221
1223
|
|
|
1222
1224
|
export function delegationActivity(entry: DelegationEntry): DelegationActivity {
|
|
1223
1225
|
if (entry.state === 'completed') return 'completed'
|
|
1224
|
-
if (
|
|
1226
|
+
if (
|
|
1227
|
+
entry.state === 'error' ||
|
|
1228
|
+
entry.state === 'startup_failed' ||
|
|
1229
|
+
entry.state === 'startup_unknown'
|
|
1230
|
+
)
|
|
1231
|
+
return 'error'
|
|
1225
1232
|
if (entry.state === 'cancelled') return 'cancelled'
|
|
1226
1233
|
if (entry.read) return 'reading'
|
|
1227
1234
|
if (entry.alias.startsWith('live-') && entry.taskID === undefined) return 'delegating'
|
|
@@ -1274,7 +1281,12 @@ export function mergeChildDelegationSources(
|
|
|
1274
1281
|
})
|
|
1275
1282
|
|
|
1276
1283
|
for (const liveEntry of live) {
|
|
1277
|
-
if (
|
|
1284
|
+
if (
|
|
1285
|
+
liveEntry.alias === null &&
|
|
1286
|
+
liveEntry.taskID === null &&
|
|
1287
|
+
Date.now() - liveEntry.startedAt > 30_000
|
|
1288
|
+
)
|
|
1289
|
+
continue
|
|
1278
1290
|
const incoming = toDelegationEntry(liveEntry)
|
|
1279
1291
|
const index =
|
|
1280
1292
|
(incoming.taskID !== undefined ? byTask.get(incoming.taskID) : undefined) ??
|
|
@@ -1292,8 +1304,26 @@ export function mergeChildDelegationSources(
|
|
|
1292
1304
|
|
|
1293
1305
|
const existing = result[index]
|
|
1294
1306
|
if (existing === undefined) continue
|
|
1295
|
-
|
|
1296
|
-
|
|
1307
|
+
// Any terminal state is authoritative — a child session that went idle
|
|
1308
|
+
// correctly derives 'completed' via childStatusToState before the MD
|
|
1309
|
+
// report is written. The live tool-part channel stays 'running' until
|
|
1310
|
+
// pantheon_delegation_read fires, so allowing it to overwrite a
|
|
1311
|
+
// terminal state would flip completed → running (the bug this fixes).
|
|
1312
|
+
//
|
|
1313
|
+
// When the existing entry IS terminal, we still absorb live metadata
|
|
1314
|
+
// (alias, agent, read) but preserve the terminal state.
|
|
1315
|
+
if (existing.state !== 'running') {
|
|
1316
|
+
if (liveEntry.alias !== null && existing.alias !== incoming.alias) {
|
|
1317
|
+
existing.alias = incoming.alias
|
|
1318
|
+
}
|
|
1319
|
+
if (incoming.agent !== 'agent' && existing.agent !== incoming.agent) {
|
|
1320
|
+
existing.agent = incoming.agent
|
|
1321
|
+
}
|
|
1322
|
+
if (incoming.read && !existing.read) {
|
|
1323
|
+
existing.read = true
|
|
1324
|
+
}
|
|
1325
|
+
continue
|
|
1326
|
+
}
|
|
1297
1327
|
result[index] = {
|
|
1298
1328
|
...existing,
|
|
1299
1329
|
alias: liveEntry.alias !== null ? incoming.alias : existing.alias,
|
|
@@ -2220,7 +2250,9 @@ function View(props: {
|
|
|
2220
2250
|
}
|
|
2221
2251
|
const withStatus = children.map((c) => ({ ...c, status: resolveStatus(c.id) }))
|
|
2222
2252
|
const childEntries = childrenToDelegationEntries(withStatus, md, now())
|
|
2223
|
-
for (const [k, v] of props.liveStore.map)
|
|
2253
|
+
for (const [k, v] of props.liveStore.map)
|
|
2254
|
+
if (v.alias === null && v.taskID === null && Date.now() - v.startedAt > 30_000)
|
|
2255
|
+
props.liveStore.map.delete(k)
|
|
2224
2256
|
// The event channel is optimistic: it renders a job even while the
|
|
2225
2257
|
// child session/report is still being created. Filter by parent so a
|
|
2226
2258
|
// different focused session never leaks rows into this sidebar.
|
|
@@ -2488,7 +2520,9 @@ const tui: TuiPlugin = (api, _options, _meta) => {
|
|
|
2488
2520
|
order: 900,
|
|
2489
2521
|
slots: {
|
|
2490
2522
|
sidebar_content(_ctx, props) {
|
|
2491
|
-
return
|
|
2523
|
+
return (
|
|
2524
|
+
<View api={api} sessionID={props.session_id} version={version()} liveStore={liveStore} />
|
|
2525
|
+
)
|
|
2492
2526
|
},
|
|
2493
2527
|
},
|
|
2494
2528
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pantheon-tui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.3.
|
|
4
|
+
"version": "1.3.6",
|
|
5
5
|
"description": "Pantheon TUI plugin — sidebar (version, preset, sessions, real-time delegations) + AI subscription usage gauges incl. OpenCode Go/Zen dollar limits (vendored, MIT)",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"exports": {
|
|
@@ -677,25 +677,25 @@ function parseConfig(raw: string): UsageBarConfig {
|
|
|
677
677
|
const root = asTable(toml.parse(raw))
|
|
678
678
|
const cfg = defaultConfig()
|
|
679
679
|
|
|
680
|
-
const ui = asTable(root
|
|
681
|
-
cfg.showBars = bool(ui
|
|
682
|
-
cfg.showStatus = bool(ui
|
|
683
|
-
const rawWidth = ui
|
|
680
|
+
const ui = asTable(root.ui)
|
|
681
|
+
cfg.showBars = bool(ui.show_bars, cfg.showBars)
|
|
682
|
+
cfg.showStatus = bool(ui.show_status, cfg.showStatus)
|
|
683
|
+
const rawWidth = ui.bar_width
|
|
684
684
|
if (typeof rawWidth === 'number' && Number.isFinite(rawWidth) && rawWidth >= 1)
|
|
685
685
|
cfg.barWidth = Math.min(40, Math.floor(rawWidth))
|
|
686
686
|
|
|
687
687
|
for (const id of ['anthropic', 'openai', 'opencodego'] as ProviderId[]) {
|
|
688
688
|
const t = asTable(root[id])
|
|
689
689
|
const p = cfg.providers[id]
|
|
690
|
-
p.enabled = bool(t
|
|
691
|
-
p.show['5h'] = bool(t
|
|
692
|
-
p.show['7d'] = bool(t
|
|
693
|
-
p.show['1m'] = bool(t
|
|
694
|
-
p.show.model = bool(t
|
|
690
|
+
p.enabled = bool(t.enabled, p.enabled)
|
|
691
|
+
p.show['5h'] = bool(t.show_5h, p.show['5h'])
|
|
692
|
+
p.show['7d'] = bool(t.show_7d, p.show['7d'])
|
|
693
|
+
p.show['1m'] = bool(t.show_1m, p.show['1m'])
|
|
694
|
+
p.show.model = bool(t.show_model, p.show.model)
|
|
695
695
|
// Assign only when present — keeps `exactOptionalPropertyTypes` happy.
|
|
696
|
-
const credentialsPath = str(t
|
|
696
|
+
const credentialsPath = str(t.credentials_path)
|
|
697
697
|
if (credentialsPath !== undefined) p.credentialsPath = credentialsPath
|
|
698
|
-
const codexAuthPath = str(t
|
|
698
|
+
const codexAuthPath = str(t.codex_auth_path)
|
|
699
699
|
if (codexAuthPath !== undefined) p.codexAuthPath = codexAuthPath
|
|
700
700
|
}
|
|
701
701
|
return cfg
|
|
@@ -942,7 +942,7 @@ export type DelegationEntry = {
|
|
|
942
942
|
taskID?: string
|
|
943
943
|
/** Agent name, e.g. "apollo". */
|
|
944
944
|
agent: string
|
|
945
|
-
state: 'running' | 'completed' | 'error' | 'cancelled'
|
|
945
|
+
state: 'running' | 'completed' | 'error' | 'startup_failed' | 'startup_unknown' | 'cancelled'
|
|
946
946
|
/** Epoch ms of the `Started` header. */
|
|
947
947
|
startedAt: number
|
|
948
948
|
/** Epoch ms of the `Finalized` header — null while still running. */
|
|
@@ -1052,6 +1052,8 @@ export function parseDelegationMarkdown(
|
|
|
1052
1052
|
normalized !== 'running' &&
|
|
1053
1053
|
normalized !== 'completed' &&
|
|
1054
1054
|
normalized !== 'error' &&
|
|
1055
|
+
normalized !== 'startup_failed' &&
|
|
1056
|
+
normalized !== 'startup_unknown' &&
|
|
1055
1057
|
normalized !== 'cancelled'
|
|
1056
1058
|
) {
|
|
1057
1059
|
return null
|
|
@@ -1221,7 +1223,12 @@ export type DelegationActivity =
|
|
|
1221
1223
|
|
|
1222
1224
|
export function delegationActivity(entry: DelegationEntry): DelegationActivity {
|
|
1223
1225
|
if (entry.state === 'completed') return 'completed'
|
|
1224
|
-
if (
|
|
1226
|
+
if (
|
|
1227
|
+
entry.state === 'error' ||
|
|
1228
|
+
entry.state === 'startup_failed' ||
|
|
1229
|
+
entry.state === 'startup_unknown'
|
|
1230
|
+
)
|
|
1231
|
+
return 'error'
|
|
1225
1232
|
if (entry.state === 'cancelled') return 'cancelled'
|
|
1226
1233
|
if (entry.read) return 'reading'
|
|
1227
1234
|
if (entry.alias.startsWith('live-') && entry.taskID === undefined) return 'delegating'
|
|
@@ -1274,7 +1281,12 @@ export function mergeChildDelegationSources(
|
|
|
1274
1281
|
})
|
|
1275
1282
|
|
|
1276
1283
|
for (const liveEntry of live) {
|
|
1277
|
-
if (
|
|
1284
|
+
if (
|
|
1285
|
+
liveEntry.alias === null &&
|
|
1286
|
+
liveEntry.taskID === null &&
|
|
1287
|
+
Date.now() - liveEntry.startedAt > 30_000
|
|
1288
|
+
)
|
|
1289
|
+
continue
|
|
1278
1290
|
const incoming = toDelegationEntry(liveEntry)
|
|
1279
1291
|
const index =
|
|
1280
1292
|
(incoming.taskID !== undefined ? byTask.get(incoming.taskID) : undefined) ??
|
|
@@ -1292,8 +1304,26 @@ export function mergeChildDelegationSources(
|
|
|
1292
1304
|
|
|
1293
1305
|
const existing = result[index]
|
|
1294
1306
|
if (existing === undefined) continue
|
|
1295
|
-
|
|
1296
|
-
|
|
1307
|
+
// Any terminal state is authoritative — a child session that went idle
|
|
1308
|
+
// correctly derives 'completed' via childStatusToState before the MD
|
|
1309
|
+
// report is written. The live tool-part channel stays 'running' until
|
|
1310
|
+
// pantheon_delegation_read fires, so allowing it to overwrite a
|
|
1311
|
+
// terminal state would flip completed → running (the bug this fixes).
|
|
1312
|
+
//
|
|
1313
|
+
// When the existing entry IS terminal, we still absorb live metadata
|
|
1314
|
+
// (alias, agent, read) but preserve the terminal state.
|
|
1315
|
+
if (existing.state !== 'running') {
|
|
1316
|
+
if (liveEntry.alias !== null && existing.alias !== incoming.alias) {
|
|
1317
|
+
existing.alias = incoming.alias
|
|
1318
|
+
}
|
|
1319
|
+
if (incoming.agent !== 'agent' && existing.agent !== incoming.agent) {
|
|
1320
|
+
existing.agent = incoming.agent
|
|
1321
|
+
}
|
|
1322
|
+
if (incoming.read && !existing.read) {
|
|
1323
|
+
existing.read = true
|
|
1324
|
+
}
|
|
1325
|
+
continue
|
|
1326
|
+
}
|
|
1297
1327
|
result[index] = {
|
|
1298
1328
|
...existing,
|
|
1299
1329
|
alias: liveEntry.alias !== null ? incoming.alias : existing.alias,
|
|
@@ -2220,7 +2250,9 @@ function View(props: {
|
|
|
2220
2250
|
}
|
|
2221
2251
|
const withStatus = children.map((c) => ({ ...c, status: resolveStatus(c.id) }))
|
|
2222
2252
|
const childEntries = childrenToDelegationEntries(withStatus, md, now())
|
|
2223
|
-
for (const [k, v] of props.liveStore.map)
|
|
2253
|
+
for (const [k, v] of props.liveStore.map)
|
|
2254
|
+
if (v.alias === null && v.taskID === null && Date.now() - v.startedAt > 30_000)
|
|
2255
|
+
props.liveStore.map.delete(k)
|
|
2224
2256
|
// The event channel is optimistic: it renders a job even while the
|
|
2225
2257
|
// child session/report is still being created. Filter by parent so a
|
|
2226
2258
|
// different focused session never leaks rows into this sidebar.
|
|
@@ -2488,7 +2520,9 @@ const tui: TuiPlugin = (api, _options, _meta) => {
|
|
|
2488
2520
|
order: 900,
|
|
2489
2521
|
slots: {
|
|
2490
2522
|
sidebar_content(_ctx, props) {
|
|
2491
|
-
return
|
|
2523
|
+
return (
|
|
2524
|
+
<View api={api} sessionID={props.session_id} version={version()} liveStore={liveStore} />
|
|
2525
|
+
)
|
|
2492
2526
|
},
|
|
2493
2527
|
},
|
|
2494
2528
|
})
|
package/src/routing.yml
CHANGED
|
@@ -151,6 +151,7 @@ presets:
|
|
|
151
151
|
agents:
|
|
152
152
|
zeus:
|
|
153
153
|
role: Central orchestrator
|
|
154
|
+
max_steps: 40 # R4: step budget — at max_steps the agent is forced to summarize-and-stop. Tracker is permanent-per-process (no reset wiring).
|
|
154
155
|
reasoning_effort: medium
|
|
155
156
|
user_invocable: true
|
|
156
157
|
can_delegate: true
|
|
@@ -189,6 +190,7 @@ agents:
|
|
|
189
190
|
- incremental-implementation
|
|
190
191
|
athena:
|
|
191
192
|
role: Strategic planner
|
|
193
|
+
max_steps: 15 # R4: step budget — at max_steps the agent is forced to summarize-and-stop
|
|
192
194
|
reasoning_effort: high
|
|
193
195
|
user_invocable: true
|
|
194
196
|
can_delegate: true
|
|
@@ -208,6 +210,7 @@ agents:
|
|
|
208
210
|
- memory-bank
|
|
209
211
|
apollo:
|
|
210
212
|
role: Investigation scout
|
|
213
|
+
max_steps: 25 # R4: step budget — at max_steps the agent is forced to summarize-and-stop
|
|
211
214
|
reasoning_effort: low
|
|
212
215
|
user_invocable: false
|
|
213
216
|
can_delegate: false
|
|
@@ -225,6 +228,7 @@ agents:
|
|
|
225
228
|
- auto-continue
|
|
226
229
|
hermes:
|
|
227
230
|
role: Backend specialist
|
|
231
|
+
max_steps: 60 # R4: step budget — at max_steps the agent is forced to summarize-and-stop
|
|
228
232
|
reasoning_effort: medium
|
|
229
233
|
user_invocable: true
|
|
230
234
|
can_delegate: true
|
|
@@ -247,6 +251,7 @@ agents:
|
|
|
247
251
|
- incremental-implementation
|
|
248
252
|
aphrodite:
|
|
249
253
|
role: Frontend specialist
|
|
254
|
+
max_steps: 60 # R4: step budget — at max_steps the agent is forced to summarize-and-stop
|
|
250
255
|
reasoning_effort: medium
|
|
251
256
|
user_invocable: true
|
|
252
257
|
can_delegate: false
|
|
@@ -267,6 +272,7 @@ agents:
|
|
|
267
272
|
- file-prompts
|
|
268
273
|
demeter:
|
|
269
274
|
role: Database specialist
|
|
275
|
+
max_steps: 50 # R4: step budget — at max_steps the agent is forced to summarize-and-stop
|
|
270
276
|
reasoning_effort: medium
|
|
271
277
|
user_invocable: true
|
|
272
278
|
can_delegate: false
|
|
@@ -286,6 +292,7 @@ agents:
|
|
|
286
292
|
- incremental-implementation
|
|
287
293
|
themis:
|
|
288
294
|
role: Quality gate
|
|
295
|
+
max_steps: 25 # R4: step budget — at max_steps the agent is forced to summarize-and-stop
|
|
289
296
|
reasoning_effort: high
|
|
290
297
|
user_invocable: true
|
|
291
298
|
can_delegate: false
|
|
@@ -307,6 +314,7 @@ agents:
|
|
|
307
314
|
- context-compression
|
|
308
315
|
prometheus:
|
|
309
316
|
role: Infrastructure specialist
|
|
317
|
+
max_steps: 30 # R4: step budget — at max_steps the agent is forced to summarize-and-stop
|
|
310
318
|
reasoning_effort: medium
|
|
311
319
|
user_invocable: true
|
|
312
320
|
can_delegate: false
|
|
@@ -325,6 +333,7 @@ agents:
|
|
|
325
333
|
- incremental-implementation
|
|
326
334
|
hephaestus:
|
|
327
335
|
role: AI pipelines
|
|
336
|
+
max_steps: 50 # R4: step budget — at max_steps the agent is forced to summarize-and-stop
|
|
328
337
|
reasoning_effort: medium
|
|
329
338
|
user_invocable: true
|
|
330
339
|
can_delegate: false
|
|
@@ -343,6 +352,7 @@ agents:
|
|
|
343
352
|
- auto-continue
|
|
344
353
|
nyx:
|
|
345
354
|
role: Observability
|
|
355
|
+
max_steps: 25 # R4: step budget — at max_steps the agent is forced to summarize-and-stop
|
|
346
356
|
reasoning_effort: low
|
|
347
357
|
user_invocable: true
|
|
348
358
|
can_delegate: false
|
|
@@ -361,6 +371,7 @@ agents:
|
|
|
361
371
|
- auto-continue
|
|
362
372
|
gaia:
|
|
363
373
|
role: Remote sensing domain specialist
|
|
374
|
+
max_steps: 25 # R4: step budget — at max_steps the agent is forced to summarize-and-stop
|
|
364
375
|
reasoning_effort: low
|
|
365
376
|
user_invocable: false
|
|
366
377
|
can_delegate: false
|
|
@@ -375,6 +386,7 @@ agents:
|
|
|
375
386
|
- auto-continue
|
|
376
387
|
iris:
|
|
377
388
|
role: GitHub operations
|
|
389
|
+
max_steps: 20 # R4: step budget — at max_steps the agent is forced to summarize-and-stop
|
|
378
390
|
reasoning_effort: low
|
|
379
391
|
user_invocable: true
|
|
380
392
|
can_delegate: false
|
|
@@ -392,6 +404,7 @@ agents:
|
|
|
392
404
|
- artifact-management
|
|
393
405
|
mnemosyne:
|
|
394
406
|
role: Memory bank
|
|
407
|
+
max_steps: 20 # R4: step budget — at max_steps the agent is forced to summarize-and-stop
|
|
395
408
|
reasoning_effort: low
|
|
396
409
|
user_invocable: true
|
|
397
410
|
can_delegate: false
|
|
@@ -415,6 +428,7 @@ agents:
|
|
|
415
428
|
- session-goal
|
|
416
429
|
talos:
|
|
417
430
|
role: Hotfix agent
|
|
431
|
+
max_steps: 15 # R4: step budget — at max_steps the agent is forced to summarize-and-stop
|
|
418
432
|
reasoning_effort: low
|
|
419
433
|
user_invocable: true
|
|
420
434
|
can_delegate: false
|
|
@@ -573,6 +587,34 @@ background_delegation:
|
|
|
573
587
|
read_only_agents: [apollo, gaia]
|
|
574
588
|
session_max: 3
|
|
575
589
|
retry_count: 1
|
|
590
|
+
# ── R1: Per-error-type retry + provider cooldown (LiteLLM pattern) ──────
|
|
591
|
+
# retry_policy: max retries per error class before escalating. Exponential
|
|
592
|
+
# backoff (base 1s, doubling, capped 30s) applies between retries. auth
|
|
593
|
+
# errors are NEVER retried (0) — a credential problem will not fix itself.
|
|
594
|
+
# Enforcement: zeus-delegate-with-retry (manual waves) + RetryPolicyEngine.
|
|
595
|
+
retry_policy:
|
|
596
|
+
auth: 0
|
|
597
|
+
rate_limit: 3
|
|
598
|
+
timeout: 2
|
|
599
|
+
other: 1
|
|
600
|
+
# cooldown: after `allowed_fails` consecutive failures for a provider, skip
|
|
601
|
+
# that provider for `cooldown_time_seconds`. A success resets the counter.
|
|
602
|
+
# In-memory tracker (no Redis) — process-wide, shared across retry helpers.
|
|
603
|
+
cooldown:
|
|
604
|
+
allowed_fails: 3
|
|
605
|
+
cooldown_time_seconds: 60
|
|
606
|
+
# ── O5: permission.task — glob rules for which subagents an agent may
|
|
607
|
+
# invoke (last matching rule wins; deny removes the agent from the delegate
|
|
608
|
+
# tool description entirely — prevents circular delegation at the
|
|
609
|
+
# permission layer). Default "*": allow keeps the existing runtime matrix
|
|
610
|
+
# (zeus → anyone; athena/hermes → apollo only). Example deny-first config:
|
|
611
|
+
# permission:
|
|
612
|
+
# task:
|
|
613
|
+
# "*": deny
|
|
614
|
+
# "orchestrator-*": allow
|
|
615
|
+
permission:
|
|
616
|
+
task:
|
|
617
|
+
"*": allow
|
|
576
618
|
todo_enforcer:
|
|
577
619
|
enabled: true
|
|
578
620
|
cooldown_base_ms: 5000 # base backoff between injections
|