@kurokeita/add-skill 2.5.1 → 2.6.1

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.
package/dist/bin/cli.js CHANGED
@@ -1690,7 +1690,7 @@ async function remove(type, options) {
1690
1690
  }
1691
1691
 
1692
1692
  // package.json
1693
- var version = "2.5.1";
1693
+ var version = "2.6.1";
1694
1694
 
1695
1695
  // bin/cli.ts
1696
1696
  var program = new Command();
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: statusline-setup
3
- description: 'Set up the Claude Code or Gemini/Antigravity CLI statusline as side-by-side bordered boxes: a repo box (cwd, git branch, working-tree state, last commit), a session box (model, context % + token totals, 5h/7d quota with ETA), and a work box (the current branch's pull request and its linked issues or work items, fetched from GitHub with gh or Azure DevOps with az). Use when asked to "set up my statusline", "install statusline", "configure statusline", or to add a colored multi-line status line showing rate limits, token usage, or the PR and work items for the current branch. Detects OS and installs the appropriate variant (bash + jq on Linux/macOS, PowerShell on Windows).'
3
+ description: 'Set up the Claude Code or Gemini/Antigravity CLI statusline as side-by-side bordered boxes: a repo box (cwd, git branch, working-tree state, last commit), a session box (model, context % + token totals, 5h/7d quota with ETA), and a work box (the current branch''s pull request and its linked issues or work items, fetched from GitHub with gh or Azure DevOps with az). Use when asked to "set up my statusline", "install statusline", "configure statusline", or to add a colored multi-line status line showing rate limits, token usage, or the PR and work items for the current branch. Detects OS and installs the appropriate variant (bash + jq on Linux/macOS, PowerShell on Windows).'
4
4
  ---
5
5
 
6
6
  # Statusline Setup
@@ -1256,7 +1256,7 @@ The work box shows a few rows. The work pane is its scrollable companion: a Clau
1256
1256
 
1257
1257
  What it shows, in a side pane:
1258
1258
 
1259
- - **Summary and Steps** of the session, written by a Haiku call. It runs when the pane first opens and on **Refresh**, never per turn.
1259
+ - **Summary and Steps** of the session, written by a Haiku call. It runs when the pane first opens, at the end of each turn while the pane is open, and on **Refresh**.
1260
1260
  - **Pull requests**: the current branch's, those of branches this session committed to, and any PR of this repository linked in the conversation. Each shows its state, review, checks and comment count.
1261
1261
  - **Work items**: the PRs' linked issues or work items or, for a branch without a PR, the same branch refs the work box uses.
1262
1262
 
@@ -32,6 +32,7 @@ let isAutoOpened = false
32
32
  // Which conversation this process shows, and whether a prompt was sent in it here.
33
33
  let watchedId = ""
34
34
  let hasPromptedHere = false
35
+ let isClearPending = false
35
36
  let sessionStartedAt = Date.now()
36
37
 
37
38
  const runner =
