opencastle 0.16.0 → 0.17.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/dist/cli/convoy/engine.d.ts.map +1 -1
- package/dist/cli/convoy/engine.js +32 -9
- package/dist/cli/convoy/engine.js.map +1 -1
- package/dist/cli/convoy/engine.test.js +104 -1
- package/dist/cli/convoy/engine.test.js.map +1 -1
- package/dist/cli/convoy/health.test.js +1 -0
- package/dist/cli/convoy/health.test.js.map +1 -1
- package/dist/cli/convoy/store.d.ts.map +1 -1
- package/dist/cli/convoy/store.js +8 -3
- package/dist/cli/convoy/store.js.map +1 -1
- package/dist/cli/convoy/store.test.js +83 -3
- package/dist/cli/convoy/store.test.js.map +1 -1
- package/dist/cli/convoy/types.d.ts +1 -0
- package/dist/cli/convoy/types.d.ts.map +1 -1
- package/dist/cli/run/adapters/index.d.ts.map +1 -1
- package/dist/cli/run/adapters/index.js +2 -1
- package/dist/cli/run/adapters/index.js.map +1 -1
- package/dist/cli/run/adapters/opencode.d.ts +16 -0
- package/dist/cli/run/adapters/opencode.d.ts.map +1 -0
- package/dist/cli/run/adapters/opencode.js +75 -0
- package/dist/cli/run/adapters/opencode.js.map +1 -0
- package/dist/cli/run/schema.d.ts.map +1 -1
- package/dist/cli/run/schema.js +11 -0
- package/dist/cli/run/schema.js.map +1 -1
- package/dist/cli/run/schema.test.js +44 -0
- package/dist/cli/run/schema.test.js.map +1 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +2 -0
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/types.d.ts +3 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli/convoy/engine.test.ts +126 -1
- package/src/cli/convoy/engine.ts +30 -7
- package/src/cli/convoy/health.test.ts +1 -0
- package/src/cli/convoy/store.test.ts +89 -3
- package/src/cli/convoy/store.ts +8 -3
- package/src/cli/convoy/types.ts +1 -0
- package/src/cli/run/adapters/index.ts +2 -1
- package/src/cli/run/adapters/opencode.ts +88 -0
- package/src/cli/run/schema.test.ts +50 -0
- package/src/cli/run/schema.ts +13 -0
- package/src/cli/run.ts +3 -0
- package/src/cli/types.ts +3 -0
- package/src/dashboard/node_modules/.vite/deps/_metadata.json +6 -6
|
@@ -43,6 +43,7 @@ function makeTask(overrides: Partial<Parameters<ConvoyStore['insertTask']>[0]> =
|
|
|
43
43
|
phase: 0,
|
|
44
44
|
prompt: 'Do something',
|
|
45
45
|
agent: 'developer',
|
|
46
|
+
adapter: null as string | null,
|
|
46
47
|
model: null,
|
|
47
48
|
timeout_ms: 1_800_000,
|
|
48
49
|
status: 'pending' as const,
|
|
@@ -83,11 +84,11 @@ describe('DB creation', () => {
|
|
|
83
84
|
expect(row.journal_mode).toBe('wal')
|
|
84
85
|
})
|
|
85
86
|
|
|
86
|
-
it('sets schema version to
|
|
87
|
+
it('sets schema version to 2', () => {
|
|
87
88
|
const db = new DatabaseSync(dbPath)
|
|
88
89
|
const row = db.prepare('PRAGMA user_version').get() as { user_version: number }
|
|
89
90
|
db.close()
|
|
90
|
-
expect(row.user_version).toBe(
|
|
91
|
+
expect(row.user_version).toBe(2)
|
|
91
92
|
})
|
|
92
93
|
|
|
93
94
|
it('creates all required tables', () => {
|
|
@@ -112,7 +113,86 @@ describe('DB creation', () => {
|
|
|
112
113
|
store2.close()
|
|
113
114
|
// Reassign so afterEach does not double-close
|
|
114
115
|
store = createConvoyStore(dbPath)
|
|
115
|
-
expect(row.user_version).toBe(
|
|
116
|
+
expect(row.user_version).toBe(2)
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
// ── schema migration ─────────────────────────────────────────────────────────
|
|
121
|
+
|
|
122
|
+
describe('schema migration', () => {
|
|
123
|
+
it('schema migration v1 to v2 adds adapter column', () => {
|
|
124
|
+
// Create a v1 database manually: task table without adapter column
|
|
125
|
+
const v1DbPath = join(tmpDir, 'v1.db')
|
|
126
|
+
const rawDb = new DatabaseSync(v1DbPath)
|
|
127
|
+
rawDb.exec(`
|
|
128
|
+
CREATE TABLE convoy (
|
|
129
|
+
id TEXT PRIMARY KEY,
|
|
130
|
+
name TEXT NOT NULL,
|
|
131
|
+
spec_hash TEXT NOT NULL,
|
|
132
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
133
|
+
branch TEXT,
|
|
134
|
+
created_at TEXT NOT NULL,
|
|
135
|
+
started_at TEXT,
|
|
136
|
+
finished_at TEXT,
|
|
137
|
+
spec_yaml TEXT NOT NULL
|
|
138
|
+
);
|
|
139
|
+
CREATE TABLE task (
|
|
140
|
+
id TEXT PRIMARY KEY,
|
|
141
|
+
convoy_id TEXT NOT NULL REFERENCES convoy(id),
|
|
142
|
+
phase INTEGER NOT NULL,
|
|
143
|
+
prompt TEXT NOT NULL,
|
|
144
|
+
agent TEXT NOT NULL DEFAULT 'developer',
|
|
145
|
+
model TEXT,
|
|
146
|
+
timeout_ms INTEGER NOT NULL DEFAULT 1800000,
|
|
147
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
148
|
+
worker_id TEXT,
|
|
149
|
+
worktree TEXT,
|
|
150
|
+
output TEXT,
|
|
151
|
+
exit_code INTEGER,
|
|
152
|
+
started_at TEXT,
|
|
153
|
+
finished_at TEXT,
|
|
154
|
+
retries INTEGER NOT NULL DEFAULT 0,
|
|
155
|
+
max_retries INTEGER NOT NULL DEFAULT 1,
|
|
156
|
+
files TEXT,
|
|
157
|
+
depends_on TEXT
|
|
158
|
+
);
|
|
159
|
+
CREATE TABLE worker (
|
|
160
|
+
id TEXT PRIMARY KEY,
|
|
161
|
+
task_id TEXT REFERENCES task(id),
|
|
162
|
+
adapter TEXT NOT NULL,
|
|
163
|
+
pid INTEGER,
|
|
164
|
+
session_id TEXT,
|
|
165
|
+
status TEXT NOT NULL DEFAULT 'spawned',
|
|
166
|
+
worktree TEXT,
|
|
167
|
+
created_at TEXT NOT NULL,
|
|
168
|
+
finished_at TEXT,
|
|
169
|
+
last_heartbeat TEXT
|
|
170
|
+
);
|
|
171
|
+
CREATE TABLE event (
|
|
172
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
173
|
+
convoy_id TEXT REFERENCES convoy(id),
|
|
174
|
+
task_id TEXT,
|
|
175
|
+
worker_id TEXT,
|
|
176
|
+
type TEXT NOT NULL,
|
|
177
|
+
data TEXT,
|
|
178
|
+
created_at TEXT NOT NULL
|
|
179
|
+
);
|
|
180
|
+
`)
|
|
181
|
+
rawDb.exec('PRAGMA user_version = 1')
|
|
182
|
+
rawDb.close()
|
|
183
|
+
|
|
184
|
+
// Open with createConvoyStore — should apply the v1→v2 migration
|
|
185
|
+
const v1Store = createConvoyStore(v1DbPath)
|
|
186
|
+
v1Store.close()
|
|
187
|
+
|
|
188
|
+
// Verify adapter column was added to task table
|
|
189
|
+
const verifyDb = new DatabaseSync(v1DbPath)
|
|
190
|
+
const cols = verifyDb.prepare('PRAGMA table_info(task)').all() as Array<{ name: string }>
|
|
191
|
+
const version = verifyDb.prepare('PRAGMA user_version').get() as { user_version: number }
|
|
192
|
+
verifyDb.close()
|
|
193
|
+
|
|
194
|
+
expect(cols.map(c => c.name)).toContain('adapter')
|
|
195
|
+
expect(version.user_version).toBe(2)
|
|
116
196
|
})
|
|
117
197
|
})
|
|
118
198
|
|
|
@@ -182,6 +262,12 @@ describe('task CRUD', () => {
|
|
|
182
262
|
expect(store.getTask('does-not-exist', 'convoy-1')).toBeUndefined()
|
|
183
263
|
})
|
|
184
264
|
|
|
265
|
+
it('insertTask stores adapter field', () => {
|
|
266
|
+
store.insertTask(makeTask({ adapter: 'opencode' }))
|
|
267
|
+
const retrieved = store.getTask('task-1', 'convoy-1')!
|
|
268
|
+
expect(retrieved.adapter).toBe('opencode')
|
|
269
|
+
})
|
|
270
|
+
|
|
185
271
|
it('stores JSON fields as strings', () => {
|
|
186
272
|
const task = makeTask({
|
|
187
273
|
id: 'task-json',
|
package/src/cli/convoy/store.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
EventRecord,
|
|
10
10
|
} from './types.js'
|
|
11
11
|
|
|
12
|
-
const SCHEMA_VERSION =
|
|
12
|
+
const SCHEMA_VERSION = 2
|
|
13
13
|
|
|
14
14
|
export interface ConvoyStore {
|
|
15
15
|
insertConvoy(record: Omit<ConvoyRecord, 'started_at' | 'finished_at'>): void
|
|
@@ -82,6 +82,7 @@ class ConvoyStoreImpl implements ConvoyStore {
|
|
|
82
82
|
phase INTEGER NOT NULL,
|
|
83
83
|
prompt TEXT NOT NULL,
|
|
84
84
|
agent TEXT NOT NULL DEFAULT 'developer',
|
|
85
|
+
adapter TEXT,
|
|
85
86
|
model TEXT,
|
|
86
87
|
timeout_ms INTEGER NOT NULL DEFAULT 1800000,
|
|
87
88
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
@@ -122,6 +123,10 @@ class ConvoyStoreImpl implements ConvoyStore {
|
|
|
122
123
|
`)
|
|
123
124
|
this.db.exec(`PRAGMA user_version = ${SCHEMA_VERSION}`)
|
|
124
125
|
}
|
|
126
|
+
if (row.user_version === 1) {
|
|
127
|
+
this.db.exec('ALTER TABLE task ADD COLUMN adapter TEXT')
|
|
128
|
+
this.db.exec('PRAGMA user_version = 2')
|
|
129
|
+
}
|
|
125
130
|
}
|
|
126
131
|
|
|
127
132
|
insertConvoy(record: Omit<ConvoyRecord, 'started_at' | 'finished_at'>): void {
|
|
@@ -174,11 +179,11 @@ class ConvoyStoreImpl implements ConvoyStore {
|
|
|
174
179
|
this.db
|
|
175
180
|
.prepare(
|
|
176
181
|
`INSERT INTO task
|
|
177
|
-
(id, convoy_id, phase, prompt, agent, model, timeout_ms, status,
|
|
182
|
+
(id, convoy_id, phase, prompt, agent, adapter, model, timeout_ms, status,
|
|
178
183
|
worker_id, worktree, output, exit_code, started_at, finished_at,
|
|
179
184
|
retries, max_retries, files, depends_on)
|
|
180
185
|
VALUES
|
|
181
|
-
(:id, :convoy_id, :phase, :prompt, :agent, :model, :timeout_ms, :status,
|
|
186
|
+
(:id, :convoy_id, :phase, :prompt, :agent, :adapter, :model, :timeout_ms, :status,
|
|
182
187
|
NULL, NULL, NULL, NULL, NULL, NULL,
|
|
183
188
|
:retries, :max_retries, :files, :depends_on)`,
|
|
184
189
|
)
|
package/src/cli/convoy/types.ts
CHANGED
|
@@ -7,6 +7,7 @@ const ADAPTERS: Record<string, () => Promise<AgentAdapter>> = {
|
|
|
7
7
|
'claude-code': () => import('./claude-code.js') as Promise<AgentAdapter>,
|
|
8
8
|
copilot: () => import('./copilot.js') as Promise<AgentAdapter>,
|
|
9
9
|
cursor: () => import('./cursor.js') as Promise<AgentAdapter>,
|
|
10
|
+
opencode: () => import('./opencode.js') as Promise<AgentAdapter>,
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -28,7 +29,7 @@ export async function getAdapter(name: string): Promise<AgentAdapter> {
|
|
|
28
29
|
* Detection priority order — checked first-to-last.
|
|
29
30
|
* The first available adapter wins.
|
|
30
31
|
*/
|
|
31
|
-
const DETECTION_ORDER = ['copilot', 'claude-code', 'cursor'] as const
|
|
32
|
+
const DETECTION_ORDER = ['copilot', 'claude-code', 'cursor', 'opencode'] as const
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* Auto-detect which adapter CLI is available on the system.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process'
|
|
2
|
+
import type { Task, ExecuteOptions, ExecuteResult } from '../../types.js'
|
|
3
|
+
|
|
4
|
+
/** Adapter name */
|
|
5
|
+
export const name = 'opencode'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Check if the `opencode` CLI is available on the system PATH.
|
|
9
|
+
*/
|
|
10
|
+
export async function isAvailable(): Promise<boolean> {
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
const proc = spawn('which', ['opencode'], { stdio: 'pipe' })
|
|
13
|
+
proc.on('close', (code) => resolve(code === 0))
|
|
14
|
+
proc.on('error', () => resolve(false))
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Execute a task by invoking the OpenCode CLI in headless mode.
|
|
20
|
+
*/
|
|
21
|
+
export async function execute(task: Task, options: ExecuteOptions = {}): Promise<ExecuteResult> {
|
|
22
|
+
let prompt = `You are a ${task.agent}. ${task.prompt}`
|
|
23
|
+
|
|
24
|
+
if (task.files && task.files.length > 0) {
|
|
25
|
+
prompt += `\n\nOnly modify files under: ${task.files.join(', ')}`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const args = ['--headless', '-p', prompt]
|
|
29
|
+
|
|
30
|
+
return new Promise((resolve) => {
|
|
31
|
+
const proc = spawn('opencode', args, {
|
|
32
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
33
|
+
env: { ...process.env },
|
|
34
|
+
cwd: options?.cwd ?? process.cwd(),
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
let stdout = ''
|
|
38
|
+
let stderr = ''
|
|
39
|
+
|
|
40
|
+
proc.stdout.on('data', (chunk: Buffer) => {
|
|
41
|
+
stdout += chunk.toString()
|
|
42
|
+
if (options.verbose) {
|
|
43
|
+
process.stdout.write(chunk)
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
proc.stderr.on('data', (chunk: Buffer) => {
|
|
48
|
+
stderr += chunk.toString()
|
|
49
|
+
if (options.verbose) {
|
|
50
|
+
process.stderr.write(chunk)
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
proc.on('close', (code) => {
|
|
55
|
+
const output = [stdout, stderr].filter(Boolean).join('\n')
|
|
56
|
+
resolve({
|
|
57
|
+
success: code === 0,
|
|
58
|
+
output: output.slice(0, 10000), // Cap output size
|
|
59
|
+
exitCode: code ?? -1,
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
proc.on('error', (err) => {
|
|
64
|
+
resolve({
|
|
65
|
+
success: false,
|
|
66
|
+
output: `Failed to spawn opencode: ${err.message}`,
|
|
67
|
+
exitCode: -1,
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
// Store process ref for potential timeout kill
|
|
72
|
+
task._process = proc
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Kill the process associated with a task (used by timeout enforcement).
|
|
78
|
+
*/
|
|
79
|
+
export function kill(task: Task): void {
|
|
80
|
+
if (task._process && !task._process.killed) {
|
|
81
|
+
task._process.kill('SIGTERM')
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
if (task._process && !task._process.killed) {
|
|
84
|
+
task._process.kill('SIGKILL')
|
|
85
|
+
}
|
|
86
|
+
}, 5000)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -529,6 +529,27 @@ describe('validateSpec — branch field', () => {
|
|
|
529
529
|
})
|
|
530
530
|
})
|
|
531
531
|
|
|
532
|
+
// ── validateSpec — per-task adapter ──────────────────────────
|
|
533
|
+
|
|
534
|
+
describe('validateSpec — per-task adapter', () => {
|
|
535
|
+
it('task.adapter must be a string', () => {
|
|
536
|
+
const result = validateSpec({
|
|
537
|
+
name: 'test',
|
|
538
|
+
tasks: [{ id: 'a', prompt: 'x', adapter: 123 }],
|
|
539
|
+
})
|
|
540
|
+
expect(result.valid).toBe(false)
|
|
541
|
+
expect(result.errors).toContainEqual(expect.stringContaining('adapter'))
|
|
542
|
+
})
|
|
543
|
+
|
|
544
|
+
it('task.adapter accepts valid string', () => {
|
|
545
|
+
const result = validateSpec({
|
|
546
|
+
name: 'test',
|
|
547
|
+
tasks: [{ id: 'a', prompt: 'x', adapter: 'opencode' }],
|
|
548
|
+
})
|
|
549
|
+
expect(result.valid).toBe(true)
|
|
550
|
+
})
|
|
551
|
+
})
|
|
552
|
+
|
|
532
553
|
// ── validateSpec — per-task model and max_retries ──────────────
|
|
533
554
|
|
|
534
555
|
describe('validateSpec — per-task model and max_retries', () => {
|
|
@@ -721,6 +742,35 @@ describe('applyDefaults — convoy spec (version: 1)', () => {
|
|
|
721
742
|
expect(spec.gates).toEqual(['npm test'])
|
|
722
743
|
expect(spec.branch).toBe('feat/convoy')
|
|
723
744
|
})
|
|
745
|
+
|
|
746
|
+
it('applies defaults.adapter to tasks without explicit adapter', () => {
|
|
747
|
+
const spec = applyDefaults({
|
|
748
|
+
name: 'test',
|
|
749
|
+
version: 1,
|
|
750
|
+
defaults: { adapter: 'opencode' },
|
|
751
|
+
tasks: [{ id: 'a', prompt: 'x' }],
|
|
752
|
+
})
|
|
753
|
+
expect(spec.tasks![0].adapter).toBe('opencode')
|
|
754
|
+
})
|
|
755
|
+
|
|
756
|
+
it('task-level adapter overrides defaults.adapter', () => {
|
|
757
|
+
const spec = applyDefaults({
|
|
758
|
+
name: 'test',
|
|
759
|
+
version: 1,
|
|
760
|
+
defaults: { adapter: 'opencode' },
|
|
761
|
+
tasks: [{ id: 'a', prompt: 'x', adapter: 'claude-code' }],
|
|
762
|
+
})
|
|
763
|
+
expect(spec.tasks![0].adapter).toBe('claude-code')
|
|
764
|
+
})
|
|
765
|
+
|
|
766
|
+
it('tasks without adapter remain undefined when no defaults', () => {
|
|
767
|
+
const spec = applyDefaults({
|
|
768
|
+
name: 'test',
|
|
769
|
+
version: 1,
|
|
770
|
+
tasks: [{ id: 'a', prompt: 'x' }],
|
|
771
|
+
})
|
|
772
|
+
expect(spec.tasks![0].adapter).toBeUndefined()
|
|
773
|
+
})
|
|
724
774
|
})
|
|
725
775
|
|
|
726
776
|
// ── applyDefaults — max_retries default always applied ─────────
|
package/src/cli/run/schema.ts
CHANGED
|
@@ -55,6 +55,7 @@ interface RawTask {
|
|
|
55
55
|
description?: unknown
|
|
56
56
|
model?: unknown
|
|
57
57
|
max_retries?: unknown
|
|
58
|
+
adapter?: unknown
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
/**
|
|
@@ -126,6 +127,9 @@ export function validateSpec(spec: unknown): ValidationResult {
|
|
|
126
127
|
if (d.agent !== undefined && typeof d.agent !== 'string') {
|
|
127
128
|
errors.push('`defaults.agent` must be a string')
|
|
128
129
|
}
|
|
130
|
+
if (d.adapter !== undefined && typeof d.adapter !== 'string') {
|
|
131
|
+
errors.push('`defaults.adapter` must be a string')
|
|
132
|
+
}
|
|
129
133
|
}
|
|
130
134
|
}
|
|
131
135
|
|
|
@@ -219,6 +223,11 @@ export function validateSpec(spec: unknown): ValidationResult {
|
|
|
219
223
|
)
|
|
220
224
|
}
|
|
221
225
|
}
|
|
226
|
+
|
|
227
|
+
// adapter
|
|
228
|
+
if (task.adapter !== undefined && typeof task.adapter !== 'string') {
|
|
229
|
+
errors.push(`${prefix}: \`adapter\` must be a string`)
|
|
230
|
+
}
|
|
222
231
|
}
|
|
223
232
|
|
|
224
233
|
// DAG cycle detection
|
|
@@ -308,6 +317,10 @@ export function applyDefaults(spec: Record<string, unknown>): TaskSpec {
|
|
|
308
317
|
task.max_retries =
|
|
309
318
|
d.max_retries !== undefined ? Number(d.max_retries) : 1
|
|
310
319
|
}
|
|
320
|
+
// adapter: task-level overrides defaults, no hardcoded fallback (convoy-level is used at runtime)
|
|
321
|
+
if (task.adapter === undefined && d.adapter !== undefined) {
|
|
322
|
+
task.adapter = d.adapter
|
|
323
|
+
}
|
|
311
324
|
}
|
|
312
325
|
|
|
313
326
|
return s as unknown as TaskSpec
|
package/src/cli/run.ts
CHANGED
|
@@ -124,6 +124,9 @@ function printAdapterError(detectionFailed: boolean, adapterName: string): void
|
|
|
124
124
|
' The Cursor agent CLI ships with the Cursor editor.\n' +
|
|
125
125
|
' Install Cursor from https://cursor.com and ensure the\n' +
|
|
126
126
|
' "agent" command is on your PATH (Cursor > Install CLI).',
|
|
127
|
+
opencode:
|
|
128
|
+
' Install OpenCode from https://opencode.ai\n' +
|
|
129
|
+
' Ensure the "opencode" command is on your PATH.',
|
|
127
130
|
}
|
|
128
131
|
const cliName = adapterName === 'claude-code' ? 'claude' : adapterName
|
|
129
132
|
const hint = hints[adapterName] ?? ''
|
package/src/cli/types.ts
CHANGED
|
@@ -132,6 +132,7 @@ export interface TaskDefaults {
|
|
|
132
132
|
model?: string;
|
|
133
133
|
max_retries?: number;
|
|
134
134
|
agent?: string;
|
|
135
|
+
adapter?: string;
|
|
135
136
|
}
|
|
136
137
|
|
|
137
138
|
/** Validated task spec from YAML. */
|
|
@@ -166,6 +167,8 @@ export interface Task {
|
|
|
166
167
|
model?: string;
|
|
167
168
|
/** Max retry attempts (default: 1). */
|
|
168
169
|
max_retries: number;
|
|
170
|
+
/** Per-task adapter override. */
|
|
171
|
+
adapter?: string;
|
|
169
172
|
}
|
|
170
173
|
|
|
171
174
|
/** Task execution status. */
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
|
-
"hash": "
|
|
2
|
+
"hash": "e38e79fd",
|
|
3
3
|
"configHash": "30f8ea04",
|
|
4
|
-
"lockfileHash": "
|
|
5
|
-
"browserHash": "
|
|
4
|
+
"lockfileHash": "dc112ec5",
|
|
5
|
+
"browserHash": "ee856457",
|
|
6
6
|
"optimized": {
|
|
7
7
|
"astro > cssesc": {
|
|
8
8
|
"src": "../../../../../node_modules/cssesc/cssesc.js",
|
|
9
9
|
"file": "astro___cssesc.js",
|
|
10
|
-
"fileHash": "
|
|
10
|
+
"fileHash": "a803959e",
|
|
11
11
|
"needsInterop": true
|
|
12
12
|
},
|
|
13
13
|
"astro > aria-query": {
|
|
14
14
|
"src": "../../../../../node_modules/aria-query/lib/index.js",
|
|
15
15
|
"file": "astro___aria-query.js",
|
|
16
|
-
"fileHash": "
|
|
16
|
+
"fileHash": "8505e2b8",
|
|
17
17
|
"needsInterop": true
|
|
18
18
|
},
|
|
19
19
|
"astro > axobject-query": {
|
|
20
20
|
"src": "../../../../../node_modules/axobject-query/lib/index.js",
|
|
21
21
|
"file": "astro___axobject-query.js",
|
|
22
|
-
"fileHash": "
|
|
22
|
+
"fileHash": "e7d3a98b",
|
|
23
23
|
"needsInterop": true
|
|
24
24
|
}
|
|
25
25
|
},
|