@rse/ase 2.0.7 → 2.0.8

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.
Files changed (33) hide show
  1. package/dst/ase-agent-relay-client.js +3 -4
  2. package/dst/ase-config-schema.js +4 -1
  3. package/dst/ase-lib-fetch.js +12 -0
  4. package/dst/ase-lib-server-cli.js +8 -5
  5. package/dst/ase-task-board-diff.js +120 -0
  6. package/dst/ase-task-board-tui-control.js +8 -5
  7. package/dst/ase-task-board-tui-model.js +54 -14
  8. package/dst/ase-task-board-tui-popup.js +41 -8
  9. package/dst/ase-task-board-tui.js +42 -27
  10. package/dst/ase-task-board-web-client.css +1 -1
  11. package/dst/ase-task-board-web-client.html +16 -0
  12. package/dst/ase-task-board-web-client.js +33 -33
  13. package/dst/ase-task-board-web-server.js +44 -9
  14. package/dst/ase-task-board.js +12 -4
  15. package/dst/ase-task-store-client.js +4 -5
  16. package/dst/man/ase-config-init.md +2 -1
  17. package/dst/man/ase-config.md +5 -0
  18. package/dst/man/ase-task-board.md +44 -2
  19. package/package.json +7 -6
  20. package/plugin/.claude-plugin/plugin.json +1 -1
  21. package/plugin/.codex-plugin/plugin.json +1 -1
  22. package/plugin/.github/plugin/plugin.json +1 -1
  23. package/plugin/meta/ase-common-task.md +24 -0
  24. package/plugin/mods/ase-mods-common.ts +73 -42
  25. package/plugin/mods/ase-mods-task-edit.ts +427 -0
  26. package/plugin/mods/ase-mods.ts +45 -14
  27. package/plugin/skills/ase-help-intent/data.md +78 -8
  28. package/plugin/skills/ase-task-edit/SKILL.md +114 -9
  29. package/plugin/skills/ase-task-edit/help.md +60 -0
  30. package/plugin/skills/ase-task-grill/SKILL.md +35 -20
  31. package/plugin/skills/ase-task-grill/help.md +18 -8
  32. /package/plugin/mods/{ase-mods-evaluate.ts → ase-mods-meta-evaluate.ts} +0 -0
  33. /package/plugin/mods/{ase-mods-grill.ts → ase-mods-task-grill.ts} +0 -0
@@ -16,10 +16,45 @@ import { palette, loadPalette, cx } from "./ase-task-board-tui-style.js";
16
16
  import { sanitize, renderDialog, renderConfirm, renderTransfer, renderAssign, renderPrompt, renderBusy } from "./ase-task-board-tui-popup.js";
17
17
  /* render the whole screen */
