@cueloop/daemon 0.1.0-alpha.38 → 0.1.0-alpha.39

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.38",
3
+ "version": "0.1.0-alpha.39",
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": {
@@ -28,7 +28,7 @@
28
28
  "access": "public"
29
29
  },
30
30
  "dependencies": {
31
- "@cueloop/schema": "0.1.0-alpha.38",
31
+ "@cueloop/schema": "0.1.0-alpha.39",
32
32
  "valibot": "^1.4.2"
33
33
  },
34
34
  "engines": {
package/src/api.test.ts CHANGED
@@ -63,6 +63,29 @@ describe("session lifecycle", () => {
63
63
  expect(core.sessionGet(session.id).annotations.length).toBe(0);
64
64
  });
65
65
 
66
+ test("annotate with an author registers them in the participant registry", () => {
67
+ // Arrange
68
+ const session = core.sessionCreate({ workspace: WS, artifact: PLAN });
69
+
70
+ // Act
71
+ core.sessionAnnotate(
72
+ session.id,
73
+ {
74
+ id: "a1",
75
+ kind: "comment",
76
+ anchor: { quote: "carefully", prefix: "the thing ", suffix: "." },
77
+ body: "A collaborator's note.",
78
+ author: "SHA256:ana",
79
+ },
80
+ "Ana",
81
+ );
82
+
83
+ // Assert
84
+ const stored = core.sessionGet(session.id);
85
+ expect(stored.annotations[0]!.author).toBe("SHA256:ana");
86
+ expect(stored.participants).toEqual([{ id: "SHA256:ana", provider: "ssh", name: "Ana" }]);
87
+ });
88
+
66
89
  test("resolve produces feedback.md and maps to the agent contract", () => {
67
90
  // Arrange
68
91
  const session = core.sessionCreate({ workspace: WS, artifact: PLAN });
package/src/api.ts CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  isAddressed,
12
12
  isAgentNote,
13
13
  parseBlocks,
14
+ registerParticipant,
14
15
  resolveAnchor,
15
16
  verdictAllows,
16
17
  type Annotation,
@@ -143,7 +144,15 @@ export class DaemonCore {
143
144
  });
144
145
  }
145
146
 
146
- sessionAnnotate(id: string, annotation: Omit<Annotation, "createdAt">): ReviewSession {
147
+ /**
148
+ * `authorName` registers the annotation's author in the participant registry;
149
+ * a bare author id (no name) keeps its short-handle fallback instead.
150
+ */
151
+ sessionAnnotate(
152
+ id: string,
153
+ annotation: Omit<Annotation, "createdAt">,
154
+ authorName?: string,
155
+ ): ReviewSession {
147
156
  const session = this.mutable(id);
148
157
  const existing = session.annotations.findIndex((candidate) => candidate.id === annotation.id);
149
158
  const full: Annotation = { ...annotation, createdAt: new Date().toISOString() };
@@ -153,6 +162,12 @@ export class DaemonCore {
153
162
  ...full,
154
163
  createdAt: session.annotations[existing]!.createdAt,
155
164
  };
165
+ if (annotation.author && authorName)
166
+ session.participants = registerParticipant(
167
+ session,
168
+ annotation.author,
169
+ authorName,
170
+ ).participants;
156
171
  this.store.upsert(session);
157
172
  this.emit("session.updated", id);
158
173
  return session;
package/src/client.ts CHANGED
@@ -38,7 +38,11 @@ export interface SessionClient {
38
38
  subscribe(): Promise<void>;
39
39
  sessionGet(id: string): Promise<ReviewSession>;
40
40
  sessionList(filter?: { status?: "pending" | "resolved" }): Promise<ReviewSession[]>;
41
- sessionAnnotate(id: string, annotation: Omit<Annotation, "createdAt">): Promise<ReviewSession>;
41
+ sessionAnnotate(
42
+ id: string,
43
+ annotation: Omit<Annotation, "createdAt">,
44
+ authorName?: string,
45
+ ): Promise<ReviewSession>;
42
46
  sessionRemoveAnnotation(id: string, annotationId: string): Promise<ReviewSession>;
43
47
  sessionSetWorkingCopy(id: string, workingCopy: string | undefined): Promise<ReviewSession>;
44
48
  sessionSetViewed(id: string, viewedPaths: string[]): Promise<ReviewSession>;
@@ -188,8 +192,12 @@ export class DaemonClient implements SessionClient {
188
192
  sessionWait(id: string, timeoutMs: number): Promise<ReviewSession | null> {
189
193
  return this.request("session.wait", { id, timeoutMs }, timeoutMs + 10_000);
190
194
  }
191
- sessionAnnotate(id: string, annotation: Omit<Annotation, "createdAt">): Promise<ReviewSession> {
192
- return this.request("session.annotate", { id, annotation });
195
+ sessionAnnotate(
196
+ id: string,
197
+ annotation: Omit<Annotation, "createdAt">,
198
+ authorName?: string,
199
+ ): Promise<ReviewSession> {
200
+ return this.request("session.annotate", { id, annotation, authorName });
193
201
  }
194
202
  sessionRemoveAnnotation(id: string, annotationId: string): Promise<ReviewSession> {
195
203
  return this.request("session.removeAnnotation", { id, annotationId });
package/src/server.ts CHANGED
@@ -246,7 +246,7 @@ export class DaemonServer {
246
246
  }
247
247
  case "session.annotate": {
248
248
  const params = parseParams("session.annotate", request.params);
249
- return core.sessionAnnotate(params.id, params.annotation);
249
+ return core.sessionAnnotate(params.id, params.annotation, params.authorName);
250
250
  }
251
251
  case "session.removeAnnotation": {
252
252
  const params = parseParams("session.removeAnnotation", request.params);
package/src/validate.ts CHANGED
@@ -125,7 +125,11 @@ export const Params = {
125
125
  60_000,
126
126
  ),
127
127
  }),
128
- "session.annotate": v.object({ id: SessionId, annotation: AnnotationSchema }),
128
+ "session.annotate": v.object({
129
+ id: SessionId,
130
+ annotation: AnnotationSchema,
131
+ authorName: v.optional(v.string()),
132
+ }),
129
133
  "session.removeAnnotation": v.object({ id: SessionId, annotationId: NonEmpty }),
130
134
  "session.setWorkingCopy": v.object({ id: SessionId, workingCopy: v.optional(v.string()) }),
131
135
  "session.setViewed": v.object({ id: SessionId, viewedPaths: v.array(v.string()) }),