@shanepadgett/tau-agent 0.2.1 → 0.3.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.
@@ -3,6 +3,7 @@ import { join } from "node:path";
3
3
  import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
4
4
  import { createGitRunner, type GitRunner, loadRepoStatus } from "../../shared/git.ts";
5
5
  import { errorText } from "../../shared/text.ts";
6
+ import { PublishActivityPanel, type PublishProgress } from "./publish-ui.ts";
6
7
 
7
8
  const PACKAGE_PATHS = ["packages/tui/package.json", "packages/agent/package.json"] as const;
8
9
  const LOCKFILE_PATH = "package-lock.json";
@@ -38,14 +39,10 @@ export default function publishExtension(pi: ExtensionAPI): void {
38
39
  ctx.ui.notify("Publishing requires interactive confirmation.", "error");
39
40
  return;
40
41
  }
41
- ctx.ui.setStatus("publish", "preparing release");
42
42
  try {
43
43
  await publish(pi, ctx);
44
44
  } catch (error) {
45
45
  ctx.ui.notify(`Publish failed: ${errorText(error)}`, "error");
46
- } finally {
47
- ctx.ui.setStatus("publish", undefined);
48
- ctx.ui.setWidget("publish", undefined);
49
46
  }
50
47
  },
51
48
  });
@@ -86,19 +83,50 @@ async function publish(pi: ExtensionAPI, ctx: ExtensionCommandContext): Promise<
86
83
  );
87
84
  if (!confirmed) return;
88
85
 
89
- if (tag) await writeReleaseVersion(repo.root, manifests, finalVersion);
90
- ctx.ui.setStatus("publish", "packing packages");
91
- await run(pi, ctx, "npm", ["pack", "--dry-run", "--workspace", "@shanepadgett/tau-tui"], repo.root);
92
- await run(pi, ctx, "npm", ["pack", "--dry-run", "--workspace", "@shanepadgett/tau-agent"], repo.root);
86
+ if (ctx.mode !== "tui") {
87
+ await completePublish(pi, ctx, git, repo.root, manifests, tag, finalVersion, releaseTag);
88
+ return;
89
+ }
90
+ const failure = await ctx.ui.custom<Error | undefined>((tui, theme, _keybindings, done) => {
91
+ const progress = new PublishActivityPanel(tui, theme, releaseTag);
92
+ void completePublish(pi, ctx, git, repo.root, manifests, tag, finalVersion, releaseTag, progress)
93
+ .then(() => done(undefined))
94
+ .catch((error) => done(error instanceof Error ? error : new Error(errorText(error))));
95
+ return progress;
96
+ });
97
+ if (failure) throw failure;
98
+ }
99
+
100
+ async function completePublish(
101
+ pi: ExtensionAPI,
102
+ ctx: ExtensionCommandContext,
103
+ git: GitRunner,
104
+ root: string,
105
+ manifests: readonly PackageManifest[],
106
+ tag: string | undefined,
107
+ version: string,
108
+ releaseTag: string,
109
+ progress: PublishProgress | undefined = undefined,
110
+ ): Promise<void> {
111
+ if (tag) {
112
+ progress?.update("Updating version files");
113
+ await writeReleaseVersion(root, manifests, version);
114
+ }
115
+ progress?.update("Packing packages");
116
+ await run(pi, ctx, "npm", ["pack", "--dry-run", "--workspace", "@shanepadgett/tau-tui"], root);
117
+ await run(pi, ctx, "npm", ["pack", "--dry-run", "--workspace", "@shanepadgett/tau-agent"], root);
93
118
 
94
119
  if (tag) {
95
- await git.run(["add", ...PACKAGE_PATHS, LOCKFILE_PATH], { cwd: repo.root });
96
- await git.run(["commit", "-m", `chore(release): ${releaseTag}`], { cwd: repo.root });
120
+ progress?.update("Committing release version");
121
+ await git.run(["add", ...PACKAGE_PATHS, LOCKFILE_PATH], { cwd: root });
122
+ await git.run(["commit", "-m", `chore(release): ${releaseTag}`], { cwd: root });
97
123
  }
98
- await git.run(["tag", releaseTag], { cwd: repo.root });
99
- await git.run(["push", "origin", "HEAD"], { cwd: repo.root, timeout: 120_000 });
100
- await git.run(["push", "origin", releaseTag], { cwd: repo.root, timeout: 120_000 });
101
- await monitorWorkflow(pi, ctx, repo.root, await git.run(["rev-parse", "HEAD"], { cwd: repo.root }), releaseTag);
124
+ progress?.update(`Pushing ${releaseTag}`);
125
+ await git.run(["tag", releaseTag], { cwd: root });
126
+ await git.run(["push", "origin", "HEAD"], { cwd: root, timeout: 120_000 });
127
+ await git.run(["push", "origin", releaseTag], { cwd: root, timeout: 120_000 });
128
+ progress?.update("Waiting for GitHub Actions");
129
+ await monitorWorkflow(pi, ctx, root, await git.run(["rev-parse", "HEAD"], { cwd: root }), releaseTag, progress);
102
130
  }