@@ -168,7 +169,9 @@ async function checkResumed($: EngineInterface) {
168
169
  const id = await $.session.id()
169
170
  if (id !== watchedId) {
170
171
  watchedId = id
171
- hasPromptedHere = false
172
+ // A /clear starts its conversation here, though the transcript's /clear row counts as a turn.
173
+ hasPromptedHere = isClearPending
174
+ isClearPending = false
172
175
  isAutoOpenWanted = false
173
176
  isAutoOpened = false
174
177
  // Another conversation now: its branches start over from here.
@@ -232,16 +235,23 @@ export const register: Register = (on) => {
232
235
  on("turn.complete", async ($, e, next) => {
233
236
  const result = await next(e)
234
237
  if (e.agentId) return result
235
- // A main-conversation turn is when the session pushes branches and opens PRs.
238
+ // A main-conversation turn is when the session pushes branches and opens PRs,
239
+ // and moves its goal and steps on.
236
240
  void (async () => {
237
241
  await noteBranch($)
238
242
  if (isAutoOpenWanted && !isAutoOpened) return autoOpen($)
239
- if (await isPaneOpen($)) await refreshWork($)
243
+ if (await isPaneOpen($)) await Promise.all([refreshWork($), summarize($)])
240
244
  })()
241
245
 
242
246
  return result
243
247
  })
244
248
 
249
+ on("session.end", async (_$, e, next) => {
250
+ if (e.reason === "clear") isClearPending = true
251
+
252
+ return next(e)
253
+ })
254
+
245
255
  on("prompt.submit", async (_$, e, next) => {
246
256
  hasPromptedHere = true
247
257
 
@@ -249,6 +259,8 @@ export const register: Register = (on) => {
249
259
  })
250
260
 
251
261
  on("command.run", { command: "work" }, async ($) => {
262
+ // Opened by hand: auto-open has nothing left to do, so turns refresh the pane.
263
+ isAutoOpened = true
252
264
  void refreshWork($)
253
265
  await $.ui.open({
254
266
  id: PANE,
@@ -152,7 +152,15 @@ function fakeWorld(
152
152
  opened.push(e.id)
153
153
  return { value: { isPlaced: true } }
154
154
  })
155
- on("ui.panes", () => ({ value: [] }))
155
+ on("ui.panes", () => ({
156
+ value: opened.map((id) => ({
157
+ id,
158
+ title: "Work",
159
+ isShown: true,
160
+ isFocused: false,
161
+ isPlaced: true,
162
+ })),
163
+ }))
156
164
  on("command.register", (_$, e) => ({ value: { command: e.name } }))
157
165
  on("session.start", (_$, e) => ({ cwd: e.cwd }))
158
166
  return prompts
@@ -304,3 +312,67 @@ test("the picker and /resume open the pane once the resumed turns load", async (
304
312
  await clock.advance(5_000)
305
313
  expect(opened).toEqual(["work-items"])
306
314
  })
315
+
316
+ test("each turn summarizes again while the pane is open, not once it closes", async ($, on) => {
317
+ const clock = mock.clock(on)
318
+ const opened = ["work-items"]
319
+ const prompts = fakeWorld(on, opened)
320
+ on("turn.complete", (_$, e) => ({ text: e.answer }))
321
+ const turn = {
322
+ answer: "",
323
+ durationMs: 1,
324
+ isAborted: false,
325
+ reason: "answer",
326
+ } as const
327
+ await $.turn.complete({ ...turn, turnId: "t1" })
328
+ await clock.settle()
329
+ await $.turn.complete({ ...turn, turnId: "t2" })
330
+ await clock.settle()
331
+ expect(prompts.length).toBe(2)
332
+ opened.length = 0
333
+ await $.turn.complete({ ...turn, turnId: "t3" })
334
+ await clock.settle()
335
+ expect(prompts.length).toBe(2)
336
+ })
337
+
338
+ test("a resumed session with nothing to show still summarizes each turn once /work opens the pane", async ($, on) => {
339
+ const clock = mock.clock(on)
340
+ const opened: string[] = []
341
+ const prompts = fakeWorld(on, opened, [message("hello")], (argv) =>
342
+ argv[0] === "gh" ? '{"data":{"repository":{}}}' : undefined,
343
+ )
344
+ on("turn.complete", (_$, e) => ({ text: e.answer }))
345
+ fakeSession(on, { id: "a", turns: 4 })
346
+ await $.session.start(START)
347
+ await clock.settle()
348
+ expect(opened).toEqual([])
349
+ await $.command.run({ command: "work", args: "" })
350
+ await clock.settle()
351
+ const before = prompts.length
352
+ await $.turn.complete({
353
+ answer: "",
354
+ durationMs: 1,
355
+ isAborted: false,
356
+ reason: "answer",
357
+ turnId: "t1",
358
+ })
359
+ await clock.settle()
360
+ expect(prompts.length).toBe(before + 1)
361
+ })
362
+
363
+ test("/clear neither opens the pane nor summarizes the cleared conversation", async ($, on) => {
364
+ const clock = mock.clock(on)
365
+ const opened: string[] = []
366
+ const prompts = fakeWorld(on, opened, [message("/clear")])
367
+ on("session.end", (_$, e) => ({ sessionId: e.sessionId }))
368
+ const session = fakeSession(on, { id: "a", turns: 0 })
369
+ await $.session.start(START)
370
+ await clock.settle()
371
+ await $.session.end({ reason: "clear", sessionId: "a", resume: { id: "a" } })
372
+ // The cleared transcript opens with the /clear command row, a user turn.
373
+ session.id = "b"
374
+ session.turns = 1
375
+ await clock.advance(10_000)
376
+ expect(opened).toEqual([])
377
+ expect(prompts).toEqual([])
378
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kurokeita/add-skill",
3
- "version": "2.5.1",
3
+ "version": "2.6.1",
4
4
  "description": "CLI to install AI agent skills to various platforms",
5
5
  "type": "module",
6
6
  "bin": {