@jals1212/ci-local-pi 0.3.0 → 0.3.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/CHANGELOG.md CHANGED
@@ -6,6 +6,16 @@ add or change behaviour and a patch version fixes.
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## 0.3.1
10
+
11
+ ### Fixed
12
+
13
+ - A `ci-local.config.sh` written after the session started is now followed:
14
+ `ci_local_run`, or the end of a turn, sets up the status line, the cards and
15
+ the end card, which before came only after a `/reload`. When nothing can
16
+ follow the run (no UI, or no events file), `ci_local_run` no longer promises
17
+ a footer or an end card. (#51)
18
+
9
19
  ## 0.3.0
10
20
 
11
21
  ### Changed
@@ -89,6 +89,9 @@ function ciLocal(pi: ExtensionAPI, { launchWaitMs }: { launchWaitMs: number }) {
89
89
  // agent_start to agent_settled (in-run compaction and retries included).
90
90
  let delivery: ReturnType<typeof createDelivery> | undefined
91
91
  let runActive = false
92
+ // The reason of the session's session_start (createStatusLine reads it);
93
+ // undefined before one and after session_shutdown, when nothing is followed.
94
+ let startReason: string | undefined
92
95
  // The runs ci_local_run started, by pid, until their run shows in the events
93
96
  // file (seen) or they end. One that ends unseen, after the tool returned,
94
97
  // gets an end card of its own (exitCard): no event will ever name it. Each
@@ -104,7 +107,10 @@ function ciLocal(pi: ExtensionAPI, { launchWaitMs }: { launchWaitMs: number }) {
104
107
  runActive = false
105
108
  delivery?.boundary()
106
109
  })
107
- pi.on('turn_end', async () => delivery?.boundary())
110
+ pi.on('turn_end', async (_event, ctx) => {
111
+ follow(ctx)
112
+ delivery?.boundary()
113
+ })
108
114
  pi.on('session_compact', async () => delivery?.boundary())
109
115
  pi.on('session_compact_failed', async () => delivery?.boundary())
110
116
 
@@ -167,6 +173,8 @@ function ciLocal(pi: ExtensionAPI, { launchWaitMs }: { launchWaitMs: number }) {
167
173
  async execute(_id, params, signal, _onUpdate, ctx) {
168
174
  const found = findProject(ctx.cwd)
169
175
  if (!found) throw new Error(`no ci-local.config.sh with a literal CI_PROJECT at or above ${ctx.cwd}`)
176
+ // Followed before the launch, so the tracker is there when the run starts.
177
+ const followed = follow(ctx)
170
178
  const sessionId = ctx.sessionManager.getSessionId()
171
179
  const launch = launchRun({ repo: found.repo, args: params.args ?? [], sessionId })
172
180
  const tracked: Launch = Object.assign(launch, { seen: false, waiting: true, sessionId })
@@ -178,7 +186,7 @@ function ciLocal(pi: ExtensionAPI, { launchWaitMs }: { launchWaitMs: number }) {
178
186
  if (launch.pid !== undefined) launches.delete(launch.pid)
179
187
  if (launch.error) throw new Error(`cannot start ${launch.bin}: ${launch.error}`)
180
188
  }
181
- return { content: [{ type: 'text', text: launchReport(result, launch, found.project) }], details: { kind: result.kind, pid: launch.pid } }
189
+ return { content: [{ type: 'text', text: launchReport(result, launch, found.project, { followed }) }], details: { kind: result.kind, pid: launch.pid } }
182
190
  },
183
191
  })
184
192
 
