@jpcasabiancai/cayenne 0.5.11 → 0.5.13
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/dist/cli.js +164 -213
- 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,
|
|
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
|
-
|
|
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
|
|
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
|
-
//
|
|
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}
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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 = [
|
|
@@ -12376,7 +12363,7 @@ function asInterrupted(row) {
|
|
|
12376
12363
|
)
|
|
12377
12364
|
};
|
|
12378
12365
|
}
|
|
12379
|
-
var SESSION_FLAG_SETTINGS, SESSION_ASK_TOOLS, GUARD_FAILED, WRITE_TOOLS_MATCHER, CONTEXT_HOOK_TIMEOUT_MS, ASK_TOOL_REASON, CAYENNE_CHECK_MS, CAYENNE_CHECK_POLL_MS, CAYENNE_UNCONFIRMED, TOOL_FAILED, toResult, INTERRUPTED, STOPPED_TURN, ClaudeSession;
|
|
12366
|
+
var SESSION_FLAG_SETTINGS, SESSION_ASK_TOOLS, GUARD_FAILED, WRITE_TOOLS_MATCHER, CONTEXT_HOOK_TIMEOUT_MS, ASK_TOOL_REASON, CAYENNE_CHECK_MS, CAYENNE_CHECK_POLL_MS, CAYENNE_UNLISTED_POLL_MS, CAYENNE_UNCONFIRMED, TOOL_FAILED, toResult, INTERRUPTED, STOPPED_TURN, ClaudeSession;
|
|
12380
12367
|
var init_session2 = __esm({
|
|
12381
12368
|
"src/claude/session.ts"() {
|
|
12382
12369
|
"use strict";
|
|
@@ -12399,6 +12386,7 @@ var init_session2 = __esm({
|
|
|
12399
12386
|
ASK_TOOL_REASON = "This session was started from a task, so every shell command needs the member's approval.";
|
|
12400
12387
|
CAYENNE_CHECK_MS = 1e4;
|
|
12401
12388
|
CAYENNE_CHECK_POLL_MS = 100;
|
|
12389
|
+
CAYENNE_UNLISTED_POLL_MS = 1e3;
|
|
12402
12390
|
CAYENNE_UNCONFIRMED = "Refused: the cayenne MCP server is not confirmed as the runner\u2019s own.";
|
|
12403
12391
|
TOOL_FAILED = "Cayenne could not answer this call.";
|
|
12404
12392
|
toResult = (a) => ({
|
|
@@ -12678,15 +12666,21 @@ var init_session2 = __esm({
|
|
|
12678
12666
|
*
|
|
12679
12667
|
* Any other answer stops the session. A `cayenne` with another `serverInfo` or config type is a
|
|
12680
12668
|
* foreign server (`CAYENNE_NAME_TAKEN`); one never confirmed (connected without `serverInfo`, a
|
|
12681
|
-
* status other than `pending`, still pending
|
|
12682
|
-
*
|
|
12683
|
-
*
|
|
12669
|
+
* status other than `pending`, still pending at the deadline, a status call that fails) ends with
|
|
12670
|
+
* `CAYENNE_UNCONFIRMED_EXIT`, the reason logged at warn. Until confirmed, `canUseTool` refuses
|
|
12671
|
+
* every `cayenne` tool. A session already stopping or ended is left alone.
|
|
12672
|
+
*
|
|
12673
|
+
* An unlisted `cayenne` is waited for, not stopped: the CLI answers `[]` before it registers its
|
|
12674
|
+
* MCP servers, and on a slow network that took longer than the window (three chats killed
|
|
12675
|
+
* 2026-10-21/22). Nothing answers under the name meanwhile, so no tool of it can be called.
|
|
12684
12676
|
*/
|
|
12685
12677
|
async confirmCayenne(q) {
|
|
12686
12678
|
let deadline;
|
|
12679
|
+
let unlistedSince;
|
|
12680
|
+
let unlistedWarned = false;
|
|
12681
|
+
const warn = this.opts.log?.warn ?? ((obj, m) => logger.warn(obj, m));
|
|
12687
12682
|
const end = (fatal, fields, msg) => {
|
|
12688
12683
|
if (this.ending) return false;
|
|
12689
|
-
const warn = this.opts.log?.warn ?? ((obj, m) => logger.warn(obj, m));
|
|
12690
12684
|
warn({ providerSessionId: this.providerSessionId, ...fields }, msg);
|
|
12691
12685
|
this.fatal = fatal;
|
|
12692
12686
|
void this.stop();
|
|
@@ -12701,21 +12695,33 @@ var init_session2 = __esm({
|
|
|
12701
12695
|
for (; ; ) {
|
|
12702
12696
|
if (this.ending) return false;
|
|
12703
12697
|
const statuses = await q.mcpServerStatus();
|
|
12704
|
-
deadline ??= Date.now() + CAYENNE_CHECK_MS;
|
|
12705
12698
|
const entry = statuses.find((s) => s.name === CAYENNE_SERVER);
|
|
12706
|
-
|
|
12707
|
-
|
|
12699
|
+
if (!entry) {
|
|
12700
|
+
unlistedSince ??= Date.now();
|
|
12701
|
+
if (!unlistedWarned && Date.now() - unlistedSince >= CAYENNE_CHECK_MS) {
|
|
12702
|
+
unlistedWarned = true;
|
|
12703
|
+
warn(
|
|
12704
|
+
{ providerSessionId: this.providerSessionId },
|
|
12705
|
+
"cayenne MCP server not listed yet; its tools stay refused until it is"
|
|
12706
|
+
);
|
|
12707
|
+
}
|
|
12708
|
+
await new Promise((r) => setTimeout(r, CAYENNE_UNLISTED_POLL_MS));
|
|
12709
|
+
continue;
|
|
12710
|
+
}
|
|
12711
|
+
deadline ??= Date.now() + CAYENNE_CHECK_MS;
|
|
12712
|
+
const config2 = entry.config;
|
|
12713
|
+
const info = entry.serverInfo;
|
|
12708
12714
|
if (config2 !== void 0 && config2.type !== "sdk" || info !== void 0 && (info.name !== CAYENNE_SERVER || info.version !== this.cayenneVersion)) {
|
|
12709
|
-
return end(CAYENNE_NAME_TAKEN, { scope: entry
|
|
12715
|
+
return end(CAYENNE_NAME_TAKEN, { scope: entry.scope }, CAYENNE_NAME_TAKEN);
|
|
12710
12716
|
}
|
|
12711
|
-
if (entry
|
|
12717
|
+
if (entry.status === "connected") {
|
|
12712
12718
|
return info !== void 0 || unconfirmed("connected without serverInfo", entry.scope);
|
|
12713
12719
|
}
|
|
12714
|
-
if (entry
|
|
12720
|
+
if (entry.status !== "pending") {
|
|
12715
12721
|
return unconfirmed(`status ${entry.status}`, entry.scope);
|
|
12716
12722
|
}
|
|
12717
12723
|
if (Date.now() >= deadline) {
|
|
12718
|
-
return unconfirmed(
|
|
12724
|
+
return unconfirmed("still pending", entry.scope);
|
|
12719
12725
|
}
|
|
12720
12726
|
await new Promise((r) => setTimeout(r, CAYENNE_CHECK_POLL_MS));
|
|
12721
12727
|
}
|
|
@@ -13095,64 +13101,6 @@ ${card.data}` : card.instructions;
|
|
|
13095
13101
|
}
|
|
13096
13102
|
});
|
|
13097
13103
|
|
|
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
13104
|
// src/coordination/collision.ts
|
|
13157
13105
|
function detectCollision(path, scope) {
|
|
13158
13106
|
const hits = scope.index.collisionsFor(scope.repo, path, scope.writer);
|
|
@@ -19121,12 +19069,15 @@ var init_manager = __esm({
|
|
|
19121
19069
|
]);
|
|
19122
19070
|
}
|
|
19123
19071
|
/**
|
|
19124
|
-
* A `<handoff segment="n">` block handed to segment `n + 1` as its `handoff` row (design §5.7 L2)
|
|
19125
|
-
*
|
|
19072
|
+
* A `<handoff segment="n">` block handed to segment `n + 1` as its `handoff` row (design §5.7 L2),
|
|
19073
|
+
* naming segment `n` (`memory_recall`'s `chat_segments:<session>:<n>`, protocol §2.10).
|
|
19126
19074
|
*/
|
|
19127
19075
|
ledgerHandoff(sessionId, live, block, seq) {
|
|
19076
|
+
const refs = [
|
|
19077
|
+
{ kind: "segment", session: sessionId, index: block.segment }
|
|
19078
|
+
];
|
|
19128
19079
|
this.writeLedgerRows(sessionId, live.renewal.segment, [
|
|
19129
|
-
{ layer: "handoff", refs
|
|
19080
|
+
{ layer: "handoff", refs, tokens: estimateTokens(block.text), turn_seq: seq }
|
|
19130
19081
|
]);
|
|
19131
19082
|
}
|
|
19132
19083
|
/**
|
|
@@ -19870,14 +19821,14 @@ var init_manager = __esm({
|
|
|
19870
19821
|
if (send === "now") {
|
|
19871
19822
|
const queued = first !== null && rn.queued[0] === first ? rn.queued.shift() : void 0;
|
|
19872
19823
|
if (queued && !await this.writeQueued(sessionId, live, queued)) {
|
|
19873
|
-
rn.pendingBlock = handoffBlock(n, handoffText);
|
|
19824
|
+
rn.pendingBlock = { text: handoffBlock(n, handoffText), segment: n };
|
|
19874
19825
|
} else {
|
|
19875
19826
|
const uuid = queued?.uuid ?? randomUUID5();
|
|
19876
19827
|
live.echoed.add(uuid);
|
|
19877
19828
|
this.ledgerHandoff(
|
|
19878
19829
|
sessionId,
|
|
19879
19830
|
live,
|
|
19880
|
-
handoffBlock(n, handoffText),
|
|
19831
|
+
{ text: handoffBlock(n, handoffText), segment: n },
|
|
19881
19832
|
live.promptSeqs.get(uuid) ?? null
|
|
19882
19833
|
);
|
|
19883
19834
|
live.handed.push({ text: text3, seq: live.promptSeqs.get(uuid) ?? null });
|
|
@@ -19887,7 +19838,7 @@ var init_manager = __esm({
|
|
|
19887
19838
|
this.turnHandedOver(live);
|
|
19888
19839
|
}
|
|
19889
19840
|
} else {
|
|
19890
|
-
rn.pendingBlock = handoffBlock(n, handoffText);
|
|
19841
|
+
rn.pendingBlock = { text: handoffBlock(n, handoffText), segment: n };
|
|
19891
19842
|
}
|
|
19892
19843
|
await this.flushQueued(sessionId, live);
|
|
19893
19844
|
}
|
|
@@ -19965,7 +19916,7 @@ ${text3}`;
|
|
|
19965
19916
|
const block = rn.pendingBlock;
|
|
19966
19917
|
if (block !== null && !isSlashCommand(text3)) {
|
|
19967
19918
|
rn.pendingBlock = null;
|
|
19968
|
-
text3 = `${block}
|
|
19919
|
+
text3 = `${block.text}
|
|
19969
19920
|
|
|
19970
19921
|
${text3}`;
|
|
19971
19922
|
this.ledgerHandoff(sessionId, live, block, live.promptSeqs.get(uuid) ?? null);
|