@cat-factory/app 0.121.1 → 0.121.2
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/app/stores/agentRuns.spec.ts +54 -1
- package/app/stores/agentRuns.ts +10 -19
- package/app/stores/ui/modals.ts +810 -0
- package/app/stores/ui/navigation.ts +63 -0
- package/app/stores/ui/resultViews.ts +246 -0
- package/app/stores/ui.spec.ts +30 -0
- package/app/stores/ui.ts +19 -1072
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach } from 'vitest'
|
|
2
|
-
import type { BootstrapJob } from '~/types/domain'
|
|
2
|
+
import type { BootstrapJob, EnvConfigRepairJob } from '~/types/domain'
|
|
3
3
|
import { useAgentRunsStore } from '~/stores/agentRuns'
|
|
4
4
|
|
|
5
5
|
/** Minimal BootstrapJob factory — only the fields the store's reconcile logic touches. */
|
|
@@ -72,3 +72,56 @@ describe('agentRuns store — monotonic bootstrap reconcile', () => {
|
|
|
72
72
|
expect(store.bootstrapJobs[0]!.status).toBe('succeeded')
|
|
73
73
|
})
|
|
74
74
|
})
|
|
75
|
+
|
|
76
|
+
/** Minimal EnvConfigRepairJob factory — only the fields the store touches. */
|
|
77
|
+
function repairJob(id: string, over: Partial<EnvConfigRepairJob> = {}): EnvConfigRepairJob {
|
|
78
|
+
return {
|
|
79
|
+
id,
|
|
80
|
+
workspaceId: 'ws_test',
|
|
81
|
+
owner: 'acme',
|
|
82
|
+
repo: 'svc',
|
|
83
|
+
branch: 'main',
|
|
84
|
+
status: 'running',
|
|
85
|
+
ok: null,
|
|
86
|
+
issues: [],
|
|
87
|
+
subtasks: null,
|
|
88
|
+
error: null,
|
|
89
|
+
failure: null,
|
|
90
|
+
createdAt: 1,
|
|
91
|
+
updatedAt: 1,
|
|
92
|
+
...over,
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
describe('agentRuns store — env-config-repair (plain useUpsertList adoption, candidate #3)', () => {
|
|
97
|
+
let store: ReturnType<typeof useAgentRunsStore>
|
|
98
|
+
beforeEach(() => {
|
|
99
|
+
store = useAgentRunsStore()
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('upsertEnvConfigRepair prepends a new run (newest-first) and replaces in place by id', () => {
|
|
103
|
+
store.upsertEnvConfigRepair(repairJob('r1'))
|
|
104
|
+
store.upsertEnvConfigRepair(repairJob('r2'))
|
|
105
|
+
// Newest prepended, so r2 leads r1.
|
|
106
|
+
expect(store.envConfigRepairJobs.map((j) => j.id)).toEqual(['r2', 'r1'])
|
|
107
|
+
// A later event for r1 replaces it IN PLACE (no reorder), unlike a monotonic-guarded list.
|
|
108
|
+
store.upsertEnvConfigRepair(repairJob('r1', { status: 'succeeded' }))
|
|
109
|
+
expect(store.envConfigRepairJobs.map((j) => j.id)).toEqual(['r2', 'r1'])
|
|
110
|
+
expect(store.envConfigRepairById('r1')?.status).toBe('succeeded')
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('envConfigRepairById looks a run up by id (absent → undefined)', () => {
|
|
114
|
+
store.upsertEnvConfigRepair(repairJob('r1'))
|
|
115
|
+
expect(store.envConfigRepairById('r1')?.id).toBe('r1')
|
|
116
|
+
expect(store.envConfigRepairById('nope')).toBeUndefined()
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('hydrateEnvConfigRepair replaces the cache newest-first', () => {
|
|
120
|
+
store.upsertEnvConfigRepair(repairJob('stale'))
|
|
121
|
+
store.hydrateEnvConfigRepair([
|
|
122
|
+
repairJob('old', { createdAt: 1 }),
|
|
123
|
+
repairJob('new', { createdAt: 9 }),
|
|
124
|
+
])
|
|
125
|
+
expect(store.envConfigRepairJobs.map((j) => j.id)).toEqual(['new', 'old'])
|
|
126
|
+
})
|
|
127
|
+
})
|
package/app/stores/agentRuns.ts
CHANGED
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
} from '~/types/domain'
|
|
10
10
|
import { useWorkspaceStore } from '~/stores/workspace'
|
|
11
11
|
import { useExecutionStore } from '~/stores/execution'
|
|
12
|
+
import { useUpsertList } from '~/composables/useUpsertList'
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* A coarse, per-block view of the current "agent run" against a block, regardless
|
|
@@ -62,9 +63,15 @@ export const useAgentRunsStore = defineStore('agentRuns', () => {
|
|
|
62
63
|
* Env-config-repair runs for this workspace, newest-first. These have NO board block —
|
|
63
64
|
* they're surfaced only on the infrastructure-providers window (looked up by the
|
|
64
65
|
* `repairJobId` the `bootstrapRepo` response returned), so they're held separately and
|
|
65
|
-
* NOT merged into {@link byBlock}.
|
|
66
|
+
* NOT merged into {@link byBlock}. Unlike the bootstrap list this is a PLAIN find-by-id
|
|
67
|
+
* upsert (no `updatedAt` monotonic guard), so it routes through the shared
|
|
68
|
+
* {@link useUpsertList} helper (the last plain-upsert holdout, refactoring candidate #3).
|
|
66
69
|
*/
|
|
67
|
-
const
|
|
70
|
+
const {
|
|
71
|
+
items: envConfigRepairJobs,
|
|
72
|
+
upsert: upsertEnvConfigRepair,
|
|
73
|
+
get: envConfigRepairById,
|
|
74
|
+
} = useUpsertList<EnvConfigRepairJob>({ key: (j) => j.id, prepend: true })
|
|
68
75
|
|
|
69
76
|
/**
|
|
70
77
|
* Reconcile the cached bootstrap runs with a server snapshot for `workspaceId`. A snapshot is
|
|
@@ -96,27 +103,11 @@ export const useAgentRunsStore = defineStore('agentRuns', () => {
|
|
|
96
103
|
bootstrapJobs.value = [...reconciled, ...preserved].sort((a, b) => b.createdAt - a.createdAt)
|
|
97
104
|
}
|
|
98
105
|
|
|
99
|
-
/** Replace the cached env-config-repair runs with a server snapshot. */
|
|
106
|
+
/** Replace the cached env-config-repair runs with a server snapshot (newest-first). */
|
|
100
107
|
function hydrateEnvConfigRepair(jobs: EnvConfigRepairJob[]) {
|
|
101
108
|
envConfigRepairJobs.value = [...jobs].sort((a, b) => b.createdAt - a.createdAt)
|
|
102
109
|
}
|
|
103
110
|
|
|
104
|
-
/**
|
|
105
|
-
* Patch an env-config-repair run from a real-time `env-config-repair` event (or after
|
|
106
|
-
* launching one): replace it in place by id, else prepend it. Keeps the infra window's
|
|
107
|
-
* "repairing…" indicator reactive to live progress / outcome without a refetch.
|
|
108
|
-
*/
|
|
109
|
-
function upsertEnvConfigRepair(job: EnvConfigRepairJob) {
|
|
110
|
-
const i = envConfigRepairJobs.value.findIndex((j) => j.id === job.id)
|
|
111
|
-
if (i >= 0) envConfigRepairJobs.value[i] = job
|
|
112
|
-
else envConfigRepairJobs.value.unshift(job)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/** Look up a single env-config-repair run by id (the infra window tracks one by `repairJobId`). */
|
|
116
|
-
function envConfigRepairById(id: string): EnvConfigRepairJob | undefined {
|
|
117
|
-
return envConfigRepairJobs.value.find((j) => j.id === id)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
111
|
/**
|
|
121
112
|
* Patch a bootstrap run from a real-time `bootstrap` event (or after launching
|
|
122
113
|
* one): replace it in place by id, else prepend it. Keeps the service card
|