@alecsibilia/luca 14.0.0-alpha.2 → 14.0.0-alpha.21
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 +76 -0
- package/README.md +7 -2
- package/board/client/board-look.ts +31 -1
- package/board/client/board-panel-parts.tsx +150 -0
- package/board/client/board-panel-stages.ts +99 -0
- package/board/client/board-panel-styles.ts +223 -0
- package/board/client/board-panel.tsx +77 -1275
- package/board/client/engine-life.ts +48 -0
- package/board/client/final-review-stack.tsx +144 -0
- package/board/client/heartbeat.tsx +61 -0
- package/board/client/helper-lines.tsx +69 -0
- package/board/client/live-feed.tsx +86 -0
- package/board/client/live-line.ts +73 -0
- package/board/client/model-line.tsx +178 -0
- package/board/client/needs-you-section.tsx +133 -0
- package/board/client/one-line.tsx +193 -0
- package/board/client/repo-wait-banner.tsx +69 -0
- package/board/client/run-footer.tsx +68 -0
- package/board/client/run-header.tsx +189 -0
- package/board/client/run-picker.tsx +98 -0
- package/board/client/status-bar.tsx +131 -0
- package/board/client/step-dots.tsx +127 -0
- package/board/client/stuck-actions.tsx +269 -0
- package/board/client/ticket-card-view.tsx +238 -0
- package/board/client/ticket-detail.tsx +87 -0
- package/board/client/ticket-stack.tsx +119 -0
- package/board/client/ticket-wait.ts +188 -0
- package/board/client/timeline-rows.tsx +41 -14
- package/board/client/usage-line.tsx +51 -0
- package/board/client/wait-line.tsx +39 -0
- package/board/index.client.tsx +1 -1
- package/board/index.server.ts +7 -1
- package/board/package.json +1 -1
- package/board/server/board-panel-state-helpers.ts +67 -0
- package/board/server/board-server-check.ts +294 -0
- package/board/server/board-server-engine.ts +129 -0
- package/board/server/board-server-events.ts +134 -0
- package/board/server/board-server-read.ts +190 -0
- package/board/server/board-server-resume.ts +164 -0
- package/board/server/board-server-start.ts +174 -0
- package/board/server/board-server-store.ts +281 -0
- package/board/server/board-server-types.ts +114 -0
- package/board/server/board-server-util.ts +4 -0
- package/board/server/board-server.ts +52 -943
- package/board/server/board-vocabulary-engine.ts +144 -0
- package/board/server/board-vocabulary-review.ts +115 -0
- package/board/server/board-vocabulary-run.ts +145 -0
- package/board/server/board-vocabulary-shapes.ts +153 -0
- package/board/server/board-vocabulary.ts +20 -375
- package/board/server/current-step-panel-helpers.ts +108 -0
- package/board/server/describe-record.ts +403 -0
- package/board/server/engine-launch.ts +20 -3
- package/board/server/engine-restart-helpers.ts +105 -0
- package/board/server/engine-watch.ts +45 -5
- package/board/server/journal-rebuild-helpers.ts +169 -0
- package/board/server/live-file.ts +130 -0
- package/board/server/luca-version.ts +1 -1
- package/board/server/make-rows.ts +14 -629
- package/board/server/record-texts.ts +350 -0
- package/board/server/reduce-board-agent-start.ts +224 -0
- package/board/server/reduce-board-agents.ts +160 -0
- package/board/server/reduce-board-counters.ts +138 -0
- package/board/server/reduce-board-create.ts +148 -0
- package/board/server/reduce-board-final-review.ts +174 -0
- package/board/server/reduce-board-needs-you.ts +283 -0
- package/board/server/reduce-board-reasons.ts +59 -0
- package/board/server/reduce-board-run.ts +255 -0
- package/board/server/reduce-board-settle.ts +88 -0
- package/board/server/reduce-board-steps.ts +226 -0
- package/board/server/reduce-board-text.ts +139 -0
- package/board/server/reduce-board-ticket-checks.ts +168 -0
- package/board/server/reduce-board-ticket-join.ts +144 -0
- package/board/server/reduce-board-ticket-start.ts +132 -0
- package/board/server/reduce-board-update.ts +117 -0
- package/board/server/reduce-board-usage.ts +247 -0
- package/board/server/reduce-board.ts +100 -1917
- package/board/server/reply-post.ts +407 -0
- package/board/server/run-registry.ts +8 -4
- package/board/server/ticket-stages-panel-helpers.ts +296 -0
- package/board/shared/board-rows.ts +9 -0
- package/board/shared/board-rpc.ts +42 -0
- package/board/shared/board-state-counts.ts +77 -0
- package/board/shared/board-state-live.ts +99 -0
- package/board/shared/board-state-review.ts +59 -0
- package/board/shared/board-state-run.ts +236 -0
- package/board/shared/board-state-ticket.ts +257 -0
- package/board/shared/board-state-usage.ts +107 -0
- package/board/shared/board-state.ts +97 -567
- package/board/shared/reply-actions.ts +207 -0
- package/engine/agents/agent-launcher.ts +27 -4
- package/engine/agents/claude-launcher-helpers.ts +233 -0
- package/engine/agents/claude-launcher.ts +28 -669
- package/engine/agents/claude-messages.ts +212 -0
- package/engine/agents/claude-options.ts +43 -8
- package/engine/agents/common-instructions.ts +138 -0
- package/engine/agents/input-channel.ts +36 -0
- package/engine/agents/launch-paths.ts +29 -0
- package/engine/agents/launch-session.ts +227 -0
- package/engine/agents/learner-instructions.ts +31 -0
- package/engine/agents/open-session.ts +210 -0
- package/engine/agents/prompt-sections.ts +95 -0
- package/engine/agents/rejoin-prompts.ts +135 -0
- package/engine/agents/reviewer-instructions.ts +99 -0
- package/engine/agents/role-instructions.ts +31 -244
- package/engine/agents/role-prompts.ts +39 -109
- package/engine/agents/role-results.ts +106 -7
- package/engine/agents/scripted-launcher.ts +21 -6
- package/engine/agents/session-pool.ts +124 -0
- package/engine/agents/turn-progress.ts +283 -0
- package/engine/agents/writer-instructions.ts +151 -0
- package/engine/cli/computer-adapters-real.ts +15 -3
- package/engine/cli/computer-adapters.ts +2 -0
- package/engine/cli/computer-checks.ts +87 -4
- package/engine/cli/config-reload-text.ts +39 -0
- package/engine/cli/decision-model-setup.ts +70 -0
- package/engine/cli/doctor-command.ts +1 -0
- package/engine/cli/doctor.ts +21 -3
- package/engine/cli/going-runs.ts +192 -36
- package/engine/cli/init-command.ts +1 -0
- package/engine/cli/init.ts +23 -1
- package/engine/cli/live-runs.ts +73 -0
- package/engine/cli/luca-run.ts +42 -7
- package/engine/cli/luca-skills.ts +183 -0
- package/engine/cli/luca.ts +8 -1
- package/engine/cli/models-command.ts +119 -0
- package/engine/cli/read-run.ts +81 -0
- package/engine/cli/run-args.ts +33 -6
- package/engine/cli/run-demo.ts +143 -0
- package/engine/cli/run-end.ts +184 -0
- package/engine/cli/run-modes-helpers.ts +81 -0
- package/engine/cli/run-modes.ts +62 -439
- package/engine/cli/setup.ts +5 -48
- package/engine/cli/unfinished-runs.ts +122 -0
- package/engine/cli/upgrade-command.ts +212 -30
- package/engine/cli/upgrade-finish.ts +149 -0
- package/engine/cli/upgrade.ts +112 -71
- package/engine/config/config-fields.ts +127 -0
- package/engine/config/config-reload.ts +250 -0
- package/engine/config/engine-config-schema.ts +235 -0
- package/engine/config/engine-config.ts +72 -142
- package/engine/config/test-commands.ts +102 -0
- package/engine/core/agent-guards-helpers.ts +84 -0
- package/engine/core/agent-turn.ts +395 -0
- package/engine/core/already-done.ts +44 -1
- package/engine/core/build-action.ts +214 -0
- package/engine/core/build-context.ts +135 -0
- package/engine/core/build-launch.ts +259 -0
- package/engine/core/commit-in.ts +282 -0
- package/engine/core/decide-build-early.ts +108 -0
- package/engine/core/decide-build-ending.ts +145 -0
- package/engine/core/decide-build-helpers.ts +87 -0
- package/engine/core/decide-build-tickets.ts +207 -0
- package/engine/core/decide-build-view.ts +103 -0
- package/engine/core/decide-build.ts +101 -1368
- package/engine/core/decide-final-fix.ts +203 -0
- package/engine/core/decide-final-review.ts +55 -310
- package/engine/core/decide-red-green.ts +398 -0
- package/engine/core/decide-rejoin.ts +259 -0
- package/engine/core/decide-repo-wait.ts +129 -0
- package/engine/core/decide-run-budget.ts +86 -12
- package/engine/core/decide-stuck-helpers.ts +127 -0
- package/engine/core/decide-stuck.ts +60 -8
- package/engine/core/decide-ticket-review.ts +95 -0
- package/engine/core/decide-ticket.ts +267 -0
- package/engine/core/decide-waits.ts +47 -0
- package/engine/core/decide.ts +74 -23
- package/engine/core/engine-chores.ts +163 -0
- package/engine/core/environment-rerun.ts +83 -0
- package/engine/core/evidence-text.ts +84 -0
- package/engine/core/execute-action.ts +303 -0
- package/engine/core/execute-already-done-check.ts +133 -0
- package/engine/core/execute-build.ts +68 -944
- package/engine/core/execute-changeset.ts +5 -7
- package/engine/core/execute-final-review.ts +125 -13
- package/engine/core/execute-gates.ts +182 -0
- package/engine/core/execute-intake.ts +130 -0
- package/engine/core/execute-join.ts +276 -0
- package/engine/core/execute-memory.ts +12 -0
- package/engine/core/execute-pull-request.ts +84 -0
- package/engine/core/execute-red-check.ts +219 -0
- package/engine/core/execute-repo-wait.ts +129 -0
- package/engine/core/execute-stuck.ts +25 -10
- package/engine/core/execute-waits.ts +158 -0
- package/engine/core/execute-with-jev.ts +118 -0
- package/engine/core/execute.ts +124 -831
- package/engine/core/final-failure-cap.ts +38 -0
- package/engine/core/final-review-action.ts +125 -0
- package/engine/core/final-review-text.ts +63 -17
- package/engine/core/final-stuck-text.ts +86 -0
- package/engine/core/fix-loop-text.ts +49 -2
- package/engine/core/left-out.ts +120 -0
- package/engine/core/live-file.ts +372 -0
- package/engine/core/loop-caps.ts +25 -2
- package/engine/core/not-in-run.ts +7 -3
- package/engine/core/pull-request-text.ts +255 -6
- package/engine/core/repo-wait-text.ts +81 -0
- package/engine/core/review-text.ts +55 -1
- package/engine/core/run-crash-recovery-helpers.ts +16 -0
- package/engine/core/run-session-close-helpers.ts +96 -0
- package/engine/core/run-start.ts +148 -0
- package/engine/core/run-stuck-text.ts +86 -0
- package/engine/core/schedule-rules.ts +193 -0
- package/engine/core/stuck-detail-text.ts +89 -0
- package/engine/core/stuck-format.ts +22 -0
- package/engine/core/stuck-text.ts +29 -332
- package/engine/core/ticket-stuck-text.ts +192 -0
- package/engine/core/worktree-changes.ts +106 -0
- package/engine/gates/already-done-check.ts +120 -0
- package/engine/gates/feature-map.ts +96 -0
- package/engine/gates/gate-runner.ts +108 -108
- package/engine/gates/gate-schemas.ts +61 -2
- package/engine/gates/leftover-scan.ts +154 -31
- package/engine/gates/new-tests.ts +45 -0
- package/engine/gates/own-files-check.ts +98 -0
- package/engine/gates/prepare-check.ts +60 -0
- package/engine/gates/prepare-slots.ts +99 -0
- package/engine/gates/red-check.ts +184 -16
- package/engine/gates/shell-check.ts +64 -0
- package/engine/gates/slot-waits.ts +55 -0
- package/engine/gates/slow-test-runner.ts +59 -0
- package/engine/gates/test-checks.ts +161 -0
- package/engine/gates/test-runner.ts +164 -5
- package/engine/gates/test-slots.ts +48 -0
- package/engine/git/git-adapter.ts +55 -396
- package/engine/git/git-commits.ts +132 -0
- package/engine/git/git-join.ts +139 -0
- package/engine/git/git-read.ts +123 -0
- package/engine/git/git-run.ts +32 -0
- package/engine/git/git-worktrees.ts +143 -0
- package/engine/git/outside-links.ts +55 -0
- package/engine/guards/after-turn-check.ts +31 -5
- package/engine/guards/guard-hook.ts +60 -12
- package/engine/guards/guard-roles.ts +68 -0
- package/engine/guards/helper-rules.ts +92 -0
- package/engine/guards/permission-rules.ts +161 -0
- package/engine/guards/role-rules-helpers.ts +48 -0
- package/engine/guards/role-rules.ts +34 -606
- package/engine/guards/shell-rules.ts +344 -0
- package/engine/guards/worktree-git.ts +208 -0
- package/engine/guards/worktree-snapshot.ts +412 -0
- package/engine/guards/worktree-state.ts +28 -825
- package/engine/guards/worktree-undo.ts +260 -0
- package/engine/guards/write-rules.ts +149 -0
- package/engine/index.ts +30 -9
- package/engine/intake/criteria-checks.ts +114 -0
- package/engine/intake/intake-checks.ts +164 -30
- package/engine/intake/intake-schemas.ts +37 -2
- package/engine/jev/clef-client.ts +259 -0
- package/engine/jev/decision-model-credentials.ts +212 -0
- package/engine/jev/jev-jobs.ts +144 -60
- package/engine/jev/jev-schemas.ts +86 -5
- package/engine/jev/jev-shadow-helpers.ts +218 -0
- package/engine/jev/jev-shadow.ts +109 -64
- package/engine/jev/model-pick.ts +275 -0
- package/engine/journal/agent-entries.ts +167 -0
- package/engine/journal/agent-message-entries.ts +72 -0
- package/engine/journal/agent-turn-replay.ts +203 -0
- package/engine/journal/already-done-entries.ts +55 -0
- package/engine/journal/commit-entries.ts +56 -0
- package/engine/journal/cross-ticket-replay.ts +222 -0
- package/engine/journal/decision-model-entries.ts +86 -0
- package/engine/journal/entry-fields.ts +10 -0
- package/engine/journal/final-review-entries.ts +128 -0
- package/engine/journal/final-review-replay.ts +324 -0
- package/engine/journal/final-review-round.ts +320 -0
- package/engine/journal/final-review-state.ts +180 -0
- package/engine/journal/gate-entries.ts +81 -0
- package/engine/journal/intake-entries.ts +87 -0
- package/engine/journal/join-entries.ts +126 -0
- package/engine/journal/journal-entry-schema.ts +218 -0
- package/engine/journal/journal-kinds.ts +97 -0
- package/engine/journal/journal-record-schema.ts +218 -0
- package/engine/journal/journal-record.ts +43 -1400
- package/engine/journal/journal.ts +6 -1
- package/engine/journal/limit-entries.ts +90 -0
- package/engine/journal/memory-entries.ts +124 -0
- package/engine/journal/memory-replay.ts +157 -0
- package/engine/journal/plan-replay.ts +139 -0
- package/engine/journal/pull-request-entries.ts +41 -0
- package/engine/journal/replay.ts +157 -2144
- package/engine/journal/reply-replay.ts +144 -0
- package/engine/journal/repo-wait-entries.ts +53 -0
- package/engine/journal/run-entries.ts +172 -0
- package/engine/journal/run-state.ts +264 -0
- package/engine/journal/shared-failure-replay.ts +133 -0
- package/engine/journal/stuck-entries.ts +193 -0
- package/engine/journal/ticket-progress.ts +392 -0
- package/engine/journal/ticket-replay.ts +411 -0
- package/engine/journal/ticket-result-replay.ts +364 -0
- package/engine/journal/ticket-retry-replay.ts +142 -0
- package/engine/journal/worktree-entries.ts +122 -0
- package/engine/models/model-score.ts +512 -0
- package/engine/shell/run-command.ts +187 -18
- package/engine/testing/agent-turn-fixtures.ts +287 -0
- package/engine/testing/already-done-fixtures.ts +97 -0
- package/engine/testing/build-fixtures.ts +68 -973
- package/engine/testing/checkouts-fixtures.ts +48 -0
- package/engine/testing/final-review-fixtures.ts +62 -1
- package/engine/testing/final-review-steps.ts +143 -0
- package/engine/testing/limit-fixtures.ts +85 -0
- package/engine/testing/live-file-fixtures.ts +57 -0
- package/engine/testing/practice-repo.ts +10 -4
- package/engine/testing/practice-run.ts +1 -1
- package/engine/testing/reply-fixtures.ts +88 -0
- package/engine/testing/run-budget-fixtures.ts +165 -0
- package/engine/testing/run-fixtures.ts +219 -0
- package/engine/testing/sdk-play.ts +177 -0
- package/engine/testing/setup-repo.ts +194 -0
- package/engine/testing/step-record-fixtures.ts +55 -0
- package/engine/testing/ticket-step-fixtures.ts +272 -0
- package/engine/testing/wait-scenarios.ts +186 -0
- package/engine/tracker/gh-retry.ts +217 -0
- package/engine/tracker/github-tracker.ts +310 -90
- package/engine/tracker/in-memory-tracker.ts +8 -4
- package/engine/tracker/tracker.ts +131 -6
- package/package.json +2 -1
- package/skills/luca-retro/SKILL.md +74 -0
- package/skills/luca-retro/scripts/retro-summary.ts +1356 -0
- package/skills/luca-unstick/SKILL.md +153 -0
- package/skills/luca-unstick/scripts/stuck-summary.ts +1063 -0
- package/engine/jev/jev-client.ts +0 -173
|
@@ -49,7 +49,12 @@ const parseLine = ({
|
|
|
49
49
|
return parsed.data
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Reads and checks every record of the journal at `file`, oldest first,
|
|
54
|
+
* without opening it for appends: none when it has no file. Throws on a
|
|
55
|
+
* line that isn't a record.
|
|
56
|
+
*/
|
|
57
|
+
export const readRecords = ({ file }: { file: string }): JournalRecord[] => {
|
|
53
58
|
if (!existsSync(file)) return []
|
|
54
59
|
return readFileSync(file, 'utf8')
|
|
55
60
|
.split('\n')
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { ENTRY_FIELDS } from './entry-fields'
|
|
4
|
+
|
|
5
|
+
import { AgentRoleSchema } from '../agents/role-results'
|
|
6
|
+
import { UsageRecordSchema } from '../limits/plan-usage'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The journal entries of plan limits: limit waits, usage-line waits, and
|
|
10
|
+
* recorded plan usage.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A plan window was used up (a rejected rate limit), so the whole run waits
|
|
15
|
+
* until `until`: the window's reset plus a margin, or a default wait when the
|
|
16
|
+
* reading named no reset. Written with `ticket: null`; the agent whose turn
|
|
17
|
+
* hit the limit is `hit_ticket` and `hit_role`.
|
|
18
|
+
*/
|
|
19
|
+
export const LimitWaitStartedEntrySchema = z.object({
|
|
20
|
+
...ENTRY_FIELDS,
|
|
21
|
+
kind: z.literal('limit_wait_started'),
|
|
22
|
+
content: z.object({
|
|
23
|
+
/** When the window resets, if the reading said. */
|
|
24
|
+
resets_at: z.iso.datetime().nullable(),
|
|
25
|
+
/** When the engine wakes and carries on. */
|
|
26
|
+
until: z.iso.datetime(),
|
|
27
|
+
/** The window, such as `five_hour`, `seven_day`, or `seven_day_opus`. */
|
|
28
|
+
rate_limit_type: z.string().nullable(),
|
|
29
|
+
hit_ticket: z.number().int().positive().nullable(),
|
|
30
|
+
hit_role: AgentRoleSchema.nullable(),
|
|
31
|
+
}),
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
/** The limit wait is over; the run carries on where it was cut off. */
|
|
35
|
+
export const LimitWaitEndedEntrySchema = z.object({
|
|
36
|
+
...ENTRY_FIELDS,
|
|
37
|
+
kind: z.literal('limit_wait_ended'),
|
|
38
|
+
content: z.object({ until: z.iso.datetime() }),
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
/** The plan windows a usage line guards: all-models weekly, and 5-hour. */
|
|
42
|
+
export const UsageLineWindowSchema = z.enum(['seven_day', 'five_hour'])
|
|
43
|
+
|
|
44
|
+
export type UsageLineWindow = z.infer<typeof UsageLineWindowSchema>
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The newest plan-window reading was at or over its **usage line**, so the
|
|
48
|
+
* whole run pauses until `until`: the window's reset plus a margin. The wait
|
|
49
|
+
* ends sooner once the line is raised above `percent`.
|
|
50
|
+
*/
|
|
51
|
+
export const UsageLineWaitStartedEntrySchema = z.object({
|
|
52
|
+
...ENTRY_FIELDS,
|
|
53
|
+
kind: z.literal('usage_line_wait_started'),
|
|
54
|
+
content: z.object({
|
|
55
|
+
window: UsageLineWindowSchema,
|
|
56
|
+
/** The line, in percent of the window. */
|
|
57
|
+
line: z.number(),
|
|
58
|
+
/** The reading's fill level, in percent. */
|
|
59
|
+
percent: z.number(),
|
|
60
|
+
/** When the window resets. */
|
|
61
|
+
resets_at: z.iso.datetime(),
|
|
62
|
+
/** When the engine wakes and carries on, at the latest. */
|
|
63
|
+
until: z.iso.datetime(),
|
|
64
|
+
}),
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The usage-line wait is over: the window reset (`reset`), or the line was
|
|
69
|
+
* raised above the reading (`line_raised`).
|
|
70
|
+
*/
|
|
71
|
+
export const UsageLineWaitEndedEntrySchema = z.object({
|
|
72
|
+
...ENTRY_FIELDS,
|
|
73
|
+
kind: z.literal('usage_line_wait_ended'),
|
|
74
|
+
content: z.object({
|
|
75
|
+
until: z.iso.datetime(),
|
|
76
|
+
reason: z.enum(['reset', 'line_raised']),
|
|
77
|
+
}),
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The plan usage of one ticket (when it was pushed, or got stuck) or of the
|
|
82
|
+
* whole run (when it ended): tokens from its agent sessions, and how far
|
|
83
|
+
* each plan window moved. A retried ticket that finishes again gets another,
|
|
84
|
+
* over all of its sessions: the latest is its whole usage.
|
|
85
|
+
*/
|
|
86
|
+
export const UsageRecordedEntrySchema = z.object({
|
|
87
|
+
...ENTRY_FIELDS,
|
|
88
|
+
kind: z.literal('usage_recorded'),
|
|
89
|
+
content: UsageRecordSchema,
|
|
90
|
+
})
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { ENTRY_FIELDS } from './entry-fields'
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
MemoryFeedbackSchema,
|
|
7
|
+
MemorySaveSchema,
|
|
8
|
+
RecalledMemorySchema,
|
|
9
|
+
RecallPointSchema,
|
|
10
|
+
VaultSearchSchema,
|
|
11
|
+
} from '../memory/memory-schemas'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The journal entries of memory (#370): recalls, the learner's saves and
|
|
15
|
+
* feedback, each MuninnDB write, and a skipped or reported learning.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The engine searched memory at a **recall point**: the vaults it searched
|
|
20
|
+
* (each with how it went and how many it found), and the memories it will
|
|
21
|
+
* show, merged by score, at most `MAX_MEMORIES_PER_RECALL`, each with its
|
|
22
|
+
* vault and score. `key` names the moment (such as `ticket:11`), so each is
|
|
23
|
+
* searched once. `ticket` is the ticket's, or `null` for the run's start
|
|
24
|
+
* and the final review.
|
|
25
|
+
*/
|
|
26
|
+
export const MemoryRecalledEntrySchema = z.object({
|
|
27
|
+
...ENTRY_FIELDS,
|
|
28
|
+
kind: z.literal('memory_recalled'),
|
|
29
|
+
content: z.object({
|
|
30
|
+
point: RecallPointSchema,
|
|
31
|
+
key: z.string().min(1),
|
|
32
|
+
query: z.string(),
|
|
33
|
+
vaults: z.array(VaultSearchSchema),
|
|
34
|
+
memories: z.array(RecalledMemorySchema),
|
|
35
|
+
}),
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The learner's proposed memories were saved (or refused, or failed), each
|
|
40
|
+
* with its vault, what became of it, and the similar memory the engine
|
|
41
|
+
* found first; then the helped / didn't-help feedback on each memory shown
|
|
42
|
+
* in the run. Written once per run, with `ticket: null`.
|
|
43
|
+
*/
|
|
44
|
+
export const MemoriesSavedEntrySchema = z.object({
|
|
45
|
+
...ENTRY_FIELDS,
|
|
46
|
+
kind: z.literal('memories_saved'),
|
|
47
|
+
content: z.object({
|
|
48
|
+
saves: z.array(MemorySaveSchema),
|
|
49
|
+
feedback: z.array(MemoryFeedbackSchema),
|
|
50
|
+
}),
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The engine is about to make one MuninnDB write of `save_memories` (#369):
|
|
55
|
+
* a save (`update_id` names the similar memory it updates, `muninn_evolve`;
|
|
56
|
+
* `null` adds a new one, `muninn_remember` with `op_id`) or a feedback on a
|
|
57
|
+
* shown memory. `write_key` names it within its step: `save:<op_id>` or
|
|
58
|
+
* `feedback:<vault>:<id>`. A redo of the step repeats a save started but
|
|
59
|
+
* not done the same way, and never sends such a feedback again.
|
|
60
|
+
*/
|
|
61
|
+
export const MemoryWriteStartedEntrySchema = z.object({
|
|
62
|
+
...ENTRY_FIELDS,
|
|
63
|
+
kind: z.literal('memory_write_started'),
|
|
64
|
+
content: z.discriminatedUnion('what', [
|
|
65
|
+
z.object({
|
|
66
|
+
write_key: z.string().min(1),
|
|
67
|
+
what: z.literal('save'),
|
|
68
|
+
vault: z.string().min(1),
|
|
69
|
+
concept: z.string(),
|
|
70
|
+
op_id: z.string().min(1),
|
|
71
|
+
update_id: z.string().nullable(),
|
|
72
|
+
similar: MemorySaveSchema.shape.similar,
|
|
73
|
+
}),
|
|
74
|
+
z.object({
|
|
75
|
+
write_key: z.string().min(1),
|
|
76
|
+
what: z.literal('feedback'),
|
|
77
|
+
vault: z.string().min(1),
|
|
78
|
+
id: z.string().min(1),
|
|
79
|
+
useful: z.boolean(),
|
|
80
|
+
}),
|
|
81
|
+
]),
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* One MuninnDB write of `save_memories` settled (or a save failed before
|
|
86
|
+
* its write): its outcome, which a redo of the step reuses as it is. Its
|
|
87
|
+
* step's `memories_saved` lists them all.
|
|
88
|
+
*/
|
|
89
|
+
export const MemoryWriteDoneEntrySchema = z.object({
|
|
90
|
+
...ENTRY_FIELDS,
|
|
91
|
+
kind: z.literal('memory_write_done'),
|
|
92
|
+
content: z.discriminatedUnion('what', [
|
|
93
|
+
z.object({
|
|
94
|
+
write_key: z.string().min(1),
|
|
95
|
+
what: z.literal('save'),
|
|
96
|
+
save: MemorySaveSchema,
|
|
97
|
+
}),
|
|
98
|
+
z.object({
|
|
99
|
+
write_key: z.string().min(1),
|
|
100
|
+
what: z.literal('feedback'),
|
|
101
|
+
feedback: MemoryFeedbackSchema,
|
|
102
|
+
}),
|
|
103
|
+
]),
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
/** The learner never gave a usable answer; the run ends without it. */
|
|
107
|
+
export const LearningSkippedEntrySchema = z.object({
|
|
108
|
+
...ENTRY_FIELDS,
|
|
109
|
+
kind: z.literal('learning_skipped'),
|
|
110
|
+
content: z.object({ reason: z.string() }),
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* With no PR to list them in, the new memories went on the spec issue in
|
|
115
|
+
* the engine's comment `comment_id`.
|
|
116
|
+
*/
|
|
117
|
+
export const MemoriesReportedEntrySchema = z.object({
|
|
118
|
+
...ENTRY_FIELDS,
|
|
119
|
+
kind: z.literal('memories_reported'),
|
|
120
|
+
content: z.object({
|
|
121
|
+
comment_id: z.number().int(),
|
|
122
|
+
count: z.number().int().min(0),
|
|
123
|
+
}),
|
|
124
|
+
})
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory as replay rebuilds it (#370): its state shape, a run with memory
|
|
3
|
+
* off, and the learner's own agent records.
|
|
4
|
+
*/
|
|
5
|
+
import { ranCheaper } from './agent-turn-replay'
|
|
6
|
+
import type { ReplayedAgentFailure } from './final-review-state'
|
|
7
|
+
import type { JournalRecord } from './journal-record'
|
|
8
|
+
|
|
9
|
+
import type { LearnerResult } from '../agents/role-results'
|
|
10
|
+
import type {
|
|
11
|
+
MemoryFeedback,
|
|
12
|
+
MemorySave,
|
|
13
|
+
RecallPoint,
|
|
14
|
+
RecalledMemory,
|
|
15
|
+
} from '../memory/memory-schemas'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The learner at the end of a run (#370): its answer, or its failed tries,
|
|
19
|
+
* or that the engine gave up on it. Learner records have `ticket: null` and
|
|
20
|
+
* role `learner`; they never count as the final review's.
|
|
21
|
+
*/
|
|
22
|
+
export type LearnerState = {
|
|
23
|
+
/** Its result, once it finished. */
|
|
24
|
+
result: LearnerResult | null
|
|
25
|
+
/** The seq of its `agent_finished`, for the saves' op ids. */
|
|
26
|
+
result_seq: number | null
|
|
27
|
+
/** Its latest failed turn, if none finished after it. */
|
|
28
|
+
agent_failure: ReplayedAgentFailure | null
|
|
29
|
+
/** Failed tries (agent, result, guard), in all. */
|
|
30
|
+
failed_tries: number
|
|
31
|
+
/** The model its latest agent launched on (#604); `null` in older journals. */
|
|
32
|
+
launched_on: string | null
|
|
33
|
+
/**
|
|
34
|
+
* It used up a try on a model cheaper than Opus (#604), so its later
|
|
35
|
+
* agents run Opus.
|
|
36
|
+
*/
|
|
37
|
+
failed_cheaper: boolean
|
|
38
|
+
/** Engine failures in a row. */
|
|
39
|
+
engine_failures: number
|
|
40
|
+
/** Why the engine gave up on it (`learning_skipped`), if it did. */
|
|
41
|
+
skipped: string | null
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Where memory stands in a run (#370), from its records. */
|
|
45
|
+
export type MemoryState = {
|
|
46
|
+
/** Memory is on for this run (`run_started.memory`). */
|
|
47
|
+
on: boolean
|
|
48
|
+
/** The project's vault; `null` searches only `default`. */
|
|
49
|
+
project_vault: string | null
|
|
50
|
+
/** Each recall point's memories, by its key, once searched. */
|
|
51
|
+
recalls: Record<string, { point: RecallPoint; memories: RecalledMemory[] }>
|
|
52
|
+
/** Every memory shown in the run, oldest first; may repeat. */
|
|
53
|
+
shown: RecalledMemory[]
|
|
54
|
+
learner: LearnerState
|
|
55
|
+
/** The learner's memories as saved, and the feedback sent. */
|
|
56
|
+
saved: { saves: MemorySave[]; feedback: MemoryFeedback[] } | null
|
|
57
|
+
/** The new memories went on the spec issue (a run with no PR). */
|
|
58
|
+
reported: boolean
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** A run with memory off, before any memory record. */
|
|
62
|
+
export const EMPTY_MEMORY: MemoryState = {
|
|
63
|
+
on: false,
|
|
64
|
+
project_vault: null,
|
|
65
|
+
recalls: {},
|
|
66
|
+
shown: [],
|
|
67
|
+
learner: {
|
|
68
|
+
result: null,
|
|
69
|
+
result_seq: null,
|
|
70
|
+
agent_failure: null,
|
|
71
|
+
failed_tries: 0,
|
|
72
|
+
launched_on: null,
|
|
73
|
+
failed_cheaper: false,
|
|
74
|
+
engine_failures: 0,
|
|
75
|
+
skipped: null,
|
|
76
|
+
},
|
|
77
|
+
saved: null,
|
|
78
|
+
reported: false,
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** The agent kinds a learner's turn journals. */
|
|
82
|
+
type LearnerRecord = Extract<
|
|
83
|
+
JournalRecord,
|
|
84
|
+
{
|
|
85
|
+
kind:
|
|
86
|
+
| 'agent_started'
|
|
87
|
+
| 'agent_finished'
|
|
88
|
+
| 'agent_failed'
|
|
89
|
+
| 'agent_session'
|
|
90
|
+
}
|
|
91
|
+
>
|
|
92
|
+
|
|
93
|
+
/** The record if it is one of the learner's agent records, else `null`. */
|
|
94
|
+
export const learnerRecordOf = ({
|
|
95
|
+
record,
|
|
96
|
+
}: {
|
|
97
|
+
record: JournalRecord
|
|
98
|
+
}): LearnerRecord | null => {
|
|
99
|
+
switch (record.kind) {
|
|
100
|
+
case 'agent_started':
|
|
101
|
+
case 'agent_finished':
|
|
102
|
+
case 'agent_failed':
|
|
103
|
+
case 'agent_session':
|
|
104
|
+
return record.content.role === 'learner' ? record : null
|
|
105
|
+
default:
|
|
106
|
+
return null
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The learner after one of its records: its answer ends any failure; a
|
|
112
|
+
* failed turn counts a try (or an engine failure in a row), like any
|
|
113
|
+
* agent's.
|
|
114
|
+
*/
|
|
115
|
+
export const learnerAfter = ({
|
|
116
|
+
learner,
|
|
117
|
+
record,
|
|
118
|
+
}: {
|
|
119
|
+
learner: LearnerState
|
|
120
|
+
record: LearnerRecord
|
|
121
|
+
}): LearnerState => {
|
|
122
|
+
switch (record.kind) {
|
|
123
|
+
case 'agent_started':
|
|
124
|
+
return { ...learner, launched_on: record.content.model }
|
|
125
|
+
case 'agent_session':
|
|
126
|
+
return learner
|
|
127
|
+
case 'agent_finished':
|
|
128
|
+
return record.content.role === 'learner'
|
|
129
|
+
? {
|
|
130
|
+
...learner,
|
|
131
|
+
result: record.content.result,
|
|
132
|
+
result_seq: record.seq,
|
|
133
|
+
agent_failure: null,
|
|
134
|
+
engine_failures: 0,
|
|
135
|
+
}
|
|
136
|
+
: learner
|
|
137
|
+
case 'agent_failed': {
|
|
138
|
+
const { role, error, failure, session_id } = record.content
|
|
139
|
+
const agent_failure = { role, error, failure, session_id }
|
|
140
|
+
return failure === 'engine'
|
|
141
|
+
? {
|
|
142
|
+
...learner,
|
|
143
|
+
agent_failure,
|
|
144
|
+
engine_failures: learner.engine_failures + 1,
|
|
145
|
+
}
|
|
146
|
+
: {
|
|
147
|
+
...learner,
|
|
148
|
+
agent_failure,
|
|
149
|
+
engine_failures: 0,
|
|
150
|
+
failed_tries: learner.failed_tries + 1,
|
|
151
|
+
failed_cheaper:
|
|
152
|
+
learner.failed_cheaper ||
|
|
153
|
+
ranCheaper(learner.launched_on),
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The plan as replay rebuilds it: rate limits hit, limit and usage-line
|
|
3
|
+
* waits, and billing stops, from agents' sessions and the wait records.
|
|
4
|
+
*/
|
|
5
|
+
import type { JournalRecord, UsageLineWindow } from './journal-record'
|
|
6
|
+
|
|
7
|
+
import type { AgentRole } from '../agents/role-results'
|
|
8
|
+
import { sessionSignal } from '../limits/plan-signals'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Where the run stands with the plan, from agents' rate-limit readings and
|
|
12
|
+
* the limit-wait and stop records.
|
|
13
|
+
*/
|
|
14
|
+
export type PlanState = {
|
|
15
|
+
/**
|
|
16
|
+
* The latest rejected rate limit no limit wait has started for yet: the
|
|
17
|
+
* window, its reset (seconds since the epoch), the agent that hit it, and
|
|
18
|
+
* when the session was journaled.
|
|
19
|
+
*/
|
|
20
|
+
hit: {
|
|
21
|
+
rate_limit_type: string | null
|
|
22
|
+
resets_at: number | null
|
|
23
|
+
ticket: number | null
|
|
24
|
+
role: AgentRole | null
|
|
25
|
+
time: string
|
|
26
|
+
} | null
|
|
27
|
+
/** The limit wait under way: when it ends, and what it is for. */
|
|
28
|
+
wait: {
|
|
29
|
+
until: string
|
|
30
|
+
resets_at: string | null
|
|
31
|
+
rate_limit_type: string | null
|
|
32
|
+
} | null
|
|
33
|
+
/** Every limit wait's reset so far, oldest first; the spec hears of each new one once. */
|
|
34
|
+
resets_announced: (string | null)[]
|
|
35
|
+
/** The first sign of per-token billing in any session, if any. */
|
|
36
|
+
billing: { reason: string } | null
|
|
37
|
+
/** Set once a billing stop is journaled. It sticks. */
|
|
38
|
+
billing_stopped: { reason: string } | null
|
|
39
|
+
/** The usage-line wait under way: its window, line, reading, and end. */
|
|
40
|
+
usage_wait: {
|
|
41
|
+
window: UsageLineWindow
|
|
42
|
+
line: number
|
|
43
|
+
percent: number
|
|
44
|
+
until: string
|
|
45
|
+
} | null
|
|
46
|
+
/**
|
|
47
|
+
* The latest time the run is known to have waited until: the `until` of
|
|
48
|
+
* a limit wait that ended, or of a usage-line wait that ended at its
|
|
49
|
+
* reset. A reading whose window resets by then is out of date.
|
|
50
|
+
*/
|
|
51
|
+
waited_until: string | null
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
type PlanRecord = Extract<
|
|
55
|
+
JournalRecord,
|
|
56
|
+
{
|
|
57
|
+
kind:
|
|
58
|
+
| 'agent_session'
|
|
59
|
+
| 'run_stopped'
|
|
60
|
+
| 'limit_wait_started'
|
|
61
|
+
| 'limit_wait_ended'
|
|
62
|
+
| 'usage_line_wait_started'
|
|
63
|
+
| 'usage_line_wait_ended'
|
|
64
|
+
}
|
|
65
|
+
>
|
|
66
|
+
|
|
67
|
+
/** The later of two ISO times; the first may be missing. */
|
|
68
|
+
const laterOf = (a: string | null, b: string): string =>
|
|
69
|
+
a !== null && Date.parse(a) >= Date.parse(b) ? a : b
|
|
70
|
+
|
|
71
|
+
/** The plan state after one record. */
|
|
72
|
+
export const planAfter = ({
|
|
73
|
+
plan,
|
|
74
|
+
record,
|
|
75
|
+
}: {
|
|
76
|
+
plan: PlanState
|
|
77
|
+
record: PlanRecord
|
|
78
|
+
}): PlanState => {
|
|
79
|
+
switch (record.kind) {
|
|
80
|
+
case 'agent_session': {
|
|
81
|
+
const signal = sessionSignal({ session: record.content.session })
|
|
82
|
+
if (signal.kind === 'billing') {
|
|
83
|
+
return {
|
|
84
|
+
...plan,
|
|
85
|
+
billing: plan.billing ?? { reason: signal.reason },
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (signal.kind === 'ok') return plan
|
|
89
|
+
return {
|
|
90
|
+
...plan,
|
|
91
|
+
hit: {
|
|
92
|
+
rate_limit_type: signal.rate_limit_type,
|
|
93
|
+
resets_at: signal.resets_at,
|
|
94
|
+
ticket: record.ticket,
|
|
95
|
+
role: record.content.role,
|
|
96
|
+
time: record.time,
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
case 'run_stopped':
|
|
101
|
+
return record.content.billing
|
|
102
|
+
? {
|
|
103
|
+
...plan,
|
|
104
|
+
billing: plan.billing ?? {
|
|
105
|
+
reason: record.content.reason,
|
|
106
|
+
},
|
|
107
|
+
billing_stopped: { reason: record.content.reason },
|
|
108
|
+
}
|
|
109
|
+
: plan
|
|
110
|
+
case 'limit_wait_started': {
|
|
111
|
+
const { until, resets_at, rate_limit_type } = record.content
|
|
112
|
+
return {
|
|
113
|
+
...plan,
|
|
114
|
+
hit: null,
|
|
115
|
+
wait: { until, resets_at, rate_limit_type },
|
|
116
|
+
resets_announced: [...plan.resets_announced, resets_at],
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
case 'limit_wait_ended':
|
|
120
|
+
return {
|
|
121
|
+
...plan,
|
|
122
|
+
wait: null,
|
|
123
|
+
waited_until: laterOf(plan.waited_until, record.content.until),
|
|
124
|
+
}
|
|
125
|
+
case 'usage_line_wait_started': {
|
|
126
|
+
const { window, line, percent, until } = record.content
|
|
127
|
+
return { ...plan, usage_wait: { window, line, percent, until } }
|
|
128
|
+
}
|
|
129
|
+
case 'usage_line_wait_ended':
|
|
130
|
+
return {
|
|
131
|
+
...plan,
|
|
132
|
+
usage_wait: null,
|
|
133
|
+
waited_until:
|
|
134
|
+
record.content.reason === 'reset'
|
|
135
|
+
? laterOf(plan.waited_until, record.content.until)
|
|
136
|
+
: plan.waited_until,
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { ENTRY_FIELDS } from './entry-fields'
|
|
4
|
+
|
|
5
|
+
/** The journal entries of the run's pull request: its changeset, and the PR. */
|
|
6
|
+
|
|
7
|
+
/** A changeset's bump: from the spec's `release:*` label, patch with none. */
|
|
8
|
+
export const ChangesetBumpSchema = z.enum(['patch', 'minor', 'major', 'none'])
|
|
9
|
+
|
|
10
|
+
export type ChangesetBump = z.infer<typeof ChangesetBumpSchema>
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The engine committed the run's one changeset (#461) at `path` on the run
|
|
14
|
+
* branch and pushed it (`sha` is the run branch's HEAD after). `packages`
|
|
15
|
+
* are the ones it names. `path` is `null` when nothing was written: the
|
|
16
|
+
* spec is `release:none` (#476), or the repo no longer had a changesets
|
|
17
|
+
* config.
|
|
18
|
+
*/
|
|
19
|
+
export const ChangesetWrittenEntrySchema = z.object({
|
|
20
|
+
...ENTRY_FIELDS,
|
|
21
|
+
kind: z.literal('changeset_written'),
|
|
22
|
+
content: z.object({
|
|
23
|
+
path: z.string().nullable(),
|
|
24
|
+
bump: ChangesetBumpSchema,
|
|
25
|
+
packages: z.array(z.string()),
|
|
26
|
+
sha: z.string(),
|
|
27
|
+
}),
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
export const PullRequestOpenedEntrySchema = z.object({
|
|
31
|
+
...ENTRY_FIELDS,
|
|
32
|
+
kind: z.literal('pull_request_opened'),
|
|
33
|
+
content: z.object({
|
|
34
|
+
number: z.number().int().positive(),
|
|
35
|
+
url: z.string(),
|
|
36
|
+
head: z.string(),
|
|
37
|
+
base: z.string(),
|
|
38
|
+
title: z.string(),
|
|
39
|
+
body: z.string(),
|
|
40
|
+
}),
|
|
41
|
+
})
|