@xfey/tutti 0.1.104 → 0.1.106

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.
Files changed (64) hide show
  1. package/README.md +2 -2
  2. package/dist/approvals/decision-command.d.ts +124 -0
  3. package/dist/approvals/decision-command.js +20 -0
  4. package/dist/approvals/index.d.ts +1 -0
  5. package/dist/approvals/index.js +1 -0
  6. package/dist/approvals/manager.d.ts +3 -1
  7. package/dist/approvals/manager.js +9 -0
  8. package/dist/collaboration-ingestion/index.d.ts +3 -0
  9. package/dist/collaboration-ingestion/index.js +3 -0
  10. package/dist/collaboration-ingestion/managed-reference-snapshots.d.ts +27 -0
  11. package/dist/collaboration-ingestion/managed-reference-snapshots.js +45 -0
  12. package/dist/collaboration-ingestion/managed-reference-sources.d.ts +20 -0
  13. package/dist/collaboration-ingestion/managed-reference-sources.js +250 -0
  14. package/dist/collaboration-ingestion/reference-attachments.d.ts +22 -0
  15. package/dist/collaboration-ingestion/reference-attachments.js +132 -0
  16. package/dist/collaboration-ingestion/reference-files.d.ts +3 -2
  17. package/dist/collaboration-ingestion/reference-files.js +1 -0
  18. package/dist/platform-outbound/coordinator.d.ts +5 -2
  19. package/dist/platform-outbound/coordinator.js +95 -2
  20. package/dist/platform-outbound/repository.d.ts +17 -0
  21. package/dist/platform-outbound/repository.js +190 -5
  22. package/dist/platform-outbound/types.d.ts +13 -3
  23. package/dist/platform-outbound/worker.js +30 -14
  24. package/dist/server-shell/cli/host-lifecycle.js +3 -0
  25. package/dist/server-shell/cli/host-server-runtime.d.ts +4 -1
  26. package/dist/server-shell/cli/host-server-runtime.js +128 -40
  27. package/dist/server-shell/cli/relay-registration.js +3 -0
  28. package/dist/server-shell/http/host-tunnel.d.ts +4 -1
  29. package/dist/server-shell/http/host-tunnel.js +174 -3
  30. package/dist/server-shell/http/routes/project-api/approval-routes.js +13 -20
  31. package/dist/server-shell/http/routes/project-api/staged-uploads.d.ts +6 -0
  32. package/dist/server-shell/http/routes/project-api/staged-uploads.js +9 -2
  33. package/dist/server-shell/local-console/project-service.d.ts +2 -0
  34. package/dist/server-shell/local-console/project-service.js +37 -0
  35. package/dist/server-shell/local-console/server.js +4 -0
  36. package/dist/workspace-ops/index.d.ts +2 -2
  37. package/dist/workspace-ops/index.js +1 -1
  38. package/dist/workspace-ops/reference-files.d.ts +14 -1
  39. package/dist/workspace-ops/reference-files.js +167 -2
  40. package/dist/workspace-ops/types.d.ts +24 -0
  41. package/migrations/0018_platform_outbound_events.sql +111 -0
  42. package/migrations/0019_platform_outbound_card_content.sql +76 -0
  43. package/migrations/0020_managed_reference_sources.sql +34 -0
  44. package/migrations/README.md +4 -1
  45. package/node_modules/@tutti/relay-client/dist/host-control.d.ts +5 -2
  46. package/node_modules/@tutti/relay-client/dist/host-control.js +3 -0
  47. package/node_modules/@tutti/shared/dist/schemas/api/index.d.ts +2 -2
  48. package/node_modules/@tutti/shared/dist/schemas/api/index.js +1 -1
  49. package/node_modules/@tutti/shared/dist/schemas/api/platform-sessions.d.ts +34 -0
  50. package/node_modules/@tutti/shared/dist/schemas/api/platform-sessions.js +37 -0
  51. package/node_modules/@tutti/shared/dist/schemas/internal/feishu-user-credentials.d.ts +22 -0
  52. package/node_modules/@tutti/shared/dist/schemas/internal/feishu-user-credentials.js +37 -0
  53. package/node_modules/@tutti/shared/dist/schemas/internal/index.d.ts +1 -0
  54. package/node_modules/@tutti/shared/dist/schemas/internal/index.js +1 -0
  55. package/node_modules/@tutti/shared/dist/schemas/internal/platform-integration.d.ts +1005 -49
  56. package/node_modules/@tutti/shared/dist/schemas/internal/platform-integration.js +434 -14
  57. package/package.json +1 -1
  58. package/prompts/skills/read-references/README.md +1 -1
  59. package/prompts/skills/read-references/SKILL.md +4 -2
  60. package/web/assets/{homepage-motion-scene-DEVrQ9aj.js → homepage-motion-scene-tfFEdV9Y.js} +1 -1
  61. package/web/assets/index-B7ZGIvOv.js +69 -0
  62. package/web/assets/{index-6i9Uk7fS.css → index-C2Mmj25S.css} +1 -1
  63. package/web/index.html +2 -2
  64. package/web/assets/index-Lxtst2sl.js +0 -69
@@ -1,6 +1,7 @@
1
1
  import { Type } from "@sinclair/typebox";
2
2
  import { Value } from "@sinclair/typebox/value";
