@jpcasabiancai/cayenne 0.5.11 → 0.5.12

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 (2) hide show
  1. package/dist/cli.js +133 -201
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -554,6 +554,7 @@ var init_repositories = __esm({
554
554
  "not_found",
555
555
  "not_installed",
556
556
  "github_not_installed",
557
+ "github_not_connected",
557
558
  "archived",
558
559
  "repository_mismatch",
559
560
  "not_configured",
@@ -660,7 +661,7 @@ var init_skills = __esm({
660
661
 
661
662
  // ../../packages/shared/src/protocol/integrations.ts
662
663
  import { z as z7 } from "zod";
663
- var INTEGRATION_PROVIDERS, AUTH_KINDS, both, PROVIDER_META, IntegrationProviderSchema, AuthKindSchema, ProviderConfigPublic, ConnectStartRequest, ConnectStartResponse, ConnectCompleteRequest, DisconnectRequest, GithubInstallationId, GithubAccountLogin, GithubAccountType, GithubAvatarUrl, GithubInstallation, GithubAvailableInstallation, GithubInstallationList, GithubBindRequest, GithubBindResponse, GithubUnbindRequest, GithubUnbindResponse, MessageResourceKind, ReplyRequest, ReplyResponse, ResourceList, SetSubscriptionsRequest, INBOX_ERROR_CODES, InboxErrorCode, CONVERSATION_KINDS, ConversationKind, MESSAGE_ATTACHMENTS_MAX, MessageAttachment, MessageAttachments, INBOX_CHANNELS, InboxChannel, INBOX_CATEGORIES, InboxCategory, ATTACHMENT_KINDS, AttachmentKind, INTEL_STATUSES, IntelStatus, Probability, IntelNeeds, IntelFlags, InboxIntel, MessageIntel;
664
+ var INTEGRATION_PROVIDERS, AUTH_KINDS, IntegrationProviderSchema, AuthKindSchema, ProviderConfigPublic, ConnectStartRequest, ConnectStartResponse, ConnectCompleteRequest, DisconnectRequest, MessageResourceKind, ReplyRequest, ReplyResponse, ResourceList, SetSubscriptionsRequest, INBOX_ERROR_CODES, InboxErrorCode, CONVERSATION_KINDS, ConversationKind, MESSAGE_ATTACHMENTS_MAX, MessageAttachment, MessageAttachments, INBOX_CHANNELS, InboxChannel, INBOX_CATEGORIES, InboxCategory, ATTACHMENT_KINDS, AttachmentKind, INTEL_STATUSES, IntelStatus, Probability, IntelNeeds, IntelFlags, InboxIntel, MessageIntel;
664
665
  var init_integrations = __esm({
665
666
  "../../packages/shared/src/protocol/integrations.ts"() {
666
667
  "use strict";
@@ -678,91 +679,6 @@ var init_integrations = __esm({
678
679
  "trello"
679
680
  ];
680
681
  AUTH_KINDS = ["native", "composio", "platform"];
681
- both = () => ["native", "composio"];
682
- PROVIDER_META = {
683
- slack: {
684
- label: "Slack",
685
- badge: "SL",
686
- paths: { native: null, composio: null, platform: { stage: 1 } },
687
- capabilities: { messages: ["platform"], tasks: [] },
688
- webhook: { fn: "slack-events", params: [] }
689
- },
690
- clickup: {
691
- label: "ClickUp",
692
- badge: "CU",
693
- // Comments on the personal connection; tasks on the workspace's native connection.
694
- paths: { native: { stage: 1 }, composio: null, platform: { stage: 1 } },
695
- capabilities: { messages: ["platform"], tasks: ["native"] },
696
- webhook: { fn: "clickup-webhook", params: ["ws", "sub"] }
697
- },
698
- gmail: {
699
- label: "Gmail",
700
- badge: "ML",
701
- paths: { native: null, composio: null, platform: { stage: 1 } },
702
- capabilities: { messages: ["platform"], tasks: [] },
703
- webhook: null
704
- },
705
- teams: {
706
- label: "Microsoft Teams",
707
- badge: "MS",
708
- // Withdrawn until a personal path exists (personal inbox §3.8); its adapter stays in the tree.
709
- paths: { native: null, composio: null, platform: null },
710
- capabilities: { messages: [], tasks: [] },
711
- webhook: { fn: "teams-notifications", params: ["ws"] }
712
- },
713
- github: {
714
- label: "GitHub",
715
- badge: "GH",
716
- // The Cayenne GitHub App (D57), a team workspace's platform path; Composio is Stage 3.
717
- paths: { native: null, composio: { stage: 3, toolkit: "github" }, platform: { stage: 1 } },
718
- capabilities: { messages: [], tasks: ["composio", "platform"] },
719
- webhook: { fn: "github-webhook", params: [] }
720
- },
721
- monday: {
722
- label: "Monday.com",
723
- badge: "MO",
724
- // Composio's Monday toolkit has no triggers; not offered.
725
- paths: { native: { stage: 1 }, composio: null, platform: null },
726
- capabilities: { messages: [], tasks: ["native"] },
727
- webhook: { fn: "monday-webhook", params: ["ws", "sub"] }
728
- },
729
- linear: {
730
- label: "Linear",
731
- badge: "LN",
732
- paths: { native: { stage: 3 }, composio: { stage: 1, toolkit: "linear" }, platform: null },
733
- capabilities: { messages: [], tasks: both() },
734
- webhook: { fn: "linear-webhook", params: ["ws", "sub"] }
735
- },
736
- jira: {
737
- label: "Jira",
738
- badge: "JR",
739
- paths: { native: { stage: 3 }, composio: { stage: 1, toolkit: "jira" }, platform: null },
740
- capabilities: { messages: [], tasks: both() },
741
- // Jira signs nothing: `t` is the subscription's token, compared constant-time.
742
- webhook: { fn: "jira-webhook", params: ["ws", "sub", "t"] }
743
- },
744
- asana: {
745
- label: "Asana",
746
- badge: "AS",
747
- paths: { native: { stage: 3 }, composio: { stage: 1, toolkit: "asana" }, platform: null },
748
- capabilities: { messages: [], tasks: both() },
749
- webhook: { fn: "asana-webhook", params: ["ws", "sub"] }
750
- },
751
- notion: {
752
- label: "Notion",
753
- badge: "NO",
754
- paths: { native: { stage: 3 }, composio: { stage: 1, toolkit: "notion" }, platform: null },
755
- capabilities: { messages: [], tasks: both() },
756
- webhook: null
757
- },
758
- trello: {
759
- label: "Trello",
760
- badge: "TR",
761
- paths: { native: { stage: 3 }, composio: { stage: 1, toolkit: "trello" }, platform: null },
762
- capabilities: { messages: [], tasks: both() },
763
- webhook: { fn: "trello-webhook", params: ["ws", "sub"] }
764
- }
765
- };
766
682
  IntegrationProviderSchema = z7.enum(INTEGRATION_PROVIDERS);
767
683
  AuthKindSchema = z7.enum(AUTH_KINDS);
768
684
  ProviderConfigPublic = z7.object({
@@ -778,49 +694,11 @@ var init_integrations = __esm({
778
694
  ConnectStartRequest = z7.strictObject({
779
695
  workspaceId: z7.uuid(),
780
696
  provider: IntegrationProviderSchema,
781
- acknowledged: z7.boolean().optional(),
782
- intent: z7.enum(["connect", "install"]).optional()
783
- }).superRefine((r, ctx) => {
784
- if (r.intent === "install" && r.provider !== "github") {
785
- ctx.addIssue({ code: "custom", path: ["intent"], message: "install is GitHub only" });
786
- }
697
+ acknowledged: z7.boolean().optional()
787
698
  });
788
699
  ConnectStartResponse = z7.object({ url: z7.url({ protocol: /^https$/ }) });
789
700
  ConnectCompleteRequest = z7.strictObject({ pendingId: z7.uuid() });
790
701
  DisconnectRequest = z7.strictObject({ integrationId: z7.uuid() });
791
- GithubInstallationId = z7.number().int().positive();
792
- GithubAccountLogin = z7.string().min(1).max(100);
793
- GithubAccountType = z7.enum(["Organization", "User"]);
794
- GithubAvatarUrl = z7.url({
795
- protocol: /^https$/,
796
- hostname: /^avatars[.]githubusercontent[.]com$/
797
- });
798
- GithubInstallation = z7.object({
799
- id: z7.uuid(),
800
- installationId: GithubInstallationId,
801
- accountLogin: GithubAccountLogin,
802
- accountType: GithubAccountType,
803
- avatarUrl: GithubAvatarUrl,
804
- addedBy: z7.object({ id: z7.uuid(), displayName: z7.string().nullable() }).nullable(),
805
- createdAt: z7.string()
806
- });
807
- GithubAvailableInstallation = z7.object({
808
- installationId: GithubInstallationId,
809
- accountLogin: GithubAccountLogin,
810
- accountType: GithubAccountType,
811
- avatarUrl: GithubAvatarUrl
812
- });
813
- GithubInstallationList = z7.object({
814
- bound: z7.array(GithubInstallation),
815
- available: z7.array(GithubAvailableInstallation)
816
- });
817
- GithubBindRequest = z7.strictObject({
818
- workspaceId: z7.uuid(),
819
- installationId: GithubInstallationId
820
- });
821
- GithubBindResponse = z7.object({ binding: GithubInstallation });
822
- GithubUnbindRequest = z7.strictObject({ workspaceId: z7.uuid(), bindingId: z7.uuid() });
823
- GithubUnbindResponse = z7.object({ orphaned: z7.number().int().nonnegative() });
824
702
  MessageResourceKind = z7.enum(["clickup_team", "teams_channel", "teams_chat"]);
825
703
  ReplyRequest = z7.strictObject({
826
704
  messageId: z7.uuid(),
@@ -962,9 +840,13 @@ var init_tasks = __esm({
962
840
  });
963
841
  TaskDraft = TaskPatch.required({ title: true });
964
842
  ContainerLinkRequest = z8.strictObject({
843
+ workspaceId: z8.uuid(),
965
844
  integrationId: z8.uuid(),
966
- externalId: z8.string().min(1).max(500),
845
+ shareUrl: z8.string().min(1).max(2048).optional(),
846
+ externalId: z8.string().min(1).max(500).optional(),
967
847
  projectId: z8.uuid().optional()
848
+ }).refine((r) => r.shareUrl === void 0 !== (r.externalId === void 0), {
849
+ message: "give exactly one of shareUrl and externalId"
968
850
  });
969
851
  StatusId = z8.string().min(1).max(200);
970
852
  StatusMap = z8.strictObject({
@@ -1470,6 +1352,28 @@ var init_context = __esm({
1470
1352
  kind: z13.literal("claim"),
1471
1353
  id: z13.uuid(),
1472
1354
  collision: z13.enum(["overlap", "sequence"])
1355
+ }),
1356
+ /**
1357
+ * A recall hit on an `items` row (layer `recall`): the item its chunk belongs to, with the item's
1358
+ * `source_ref` when the hit carried one. Ids only: never a title or content.
1359
+ */
1360
+ z13.object({ kind: z13.literal("item"), id: z13.uuid(), source_ref: z13.string().max(200).optional() }),
1361
+ /** A recall hit on a `facts` row (layer `recall`). */
1362
+ z13.object({ kind: z13.literal("fact"), id: z13.uuid() }),
1363
+ /**
1364
+ * How many recall hits the block showed that are not workspace-visible, unknown visibility
1365
+ * included (layer `recall`): never their ids or `source_ref`, since a session that turns
1366
+ * workspace-visible later exposes its ledger with it. Strict: it carries no id.
1367
+ */
1368
+ z13.strictObject({ kind: z13.literal("recall_private"), count: z13.number().int().positive() }),
1369
+ /**
1370
+ * The earlier segment a handoff carried (layer `handoff`): `memory_recall`'s
1371
+ * `chat_segments:<session>:<index>`. Segment `n`'s handoff is written in `n + 1`.
1372
+ */
1373
+ z13.object({
1374
+ kind: z13.literal("segment"),
1375
+ session: z13.uuid(),
1376
+ index: z13.number().int().nonnegative()
1473
1377
  })
1474
1378
  ]);
1475
1379
  CONTEXT_UNAVAILABLE = "CONTEXT_UNAVAILABLE";
@@ -6100,7 +6004,7 @@ var init_credentials = __esm({
6100
6004
  init_introspect();
6101
6005
  READ_ONLY_NOT_CONNECTED = "Cayenne: this repository chat is read-only because you have not connected GitHub. Connect it in Settings \u2192 Integrations, then send your next message here.";
6102
6006
  READ_ONLY_NO_EXPIRY = "Cayenne: this repository chat is read-only on this runner because your GitHub token never expires, and Cayenne lends only expiring tokens to another member's runner. Reconnect GitHub in Settings \u2192 Integrations to get a token that expires, then send your next message here.";
6103
- READ_ONLY_GITHUB_NOT_INSTALLED = "Cayenne: this repository chat is read-only because this repository's GitHub organisation is not connected to this workspace. Add it in Settings \u2192 Integrations, then send your next message here.";
6007
+ READ_ONLY_GITHUB_NOT_INSTALLED = "Cayenne: this repository chat is read-only because your GitHub account cannot reach this repository through the Cayenne GitHub App. Install the app on the repository's organisation from Settings \u2192 Integrations, then send your next message here.";
6104
6008
  READ_ONLY_SCOPE_REFUSED = "Cayenne: this repository chat is read-only because GitHub would not give your token access to this repository; your GitHub account may not have access to it. Send another message here once it does.";
6105
6009
  READ_ONLY_UNAVAILABLE = "Cayenne: this repository chat could not get your GitHub token, so pushing is off for now. Send another message to retry.";
6106
6010
  CREDENTIAL_HELPER = String.raw`!f() { test "$1" = get || exit 0; if [ -n "$GH_TOKEN" ]; then echo username=x-access-token; echo "password=$GH_TOKEN"; else printf '%s\n' "$CAYENNE_READ_ONLY" >&2; exit 1; fi; }; f`;
@@ -10123,9 +10027,13 @@ function cloneRefusal(code, slug) {
10123
10027
  switch (code) {
10124
10028
  case "not_installed":
10125
10029
  return `VALIDATION: ${slug} is not in the Cayenne GitHub App's installation`;
10126
- // D57: the repository's installation is not bound to this workspace, or there is none.
10030
+ // D68: `/clone` mints for the runner owner, whose own GitHub token cannot read the repository or
10031
+ // lists no installation covering it. The member reading this may not be that owner.
10127
10032
  case "github_not_installed":
10128
- return `VALIDATION: ${slug}'s GitHub organisation is not connected to this workspace; add it in Settings \u2192 Integrations`;
10033
+ return `VALIDATION: this runner's owner cannot reach ${slug} through the Cayenne GitHub App; they need access to it on GitHub, and the app installed on its organisation from Settings \u2192 Integrations`;
10034
+ // D68: the runner owner has no active GitHub connection of their own, or GitHub refused it.
10035
+ case "github_not_connected":
10036
+ return `VALIDATION: this runner cannot get ${slug} because its owner has not connected GitHub, or their connection expired; they can connect it in Settings \u2192 Integrations`;
10129
10037
  case "repository_mismatch":
10130
10038
  return `VALIDATION: ${slug} was renamed or replaced on GitHub; pick it again`;
10131
10039
  case "bad_default_branch":
@@ -10145,7 +10053,7 @@ var init_token_client = __esm({
10145
10053
  "use strict";
10146
10054
  init_src();
10147
10055
  TOKEN_SHAPE = /^[A-Za-z0-9_]{20,255}$/;
10148
- DEFAULT_TIMEOUT_MS = 45e3;
10056
+ DEFAULT_TIMEOUT_MS = 9e4;
10149
10057
  }
10150
10058
  });
10151
10059
 
@@ -11249,6 +11157,65 @@ var init_budget = __esm({
11249
11157
  }
11250
11158
  });
11251
11159
 
11160
+ // src/context/ledger.ts
11161
+ function capRefs(refs, max = MAX_REFS) {
11162
+ const counts = refs.filter((r) => COUNT_KINDS.has(r.kind)).slice(0, max);
11163
+ const ids = refs.filter((r) => !COUNT_KINDS.has(r.kind)).slice(0, max - counts.length);
11164
+ return [...ids, ...counts];
11165
+ }
11166
+ async function writeLedger(insert, at, rows, log) {
11167
+ const valid = [];
11168
+ for (const row of rows) {
11169
+ const parsed = ContextLedgerRow.safeParse({
11170
+ workspace_id: at.workspaceId,
11171
+ session_id: at.sessionId,
11172
+ segment: at.segment,
11173
+ turn_seq: row.turn_seq ?? null,
11174
+ layer: row.layer,
11175
+ refs: capRefs(row.refs),
11176
+ tokens: row.tokens
11177
+ });
11178
+ if (parsed.success) valid.push(parsed.data);
11179
+ else log?.warn({ sessionId: at.sessionId, layer: row.layer }, "context ledger row refused");
11180
+ }
11181
+ if (valid.length === 0) return true;
11182
+ try {
11183
+ const { error } = await insert(valid);
11184
+ if (!error) return true;
11185
+ log?.warn({ sessionId: at.sessionId, err: error.message }, "context ledger write failed");
11186
+ } catch (err) {
11187
+ log?.warn(
11188
+ { sessionId: at.sessionId, err: err instanceof Error ? err.message : String(err) },
11189
+ "context ledger write failed"
11190
+ );
11191
+ }
11192
+ return false;
11193
+ }
11194
+ var ledgerInsert, MAX_REFS, COUNT_KINDS;
11195
+ var init_ledger = __esm({
11196
+ "src/context/ledger.ts"() {
11197
+ "use strict";
11198
+ init_src();
11199
+ ledgerInsert = (db) => (rows) => db.from("context_ledger").insert(
11200
+ rows.map((r) => ({
11201
+ workspace_id: r.workspace_id,
11202
+ session_id: r.session_id,
11203
+ segment: r.segment,
11204
+ turn_seq: r.turn_seq ?? null,
11205
+ layer: r.layer,
11206
+ refs: r.refs,
11207
+ tokens: r.tokens
11208
+ }))
11209
+ );
11210
+ MAX_REFS = 50;
11211
+ COUNT_KINDS = /* @__PURE__ */ new Set([
11212
+ "activity_private",
11213
+ "person_private",
11214
+ "recall_private"
11215
+ ]);
11216
+ }
11217
+ });
11218
+
11252
11219
  // src/context/recall.ts
11253
11220
  function parseHit(v) {
11254
11221
  if (!isObj2(v)) return null;
@@ -11316,8 +11283,8 @@ function hitLine(hit2, contentChars) {
11316
11283
  const title = text2(hit2.provenance.title);
11317
11284
  return `- ${word(hit2.kind)}${title ? ` ${quoted(title, 160)}` : ""}${meta ? ` (${meta})` : ""}: ${quoted(hit2.content, contentChars)}`;
11318
11285
  }
11319
- function recallBlock(hits, max = RECALL_MAX_TOKENS) {
11320
- if (hits.length === 0) return "";
11286
+ function recallFit(hits, max) {
11287
+ if (hits.length === 0) return { text: "", shown: [] };
11321
11288
  const frame = `${RECALL_PREAMBLE}
11322
11289
  ${RECALL_OPEN}
11323
11290
 
@@ -11326,10 +11293,28 @@ ${RECALL_CLOSE}`;
11326
11293
  hits.map((h) => ({ text: hitLine(h, RECALL_HIT_CHARS) })),
11327
11294
  max - estimateTokens(frame)
11328
11295
  );
11329
- return fit.text ? `${RECALL_PREAMBLE}
11296
+ if (!fit.text) return { text: "", shown: [] };
11297
+ return {
11298
+ text: `${RECALL_PREAMBLE}
11330
11299
  ${RECALL_OPEN}
11331
11300
  ${fit.text}
11332
- ${RECALL_CLOSE}` : "";
11301
+ ${RECALL_CLOSE}`,
11302
+ shown: hits.slice(0, fit.shown.length)
11303
+ };
11304
+ }
11305
+ function hitLedgerRef(hit2) {
11306
+ if (hit2.kind === "fact") return UUID4.test(hit2.id) ? { kind: "fact", id: hit2.id } : null;
11307
+ if (hit2.item_id === null || !UUID4.test(hit2.item_id)) return null;
11308
+ const sourceRef = text2(hit2.provenance.source_ref);
11309
+ return sourceRef !== null && sourceRef.length <= 200 ? { kind: "item", id: hit2.item_id, source_ref: sourceRef } : { kind: "item", id: hit2.item_id };
11310
+ }
11311
+ function recallLedgerRefs(shown) {
11312
+ const named = shown.filter((h) => h.provenance.visibility === "workspace");
11313
+ const hidden = shown.length - named.length;
11314
+ return capRefs([
11315
+ ...named.flatMap((h) => hitLedgerRef(h) ?? []),
11316
+ ...hidden > 0 ? [{ kind: "recall_private", count: hidden }] : []
11317
+ ]);
11333
11318
  }
11334
11319
  function recallQuery(prompt) {
11335
11320
  let rest = prompt.trim();
@@ -11354,11 +11339,12 @@ async function firstPromptRecall(deps, at) {
11354
11339
  const found = await searchMemory(deps.db, { sessionId: at.sessionId, query, scope }, at.signal);
11355
11340
  if (at.signal.aborted || !found.ok) return null;
11356
11341
  const hits = shownHits(found.hits, scope);
11357
- const block = recallBlock(hits);
11342
+ const { text: block, shown } = recallFit(hits, RECALL_MAX_TOKENS);
11358
11343
  if (!block) return null;
11344
+ const refs = recallLedgerRefs(shown);
11359
11345
  return {
11360
11346
  text: block,
11361
- ledger: { layer: "recall", refs: [], tokens: estimateTokens(block), turn_seq: at.turnSeq },
11347
+ ledger: { layer: "recall", refs, tokens: estimateTokens(block), turn_seq: at.turnSeq },
11362
11348
  privateSeen: scope === "all" && holdsPrivate(hits)
11363
11349
  };
11364
11350
  } catch {
@@ -11440,6 +11426,7 @@ var init_recall = __esm({
11440
11426
  init_rotation();
11441
11427
  init_budget();
11442
11428
  init_format();
11429
+ init_ledger();
11443
11430
  RECALL_MAX_TOKENS = 3e3;
11444
11431
  MAX_QUERY_CHARS = 4e3;
11445
11432
  MEMORY_KINDS = [
@@ -13095,64 +13082,6 @@ ${card.data}` : card.instructions;
13095
13082
  }
13096
13083
  });
13097
13084
 
13098
- // src/context/ledger.ts
13099
- function capRefs(refs, max = MAX_REFS) {
13100
- const counts = refs.filter((r) => COUNT_KINDS.has(r.kind)).slice(0, max);
13101
- const ids = refs.filter((r) => !COUNT_KINDS.has(r.kind)).slice(0, max - counts.length);
13102
- return [...ids, ...counts];
13103
- }
13104
- async function writeLedger(insert, at, rows, log) {
13105
- const valid = [];
13106
- for (const row of rows) {
13107
- const parsed = ContextLedgerRow.safeParse({
13108
- workspace_id: at.workspaceId,
13109
- session_id: at.sessionId,
13110
- segment: at.segment,
13111
- turn_seq: row.turn_seq ?? null,
13112
- layer: row.layer,
13113
- refs: capRefs(row.refs),
13114
- tokens: row.tokens
13115
- });
13116
- if (parsed.success) valid.push(parsed.data);
13117
- else log?.warn({ sessionId: at.sessionId, layer: row.layer }, "context ledger row refused");
13118
- }
13119
- if (valid.length === 0) return true;
13120
- try {
13121
- const { error } = await insert(valid);
13122
- if (!error) return true;
13123
- log?.warn({ sessionId: at.sessionId, err: error.message }, "context ledger write failed");
13124
- } catch (err) {
13125
- log?.warn(
13126
- { sessionId: at.sessionId, err: err instanceof Error ? err.message : String(err) },
13127
- "context ledger write failed"
13128
- );
13129
- }
13130
- return false;
13131
- }
13132
- var ledgerInsert, MAX_REFS, COUNT_KINDS;
13133
- var init_ledger = __esm({
13134
- "src/context/ledger.ts"() {
13135
- "use strict";
13136
- init_src();
13137
- ledgerInsert = (db) => (rows) => db.from("context_ledger").insert(
13138
- rows.map((r) => ({
13139
- workspace_id: r.workspace_id,
13140
- session_id: r.session_id,
13141
- segment: r.segment,
13142
- turn_seq: r.turn_seq ?? null,
13143
- layer: r.layer,
13144
- refs: r.refs,
13145
- tokens: r.tokens
13146
- }))
13147
- );
13148
- MAX_REFS = 50;
13149
- COUNT_KINDS = /* @__PURE__ */ new Set([
13150
- "activity_private",
13151
- "person_private"
13152
- ]);
13153
- }
13154
- });
13155
-
13156
13085
  // src/coordination/collision.ts
13157
13086
  function detectCollision(path, scope) {
13158
13087
  const hits = scope.index.collisionsFor(scope.repo, path, scope.writer);
@@ -19121,12 +19050,15 @@ var init_manager = __esm({
19121
19050
  ]);
19122
19051
  }
19123
19052
  /**
19124
- * A `<handoff segment="n">` block handed to segment `n + 1` as its `handoff` row (design §5.7 L2).
19125
- * No ref names the segment yet: `ContextLedgerRef` has no kind for it (protocol §2.10).
19053
+ * A `<handoff segment="n">` block handed to segment `n + 1` as its `handoff` row (design §5.7 L2),
19054
+ * naming segment `n` (`memory_recall`'s `chat_segments:<session>:<n>`, protocol §2.10).
19126
19055
  */
19127
19056
  ledgerHandoff(sessionId, live, block, seq) {
19057
+ const refs = [
19058
+ { kind: "segment", session: sessionId, index: block.segment }
19059
+ ];
19128
19060
  this.writeLedgerRows(sessionId, live.renewal.segment, [
19129
- { layer: "handoff", refs: [], tokens: estimateTokens(block), turn_seq: seq }
19061
+ { layer: "handoff", refs, tokens: estimateTokens(block.text), turn_seq: seq }
19130
19062
  ]);
19131
19063
  }
19132
19064
  /**
@@ -19870,14 +19802,14 @@ var init_manager = __esm({
19870
19802
  if (send === "now") {
19871
19803
  const queued = first !== null && rn.queued[0] === first ? rn.queued.shift() : void 0;
19872
19804
  if (queued && !await this.writeQueued(sessionId, live, queued)) {
19873
- rn.pendingBlock = handoffBlock(n, handoffText);
19805
+ rn.pendingBlock = { text: handoffBlock(n, handoffText), segment: n };
19874
19806
  } else {
19875
19807
  const uuid = queued?.uuid ?? randomUUID5();
19876
19808
  live.echoed.add(uuid);
19877
19809
  this.ledgerHandoff(
19878
19810
  sessionId,
19879
19811
  live,
19880
- handoffBlock(n, handoffText),
19812
+ { text: handoffBlock(n, handoffText), segment: n },
19881
19813
  live.promptSeqs.get(uuid) ?? null
19882
19814
  );
19883
19815
  live.handed.push({ text: text3, seq: live.promptSeqs.get(uuid) ?? null });
@@ -19887,7 +19819,7 @@ var init_manager = __esm({
19887
19819
  this.turnHandedOver(live);
19888
19820
  }
19889
19821
  } else {
19890
- rn.pendingBlock = handoffBlock(n, handoffText);
19822
+ rn.pendingBlock = { text: handoffBlock(n, handoffText), segment: n };
19891
19823
  }
19892
19824
  await this.flushQueued(sessionId, live);
19893
19825
  }
@@ -19965,7 +19897,7 @@ ${text3}`;
19965
19897
  const block = rn.pendingBlock;
19966
19898
  if (block !== null && !isSlashCommand(text3)) {
19967
19899
  rn.pendingBlock = null;
19968
- text3 = `${block}
19900
+ text3 = `${block.text}
19969
19901
 
19970
19902
  ${text3}`;
19971
19903
  this.ledgerHandoff(sessionId, live, block, live.promptSeqs.get(uuid) ?? null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jpcasabiancai/cayenne",
3
- "version": "0.5.11",
3
+ "version": "0.5.12",
4
4
  "files": [
5
5
  "dist/cli.js"
6
6
  ],