18
18
  const renderScreen = (ctx, project) => {
19
- const { columns, rows, all, board, surface, view, filter, typing, dialog, notice, carry, confirm, transfer, assign, prompt, headRef, tabLabels, dialogSel, dialogLines, transferCard, transferList, dim, store, busy, busyTick, agents } = ctx;
19
+ const { columns, rows, all, board, surface, view, filter, typing, dialog, notice, carry, confirm, transfer, assign, prompt, headRef, tabLabels, dialogW, dialogSel, dialogLines, dialogDiff, transferCard, transferList, dim, store, busy, busyTick, agents, watched } = ctx;
20
20
  /* refuse to draw into a too small window */
21
21
  if (columns < 40 || rows < 16)
22
22
  return h(Box, { width: columns, height: rows, justifyContent: "center", alignItems: "center" }, h(Text, cx("signal"), `window too small (${columns}×${rows}) — needs at least 40×16`));
23
+ /* the dialog and popups on top of the screen */
24
+ const overlays = [
25
+ dialog !== null ? renderDialog({
26
+ card: all.cards.get(dialog.id),
27
+ group: all.groups.find((g) => g.lanes.some((l) => l.status === all.cards.get(dialog.id)?.status))?.title,
28
+ id: dialog.id,
29
+ pred: all.pred.get(dialog.id) ?? [],
30
+ succ: all.succ.get(dialog.id) ?? [],
31
+ tint: (ref) => {
32
+ const c = all.cards.get(ref);
33
+ const tone = c !== undefined ? toneOf(all, c) : "idle";
34
+ return tone === "active" ? palette.accent : tone === "done" ? palette.dim : palette.normal;
35
+ },
36
+ tabs: tabLabels,
37
+ tab: dialogSel,
38
+ first: dialog.first,
39
+ scroll: dialog.scrolls[dialogSel] ?? 0,
40
+ lines: dialogLines,
41
+ width: dialogW,
42
+ columns,
43
+ rows,
44
+ notice,
45
+ viewer: watched !== undefined,
46
+ diffed: dialogDiff
47
+ }) : null,
48
+ confirm !== null ? renderConfirm(confirm.id, confirm.yes, columns, rows) : null,
49
+ transfer !== null && transferCard !== undefined ?
50
+ renderTransfer(transfer.id, transferCard.status, transferList, transfer.at, columns, rows) : null,
51
+ assign !== null ? renderAssign(assign, assignChoices(assign), assignUnknown(assign), columns, rows) : null,
52
+ prompt !== null ? renderPrompt(prompt, columns, rows, prompt.request !== null ? requestChoices(prompt.request) : []) : null,
53
+ busy !== null ? renderBusy(busy.label, busy.since, busyTick, columns, rows) : null
54
+ ];
55
+ /* the task viewer shows only the dialog and popups, without the board */
56
+ if (watched !== undefined)
57
+ return h(Box, { width: columns, height: rows, flexDirection: "column" }, ...overlays);
23
58
  /* the status line in the last line of the screen, below the key hints, enclosed
24
59
  on its left and right side by the downward lines of the rule above it,
25
60
  showing the kind and connection state of the task store (a disconnected one in
@@ -59,27 +94,7 @@ const renderScreen = (ctx, project) => {
59
94
  view === "flow" ? renderFlow(ctx) : renderAgents(ctx))
60
95
  .filter((el) => surface.keys || !String(el.key).startsWith("keys")),
61
96
  /* the horizontal rule between the key hints and the status line, turning downward with rounded corners at both ends */
62
- h(Text, cx("dim", dim && "dimmed"), " ╭" + "─".repeat(Math.max(0, columns - 4)) + "╮ "), status, dialog !== null ? renderDialog({
63
- card: all.cards.get(dialog.id),
64
- group: all.groups.find((g) => g.lanes.some((l) => l.status === all.cards.get(dialog.id)?.status))?.title,
65
- id: dialog.id,
66
- pred: all.pred.get(dialog.id) ?? [],
67
- succ: all.succ.get(dialog.id) ?? [],
68
- tint: (ref) => {
69
- const c = all.cards.get(ref);
70
- const tone = c !== undefined ? toneOf(all, c) : "idle";
71
- return tone === "active" ? palette.accent : tone === "done" ? palette.dim : palette.normal;
72
- },
73
- tabs: tabLabels,
74
- tab: dialogSel,
75
- first: dialog.first,
76
- scroll: dialog.scrolls[dialogSel] ?? 0,
77
- lines: dialogLines,
78
- columns,
79
- rows,
80
- notice
81
- }) : null, confirm !== null ? renderConfirm(confirm.id, confirm.yes, columns, rows) : null, transfer !== null && transferCard !== undefined ?
82
- renderTransfer(transfer.id, transferCard.status, transferList, transfer.at, columns, rows) : null, assign !== null ? renderAssign(assign, assignChoices(assign), assignUnknown(assign), columns, rows) : null, prompt !== null ? renderPrompt(prompt, columns, rows, prompt.request !== null ? requestChoices(prompt.request) : []) : null, busy !== null ? renderBusy(busy.label, busy.since, busyTick, columns, rows) : null);
97
+ h(Text, cx("dim", dim && "dimmed"), " ╭" + "─".repeat(Math.max(0, columns - 4)) + "╮ "), status, ...overlays);
83
98
  };
84
99
  /* pass each pressed SGR mouse report ("ESC[<b;x;y" plus "M"/"m" for press/release, 1-based)
85
100
  with its 0-based column/row, read directly from stdin, as Ink 8 drops them before
@@ -138,8 +153,8 @@ export const useMouseReports = (onPress) => {
138
153
  }, [stdin]);
139
154
  };
140
155
  /* the root component of the terminal board */
141
- const App = ({ log, initial, project, relay }) => {
142
- const ctx = useBoardState(log, initial, relay);
156
+ const App = ({ log, initial, project, relay, watched }) => {
157
+ const ctx = useBoardState(log, initial, relay, watched);
143
158
  /* handle the mouse, but ignore it while the modal busy popup is shown */
144
159
  useMouseReports((button, col, row) => {
145
160
  if (ctx.busy === null)
@@ -180,8 +195,8 @@ const lateErasing = (stream) => {
180
195
  }
181
196
  });
182
197
  };
183
- /* run the terminal board until the user quits */
184
- export const runTUI = async (log, relay) => {
198
+ /* run the terminal board (resp. with a task id, the task viewer) until the user quits */
199
+ export const runTUI = async (log, relay, watched) => {
185
200
  const initial = await buildBoard(log);
186
201
  const project = Task.projectIdOf(Task.projectRoot());
187
202
  loadPalette(log);
@@ -199,7 +214,7 @@ export const runTUI = async (log, relay) => {
199
214
  rewrite only the changed lines of a frame, as otherwise every frame
200
215
  is erased and redrawn entirely, which flickers in terminals not
201
216
  honoring synchronized output (DEC mode 2026), like tmux popups */
202
- const app = render(h(App, { log, initial, project, relay }), {
217
+ const app = render(h(App, { log, initial, project, relay, watched }), {
203
218
  alternateScreen: true, exitOnCtrlC: true, patchConsole: true, kittyKeyboard: { mode: "auto" },
204
219
  incrementalRendering: true, stdout: lateErasing(process.stdout)
205
220
  });