@shanepadgett/tau-agent 0.41.0 → 0.41.2

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.
@@ -902,17 +902,11 @@ async function switchBranch(git: GitRunner, path: string, branch: string): Promi
902
902
  return;
903
903
  }
904
904
 
905
- const remote = await git.run(["show-ref", "--verify", `refs/remotes/origin/${branch}`], {
905
+ await git.run(["remote", "set-branches", "--add", "origin", branch], { cwd: path });
906
+ await git.run(["fetch", "--quiet", "--depth=1", "origin", branch], {
906
907
  cwd: path,
907
- optional: true,
908
- timeout: BRANCH_LOOKUP_TIMEOUT_MS,
908
+ timeout: BRANCH_SWITCH_TIMEOUT_MS,
909
909
  });
910
- if (!remote.trim()) {
911
- await git.run(["fetch", "--quiet", "--depth=1", "origin", `refs/heads/${branch}:refs/remotes/origin/${branch}`], {
912
- cwd: path,
913
- timeout: BRANCH_SWITCH_TIMEOUT_MS,
914
- });
915
- }
916
910
  await git.run(["switch", "--track", "-c", branch, `origin/${branch}`], {
917
911
  cwd: path,
918
912
  timeout: BRANCH_SWITCH_TIMEOUT_MS,
@@ -18,32 +18,29 @@ interface SubagentSessionState {
18
18
 
19
19
  const SUBAGENT_SESSION_STATE_TYPE = "tau.subagent.disabled";
20
20
 
21
- const params = Type.Union([
22
- Type.Object(
23
- {
24
- agent: Type.String({ minLength: 1 }),
25
- task: Type.String({ minLength: 1 }),
26
- files: Type.Optional(
27
- Type.Array(Type.String({ minLength: 1 }), {
28
- description: "Files to autoread into the child's context before this turn",
29
- }),
30
- ),
31
- },
32
- { additionalProperties: false },
33
- ),
34
- Type.Object(
35
- {
36
- thread: Type.String({ minLength: 1 }),
37
- task: Type.String({ minLength: 1 }),
38
- files: Type.Optional(
39
- Type.Array(Type.String({ minLength: 1 }), {
40
- description: "Files to autoread into the child's context before this turn",
41
- }),
42
- ),
43
- },
44
- { additionalProperties: false },
45
- ),
46
- ]);
21
+ const params = Type.Object(
22
+ {
23
+ agent: Type.Optional(
24
+ Type.String({
25
+ minLength: 1,
26
+ description: "Fresh agent name. Pass agent or thread, never both.",
27
+ }),
28
+ ),
29
+ thread: Type.Optional(
30
+ Type.String({
31
+ minLength: 1,
32
+ description: "Retained thread id. Pass thread or agent, never both.",
33
+ }),
34
+ ),
35
+ task: Type.String({ minLength: 1 }),
36
+ files: Type.Optional(
37
+ Type.Array(Type.String({ minLength: 1 }), {
38
+ description: "Files to autoread into the child's context before this turn",
39
+ }),
40
+ ),
41
+ },
42
+ { additionalProperties: false },
43
+ );
47
44
 
48
45
  export default function subagentExtension(pi: ExtensionAPI): void {
49
46
  const runtime = new SubagentRuntime(pi);
@@ -215,7 +212,7 @@ Use \`subagent\` only when an available agent's listed purpose matches the deleg
215
212
  Available agents for this turn:
216
213
  ${lines.join("\n") || "none"}
217
214
 
218
- Start a fresh thread with \`agent\` and \`task\`. Continue an existing thread with \`thread\` and \`task\`. Reuse a thread when feedback or follow-up work depends on its prior reads and reasoning. Start fresh for unrelated work or when its context is stale or oversized.
215
+ Start a fresh thread with \`agent\` and \`task\`. Continue an existing thread with \`thread\` and \`task\`. Pass exactly one of \`agent\` or \`thread\`, never both and never neither. Reuse a thread when feedback or follow-up work depends on its prior reads and reasoning. Start fresh for unrelated work or when its context is stale or oversized.
219
216
 
220
217
  Pass \`files\` when exact relevant files are already known. Tau autoreads current line-numbered snapshots into that child turn before it starts.
221
218
 
@@ -296,25 +293,48 @@ Delegate one focused task per call. Children do not inherit parent messages. Inc
296
293
  async execute(_id, raw, signal, onUpdate, ctx) {
297
294
  const task = raw.task.trim();
298
295
  const files = [...new Set((raw.files ?? []).map((path) => path.trim()))];
299
- const continuing = "thread" in raw;
296
+ const agentName = raw.agent?.trim() || undefined;
297
+ const threadKey = raw.thread?.trim() || undefined;
300
298
  const parentModel = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : "unavailable";
301
299
  const parentThinking = pi.getThinkingLevel();
302
- const agent = continuing ? raw.thread.trim() : raw.agent.trim();
303
- const threadKey = continuing ? raw.thread.trim() : undefined;
304
300
 
305
301
  failureNotify = (message) => {
306
302
  ctx.ui.notify(message, "warning");
307
303
  };
308
304
  dashboard.setInteractive(ctx.mode === "tui" && ctx.hasUI);
309
305
 
310
- if (!task || !agent || files.some((path) => !path)) {
311
- const error = continuing
312
- ? "Subagent continuation requires non-empty thread, task, and file paths"
313
- : "Subagent input requires non-empty agent, task, and file paths";
314
- return failedToolResult(agent, task, "queue", parentModel, parentThinking, error, threadKey);
306
+ const failQueue = (agent: string, error: string, thread?: string) =>
307
+ failedToolResult(agent, task, "queue", parentModel, parentThinking, error, thread);
308
+
309
+ if (!task || files.some((path) => !path)) {
310
+ return failQueue(
311
+ agentName ?? threadKey ?? "",
312
+ threadKey !== undefined
313
+ ? "Subagent continuation requires non-empty thread, task, and file paths"
314
+ : "Subagent input requires non-empty agent, task, and file paths",
315
+ threadKey,
316
+ );
317
+ }
318
+ if (agentName !== undefined && threadKey !== undefined) {
319
+ return failQueue(
320
+ agentName,
321
+ "Subagent input requires exactly one of agent or thread, not both",
322
+ threadKey,
323
+ );
315
324
  }
316
325
 
317
- if (continuing) {
326
+ const onUpdateDetails = (details: SubagentDetails) =>
327
+ onUpdate?.({
328
+ content: [
329
+ {
330
+ type: "text",
331
+ text: details.currentActivity ?? details.response ?? `${details.agent}: ${details.status}`,
332
+ },
333
+ ],
334
+ details,
335
+ });
336
+
337
+ if (threadKey !== undefined) {
318
338
  const disabledContinuation = await disabledContinuationResult(
319
339
  ctx,
320
340
  threadKey,
@@ -323,29 +343,36 @@ Delegate one focused task per call. Children do not inherit parent messages. Inc
323
343
  parentThinking,
324
344
  );
325
345
  if (disabledContinuation) return disabledContinuation;
346
+ return runtime.execute({
347
+ agent: threadKey,
348
+ task,
349
+ files,
350
+ continuing: true,
351
+ threadKey,
352
+ ctx,
353
+ parentModel,
354
+ parentThinking,
355
+ signal,
356
+ onUpdate: onUpdateDetails,
357
+ resolveFreshDefinition: () => resolveFreshSubagentDefinition(ctx, threadKey),
358
+ });
359
+ }
360
+
361
+ if (agentName === undefined) {
362
+ return failQueue("", "Subagent input requires exactly one of agent or thread");
326
363
  }
327
364
 
328
365
  return runtime.execute({
329
- agent,
366
+ agent: agentName,
330
367
  task,
331
368
  files,
332
- continuing,
333
- threadKey,
369
+ continuing: false,
334
370
  ctx,
335
371
  parentModel,
336
372
  parentThinking,
337
373
  signal,
338
- onUpdate: (details) =>
339
- onUpdate?.({
340
- content: [
341
- {
342
- type: "text",
343
- text: details.currentActivity ?? details.response ?? `${details.agent}: ${details.status}`,
344
- },
345
- ],
346
- details,
347
- }),
348
- resolveFreshDefinition: () => resolveFreshSubagentDefinition(ctx, agent),
374
+ onUpdate: onUpdateDetails,
375
+ resolveFreshDefinition: () => resolveFreshSubagentDefinition(ctx, agentName),
349
376
  });
350
377
  },
351
378
  renderCall(args, theme, context) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shanepadgett/tau-agent",
3
- "version": "0.41.0",
3
+ "version": "0.41.2",
4
4
  "description": "Tau is a custom agentic harness built with pi extensions",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -35,7 +35,7 @@
35
35
  ],
36
36
  "dependencies": {
37
37
  "@ast-grep/wasm": "0.45.1",
38
- "@shanepadgett/tau-tui": "0.41.0",
38
+ "@shanepadgett/tau-tui": "0.41.2",
39
39
  "@vscode/tree-sitter-wasm": "0.3.1",
40
40
  "image-size": "2.0.2",
41
41
  "smol-toml": "1.8.0",