@jals1212/ci-local-pi 0.2.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 +18 -0
- package/README.md +2 -2
- package/extensions/ci-local.ts +33 -9
- package/extensions/core.js +14 -7
- package/package.json +1 -1
- package/skills/ci-local/SKILL.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,24 @@ 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
|
+
|
|
19
|
+
## 0.3.0
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Status line: a `·` separates the name from the state, as other footer
|
|
24
|
+
integrations do (`🚦 ci-local · ✓ passed · 4m12s`, was
|
|
25
|
+
`🚦 ci-local ✓ passed · 4m12s`). (#45)
|
|
26
|
+
|
|
9
27
|
## 0.2.0
|
|
10
28
|
|
|
11
29
|
### Added
|
package/README.md
CHANGED
|
@@ -23,8 +23,8 @@ In a session opened inside a repository with `ci-local.config.sh` (with a
|
|
|
23
23
|
literal `CI_PROJECT=`), it follows the events file of that project; it never
|
|
24
24
|
runs ci-local or Docker itself:
|
|
25
25
|
|
|
26
|
-
- **Status line**: `🚦 ci-local ◌ queued · 2 ahead (erp-ci running)`, `🚦 ci-local ⧗ [3/8] lint · 2m05s`,
|
|
27
|
-
then `🚦 ci-local ✓ passed · 4m12s` or `🚦 ci-local ✗ failed at lint · 2m10s` until
|
|
26
|
+
- **Status line**: `🚦 ci-local · ◌ queued · 2 ahead (erp-ci running)`, `🚦 ci-local · ⧗ [3/8] lint · 2m05s`,
|
|
27
|
+
then `🚦 ci-local · ✓ passed · 4m12s` or `🚦 ci-local · ✗ failed at lint · 2m10s` until
|
|
28
28
|
the next run. A run already over when a session starts shows only while its
|
|
29
29
|
result is undelivered, like an unread message: it ended with no session of
|
|
30
30
|
the repository open. Once a session has shown it finished, a later session
|
package/extensions/ci-local.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Pi extension for @jals1212/ci-local: the state of this repository's
|
|
2
2
|
// ci-local run in Pi's own UI, so neither the agent nor you write it by hand.
|
|
3
3
|
//
|
|
4
|
-
// - Status line: `🚦 ci-local ⧗ [3/8] lint · 2m05s`, `🚦 ci-local ◌ queued ·
|
|
5
|
-
// 2 ahead (erp-ci running)`, then `🚦 ci-local ✓ passed · 4m12s` / `🚦 ci-local
|
|
4
|
+
// - Status line: `🚦 ci-local · ⧗ [3/8] lint · 2m05s`, `🚦 ci-local · ◌ queued ·
|
|
5
|
+
// 2 ahead (erp-ci running)`, then `🚦 ci-local · ✓ passed · 4m12s` / `🚦 ci-local ·
|
|
6
6
|
// ✗ failed at lint` until the next run (🚦 is ci-local's own emoji, see BRAND).
|
|
7
7
|
// A run already over when a session starts is shown only if no session
|
|
8
8
|
// showed its result yet, like a message not yet delivered (createStatusLine).
|
|
@@ -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 () =>
|
|
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
|
-
|
|
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
|
|
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
|
}
|
package/extensions/core.js
CHANGED
|
@@ -284,10 +284,10 @@ export function createStatusLine({ file, sessionId, reason }) {
|
|
|
284
284
|
}
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
-
/** One short line for the footer: `🚦 ci-local ✓ passed · 4m12s`. */
|
|
287
|
+
/** One short line for the footer: `🚦 ci-local · ✓ passed · 4m12s`. */
|
|
288
288
|
export function footerText(state) {
|
|
289
289
|
// The state's glyph sits by the state, after the name.
|
|
290
|
-
return `${BRAND} ci-local ${GLYPHS[state.state] ?? GLYPHS.stopped} ${stateText(state)}`
|
|
290
|
+
return `${BRAND} ci-local · ${GLYPHS[state.state] ?? GLYPHS.stopped} ${stateText(state)}`
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
/** The state of a run in a few words, as the footer says it after its glyph. */
|
|
@@ -618,14 +618,21 @@ function endedLine(launch) {
|
|
|
618
618
|
return `ci-local ${verb} ${howEnded(launch)} before a run started`
|
|
619
619
|
}
|
|
620
620
|
|
|
621
|
-
/**
|
|
622
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
+
"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",
|