pantheon-opencode 1.5.0-beta.8 → 1.5.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.
Files changed (82) hide show
  1. package/AGENTS.md +14 -63
  2. package/CHANGELOG.md +320 -0
  3. package/README.md +14 -27
  4. package/README.pt-BR.md +5 -6
  5. package/commands/pantheon.md +1 -35
  6. package/package.json +1 -2
  7. package/plugin.json +1 -1
  8. package/pyproject.toml +2 -5
  9. package/scripts/doctor.mjs +32 -3
  10. package/scripts/install/plugin.mjs +9 -12
  11. package/scripts/mcp_persistence_server.py +1 -1
  12. package/scripts/sync-tui.mjs +8 -11
  13. package/src/agents/apollo.md +1 -0
  14. package/src/agents/gaia.md +1 -0
  15. package/src/agents/zeus.md +9 -52
  16. package/src/instructions/memory-protocol.instructions.md +6 -3
  17. package/src/instructions/zeus-anti-stall.instructions.md +2 -4
  18. package/src/instructions/zeus-council-synthesis.instructions.md +3 -28
  19. package/src/instructions/zeus-timeout-retry.instructions.md +3 -28
  20. package/src/mcp/mcp_persistence_server.py +1 -1
  21. package/src/mcp/toon_codec.py +2 -4
  22. package/src/pantheon/background-job-board.ts +4 -4
  23. package/src/pantheon/{delegation-compaction.ts → compaction-context.ts} +10 -100
  24. package/src/pantheon/cost-command.ts +1 -2
  25. package/src/pantheon/delegation-enforce.ts +59 -14
  26. package/src/pantheon/goal-loop.ts +1 -1
  27. package/src/pantheon/goal-store.ts +1 -1
  28. package/src/pantheon/idle-continuation.ts +4 -6
  29. package/src/pantheon/model-command.ts +1 -2
  30. package/src/pantheon/native-task-status.ts +2 -2
  31. package/src/pantheon/presets.d.mts +0 -20
  32. package/src/pantheon/presets.mjs +0 -64
  33. package/src/pantheon/session-guard.ts +2 -2
  34. package/src/pantheon/session-id.ts +30 -0
  35. package/src/pantheon/task-result-guard.ts +2 -3
  36. package/src/pantheon/todo-enforcer.ts +3 -3
  37. package/src/pantheon/tool-context.ts +23 -0
  38. package/src/pantheon/v2-bridge.ts +1 -4
  39. package/src/plugin-v2.ts +8 -21
  40. package/src/plugin.ts +61 -245
  41. package/src/plugins/pantheon-hooks.ts +1 -1
  42. package/src/plugins/tui/dist/tui.d.ts +229 -77
  43. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  44. package/src/plugins/tui/dist/tui.js +509 -259
  45. package/src/plugins/tui/package-lock.json +2 -2
  46. package/src/plugins/tui/package.json +2 -2
  47. package/src/plugins/tui/src/index.tsx +753 -279
  48. package/src/routing.yml +0 -16
  49. package/src/skills/context-compression/SKILL.md +1 -1
  50. package/scripts/generate-preset-docs.mjs +0 -300
  51. package/scripts/generate-prompts.sh +0 -222
  52. package/scripts/hash_verify.py +0 -192
  53. package/scripts/install/component.mjs +0 -24
  54. package/scripts/install/migrate-config.mjs +0 -302
  55. package/scripts/test-context-compression.sh +0 -169
  56. package/src/pantheon/auto-wake.ts +0 -85
  57. package/src/pantheon/chat-reminders.ts +0 -9
  58. package/src/pantheon/comment-checker.ts +0 -48
  59. package/src/pantheon/compaction-assert.ts +0 -160
  60. package/src/pantheon/compaction-handoff.ts +0 -304
  61. package/src/pantheon/cost-tracker.ts +0 -108
  62. package/src/pantheon/delegate-manager.ts +0 -766
  63. package/src/pantheon/delegation-classifier.ts +0 -307
  64. package/src/pantheon/delegation-finalize.ts +0 -406
  65. package/src/pantheon/delegation-notify.ts +0 -212
  66. package/src/pantheon/delegation-toast.ts +0 -73
  67. package/src/pantheon/delegation.ts +0 -1337
  68. package/src/pantheon/dispatch-guard.ts +0 -109
  69. package/src/pantheon/native-probe.ts +0 -234
  70. package/src/pantheon/permission-eval.ts +0 -284
  71. package/src/pantheon/preemptive-compact.ts +0 -76
  72. package/src/pantheon/provider-capabilities.ts +0 -221
  73. package/src/pantheon/provider-stream-tracker.ts +0 -182
  74. package/src/pantheon/retry-policy.ts +0 -212
  75. package/src/pantheon/step-cap.ts +0 -110
  76. package/src/pantheon/token-opt.ts +0 -689
  77. package/src/pantheon/toon-codec.ts +0 -481
  78. package/src/pantheon/v2-events.ts +0 -148
  79. package/src/pantheon/v2-hooks.ts +0 -287
  80. package/src/pantheon/v2-tool-definitions.ts +0 -331
  81. package/src/pantheon/zeus-delegate-with-retry.ts +0 -406
  82. package/src/plugins/tui/dist/tui.tsx +0 -2777
