@cueloop/daemon 0.1.0-alpha.62 → 0.1.0-alpha.63

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cueloop/daemon",
3
- "version": "0.1.0-alpha.62",
3
+ "version": "0.1.0-alpha.63",
4
4
  "description": "The cueloop session daemon and its client: socket protocol, atomic store, resumable waits",
5
5
  "homepage": "https://github.com/mmurakaru/cueloop#readme",
6
6
  "bugs": {
@@ -33,7 +33,7 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
- "@cueloop/schema": "0.1.0-alpha.62",
36
+ "@cueloop/schema": "0.1.0-alpha.63",
37
37
  "valibot": "^1.4.2"
38
38
  },
39
39
  "engines": {
@@ -159,6 +159,30 @@ describe("openReview", () => {
159
159
  expect(other.id).not.toBe(first.id);
160
160
  });
161
161
 
162
+ test("the same agentSessionId with a different type opens a new session, never a type mismatch", async () => {
163
+ // Arrange - the agent session's plan review is open
164
+ const plan = await openReview(client, {
165
+ type: "plan",
166
+ content: PLAN,
167
+ cwd: home,
168
+ agentSessionId: "agent-cross",
169
+ });
170
+
171
+ // Act - the same agent session now submits a reply for review
172
+ const reply = await openReview(client, {
173
+ type: "reply",
174
+ content: "# Findings\n\nThe cache is fine.\n",
175
+ cwd: home,
176
+ agentSessionId: "agent-cross",
177
+ });
178
+
179
+ // Assert - a fresh reply session; the plan session keeps its type and history
180
+ expect(reply.id).not.toBe(plan.id);
181
+ expect(reply.session.artifact.type).toBe("reply");
182
+ expect(reply.session.revisions.length).toBe(1);
183
+ expect((await client.sessionGet(plan.id)).artifact.type).toBe("plan");
184
+ });
185
+
162
186
  test("per-file notes land as note annotations anchored at the file path", async () => {
163
187
  // Act
164
188
  const review = await openReview(client, {
package/src/review.ts CHANGED
@@ -245,10 +245,14 @@ export async function openReview(
245
245
  const cwd = options.cwd ?? process.cwd();
246
246
  const workspace = options.workspace ?? (await resolveWorkspace(cwd));
247
247
 
248
- // Resubmits from the same agent session become revisions, not new sessions.
248
+ // Resubmits from the same agent session become revisions, not new sessions -
249
+ // but only within the same primitive: a different artifact type is a new
250
+ // review, never a silent type mismatch on the old session.
249
251
  if (options.agentSessionId !== undefined) {
250
252
  const existing = (await client.sessionList()).find(
251
- (candidate) => candidate.artifact.meta.agentSessionId === options.agentSessionId,
253
+ (candidate) =>
254
+ candidate.artifact.meta.agentSessionId === options.agentSessionId &&
255
+ candidate.artifact.type === options.type,
252
256
  );
253
257
 
254
258
  if (existing !== undefined) {
@@ -19,6 +19,7 @@ import {
19
19
  validateSessionRecord,
20
20
  } from "./validate";
21
21
  import {
22
+ ARTIFACT_TYPES,
22
23
  SCHEMA_VERSION,
23
24
  type Anchor,
24
25
  type Annotation,
@@ -61,13 +62,15 @@ describe("parseParams", () => {
61
62
  }
62
63
  });
63
64
 
64
- test("accepts the reply artifact type", () => {
65
- const params = parseParams("session.create", {
66
- workspace: { repoRoot: "/repo", branch: "main" },
67
- artifact: { type: "reply", content: "# R" },
68
- });
65
+ test("accepts every artifact type in the schema union", () => {
66
+ for (const type of ARTIFACT_TYPES) {
67
+ const params = parseParams("session.create", {
68
+ workspace: { repoRoot: "/repo", branch: "main" },
69
+ artifact: { type, content: "body" },
70
+ });
69
71
 
70
- expect(params.artifact.type).toBe("reply");
72
+ expect(params.artifact.type).toBe(type);
73
+ }
71
74
  });
72
75
 
73
76
  test("rejects an unknown artifact type", () => {
package/src/validate.ts CHANGED
@@ -11,6 +11,7 @@
11
11
 
12
12
  import * as v from "valibot";
13
13
  import {
14
+ ARTIFACT_TYPES,
14
15
  SCHEMA_VERSION,
15
16
  type Anchor,
16
17
  type Annotation,
@@ -60,7 +61,9 @@ export const DiffFileContentsSchema = v.object({
60
61
  } satisfies EntriesOf<DiffFileContents>);
61
62
 
62
63
  export const ArtifactSchema = v.object({
63
- type: v.picklist(["plan", "diff", "prototype", "reply"]),
64
+ // Derived from the schema's runtime union: a new primitive extends the wire
65
+ // contract without touching this file.
66
+ type: v.picklist(ARTIFACT_TYPES),
64
67
  content: v.string(),
65
68
  meta: v.optional(ArtifactMetaSchema, {}),
66
69
  files: v.optional(v.array(DiffFileContentsSchema)),