103
131
 
104
132
  async function loadManifests(root: string): Promise<PackageManifest[]> {
@@ -188,6 +216,7 @@ async function monitorWorkflow(
188
216
  root: string,
189
217
  sha: string,
190
218
  tag: string,
219
+ progress: PublishProgress | undefined = undefined,
191
220
  ): Promise<void> {
192
221
  const deadline = Date.now() + WORKFLOW_WAIT_MS;
193
222
  while (Date.now() < deadline) {
@@ -211,10 +240,19 @@ async function monitorWorkflow(
211
240
  );
212
241
  const workflowRun = (JSON.parse(output) as WorkflowRun[])[0];
213
242
  if (workflowRun) {
214
- ctx.ui.setWidget("publish", [`Release ${tag}`, `GitHub Actions: ${workflowRun.status}`, workflowRun.url]);
243
+ progress?.update(`GitHub Actions: ${workflowRun.status}`, workflowRun.url);
215
244
  if (workflowRun.status === "completed") {
216
245
  if (workflowRun.conclusion === "success") {
217
- ctx.ui.notify(`Published ${tag}: ${workflowRun.url}`, "info");
246
+ const version = tag.slice(1);
247
+ ctx.ui.notify(
248
+ [
249
+ `Published ${tag}`,
250
+ `GitHub Actions: ${workflowRun.url}`,
251
+ `npm TUI: https://www.npmjs.com/package/@shanepadgett/tau-tui/v/${version}`,
252
+ `npm Agent: https://www.npmjs.com/package/@shanepadgett/tau-agent/v/${version}`,
253
+ ].join("\n"),
254
+ "info",
255
+ );
218
256
  return;
219
257
  }
220
258
  throw new Error(`GitHub Actions ${workflowRun.conclusion ?? "failed"}: ${workflowRun.url}`);
@@ -0,0 +1,54 @@
1
+ import type { Theme } from "@earendil-works/pi-coding-agent";
2
+ import { type Component, Text, type TUI } from "@earendil-works/pi-tui";
3
+ import { ToolPanel } from "@shanepadgett/tau-tui";
4
+
5
+ export interface PublishProgress {
6
+ update(status: string, detail?: string): void;
7
+ }
8
+
9
+ export class PublishActivityPanel implements Component, PublishProgress {
10
+ private readonly tui: TUI;
11
+ private readonly theme: Theme;
12
+ private readonly body = new Text("", 0, 0);
13
+ private readonly panel: ToolPanel;
14
+ private status = "Preparing release";
15
+ private detail: string | undefined;
16
+
17
+ constructor(tui: TUI, theme: Theme, tag: string) {
18
+ this.tui = tui;
19
+ this.theme = theme;
20
+ this.panel = new ToolPanel(theme, {
21
+ title: `Publishing ${tag}`,
22
+ secondary: "Editor is unavailable until this release finishes.",
23
+ header: [theme.fg("muted", "GitHub Actions publishes through npm trusted publishing.")],
24
+ body: this.body,
25
+ footer: { kind: "infoAck", message: "Publishing…", hints: [] },
26
+ });
27
+ this.renderBody();
28
+ }
29
+
30
+ update(status: string, detail: string | undefined = undefined): void {
31
+ this.status = status;
32
+ this.detail = detail;
33
+ this.renderBody();
34
+ this.tui.requestRender();
35
+ }
36
+
37
+ render(width: number): string[] {
38
+ return this.panel.render(width);
39
+ }
40
+
41
+ invalidate(): void {
42
+ this.panel.invalidate();
43
+ }
44
+
45
+ private renderBody(): void {
46
+ this.body.setText(
47
+ [
48
+ this.theme.fg("success", "✓ Release confirmed"),
49
+ this.theme.fg("accent", `… ${this.status}`),
50
+ ...(this.detail ? [this.theme.fg("muted", this.detail)] : []),
51
+ ].join("\n"),
52
+ );
53
+ }
54
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shanepadgett/tau-agent",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Tau is a custom agentic harness built with pi extensions",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,7 +28,7 @@
28
28
  "README.md"
29
29
  ],
30
30
  "dependencies": {
31
- "@shanepadgett/tau-tui": "0.2.1",
31
+ "@shanepadgett/tau-tui": "0.3.0",
32
32
  "@toon-format/toon": "2.3.0"
33
33
  },
34
34
  "peerDependencies": {