@@ -1,287 +0,0 @@
1
- /**
2
- * V2 Session Hooks — Pantheon session hooks for the V2 plugin API.
3
- *
4
- * Provides two hook types:
5
- * - `"prompt"` hook: Vision message interception (paste-and-ask). Intercepts
6
- * user messages with pasted images and replaces them with text instructions
7
- * or native vision descriptions.
8
- * - `"context"` hook: Inject routing policy, active goals, and pending todos
9
- * into the system context before each LLM call.
10
- *
11
- * These handlers are PURE — they depend only on structural interfaces.
12
- *
13
- * @module pantheon/v2-hooks
14
- */
15
-
16
- import type { BackgroundJobBoard } from './background-job-board.ts'
17
- import { buildCompactionContext } from './delegation-compaction.ts'
18
- import type { GoalStore } from './goal-loop.ts'
19
- import { createPantheonLogger } from './logger.ts'
20
- import type { TodoEnforcer } from './todo-enforcer.ts'
21
-
22
- const log = createPantheonLogger({ module: 'pantheon-v2-hooks' })
23
-
24
- // ─── Types ───────────────────────────────────────────────────────────────
25
-
26
- /**
27
- * Structural context event passed to the "context" hook.
28
- * V2 API: `ctx.session.hook("context", (event) => { ... })`
29
- */
30
- export interface V2ContextHookEvent {
31
- sessionID: string
32
- // Unknown: host beta may send string, string[], SystemPart objects
33
- // ({type,text}), mixed arrays, or non-array. Narrow internally (fail-open).
34
- system: unknown
35
- generation: {
36
- temperature?: number
37
- }
38
- }
39
-
40
- /**
41
- * Structural prompt event passed to the "prompt" hook.
42
- * V2 API: `ctx.session.hook("prompt", (event) => { ... })`
43
- */
44
- export interface V2PromptHookEvent {
45
- sessionID: string
46
- message: unknown
47
- }
48
-
49
- /**
50
- * Dependencies for session hooks.
51
- */
52
- export interface V2HookDeps {
53
- board: BackgroundJobBoard
54
- goalStore: GoalStore
55
- todoEnforcer: TodoEnforcer
56
- }
57
-
58
- // ─── Context Hook ────────────────────────────────────────────────────────
59
-
60
- const POLICY_MARKER = '<!-- pantheon-v2-policy -->'
61
- const ROUTING_POLICY =
62
- `${POLICY_MARKER}\nFollow Pantheon routing policy: delegate implementation work ` +
63
- `to the named specialist and do not claim work was performed without verification.`
64
-
65
- /** Default max compaction items (matching routing.yml background_delegation.max_compaction_items). */
66
- const DEFAULT_MAX_COMPACTION_ITEMS = 10
67
-
68
- /**
69
- * Extract comparable text from a system entry: plain string or
70
- * SystemPart-like object ({type,text}). Returns null for junk (null/number).
71
- * Runtime sniffing: pinned SDK (@opencode-ai/plugin 1.18.18) only knows
72
- * string/string[] — host beta sends objects. Never throws (fail-open).
73
- */
74
- function systemEntryText(entry: unknown): string | null {
75
- try {
76
- if (typeof entry === 'string') return entry
77
- if (
78
- typeof entry === 'object' &&
79
- entry !== null &&
80
- typeof (entry as { text?: unknown }).text === 'string'
81
- ) {
82
- return (entry as { text: string }).text
83
- }
84
- return null
85
- } catch {
86
- return null
87
- }
88
- }
89
-
90
- function hasPolicyMarker(arr: unknown[]): boolean {
91
- try {
92
- return arr.some((s) => {
93
- const t = systemEntryText(s)
94
- return t?.includes(POLICY_MARKER) ?? false
95
- })
96
- } catch {
97
- return false
98
- }
99
- }
100
-
101
- function usesObjectShape(arr: unknown[]): boolean {
102
- try {
103
- return arr.some(
104
- (s) =>
105
- typeof s === 'object' && s !== null && typeof (s as { text?: unknown }).text === 'string',
106
- )
107
- } catch {
108
- return false
109
- }
110
- }
111
-
112
- function toSystemEntry(text: string, useObject: boolean): string | { type: 'text'; text: string } {
113
- return useObject ? { type: 'text', text } : text
114
- }
115
-
116
- /**
117
- * Context hook handler — injects Pantheon policy, routing, and compaction
118
- * state into the system context before each LLM call.
119
- *
120
- * Registered via: `ctx.session.hook("context", handler)`
121
- */
122
- export function createV2ContextHookHandler(deps: V2HookDeps) {
123
- return async (event: V2ContextHookEvent): Promise<void> => {
124
- try {
125
- // Beta 19192 hardening (defense-in-depth) + SystemPart sniffing: the
126
- // host may send string[], SystemPart objects ({type,text}), mixed
127
- // arrays, a single string, or a non-array system. Preserve the string
128
- // path behavior; inject object shape when the array contains objects
129
- // (else host schema validation fails on system[N]). Never throw.
130
- const rawSystem: unknown = (event as { system?: unknown } | null | undefined)?.system
131
- let system: unknown[]
132
- if (typeof rawSystem === 'string') {
133
- system = rawSystem.includes(POLICY_MARKER) ? [rawSystem] : [rawSystem, ROUTING_POLICY]
134
- ;(event as { system?: unknown }).system = system
135
- } else if (Array.isArray(rawSystem)) {
136
- // 1. Inject routing policy if not already present (string OU .text)
137
- if (!hasPolicyMarker(rawSystem)) {
138
- rawSystem.push(toSystemEntry(ROUTING_POLICY, usesObjectShape(rawSystem)))
139
- }
140
- system = rawSystem
141
- } else {
142
- // Non-string, non-array system: ignore silently (fail-open).
143
- return
144
- }
145
-
146
- // 2. Inject compaction context (active goals, pending todos, delegations)
147
- // Convert blocks to the same shape as the host array (object vs string).
148
- const blocks = await buildCompactionContext(deps.board, {
149
- sessionID: event.sessionID,
150
- maxItems: DEFAULT_MAX_COMPACTION_ITEMS,
151
- goals: {
152
- enabled: true,
153
- list: (sessionID: string) => deps.goalStore.list(sessionID),
154
- },
155
- todos: {
156
- enabled: true,
157
- list: (sessionID: string) => deps.todoEnforcer.listPendingTodos(sessionID),
158
- },
159
- })
160
- if (blocks.length > 0) {
161
- const useObject = usesObjectShape(system)
162
- for (const b of blocks) {
163
- system.push(useObject ? { type: 'text' as const, text: b } : b)
164
- }
165
- }
166
-
167
- // 3. Apply conservative temperature for routing decisions
168
- const generation = (event as { generation?: { temperature?: number } }).generation
169
- if (generation != null && generation.temperature === undefined) {
170
- generation.temperature = 0.2
171
- }
172
- } catch (err) {
173
- log.warn('[Pantheon V2] Context hook failed:', err)
174
- // Fail-open: never break the session
175
- }
176
- }
177
- }
178
-
179
- // ─── Prompt Hook ─────────────────────────────────────────────────────────
180
-
181
- /**
182
- * Prompt hook handler — intercepts user messages for vision processing.
183
- *
184
- * Registered via: `ctx.session.hook("prompt", handler)`
185
- *
186
- * Note: The full vision handler is complex (file I/O, provider API calls).
187
- * This is a minimal adapter that delegates to the V1 vision handler
188
- * if available. Without vision infrastructure, it's a no-op.
189
- */
190
- export function createV2PromptHookHandler(_deps: V2HookDeps) {
191
- return async (event: V2PromptHookEvent): Promise<void> => {
192
- // Vision interception is a complex subsystem (see src/pantheon/vision.ts).
193
- // The V2 prompt hook delegates to the V1 vision handler via the plugin's
194
- // integration point. Without V1 client access, this is a graceful no-op.
195
- //
196
- // TODO: Wire full vision handler when V2 provides SDK client access.
197
- void event
198
- }
199
- }
200
-
201
- // ─── Tool Hooks ──────────────────────────────────────────────────────────
202
-
203
- /**
204
- * Tool execute.before hook — enforces read-only restrictions, command
205
- * normalization, and todo preservation.
206
- *
207
- * Registered via: `ctx.tool.hook("execute.before", handler)`
208
- */
209
- export interface V2ToolBeforeEvent {
210
- tool: string
211
- sessionID: string
212
- callID: string
213
- args?: unknown
214
- }
215
-
216
- export function createV2ToolBeforeHookHandler(
217
- enforcementGuard: (
218
- input: { tool: string; sessionID: string; callID: string },
219
- output?: { args?: unknown },
220
- ) => void,
221
- commandNormalizer: (
222
- input: { tool: string; sessionID: string; callID: string },
223
- output?: { args?: unknown },
224
- ) => Promise<void>,
225
- ) {
226
- return async (event: V2ToolBeforeEvent): Promise<void> => {
227
- try {
228
- enforcementGuard(
229
- { tool: event.tool, sessionID: event.sessionID, callID: event.callID },
230
- { args: event.args },
231
- )
232
- await commandNormalizer(
233
- { tool: event.tool, sessionID: event.sessionID, callID: event.callID },
234
- { args: event.args },
235
- )
236
- } catch (err) {
237
- log.warn('[Pantheon V2] Tool before-hook failed:', err)
238
- }
239
- }
240
- }
241
-
242
- /**
243
- * Tool execute.after hook — augments read output with hashline tags
244
- * and applies context sandbox truncation.
245
- *
246
- * Registered via: `ctx.tool.hook("execute.after", handler)`
247
- */
248
- export interface V2ToolAfterEvent {
249
- tool: string
250
- sessionID: string
251
- callID: string
252
- args?: unknown
253
- // The host may send a non-string output (shape drift on beta). Keep this
254
- // honest as unknown and narrow with typeof at the use site — never assume.
255
- output: unknown
256
- }
257
-
258
- export function createV2ToolAfterHookHandler(
259
- readEnhancer: (
260
- input: { tool: string; sessionID: string; callID: string; args?: unknown },
261
- output: { output: string },
262
- ) => Promise<void>,
263
- sandboxHandler: (
264
- input: { tool: string; sessionID: string; callID: string; args?: unknown },
265
- output: { output: string },
266
- ) => Promise<void>,
267
- ) {
268
- return async (event: V2ToolAfterEvent): Promise<void> => {
269
- try {
270
- const input = {
271
- tool: event.tool,
272
- sessionID: event.sessionID,
273
- callID: event.callID,
274
- args: event.args,
275
- }
276
- // Narrow the honest unknown: only strings flow through the enhancers.
277
- // Non-string output is left untouched (fail-open, preserve host shape).
278
- if (typeof event.output !== 'string') return
279
- const output = { output: event.output }
280
- await sandboxHandler(input, output)
281
- await readEnhancer(input, output)
282
- event.output = output.output
283
- } catch (err) {
284
- log.warn('[Pantheon V2] Tool after-hook failed:', err)
285
- }
286
- }
287
- }
@@ -1,331 +0,0 @@
1
- /**
2
- * V2 Tool Definitions — the 9 Pantheon orchestration tools adapted for the
3
- * V2 plugin API. Each tool wraps existing V1 infrastructure (delegation,
4
- * goal-loop, hashline, cost-command, model-command) into a unified
5
- * `{ name, description, input, execute }` shape compatible with V2's
6
- * `ctx.tool.transform()`.
7
- *
8
- * These definitions are PURE — they don't import any V1 plugin types.
9
- * The execute functions use a structural `ToolContextLike` surface that
10
- * both V1 and V2 can satisfy.
11
- *
12
- * @module pantheon/v2-tool-definitions
13
- */
14
-
15
- import type { z } from 'zod'
16
- import type { CostCommand } from './cost-command.ts'
17
- import type { DelegationToolset } from './delegation.ts'
18
- import type { GoalToolset } from './goal-loop.ts'
19
- import type { ModelToolset } from './model-command.ts'
20
-
21
- // ─── Structural Context ──────────────────────────────────────────────────
22
-
23
- /**
24
- * Minimal structural context passed to V2 tool execute functions.
25
- * Matches V1's ToolContextLike but avoids importing V1 types.
26
- */
27
- export interface V2ToolContext {
28
- sessionID: string
29
- directory?: string
30
- worktree?: string
31
- agent?: string
32
- }
33
-
34
- /**
35
- * A V2-compatible tool definition: name + description + JSON-Schema input
36
- * + async execute function.
37
- */
38
- export interface V2ToolDefinition {
39
- name: string
40
- description: string
41
- input: {
42
- type: 'object'
43
- properties: Record<string, unknown>
44
- required?: string[]
45
- }
46
- execute: (input: Record<string, unknown>, context: V2ToolContext) => Promise<string>
47
- }
48
-
49
- // ─── Zod → JSON-Schema Helpers ──────────────────────────────────────────
50
-
51
- /**
52
- * Convert a zod ZodRawShape to a minimal JSON-Schema properties object.
53
- * Uses safe introspection: checks for `.describe()` and basic shape keys.
54
- * Falls back to `{ type: "string" }` for unrecognizable schemas.
55
- */
56
- function zodShapeToJsonSchema(
57
- shape: z.ZodRawShape,
58
- required: string[] = [],
59
- ): { properties: Record<string, unknown>; required?: string[] } {
60
- const properties: Record<string, unknown> = {}
61
- for (const [key, schema] of Object.entries(shape)) {
62
- const prop: Record<string, unknown> = {}
63
-
64
- // Get description via .describe() if available
65
- try {
66
- const schemaAsObj = schema as unknown as Record<string, unknown>
67
- const describeFn = schemaAsObj.describe
68
- if (typeof describeFn === 'function') {
69
- const desc = (describeFn as () => string).call(schemaAsObj)
70
- if (typeof desc === 'string' && desc !== '') {
71
- prop.description = desc
72
- }
73
- }
74
- } catch {
75
- // Some zod types may throw on describe()
76
- }
77
-
78
- // Detect type from constructor name or _def.type (works across zod versions)
79
- const typeName = schema.constructor?.name ?? ''
80
- const defObj = (schema as unknown as { _def?: Record<string, unknown> })?._def
81
- const defType = (defObj?.typeName as string) ?? ''
82
-
83
- if (typeName.includes('ZodString') || defType === 'ZodString') {
84
- prop.type = 'string'
85
- } else if (typeName.includes('ZodNumber') || defType === 'ZodNumber') {
86
- prop.type = 'number'
87
- } else if (typeName.includes('ZodBoolean') || defType === 'ZodBoolean') {
88
- prop.type = 'boolean'
89
- } else if (typeName.includes('ZodEnum') || defType === 'ZodEnum') {
90
- prop.type = 'string'
91
- // Safely extract enum values
92
- try {
93
- const schemaObj = schema as unknown as Record<string, unknown>
94
- const defObj = schemaObj._def as Record<string, unknown> | undefined
95
- const values = (schemaObj.options ?? defObj?.values) as string[] | undefined
96
- if (Array.isArray(values)) prop.enum = values
97
- } catch {
98
- /* ignore */
99
- }
100
- } else if (typeName.includes('ZodArray') || defType === 'ZodArray') {
101
- prop.type = 'array'
102
- } else if (typeName.includes('ZodOptional') || defType === 'ZodOptional') {
103
- // Optional wrappers — treat as string by default
104
- prop.type = 'string'
105
- } else {
106
- prop.type = 'string'
107
- }
108
-
109
- properties[key] = prop
110
- }
111
-
112
- const result: { properties: Record<string, unknown>; required?: string[] } = { properties }
113
- if (required.length > 0) {
114
- result.required = required
115
- }
116
- return result
117
- }
118
-
119
- // ─── V2 Tool Factory ────────────────────────────────────────────────────
120
-
121
- export interface V2ToolFactoryDeps {
122
- delegation: DelegationToolset
123
- goalTools: GoalToolset
124
- costCommand: CostCommand
125
- modelCommand: ModelToolset
126
- }
127
-
128
- /**
129
- * Create all 9 V2 tool definitions from the V1 infrastructure.
130
- * These can be registered via `ctx.tool.transform()` or used directly.
131
- */
132
- export function createV2ToolDefinitions(deps: V2ToolFactoryDeps): V2ToolDefinition[] {
133
- const { delegation, goalTools, costCommand, modelCommand } = deps
134
-
135
- return [
136
- // 1. pantheon_delegate
137
- {
138
- name: 'pantheon_delegate',
139
- description: delegation.pantheon_delegate.description,
140
- input: {
141
- type: 'object',
142
- ...zodShapeToJsonSchema(delegation.pantheon_delegate.args as z.ZodRawShape, [
143
- 'prompt',
144
- 'agent',
145
- ]),
146
- },
147
- execute: async (input, ctx) => {
148
- return delegation.pantheon_delegate.execute(
149
- input as Parameters<typeof delegation.pantheon_delegate.execute>[0],
150
- ctx,
151
- )
152
- },
153
- },
154
-
155
- // 2. pantheon_delegation_read
156
- {
157
- name: 'pantheon_delegation_read',
158
- description: delegation.pantheon_delegation_read.description,
159
- input: {
160
- type: 'object',
161
- ...zodShapeToJsonSchema(delegation.pantheon_delegation_read.args as z.ZodRawShape, ['id']),
162
- },
163
- execute: async (input, ctx) => {
164
- return delegation.pantheon_delegation_read.execute(
165
- input as Parameters<typeof delegation.pantheon_delegation_read.execute>[0],
166
- ctx,
167
- )
168
- },
169
- },
170
-
171
- // 3. pantheon_delegation_list
172
- {
173
- name: 'pantheon_delegation_list',
174
- description: delegation.pantheon_delegation_list.description,
175
- input: {
176
- type: 'object',
177
- properties: {},
178
- },
179
- execute: async (input, ctx) => {
180
- return delegation.pantheon_delegation_list.execute(
181
- input as Parameters<typeof delegation.pantheon_delegation_list.execute>[0],
182
- ctx,
183
- )
184
- },
185
- },
186
-
187
- // 4. hashline_edit
188
- {
189
- name: 'hashline_edit',
190
- description:
191
- 'Edit a file anchored by hashline refs (LINE#TAG) instead of raw line numbers. ' +
192
- 'Ops: replace (ref..endRef or single ref → lines), append/prepend (anchor ref → content), ' +
193
- 'delete (ref..endRef). ALL refs must be validated against the ORIGINAL file before anything ' +
194
- 'is written; on mismatch the tool returns an error with a re-tagged excerpt and a ' +
195
- 'Did-you-mean suggestion, and nothing is modified.',
196
- input: {
197
- type: 'object',
198
- properties: {
199
- file: { type: 'string', description: 'Absolute path to the file to edit.' },
200
- edits: {
201
- type: 'array',
202
- description: 'List of edit operations to apply.',
203
- items: {
204
- type: 'object',
205
- properties: {
206
- op: {
207
- type: 'string',
208
- enum: ['replace', 'append', 'prepend', 'delete'],
209
- description: 'The edit operation.',
210
- },
211
- ref: {
212
- type: 'string',
213
- description: 'Anchor ref "LINE#TAG" against the ORIGINAL snapshot.',
214
- },
215
- endRef: {
216
- type: 'string',
217
- description: 'Optional range end for replace/delete ("LINE#TAG").',
218
- },
219
- lines: {
220
- type: 'array',
221
- items: { type: 'string' },
222
- description: 'Replacement lines (replace).',
223
- },
224
- content: {
225
- type: 'string',
226
- description: 'Text to insert (append/prepend; split on newlines).',
227
- },
228
- },
229
- required: ['op', 'ref'],
230
- },
231
- },
232
- },
233
- required: ['file', 'edits'],
234
- },
235
- execute: async (input, ctx) => {
236
- // hashline_edit uses a different execute signature — it takes (args, toolContext)
237
- // where toolContext includes sessionID, directory, worktree
238
- const { createHashlineEditTool } = await import('./hashline/tool.ts')
239
- const tool = createHashlineEditTool()
240
- const result = await tool.execute(
241
- input as Parameters<typeof tool.execute>[0],
242
- ctx as Parameters<typeof tool.execute>[1],
243
- )
244
- if (typeof result === 'string') return result
245
- return result.output
246
- },
247
- },
248
-
249
- // 5. pantheon_goal_create
250
- {
251
- name: 'pantheon_goal_create',
252
- description: goalTools.pantheon_goal_create.description,
253
- input: {
254
- type: 'object',
255
- ...zodShapeToJsonSchema(goalTools.pantheon_goal_create.args as z.ZodRawShape, [
256
- 'objective',
257
- ]),
258
- },
259
- execute: async (input, ctx) => {
260
- return goalTools.pantheon_goal_create.execute(
261
- input as Parameters<typeof goalTools.pantheon_goal_create.execute>[0],
262
- ctx,
263
- )
264
- },
265
- },
266
-
267
- // 6. pantheon_goal_get
268
- {
269
- name: 'pantheon_goal_get',
270
- description: goalTools.pantheon_goal_get.description,
271
- input: {
272
- type: 'object',
273
- properties: {},
274
- },
275
- execute: async (input, ctx) => {
276
- return goalTools.pantheon_goal_get.execute(
277
- input as Parameters<typeof goalTools.pantheon_goal_get.execute>[0],
278
- ctx,
279
- )
280
- },
281
- },
282
-
283
- // 7. pantheon_goal_update
284
- {
285
- name: 'pantheon_goal_update',
286
- description: goalTools.pantheon_goal_update.description,
287
- input: {
288
- type: 'object',
289
- ...zodShapeToJsonSchema(goalTools.pantheon_goal_update.args as z.ZodRawShape),
290
- },
291
- execute: async (input, ctx) => {
292
- return goalTools.pantheon_goal_update.execute(
293
- input as Parameters<typeof goalTools.pantheon_goal_update.execute>[0],
294
- ctx,
295
- )
296
- },
297
- },
298
-
299
- // 8. pantheon_cost
300
- {
301
- name: 'pantheon_cost',
302
- description: costCommand.pantheon_cost.description,
303
- input: {
304
- type: 'object',
305
- ...zodShapeToJsonSchema(costCommand.pantheon_cost.args as z.ZodRawShape),
306
- },
307
- execute: async (input, ctx) => {
308
- return costCommand.pantheon_cost.execute(
309
- input as Parameters<typeof costCommand.pantheon_cost.execute>[0],
310
- ctx,
311
- )
312
- },
313
- },
314
-
315
- // 9. pantheon_model
316
- {
317
- name: 'pantheon_model',
318
- description: modelCommand.pantheon_model.description,
319
- input: {
320
- type: 'object',
321
- ...zodShapeToJsonSchema(modelCommand.pantheon_model.args as z.ZodRawShape),
322
- },
323
- execute: async (input, ctx) => {
324
- return modelCommand.pantheon_model.execute(
325
- input as Parameters<typeof modelCommand.pantheon_model.execute>[0],
326
- ctx,
327
- )
328
- },
329
- },
330
- ]
331
- }