opencode-agent-skill 15.0.0 → 15.1.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.
@@ -14,6 +14,7 @@ import {
14
14
  import {
15
15
  applyAnchoredFileEdits,
16
16
  diagnoseCode,
17
+ lspOperation,
17
18
  probeCodeIntelligence,
18
19
  readAnchoredCode,
19
20
  searchCodeIntelligence,
@@ -272,13 +273,20 @@ export default function (pi: ExtensionAPI) {
272
273
  name: "ues_code",
273
274
  label: "UES Code Intelligence",
274
275
  description:
275
- "Bounded code/document/context intelligence for weak models: semantic/AST search, hash-anchored reads, optional LSP diagnostics, optional MarkItDown ingestion, and reversible context recovery.",
276
+ "Bounded code/document/context intelligence for weak models: semantic/AST search, hash-anchored reads, deterministic LSP definition/references/symbols/hover/rename-preview/call hierarchy, diagnostics, optional MarkItDown ingestion, and reversible context recovery.",
276
277
  parameters: Type.Object({
277
278
  action: Type.Union([
278
279
  Type.Literal("status"),
279
280
  Type.Literal("search"),
280
281
  Type.Literal("read"),
281
282
  Type.Literal("diagnostics"),
283
+ Type.Literal("definition"),
284
+ Type.Literal("references"),
285
+ Type.Literal("symbols"),
286
+ Type.Literal("hover"),
287
+ Type.Literal("rename-preview"),
288
+ Type.Literal("incoming-calls"),
289
+ Type.Literal("outgoing-calls"),
282
290
  Type.Literal("document"),
283
291
  Type.Literal("context-expand"),
284
292
  Type.Literal("context-search"),
@@ -289,6 +297,10 @@ export default function (pi: ExtensionAPI) {
289
297
  language: Type.Optional(Type.String()),
290
298
  startLine: Type.Optional(Type.Number({ minimum: 1 })),
291
299
  endLine: Type.Optional(Type.Number({ minimum: 1 })),
300
+ line: Type.Optional(Type.Number({ minimum: 1, description: "1-based source line for LSP operations" })),
301
+ character: Type.Optional(Type.Number({ minimum: 1, description: "1-based source character for LSP operations" })),
302
+ newName: Type.Optional(Type.String({ minLength: 1, maxLength: 512 })),
303
+ includeDeclaration: Type.Optional(Type.Boolean()),
292
304
  ref: Type.Optional(Type.String()),
293
305
  maxBytes: Type.Optional(Type.Number({ minimum: 1, maximum: 128000 })),
294
306
  }),
@@ -320,7 +332,18 @@ export default function (pi: ExtensionAPI) {
320
332
  };
321
333
  } else if (params.action === "diagnostics") {
322
334
  if (!params.file) throw new Error("ues_code diagnostics requires file");
323
- result = await diagnoseCode(ctx.cwd, params.file, { timeoutMs: 3000, maxDiagnostics: 40 });
335
+ result = await diagnoseCode(ctx.cwd, params.file, { timeoutMs: 5000, maxResults: 80 });
336
+ } else if (["definition", "references", "symbols", "hover", "rename-preview", "incoming-calls", "outgoing-calls"].includes(params.action)) {
337
+ if (!params.file) throw new Error(`ues_code ${params.action} requires file`);
338
+ if (params.action === "rename-preview" && !params.newName) throw new Error("ues_code rename-preview requires newName");
339
+ result = await lspOperation(ctx.cwd, params.file, params.action, {
340
+ line: params.line || 1,
341
+ character: params.character || 1,
342
+ newName: params.newName,
343
+ includeDeclaration: params.includeDeclaration,
344
+ timeoutMs: 7000,
345
+ maxResults: 120,
346
+ });
324
347
  } else if (params.action === "document") {
325
348
  if (!params.file) throw new Error("ues_code document requires file");
326
349
  const document = await ingestDocument(ctx.cwd, params.file, { maxBytes: Math.min(Number(params.maxBytes || 4 * 1024 * 1024), 4 * 1024 * 1024) });
@@ -35,7 +35,9 @@ import { turboFastPathDecision, turboFastTimeoutBudget } from "../../lib/turbo-f
35
35
  import { failureDelta, leafTaskPolicy } from "../../lib/leaf-runtime-optimizer.mjs";
36
36
  import { planningRuntimeBudget, shouldSoftSteerArchitect, shouldSoftSteerPlanningRole } from "../../lib/planning-speed-policy.mjs";
37
37
  import { sourceFacingPaths, sourceGitPathspecs } from "../../lib/runtime-artifacts.mjs";
38
+ import { createSubagentArtifact, failSubagentArtifact, finalizeSubagentArtifact, listSubagentArtifacts, readSubagentArtifact } from "../../lib/subagent-artifacts.mjs";
38
39
  import { buildExecutionContract, buildFinalVerdictMatrix, captureInheritedDirtyState, detectInheritedDirtyViolations, enforcePhaseGates, executionContractPrompt, phaseArtifactPayloads, taskExplicitlyAllowsLocalEnvWrite } from "../../lib/execution-contract.mjs";
40
+ import { buildCompactionResumeGuard, checkpointDurableWorkBeforeCompaction, renderCompactionResumeGuard } from "../../lib/compaction-resume-guard.mjs";
39
41
  import { sessionNameFromUesInput, uesSessionName } from "../../lib/session-display.mjs";
40
42
  import { requireGitWorkspaceRoot, resolveGitWorkspaceRoot } from "../../lib/workspace-root.mjs";
41
43
  import { createAdaptiveDeadline } from "../../lib/activity-deadline.mjs";
@@ -43,7 +45,8 @@ import { extractValidatedPlan } from "../../lib/plan-salvage.mjs";
43
45
  import { auditCompletion } from "../../lib/completion-auditor.mjs";
44
46
  import { mcpExecutionPolicy } from "../../lib/mcp-tool-policy.mjs";
45
47
  import { McpHealthTracker } from "../../lib/mcp-health.mjs";
46
- import { runtimeWorkspaceFingerprint, runtimeWorkspaceSnapshot } from "../../lib/workspace-fingerprint.mjs";
48
+ import { captureWorkspaceStateV2, runtimeWorkspaceFingerprint, runtimeWorkspaceSnapshot } from "../../lib/workspace-fingerprint.mjs";
49
+ import { captureWorkspaceHygieneBaseline, postRunFileHygiene, preFinalWorkspaceAudit } from "../../lib/workspace-hygiene.mjs";
47
50
  import { appendTrajectoryEvent, createTraceID } from "../../lib/trajectory.mjs";
48
51
  import {
49
52
  browserEvidenceNeeded,
@@ -272,6 +275,7 @@ type RunResult = {
272
275
  browserTools?: string[];
273
276
  childRuntime?: "rpc" | "cli";
274
277
  workerReused?: boolean;
278
+ subagentArtifact?: any;
275
279
  optimizations?: any;
276
280
  };
277
281
 
@@ -1510,8 +1514,24 @@ async function runRoutedAgent(
1510
1514
  taskPolicyOverride?: any,
1511
1515
  contextCacheNamespace?: string,
1512
1516
  ): Promise<RunResult> {
1517
+ const routedStartedAt = Date.now();
1513
1518
  const role = roleForAgent(agent);
1514
1519
  const traceRoot = requireGitWorkspaceRoot(cwd, "UES specialist");
1520
+ const workspaceSnapshotStartedAt = Date.now();
1521
+ let agentWorkspaceState: any = null;
1522
+ let workspaceState: any = {
1523
+ cacheable: false,
1524
+ fingerprint: "unknown",
1525
+ changedFiles: [],
1526
+ };
1527
+ try {
1528
+ agentWorkspaceState = captureWorkspaceStateV2(cwd);
1529
+ workspaceState = runtimeWorkspaceSnapshot(cwd, { workspaceState: agentWorkspaceState });
1530
+ } catch {}
1531
+ const agentHygieneBaseline = captureWorkspaceHygieneBaseline(cwd, {
1532
+ workspaceState: agentWorkspaceState,
1533
+ });
1534
+ const workspaceSnapshotMs = Date.now() - workspaceSnapshotStartedAt;
1515
1535
  const browserRequested = browserEvidenceNeeded(task, role);
1516
1536
  const browserTools = browserRequested
1517
1537
  ? selectBrowserToolsForTask(HOST_BROWSER_TOOL_NAMES, task, role)
@@ -1573,14 +1593,6 @@ async function runRoutedAgent(
1573
1593
  ? undefined
1574
1594
  : inheritedThinking;
1575
1595
 
1576
- let workspaceState: any = {
1577
- cacheable: false,
1578
- fingerprint: "unknown",
1579
- changedFiles: [],
1580
- };
1581
- try {
1582
- workspaceState = runtimeWorkspaceSnapshot(cwd);
1583
- } catch {}
1584
1596
  const workspaceFingerprint = String(workspaceState.fingerprint || "unknown");
1585
1597
 
1586
1598
  let enrichedTask = task;
@@ -1590,6 +1602,8 @@ async function runRoutedAgent(
1590
1602
  let affectedTests: any = null;
1591
1603
  let reusableVerification: any = null;
1592
1604
  let contextCacheHit = false;
1605
+ let contextPerformance: any = null;
1606
+ const contextBuildStartedAt = Date.now();
1593
1607
  try {
1594
1608
  if (fastBoundedContext) {
1595
1609
  contextQuality = { schemaVersion: 1, profile: "fast-bounded", bounded: true };
@@ -1685,6 +1699,7 @@ async function runRoutedAgent(
1685
1699
  }
1686
1700
 
1687
1701
  contextQuality = pack.contextQuality;
1702
+ contextPerformance = pack.performance || null;
1688
1703
  enrichedTask = [
1689
1704
  task,
1690
1705
  "",
@@ -1723,6 +1738,7 @@ async function runRoutedAgent(
1723
1738
  enrichedTask += "\n\n## Previous failed verification\n" + cap(recentFailure, 5000);
1724
1739
  }
1725
1740
  }
1741
+ const contextBuildMs = Date.now() - contextBuildStartedAt;
1726
1742
 
1727
1743
  if (browserRequested) {
1728
1744
  enrichedTask += browserTools.length
@@ -1747,7 +1763,34 @@ async function runRoutedAgent(
1747
1763
  taskChars: task.length,
1748
1764
  });
1749
1765
  const startedAt = Date.now();
1750
- const result = await runAgent(
1766
+ const artifactRoot = await taskSandboxOwnerRoot(cwd).catch(() => null) || traceRoot;
1767
+ const childArtifact = await createSubagentArtifact(artifactRoot, {
1768
+ agent,
1769
+ role,
1770
+ attempt,
1771
+ task,
1772
+ traceID,
1773
+ model: selectedModel,
1774
+ modelTier: selection.tier,
1775
+ workspaceFingerprint,
1776
+ }).catch(() => null);
1777
+ if (childArtifact?.handle) {
1778
+ try {
1779
+ onProgress?.({
1780
+ agent,
1781
+ elapsedMs: 0,
1782
+ idleMs: 0,
1783
+ toolCalls: 0,
1784
+ model: selectedModel,
1785
+ phase: "running",
1786
+ note: `subagent handle ${childArtifact.handle}; durable status ${childArtifact.file}`,
1787
+ });
1788
+ } catch {}
1789
+ }
1790
+ let result: RunResult;
1791
+ const modelRunStartedAt = Date.now();
1792
+ try {
1793
+ result = await runAgent(
1751
1794
  agent,
1752
1795
  enrichedTask,
1753
1796
  cwd,
@@ -1801,8 +1844,56 @@ async function runRoutedAgent(
1801
1844
  allowLocalEnvWrite:
1802
1845
  taskPolicy.localEnvWriteExplicitlyAllowed === true ||
1803
1846
  taskExplicitlyAllowsLocalEnvWrite(task),
1804
- },
1805
- );
1847
+ },
1848
+ );
1849
+ } catch (error) {
1850
+ if (childArtifact?.handle) {
1851
+ await failSubagentArtifact(artifactRoot, childArtifact.handle, error).catch(() => null);
1852
+ }
1853
+ throw error;
1854
+ }
1855
+ const modelRunMs = Date.now() - modelRunStartedAt;
1856
+ const hygieneStartedAt = Date.now();
1857
+ const postRunHygiene = await postRunFileHygiene(cwd, {
1858
+ baseline: agentHygieneBaseline,
1859
+ taskText: task,
1860
+ allowSourceMutations: WRITE_AGENTS.has(agent),
1861
+ autoClean: true,
1862
+ }).catch((error) => ({
1863
+ schemaVersion: 1,
1864
+ safe: false,
1865
+ changed: [],
1866
+ created: [],
1867
+ removed: [],
1868
+ findings: [{
1869
+ kind: "hygiene-audit-error",
1870
+ file: ".",
1871
+ message: error instanceof Error ? error.message : String(error),
1872
+ }],
1873
+ summary: "workspace hygiene audit failed: " + (error instanceof Error ? error.message : String(error)),
1874
+ }));
1875
+ if (!postRunHygiene.safe) {
1876
+ const hygieneText = [
1877
+ "UES post-run workspace hygiene guard rejected this child run.",
1878
+ postRunHygiene.summary || "workspace hygiene failed",
1879
+ ].join("\n");
1880
+ result = {
1881
+ ...result,
1882
+ exitCode: result.exitCode === 0 ? 2 : result.exitCode,
1883
+ stopReason: "error",
1884
+ errorMessage: hygieneText,
1885
+ output: [result.output, "", hygieneText].filter(Boolean).join("\n"),
1886
+ };
1887
+ }
1888
+
1889
+ const hygieneMs = Date.now() - hygieneStartedAt;
1890
+ const finalizedChildArtifact = childArtifact?.handle
1891
+ ? await finalizeSubagentArtifact(artifactRoot, childArtifact.handle, {
1892
+ ...result,
1893
+ durationMs: Date.now() - startedAt,
1894
+ verdict: verdictFromOutput(result.output),
1895
+ }).catch(() => null)
1896
+ : null;
1806
1897
  const enrichedResult: RunResult = {
1807
1898
  ...result,
1808
1899
  task,
@@ -1833,10 +1924,32 @@ async function runRoutedAgent(
1833
1924
  turboFastStrategy: turboFast.strategy,
1834
1925
  turboFastTimeouts: turboFast.eligible ? TURBO_FAST_TIMEOUTS : null,
1835
1926
  planningRuntimeBudget: planningBudget,
1927
+ affectedTestInventorySource: affectedTests?.inventorySource || null,
1928
+ contextPerformance,
1929
+ latencyMs: {
1930
+ workspaceSnapshot: workspaceSnapshotMs,
1931
+ contextBuild: contextBuildMs,
1932
+ modelRun: modelRunMs,
1933
+ hygiene: hygieneMs,
1934
+ total: Date.now() - routedStartedAt,
1935
+ },
1836
1936
  },
1837
1937
  verdict: verdictFromOutput(result.output),
1838
1938
  report: parseStructuredReport(result.output),
1839
1939
  durationMs: Date.now() - startedAt,
1940
+ subagentArtifact: finalizedChildArtifact ? {
1941
+ handle: finalizedChildArtifact.handle,
1942
+ status: finalizedChildArtifact.status,
1943
+ file: finalizedChildArtifact.file,
1944
+ taskRef: finalizedChildArtifact.taskRef,
1945
+ outputRef: finalizedChildArtifact.result?.outputRef || null,
1946
+ resume: finalizedChildArtifact.resume || null,
1947
+ } : childArtifact ? {
1948
+ handle: childArtifact.handle,
1949
+ status: childArtifact.status,
1950
+ file: childArtifact.file,
1951
+ taskRef: childArtifact.taskRef,
1952
+ } : null,
1840
1953
  };
1841
1954
  if (traceID) {
1842
1955
  await appendTrajectoryEvent(traceRoot, traceID, "agent.completed", {
@@ -2848,6 +2961,40 @@ export default function (pi: ExtensionAPI) {
2848
2961
  deactivateParentUesTools();
2849
2962
  });
2850
2963
 
2964
+ pi.on("session_before_compact", async (event, ctx) => {
2965
+ const root = resolveGitWorkspaceRoot(ctx.cwd || "");
2966
+ if (!root) return undefined;
2967
+ await checkpointDurableWorkBeforeCompaction(root, {
2968
+ reason: event.reason,
2969
+ maxWorkspaces: 3,
2970
+ }).catch(() => []);
2971
+ return undefined;
2972
+ });
2973
+
2974
+ pi.on("session_compact", async (event, ctx) => {
2975
+ const root = resolveGitWorkspaceRoot(ctx.cwd || "");
2976
+ if (!root) return;
2977
+ const packet = await buildCompactionResumeGuard(root, {
2978
+ reason: event.reason,
2979
+ maxWorkspaces: 3,
2980
+ }).catch(() => null);
2981
+ if (!packet?.workspaces?.length) return;
2982
+ const content = renderCompactionResumeGuard(packet);
2983
+ if (!content) return;
2984
+ pi.sendMessage({
2985
+ customType: "ues-durable-resume-guard",
2986
+ content,
2987
+ display: false,
2988
+ details: {
2989
+ schemaVersion: 1,
2990
+ reason: event.reason,
2991
+ willRetry: event.willRetry,
2992
+ workspaceCount: packet.workspaceCount,
2993
+ source: packet.source,
2994
+ },
2995
+ }, { triggerTurn: false });
2996
+ });
2997
+
2851
2998
  pi.on("session_shutdown", async () => {
2852
2999
  directControllerAbort?.abort();
2853
3000
  directControllerAbort = null;
@@ -3212,7 +3359,13 @@ export default function (pi: ExtensionAPI) {
3212
3359
  const cwd = requireGitWorkspaceRoot(params.cwd || ctx.cwd, "ues_execute");
3213
3360
  const inheritedModel = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
3214
3361
  const inheritedThinking = ctx.thinkingLevel as string | undefined;
3215
- const inheritedDirty = captureInheritedDirtyState(cwd);
3362
+ const controllerWorkspaceState = captureWorkspaceStateV2(cwd);
3363
+ const inheritedDirty = captureInheritedDirtyState(cwd, {
3364
+ workspaceState: controllerWorkspaceState,
3365
+ });
3366
+ const controllerHygieneBaseline = captureWorkspaceHygieneBaseline(cwd, {
3367
+ workspaceState: controllerWorkspaceState,
3368
+ });
3216
3369
  const executionContract = buildExecutionContract(params.task, inheritedDirty);
3217
3370
  const contractPrompt = executionContractPrompt(executionContract);
3218
3371
  const suppliedPolicy = (params as any).__taskPolicy;
@@ -4043,6 +4196,56 @@ export default function (pi: ExtensionAPI) {
4043
4196
  };
4044
4197
  }
4045
4198
 
4199
+ const finalWriteScope = [...new Set(
4200
+ structuredPlan.tasks.flatMap((task: any) => taskWriteFiles(task)),
4201
+ )];
4202
+ const preFinalAudit = await preFinalWorkspaceAudit(cwd, {
4203
+ baseline: controllerHygieneBaseline,
4204
+ taskText: params.task,
4205
+ allowedPaths: finalWriteScope,
4206
+ strictScope: true,
4207
+ allowSourceMutations: true,
4208
+ }).catch((error) => ({
4209
+ safe: false,
4210
+ summary: "pre-final workspace audit failed: " + (error instanceof Error ? error.message : String(error)),
4211
+ findings: [],
4212
+ }));
4213
+ if (!preFinalAudit.safe) {
4214
+ if (durableWork) {
4215
+ await durableRecordIntegration(
4216
+ cwd,
4217
+ durableWork.slug,
4218
+ "PARTIAL",
4219
+ preFinalAudit.summary || "pre-final workspace hygiene failed",
4220
+ signal,
4221
+ ).catch(() => {});
4222
+ }
4223
+ return {
4224
+ content: [{
4225
+ type: "text",
4226
+ text: [
4227
+ "UES pre-final workspace audit blocked PASS.",
4228
+ "The final repository contains an undeclared, transient, or Unicode-unsafe change.",
4229
+ "",
4230
+ preFinalAudit.summary || "workspace hygiene failed",
4231
+ ].join("\n"),
4232
+ }],
4233
+ details: {
4234
+ mode: "execute",
4235
+ policy,
4236
+ steps,
4237
+ structuredPlan,
4238
+ scheduled,
4239
+ durableWork,
4240
+ verdictMatrix,
4241
+ executionContract,
4242
+ preFinalAudit,
4243
+ traceID,
4244
+ },
4245
+ isError: true,
4246
+ };
4247
+ }
4248
+
4046
4249
  let durableFinalization: any = null;
4047
4250
  if (durableWork) {
4048
4251
  const finalEvidence = finalEvidenceForContract;
@@ -4381,6 +4584,37 @@ export default function (pi: ExtensionAPI) {
4381
4584
  };
4382
4585
  }
4383
4586
 
4587
+ const preFinalAudit = await preFinalWorkspaceAudit(cwd, {
4588
+ baseline: controllerHygieneBaseline,
4589
+ taskText: params.task,
4590
+ strictScope: false,
4591
+ allowSourceMutations: true,
4592
+ }).catch((error) => ({
4593
+ safe: false,
4594
+ summary: "pre-final workspace audit failed: " + (error instanceof Error ? error.message : String(error)),
4595
+ findings: [],
4596
+ }));
4597
+ if (!preFinalAudit.safe) {
4598
+ recentFailure = "Pre-final workspace audit rejected PASS: " + (preFinalAudit.summary || "workspace hygiene failed");
4599
+ await recordRuntimeOutcome(implementation, params.task, false, attempt - 1);
4600
+ if (attempt < maxAttempts) continue;
4601
+ return {
4602
+ content: [{ type: "text", text: recentFailure }],
4603
+ details: {
4604
+ mode: "execute",
4605
+ policy,
4606
+ steps,
4607
+ attempts: attempt,
4608
+ completionAudit,
4609
+ verdictMatrix,
4610
+ executionContract,
4611
+ preFinalAudit,
4612
+ traceID,
4613
+ },
4614
+ isError: true,
4615
+ };
4616
+ }
4617
+
4384
4618
  await recordRuntimeOutcome(implementation, params.task, true, attempt - 1);
4385
4619
  const memory = await rememberVerifiedTask(cwd, params.task, verification, integrationResult);
4386
4620
  const final = steps.at(-1);
@@ -4425,6 +4659,10 @@ export default function (pi: ExtensionAPI) {
4425
4659
  "Package root: " + PACKAGE_ROOT,
4426
4660
  "Child runtime: " + CHILD_RUNTIME,
4427
4661
  "Adaptive context: " + (ADAPTIVE_CONTEXT_ENABLED ? "on" : "off"),
4662
+ "Unified workspace snapshot V2: on",
4663
+ "Parallel context preparation: on",
4664
+ "Git-index affected-test inventory: on",
4665
+ "Parallel verification evidence I/O: on",
4428
4666
  "Micro skills: " + (MICRO_SKILLS_ENABLED ? "on" : "off"),
4429
4667
  "Turbo Fast Path: on",
4430
4668
  "Parent UES tools hidden outside UES runs: on",
@@ -4435,6 +4673,9 @@ export default function (pi: ExtensionAPI) {
4435
4673
  "Portable temp-path guard: on",
4436
4674
  "Explicit phase barriers: on",
4437
4675
  "Independent final verdict matrix: on",
4676
+ "Unicode source hygiene: blocking bidi/zero-width/control/homoglyph audit",
4677
+ "Post-run file hygiene: transient cleanup + read-only mutation guard",
4678
+ "Pre-final workspace audit: on",
4438
4679
  "Disk hygiene: bounded + auto-clean",
4439
4680
  "Writer concurrency: " + MAX_WRITER_CONCURRENCY,
4440
4681
  ].join("\n");
@@ -4766,9 +5007,11 @@ export default function (pi: ExtensionAPI) {
4766
5007
  name: "ues_dispatch",
4767
5008
  label: "UES Dispatch",
4768
5009
  description:
4769
- "Run bundled UES specialist agents in isolated child Pi processes. Supports single, parallel, or chain mode. Parallel writer agents fail closed unless each writer has an explicit distinct cwd/worktree. Available agents: " +
5010
+ "Run bundled UES specialist agents in isolated child Pi processes, or inspect durable child handles with action=status/list. Every child run writes a small artifact with exact task/output evidence references. Supports single, parallel, or chain mode. Parallel writer agents fail closed unless each writer has an explicit distinct cwd/worktree. Available agents: " +
4770
5011
  Object.keys(AGENTS).join(", "),
4771
5012
  parameters: Type.Object({
5013
+ action: Type.Optional(Type.Union([Type.Literal("run"), Type.Literal("status"), Type.Literal("list")])),
5014
+ handle: Type.Optional(Type.String({ description: "Subagent artifact handle for status action" })),
4772
5015
  agent: Type.Optional(Type.String({ description: "Agent name for single mode" })),
4773
5016
  task: Type.Optional(Type.String({ description: "Task for single mode" })),
4774
5017
  cwd: Type.Optional(Type.String({ description: "Working directory for single mode" })),
@@ -4777,6 +5020,39 @@ export default function (pi: ExtensionAPI) {
4777
5020
  }),
4778
5021
  async execute(_toolCallId, params, signal, onUpdate, ctx) {
4779
5022
  refreshHostBrowserToolNames(pi);
5023
+ const action = String(params.action || "run");
5024
+ const baseCwd = ctx.cwd;
5025
+ if (action === "status") {
5026
+ if (!params.handle) {
5027
+ return {
5028
+ content: [{ type: "text", text: "ues_dispatch action=status requires handle." }],
5029
+ details: { mode: "status" },
5030
+ isError: true,
5031
+ };
5032
+ }
5033
+ try {
5034
+ const root = requireGitWorkspaceRoot(baseCwd, "ues_dispatch status");
5035
+ const artifact = await readSubagentArtifact(root, params.handle);
5036
+ return {
5037
+ content: [{ type: "text", text: JSON.stringify(artifact, null, 2) }],
5038
+ details: { mode: "status", artifact },
5039
+ };
5040
+ } catch (error) {
5041
+ return {
5042
+ content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }],
5043
+ details: { mode: "status", handle: params.handle },
5044
+ isError: true,
5045
+ };
5046
+ }
5047
+ }
5048
+ if (action === "list") {
5049
+ const root = requireGitWorkspaceRoot(baseCwd, "ues_dispatch list");
5050
+ const artifacts = await listSubagentArtifacts(root, { limit: 20 });
5051
+ return {
5052
+ content: [{ type: "text", text: JSON.stringify(artifacts, null, 2) }],
5053
+ details: { mode: "list", artifacts },
5054
+ };
5055
+ }
4780
5056
  const hasSingle = Boolean(params.agent && params.task);
4781
5057
  const hasParallel = Boolean(params.tasks?.length);
4782
5058
  const hasChain = Boolean(params.chain?.length);
@@ -4791,7 +5067,6 @@ export default function (pi: ExtensionAPI) {
4791
5067
  const validateAgent = (name: string): name is AgentName => name in AGENTS;
4792
5068
  const model = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
4793
5069
  const thinking = ctx.thinkingLevel as string | undefined;
4794
- const baseCwd = ctx.cwd;
4795
5070
 
4796
5071
  if (hasSingle) {
4797
5072
  if (!validateAgent(params.agent!)) {