Skip to content

Commit c1e4bee

Browse files
committed
refactor(workflow): name live provider availability accurately
1 parent 509d4ac commit c1e4bee

7 files changed

Lines changed: 29 additions & 26 deletions

File tree

skills/dynamic-workflows/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ profile supplies instructions, provider, model, and effort defaults; per-call
9191
mutually exclusive.
9292

9393
Without a profile, default provider resolution is `opts.provider`
94-
`meta.defaultProvider` → first **enabled ∩ available** provider.
94+
`meta.defaultProvider` → first currently available provider.
9595

9696
### Resume
9797

src/cli.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ async function main(argv: string[]): Promise<void> {
7070
runConfigCommand(args);
7171
return;
7272
case "agents":
73+
if (!loadConfig().subagents) {
74+
throw new Error(
75+
"Subagents are disabled. Set DEVSPACE_SUBAGENTS=1 to enable the experimental feature.",
76+
);
77+
}
7378
await runAgentsCommand(args);
7479
return;
7580
case "workflow":

src/workflow-api.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ export interface WorkflowApiDeps {
158158
signal: AbortSignal;
159159
workspaceRoot: string;
160160
baseSha?: string;
161-
/** Already-filtered enabled ∩ live provider ids, preference order. */
162-
enabledProviders: LocalAgentProvider[];
163-
/** Loaded, enabled profiles exposed by open_workspace for this project. */
161+
/** Currently available provider ids in stable preference order. */
162+
availableProviders: LocalAgentProvider[];
163+
/** Loaded profiles available to this project. */
164164
agentProfiles?: LocalAgentProfile[];
165165
runProvider: WorkflowRunProvider;
166166
createWorktree?: CreateAgentWorktree;
@@ -186,7 +186,6 @@ export class WorkflowEngineError extends Error {
186186
constructor(
187187
readonly kind:
188188
| "cancelled"
189-
| "provider_disabled"
190189
| "provider_unavailable"
191190
| "no_provider"
192191
| "profile"
@@ -711,7 +710,7 @@ interface ResolvedAgentTarget {
711710
function resolveAgentTarget(
712711
prompt: string,
713712
opts: AgentOpts,
714-
deps: Pick<WorkflowApiDeps, "agentProfiles" | "enabledProviders" | "meta">,
713+
deps: Pick<WorkflowApiDeps, "agentProfiles" | "availableProviders" | "meta">,
715714
): ResolvedAgentTarget {
716715
try {
717716
const resolved = resolveLocalAgentExecution({
@@ -722,7 +721,7 @@ function resolveAgentTarget(
722721
model: opts.model,
723722
effort: opts.effort,
724723
profiles: deps.agentProfiles ?? [],
725-
availableProviders: deps.enabledProviders,
724+
availableProviders: deps.availableProviders,
726725
});
727726
return {
728727
provider: resolved.provider,

src/workflow-cli.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ export async function runWorkflowWorker(
352352
try {
353353
const source = await readFile(claimed.scriptPath, "utf8");
354354
const parsed = parseWorkflowScript(source, { filename: claimed.scriptPath });
355-
const enabledProviders = resolveEnabledProviders();
355+
const availableProviders = resolveAvailableProviders();
356356
const agentProfiles = await loadLocalAgentProfiles(config, claimed.workspaceRoot);
357357
const concurrency = resolveWorkflowConcurrency(
358358
parsed.meta.concurrency,
@@ -385,7 +385,7 @@ export async function runWorkflowWorker(
385385
signal: abort.signal,
386386
workspaceRoot: claimed.workspaceRoot,
387387
baseSha: claimed.baseSha,
388-
enabledProviders,
388+
availableProviders,
389389
agentProfiles,
390390
createWorktree,
391391
replay,
@@ -600,7 +600,7 @@ function safeParseJson(text: string): unknown {
600600
}
601601
}
602602

603-
function resolveEnabledProviders(): LocalAgentProvider[] {
603+
function resolveAvailableProviders(): LocalAgentProvider[] {
604604
const snapshot = getLocalAgentProviderAvailabilitySnapshot();
605605
const live = new Set(snapshot.filter((row) => row.available).map((row) => row.name));
606606
return LOCAL_AGENT_PROVIDERS.filter((id) => live.has(id));

src/workflow-contracts.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ export const workflowErrorKindSchema = z.enum([
121121
"syntax",
122122
"meta",
123123
"determinism",
124-
"provider_disabled",
125124
"provider_unavailable",
126125
"no_provider",
127126
"provider",

src/workflow-engine.test.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ import type { LocalAgentProfile } from "./local-agent-profiles.js";
5757
concurrency: 4,
5858
signal: new AbortController().signal,
5959
workspaceRoot: dir,
60-
enabledProviders: ["codex"],
60+
availableProviders: ["codex"],
6161
runProvider: async (input) => {
6262
order.push(`start:${input.prompt}`);
6363
await new Promise((r) => setTimeout(r, 10));
@@ -102,7 +102,7 @@ import type { LocalAgentProfile } from "./local-agent-profiles.js";
102102
concurrency: 4,
103103
signal: new AbortController().signal,
104104
workspaceRoot: dir,
105-
enabledProviders: ["codex"],
105+
availableProviders: ["codex"],
106106
runProvider: async () => ({ finalResponse: "x" }),
107107
});
108108

@@ -165,7 +165,7 @@ import type { LocalAgentProfile } from "./local-agent-profiles.js";
165165
concurrency: 4,
166166
signal: new AbortController().signal,
167167
workspaceRoot: dir,
168-
enabledProviders: ["codex"],
168+
availableProviders: ["codex"],
169169
runProvider: async (input: WorkflowProviderRunInput) => {
170170
seen.push({ prompt: input.prompt, phase: input.phase });
171171
await new Promise((r) => setTimeout(r, 15));
@@ -226,7 +226,7 @@ import type { LocalAgentProfile } from "./local-agent-profiles.js";
226226
concurrency: 2,
227227
signal: new AbortController().signal,
228228
workspaceRoot: dir,
229-
enabledProviders: ["codex"],
229+
availableProviders: ["codex"],
230230
createWorktree,
231231
runProvider: async (input) => {
232232
assert.equal(input.workspace, worktrees[0]);
@@ -265,7 +265,7 @@ import type { LocalAgentProfile } from "./local-agent-profiles.js";
265265
concurrency: 1,
266266
signal: new AbortController().signal,
267267
workspaceRoot: dir,
268-
enabledProviders: ["codex"],
268+
availableProviders: ["codex"],
269269
createWorktree: async () => {
270270
throw new Error("expected worktree setup failure");
271271
},
@@ -312,7 +312,7 @@ import type { LocalAgentProfile } from "./local-agent-profiles.js";
312312
concurrency: 1,
313313
signal: new AbortController().signal,
314314
workspaceRoot: dir,
315-
enabledProviders: ["codex", "claude"],
315+
availableProviders: ["codex", "claude"],
316316
runProvider: async (input) => {
317317
used.push(input.provider);
318318
return { finalResponse: input.provider };
@@ -360,7 +360,7 @@ import type { LocalAgentProfile } from "./local-agent-profiles.js";
360360
concurrency: 1,
361361
signal: new AbortController().signal,
362362
workspaceRoot: dir,
363-
enabledProviders: ["codex", "claude"],
363+
availableProviders: ["codex", "claude"],
364364
agentProfiles: [profile],
365365
runProvider: async (input) => {
366366
calls.push(input);
@@ -401,7 +401,7 @@ import type { LocalAgentProfile } from "./local-agent-profiles.js";
401401
concurrency: 1,
402402
signal: new AbortController().signal,
403403
workspaceRoot: dir,
404-
enabledProviders: ["codex"],
404+
availableProviders: ["codex"],
405405
agentProfiles: [profile],
406406
runProvider: async () => ({ finalResponse: "unreachable" }),
407407
});
@@ -440,7 +440,7 @@ import type { LocalAgentProfile } from "./local-agent-profiles.js";
440440
concurrency: 1,
441441
signal: new AbortController().signal,
442442
workspaceRoot: dir,
443-
enabledProviders: ["codex"],
443+
availableProviders: ["codex"],
444444
runProvider: async (input) => {
445445
calls.push(input);
446446
if (calls.length === 1) {
@@ -494,7 +494,7 @@ import type { LocalAgentProfile } from "./local-agent-profiles.js";
494494
concurrency: 1,
495495
signal: new AbortController().signal,
496496
workspaceRoot: dir,
497-
enabledProviders: ["codex"],
497+
availableProviders: ["codex"],
498498
runProvider: async () => ({ finalResponse: response }),
499499
});
500500

@@ -539,7 +539,7 @@ return { a, nested }
539539
runId: run.id,
540540
journal: store,
541541
workspaceRoot: dir,
542-
enabledProviders: ["codex", "claude"],
542+
availableProviders: ["codex", "claude"],
543543
runProvider: async (input) => {
544544
prompts.push(input.prompt);
545545
providers.push(input.provider);
@@ -576,7 +576,7 @@ return await workflow({ scriptPath: ${JSON.stringify(childPath)} }).then(async (
576576
runId: run.id,
577577
journal: store,
578578
workspaceRoot: dir,
579-
enabledProviders: ["codex"],
579+
availableProviders: ["codex"],
580580
runProvider: async () => ({ finalResponse: "x" }),
581581
resolveNestedSource: async () => `
582582
export const meta = { name: 'mid', description: 'm' }
@@ -613,7 +613,7 @@ return await workflow({ scriptPath: 'x' })
613613
concurrency: 1,
614614
signal: ac.signal,
615615
workspaceRoot: dir,
616-
enabledProviders: ["codex"],
616+
availableProviders: ["codex"],
617617
runProvider: async () => {
618618
ac.abort();
619619
return { finalResponse: "late" };

src/workflow-engine.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export interface ExecuteWorkflowOptions {
4040
signal?: AbortSignal;
4141
workspaceRoot: string;
4242
baseSha?: string;
43-
enabledProviders: LocalAgentProvider[];
43+
availableProviders: LocalAgentProvider[];
4444
agentProfiles?: LocalAgentProfile[];
4545
runProvider: WorkflowRunProvider;
4646
createWorktree?: CreateAgentWorktree;
@@ -89,7 +89,7 @@ export async function executeWorkflow(
8989
signal,
9090
workspaceRoot: options.workspaceRoot,
9191
baseSha: options.baseSha,
92-
enabledProviders: options.enabledProviders,
92+
availableProviders: options.availableProviders,
9393
agentProfiles: options.agentProfiles,
9494
runProvider: options.runProvider,
9595
createWorktree: options.createWorktree,

0 commit comments

Comments
 (0)