synomem 0.9.6 → 0.10.0
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 +9 -0
- package/README.md +5 -3
- package/dist/actor-directory.d.ts +34 -0
- package/dist/actor-directory.d.ts.map +1 -0
- package/dist/actor-directory.js +52 -0
- package/dist/actor-directory.js.map +1 -0
- package/dist/backend.d.ts +3 -0
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js +26 -3
- package/dist/backend.js.map +1 -1
- package/dist/bookmarks.d.ts +30 -0
- package/dist/bookmarks.d.ts.map +1 -0
- package/dist/bookmarks.js +87 -0
- package/dist/bookmarks.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +291 -61
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +115 -4
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +854 -138
- package/dist/client.js.map +1 -1
- package/dist/cursors.d.ts +30 -0
- package/dist/cursors.d.ts.map +1 -0
- package/dist/cursors.js +101 -0
- package/dist/cursors.js.map +1 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -0
- package/dist/errors.js.map +1 -1
- package/dist/import.d.ts +605 -39
- package/dist/import.d.ts.map +1 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +329 -22
- package/dist/mcp/index.js.map +1 -1
- package/dist/mutation-receipts.d.ts +8 -0
- package/dist/mutation-receipts.d.ts.map +1 -0
- package/dist/mutation-receipts.js +2 -0
- package/dist/mutation-receipts.js.map +1 -0
- package/dist/notifications.d.ts +73 -0
- package/dist/notifications.d.ts.map +1 -0
- package/dist/notifications.js +309 -0
- package/dist/notifications.js.map +1 -0
- package/dist/participation-repository.d.ts +46 -0
- package/dist/participation-repository.d.ts.map +1 -0
- package/dist/participation-repository.js +296 -0
- package/dist/participation-repository.js.map +1 -0
- package/dist/participation.d.ts +97 -0
- package/dist/participation.d.ts.map +1 -0
- package/dist/participation.js +10 -0
- package/dist/participation.js.map +1 -0
- package/dist/policy.d.ts +31 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +71 -0
- package/dist/policy.js.map +1 -0
- package/dist/ports/repository.d.ts +23 -0
- package/dist/ports/repository.d.ts.map +1 -1
- package/dist/profiles.d.ts +12 -0
- package/dist/profiles.d.ts.map +1 -1
- package/dist/profiles.js +2 -1
- package/dist/profiles.js.map +1 -1
- package/dist/projections.d.ts.map +1 -1
- package/dist/projections.js +29 -11
- package/dist/projections.js.map +1 -1
- package/dist/remote.d.ts +79 -0
- package/dist/remote.d.ts.map +1 -1
- package/dist/remote.js +65 -6
- package/dist/remote.js.map +1 -1
- package/dist/schemas.d.ts +746 -58
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +114 -16
- package/dist/schemas.js.map +1 -1
- package/dist/search.d.ts +25 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +2 -0
- package/dist/search.js.map +1 -0
- package/dist/service.d.ts +89 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/storage.d.ts +38 -3
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +494 -365
- package/dist/storage.js.map +1 -1
- package/dist/types.d.ts +65 -34
- package/dist/types.d.ts.map +1 -1
- package/docs/cli.md +6 -0
- package/docs/human-participation.md +20 -0
- package/docs/mcp.md +2 -0
- package/docs/storage-format.md +4 -15
- package/openapi/synomem-v1.yaml +187 -10
- package/package.json +2 -1
- package/skills/synomem/SKILL.md +2 -0
- package/src/actor-directory.ts +87 -0
- package/src/backend.ts +29 -3
- package/src/bookmarks.ts +127 -0
- package/src/cli.ts +941 -546
- package/src/client.ts +1143 -279
- package/src/cursors.ts +132 -0
- package/src/errors.ts +2 -0
- package/src/index.ts +50 -0
- package/src/mcp/index.ts +412 -96
- package/src/mutation-receipts.ts +7 -0
- package/src/notifications.ts +483 -0
- package/src/participation-repository.ts +406 -0
- package/src/participation.ts +103 -0
- package/src/policy.ts +109 -0
- package/src/ports/repository.ts +33 -0
- package/src/profiles.ts +2 -1
- package/src/projections.ts +49 -48
- package/src/remote.ts +227 -37
- package/src/schemas.ts +116 -16
- package/src/search.ts +24 -0
- package/src/service.ts +122 -8
- package/src/storage.ts +1039 -697
- package/src/types.ts +67 -32
package/src/remote.ts
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ActorDirectoryInput,
|
|
3
|
+
ActorDirectoryPage,
|
|
4
|
+
ActorProfile,
|
|
5
|
+
ActorProfileInput,
|
|
6
|
+
} from './actor-directory.js';
|
|
7
|
+
import type {
|
|
8
|
+
NotificationInput as HpNotificationInput,
|
|
9
|
+
NotificationPage as HpNotificationPage,
|
|
10
|
+
} from './notifications.js';
|
|
11
|
+
import type {
|
|
12
|
+
ReactionSetInput as HpReactionSetInput,
|
|
13
|
+
ReactionSummary as HpReactionSummary,
|
|
14
|
+
ReplyCreateInput as HpReplyCreateInput,
|
|
15
|
+
ReplyDeleteInput as HpReplyDeleteInput,
|
|
16
|
+
ReplyRecord as HpReplyRecord,
|
|
17
|
+
ThreadInput as HpThreadInput,
|
|
18
|
+
ThreadPage as HpThreadPage,
|
|
19
|
+
} from './participation.js';
|
|
20
|
+
import type { BookmarkInput, BookmarkPage } from './bookmarks.js';
|
|
21
|
+
import type { SearchInput, SearchPage } from './search.js';
|
|
22
|
+
import type { OverrideTaskDecisionInput } from './types.js';
|
|
23
|
+
import type { ActorRef, AddressableActor } from './policy.js';
|
|
1
24
|
import { actorSchema } from './schemas.js';
|
|
2
25
|
import { errorCodes, SynomemError, type SynomemErrorCode } from './errors.js';
|
|
3
26
|
import type { SynomemService, SynomemServiceCapabilities, SynomemServiceInfo } from './service.js';
|
|
@@ -117,7 +140,7 @@ function queryString(input: object): string {
|
|
|
117
140
|
if (Array.isArray(value)) {
|
|
118
141
|
for (const item of value) parameters.append(key, String(item));
|
|
119
142
|
} else {
|
|
120
|
-
parameters.set(key, String(value));
|
|
143
|
+
parameters.set(key, typeof value === 'object' ? JSON.stringify(value) : String(value));
|
|
121
144
|
}
|
|
122
145
|
}
|
|
123
146
|
const encoded = parameters.toString();
|
|
@@ -195,6 +218,97 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
195
218
|
private initialized = false;
|
|
196
219
|
private cachedCapabilities?: SynomemServiceCapabilities;
|
|
197
220
|
|
|
221
|
+
readonly bookmarks = {
|
|
222
|
+
list: (input: BookmarkInput = {}) =>
|
|
223
|
+
this.request<BookmarkPage>('GET', `bookmarks${queryString(input)}`),
|
|
224
|
+
has: (rootId: string) =>
|
|
225
|
+
this.request<{ saved: boolean }>('GET', `items/${encodeURIComponent(rootId)}/bookmark`),
|
|
226
|
+
set: (input: { rootId: string; present: boolean }) =>
|
|
227
|
+
this.request<{ saved: boolean }>(
|
|
228
|
+
input.present ? 'PUT' : 'DELETE',
|
|
229
|
+
`items/${encodeURIComponent(input.rootId)}/bookmark`,
|
|
230
|
+
{},
|
|
231
|
+
),
|
|
232
|
+
};
|
|
233
|
+
readonly notifications = {
|
|
234
|
+
list: (input: HpNotificationInput = {}) =>
|
|
235
|
+
this.request<HpNotificationPage>('GET', `inbox${queryString(input)}`),
|
|
236
|
+
read: async (id: string) => {
|
|
237
|
+
await this.request('POST', `inbox/${encodeURIComponent(id)}/read`, {});
|
|
238
|
+
},
|
|
239
|
+
dismiss: async (id: string) => {
|
|
240
|
+
await this.request('POST', `inbox/${encodeURIComponent(id)}/dismiss`, {});
|
|
241
|
+
},
|
|
242
|
+
readThrough: async (through: string) => {
|
|
243
|
+
await this.request('POST', 'inbox/read', { through });
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
readonly replies = {
|
|
247
|
+
changes: (input: HpThreadInput) =>
|
|
248
|
+
this.request<HpThreadPage>('GET', `replies/changes${queryString(input)}`),
|
|
249
|
+
create: (input: HpReplyCreateInput) =>
|
|
250
|
+
this.request<HpReplyRecord>(
|
|
251
|
+
'POST',
|
|
252
|
+
`items/${encodeURIComponent(input.rootId)}/replies`,
|
|
253
|
+
input,
|
|
254
|
+
),
|
|
255
|
+
get: (id: string) => this.request<HpReplyRecord>('GET', `replies/${encodeURIComponent(id)}`),
|
|
256
|
+
delete: (input: HpReplyDeleteInput) =>
|
|
257
|
+
this.request<HpReplyRecord>('DELETE', `replies/${encodeURIComponent(input.replyId)}`, input),
|
|
258
|
+
};
|
|
259
|
+
readonly threads = {
|
|
260
|
+
read: async (input: { rootId: string; through: string }) => {
|
|
261
|
+
await this.request('PUT', `items/${encodeURIComponent(input.rootId)}/thread/read`, {
|
|
262
|
+
through: input.through,
|
|
263
|
+
});
|
|
264
|
+
},
|
|
265
|
+
get: (input: HpThreadInput) =>
|
|
266
|
+
this.request<HpThreadPage>(
|
|
267
|
+
'GET',
|
|
268
|
+
`items/${encodeURIComponent(input.rootId)}/thread${queryString({ after: input.after, limit: input.limit })}`,
|
|
269
|
+
),
|
|
270
|
+
subscription: (input: { rootId: string; following: boolean; muted: boolean }) =>
|
|
271
|
+
this.request<void>(
|
|
272
|
+
'PUT',
|
|
273
|
+
`items/${encodeURIComponent(input.rootId)}/thread/subscription`,
|
|
274
|
+
input,
|
|
275
|
+
),
|
|
276
|
+
};
|
|
277
|
+
readonly reactions = {
|
|
278
|
+
set: (input: HpReactionSetInput) =>
|
|
279
|
+
this.request<HpReactionSummary>(
|
|
280
|
+
input.present ? 'PUT' : 'DELETE',
|
|
281
|
+
`reactions/${encodeURIComponent(input.targetId)}/${input.code}`,
|
|
282
|
+
input,
|
|
283
|
+
),
|
|
284
|
+
get: (targetId: string) =>
|
|
285
|
+
this.request<HpReactionSummary>('GET', `reactions/${encodeURIComponent(targetId)}`),
|
|
286
|
+
};
|
|
287
|
+
readonly actors = {
|
|
288
|
+
profile: (input: ActorProfileInput) =>
|
|
289
|
+
this.request<ActorProfile>(
|
|
290
|
+
'GET',
|
|
291
|
+
`actor-directory/${input.target.kind}/${encodeURIComponent(input.target.id)}/profile${queryString({ after: input.after, limit: input.limit })}`,
|
|
292
|
+
),
|
|
293
|
+
list: (input: ActorDirectoryInput = {}) =>
|
|
294
|
+
this.request<ActorDirectoryPage>('GET', `actor-directory${queryString(input)}`),
|
|
295
|
+
get: (ref: ActorRef) =>
|
|
296
|
+
this.request<AddressableActor>(
|
|
297
|
+
'GET',
|
|
298
|
+
`actor-directory/${ref.kind}/${encodeURIComponent(ref.id)}`,
|
|
299
|
+
),
|
|
300
|
+
registerHuman: async (_input: {
|
|
301
|
+
id: string;
|
|
302
|
+
handle: string;
|
|
303
|
+
displayName: string;
|
|
304
|
+
}): Promise<AddressableActor> => {
|
|
305
|
+
void _input;
|
|
306
|
+
throw new SynomemError(
|
|
307
|
+
'MUTATION_FORBIDDEN',
|
|
308
|
+
'Hosted human identities are provisioned through workspace membership.',
|
|
309
|
+
);
|
|
310
|
+
},
|
|
311
|
+
};
|
|
198
312
|
readonly agents = {
|
|
199
313
|
create: (input: CreateAgentInput) =>
|
|
200
314
|
this.request<Awaited<ReturnType<SynomemService['agents']['create']>>>(
|
|
@@ -329,24 +443,41 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
329
443
|
input,
|
|
330
444
|
['postId'],
|
|
331
445
|
),
|
|
332
|
-
archive: (input: {
|
|
446
|
+
archive: (input: {
|
|
447
|
+
expectedVersion: number;
|
|
448
|
+
postId: string;
|
|
449
|
+
reason?: string;
|
|
450
|
+
idempotencyKey?: string;
|
|
451
|
+
}) =>
|
|
333
452
|
this.mutation<Awaited<ReturnType<SynomemService['posts']['archive']>>>(
|
|
334
453
|
'POST',
|
|
335
454
|
`posts/${encodeURIComponent(input.postId)}/archive`,
|
|
336
455
|
input,
|
|
337
456
|
['postId'],
|
|
338
457
|
),
|
|
339
|
-
acknowledge: (input: {
|
|
458
|
+
acknowledge: (input: {
|
|
459
|
+
expectedVersion: number;
|
|
460
|
+
postId: string;
|
|
461
|
+
note?: string;
|
|
462
|
+
idempotencyKey?: string;
|
|
463
|
+
}) =>
|
|
340
464
|
this.mutation<Awaited<ReturnType<SynomemService['posts']['acknowledge']>>>(
|
|
341
465
|
'POST',
|
|
342
466
|
`posts/${encodeURIComponent(input.postId)}/acknowledgment`,
|
|
343
467
|
input,
|
|
344
468
|
['postId'],
|
|
345
469
|
),
|
|
346
|
-
withdrawAcknowledgment: (input: {
|
|
347
|
-
|
|
470
|
+
withdrawAcknowledgment: (input: {
|
|
471
|
+
expectedVersion: number;
|
|
472
|
+
postId: string;
|
|
473
|
+
reason?: string;
|
|
474
|
+
idempotencyKey?: string;
|
|
475
|
+
}) =>
|
|
476
|
+
this.mutation<Awaited<ReturnType<SynomemService['posts']['withdrawAcknowledgment']>>>(
|
|
348
477
|
'DELETE',
|
|
349
478
|
`posts/${encodeURIComponent(input.postId)}/acknowledgment`,
|
|
479
|
+
input,
|
|
480
|
+
['postId'],
|
|
350
481
|
),
|
|
351
482
|
roster: (postId: string) =>
|
|
352
483
|
this.request<Awaited<ReturnType<SynomemService['posts']['roster']>>>(
|
|
@@ -373,17 +504,30 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
373
504
|
'GET',
|
|
374
505
|
`kudos/${encodeURIComponent(id)}`,
|
|
375
506
|
),
|
|
376
|
-
acknowledge: (input: {
|
|
377
|
-
|
|
507
|
+
acknowledge: (input: {
|
|
508
|
+
expectedVersion: number;
|
|
509
|
+
kudosId: string;
|
|
510
|
+
note?: string;
|
|
511
|
+
idempotencyKey?: string;
|
|
512
|
+
}) =>
|
|
513
|
+
this.mutation<Awaited<ReturnType<SynomemService['kudos']['acknowledge']>>>(
|
|
378
514
|
'POST',
|
|
379
515
|
`kudos/${encodeURIComponent(input.kudosId)}/acknowledgment`,
|
|
380
|
-
input
|
|
516
|
+
input,
|
|
517
|
+
['kudosId'],
|
|
381
518
|
),
|
|
382
|
-
revoke: (input: {
|
|
383
|
-
|
|
519
|
+
revoke: (input: {
|
|
520
|
+
expectedVersion: number;
|
|
521
|
+
kudosId: string;
|
|
522
|
+
reason: string;
|
|
523
|
+
administrative?: boolean;
|
|
524
|
+
idempotencyKey?: string;
|
|
525
|
+
}) =>
|
|
526
|
+
this.mutation<Awaited<ReturnType<SynomemService['kudos']['revoke']>>>(
|
|
384
527
|
'POST',
|
|
385
528
|
`kudos/${encodeURIComponent(input.kudosId)}/revocation`,
|
|
386
|
-
|
|
529
|
+
input,
|
|
530
|
+
['kudosId', 'administrative'],
|
|
387
531
|
),
|
|
388
532
|
};
|
|
389
533
|
|
|
@@ -400,14 +544,14 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
400
544
|
'GET',
|
|
401
545
|
`memos/${encodeURIComponent(id)}`,
|
|
402
546
|
),
|
|
403
|
-
read: (input: { memoId: string; idempotencyKey?: string }) =>
|
|
547
|
+
read: (input: { expectedVersion: number; memoId: string; idempotencyKey?: string }) =>
|
|
404
548
|
this.mutation<Awaited<ReturnType<SynomemService['memos']['read']>>>(
|
|
405
549
|
'POST',
|
|
406
550
|
`memos/${encodeURIComponent(input.memoId)}/read`,
|
|
407
551
|
input,
|
|
408
552
|
['memoId'],
|
|
409
553
|
),
|
|
410
|
-
archive: (input: { memoId: string; idempotencyKey?: string }) =>
|
|
554
|
+
archive: (input: { expectedVersion: number; memoId: string; idempotencyKey?: string }) =>
|
|
411
555
|
this.mutation<Awaited<ReturnType<SynomemService['memos']['archive']>>>(
|
|
412
556
|
'POST',
|
|
413
557
|
`memos/${encodeURIComponent(input.memoId)}/archive`,
|
|
@@ -436,7 +580,7 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
436
580
|
input,
|
|
437
581
|
['noteId'],
|
|
438
582
|
),
|
|
439
|
-
archive: (input: { noteId: string; idempotencyKey?: string }) =>
|
|
583
|
+
archive: (input: { expectedVersion: number; noteId: string; idempotencyKey?: string }) =>
|
|
440
584
|
this.mutation<Awaited<ReturnType<SynomemService['notes']['archive']>>>(
|
|
441
585
|
'POST',
|
|
442
586
|
`notes/${encodeURIComponent(input.noteId)}/archive`,
|
|
@@ -446,6 +590,7 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
446
590
|
};
|
|
447
591
|
|
|
448
592
|
readonly tasks = {
|
|
593
|
+
overrideDecision: (input: OverrideTaskDecisionInput) => this.taskTransition('override', input),
|
|
449
594
|
create: (input: CreateTaskInput) =>
|
|
450
595
|
this.mutation<Awaited<ReturnType<SynomemService['tasks']['create']>>>('POST', 'tasks', input),
|
|
451
596
|
list: (input: Omit<ItemListInput, 'kinds'> = {}) =>
|
|
@@ -465,16 +610,32 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
465
610
|
input,
|
|
466
611
|
['taskId'],
|
|
467
612
|
),
|
|
468
|
-
accept: (input: {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
613
|
+
accept: (input: {
|
|
614
|
+
expectedVersion: number;
|
|
615
|
+
taskId: string;
|
|
616
|
+
response?: string;
|
|
617
|
+
idempotencyKey?: string;
|
|
618
|
+
}) => this.taskTransition('accept', input),
|
|
619
|
+
reject: (input: {
|
|
620
|
+
expectedVersion: number;
|
|
621
|
+
taskId: string;
|
|
622
|
+
response: string;
|
|
623
|
+
idempotencyKey?: string;
|
|
624
|
+
}) => this.taskTransition('reject', input),
|
|
625
|
+
complete: (input: {
|
|
626
|
+
expectedVersion: number;
|
|
627
|
+
taskId: string;
|
|
628
|
+
note?: string;
|
|
629
|
+
idempotencyKey?: string;
|
|
630
|
+
}) => this.taskTransition('complete', input),
|
|
631
|
+
reopen: (input: { expectedVersion: number; taskId: string; idempotencyKey?: string }) =>
|
|
475
632
|
this.taskTransition('reopen', input),
|
|
476
|
-
cancel: (input: {
|
|
477
|
-
|
|
633
|
+
cancel: (input: {
|
|
634
|
+
expectedVersion: number;
|
|
635
|
+
taskId: string;
|
|
636
|
+
reason?: string;
|
|
637
|
+
idempotencyKey?: string;
|
|
638
|
+
}) => this.taskTransition('cancel', input),
|
|
478
639
|
};
|
|
479
640
|
|
|
480
641
|
/**
|
|
@@ -501,13 +662,21 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
501
662
|
input,
|
|
502
663
|
['todoId'],
|
|
503
664
|
),
|
|
504
|
-
complete: (input: {
|
|
505
|
-
|
|
506
|
-
|
|
665
|
+
complete: (input: {
|
|
666
|
+
expectedVersion: number;
|
|
667
|
+
todoId: string;
|
|
668
|
+
note?: string;
|
|
669
|
+
idempotencyKey?: string;
|
|
670
|
+
}) => this.todoTransition('complete', input),
|
|
671
|
+
reopen: (input: { expectedVersion: number; todoId: string; idempotencyKey?: string }) =>
|
|
507
672
|
this.todoTransition('reopen', input),
|
|
508
|
-
cancel: (input: {
|
|
509
|
-
|
|
510
|
-
|
|
673
|
+
cancel: (input: {
|
|
674
|
+
expectedVersion: number;
|
|
675
|
+
todoId: string;
|
|
676
|
+
reason?: string;
|
|
677
|
+
idempotencyKey?: string;
|
|
678
|
+
}) => this.todoTransition('cancel', input),
|
|
679
|
+
archive: (input: { expectedVersion: number; todoId: string; idempotencyKey?: string }) =>
|
|
511
680
|
this.todoTransition('archive', input),
|
|
512
681
|
};
|
|
513
682
|
|
|
@@ -540,6 +709,12 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
540
709
|
},
|
|
541
710
|
};
|
|
542
711
|
|
|
712
|
+
async search(input: SearchInput): Promise<SearchPage> {
|
|
713
|
+
const capabilities = await this.capabilities();
|
|
714
|
+
if (!capabilities.participation?.search)
|
|
715
|
+
throw new SynomemError('UNSUPPORTED_BACKEND', 'This workspace does not support search.');
|
|
716
|
+
return this.request('GET', `search${queryString(input)}`);
|
|
717
|
+
}
|
|
543
718
|
readonly items = {
|
|
544
719
|
list: (input: ItemListInput = {}) =>
|
|
545
720
|
this.request<Awaited<ReturnType<SynomemService['items']['list']>>>(
|
|
@@ -595,6 +770,11 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
595
770
|
if (this.cachedCapabilities.backend !== 'remote') {
|
|
596
771
|
throw new SynomemError('REMOTE_PROTOCOL', 'The configured server is not a remote backend.');
|
|
597
772
|
}
|
|
773
|
+
if (this.cachedCapabilities.participation?.version !== 2)
|
|
774
|
+
throw new SynomemError(
|
|
775
|
+
'UNSUPPORTED_SCHEMA',
|
|
776
|
+
'This client requires the human participation v2 contract.',
|
|
777
|
+
);
|
|
598
778
|
const binding = this.cachedCapabilities.binding;
|
|
599
779
|
if (binding.workspaceId !== this.workspaceId) {
|
|
600
780
|
throw new SynomemError(
|
|
@@ -646,10 +826,8 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
646
826
|
}
|
|
647
827
|
|
|
648
828
|
async capabilities(): Promise<SynomemServiceCapabilities> {
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
(await this.request<SynomemServiceCapabilities>('GET', '../../capabilities'))
|
|
652
|
-
);
|
|
829
|
+
await this.init();
|
|
830
|
+
return this.cachedCapabilities!;
|
|
653
831
|
}
|
|
654
832
|
|
|
655
833
|
async info(): Promise<SynomemServiceInfo> {
|
|
@@ -664,8 +842,9 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
664
842
|
}
|
|
665
843
|
|
|
666
844
|
private taskTransition(
|
|
667
|
-
transition: 'accept' | 'reject' | 'complete' | 'reopen' | 'cancel',
|
|
845
|
+
transition: 'accept' | 'reject' | 'complete' | 'reopen' | 'cancel' | 'override',
|
|
668
846
|
input: {
|
|
847
|
+
expectedVersion: number;
|
|
669
848
|
taskId: string;
|
|
670
849
|
idempotencyKey?: string;
|
|
671
850
|
reason?: string;
|
|
@@ -683,7 +862,13 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
683
862
|
|
|
684
863
|
private todoTransition(
|
|
685
864
|
transition: 'complete' | 'reopen' | 'cancel' | 'archive',
|
|
686
|
-
input: {
|
|
865
|
+
input: {
|
|
866
|
+
expectedVersion: number;
|
|
867
|
+
todoId: string;
|
|
868
|
+
idempotencyKey?: string;
|
|
869
|
+
reason?: string;
|
|
870
|
+
note?: string;
|
|
871
|
+
},
|
|
687
872
|
) {
|
|
688
873
|
return this.mutation<Awaited<ReturnType<SynomemService['todos']['complete']>>>(
|
|
689
874
|
'POST',
|
|
@@ -694,7 +879,7 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
694
879
|
}
|
|
695
880
|
|
|
696
881
|
private mutation<T>(
|
|
697
|
-
method: 'POST' | 'PATCH',
|
|
882
|
+
method: 'POST' | 'PATCH' | 'DELETE',
|
|
698
883
|
path: string,
|
|
699
884
|
input: object,
|
|
700
885
|
omittedKeys: string[] = [],
|
|
@@ -708,11 +893,16 @@ export class RemoteSynomemService implements SynomemService {
|
|
|
708
893
|
}
|
|
709
894
|
|
|
710
895
|
private async request<T>(
|
|
711
|
-
method: 'GET' | 'POST' | 'PATCH' | 'DELETE',
|
|
896
|
+
method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE',
|
|
712
897
|
path: string,
|
|
713
898
|
body?: object,
|
|
714
899
|
idempotencyKey?: string,
|
|
715
900
|
): Promise<T> {
|
|
901
|
+
if (method !== 'GET') {
|
|
902
|
+
await this.init();
|
|
903
|
+
if (!this.cachedCapabilities?.participation?.canWrite)
|
|
904
|
+
throw new SynomemError('READ_ONLY', 'The selected binding has no write capability.');
|
|
905
|
+
}
|
|
716
906
|
const accessToken = await this.bearer(this.signal);
|
|
717
907
|
if (!accessToken) {
|
|
718
908
|
throw new SynomemError('AUTH_REQUIRED', 'Remote Synomem authentication is required.');
|