pantheon-opencode 1.6.0-beta.1 → 1.6.0-beta.11
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/AGENTS.global.md +206 -0
- package/AGENTS.md +10 -891
- package/CHANGELOG.md +350 -0
- package/README.md +561 -52
- package/README.pt-BR.md +285 -20
- package/bin/pantheon-init.mjs +70 -4
- package/commands/pantheon-audit.md +7 -1
- package/commands/pantheon-consolidate.md +1 -1
- package/commands/pantheon-deepwork.md +14 -3
- package/commands/pantheon-focus.md +17 -0
- package/commands/pantheon-vision.md +61 -12
- package/package.json +24 -17
- package/plugin.json +2 -2
- package/pyproject.toml +8 -6
- package/scripts/build-agents-md.mjs +428 -56
- package/scripts/changelog-merge.mjs +161 -0
- package/scripts/{code_mode_server.py → code_mode.py} +3 -3
- package/scripts/cost.mjs +244 -41
- package/scripts/doctor.mjs +151 -1
- package/scripts/install/agents-md.mjs +4 -4
- package/scripts/install/backup.mjs +475 -0
- package/scripts/install/cli-ui.mjs +6 -1
- package/scripts/install/config-migration.mjs +317 -4
- package/scripts/install/exit-codes.mjs +26 -0
- package/scripts/install/health-check.mjs +21 -19
- package/scripts/install/interactive.mjs +16 -2
- package/scripts/install/migrate.mjs +41 -22
- package/scripts/install/opencode-version.mjs +246 -4
- package/scripts/install/opencode.mjs +1175 -215
- package/scripts/install/plan.mjs +287 -0
- package/scripts/install/plugin.mjs +62 -14
- package/scripts/install/shared.mjs +190 -48
- package/scripts/install/strings.mjs +20 -0
- package/scripts/install/venv.mjs +13 -3
- package/scripts/install/vision-prompt.mjs +171 -0
- package/scripts/install-mcp.mjs +28 -9
- package/scripts/{mcp_persistence_server.py → mcp_persistence.py} +52 -17
- package/{src/mcp/mcp_resources_server.py → scripts/mcp_resources.py} +2 -2
- package/scripts/{memory_mcp_server.py → memory_mcp.py} +2 -2
- package/scripts/probe-context-rehydrate.mjs +8 -2
- package/scripts/probe-pantheon-cost.mjs +71 -15
- package/scripts/prune.mjs +9 -3
- package/scripts/restore.mjs +222 -0
- package/scripts/run-node-tests.mjs +189 -0
- package/scripts/sync-artifacts.mjs +26 -13
- package/scripts/sync-tui.mjs +24 -3
- package/scripts/test-opencode-v2-sandbox.sh +180 -26
- package/scripts/validate-routing.mjs +3 -3
- package/scripts/validate-sandbox-install.mjs +138 -0
- package/scripts/versioning.mjs +13 -1
- package/scripts/vision-status.mjs +682 -0
- package/skills-lock.json +8 -8
- package/src/agents/aphrodite.md +20 -37
- package/src/agents/apollo.md +7 -3
- package/src/agents/athena.md +63 -35
- package/src/agents/demeter.md +8 -28
- package/src/agents/gaia.md +1 -1
- package/src/agents/hephaestus.md +10 -21
- package/src/agents/hermes.md +15 -38
- package/src/agents/iris.md +7 -1
- package/src/agents/mnemosyne.md +18 -54
- package/src/agents/nyx.md +1 -1
- package/src/agents/prometheus.md +16 -20
- package/src/agents/talos.md +10 -2
- package/src/agents/themis.md +5 -5
- package/src/agents/zeus.md +99 -172
- package/src/instructions/agent-return-format.instructions.md +34 -17
- package/src/instructions/backend-standards.instructions.md +2 -0
- package/src/instructions/frontend-standards.instructions.md +3 -1
- package/src/instructions/memory-protocol.instructions.md +12 -110
- package/src/instructions/test-economy.instructions.md +21 -0
- package/src/instructions/zeus-anti-stall.instructions.md +20 -67
- package/src/instructions/zeus-communication-rules.instructions.md +0 -1
- package/src/instructions/zeus-council-synthesis.instructions.md +31 -260
- package/src/instructions/zeus-memory-operations.instructions.md +30 -0
- package/src/instructions/zeus-timeout-retry.instructions.md +61 -89
- package/src/mcp/{code_mode_server.py → code_mode.py} +3 -3
- package/src/mcp/eval_store.py +2 -2
- package/src/mcp/{mcp_persistence_server.py → mcp_persistence.py} +52 -17
- package/{scripts/mcp_resources_server.py → src/mcp/mcp_resources.py} +2 -2
- package/src/mcp/{memory_mcp_server.py → memory_mcp.py} +2 -2
- package/src/mcp/{pantheon_vision_server.py → pantheon_vision.py} +286 -42
- package/src/mcp/requirements-mcp.txt +6 -4
- package/src/mcp/requirements-vision.txt +2 -2
- package/src/pantheon/cost-command.ts +403 -102
- package/src/pantheon/delegation-enforce.ts +10 -1
- package/src/pantheon/model-agents.ts +19 -0
- package/src/pantheon/model-command.ts +218 -56
- package/src/pantheon/presets.d.mts +0 -8
- package/src/pantheon/presets.mjs +5 -32
- package/src/pantheon/v2-bounded-read.ts +640 -0
- package/src/pantheon/v2-delegation-enforce.ts +214 -0
- package/src/pantheon/v2-execute-after.ts +186 -0
- package/src/pantheon/v2-model-overrides.ts +275 -0
- package/src/pantheon/v2-tools.ts +418 -0
- package/src/pantheon/v2-unsupported.d.mts +11 -0
- package/src/pantheon/v2-unsupported.mjs +90 -0
- package/src/pantheon/v2-vision.ts +622 -0
- package/src/pantheon/vision-local.ts +531 -0
- package/src/pantheon/vision.ts +1160 -115
- package/src/plugin-v2.ts +1158 -219
- package/src/plugin.ts +12 -9
- package/src/plugins/tui/dist/server.d.ts +1 -2
- package/src/plugins/tui/dist/server.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui-v2.d.ts +154 -0
- package/src/plugins/tui/dist/tui-v2.d.ts.map +1 -0
- package/src/plugins/tui/dist/tui-v2.js +659 -0
- package/src/plugins/tui/dist/tui-v2.js.map +1 -0
- package/src/plugins/tui/dist/tui.d.ts +85 -82
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +72 -59
- package/src/plugins/tui/index-v2.ts +6 -0
- package/src/plugins/tui/package-lock.json +5516 -1353
- package/src/plugins/tui/package.json +22 -12
- package/src/plugins/tui/src/index-v2.tsx +734 -0
- package/src/plugins/tui/src/index.tsx +106 -85
- package/src/plugins/tui/src/opencode-v2.d.ts +13 -0
- package/src/plugins/tui/tsconfig.build.json +5 -0
- package/src/plugins/tui/tsconfig.typecheck.json +5 -0
- package/src/plugins/tui/tsdown.config.ts +22 -2
- package/src/plugins/tui/tui-v2.ts +2 -0
- package/src/plugins/tui/tui.ts +3 -0
- package/src/routing.yml +11 -21
- package/src/skills/README.md +3 -3
- package/src/skills/agent-coordination/SKILL.md +7 -2
- package/src/skills/artifact-management/SKILL.md +12 -5
- package/src/skills/auto-continue/SKILL.md +52 -35
- package/src/skills/code-review-checklist/SKILL.md +5 -5
- package/src/skills/context-compression/SKILL.md +26 -879
- package/src/skills/session-goal/SKILL.md +14 -5
- package/src/skills/spec-driven-development/SKILL.md +3 -1
- package/src/skills/tdd-with-agents/SKILL.md +18 -10
- package/opencode.json +0 -58
|
@@ -1,132 +1,100 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "Timeout enforcement, retry policies, subtask dispatch, and timeout tracking for Zeus"
|
|
3
3
|
name: "Zeus Timeout & Retry"
|
|
4
|
-
|
|
4
|
+
agents: [zeus]
|
|
5
|
+
fallback: shared
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# ⏱️ TIMEOUT & RETRY ENFORCEMENT
|
|
8
9
|
|
|
9
10
|
When a delegated agent does not respond in time, enforce the timeout policy from `routing.yml`.
|
|
10
11
|
|
|
12
|
+
Use the root `subagent` dispatch observed in the Beta 10 runtime. `task()` is
|
|
13
|
+
host/API terminology; the active runtime determines the callable schema and any
|
|
14
|
+
background options. Do not assume root `task_status`, `cancel_task`, or board
|
|
15
|
+
tracking/recovery tools. Prefer synchronous dispatch unless background completion
|
|
16
|
+
is observable through the host, and keep any retry list in the current context
|
|
17
|
+
only; do not claim persistent job tracking.
|
|
18
|
+
|
|
11
19
|
## Timeout Behavior by Agent Role
|
|
12
20
|
|
|
13
|
-
| Agent Role | Timeout | Retry Policy |
|
|
14
|
-
|
|
15
|
-
| Explorer (@apollo) | 60s |
|
|
16
|
-
| Implementer (@hermes, @aphrodite, @demeter) | 180s |
|
|
17
|
-
| Reviewer (@themis) | 120s |
|
|
18
|
-
| Infrastructure (@prometheus) | 300s |
|
|
19
|
-
| Hotfix (@talos) | 30s |
|
|
20
|
-
| Remote Sensing (@gaia) | 120s |
|
|
21
|
+
| Agent Role | Timeout | Retry Policy | Partial Results OK? | Reasoning Effort |
|
|
22
|
+
|------------|---------|--------------|---------------------|------------------|
|
|
23
|
+
| Explorer (@apollo) | 60s | 1 retry | ✅ Yes | low |
|
|
24
|
+
| Implementer (@hermes, @aphrodite, @demeter) | 180s | 1 retry | ❌ No | medium |
|
|
25
|
+
| Reviewer (@themis) | 120s | 1 retry | ❌ No | high |
|
|
26
|
+
| Infrastructure (@prometheus) | 300s | 1 retry | ❌ No | medium |
|
|
27
|
+
| Hotfix (@talos) | 30s | 1 retry | ✅ Yes | low |
|
|
28
|
+
| Remote Sensing (@gaia) | 120s | 1 retry | ✅ Yes | high |
|
|
21
29
|
|
|
22
30
|
## Retry Flow
|
|
23
31
|
|
|
24
32
|
```
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
│
|
|
29
|
-
├─ retries exhausted → FALLBACK CHAIN:
|
|
30
|
-
│ ├─ fallback[0] exists? → dispatch to fallback agent
|
|
31
|
-
│ │ └─ keep original task spec + context; add error context
|
|
32
|
-
│ ├─ fallback[1] exists? → dispatch to second fallback
|
|
33
|
-
│ └─ all fallbacks failed? → ESCALATE
|
|
34
|
-
│
|
|
35
|
-
├─ no fallbacks defined → return TIMEOUT error to user
|
|
36
|
-
│
|
|
37
|
-
└─ ESCALATE: "Agent X failed after N retries. Fallbacks Y, Z also failed.
|
|
38
|
-
Options: (a) try different agent, (b) simplify scope, (c) manual"
|
|
33
|
+
Initial attempt → timeout/failure → log it → make at most one retry
|
|
34
|
+
└─ retry fails → try fallback agents left-to-right with original task/context
|
|
35
|
+
└─ all fallbacks fail (or none exist) → report the chain and escalate
|
|
39
36
|
```
|
|
37
|
+
`background_delegation.retry_count: 1` means one retry after the initial attempt, not one total attempt. Never restart an exhausted chain automatically.
|
|
40
38
|
|
|
41
|
-
|
|
39
|
+
Apply the retry only to a transient dispatch failure (timeout, crash, or empty response). A failed test, validation, or migration is a result to diagnose, not a reason to repeat the same command or agent blindly. Track agents already tried: each agent may be retried at most once and each listed fallback may be tried at most once. For auth/security/data/schema work, a fallback must preserve specialist competence, Themis review, and human approval; otherwise stop and escalate. Never let full-auto bypass these gates.
|
|
40
|
+
An agent refusal or scope-boundary response is not a transient failure: do not retry it with a rephrased prompt. Correct the route once if the right specialist is clear; otherwise stop and ask.
|
|
42
41
|
|
|
43
42
|
## Fallback Chain Definitions
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
| @apollo | @athena (plan scoped task) | @hermes (implement search) | @zeus |
|
|
50
|
-
| @hermes | @talos (minimal fix) | @athena (replan + simplify) | @zeus |
|
|
51
|
-
| @aphrodite | @talos (CSS/UX fix) | @hermes (generic fallback) | @zeus |
|
|
52
|
-
| @demeter | @hermes (generic backend) | @athena (replan schema) | @zeus |
|
|
53
|
-
| @themis | @zeus (direct escalation) | — | user |
|
|
54
|
-
| @prometheus | @hermes (config/deploy) | @zeus | user |
|
|
55
|
-
| @talos | @hermes (full implementation) | — | @zeus |
|
|
56
|
-
| @hephaestus | @nyx (observability debug) | @hermes (generic) | @zeus |
|
|
57
|
-
| @nyx | @hermes (generic) | — | @zeus |
|
|
58
|
-
| @iris | @zeus (manual override) | — | user |
|
|
59
|
-
| @mnemosyne | @zeus (manual) | — | user |
|
|
44
|
+
`routing.yml` → `fallback_chains` is the canonical agent-by-agent mapping. Evaluate
|
|
45
|
+
the configured chain left-to-right; if an agent has no configured chain, stop
|
|
46
|
+
and escalate rather than guessing a fallback. Each listed fallback may be tried
|
|
47
|
+
at most once, and an exhausted chain is never restarted automatically.
|
|
60
48
|
|
|
61
|
-
###
|
|
62
|
-
When ALL fallbacks fail:
|
|
63
|
-
1. Log the full failure chain: which agents were tried, what error each returned
|
|
64
|
-
2. Report to user: "Task [X] failed. Tried: [agent list]. Error: [summary]."
|
|
65
|
-
3. Offer options: (a) try different approach, (b) simplify scope, (c) manual fix
|
|
66
|
-
4. NEVER retry the same chain automatically — break the cycle
|
|
49
|
+
### Refusal Is a Routing Error
|
|
67
50
|
|
|
68
|
-
|
|
69
|
-
|
|
51
|
+
For a domain/scope refusal, do not retry with a rephrased prompt. Correct the
|
|
52
|
+
route once only when the right specialist is clear; otherwise stop and ask.
|
|
53
|
+
Record one `DelegationCacheDecision` telemetry item only when telemetry recording
|
|
54
|
+
is actually exposed; otherwise keep the corrected route in the current handoff
|
|
55
|
+
and do not claim telemetry was persisted. Include `reroute_from`, `reroute_to`,
|
|
56
|
+
and `delegation_id` when available.
|
|
70
57
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
Files already explored: backend/routers/auth.py, backend/services/auth_service.py.
|
|
74
|
-
New task: add refresh token rotation.
|
|
75
|
-
```
|
|
58
|
+
### Escalation Protocol
|
|
59
|
+
When all fallbacks fail, report the tried agents and errors, offer a different approach/simpler scope/manual fix, and stop. Never retry the same chain automatically.
|
|
76
60
|
|
|
77
|
-
|
|
61
|
+
### Session Reuse Check
|
|
62
|
+
Reuse a prior specialist session only when the active host exposes that capability;
|
|
63
|
+
otherwise dispatch through `subagent` with necessary context. Treat `session_max`
|
|
64
|
+
as policy context, not as a claim that Zeus can enumerate sessions.
|
|
78
65
|
|
|
79
66
|
---
|
|
80
67
|
|
|
81
68
|
# 📦 SUBTASK DISPATCH (Lightweight Delegation)
|
|
82
69
|
|
|
83
|
-
Subtask is a bounded, low-risk delegation mode that **skips** the standard artifact lifecycle.
|
|
70
|
+
Subtask is a bounded, low-risk delegation mode that **skips** the standard artifact lifecycle. Choose it by risk and need for review, not by a fixed file/line count.
|
|
84
71
|
|
|
85
72
|
## When to Use Subtask vs Full Task
|
|
86
73
|
|
|
87
|
-
|
|
74
|
+
Use the lightest path that safely meets the request. A multi-file but bounded low-risk change does not automatically need a plan/artifact phase.
|
|
88
75
|
|
|
89
76
|
### Subtask Decision Tree (run BEFORE every delegation)
|
|
90
77
|
|
|
91
78
|
```
|
|
92
|
-
□
|
|
93
|
-
□
|
|
94
|
-
□
|
|
95
|
-
□ Data: No data loss risk, no migration? [YES→continue | NO→full task]
|
|
96
|
-
□ Review: Output does NOT feed into Themis review? [YES→continue | NO→full task]
|
|
97
|
-
|
|
98
|
-
ALL YES → subtask (skip artifact + Themis)
|
|
99
|
-
ANY NO → full task (IMPL artifact + Themis review mandatory)
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Comparison Table
|
|
103
|
-
|
|
104
|
-
| Aspect | Subtask | Full Task |
|
|
105
|
-
|--------|---------|-----------|
|
|
106
|
-
| Scope | Single file, <10 lines, read-only | Feature, multi-file, schema change |
|
|
107
|
-
| Risk | Low (no security/data implications) | Any risk level |
|
|
108
|
-
| Artifact | ❌ No IMPL artifact | ✅ IMPL artifact required |
|
|
109
|
-
| Themis review | ❌ None | ✅ Mandatory |
|
|
110
|
-
| Use case | Apollo discovery, Talos hotfix, bounded fix | Feature implementation, migration, API change |
|
|
79
|
+
□ Is the scope clear, bounded, reversible, and low-uncertainty? [YES→continue | NO→clarify/plan]
|
|
80
|
+
□ Does it avoid auth/security, data/schema, destructive, broad/material, and user-visible API risk? [YES→continue | NO→relevant gates]
|
|
81
|
+
□ Is there no required Themis/audit handoff for this change? [YES→continue | NO→preserve that review]
|
|
111
82
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|------|-------|------|----------|-----|
|
|
116
|
-
| Fix typo in CSS class | 1 file, 1 line | None | ✅ | Bounded, no security impact |
|
|
117
|
-
| Add error handling to existing endpoint | 1 file, 5 lines | Low | ✅ | No schema change |
|
|
118
|
-
| Implement login endpoint | 2+ files, 50+ lines | High (auth) | ❌ | Security-critical, needs Themis |
|
|
119
|
-
| Database migration | 1 file, 15 lines | High (data) | ❌ | Data loss risk, needs rollback |
|
|
120
|
-
| Apollo codebase search | 0 files | None | ✅ | Read-only investigation |
|
|
121
|
-
| Update README | 1 file, 3 lines | None | ✅ | Documentation only |
|
|
83
|
+
ALL YES → one correct domain specialist; they inspect needed context, implement, and verify; no routine plan/artifact, separate discovery, council, or review
|
|
84
|
+
ANY NO → add only the planning, artifact, specialist review, and approval gates the risk requires
|
|
85
|
+
```
|
|
122
86
|
|
|
123
87
|
### Safety Rules
|
|
124
|
-
1. **Bounded scope** —
|
|
125
|
-
2. **Low risk** — no security implications,
|
|
126
|
-
3. **No Themis dependency** — output
|
|
88
|
+
1. **Bounded scope** — can be a small multi-file change or a read-only investigation
|
|
89
|
+
2. **Low risk and uncertainty** — no security implications, data loss, breaking/user-visible API impact, broad material scope, or unresolved high uncertainty
|
|
90
|
+
3. **No required Themis dependency** — sensitive/material output retains its review gate
|
|
91
|
+
|
|
92
|
+
The selected specialist, not a routine Apollo discovery pass, inspects the relevant
|
|
93
|
+
local context for a lightweight implementation. Keep specialist roles available for
|
|
94
|
+
on-demand routing; do not remove an agent based on one task or one overhead observation.
|
|
127
95
|
|
|
128
96
|
## Subtask Return Format
|
|
129
|
-
Return the
|
|
97
|
+
Return the required `## subtask_summary` fields defined in `## Agent Return Format`; include `memory_context` when memory was used.
|
|
130
98
|
|
|
131
99
|
## Timeout Parcial (Partial Results)
|
|
132
100
|
|
|
@@ -136,4 +104,8 @@ Only agents marked ✅ in the Timeout Behavior table above may return partial re
|
|
|
136
104
|
|
|
137
105
|
# 📊 TIMEOUT TRACKING
|
|
138
106
|
|
|
139
|
-
|
|
107
|
+
Keep only an in-context list of active delegations and already-tried agents when
|
|
108
|
+
needed. Use results returned by `subagent` or host completion notifications; do
|
|
109
|
+
not poll, cancel, or write a timeout log unless the corresponding tool is exposed.
|
|
110
|
+
Report any timeout and the retry/fallback taken in the user-facing handoff; do
|
|
111
|
+
not claim persistent tracking or recovery.
|
|
@@ -5,12 +5,12 @@ Provides a confined execution environment for orchestration scripts
|
|
|
5
5
|
via MCP tools and resources.
|
|
6
6
|
|
|
7
7
|
Usage:
|
|
8
|
-
python scripts/
|
|
8
|
+
python scripts/code_mode.py
|
|
9
9
|
|
|
10
10
|
Or via MCP client (stdio transport):
|
|
11
11
|
pantheon-code-mode:
|
|
12
12
|
command: python
|
|
13
|
-
args: ["scripts/
|
|
13
|
+
args: ["scripts/code_mode.py"]
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
from __future__ import annotations
|
|
@@ -36,7 +36,7 @@ from typing import Any
|
|
|
36
36
|
|
|
37
37
|
import yaml
|
|
38
38
|
from _pantheon_paths import pantheon_home, pantheon_project
|
|
39
|
-
from
|
|
39
|
+
from fastmcp import FastMCP
|
|
40
40
|
|
|
41
41
|
# ── Constants ─────────────────────────────────────────────────────────────────
|
|
42
42
|
ALLOWED_EXTENSIONS: frozenset[str] = frozenset({".sh", ".py"})
|
package/src/mcp/eval_store.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"""Plugin eval certification storage — ``plugin_eval`` memory namespace.
|
|
3
3
|
|
|
4
4
|
Thin stdlib-only wrapper around the memory SQLite DB (same schema as
|
|
5
|
-
``src/mcp/
|
|
5
|
+
``src/mcp/memory_mcp.py``) for plugin-eval certification results.
|
|
6
6
|
|
|
7
7
|
Namespace: ``plugin_eval``
|
|
8
8
|
Key format: ``eval:<name>:<date>`` (e.g. ``eval:tdd-with-agents:2026-08-21``)
|
|
@@ -30,7 +30,7 @@ from typing import Any
|
|
|
30
30
|
|
|
31
31
|
NAMESPACE = "plugin_eval"
|
|
32
32
|
|
|
33
|
-
# Minimal schema — matches
|
|
33
|
+
# Minimal schema — matches memory_mcp.SCHEMA_SQL for the memories
|
|
34
34
|
# table (vec/FTS tables are initialized by the memory MCP server on first
|
|
35
35
|
# run; eval entries remain readable via list/recall regardless).
|
|
36
36
|
_SCHEMA_SQL = """
|
|
@@ -5,7 +5,7 @@ Key-Value store with FTS5 full-text search, TTL-based expiration,
|
|
|
5
5
|
and namespace isolation. Uses SQLite with zero external dependencies.
|
|
6
6
|
|
|
7
7
|
Usage:
|
|
8
|
-
python scripts/
|
|
8
|
+
python scripts/mcp_persistence.py
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
@@ -25,7 +25,7 @@ from pathlib import Path
|
|
|
25
25
|
from typing import Annotated
|
|
26
26
|
|
|
27
27
|
from _pantheon_paths import pantheon_home, pantheon_project
|
|
28
|
-
from
|
|
28
|
+
from fastmcp import FastMCP
|
|
29
29
|
from pydantic import Field
|
|
30
30
|
|
|
31
31
|
# ── Schema ──────────────────────────────────────────────────────────────────────
|
|
@@ -914,15 +914,35 @@ def _validate_delegations(delegations: object) -> None:
|
|
|
914
914
|
|
|
915
915
|
def _validate_tail(tail: object, payload_bytes: int | None = None) -> list[str]:
|
|
916
916
|
"""Validate bounded serialized tail lines."""
|
|
917
|
-
if not isinstance(tail, list)
|
|
918
|
-
raise ValueError("tail
|
|
917
|
+
if not isinstance(tail, list):
|
|
918
|
+
raise ValueError("tail must be an array")
|
|
919
|
+
if len(tail) > MAX_TAIL_ITEMS:
|
|
920
|
+
raise ValueError(
|
|
921
|
+
f"tail has {len(tail)} items; maximum is {MAX_TAIL_ITEMS}; "
|
|
922
|
+
"remove tail entries or omit tail"
|
|
923
|
+
)
|
|
919
924
|
for line in tail:
|
|
920
|
-
if not isinstance(line, str)
|
|
921
|
-
raise ValueError("tail entries
|
|
925
|
+
if not isinstance(line, str):
|
|
926
|
+
raise ValueError("tail entries must be strings")
|
|
927
|
+
line_bytes = len(line.encode())
|
|
928
|
+
if line_bytes > MAX_TAIL_LINE_LENGTH:
|
|
929
|
+
raise ValueError(
|
|
930
|
+
f"tail entries are {line_bytes:,} UTF-8 bytes; maximum is "
|
|
931
|
+
f"{MAX_TAIL_LINE_LENGTH:,}; remove or shorten tail entries, "
|
|
932
|
+
"or omit tail"
|
|
933
|
+
)
|
|
922
934
|
if payload_bytes is not None and payload_bytes > MAX_CONTEXT_CONTENT_BYTES:
|
|
923
|
-
raise ValueError(
|
|
924
|
-
|
|
925
|
-
|
|
935
|
+
raise ValueError(
|
|
936
|
+
f"tail payload is {payload_bytes:,} UTF-8 bytes; maximum is "
|
|
937
|
+
f"{MAX_CONTEXT_CONTENT_BYTES:,}; remove tail entries or omit tail"
|
|
938
|
+
)
|
|
939
|
+
tail_bytes = sum(len(line.encode()) for line in tail)
|
|
940
|
+
if tail_bytes > MAX_CONTEXT_CONTENT_BYTES:
|
|
941
|
+
raise ValueError(
|
|
942
|
+
f"tail contains {tail_bytes:,} UTF-8 bytes across strings; maximum "
|
|
943
|
+
f"is {MAX_CONTEXT_CONTENT_BYTES:,} bytes; remove tail entries or "
|
|
944
|
+
"omit tail"
|
|
945
|
+
)
|
|
926
946
|
return tail
|
|
927
947
|
|
|
928
948
|
|
|
@@ -1020,8 +1040,14 @@ def _collect_context_content_errors(
|
|
|
1020
1040
|
if not isinstance(content, str):
|
|
1021
1041
|
errors.shape(prefix, "a string", content)
|
|
1022
1042
|
return
|
|
1023
|
-
|
|
1024
|
-
|
|
1043
|
+
content_bytes = len(content.encode())
|
|
1044
|
+
if content_bytes > MAX_CONTEXT_CONTENT_BYTES:
|
|
1045
|
+
errors.add(
|
|
1046
|
+
prefix,
|
|
1047
|
+
f"is {content_bytes:,} UTF-8 bytes; maximum is "
|
|
1048
|
+
f"{MAX_CONTEXT_CONTENT_BYTES:,} bytes. Reduce content or omit "
|
|
1049
|
+
"optional tail if it contributes",
|
|
1050
|
+
)
|
|
1025
1051
|
return
|
|
1026
1052
|
try:
|
|
1027
1053
|
parsed = json.loads(content)
|
|
@@ -1030,11 +1056,10 @@ def _collect_context_content_errors(
|
|
|
1030
1056
|
# it as a checkpoint. It is still bounded above.
|
|
1031
1057
|
return
|
|
1032
1058
|
if isinstance(parsed, list) and key == "tail":
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
errors.add(f"{prefix}.tail", "exceeds its size limit")
|
|
1059
|
+
try:
|
|
1060
|
+
_validate_tail(parsed)
|
|
1061
|
+
except ValueError as exc:
|
|
1062
|
+
errors.reroot(prefix, str(exc))
|
|
1038
1063
|
return
|
|
1039
1064
|
if not isinstance(parsed, dict):
|
|
1040
1065
|
# The message already names 'content': do not prepend the path again.
|
|
@@ -1164,6 +1189,11 @@ def _upsert_context_entry(
|
|
|
1164
1189
|
name="context_save",
|
|
1165
1190
|
description="Save a context checkpoint for a session/phase. "
|
|
1166
1191
|
"Stores structured JSON in persistence KV with a key-specific TTL. "
|
|
1192
|
+
"The serialized content is limited to 65,536 UTF-8 bytes. An included "
|
|
1193
|
+
"tail may contain at most 100 strings, each at most 4,096 UTF-8 bytes, "
|
|
1194
|
+
"with at most 65,536 UTF-8 bytes across all tail strings. Oversized "
|
|
1195
|
+
"content or tail is rejected, never truncated; remove or omit optional "
|
|
1196
|
+
"tail data when applicable. "
|
|
1167
1197
|
"content is a JSON STRING; when it parses to an object, 'goal', 'phase', "
|
|
1168
1198
|
"'delegations' and 'heartbeat' must each be JSON OBJECTS and 'tail' must "
|
|
1169
1199
|
"be a JSON ARRAY. 'phase' is an object {current,total,name} — NOT a phase "
|
|
@@ -1180,7 +1210,12 @@ async def context_save(
|
|
|
1180
1210
|
str,
|
|
1181
1211
|
Field(
|
|
1182
1212
|
description=(
|
|
1183
|
-
"JSON checkpoint string
|
|
1213
|
+
"JSON checkpoint string, limited to 65,536 UTF-8 bytes. An "
|
|
1214
|
+
"included 'tail' may contain at most 100 strings, each at "
|
|
1215
|
+
"most 4,096 UTF-8 bytes, with at most 65,536 UTF-8 bytes "
|
|
1216
|
+
"across all tail strings. Oversized input is rejected, never "
|
|
1217
|
+
"truncated; remove or omit optional 'tail' when applicable. "
|
|
1218
|
+
"When it parses to an object, 'goal', "
|
|
1184
1219
|
"'phase', 'delegations' and 'heartbeat' must be objects and "
|
|
1185
1220
|
"'tail' must be an array; all are optional. 'phase' is an "
|
|
1186
1221
|
"object {current,total,name}, not a counter. Example: "
|
|
@@ -7,7 +7,7 @@ Provides MCP resources for the Pantheon agent framework:
|
|
|
7
7
|
plans/status, memory-bank files
|
|
8
8
|
|
|
9
9
|
Usage:
|
|
10
|
-
python scripts/
|
|
10
|
+
python scripts/mcp_resources.py
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
@@ -19,7 +19,7 @@ from typing import Any
|
|
|
19
19
|
import yaml
|
|
20
20
|
from _pantheon_paths import has_symlink_component, pantheon_home, pantheon_project
|
|
21
21
|
from eval_store import get_latest_eval, list_evals
|
|
22
|
-
from
|
|
22
|
+
from fastmcp import FastMCP
|
|
23
23
|
|
|
24
24
|
# ── Path Resolution ──────────────────────────────────────────────────────────
|
|
25
25
|
_PANTHEON_HOME: Path = pantheon_home()
|
|
@@ -19,7 +19,7 @@ Tools:
|
|
|
19
19
|
memory_stats — DB statistics
|
|
20
20
|
|
|
21
21
|
Usage:
|
|
22
|
-
python scripts/
|
|
22
|
+
python scripts/memory_mcp.py
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
25
|
from __future__ import annotations
|
|
@@ -34,7 +34,7 @@ from pathlib import Path
|
|
|
34
34
|
from typing import Annotated, Any
|
|
35
35
|
|
|
36
36
|
from _pantheon_paths import pantheon_home
|
|
37
|
-
from
|
|
37
|
+
from fastmcp import FastMCP
|
|
38
38
|
from pydantic import BeforeValidator, Field
|
|
39
39
|
|
|
40
40
|
try:
|