3
3
  import { IdempotencyKeySchema, IsoDateTimeStringSchema, MessageIdSchema, RelayAccountRefSchema, RelayProjectRefSchema, } from "../domain/index.js";
4
+ import { MAX_REFERENCE_STAGED_UPLOAD_BYTES, PresignedUploadPutSchema, ReferenceStagedUploadReferenceProperties, RelayUploadProjectionSchema, } from "../api/uploads.js";
4
5
  export const PlatformAdapterKeySchema = Type.String({
5
6
  minLength: 1,
6
7
  maxLength: 64,
@@ -52,6 +53,7 @@ export const TrustedHumanIntegrationActorContextSchema = Type.Object({
52
53
  Type.Literal("platform_chat"),
53
54
  Type.Literal("platform_h5"),
54
55
  Type.Literal("platform_card_callback"),
56
+ Type.Literal("platform_document_sync"),
55
57
  ]),
56
58
  external_subject: ExternalSubjectLocatorSchema,
57
59
  binding_ref: IntegrationOwnedRefSchema,
@@ -116,11 +118,19 @@ export const ExternalAttachmentDescriptorSchema = Type.Object({
116
118
  }, { additionalProperties: false });
117
119
  export const VerifiedAttachmentContentMetadataSchema = Type.Object({
118
120
  attachment: ExternalAttachmentDescriptorSchema,
119
- size_bytes: Type.Integer({ minimum: 0, maximum: Number.MAX_SAFE_INTEGER }),
121
+ size_bytes: Type.Integer({ minimum: 1, maximum: Number.MAX_SAFE_INTEGER }),
120
122
  sha256: Type.String({ pattern: "^sha256:[0-9a-f]{64}$" }),
121
123
  media_type: Type.String({ minLength: 1, maxLength: 255 }),
122
124
  verified_at: IsoDateTimeStringSchema,
123
125
  }, { additionalProperties: false });
126
+ export const PreIdentityReferenceAttachmentSourceSchema = Type.Object({
127
+ locator: ExternalMessageLocatorSchema,
128
+ author: PreIdentityConversationAuthorSchema,
129
+ attachment: ExternalAttachmentDescriptorSchema,
130
+ external_created_at: IsoDateTimeStringSchema,
131
+ observed_at: IsoDateTimeStringSchema,
132
+ adapter_version: Type.String({ minLength: 1, maxLength: 128 }),
133
+ }, { additionalProperties: false });
124
134
  export const NormalizedConversationSourceSchema = Type.Object({
125
135
  locator: ExternalMessageLocatorSchema,
126
136
  revision_ref: ExternalObjectRefSchema,
@@ -221,7 +231,11 @@ export const IntegrationDeliveryDispositionSchema = Type.Union([
221
231
  Type.Object({
222
232
  kind: Type.Literal("host_incompatible"),
223
233
  retryable: Type.Literal(true),
224
- reason_code: Type.Literal("integration_source_ingestion_unsupported"),
234
+ reason_code: Type.Union([
235
+ Type.Literal("integration_source_ingestion_unsupported"),
236
+ Type.Literal("integration_attachment_ingestion_unsupported"),
237
+ Type.Literal("integration_managed_reference_ingestion_unsupported"),
238
+ ]),
225
239
  }, { additionalProperties: false }),
226
240
  Type.Object({
227
241
  kind: Type.Literal("invalid"),
@@ -236,6 +250,39 @@ export const IntegrationConversationSourceDeliveryRequestSchema = Type.Object({
236
250
  receipt: InboundIntegrationEventReceiptSchema,
237
251
  source: PreIdentityNormalizedConversationSourceSchema,
238
252
  }, { additionalProperties: false });
253
+ export const IntegrationReferenceAttachmentStageRequestSchema = Type.Object({
254
+ protocol_version: Type.Literal(1),
255
+ command_id: IdempotencyKeySchema,
256
+ relay_project_ref: RelayProjectRefSchema,
257
+ binding_ref: IntegrationOwnedRefSchema,
258
+ receipt: InboundIntegrationEventReceiptSchema,
259
+ source: PreIdentityReferenceAttachmentSourceSchema,
260
+ content: VerifiedAttachmentContentMetadataSchema,
261
+ }, { additionalProperties: false });
262
+ export const IntegrationReferenceAttachmentStageDispositionSchema = Type.Union([
263
+ Type.Object({
264
+ kind: Type.Literal("staged"),
265
+ upload: RelayUploadProjectionSchema,
266
+ put: PresignedUploadPutSchema,
267
+ }, { additionalProperties: false }),
268
+ Type.Object({
269
+ kind: Type.Literal("unauthorized"),
270
+ reason_code: Type.String({ minLength: 1, maxLength: 128 }),
271
+ }, { additionalProperties: false }),
272
+ Type.Object({
273
+ kind: Type.Literal("invalid"),
274
+ reason_code: Type.String({ minLength: 1, maxLength: 128 }),
275
+ }, { additionalProperties: false }),
276
+ Type.Object({
277
+ kind: Type.Literal("unavailable"),
278
+ retryable: Type.Literal(true),
279
+ reason_code: Type.String({ minLength: 1, maxLength: 128 }),
280
+ }, { additionalProperties: false }),
281
+ ]);
282
+ export const IntegrationReferenceAttachmentStageResponseSchema = Type.Object({
283
+ protocol_version: Type.Literal(1),
284
+ disposition: IntegrationReferenceAttachmentStageDispositionSchema,
285
+ }, { additionalProperties: false });
239
286
  export const FEISHU_CONVERSATION_PAIRING_CODE_LENGTH = 20;
240
287
  export const FeishuConversationPairingCodeSchema = Type.String({
241
288
  minLength: FEISHU_CONVERSATION_PAIRING_CODE_LENGTH,
@@ -296,6 +343,106 @@ export const IntegrationConversationBindingResponseSchema = Type.Object({
296
343
  disposition: IntegrationConversationBindingDispositionSchema,
297
344
  }, { additionalProperties: false });
298
345
  export const INTEGRATION_CONVERSATION_SOURCE_TUNNEL_PATH = "/internal/integration/v1/conversation-sources";
346
+ export const INTEGRATION_REFERENCE_ATTACHMENT_TUNNEL_PATH = "/internal/integration/v1/reference-attachments";
347
+ export const INTEGRATION_MANAGED_REFERENCE_TUNNEL_PATH = "/internal/integration/v1/managed-references";
348
+ export const ManagedReferenceSourceSchema = Type.Object({
349
+ source_ref: IntegrationOwnedRefSchema,
350
+ adapter_key: Type.Literal("feishu_docx"),
351
+ installation: PlatformInstallationLocatorSchema,
352
+ external_subject: ExternalSubjectLocatorSchema,
353
+ reference_path: Type.String({ minLength: 1, maxLength: 1_024 }),
354
+ }, { additionalProperties: false });
355
+ export const ManagedReferenceContentMetadataSchema = Type.Object({
356
+ size_bytes: Type.Integer({ minimum: 0, maximum: Number.MAX_SAFE_INTEGER }),
357
+ sha256: Type.String({ pattern: "^sha256:[0-9a-f]{64}$" }),
358
+ media_type: Type.Literal("text/plain; charset=utf-8"),
359
+ }, { additionalProperties: false });
360
+ export const IntegrationManagedReferenceStageRequestSchema = Type.Object({
361
+ protocol_version: Type.Literal(1),
362
+ command_id: IdempotencyKeySchema,
363
+ operation_ref: IntegrationOwnedRefSchema,
364
+ relay_project_ref: RelayProjectRefSchema,
365
+ binding_ref: IntegrationOwnedRefSchema,
366
+ source: ManagedReferenceSourceSchema,
367
+ remote_revision_ref: ExternalObjectRefSchema,
368
+ expected_host_blob_oid: Type.Optional(Type.String({ pattern: "^[0-9a-f]{40,64}$" })),
369
+ content: ManagedReferenceContentMetadataSchema,
370
+ }, { additionalProperties: false });
371
+ export const IntegrationManagedReferenceStageDispositionSchema = IntegrationReferenceAttachmentStageDispositionSchema;
372
+ export const IntegrationManagedReferenceStageResponseSchema = Type.Object({
373
+ protocol_version: Type.Literal(1),
374
+ disposition: IntegrationManagedReferenceStageDispositionSchema,
375
+ }, { additionalProperties: false });
376
+ export const IntegrationManagedReferenceDeliveryRequestSchema = Type.Object({
377
+ protocol_version: Type.Literal(1),
378
+ command_id: IdempotencyKeySchema,
379
+ operation_ref: IntegrationOwnedRefSchema,
380
+ relay_project_ref: RelayProjectRefSchema,
381
+ binding_ref: IntegrationOwnedRefSchema,
382
+ source: ManagedReferenceSourceSchema,
383
+ remote_revision_ref: ExternalObjectRefSchema,
384
+ expected_host_blob_oid: Type.Optional(Type.String({ pattern: "^[0-9a-f]{40,64}$" })),
385
+ content: ManagedReferenceContentMetadataSchema,
386
+ staged_upload: Type.Object(ReferenceStagedUploadReferenceProperties, {
387
+ additionalProperties: false,
388
+ }),
389
+ }, { additionalProperties: false });
390
+ export const TrustedManagedReferenceIngestionCommandSchema = Type.Object({
391
+ protocol_version: Type.Literal(1),
392
+ command_id: IdempotencyKeySchema,
393
+ operation_ref: IntegrationOwnedRefSchema,
394
+ relay_project_ref: RelayProjectRefSchema,
395
+ binding_ref: IntegrationOwnedRefSchema,
396
+ source: ManagedReferenceSourceSchema,
397
+ remote_revision_ref: ExternalObjectRefSchema,
398
+ expected_host_blob_oid: Type.Optional(Type.String({ pattern: "^[0-9a-f]{40,64}$" })),
399
+ content: ManagedReferenceContentMetadataSchema,
400
+ staged_upload: Type.Object(ReferenceStagedUploadReferenceProperties, {
401
+ additionalProperties: false,
402
+ }),
403
+ actor: TrustedHumanIntegrationActorContextSchema,
404
+ }, { additionalProperties: false });
405
+ export const IntegrationManagedReferenceDispositionSchema = Type.Union([
406
+ Type.Object({
407
+ kind: Type.Union([
408
+ Type.Literal("created"),
409
+ Type.Literal("updated"),
410
+ Type.Literal("unchanged"),
411
+ ]),
412
+ current_blob_oid: Type.String({ pattern: "^[0-9a-f]{40,64}$" }),
413
+ }, { additionalProperties: false }),
414
+ Type.Object({
415
+ kind: Type.Literal("duplicate"),
416
+ outcome: Type.Union([
417
+ Type.Literal("created"),
418
+ Type.Literal("updated"),
419
+ Type.Literal("unchanged"),
420
+ ]),
421
+ current_blob_oid: Type.String({ pattern: "^[0-9a-f]{40,64}$" }),
422
+ }, { additionalProperties: false }),
423
+ Type.Object({
424
+ kind: Type.Literal("host_unavailable"),
425
+ retryable: Type.Literal(true),
426
+ reason_code: Type.String({ minLength: 1, maxLength: 128 }),
427
+ }, { additionalProperties: false }),
428
+ Type.Object({
429
+ kind: Type.Literal("host_incompatible"),
430
+ retryable: Type.Literal(true),
431
+ reason_code: Type.Literal("integration_managed_reference_ingestion_unsupported"),
432
+ }, { additionalProperties: false }),
433
+ Type.Object({
434
+ kind: Type.Union([
435
+ Type.Literal("invalid"),
436
+ Type.Literal("unauthorized"),
437
+ Type.Literal("conflict"),
438
+ ]),
439
+ reason_code: Type.String({ minLength: 1, maxLength: 128 }),
440
+ }, { additionalProperties: false }),
441
+ ]);
442
+ export const IntegrationManagedReferenceDeliveryResponseSchema = Type.Object({
443
+ protocol_version: Type.Literal(1),
444
+ disposition: IntegrationManagedReferenceDispositionSchema,
445
+ }, { additionalProperties: false });
299
446
  export const TrustedConversationSourceIngestionCommandSchema = Type.Object({
300
447
  protocol_version: Type.Literal(1),
301
448
  command_id: IdempotencyKeySchema,
@@ -305,14 +452,47 @@ export const TrustedConversationSourceIngestionCommandSchema = Type.Object({
305
452
  actor: TrustedHumanIntegrationActorContextSchema,
306
453
  source: NormalizedConversationSourceSchema,
307
454
  }, { additionalProperties: false });
308
- export const IntegrationDeliveryTunnelMetadataSchema = Type.Object({
455
+ export const IntegrationReferenceAttachmentDeliveryRequestSchema = Type.Object({
309
456
  protocol_version: Type.Literal(1),
457
+ command_id: IdempotencyKeySchema,
310
458
  relay_project_ref: RelayProjectRefSchema,
311
- installation: PlatformInstallationLocatorSchema,
312
459
  binding_ref: IntegrationOwnedRefSchema,
313
- receipt_key: IntegrationOwnedRefSchema,
314
- verified_at: IsoDateTimeStringSchema,
460
+ receipt: InboundIntegrationEventReceiptSchema,
461
+ source: PreIdentityReferenceAttachmentSourceSchema,
462
+ staged_upload: Type.Object(ReferenceStagedUploadReferenceProperties, {
463
+ additionalProperties: false,
464
+ }),
315
465
  }, { additionalProperties: false });
466
+ export const TrustedReferenceAttachmentIngestionCommandSchema = Type.Object({
467
+ protocol_version: Type.Literal(1),
468
+ command_id: IdempotencyKeySchema,
469
+ relay_project_ref: RelayProjectRefSchema,
470
+ binding_ref: IntegrationOwnedRefSchema,
471
+ receipt: InboundIntegrationEventReceiptSchema,
472
+ actor: TrustedHumanIntegrationActorContextSchema,
473
+ source: PreIdentityReferenceAttachmentSourceSchema,
474
+ staged_upload: Type.Object(ReferenceStagedUploadReferenceProperties, {
475
+ additionalProperties: false,
476
+ }),
477
+ }, { additionalProperties: false });
478
+ export const IntegrationDeliveryTunnelMetadataSchema = Type.Union([
479
+ Type.Object({
480
+ protocol_version: Type.Literal(1),
481
+ relay_project_ref: RelayProjectRefSchema,
482
+ installation: PlatformInstallationLocatorSchema,
483
+ binding_ref: IntegrationOwnedRefSchema,
484
+ receipt_key: IntegrationOwnedRefSchema,
485
+ verified_at: IsoDateTimeStringSchema,
486
+ }, { additionalProperties: false }),
487
+ Type.Object({
488
+ protocol_version: Type.Literal(1),
489
+ relay_project_ref: RelayProjectRefSchema,
490
+ installation: PlatformInstallationLocatorSchema,
491
+ binding_ref: IntegrationOwnedRefSchema,
492
+ operation_ref: IntegrationOwnedRefSchema,
493
+ verified_at: IsoDateTimeStringSchema,
494
+ }, { additionalProperties: false }),
495
+ ]);
316
496
  export const IntegrationConversationSourceDeliveryResponseSchema = Type.Object({
317
497
  protocol_version: Type.Literal(1),
318
498
  disposition: IntegrationDeliveryDispositionSchema,
@@ -321,25 +501,149 @@ const PlatformOutboundTextContentSchema = Type.Object({
321
501
  kind: Type.Literal("text"),
322
502
  text: Type.String({ minLength: 1, maxLength: 4_000 }),
323
503
  }, { additionalProperties: false });
504
+ export const PlatformApprovalCardRevisionSchema = Type.String({
505
+ minLength: 1,
506
+ maxLength: 128,
507
+ pattern: "^cardrev_[0-9a-f]{32}$",
508
+ });
509
+ export const PlatformApprovalDecisionOptionSchema = Type.Object({
510
+ decision_id: Type.String({ minLength: 1, maxLength: 256 }),
511
+ kind: Type.Union([
512
+ Type.Literal("allow_once"),
513
+ Type.Literal("allow_session"),
514
+ Type.Literal("deny"),
515
+ Type.Literal("cancel"),
516
+ ]),
517
+ label: Type.String({ minLength: 1, maxLength: 256 }),
518
+ tone: Type.Union([Type.Literal("primary"), Type.Literal("neutral"), Type.Literal("danger")]),
519
+ }, { additionalProperties: false });
520
+ export const PlatformOutboundApprovalRequestContentSchema = Type.Object({
521
+ kind: Type.Literal("approval_request"),
522
+ approval_id: Type.String({ minLength: 1, maxLength: 256 }),
523
+ card_revision: PlatformApprovalCardRevisionSchema,
524
+ title: Type.String({ minLength: 1, maxLength: 512 }),
525
+ summary: Type.String({ minLength: 1, maxLength: 4_000 }),
526
+ reason: Type.Optional(Type.String({ minLength: 1, maxLength: 2_000 })),
527
+ requested_at: IsoDateTimeStringSchema,
528
+ expires_at: Type.Optional(IsoDateTimeStringSchema),
529
+ decisions: Type.Array(PlatformApprovalDecisionOptionSchema, {
530
+ minItems: 1,
531
+ maxItems: 8,
532
+ }),
533
+ }, { additionalProperties: false });
534
+ export const PlatformOutboundContentSchema = Type.Union([
535
+ PlatformOutboundTextContentSchema,
536
+ PlatformOutboundApprovalRequestContentSchema,
537
+ ]);
538
+ export const PlatformOutboundEventSchema = Type.Object({
539
+ kind: Type.Union([
540
+ Type.Literal("chat_response"),
541
+ Type.Literal("needs_input"),
542
+ Type.Literal("task_completed"),
543
+ Type.Literal("task_failed"),
544
+ ]),
545
+ event_key: ExternalObjectRefSchema,
546
+ subject: Type.Object({
547
+ kind: Type.Union([
548
+ Type.Literal("message"),
549
+ Type.Literal("clarification_round"),
550
+ Type.Literal("approval_request"),
551
+ Type.Literal("task_result"),
552
+ ]),
553
+ ref: ExternalObjectRefSchema,
554
+ }, { additionalProperties: false }),
555
+ target: Type.Object({
556
+ kind: Type.Union([Type.Literal("project"), Type.Literal("work")]),
557
+ }, { additionalProperties: false }),
558
+ }, { additionalProperties: false });
324
559
  const PlatformOutboundIntentFields = {
325
560
  protocol_version: Type.Literal(1),
326
561
  intent_ref: IdempotencyKeySchema,
327
562
  relay_project_ref: RelayProjectRefSchema,
328
563
  installation: PlatformInstallationLocatorSchema,
329
564
  binding_ref: IntegrationOwnedRefSchema,
330
- canonical_message_ref: MessageIdSchema,
331
- trigger_message_ref: MessageIdSchema,
332
- content: PlatformOutboundTextContentSchema,
565
+ canonical_message_ref: Type.Optional(MessageIdSchema),
566
+ trigger_message_ref: Type.Optional(MessageIdSchema),
567
+ content: PlatformOutboundContentSchema,
568
+ event: Type.Optional(PlatformOutboundEventSchema),
333
569
  created_at: IsoDateTimeStringSchema,
334
570
  attempt: Type.Integer({ minimum: 1, maximum: 1_000_000 }),
335
571
  };
336
- export const PlatformOutboundTextIntentSchema = Type.Object(PlatformOutboundIntentFields, {
572
+ export const PlatformOutboundIntentSchema = Type.Object(PlatformOutboundIntentFields, {
337
573
  additionalProperties: false,
338
574
  });
339
- export const RelayAuthorizedPlatformOutboundTextIntentSchema = Type.Object({
575
+ export const RelayAuthorizedPlatformOutboundIntentSchema = Type.Object({
340
576
  ...PlatformOutboundIntentFields,
341
577
  conversation_ref: ExternalObjectRefSchema,
342
578
  }, { additionalProperties: false });
579
+ // Compatibility aliases for the original text-only contract name. The schema now
580
+ // carries either text or a structured approval request.
581
+ export const PlatformOutboundTextIntentSchema = PlatformOutboundIntentSchema;
582
+ export const RelayAuthorizedPlatformOutboundTextIntentSchema = RelayAuthorizedPlatformOutboundIntentSchema;
583
+ export const PlatformCardCallbackSchema = Type.Object({
584
+ conversation_ref: ExternalObjectRefSchema,
585
+ message_ref: ExternalObjectRefSchema,
586
+ action_ref: IntegrationOwnedRefSchema,
587
+ card_revision: PlatformApprovalCardRevisionSchema,
588
+ external_subject: ExternalSubjectLocatorSchema,
589
+ }, { additionalProperties: false });
590
+ export const IntegrationApprovalDecisionDeliveryRequestSchema = Type.Object({
591
+ protocol_version: Type.Literal(1),
592
+ command_id: IdempotencyKeySchema,
593
+ relay_project_ref: RelayProjectRefSchema,
594
+ binding_ref: IntegrationOwnedRefSchema,
595
+ receipt: InboundIntegrationEventReceiptSchema,
596
+ callback: PlatformCardCallbackSchema,
597
+ approval_id: Type.String({ minLength: 1, maxLength: 256 }),
598
+ decision_id: Type.String({ minLength: 1, maxLength: 256 }),
599
+ }, { additionalProperties: false });
600
+ export const TrustedApprovalDecisionCommandSchema = Type.Object({
601
+ protocol_version: Type.Literal(1),
602
+ command_id: IdempotencyKeySchema,
603
+ relay_project_ref: RelayProjectRefSchema,
604
+ binding_ref: IntegrationOwnedRefSchema,
605
+ receipt: InboundIntegrationEventReceiptSchema,
606
+ actor: TrustedHumanIntegrationActorContextSchema,
607
+ callback: Type.Object({
608
+ message_ref: ExternalObjectRefSchema,
609
+ action_ref: IntegrationOwnedRefSchema,
610
+ card_revision: PlatformApprovalCardRevisionSchema,
611
+ }, { additionalProperties: false }),
612
+ approval_id: Type.String({ minLength: 1, maxLength: 256 }),
613
+ decision_id: Type.String({ minLength: 1, maxLength: 256 }),
614
+ }, { additionalProperties: false });
615
+ export const IntegrationApprovalDecisionDispositionSchema = Type.Union([
616
+ Type.Object({ kind: Type.Literal("accepted") }, { additionalProperties: false }),
617
+ Type.Object({ kind: Type.Literal("stale_approval") }, { additionalProperties: false }),
618
+ Type.Object({ kind: Type.Literal("decision_unavailable") }, { additionalProperties: false }),
619
+ Type.Object({
620
+ kind: Type.Literal("interrupted"),
621
+ retry_with_new_command_id: Type.Boolean(),
622
+ }, { additionalProperties: false }),
623
+ Type.Object({
624
+ kind: Type.Literal("unauthorized"),
625
+ reason_code: Type.String({ minLength: 1, maxLength: 128 }),
626
+ }, { additionalProperties: false }),
627
+ Type.Object({
628
+ kind: Type.Literal("invalid"),
629
+ reason_code: Type.String({ minLength: 1, maxLength: 128 }),
630
+ }, { additionalProperties: false }),
631
+ Type.Object({
632
+ kind: Type.Literal("host_unavailable"),
633
+ retryable: Type.Literal(true),
634
+ reason_code: Type.String({ minLength: 1, maxLength: 128 }),
635
+ }, { additionalProperties: false }),
636
+ Type.Object({
637
+ kind: Type.Literal("host_incompatible"),
638
+ retryable: Type.Literal(true),
639
+ reason_code: Type.Literal("integration_approval_decision_unsupported"),
640
+ }, { additionalProperties: false }),
641
+ ]);
642
+ export const IntegrationApprovalDecisionDeliveryResponseSchema = Type.Object({
643
+ protocol_version: Type.Literal(1),
644
+ disposition: IntegrationApprovalDecisionDispositionSchema,
645
+ }, { additionalProperties: false });
646
+ export const INTEGRATION_APPROVAL_DECISION_TUNNEL_PATH = "/internal/integration/v1/approval-decisions";
343
647
  export const IntegrationOutboundClaimRequestSchema = Type.Object({
344
648
  protocol_version: Type.Literal(1),
345
649
  installation: PlatformInstallationLocatorSchema,
@@ -358,7 +662,7 @@ export const IntegrationOutboundClaimResponseSchema = Type.Union([
358
662
  kind: Type.Literal("claimed"),
359
663
  claim_ref: IntegrationOwnedRefSchema,
360
664
  claim_expires_at: IsoDateTimeStringSchema,
361
- intent: RelayAuthorizedPlatformOutboundTextIntentSchema,
665
+ intent: RelayAuthorizedPlatformOutboundIntentSchema,
362
666
  }, { additionalProperties: false }),
363
667
  }, { additionalProperties: false }),
364
668
  ]);
@@ -457,6 +761,83 @@ export function isIntegrationConversationSourceDeliveryRequest(value) {
457
761
  sameInstallation(request.receipt.installation, sourceInstallation) &&
458
762
  sameInstallation(request.receipt.installation, sourceSubject.installation));
459
763
  }
764
+ function sameAttachment(left, right) {
765
+ return (left.attachment_ref === right.attachment_ref &&
766
+ left.attachment_kind === right.attachment_kind &&
767
+ left.file_name === right.file_name &&
768
+ left.media_type === right.media_type);
769
+ }
770
+ function validPreIdentityReferenceAttachmentAuthority(value) {
771
+ return (value.receipt.event_kind === "attachment" &&
772
+ value.source.author.external_subject.subject_kind === "human" &&
773
+ sameInstallation(value.receipt.installation, value.source.locator.conversation.installation) &&
774
+ sameInstallation(value.receipt.installation, value.source.author.external_subject.installation));
775
+ }
776
+ export function isIntegrationReferenceAttachmentStageRequest(value) {
777
+ return (Value.Check(IntegrationReferenceAttachmentStageRequestSchema, value) &&
778
+ validPreIdentityReferenceAttachmentAuthority(value) &&
779
+ sameAttachment(value.source.attachment, value.content.attachment) &&
780
+ value.content.attachment.file_name !== undefined);
781
+ }
782
+ export function isIntegrationReferenceAttachmentStageResponse(value) {
783
+ return Value.Check(IntegrationReferenceAttachmentStageResponseSchema, value);
784
+ }
785
+ export function isIntegrationReferenceAttachmentDeliveryRequest(value) {
786
+ return (Value.Check(IntegrationReferenceAttachmentDeliveryRequestSchema, value) &&
787
+ validPreIdentityReferenceAttachmentAuthority(value) &&
788
+ value.source.attachment.file_name === value.staged_upload.file_name &&
789
+ value.source.attachment.media_type === value.staged_upload.media_type);
790
+ }
791
+ function validManagedReferenceSource(value) {
792
+ return (value.source_ref.startsWith("managed_ref_") &&
793
+ value.installation.platform === "feishu" &&
794
+ value.external_subject.subject_kind === "human" &&
795
+ sameInstallation(value.installation, value.external_subject.installation) &&
796
+ value.reference_path.startsWith("docs/reference/") &&
797
+ !value.reference_path.includes("\\") &&
798
+ !value.reference_path
799
+ .split("/")
800
+ .some((segment) => segment.length === 0 || segment === "." || segment === ".."));
801
+ }
802
+ function validManagedReferenceContent(value) {
803
+ return value.size_bytes <= MAX_REFERENCE_STAGED_UPLOAD_BYTES;
804
+ }
805
+ function sameManagedReferenceStageContent(value) {
806
+ return (value.content.size_bytes === value.staged_upload.size_bytes &&
807
+ value.content.sha256 === value.staged_upload.sha256 &&
808
+ value.content.media_type === value.staged_upload.media_type &&
809
+ value.staged_upload.file_name === value.source.reference_path.split("/").at(-1));
810
+ }
811
+ export function isIntegrationManagedReferenceStageRequest(value) {
812
+ return (Value.Check(IntegrationManagedReferenceStageRequestSchema, value) &&
813
+ validManagedReferenceSource(value.source) &&
814
+ validManagedReferenceContent(value.content));
815
+ }
816
+ export function isIntegrationManagedReferenceStageResponse(value) {
817
+ return Value.Check(IntegrationManagedReferenceStageResponseSchema, value);
818
+ }
819
+ export function isIntegrationManagedReferenceDeliveryRequest(value) {
820
+ return (Value.Check(IntegrationManagedReferenceDeliveryRequestSchema, value) &&
821
+ validManagedReferenceSource(value.source) &&
822
+ validManagedReferenceContent(value.content) &&
823
+ sameManagedReferenceStageContent(value));
824
+ }
825
+ export function isTrustedManagedReferenceIngestionCommand(value) {
826
+ if (!Value.Check(TrustedManagedReferenceIngestionCommandSchema, value)) {
827
+ return false;
828
+ }
829
+ return (validManagedReferenceSource(value.source) &&
830
+ validManagedReferenceContent(value.content) &&
831
+ sameManagedReferenceStageContent(value) &&
832
+ value.actor.channel === "platform_document_sync" &&
833
+ value.actor.external_subject.subject_ref === value.source.external_subject.subject_ref &&
834
+ sameInstallation(value.actor.external_subject.installation, value.source.installation) &&
835
+ value.actor.binding_ref === value.binding_ref &&
836
+ value.actor.membership.relay_project_ref === value.relay_project_ref);
837
+ }
838
+ export function isIntegrationManagedReferenceDeliveryResponse(value) {
839
+ return Value.Check(IntegrationManagedReferenceDeliveryResponseSchema, value);
840
+ }
460
841
  export function isIntegrationConversationBindingRequest(value) {
461
842
  if (!Value.Check(IntegrationConversationBindingRequestSchema, value)) {
462
843
  return false;
@@ -484,17 +865,56 @@ export function isTrustedConversationSourceIngestionCommand(value) {
484
865
  sameInstallation(command.receipt.installation, sourceInstallation) &&
485
866
  sameInstallation(command.receipt.installation, sourceAuthor.external_subject.installation));
486
867
  }
868
+ export function isTrustedReferenceAttachmentIngestionCommand(value) {
869
+ if (!Value.Check(TrustedReferenceAttachmentIngestionCommandSchema, value)) {
870
+ return false;
871
+ }
872
+ return (validPreIdentityReferenceAttachmentAuthority(value) &&
873
+ value.actor.channel === "platform_chat" &&
874
+ value.actor.membership.relay_project_ref === value.relay_project_ref &&
875
+ value.actor.binding_ref === value.binding_ref &&
876
+ sameExternalSubject(value.actor.external_subject, value.source.author.external_subject) &&
877
+ value.source.attachment.file_name === value.staged_upload.file_name &&
878
+ value.source.attachment.media_type === value.staged_upload.media_type);
879
+ }
487
880
  export function isIntegrationDeliveryTunnelMetadata(value) {
488
881
  return Value.Check(IntegrationDeliveryTunnelMetadataSchema, value);
489
882
  }
490
883
  export function isIntegrationConversationSourceDeliveryResponse(value) {
491
884
  return Value.Check(IntegrationConversationSourceDeliveryResponseSchema, value);
492
885
  }
886
+ export function isIntegrationApprovalDecisionDeliveryRequest(value) {
887
+ if (!Value.Check(IntegrationApprovalDecisionDeliveryRequestSchema, value)) {
888
+ return false;
889
+ }
890
+ return (value.receipt.event_kind === "card_action" &&
891
+ value.callback.external_subject.subject_kind === "human" &&
892
+ sameInstallation(value.receipt.installation, value.callback.external_subject.installation));
893
+ }
894
+ export function isTrustedApprovalDecisionCommand(value) {
895
+ if (!Value.Check(TrustedApprovalDecisionCommandSchema, value)) {
896
+ return false;
897
+ }
898
+ return (value.receipt.event_kind === "card_action" &&
899
+ value.actor.channel === "platform_card_callback" &&
900
+ value.actor.membership.relay_project_ref === value.relay_project_ref &&
901
+ value.actor.binding_ref === value.binding_ref &&
902
+ sameInstallation(value.receipt.installation, value.actor.external_subject.installation));
903
+ }
904
+ export function isIntegrationApprovalDecisionDeliveryResponse(value) {
905
+ return Value.Check(IntegrationApprovalDecisionDeliveryResponseSchema, value);
906
+ }
493
907
  export function isPlatformOutboundTextIntent(value) {
494
- return Value.Check(PlatformOutboundTextIntentSchema, value);
908
+ return Value.Check(PlatformOutboundIntentSchema, value);
909
+ }
910
+ export function isPlatformOutboundIntent(value) {
911
+ return Value.Check(PlatformOutboundIntentSchema, value);
495
912
  }
496
913
  export function isRelayAuthorizedPlatformOutboundTextIntent(value) {
497
- return Value.Check(RelayAuthorizedPlatformOutboundTextIntentSchema, value);
914
+ return Value.Check(RelayAuthorizedPlatformOutboundIntentSchema, value);
915
+ }
916
+ export function isRelayAuthorizedPlatformOutboundIntent(value) {
917
+ return Value.Check(RelayAuthorizedPlatformOutboundIntentSchema, value);
498
918
  }
499
919
  export function isIntegrationOutboundClaimRequest(value) {
500
920
  return (Value.Check(IntegrationOutboundClaimRequestSchema, value) &&
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xfey/tutti",
3
- "version": "0.1.104",
3
+ "version": "0.1.106",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -2,7 +2,7 @@
2
2
 
3
3
  Built-in Codex context access skill for reading Tutti reference files.
4
4
 
5
- This skill covers reference listing, existing summary metadata, and text file reads. It is selected only by app-server turns whose server-side configuration grants `references:list` and, when file text is needed, `references:read`.
5
+ This skill covers reference listing, existing summary metadata, and text file reads. The same capability reads ordinary repo References and Host-managed external document snapshots; platform synchronization remains outside the model-facing skill. It is selected only by app-server turns whose server-side configuration grants `references:list` and, when file text is needed, `references:read`.
6
6
 
7
7
  The skill remains read-only. It can return summary fields produced elsewhere, but it never creates, refreshes, or writes summaries.
8
8
 
@@ -5,7 +5,7 @@ description: List and read bounded Tutti reference files when the turn has refer
5
5
 
6
6
  # Read References
7
7
 
8
- Use this skill when a Tutti app-server turn needs material from the shared project Reference space. Files may have been uploaded by a project member or created by Tutti in an earlier Run.
8
+ Use this skill when a Tutti app-server turn needs material from the shared project Reference space. References may be ordinary files uploaded by a project member, files created by Tutti in an earlier Run, or Host-managed snapshots of an external document. The Host snapshot is the only readable content authority for this skill; do not call the external platform directly or infer that its remote revision is current.
9
9
 
10
10
  When a Tutti context API runtime hint is present and includes `references:list`, list available references through:
11
11
 
@@ -13,6 +13,8 @@ When a Tutti context API runtime hint is present and includes `references:list`,
13
13
 
14
14
  List items may include a `summary` object with `status`, optional `text`, `generated_at`, `source_blob_oid`, `unavailable_reason`, and `read_paths`. Treat this summary as orientation only. It can be missing, stale, or unavailable, and it does not replace reading a relevant file.
15
15
 
16
+ For a managed snapshot, `stale` means the saved summary belongs to an older local content blob. Read the current file when it matters, even while its replacement summary is still pending. It does not mean this API has checked the external platform for a newer remote revision.
17
+
16
18
  When a listed text file is relevant and the hint includes `references:read`, read it through:
17
19
 
18
20
  `GET {base_url}/references/file?path=...&max_bytes=...`
@@ -21,6 +23,6 @@ Read responses may include the same `summary` object alongside text or unavailab
21
23
 
22
24
  Read only reference files that are relevant to the current task or question. Do not infer file contents from creation events, names, media types, paths, or summaries alone. If a file is unavailable, restricted, binary, too large, or unsupported, use the returned disposition instead of guessing.
23
25
 
24
- This skill is read-only. Do not attempt to create, update, refresh, or write reference summaries from this skill.
26
+ This skill is read-only. Do not attempt to create, synchronize, update, refresh, or write Reference content or summaries from this skill.
25
27
 
26
28
  Never expose the context API token, base URL, raw large responses, host paths, credentials, cookies, provider details, or private reference excerpts beyond what is necessary for the final structured output.