@@ -197,11 +205,25 @@ function ciLocal(pi: ExtensionAPI, { launchWaitMs }: { launchWaitMs: number }) {
197
205
  pi.on('session_start', async (event, ctx: ExtensionContext) => {
198
206
  stop()
199
207
  runActive = false
200
- if (!ctx.hasUI) return
208
+ startReason = event.reason
209
+ follow(ctx)
210
+ })
211
+
212
+ /**
213
+ * Sets up what follows the runs of the session's repository (the tick timer,
214
+ * the status line, the cards, the delivery to the agent); true once it is
215
+ * running. session_start calls it, and so do ci_local_run and turn_end while
216
+ * nothing is followed yet: a ci-local.config.sh written during the session
217
+ * is picked up then, not only after a /reload (#51).
218
+ */
219
+ function follow(ctx: ExtensionContext): boolean {
220
+ if (timer) return true
221
+ if (startReason === undefined || !ctx.hasUI) return false
222
+ const reason = startReason
201
223
  const found = findProject(ctx.cwd)
202
- if (!found) return
224
+ if (!found) return false
203
225
  const file = eventsFileFor(found.project, process.env, found.repo)
204
- if (!file) return // CI_LOCAL_EVENTS=off, or no private cache: runs write no events
226
+ if (!file) return false // CI_LOCAL_EVENTS=off, or no private cache: runs write no events
205
227
  const tracker = createTracker()
206
228
  // Start cards this session already shows (a reload, a resumed session): not again.
207
229
  for (const entry of ctx.sessionManager.getBranch()) {
@@ -226,7 +248,7 @@ function ciLocal(pi: ExtensionAPI, { launchWaitMs }: { launchWaitMs: number }) {
226
248
  // The status line leaves out a run already over whose result a session
227
249
  // already showed, and records each finished run it shows (see
228
250
  // createStatusLine in core.js).
229
- const statusLine = createStatusLine({ file, sessionId, reason: event.reason })
251
+ const statusLine = createStatusLine({ file, sessionId, reason })
230
252
 
231
253
  const tick = () => {
232
254
  let run
@@ -309,10 +331,12 @@ function ciLocal(pi: ExtensionAPI, { launchWaitMs }: { launchWaitMs: number }) {
309
331
  tick()
310
332
  timer = setInterval(tick, POLL_MS)
311
333
  timer.unref?.()
312
- })
334
+ return true
335
+ }
313
336
 
314
337
  pi.on('session_shutdown', async () => {
315
338
  stop()
339
+ startReason = undefined
316
340
  delete (globalThis as Record<symbol, unknown>)[FLAG]
317
341
  })
318
342
  }
@@ -618,14 +618,21 @@ function endedLine(launch) {
618
618
  return `ci-local ${verb} ${howEnded(launch)} before a run started`
619
619
  }
620
620
 
621
- /** What ci_local_run tells the agent of a launch and how it stands. */
622
- export function launchReport(result, launch, project) {
621
+ /**
622
+ * What ci_local_run tells the agent of a launch and how it stands. followed:
623
+ * whether this session follows the run (a footer and an end card will come).
624
+ */
625
+ export function launchReport(result, launch, project, { followed = true } = {}) {
623
626
  const where = `Output: ${launch.output}.`
624
- const follow = 'The footer follows it and its end card reaches you when it ends: do not poll, sleep or run `ci-local --status`.'
627
+ const follow = followed
628
+ ? 'The footer follows it and its end card reaches you when it ends: do not poll, sleep or run `ci-local --status`.'
629
+ : 'This session cannot follow it (no UI, or no events file to read), so no footer or end card will come: read its output, or ask ci_local_status.'
625
630
  if (result.kind === 'started')
626
631
  return `ci-local started (pid ${launch.pid}) for ${project}: ${stateText(result.run.state)}. ${follow} ${where}`
627
- if (result.kind === 'waiting')
628
- return `ci-local launched (pid ${launch.pid}) for ${project}, no event yet: another run of ${project} may hold its events file until it ends. ${follow} ${where}`
632
+ if (result.kind === 'waiting') {
633
+ const why = followed ? `: another run of ${project} may hold its events file until it ends` : ''
634
+ return `ci-local launched (pid ${launch.pid}) for ${project}, no event yet${why}. ${follow} ${where}`
635
+ }
629
636
  const tail = outputTail(launch.output)
630
637
  return [
631
638
  `${endedLine(launch)}. ${where}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jals1212/ci-local-pi",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Pi extension and skill for @jals1212/ci-local: the state of this repository's ci-local run in Pi's status line, cards and a read-only tool for the agent.",
5
5
  "license": "MIT",
6
6
  "author": "jals1212",
@@ -4,7 +4,7 @@ description: "Trigger: ci-local, run CI locally, ci-local.config.sh, CI_PROJECT,
4
4
  license: MIT
5
5
  metadata:
6
6
  author: jals1212
7
- version: "0.3.0"
7
+ version: "0.3.1"
8
8
  ---
9
9
 
10
10
  ## Activation Contract