| ... | ... | @@ -2186,6 +2186,99 @@ it.layer(layerTest)("ProjectionStoreV2", (it) => { |
| 2186 | 2186 | }), |
| 2187 | 2187 | ); |
| 2188 | 2188 | |
| 2189 | it.effect("dates thread activity by a run event and leaves the rest of the thread alone", () => |
| 2190 | Effect.gen(function* () { |
| 2191 | const projectionStore = yield* ProjectionStore.ProjectionStoreV2; |
| 2192 | const createdAt = yield* DateTime.now; |
| 2193 | const runOccurredAt = DateTime.add(createdAt, { seconds: 5 }); |
| 2194 | const threadId = ThreadId.make("thread:projection-activity"); |
| 2195 | const runId = RunId.make("run:projection-activity"); |
| 2196 | const rootNodeId = NodeId.make("node:projection-activity"); |
| 2197 | const thread = { |
| 2198 | createdBy: "user" as const, |
| 2199 | creationSource: "web" as const, |
| 2200 | id: threadId, |
| 2201 | projectId: ProjectId.make("project:projection-activity"), |
| 2202 | title: "Projection activity", |
| 2203 | providerInstanceId, |
| 2204 | modelSelection, |
| 2205 | runtimeMode: "full-access" as const, |
| 2206 | interactionMode: "default" as const, |
| 2207 | branch: "feature/activity", |
| 2208 | worktreePath: null, |
| 2209 | activeProviderThreadId: null, |
| 2210 | lineage: { |
| 2211 | parentThreadId: null, |
| 2212 | relationshipToParent: null, |
| 2213 | rootThreadId: threadId, |
| 2214 | }, |
| 2215 | forkedFrom: null, |
| 2216 | createdAt, |
| 2217 | updatedAt: createdAt, |
| 2218 | archivedAt: null, |
| 2219 | settledOverride: null, |
| 2220 | settledAt: null, |
| 2221 | lastVisitedAt: createdAt, |
| 2222 | deletedAt: null, |
| 2223 | }; |
| 2224 | |
| 2225 | yield* projectionStore.apply({ |
| 2226 | id: EventId.make("event:projection-activity:created"), |
| 2227 | type: "thread.created", |
| 2228 | threadId, |
| 2229 | occurredAt: createdAt, |
| 2230 | payload: thread, |
| 2231 | }); |
| 2232 | const created = (yield* projectionStore.getThreadProjection(threadId)).thread; |
| 2233 | |
| 2234 | const { statements, tracer } = traceSqlStatements(); |
| 2235 | yield* projectionStore |
| 2236 | .apply({ |
| 2237 | id: EventId.make("event:projection-activity:run-created"), |
| 2238 | type: "run.created", |
| 2239 | threadId, |
| 2240 | runId, |
| 2241 | nodeId: rootNodeId, |
| 2242 | driver, |
| 2243 | providerInstanceId, |
| 2244 | occurredAt: runOccurredAt, |
| 2245 | payload: { |
| 2246 | id: runId, |
| 2247 | threadId, |
| 2248 | ordinal: 1, |
| 2249 | providerInstanceId, |
| 2250 | modelSelection, |
| 2251 | providerThreadId: null, |
| 2252 | userMessageId: MessageId.make("message:projection-activity"), |
| 2253 | rootNodeId, |
| 2254 | activeAttemptId: null, |
| 2255 | status: "running" as const, |
| 2256 | requestedAt: runOccurredAt, |
| 2257 | startedAt: runOccurredAt, |
| 2258 | completedAt: null, |
| 2259 | checkpointId: null, |
| 2260 | contextHandoffId: null, |
| 2261 | }, |
| 2262 | }) |
| 2263 | .pipe(Effect.withTracer(tracer)); |
| 2264 | // The thread row is patched in place, never read back to be re-encoded. |
| 2265 | assert.isEmpty( |
| 2266 | statements.filter( |
| 2267 | (statement) => |
| 2268 | /^\s*SELECT/i.test(statement) && |
| 2269 | statement.includes("orchestration_v2_projection_threads"), |
| 2270 | ), |
| 2271 | ); |
| 2272 | |
| 2273 | const active = (yield* projectionStore.getThreadProjection(threadId)).thread; |
| 2274 | assert.deepEqual(active, { ...created, updatedAt: runOccurredAt }); |
| 2275 | const shell = (yield* projectionStore.getShellSnapshot()).threads.find( |
| 2276 | (candidate) => candidate.id === threadId, |
| 2277 | ); |
| 2278 | assert.deepEqual(shell?.updatedAt, runOccurredAt); |
| 2279 | }), |
| 2280 | ); |
| 2281 | |
| 2189 | 2282 | it.effect("preserves delegated completion ownership across stale run and task updates", () => |
| 2190 | 2283 | Effect.gen(function* () { |
| 2191 | 2284 | const projectionStore = yield* ProjectionStore.ProjectionStoreV2; |