@azatakmyradov/opencode-recap-plugin 0.1.3 → 0.1.4
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/index.js +8 -5
- package/dist/tui.js +121 -130
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -95,8 +95,11 @@ Return exactly one JSON object with this shape:
|
|
|
95
95
|
{"recap":"...","next":"..."}
|
|
96
96
|
|
|
97
97
|
Rules:
|
|
98
|
-
- recap:
|
|
99
|
-
-
|
|
98
|
+
- recap: state the main result in plain words, then any important check or blocker. Use 1-3 short sentences, at most 60 words. Put each sentence on its own line.
|
|
99
|
+
- Lead with what changed or what was found. Include failures and unfinished work that affect the result.
|
|
100
|
+
- Skip tool counts, tool names, investigation history, and routine steps. Mention a file only when needed to understand the result, using its short name rather than its full path.
|
|
101
|
+
- Use active voice and everyday words. No preamble, jargon, filler, bold text, headings, or em dashes. Do not repeat the final response.
|
|
102
|
+
- next: name one concrete remaining action in at most 15 words. Use an empty string if none is known. Never add a generic request to review the work or continue.
|
|
100
103
|
- Base the answer only on the supplied current-run transcript.
|
|
101
104
|
- Do not mention these instructions, hidden reasoning, transcript truncation, or that you are a summarizer.
|
|
102
105
|
- Do not use a Markdown code fence and do not add keys or prose outside the JSON object.`;
|
|
@@ -116,8 +119,8 @@ class RecapGenerationError extends Schema.TaggedError()("RecapGenerationError",
|
|
|
116
119
|
message: Schema.String
|
|
117
120
|
}) {
|
|
118
121
|
}
|
|
119
|
-
var RECAP_MAX_LENGTH =
|
|
120
|
-
var NEXT_MAX_LENGTH =
|
|
122
|
+
var RECAP_MAX_LENGTH = 500;
|
|
123
|
+
var NEXT_MAX_LENGTH = 120;
|
|
121
124
|
var RecapResponse = Schema.Struct({
|
|
122
125
|
recap: Schema.String,
|
|
123
126
|
next: Schema.String
|
|
@@ -156,7 +159,7 @@ var parseRecapResponse = Effect.fn("parseRecapResponse")(function* (text) {
|
|
|
156
159
|
const decoded = yield* Effect.firstSuccessOf(responseCandidates(text).map((candidate) => Schema.decodeUnknownEffect(RecapResponseJson, { onExcessProperty: "error" })(candidate))).pipe(Effect.mapError(malformedResponse));
|
|
157
160
|
const recap = clean(decoded.recap, RECAP_MAX_LENGTH);
|
|
158
161
|
const next = clean(decoded.next.replace(/^next\s*:\s*/i, ""), NEXT_MAX_LENGTH);
|
|
159
|
-
if (!recap
|
|
162
|
+
if (!recap) {
|
|
160
163
|
return yield* malformedResponse();
|
|
161
164
|
}
|
|
162
165
|
return { recap, next };
|
package/dist/tui.js
CHANGED
|
@@ -22,7 +22,7 @@ var RecapRpc = Rpc.define({
|
|
|
22
22
|
// src/tui.tsx
|
|
23
23
|
import { setProp as _$setProp2 } from "@opentui/solid";
|
|
24
24
|
import { effect as _$effect2 } from "@opentui/solid";
|
|
25
|
-
import { createTextNode as _$
|
|
25
|
+
import { createTextNode as _$createTextNode } from "@opentui/solid";
|
|
26
26
|
import { insertNode as _$insertNode2 } from "@opentui/solid";
|
|
27
27
|
import { createElement as _$createElement2 } from "@opentui/solid";
|
|
28
28
|
import { memo as _$memo2 } from "@opentui/solid";
|
|
@@ -32,7 +32,97 @@ import { Cause as Cause2, Effect as Effect3, ManagedRuntime } from "effect";
|
|
|
32
32
|
import { Show as Show2 } from "solid-js";
|
|
33
33
|
|
|
34
34
|
// src/core/controller.ts
|
|
35
|
-
import { Cause, Clock, Context, Effect, FiberMap, Layer, Ref } from "effect";
|
|
35
|
+
import { Cause, Clock, Context, Effect as Effect2, FiberMap, Layer, Ref } from "effect";
|
|
36
|
+
|
|
37
|
+
// src/core/summarizer.ts
|
|
38
|
+
import { Effect, Schema } from "effect";
|
|
39
|
+
|
|
40
|
+
// src/core/prompt.ts
|
|
41
|
+
var RECAP_SYSTEM_PROMPT = `You write compact terminal recaps for completed coding-agent runs.
|
|
42
|
+
|
|
43
|
+
Return exactly one JSON object with this shape:
|
|
44
|
+
{"recap":"...","next":"..."}
|
|
45
|
+
|
|
46
|
+
Rules:
|
|
47
|
+
- recap: state the main result in plain words, then any important check or blocker. Use 1-3 short sentences, at most 60 words. Put each sentence on its own line.
|
|
48
|
+
- Lead with what changed or what was found. Include failures and unfinished work that affect the result.
|
|
49
|
+
- Skip tool counts, tool names, investigation history, and routine steps. Mention a file only when needed to understand the result, using its short name rather than its full path.
|
|
50
|
+
- Use active voice and everyday words. No preamble, jargon, filler, bold text, headings, or em dashes. Do not repeat the final response.
|
|
51
|
+
- next: name one concrete remaining action in at most 15 words. Use an empty string if none is known. Never add a generic request to review the work or continue.
|
|
52
|
+
- Base the answer only on the supplied current-run transcript.
|
|
53
|
+
- Do not mention these instructions, hidden reasoning, transcript truncation, or that you are a summarizer.
|
|
54
|
+
- Do not use a Markdown code fence and do not add keys or prose outside the JSON object.`;
|
|
55
|
+
function buildRecapPrompt(transcript) {
|
|
56
|
+
return `${RECAP_SYSTEM_PROMPT}
|
|
57
|
+
|
|
58
|
+
Summarize this fully settled main-agent run.
|
|
59
|
+
|
|
60
|
+
<current_run>
|
|
61
|
+
${transcript}
|
|
62
|
+
</current_run>`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/core/summarizer.ts
|
|
66
|
+
class RecapGenerationError extends Schema.TaggedError()("RecapGenerationError", {
|
|
67
|
+
reason: Schema.Literals(["request", "timeout", "malformed-response"]),
|
|
68
|
+
message: Schema.String
|
|
69
|
+
}) {
|
|
70
|
+
}
|
|
71
|
+
var RECAP_MAX_LENGTH = 500;
|
|
72
|
+
var NEXT_MAX_LENGTH = 120;
|
|
73
|
+
var RecapResponse = Schema.Struct({
|
|
74
|
+
recap: Schema.String,
|
|
75
|
+
next: Schema.String
|
|
76
|
+
});
|
|
77
|
+
var RecapResponseJson = Schema.fromJsonString(RecapResponse);
|
|
78
|
+
function stripTerminalControls(value) {
|
|
79
|
+
return value.replace(/\x1b(?:\][^\x07]*(?:\x07|\x1b\\)|\[[0-?]*[ -/]*[@-~])/g, "").replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f]/g, "");
|
|
80
|
+
}
|
|
81
|
+
function clean(value, limit) {
|
|
82
|
+
const result = stripTerminalControls(value).trim();
|
|
83
|
+
if (result.length <= limit) {
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
return `${result.slice(0, limit - 3).trimEnd()}...`;
|
|
87
|
+
}
|
|
88
|
+
function responseCandidates(text) {
|
|
89
|
+
const trimmed = text.trim();
|
|
90
|
+
const candidates = [trimmed];
|
|
91
|
+
for (const match of trimmed.matchAll(/```(?:json)?\s*([\s\S]*?)```/gi)) {
|
|
92
|
+
if (match[1]) {
|
|
93
|
+
candidates.push(match[1].trim());
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const first = trimmed.indexOf("{");
|
|
97
|
+
const last = trimmed.lastIndexOf("}");
|
|
98
|
+
if (first >= 0 && last > first) {
|
|
99
|
+
candidates.push(trimmed.slice(first, last + 1));
|
|
100
|
+
}
|
|
101
|
+
return [...new Set(candidates)];
|
|
102
|
+
}
|
|
103
|
+
var malformedResponse = () => new RecapGenerationError({
|
|
104
|
+
reason: "malformed-response",
|
|
105
|
+
message: "The recap model did not return valid recap JSON."
|
|
106
|
+
});
|
|
107
|
+
var parseRecapResponse = Effect.fn("parseRecapResponse")(function* (text) {
|
|
108
|
+
const decoded = yield* Effect.firstSuccessOf(responseCandidates(text).map((candidate) => Schema.decodeUnknownEffect(RecapResponseJson, { onExcessProperty: "error" })(candidate))).pipe(Effect.mapError(malformedResponse));
|
|
109
|
+
const recap = clean(decoded.recap, RECAP_MAX_LENGTH);
|
|
110
|
+
const next = clean(decoded.next.replace(/^next\s*:\s*/i, ""), NEXT_MAX_LENGTH);
|
|
111
|
+
if (!recap) {
|
|
112
|
+
return yield* malformedResponse();
|
|
113
|
+
}
|
|
114
|
+
return { recap, next };
|
|
115
|
+
});
|
|
116
|
+
var summarizeRun = Effect.fn("summarizeRun")(function* (options) {
|
|
117
|
+
const text = yield* options.generate({
|
|
118
|
+
prompt: buildRecapPrompt(options.transcript),
|
|
119
|
+
model: options.model
|
|
120
|
+
}).pipe(Effect.timeout(options.timeoutMs ?? 45000), Effect.mapError((error) => error._tag === "TimeoutError" ? new RecapGenerationError({
|
|
121
|
+
reason: "timeout",
|
|
122
|
+
message: "The recap model request timed out."
|
|
123
|
+
}) : error));
|
|
124
|
+
return yield* parseRecapResponse(text);
|
|
125
|
+
});
|
|
36
126
|
|
|
37
127
|
// src/core/transcript.ts
|
|
38
128
|
var TOOL_ARGUMENT_MAX_BYTES = 2000;
|
|
@@ -172,31 +262,24 @@ function serializeRunTranscript(messages, detail, maxBytes = TRANSCRIPT_MAX_BYTE
|
|
|
172
262
|
return `${head}${marker}${tail}`;
|
|
173
263
|
}
|
|
174
264
|
function buildFallbackRecap(messages, outcome = "completed") {
|
|
175
|
-
const tools = [];
|
|
176
265
|
let final = "";
|
|
177
266
|
for (const message of messages) {
|
|
178
267
|
if (message.type !== "assistant") {
|
|
179
268
|
continue;
|
|
180
269
|
}
|
|
181
270
|
for (const part of message.content) {
|
|
182
|
-
if (part.type === "tool") {
|
|
183
|
-
tools.push(part.name);
|
|
184
|
-
}
|
|
185
271
|
if (part.type === "text" && part.text.trim()) {
|
|
186
272
|
final = redactSecrets(part.text.trim());
|
|
187
273
|
}
|
|
188
274
|
}
|
|
189
275
|
}
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const toolCallLabel = tools.length === 1 ? "tool call" : "tool calls";
|
|
194
|
-
activity = ` The run used ${tools.length} ${toolCallLabel} across ${names.join(", ")}.`;
|
|
195
|
-
}
|
|
196
|
-
const result = final ? ` ${capped(final.replace(/\s+/g, " "), 700, "final response capped")}` : "";
|
|
276
|
+
const excerpt = stripTerminalControls(final).split(/\n\s*\n/)[0].replace(/\*\*|`/g, "").trim();
|
|
277
|
+
const result = excerpt.length <= 360 ? excerpt : `${excerpt.slice(0, 357).replace(/\s+\S*$/, "").trimEnd()}...`;
|
|
278
|
+
const status = `Run ${outcome}.`;
|
|
197
279
|
return {
|
|
198
|
-
recap:
|
|
199
|
-
|
|
280
|
+
recap: result ? outcome === "completed" || outcome === "succeeded" ? result : `${status}
|
|
281
|
+
${result}` : status,
|
|
282
|
+
next: ""
|
|
200
283
|
};
|
|
201
284
|
}
|
|
202
285
|
function selectRunMessages(messages, baseline) {
|
|
@@ -206,13 +289,13 @@ function selectRunMessages(messages, baseline) {
|
|
|
206
289
|
// src/core/controller.ts
|
|
207
290
|
class RecapControllerService extends Context.Service()("opencode-recap-plugin/RecapController") {
|
|
208
291
|
}
|
|
209
|
-
var createRecapController =
|
|
292
|
+
var createRecapController = Effect2.fn("createRecapController")(function* (deps) {
|
|
210
293
|
const state = yield* Ref.make({
|
|
211
294
|
inboxBaselines: new Map,
|
|
212
295
|
runs: new Map
|
|
213
296
|
});
|
|
214
297
|
const active = yield* FiberMap.make();
|
|
215
|
-
const invalidate =
|
|
298
|
+
const invalidate = Effect2.fn("RecapController.invalidate")(function* (sessionID) {
|
|
216
299
|
yield* FiberMap.remove(active, sessionID);
|
|
217
300
|
yield* Ref.modify(state, (current) => {
|
|
218
301
|
const runs = new Map(current.runs);
|
|
@@ -221,7 +304,7 @@ var createRecapController = Effect.fn("createRecapController")(function* (deps)
|
|
|
221
304
|
});
|
|
222
305
|
yield* deps.persist(undefined, sessionID);
|
|
223
306
|
});
|
|
224
|
-
const inbox =
|
|
307
|
+
const inbox = Effect2.fn("RecapController.inbox")(function* (sessionID, user) {
|
|
225
308
|
if (!user || deps.session(sessionID)?.parentID) {
|
|
226
309
|
return;
|
|
227
310
|
}
|
|
@@ -236,7 +319,7 @@ var createRecapController = Effect.fn("createRecapController")(function* (deps)
|
|
|
236
319
|
yield* FiberMap.remove(active, sessionID);
|
|
237
320
|
yield* deps.persist(undefined, sessionID);
|
|
238
321
|
});
|
|
239
|
-
const started =
|
|
322
|
+
const started = Effect2.fn("RecapController.started")(function* (sessionID) {
|
|
240
323
|
if (deps.session(sessionID)?.parentID) {
|
|
241
324
|
return;
|
|
242
325
|
}
|
|
@@ -253,7 +336,7 @@ var createRecapController = Effect.fn("createRecapController")(function* (deps)
|
|
|
253
336
|
});
|
|
254
337
|
yield* deps.persist(undefined, sessionID);
|
|
255
338
|
});
|
|
256
|
-
const terminal =
|
|
339
|
+
const terminal = Effect2.fn("RecapController.terminal")(function* (input) {
|
|
257
340
|
const baseline = yield* Ref.modify(state, (current) => {
|
|
258
341
|
const runs = new Map(current.runs);
|
|
259
342
|
const boundary = runs.get(input.sessionID);
|
|
@@ -263,7 +346,7 @@ var createRecapController = Effect.fn("createRecapController")(function* (deps)
|
|
|
263
346
|
if (!baseline) {
|
|
264
347
|
return;
|
|
265
348
|
}
|
|
266
|
-
const generation =
|
|
349
|
+
const generation = Effect2.gen(function* () {
|
|
267
350
|
yield* deps.syncMessages(input.sessionID);
|
|
268
351
|
const messages = selectRunMessages(deps.messages(input.sessionID), baseline);
|
|
269
352
|
if (messages.length === 0) {
|
|
@@ -275,7 +358,7 @@ var createRecapController = Effect.fn("createRecapController")(function* (deps)
|
|
|
275
358
|
eventID: input.eventID,
|
|
276
359
|
transcript: serializeRunTranscript(messages, input.detail),
|
|
277
360
|
model
|
|
278
|
-
}).pipe(
|
|
361
|
+
}).pipe(Effect2.map((recap) => ({ recap, fallback: false })), Effect2.catch((error) => deps.warning(`The recap model failed; showing a local fallback. ${error.message}`).pipe(Effect2.as({
|
|
279
362
|
recap: buildFallbackRecap(messages, input.outcome),
|
|
280
363
|
fallback: true
|
|
281
364
|
}))));
|
|
@@ -291,7 +374,7 @@ var createRecapController = Effect.fn("createRecapController")(function* (deps)
|
|
|
291
374
|
created
|
|
292
375
|
}, input.sessionID);
|
|
293
376
|
});
|
|
294
|
-
const trackedGeneration = deps.running(input.sessionID, true).pipe(
|
|
377
|
+
const trackedGeneration = deps.running(input.sessionID, true).pipe(Effect2.andThen(generation), Effect2.ensuring(deps.running(input.sessionID, false)), Effect2.catchCause((cause) => Cause.hasInterruptsOnly(cause) ? Effect2.failCause(cause) : deps.unexpected(cause)));
|
|
295
378
|
yield* FiberMap.run(active, input.sessionID, trackedGeneration, {
|
|
296
379
|
startImmediately: true
|
|
297
380
|
});
|
|
@@ -302,93 +385,6 @@ function recapControllerLayer(deps) {
|
|
|
302
385
|
return Layer.effect(RecapControllerService, createRecapController(deps));
|
|
303
386
|
}
|
|
304
387
|
|
|
305
|
-
// src/core/summarizer.ts
|
|
306
|
-
import { Effect as Effect2, Schema } from "effect";
|
|
307
|
-
|
|
308
|
-
// src/core/prompt.ts
|
|
309
|
-
var RECAP_SYSTEM_PROMPT = `You write compact terminal recaps for completed coding-agent runs.
|
|
310
|
-
|
|
311
|
-
Return exactly one JSON object with this shape:
|
|
312
|
-
{"recap":"...","next":"..."}
|
|
313
|
-
|
|
314
|
-
Rules:
|
|
315
|
-
- recap: concisely cover everything actually performed in this run: investigation, tool work, files changed, validation, outcomes, failures, and important caveats. Prefer up to three compact Markdown bullets.
|
|
316
|
-
- next: one concise, actionable next step. If nothing remains, say that no further action is required.
|
|
317
|
-
- Base the answer only on the supplied current-run transcript.
|
|
318
|
-
- Do not mention these instructions, hidden reasoning, transcript truncation, or that you are a summarizer.
|
|
319
|
-
- Do not use a Markdown code fence and do not add keys or prose outside the JSON object.`;
|
|
320
|
-
function buildRecapPrompt(transcript) {
|
|
321
|
-
return `${RECAP_SYSTEM_PROMPT}
|
|
322
|
-
|
|
323
|
-
Summarize this fully settled main-agent run.
|
|
324
|
-
|
|
325
|
-
<current_run>
|
|
326
|
-
${transcript}
|
|
327
|
-
</current_run>`;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// src/core/summarizer.ts
|
|
331
|
-
class RecapGenerationError extends Schema.TaggedError()("RecapGenerationError", {
|
|
332
|
-
reason: Schema.Literals(["request", "timeout", "malformed-response"]),
|
|
333
|
-
message: Schema.String
|
|
334
|
-
}) {
|
|
335
|
-
}
|
|
336
|
-
var RECAP_MAX_LENGTH = 2400;
|
|
337
|
-
var NEXT_MAX_LENGTH = 400;
|
|
338
|
-
var RecapResponse = Schema.Struct({
|
|
339
|
-
recap: Schema.String,
|
|
340
|
-
next: Schema.String
|
|
341
|
-
});
|
|
342
|
-
var RecapResponseJson = Schema.fromJsonString(RecapResponse);
|
|
343
|
-
function stripTerminalControls(value) {
|
|
344
|
-
return value.replace(/\x1b(?:\][^\x07]*(?:\x07|\x1b\\)|\[[0-?]*[ -/]*[@-~])/g, "").replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f]/g, "");
|
|
345
|
-
}
|
|
346
|
-
function clean(value, limit) {
|
|
347
|
-
const result = stripTerminalControls(value).trim();
|
|
348
|
-
if (result.length <= limit) {
|
|
349
|
-
return result;
|
|
350
|
-
}
|
|
351
|
-
return `${result.slice(0, limit - 3).trimEnd()}...`;
|
|
352
|
-
}
|
|
353
|
-
function responseCandidates(text) {
|
|
354
|
-
const trimmed = text.trim();
|
|
355
|
-
const candidates = [trimmed];
|
|
356
|
-
for (const match of trimmed.matchAll(/```(?:json)?\s*([\s\S]*?)```/gi)) {
|
|
357
|
-
if (match[1]) {
|
|
358
|
-
candidates.push(match[1].trim());
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
const first = trimmed.indexOf("{");
|
|
362
|
-
const last = trimmed.lastIndexOf("}");
|
|
363
|
-
if (first >= 0 && last > first) {
|
|
364
|
-
candidates.push(trimmed.slice(first, last + 1));
|
|
365
|
-
}
|
|
366
|
-
return [...new Set(candidates)];
|
|
367
|
-
}
|
|
368
|
-
var malformedResponse = () => new RecapGenerationError({
|
|
369
|
-
reason: "malformed-response",
|
|
370
|
-
message: "The recap model did not return valid recap JSON."
|
|
371
|
-
});
|
|
372
|
-
var parseRecapResponse = Effect2.fn("parseRecapResponse")(function* (text) {
|
|
373
|
-
const decoded = yield* Effect2.firstSuccessOf(responseCandidates(text).map((candidate) => Schema.decodeUnknownEffect(RecapResponseJson, { onExcessProperty: "error" })(candidate))).pipe(Effect2.mapError(malformedResponse));
|
|
374
|
-
const recap = clean(decoded.recap, RECAP_MAX_LENGTH);
|
|
375
|
-
const next = clean(decoded.next.replace(/^next\s*:\s*/i, ""), NEXT_MAX_LENGTH);
|
|
376
|
-
if (!recap || !next) {
|
|
377
|
-
return yield* malformedResponse();
|
|
378
|
-
}
|
|
379
|
-
return { recap, next };
|
|
380
|
-
});
|
|
381
|
-
var summarizeRun = Effect2.fn("summarizeRun")(function* (options) {
|
|
382
|
-
const text = yield* options.generate({
|
|
383
|
-
prompt: buildRecapPrompt(options.transcript),
|
|
384
|
-
model: options.model
|
|
385
|
-
}).pipe(Effect2.timeout(options.timeoutMs ?? 45000), Effect2.mapError((error) => error._tag === "TimeoutError" ? new RecapGenerationError({
|
|
386
|
-
reason: "timeout",
|
|
387
|
-
message: "The recap model request timed out."
|
|
388
|
-
}) : error));
|
|
389
|
-
return yield* parseRecapResponse(text);
|
|
390
|
-
});
|
|
391
|
-
|
|
392
388
|
// src/tui/inline.tsx
|
|
393
389
|
import { createComponent as _$createComponent } from "@opentui/solid";
|
|
394
390
|
import { isRenderable } from "@opentui/core";
|
|
@@ -397,44 +393,39 @@ import { createSignal, onCleanup, onMount, Show } from "solid-js";
|
|
|
397
393
|
|
|
398
394
|
// src/tui/card.tsx
|
|
399
395
|
import { effect as _$effect } from "@opentui/solid";
|
|
400
|
-
import { memo as _$memo } from "@opentui/solid";
|
|
401
|
-
import { insert as _$insert } from "@opentui/solid";
|
|
402
|
-
import { createTextNode as _$createTextNode } from "@opentui/solid";
|
|
403
396
|
import { insertNode as _$insertNode } from "@opentui/solid";
|
|
397
|
+
import { insert as _$insert } from "@opentui/solid";
|
|
398
|
+
import { memo as _$memo } from "@opentui/solid";
|
|
404
399
|
import { setProp as _$setProp } from "@opentui/solid";
|
|
405
400
|
import { createElement as _$createElement } from "@opentui/solid";
|
|
406
401
|
function RecapCard(props) {
|
|
407
402
|
return (() => {
|
|
408
|
-
var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("b"), _el$
|
|
403
|
+
var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("b"), _el$4 = _$createElement("text");
|
|
409
404
|
_$insertNode(_el$, _el$2);
|
|
410
|
-
_$insertNode(_el$, _el$
|
|
411
|
-
_$insertNode(_el$, _el$6);
|
|
405
|
+
_$insertNode(_el$, _el$4);
|
|
412
406
|
_$setProp(_el$, "flexDirection", "column");
|
|
413
407
|
_$setProp(_el$, "marginTop", 1);
|
|
414
408
|
_$setProp(_el$, "paddingLeft", 3);
|
|
415
409
|
_$insertNode(_el$2, _el$3);
|
|
416
|
-
_$
|
|
417
|
-
_$insert(_el$
|
|
418
|
-
_$insert(_el$6, () => `Next: ${props.recap.next}`);
|
|
410
|
+
_$insert(_el$3, () => props.recap.fallback ? "Recap \xB7 excerpt" : "Recap");
|
|
411
|
+
_$insert(_el$4, () => props.recap.recap);
|
|
419
412
|
_$insert(_el$, (() => {
|
|
420
|
-
var _c$ = _$memo(() => !!props.recap.
|
|
413
|
+
var _c$ = _$memo(() => !!props.recap.next);
|
|
421
414
|
return () => _c$() ? (() => {
|
|
422
|
-
var _el$
|
|
423
|
-
_$
|
|
424
|
-
_$effect((_$p) => _$setProp(_el$
|
|
425
|
-
return _el$
|
|
415
|
+
var _el$5 = _$createElement("text");
|
|
416
|
+
_$insert(_el$5, () => `Next: ${props.recap.next}`);
|
|
417
|
+
_$effect((_$p) => _$setProp(_el$5, "fg", props.theme.text.subdued, _$p));
|
|
418
|
+
return _el$5;
|
|
426
419
|
})() : null;
|
|
427
420
|
})(), null);
|
|
428
421
|
_$effect((_p$) => {
|
|
429
|
-
var _v$ = props.theme.text.subdued, _v$2 = props.theme.text.default
|
|
422
|
+
var _v$ = props.theme.text.subdued, _v$2 = props.theme.text.default;
|
|
430
423
|
_v$ !== _p$.e && (_p$.e = _$setProp(_el$2, "fg", _v$, _p$.e));
|
|
431
|
-
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$
|
|
432
|
-
_v$3 !== _p$.a && (_p$.a = _$setProp(_el$6, "fg", _v$3, _p$.a));
|
|
424
|
+
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$4, "fg", _v$2, _p$.t));
|
|
433
425
|
return _p$;
|
|
434
426
|
}, {
|
|
435
427
|
e: undefined,
|
|
436
|
-
t: undefined
|
|
437
|
-
a: undefined
|
|
428
|
+
t: undefined
|
|
438
429
|
});
|
|
439
430
|
return _el$;
|
|
440
431
|
})();
|
|
@@ -781,7 +772,7 @@ ${event.data.reason}`
|
|
|
781
772
|
},
|
|
782
773
|
get children() {
|
|
783
774
|
var _el$ = _$createElement2("text");
|
|
784
|
-
_$insertNode2(_el$, _$
|
|
775
|
+
_$insertNode2(_el$, _$createTextNode(`\u25CF generating run recap...`));
|
|
785
776
|
_$effect2((_$p) => _$setProp2(_el$, "fg", context.theme.text.status.running, _$p));
|
|
786
777
|
return _el$;
|
|
787
778
|
}
|