@circuitwall/jarela 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +4 -4
- package/.next/standalone/.next/build-manifest.json +2 -2
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +2 -2
- package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/v1/access/[identity]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/access/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/display-filters/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/thread/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/agents/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/allowed-sites/[hostname]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/allowed-sites/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/artifacts/lifecycle/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/[remote_jid]/route.js +18 -7
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/route.js +18 -7
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js +27 -33
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/[route_id]/route.js +28 -12
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/route.js +28 -12
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js +9 -2
- package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/bridges/route.js +19 -7
- package/.next/standalone/.next/server/app/api/v1/bridges/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/dashboard/metrics/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/dashboard/pricing/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/documents/search/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/documents/settings/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/env-sync/allowlist/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/env-sync/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/events/route.js +26 -32
- package/.next/standalone/.next/server/app/api/v1/events/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/extension/browser/activate/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/foreground/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/history/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/poll/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/progress/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/result/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/retry/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/extension/browser/tabs/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/harnesses/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/harnesses/default/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/harnesses/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/health/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/integrations/[name]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/callback/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/start/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/callback/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/start/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/integrations/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/maps/embed/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/mcp-servers/[name]/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/mcp-servers/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/memory/[namespace]/[key]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/memory/policy/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/memory/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/memory/search/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/models/[name]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/models/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js +27 -12
- package/.next/standalone/.next/server/app/api/v1/profile/location/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/profile/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/providers/[provider]/models/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/providers/[provider]/probe/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/providers/github-copilot/auth/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/providers/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/proxy-config/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/redaction/init/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/redaction/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/idle-timeout/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/pin/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/state/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/unlock/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/security/verify-pin/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/repos/[id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/repos/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/skills/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/tasks/[agent_id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/tasks/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js +12 -6
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js +7 -0
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js +0 -1
- package/.next/standalone/.next/server/app/api/v1/threads/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/update/apply/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/v1/voice/transcribe/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/voice/tts/route.js +17 -5
- package/.next/standalone/.next/server/app/api/v1/watchers/[id]/route.js +17 -5
- package/.next/standalone/.next/server/app/page.js +322 -275
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/setup/page.js +8 -0
- package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +4 -4
- package/.next/standalone/.next/server/chunks/1388.js +106 -36
- package/.next/standalone/.next/server/chunks/2068.js +47 -10
- package/.next/standalone/.next/server/chunks/210.js +6 -6
- package/.next/standalone/.next/server/chunks/2447.js +10 -5
- package/.next/standalone/.next/server/chunks/2471.js +17 -17
- package/.next/standalone/.next/server/chunks/3042.js +10 -8
- package/.next/standalone/.next/server/chunks/{4540.js → 309.js} +104 -38
- package/.next/standalone/.next/server/chunks/{2350.js → 3272.js} +104 -37
- package/.next/standalone/.next/server/chunks/3399.js +525 -525
- package/.next/standalone/.next/server/chunks/3524.js +150 -67
- package/.next/standalone/.next/server/chunks/4189.js +1 -1
- package/.next/standalone/.next/server/chunks/4508.js +2 -2
- package/.next/standalone/.next/server/chunks/46.js +73 -28
- package/.next/standalone/.next/server/chunks/5908.js +63 -42
- package/.next/standalone/.next/server/chunks/6142.js +10 -2
- package/.next/standalone/.next/server/chunks/6649.js +1 -1
- package/.next/standalone/.next/server/chunks/8461.js +10 -8
- package/.next/standalone/.next/server/chunks/9032.js +5 -5
- package/.next/standalone/.next/server/chunks/9164.js +435 -176
- package/.next/standalone/.next/server/chunks/9304.js +51 -12
- package/.next/standalone/.next/server/chunks/{423.js → 9590.js} +66 -21
- package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
- package/.next/standalone/.next/server/middleware.js +71 -18
- package/.next/standalone/.next/server/pages/404.html +2 -2
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/preview-props.json +3 -3
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/app/{page-213a623b37226452.js → page-04748847c6ff866f.js} +171 -132
- package/.next/standalone/.next/static/css/{312542a5725ba0d5.css → 2669e8744cc8c212.css} +2 -2
- package/.next/standalone/docs/adoption/changesets.json +49 -0
- package/.next/standalone/package.json +1 -1
- package/CHANGELOG.md +19 -0
- package/app/api/v1/threads/[thread_id]/run/route.ts +0 -1
- package/components/chat/MessageBubble.tsx +12 -0
- package/components/integrations/NetworkSection.tsx +2 -2
- package/lib/agents/citation-checker.test.ts +40 -2
- package/lib/agents/citation-checker.ts +56 -11
- package/lib/agents/context-boundary.ts +5 -6
- package/lib/agents/instruction-edits.test.ts +120 -0
- package/lib/agents/instruction-edits.ts +65 -42
- package/lib/agents/prepare/request.ts +0 -2
- package/lib/agents/prepare/system-prompt.test.ts +10 -0
- package/lib/agents/prepare/system-prompt.ts +8 -2
- package/lib/agents/proposals.test.ts +76 -0
- package/lib/agents/proposals.ts +13 -5
- package/lib/agents/run-thread.auto-boundary.test.ts +125 -5
- package/lib/agents/run-thread.ts +24 -9
- package/lib/agents/sqlite-checkpoint-saver.test.ts +91 -0
- package/lib/agents/warm-summary-background.ts +22 -2
- package/lib/agents/warm-topics.test.ts +155 -1
- package/lib/agents/warm-topics.ts +27 -7
- package/lib/bridges/dispatcher.ts +1 -0
- package/lib/bridges/message-role.test.ts +81 -0
- package/lib/bridges/message-role.ts +23 -10
- package/lib/bridges/types.ts +6 -0
- package/lib/bridges/whatsapp-link.test.ts +32 -0
- package/lib/bridges/whatsapp-link.ts +21 -0
- package/lib/bridges/whatsapp.inbound.test.ts +239 -0
- package/lib/bridges/whatsapp.sender.test.ts +80 -1
- package/lib/bridges/whatsapp.ts +76 -38
- package/lib/pricing/snapshot.test.ts +70 -0
- package/lib/pricing/snapshot.ts +10 -2
- package/lib/proxy/dispatcher.test.ts +119 -1
- package/lib/proxy/dispatcher.ts +22 -9
- package/lib/stores/agent-configs.ts +10 -5
- package/lib/stores/bridges.test.ts +81 -0
- package/lib/stores/bridges.ts +9 -8
- package/lib/stores/proxy-config.test.ts +120 -0
- package/lib/stores/proxy-config.ts +22 -4
- package/lib/stores/threads.ts +12 -8
- package/lib/tools/communications/calendar.test.ts +43 -2
- package/lib/tools/communications/calendar.ts +2 -0
- package/lib/tools/communications/gmail.test.ts +51 -1
- package/lib/tools/communications/gmail.ts +44 -2
- package/lib/tools/communications/outlook-calendar.ts +2 -0
- package/lib/tools/communications/outlook.test.ts +33 -2
- package/lib/tools/communications/outlook.ts +2 -0
- package/lib/tools/filesystem/edit-match.test.ts +133 -0
- package/lib/tools/filesystem/edit-match.ts +7 -2
- package/lib/tools/support/result-refs.test.ts +131 -0
- package/lib/tools/support/result-refs.ts +41 -9
- package/lib/utils/source-link.test.ts +51 -0
- package/lib/utils/source-link.ts +45 -0
- package/package.json +1 -1
- /package/.next/standalone/.next/static/{bMRK5y3ruT7c3WtBfCQOG → hwujW4hR1b-r3k5WdMxZO}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{bMRK5y3ruT7c3WtBfCQOG → hwujW4hR1b-r3k5WdMxZO}/_ssgManifest.js +0 -0
|
@@ -677,10 +677,11 @@ function isIntegrationProbe(name) {
|
|
|
677
677
|
/* harmony export */ VJ: () => (/* binding */ _resolveOutlookAuth)
|
|
678
678
|
/* harmony export */ });
|
|
679
679
|
/* unused harmony exports outlookSearchTool, outlookGetMessageTool, outlookListFoldersTool, outlookModifyMessageTool, outlookCreateDraftTool, outlookTrashMessageTool, outlookSendEmailTool */
|
|
680
|
-
/* harmony import */ var _langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
|
|
681
|
-
/* harmony import */ var
|
|
682
|
-
/* harmony import */ var
|
|
683
|
-
/* harmony import */ var
|
|
680
|
+
/* harmony import */ var _langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(71966);
|
|
681
|
+
/* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17033);
|
|
682
|
+
/* harmony import */ var _lib_utils_html__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(85212);
|
|
683
|
+
/* harmony import */ var _lib_utils_text__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(69494);
|
|
684
|
+
/* harmony import */ var _lib_utils_source_link__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(76385);
|
|
684
685
|
/* harmony import */ var _packages_langchain_package__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(18932);
|
|
685
686
|
/* harmony import */ var _lib_integrations_microsoft_oauth__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(46291);
|
|
686
687
|
/**
|
|
@@ -700,6 +701,7 @@ function isIntegrationProbe(name) {
|
|
|
700
701
|
|
|
701
702
|
|
|
702
703
|
|
|
704
|
+
|
|
703
705
|
// Exposed for the integrations test endpoint.
|
|
704
706
|
function _resolveOutlookAuth() {
|
|
705
707
|
return (0,_lib_integrations_microsoft_oauth__WEBPACK_IMPORTED_MODULE_2__/* .resolveMicrosoftAuth */ .jG)();
|
|
@@ -725,7 +727,8 @@ function summarizeMessage(m) {
|
|
|
725
727
|
categories: m.categories ?? [],
|
|
726
728
|
folder_id: m.parentFolderId ?? null,
|
|
727
729
|
snippet: m.bodyPreview ?? null,
|
|
728
|
-
web_link: m.webLink ?? null
|
|
730
|
+
web_link: m.webLink ?? null,
|
|
731
|
+
cite_as: (0,_lib_utils_source_link__WEBPACK_IMPORTED_MODULE_3__/* .citeAs */ .w)(m.subject, m.webLink, "Outlook message")
|
|
729
732
|
};
|
|
730
733
|
}
|
|
731
734
|
const BODY_CAP = 30000;
|
|
@@ -761,9 +764,9 @@ const outlookSearchTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/
|
|
|
761
764
|
}, {
|
|
762
765
|
name: "outlook_search",
|
|
763
766
|
description: "Search the user's Outlook mailbox using KQL (Microsoft's keyword query language). " + "Returns message metadata (from, to, subject, received, snippet, labels) plus @odata.count " + "and next_link when available. Examples: " + "'from:notifications@github.com', 'subject:invoice hasAttachment:true', " + "'isRead:false received>=2026-05-17'. **Use this before calling outlook_get_message** — " + "the snippet is often enough.",
|
|
764
|
-
schema:
|
|
765
|
-
query:
|
|
766
|
-
max_results:
|
|
767
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_4__/* .object */ .Ikc({
|
|
768
|
+
query: zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().describe("KQL query string"),
|
|
769
|
+
max_results: zod__WEBPACK_IMPORTED_MODULE_4__/* .number */ .aig().int().optional().describe("Max messages (default 25, max 100)")
|
|
767
770
|
})
|
|
768
771
|
});
|
|
769
772
|
const outlookGetMessageTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/* .tool */ .z6)(async ({ id })=>{
|
|
@@ -775,10 +778,10 @@ const outlookGetMessageTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_
|
|
|
775
778
|
if (m.error) return JSON.stringify(m);
|
|
776
779
|
const summary = summarizeMessage(m);
|
|
777
780
|
const rawBody = m.body?.content ?? "";
|
|
778
|
-
const plain = m.body?.contentType === "html" ? (0,
|
|
781
|
+
const plain = m.body?.contentType === "html" ? (0,_lib_utils_html__WEBPACK_IMPORTED_MODULE_5__/* .stripHtml */ .Q)(rawBody, {
|
|
779
782
|
preserveParagraphs: true
|
|
780
783
|
}) : rawBody;
|
|
781
|
-
const { text: body, truncated } = (0,
|
|
784
|
+
const { text: body, truncated } = (0,_lib_utils_text__WEBPACK_IMPORTED_MODULE_6__/* .truncateBytes */ .Q)(plain, BODY_CAP);
|
|
782
785
|
return JSON.stringify({
|
|
783
786
|
...summary,
|
|
784
787
|
body,
|
|
@@ -787,8 +790,8 @@ const outlookGetMessageTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_
|
|
|
787
790
|
}, {
|
|
788
791
|
name: "outlook_get_message",
|
|
789
792
|
description: "Fetch one Outlook message by id, including full headers and the decoded text body " + "(HTML stripped to plain text when needed). Body capped at 30KB with `truncated:true` " + "when cut off.",
|
|
790
|
-
schema:
|
|
791
|
-
id:
|
|
793
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_4__/* .object */ .Ikc({
|
|
794
|
+
id: zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().describe("Outlook message id (from outlook_search results)")
|
|
792
795
|
})
|
|
793
796
|
});
|
|
794
797
|
const outlookListFoldersTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/* .tool */ .z6)(async ()=>{
|
|
@@ -814,7 +817,7 @@ const outlookListFoldersTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE
|
|
|
814
817
|
}, {
|
|
815
818
|
name: "outlook_list_folders",
|
|
816
819
|
description: "List all Outlook mail folders. Use the `id` (or `well_known` name like 'inbox', " + "'drafts', 'sentitems', 'deleteditems', 'archive') with outlook_modify_message to move " + "a message between folders.",
|
|
817
|
-
schema:
|
|
820
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_4__/* .object */ .Ikc({})
|
|
818
821
|
});
|
|
819
822
|
const outlookModifyMessageTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/* .tool */ .z6)(async ({ id, mark_read, move_to_folder })=>{
|
|
820
823
|
const auth = (0,_lib_integrations_microsoft_oauth__WEBPACK_IMPORTED_MODULE_2__/* .resolveMicrosoftAuth */ .jG)();
|
|
@@ -857,10 +860,10 @@ const outlookModifyMessageTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODU
|
|
|
857
860
|
}, {
|
|
858
861
|
name: "outlook_modify_message",
|
|
859
862
|
description: "Modify an Outlook message: mark read/unread and/or move to another folder. Use " + "`mark_read: true` to mark read, `mark_read: false` to mark unread. `move_to_folder` " + "accepts a folder id from outlook_list_folders or a well-known name (e.g. 'archive', " + "'deleteditems'). Note that moving returns a NEW message id because Graph clones the " + "item into the destination folder.",
|
|
860
|
-
schema:
|
|
861
|
-
id:
|
|
862
|
-
mark_read:
|
|
863
|
-
move_to_folder:
|
|
863
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_4__/* .object */ .Ikc({
|
|
864
|
+
id: zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().describe("Outlook message id"),
|
|
865
|
+
mark_read: zod__WEBPACK_IMPORTED_MODULE_4__/* .boolean */ .zMY().optional().describe("Mark read (true) or unread (false)"),
|
|
866
|
+
move_to_folder: zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().optional().describe("Destination folder id or well-known name")
|
|
864
867
|
})
|
|
865
868
|
});
|
|
866
869
|
const outlookCreateDraftTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/* .tool */ .z6)(async ({ to, cc, subject, body, content_type })=>{
|
|
@@ -899,12 +902,12 @@ const outlookCreateDraftTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE
|
|
|
899
902
|
}, {
|
|
900
903
|
name: "outlook_create_draft",
|
|
901
904
|
description: "Create an Outlook draft email (saved to the Drafts folder, NOT sent). The user opens " + "Outlook to review and click Send. `to` and `cc` are arrays of plain email addresses. " + "`content_type` defaults to 'text'; pass 'html' if `body` contains HTML markup.",
|
|
902
|
-
schema:
|
|
903
|
-
to:
|
|
904
|
-
cc:
|
|
905
|
-
subject:
|
|
906
|
-
body:
|
|
907
|
-
content_type:
|
|
905
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_4__/* .object */ .Ikc({
|
|
906
|
+
to: zod__WEBPACK_IMPORTED_MODULE_4__/* .array */ .YOg(zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().email()).min(1).describe("Primary recipient emails"),
|
|
907
|
+
cc: zod__WEBPACK_IMPORTED_MODULE_4__/* .array */ .YOg(zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().email()).optional().describe("CC recipient emails"),
|
|
908
|
+
subject: zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().optional().describe("Subject line"),
|
|
909
|
+
body: zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().max(DRAFT_BODY_MAX_CHARS).optional().describe("Email body (max 100,000 characters)"),
|
|
910
|
+
content_type: zod__WEBPACK_IMPORTED_MODULE_4__/* ["enum"] */ .k5n([
|
|
908
911
|
"text",
|
|
909
912
|
"html"
|
|
910
913
|
]).optional().describe("Body content type (default 'text')")
|
|
@@ -933,8 +936,8 @@ const outlookTrashMessageTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODUL
|
|
|
933
936
|
}, {
|
|
934
937
|
name: "outlook_trash_message",
|
|
935
938
|
description: "Move an Outlook message to Deleted Items (recoverable from the trash for 30 days). " + "Does NOT permanently delete. Returns the new message id assigned after the move.",
|
|
936
|
-
schema:
|
|
937
|
-
id:
|
|
939
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_4__/* .object */ .Ikc({
|
|
940
|
+
id: zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().describe("Outlook message id to trash")
|
|
938
941
|
})
|
|
939
942
|
});
|
|
940
943
|
const outlookSendEmailTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/* .tool */ .z6)(async ({ to, cc, bcc, subject, body, content_type, save_to_sent_items })=>{
|
|
@@ -982,17 +985,17 @@ const outlookSendEmailTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0
|
|
|
982
985
|
}, {
|
|
983
986
|
name: "outlook_send_email",
|
|
984
987
|
description: "Send an Outlook email immediately via Microsoft Graph. Only use when the user explicitly asks " + "to send now; otherwise create a draft with outlook_create_draft. Supports text or HTML bodies " + "via `content_type`. If this returns a 403 scope error, ask the user to reconnect Outlook so " + "Mail.Send is granted.",
|
|
985
|
-
schema:
|
|
986
|
-
to:
|
|
987
|
-
cc:
|
|
988
|
-
bcc:
|
|
989
|
-
subject:
|
|
990
|
-
body:
|
|
991
|
-
content_type:
|
|
988
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_4__/* .object */ .Ikc({
|
|
989
|
+
to: zod__WEBPACK_IMPORTED_MODULE_4__/* .array */ .YOg(zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().email()).min(1).describe("Primary recipient emails"),
|
|
990
|
+
cc: zod__WEBPACK_IMPORTED_MODULE_4__/* .array */ .YOg(zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().email()).optional().describe("CC recipient emails"),
|
|
991
|
+
bcc: zod__WEBPACK_IMPORTED_MODULE_4__/* .array */ .YOg(zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().email()).optional().describe("BCC recipient emails"),
|
|
992
|
+
subject: zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().optional().describe("Subject line"),
|
|
993
|
+
body: zod__WEBPACK_IMPORTED_MODULE_4__/* .string */ .YjP().max(SEND_BODY_MAX_CHARS).optional().describe("Email body (max 100,000 characters)"),
|
|
994
|
+
content_type: zod__WEBPACK_IMPORTED_MODULE_4__/* ["enum"] */ .k5n([
|
|
992
995
|
"text",
|
|
993
996
|
"html"
|
|
994
997
|
]).optional().describe("Body content type (default 'text')"),
|
|
995
|
-
save_to_sent_items:
|
|
998
|
+
save_to_sent_items: zod__WEBPACK_IMPORTED_MODULE_4__/* .boolean */ .zMY().optional().describe("Whether Graph should save the message to Sent Items (default true)")
|
|
996
999
|
})
|
|
997
1000
|
});
|
|
998
1001
|
(0,_packages_langchain_package__WEBPACK_IMPORTED_MODULE_1__/* .registerLangChainPackage */ .p)({
|
|
@@ -2652,7 +2655,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
2652
2655
|
// UNUSED EXPORTS: buildToolTelemetryComplaintIssue, createToolTelemetryGitHubIssue, currentToolFailureMetric, reportToolTelemetryIssueTool
|
|
2653
2656
|
|
|
2654
2657
|
// EXTERNAL MODULE: ./node_modules/@langchain/core/dist/tools/index.js
|
|
2655
|
-
var tools = __webpack_require__(
|
|
2658
|
+
var tools = __webpack_require__(71966);
|
|
2656
2659
|
// EXTERNAL MODULE: ./node_modules/zod/v4/classic/schemas.js + 4 modules
|
|
2657
2660
|
var schemas = __webpack_require__(17033);
|
|
2658
2661
|
// EXTERNAL MODULE: external "node:crypto"
|
|
@@ -3832,12 +3835,13 @@ function drainQueuedBoundary(threadId) {
|
|
|
3832
3835
|
function runBoundaryCompaction(threadId, boundarySeq, options) {
|
|
3833
3836
|
const baseThread = (0,threads/* getThread */.fG)(threadId);
|
|
3834
3837
|
const basePinSeq = baseThread?.hot_since_seq ?? null;
|
|
3838
|
+
const baseLock = baseThread?.auto_boundary_locked_until_msg_count ?? 0;
|
|
3835
3839
|
void (0,thread_compaction_state/* runTrackedCompaction */.PL)(threadId, "auto", boundarySeq, async (attempt)=>{
|
|
3836
3840
|
await Promise.resolve();
|
|
3837
|
-
await commitBoundaryCompaction(threadId, boundarySeq, basePinSeq, options, attempt);
|
|
3841
|
+
await commitBoundaryCompaction(threadId, boundarySeq, basePinSeq, baseLock, options, attempt);
|
|
3838
3842
|
}).catch((err)=>console.warn(`[context-boundary:auto] compaction failed thread=${threadId}: ${String(err)}`)).finally(()=>drainQueuedBoundary(threadId));
|
|
3839
3843
|
}
|
|
3840
|
-
async function commitBoundaryCompaction(threadId, boundarySeq, basePinSeq, options, attempt) {
|
|
3844
|
+
async function commitBoundaryCompaction(threadId, boundarySeq, basePinSeq, baseLock, options, attempt) {
|
|
3841
3845
|
const committed = await compactThreadWarmContext(threadId, boundarySeq, {
|
|
3842
3846
|
expectedHotSinceSeq: basePinSeq,
|
|
3843
3847
|
alignTopicBoundary: true,
|
|
@@ -3845,7 +3849,18 @@ async function commitBoundaryCompaction(threadId, boundarySeq, basePinSeq, optio
|
|
|
3845
3849
|
...options,
|
|
3846
3850
|
attempt
|
|
3847
3851
|
});
|
|
3848
|
-
if (!committed)
|
|
3852
|
+
if (!committed) {
|
|
3853
|
+
// A pass that resolved to no change (the active topic still starts at the
|
|
3854
|
+
// current pin) must not be retried on every following turn either. Skip
|
|
3855
|
+
// it when the boundary or lock changed mid-pass (e.g. the user cleared or
|
|
3856
|
+
// moved the boundary): that newer state wins over this stale pass.
|
|
3857
|
+
const lockUntil = options.autoBoundaryLockedUntilMessageCount;
|
|
3858
|
+
const current = (0,threads/* getThread */.fG)(threadId);
|
|
3859
|
+
if (lockUntil !== undefined && current && (current.hot_since_seq ?? null) === basePinSeq && (current.auto_boundary_locked_until_msg_count ?? 0) === baseLock && lockUntil > baseLock) {
|
|
3860
|
+
(0,threads/* setAutoBoundaryLock */.NU)(threadId, lockUntil);
|
|
3861
|
+
}
|
|
3862
|
+
return;
|
|
3863
|
+
}
|
|
3849
3864
|
console.info(`[context-boundary:auto] thread=${threadId} committed boundary_seq=${committed.boundarySeq} warm_msgs=${committed.sourceMessages}`);
|
|
3850
3865
|
}
|
|
3851
3866
|
async function findTopicBoundary(threadId, boundarySeq) {
|
|
@@ -4938,7 +4953,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
4938
4953
|
// UNUSED EXPORTS: allBuiltins, builtinNames, getAllTools, getBuiltinToolNames, getPackagesDir, getToolCategory, getToolCredentialsRequired, getToolIntegration, getToolSource, getToolsDir, loadExternal, loadLangChainPackages, registerTools, reloadLangChainPackages, toCatalogEntry
|
|
4939
4954
|
|
|
4940
4955
|
// EXTERNAL MODULE: ./node_modules/@langchain/core/dist/tools/index.js
|
|
4941
|
-
var tools = __webpack_require__(
|
|
4956
|
+
var tools = __webpack_require__(71966);
|
|
4942
4957
|
// EXTERNAL MODULE: ./lib/env/config.ts
|
|
4943
4958
|
var env_config = __webpack_require__(62207);
|
|
4944
4959
|
// EXTERNAL MODULE: ./lib/cache/keyed-cache.ts
|
|
@@ -7187,10 +7202,13 @@ function fuzzyUniqueRange(raw, oldString) {
|
|
|
7187
7202
|
if (oldLines.some((line)=>line.length === 0)) return [];
|
|
7188
7203
|
const rawLines = raw.split(/\r\n|\r|\n/);
|
|
7189
7204
|
const rawLineStarts = [];
|
|
7205
|
+
const eol = /\r\n|\r|\n/g;
|
|
7190
7206
|
let offset = 0;
|
|
7191
7207
|
for (const line of rawLines){
|
|
7192
7208
|
rawLineStarts.push(offset);
|
|
7193
|
-
offset
|
|
7209
|
+
eol.lastIndex = offset + line.length;
|
|
7210
|
+
const brk = eol.exec(raw);
|
|
7211
|
+
offset = offset + line.length + (brk ? brk[0].length : 0);
|
|
7194
7212
|
}
|
|
7195
7213
|
const scores = [];
|
|
7196
7214
|
for(let i = 0; i + oldLines.length <= rawLines.length; i++){
|
|
@@ -7247,7 +7265,9 @@ function findAllExact(haystack, needle) {
|
|
|
7247
7265
|
function findWithTransforms(raw, oldString, fns) {
|
|
7248
7266
|
const bufT = composeTransforms(raw, fns);
|
|
7249
7267
|
const oldT = composeTransforms(oldString, fns);
|
|
7250
|
-
|
|
7268
|
+
// A needle that normalizes to bare whitespace would match an arbitrary
|
|
7269
|
+
// line break, so it can never identify an edit target.
|
|
7270
|
+
if (oldT.text.trim().length === 0) return [];
|
|
7251
7271
|
const starts = findAllExact(bufT.text, oldT.text);
|
|
7252
7272
|
return starts.map((s)=>({
|
|
7253
7273
|
start: bufT.toOriginal[s],
|
|
@@ -11675,6 +11695,7 @@ const PRICE_LINE_RE = new RegExp([
|
|
|
11675
11695
|
String.raw`\$\s*\d+(?:\.\d+)?\s*(?:/|per)\s*(?:image|minute|request)`
|
|
11676
11696
|
].join("|"), "gi");
|
|
11677
11697
|
const GOOGLE_RESULT_RE = /href="\/url\?q=([^"&]+)[^"]*"/gi;
|
|
11698
|
+
const GOOGLE_OWN_HOST_RE = /^(?:www|accounts|support|maps|policies|webcache)?\.?google\.[a-z.]+$/i;
|
|
11678
11699
|
function toCanonicalProvider(id) {
|
|
11679
11700
|
const lower = id.toLowerCase();
|
|
11680
11701
|
if (lower.includes("google") || lower.includes("gemini")) return "google";
|
|
@@ -11706,7 +11727,8 @@ async function refreshPricingSnapshot(opts) {
|
|
|
11706
11727
|
const existing = await readPricingSnapshot();
|
|
11707
11728
|
if (!force && existing) {
|
|
11708
11729
|
const ageDays = (Date.now() - Date.parse(existing.generated_at)) / (24 * 60 * 60 * 1000);
|
|
11709
|
-
|
|
11730
|
+
// A future generated_at (clock skew, copied snapshot) must not pin the cache as fresh.
|
|
11731
|
+
if (Number.isFinite(ageDays) && ageDays >= 0 && ageDays < ttlDays) {
|
|
11710
11732
|
return {
|
|
11711
11733
|
refreshed: false,
|
|
11712
11734
|
reason: "fresh",
|
|
@@ -11843,6 +11865,8 @@ function parseGoogleResultLinks(html) {
|
|
|
11843
11865
|
const out = [];
|
|
11844
11866
|
const seen = new Set();
|
|
11845
11867
|
let m;
|
|
11868
|
+
// Shared /g regex: an early break leaves lastIndex mid-string for the next page.
|
|
11869
|
+
GOOGLE_RESULT_RE.lastIndex = 0;
|
|
11846
11870
|
while((m = GOOGLE_RESULT_RE.exec(html)) !== null){
|
|
11847
11871
|
const raw = m[1] ?? "";
|
|
11848
11872
|
let url = "";
|
|
@@ -11852,7 +11876,11 @@ function parseGoogleResultLinks(html) {
|
|
|
11852
11876
|
continue;
|
|
11853
11877
|
}
|
|
11854
11878
|
if (!/^https?:\/\//i.test(url)) continue;
|
|
11855
|
-
|
|
11879
|
+
try {
|
|
11880
|
+
if (GOOGLE_OWN_HOST_RE.test(new URL(url).hostname)) continue;
|
|
11881
|
+
} catch {
|
|
11882
|
+
continue;
|
|
11883
|
+
}
|
|
11856
11884
|
if (seen.has(url)) continue;
|
|
11857
11885
|
seen.add(url);
|
|
11858
11886
|
out.push(url);
|
|
@@ -13511,58 +13539,79 @@ function containsText(source, needle, ignoreCase) {
|
|
|
13511
13539
|
if (!ignoreCase) return source.includes(needle);
|
|
13512
13540
|
return source.toLowerCase().includes(needle.toLowerCase());
|
|
13513
13541
|
}
|
|
13514
|
-
|
|
13515
|
-
|
|
13516
|
-
|
|
13517
|
-
|
|
13518
|
-
|
|
13519
|
-
|
|
13520
|
-
|
|
13521
|
-
|
|
13522
|
-
|
|
13523
|
-
|
|
13524
|
-
...
|
|
13542
|
+
const FENCE_RE = /^\s{0,3}(`{3,}|~{3,})/;
|
|
13543
|
+
const HORIZONTAL_RULE_RE = /^\s{0,3}([-*_])(?:\s*\1){2,}\s*$/;
|
|
13544
|
+
/**
|
|
13545
|
+
* Drop duplicate segments from `parts`, which alternates content (even
|
|
13546
|
+
* indexes) and the original separator that follows it (odd indexes).
|
|
13547
|
+
* Separators are preserved verbatim, so only removed segments change the
|
|
13548
|
+
* text. `keyOf` returns null for a segment that must always be kept.
|
|
13549
|
+
*/ function dedupeSegments(parts, keyOf, keep) {
|
|
13550
|
+
const contentIdx = parts.map((_, i)=>i).filter((i)=>i % 2 === 0);
|
|
13551
|
+
const visit = keep === "first" ? contentIdx : [
|
|
13552
|
+
...contentIdx
|
|
13525
13553
|
].reverse();
|
|
13526
13554
|
const seen = new Set();
|
|
13555
|
+
const dropped = new Set();
|
|
13527
13556
|
for (const idx of visit){
|
|
13528
|
-
const key =
|
|
13529
|
-
if (
|
|
13530
|
-
|
|
13531
|
-
|
|
13532
|
-
|
|
13533
|
-
|
|
13534
|
-
|
|
13535
|
-
|
|
13557
|
+
const key = keyOf(idx);
|
|
13558
|
+
if (key === null) continue;
|
|
13559
|
+
if (seen.has(key)) dropped.add(idx);
|
|
13560
|
+
else seen.add(key);
|
|
13561
|
+
}
|
|
13562
|
+
if (dropped.size === 0) return {
|
|
13563
|
+
text: parts.join(""),
|
|
13564
|
+
removed: 0
|
|
13565
|
+
};
|
|
13566
|
+
let text = "";
|
|
13567
|
+
let emitted = false;
|
|
13568
|
+
for (const idx of contentIdx){
|
|
13569
|
+
if (dropped.has(idx)) continue;
|
|
13570
|
+
if (emitted && idx > 0) text += parts[idx - 1];
|
|
13571
|
+
text += parts[idx];
|
|
13572
|
+
emitted = true;
|
|
13536
13573
|
}
|
|
13537
|
-
const next = lines.filter((_, idx)=>keep.has(idx));
|
|
13538
13574
|
return {
|
|
13539
|
-
text
|
|
13540
|
-
removed:
|
|
13575
|
+
text,
|
|
13576
|
+
removed: dropped.size
|
|
13541
13577
|
};
|
|
13542
13578
|
}
|
|
13579
|
+
function dedupeLines(source, opts) {
|
|
13580
|
+
const parts = source.split(/(\r?\n)/);
|
|
13581
|
+
// Fence markers, fenced code and horizontal rules repeat by design; a
|
|
13582
|
+
// closing ``` is always a "duplicate" of the opening one.
|
|
13583
|
+
const protectedIdx = new Set();
|
|
13584
|
+
let fence = null;
|
|
13585
|
+
for(let i = 0; i < parts.length; i += 2){
|
|
13586
|
+
const marker = FENCE_RE.exec(parts[i])?.[1];
|
|
13587
|
+
if (fence !== null) {
|
|
13588
|
+
protectedIdx.add(i);
|
|
13589
|
+
if (marker && marker[0] === fence[0] && marker.length >= fence.length && /^\s*[`~]+\s*$/.test(parts[i])) fence = null;
|
|
13590
|
+
} else if (marker) {
|
|
13591
|
+
protectedIdx.add(i);
|
|
13592
|
+
fence = marker;
|
|
13593
|
+
} else if (HORIZONTAL_RULE_RE.test(parts[i])) {
|
|
13594
|
+
protectedIdx.add(i);
|
|
13595
|
+
}
|
|
13596
|
+
}
|
|
13597
|
+
return dedupeSegments(parts, (i)=>{
|
|
13598
|
+
if (protectedIdx.has(i)) return null;
|
|
13599
|
+
const normalized = opts.trim ? parts[i].trim() : parts[i];
|
|
13600
|
+
if (opts.skipBlank && normalized.length === 0) return null;
|
|
13601
|
+
return opts.ignoreCase ? normalized.toLowerCase() : normalized;
|
|
13602
|
+
}, opts.keep);
|
|
13603
|
+
}
|
|
13543
13604
|
function dedupeParagraphs(source, opts) {
|
|
13544
|
-
const
|
|
13545
|
-
const
|
|
13546
|
-
|
|
13605
|
+
const tail = /\s*$/.exec(source)?.[0] ?? "";
|
|
13606
|
+
const parts = source.slice(0, source.length - tail.length).split(/(\r?\n(?:[ \t]*\r?\n)+)/);
|
|
13607
|
+
const out = dedupeSegments(parts, (i)=>{
|
|
13608
|
+
if (parts[i].trim().length === 0) return null;
|
|
13609
|
+
const base = opts.trim ? parts[i].trim() : parts[i];
|
|
13547
13610
|
return opts.ignoreCase ? base.toLowerCase() : base;
|
|
13548
|
-
});
|
|
13549
|
-
const keep = new Set();
|
|
13550
|
-
const visit = opts.keep === "first" ? [
|
|
13551
|
-
...keys.keys()
|
|
13552
|
-
] : [
|
|
13553
|
-
...keys.keys()
|
|
13554
|
-
].reverse();
|
|
13555
|
-
const seen = new Set();
|
|
13556
|
-
for (const idx of visit){
|
|
13557
|
-
const key = keys[idx];
|
|
13558
|
-
if (seen.has(key)) continue;
|
|
13559
|
-
seen.add(key);
|
|
13560
|
-
keep.add(idx);
|
|
13561
|
-
}
|
|
13562
|
-
const next = paragraphs.filter((_, idx)=>keep.has(idx));
|
|
13611
|
+
}, opts.keep);
|
|
13563
13612
|
return {
|
|
13564
|
-
text:
|
|
13565
|
-
removed:
|
|
13613
|
+
text: out.text + tail,
|
|
13614
|
+
removed: out.removed
|
|
13566
13615
|
};
|
|
13567
13616
|
}
|
|
13568
13617
|
|
|
@@ -14363,7 +14412,7 @@ function version_getCurrentVersion() {
|
|
|
14363
14412
|
}
|
|
14364
14413
|
|
|
14365
14414
|
;// ./docs/adoption/changesets.json
|
|
14366
|
-
const changesets_namespaceObject = /*#__PURE__*/JSON.parse('{"schema_version":1,"changesets":[{"version":"2.0.1","previous_version":"2.0.0","date":"2026-10-11","hints":[],"commits":["chore(release): bump to 2.0.1","fix(npm): remove oversized runtime assets"],"prompts":[],"tools":[]},{"version":"2.0.2","previous_version":"2.0.1","date":"2026-10-11","hints":[],"commits":["chore(release): bump to 2.0.2","fix(npm): exclude nested server source maps"],"prompts":[],"tools":[]},{"version":"2.0.3","previous_version":"2.0.2","date":"2026-10-12","hints":[],"commits":["chore(release): bump to 2.0.3","fix(npm): remove maps before npm packing"],"prompts":[],"tools":[]},{"version":"2.0.4","previous_version":"2.0.3","date":"2026-10-12","hints":[],"commits":["chore(release): bump to 2.0.4","fix(npm): use installed onnx runtime dependencies"],"prompts":[],"tools":[]},{"version":"2.0.5","previous_version":"2.0.4","date":"2026-10-13","hints":[],"commits":["chore(release): bump to 2.0.5","fix(providers): detect streams that end without events","fix(http): fix gzip response decoding","docs(site): update guides, theme, and architecture diagrams","refactor(bridges): add capability-driven bridge modules","fix(security): update vulnerable media parser","refactor(modules): split built-in provider and package registries"],"prompts":[],"tools":[]},{"version":"2.1.0","previous_version":"2.0.5","date":"2026-10-14","hints":[],"commits":["chore(release): bump to 2.1.0","fix(release): add model download retries and cache","fix(chat): render grouped summary topic previews","fix(workflows): validate legacy checklist items","docs(pricing): document aggregator data sources","feat(core): add verified workflows, pricing signals, and summaries"],"prompts":[{"id":"static.agent.tool-usage-sop","source":"lib/agents/prepare/system-prompt.ts","change":"changed","added_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"removed_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"omitted_lines":0},{"id":"system.Tool usage SOP","source":"lib/agents/prepare/system-prompt.ts","change":"changed","added_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"removed_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"omitted_lines":0}],"tools":[{"name":"refresh_model_pricing","change":"changed","description_changed":true,"description":"Refresh provider pricing pages and separate OpenRouter/LiteLLM reference feeds, then recalculate dashboard estimates using provider-page rates only. Returns rate changes, source health, confidence, and current-versus-recorded dashboard totals. These are estimates, not invoice amounts.","previous_description":"Refresh the configured official LLM pricing sources and recalculate dashboard estimates using the latest rates. Returns rate changes, source health, confidence, and current-versus-recorded dashboard totals. These are estimates, not invoice amounts.","params_added":[],"params_removed":[],"params_changed":[],"required_added":[],"required_removed":[]},{"name":"workflow_progress","change":"changed","description_changed":true,"description":"Report structured progress for a substantial multi-step task. Use only when the task has several dependent phases, likely spans turns, or needs explicit verification; skip simple tasks and work already covered by native tool progress. For agent-created workflows, send the full current items snapshot on every call and reuse the same workflow_id. Keep secrets and private data out of workflow fields. Mark items done only with observed validation evidence; use needs_attention for blockers; phase=complete requires every item done or skipped. Every item needs input, expected output, and concrete va…","previous_description":"Report structured progress for a substantial multi-step task. Use only when the task has several dependent phases, likely spans turns, or needs explicit verification; skip simple tasks and work already covered by native tool progress. For agent-created workflows, send the full current items snapshot on every call and reuse the same workflow_id. Keep secrets and private data out of workflow fields. Mark items done only after verifying the action; use needs_attention for blockers; phase=complete requires every item done or skipped. The system-owned version_adoption workflow has its own durable …","params_added":["validation_evidence"],"params_removed":[],"params_changed":["items"],"required_added":[],"required_removed":[]}]},{"version":"2.2.0","previous_version":"2.1.0","date":"2026-10-15","hints":[],"commits":["chore(release): bump to 2.2.0","feat(embeddings): add on-demand local model download","fix(build): exclude foreign runtimes from standalone bundles"],"prompts":[],"tools":[]},{"version":"2.2.1","previous_version":"2.2.0","date":"2026-10-15","hints":[],"commits":["chore(release): bump to 2.2.1","fix(api): skip browser http cache for client requests","feat(models): add model enable toggle and atomic default","fix(github-copilot): remove retired pat route"],"prompts":[],"tools":[]},{"version":"2.3.0","previous_version":"2.2.1","date":"2026-10-16","hints":["If an agent\'s instructions or skills tell it to leave fact capture to compaction or to avoid `memory_upsert`, remove that guidance, since agents now save facts during the turn.","If a scheduled task or watcher prompt asks the agent to write memory facts, keep that in the agent\'s own turn; automation channel summaries no longer extract facts."],"commits":["chore(repo): remove dead exports and the unused deepseek package","fix(chat): restore thread activity and bound compaction per thread","fix(chat): render automation recaps in the warm summary card","fix(chat): restore the compacting state after switching agents","fix(chat): allow compacting bridge-only threads, report via toasts","fix(scripts): align make targets and install the current working tree","feat(agents): add topic pipeline to automation channel summaries","feat(agents): add validated topic pipeline for warm compaction","feat(agents): add proactive, validated memory saving for agents","fix(chat): group older summaries into collapsible topic rows","feat(agents): add auto-retry for failed workflow step contracts","feat(chat): add per-step retry to workflow checklists","feat(lifecycle): add release changesets for version adoption","fix(chat): keep boundary locate from snapping to bottom"],"prompts":[{"id":"static.agent.compaction-group","source":"lib/agents/compaction-pipeline.ts","change":"added","added_lines":[],"removed_lines":[],"omitted_lines":0},{"id":"static.agent.compaction-group-automation","source":"lib/agents/compaction-pipeline.ts","change":"added","added_lines":[],"removed_lines":[],"omitted_lines":0},{"id":"static.agent.compaction-topic-recap","source":"lib/agents/compaction-pipeline.ts","change":"added","added_lines":[],"removed_lines":[],"omitted_lines":0},{"id":"static.agent.compaction-topic-recap-automation","source":"lib/agents/compaction-pipeline.ts","change":"added","added_lines":[],"removed_lines":[],"omitted_lines":0},{"id":"static.agent.conversation-summary","source":"lib/agents/conversation-summary.ts","change":"changed","added_lines":["A topic groups every consecutive message about one subject and must","span at least two messages (a request and its reply); fold a stray","single message into the adjacent topic instead of giving it its own."],"removed_lines":[],"omitted_lines":0},{"id":"static.agent.tool-usage-sop","source":"lib/agents/prepare/system-prompt.ts","change":"changed","added_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"removed_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"omitted_lines":0},{"id":"system.Memory & recall","source":"lib/agents/prepare/system-prompt.ts","change":"changed","added_lines":["You have long-term memory across sessions, shared with every other Jarela agent. A record you save is available to other agents immediately. Background compaction also extracts facts later, but it runs late and can miss details, so it is a backstop, not your save step.","Proactive save procedure — run it whenever information fits the active memory policy, without waiting to be asked:","1. Trigger: the user states a preference, a fact about themselves or their work, a decision, a constraint, or a correction to something saved; or a tool result verifies a durable fact. Routine status, one-off chatter, secrets, credentials, and raw transcripts never qualify.","2. Check: memory_search (or memory_read for a known key) for an existing record on the same subject. Update that stable key rather than creating a duplicate or contradictory copy.","3. Write: call memory_upsert in the same turn, before your final reply, with namespace=\'facts\', a stable descriptive key, standalone content, concise tags, confidence=\'explicit\' for user-stated information (\'verified\' when tool-backed, \'inferred\' only when useful and reversible), observed_at when t…","4. Validate: the memory_upsert result must contain ok:true and the key you sent. If it failed, correct the arguments and retry once; if it still fails, tell the user it was not saved.","5. Cite: end your reply with one short line naming each saved key, for example \'Saved to memory: facts/answer-format-preference\'. Omit the line when nothing was saved."],"removed_lines":["You have long-term memory across sessions.","- Use memory_upsert proactively for structured records. Use namespace=\'facts\', concise tags, confidence=\'explicit\' for user-stated information, observed_at when the information was true, and expires_at for temporary facts. Keep memory_write only for legacy/free-form notes."],"omitted_lines":0},{"id":"system.Tool usage SOP","source":"lib/agents/prepare/system-prompt.ts","change":"changed","added_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"removed_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"omitted_lines":0}],"tools":[{"name":"memory_upsert","change":"changed","description_changed":true,"description":"Store a durable, structured memory record for proactive semantic recall. Use namespace=\'facts\' for information that should surface in future conversations. Store explicit user preferences, verified facts, decisions, constraints, and reusable project context; do not store transient chat details or secrets. Use an expiry for temporary facts, and status=\'archived\' to soft-retire a record instead of deleting it. Save proactively in the same turn the information appears so other agents can use it immediately; do not defer to background compaction.","previous_description":"Store a durable, structured memory record for proactive semantic recall. Use namespace=\'facts\' for information that should surface in future conversations. Store explicit user preferences, verified facts, decisions, constraints, and reusable project context; do not store transient chat details or secrets. Use an expiry for temporary facts, and status=\'archived\' to soft-retire a record instead of deleting it.","params_added":[],"params_removed":[],"params_changed":[],"required_added":[],"required_removed":[]},{"name":"workflow_progress","change":"changed","description_changed":true,"description":"Report structured progress for a substantial multi-step task. Use only when the task has several dependent phases, likely spans turns, or needs explicit verification; skip simple tasks and work already covered by native tool progress. For agent-created workflows, send the full current items snapshot on every call and reuse the same workflow_id. Keep secrets and private data out of workflow fields. Mark items done only with observed validation evidence; use needs_attention for blockers; phase=complete requires every item done or skipped. A rejected update, or a step left checking or needs_atte…","previous_description":"Report structured progress for a substantial multi-step task. Use only when the task has several dependent phases, likely spans turns, or needs explicit verification; skip simple tasks and work already covered by native tool progress. For agent-created workflows, send the full current items snapshot on every call and reuse the same workflow_id. Keep secrets and private data out of workflow fields. Mark items done only with observed validation evidence; use needs_attention for blockers; phase=complete requires every item done or skipped. Every item needs input, expected output, and concrete va…","params_added":["needs_user"],"params_removed":[],"params_changed":[],"required_added":[],"required_removed":[]}]}]}');
|
|
14415
|
+
const changesets_namespaceObject = /*#__PURE__*/JSON.parse('{"schema_version":1,"changesets":[{"version":"2.0.1","previous_version":"2.0.0","date":"2026-10-11","hints":[],"commits":["chore(release): bump to 2.0.1","fix(npm): remove oversized runtime assets"],"prompts":[],"tools":[]},{"version":"2.0.2","previous_version":"2.0.1","date":"2026-10-11","hints":[],"commits":["chore(release): bump to 2.0.2","fix(npm): exclude nested server source maps"],"prompts":[],"tools":[]},{"version":"2.0.3","previous_version":"2.0.2","date":"2026-10-12","hints":[],"commits":["chore(release): bump to 2.0.3","fix(npm): remove maps before npm packing"],"prompts":[],"tools":[]},{"version":"2.0.4","previous_version":"2.0.3","date":"2026-10-12","hints":[],"commits":["chore(release): bump to 2.0.4","fix(npm): use installed onnx runtime dependencies"],"prompts":[],"tools":[]},{"version":"2.0.5","previous_version":"2.0.4","date":"2026-10-13","hints":[],"commits":["chore(release): bump to 2.0.5","fix(providers): detect streams that end without events","fix(http): fix gzip response decoding","docs(site): update guides, theme, and architecture diagrams","refactor(bridges): add capability-driven bridge modules","fix(security): update vulnerable media parser","refactor(modules): split built-in provider and package registries"],"prompts":[],"tools":[]},{"version":"2.1.0","previous_version":"2.0.5","date":"2026-10-14","hints":[],"commits":["chore(release): bump to 2.1.0","fix(release): add model download retries and cache","fix(chat): render grouped summary topic previews","fix(workflows): validate legacy checklist items","docs(pricing): document aggregator data sources","feat(core): add verified workflows, pricing signals, and summaries"],"prompts":[{"id":"static.agent.tool-usage-sop","source":"lib/agents/prepare/system-prompt.ts","change":"changed","added_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"removed_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"omitted_lines":0},{"id":"system.Tool usage SOP","source":"lib/agents/prepare/system-prompt.ts","change":"changed","added_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"removed_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"omitted_lines":0}],"tools":[{"name":"refresh_model_pricing","change":"changed","description_changed":true,"description":"Refresh provider pricing pages and separate OpenRouter/LiteLLM reference feeds, then recalculate dashboard estimates using provider-page rates only. Returns rate changes, source health, confidence, and current-versus-recorded dashboard totals. These are estimates, not invoice amounts.","previous_description":"Refresh the configured official LLM pricing sources and recalculate dashboard estimates using the latest rates. Returns rate changes, source health, confidence, and current-versus-recorded dashboard totals. These are estimates, not invoice amounts.","params_added":[],"params_removed":[],"params_changed":[],"required_added":[],"required_removed":[]},{"name":"workflow_progress","change":"changed","description_changed":true,"description":"Report structured progress for a substantial multi-step task. Use only when the task has several dependent phases, likely spans turns, or needs explicit verification; skip simple tasks and work already covered by native tool progress. For agent-created workflows, send the full current items snapshot on every call and reuse the same workflow_id. Keep secrets and private data out of workflow fields. Mark items done only with observed validation evidence; use needs_attention for blockers; phase=complete requires every item done or skipped. Every item needs input, expected output, and concrete va…","previous_description":"Report structured progress for a substantial multi-step task. Use only when the task has several dependent phases, likely spans turns, or needs explicit verification; skip simple tasks and work already covered by native tool progress. For agent-created workflows, send the full current items snapshot on every call and reuse the same workflow_id. Keep secrets and private data out of workflow fields. Mark items done only after verifying the action; use needs_attention for blockers; phase=complete requires every item done or skipped. The system-owned version_adoption workflow has its own durable …","params_added":["validation_evidence"],"params_removed":[],"params_changed":["items"],"required_added":[],"required_removed":[]}]},{"version":"2.2.0","previous_version":"2.1.0","date":"2026-10-15","hints":[],"commits":["chore(release): bump to 2.2.0","feat(embeddings): add on-demand local model download","fix(build): exclude foreign runtimes from standalone bundles"],"prompts":[],"tools":[]},{"version":"2.2.1","previous_version":"2.2.0","date":"2026-10-15","hints":[],"commits":["chore(release): bump to 2.2.1","fix(api): skip browser http cache for client requests","feat(models): add model enable toggle and atomic default","fix(github-copilot): remove retired pat route"],"prompts":[],"tools":[]},{"version":"2.3.0","previous_version":"2.2.1","date":"2026-10-16","hints":["If an agent\'s instructions or skills tell it to leave fact capture to compaction or to avoid `memory_upsert`, remove that guidance, since agents now save facts during the turn.","If a scheduled task or watcher prompt asks the agent to write memory facts, keep that in the agent\'s own turn; automation channel summaries no longer extract facts."],"commits":["chore(repo): remove dead exports and the unused deepseek package","fix(chat): restore thread activity and bound compaction per thread","fix(chat): render automation recaps in the warm summary card","fix(chat): restore the compacting state after switching agents","fix(chat): allow compacting bridge-only threads, report via toasts","fix(scripts): align make targets and install the current working tree","feat(agents): add topic pipeline to automation channel summaries","feat(agents): add validated topic pipeline for warm compaction","feat(agents): add proactive, validated memory saving for agents","fix(chat): group older summaries into collapsible topic rows","feat(agents): add auto-retry for failed workflow step contracts","feat(chat): add per-step retry to workflow checklists","feat(lifecycle): add release changesets for version adoption","fix(chat): keep boundary locate from snapping to bottom"],"prompts":[{"id":"static.agent.compaction-group","source":"lib/agents/compaction-pipeline.ts","change":"added","added_lines":[],"removed_lines":[],"omitted_lines":0},{"id":"static.agent.compaction-group-automation","source":"lib/agents/compaction-pipeline.ts","change":"added","added_lines":[],"removed_lines":[],"omitted_lines":0},{"id":"static.agent.compaction-topic-recap","source":"lib/agents/compaction-pipeline.ts","change":"added","added_lines":[],"removed_lines":[],"omitted_lines":0},{"id":"static.agent.compaction-topic-recap-automation","source":"lib/agents/compaction-pipeline.ts","change":"added","added_lines":[],"removed_lines":[],"omitted_lines":0},{"id":"static.agent.conversation-summary","source":"lib/agents/conversation-summary.ts","change":"changed","added_lines":["A topic groups every consecutive message about one subject and must","span at least two messages (a request and its reply); fold a stray","single message into the adjacent topic instead of giving it its own."],"removed_lines":[],"omitted_lines":0},{"id":"static.agent.tool-usage-sop","source":"lib/agents/prepare/system-prompt.ts","change":"changed","added_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"removed_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"omitted_lines":0},{"id":"system.Memory & recall","source":"lib/agents/prepare/system-prompt.ts","change":"changed","added_lines":["You have long-term memory across sessions, shared with every other Jarela agent. A record you save is available to other agents immediately. Background compaction also extracts facts later, but it runs late and can miss details, so it is a backstop, not your save step.","Proactive save procedure — run it whenever information fits the active memory policy, without waiting to be asked:","1. Trigger: the user states a preference, a fact about themselves or their work, a decision, a constraint, or a correction to something saved; or a tool result verifies a durable fact. Routine status, one-off chatter, secrets, credentials, and raw transcripts never qualify.","2. Check: memory_search (or memory_read for a known key) for an existing record on the same subject. Update that stable key rather than creating a duplicate or contradictory copy.","3. Write: call memory_upsert in the same turn, before your final reply, with namespace=\'facts\', a stable descriptive key, standalone content, concise tags, confidence=\'explicit\' for user-stated information (\'verified\' when tool-backed, \'inferred\' only when useful and reversible), observed_at when t…","4. Validate: the memory_upsert result must contain ok:true and the key you sent. If it failed, correct the arguments and retry once; if it still fails, tell the user it was not saved.","5. Cite: end your reply with one short line naming each saved key, for example \'Saved to memory: facts/answer-format-preference\'. Omit the line when nothing was saved."],"removed_lines":["You have long-term memory across sessions.","- Use memory_upsert proactively for structured records. Use namespace=\'facts\', concise tags, confidence=\'explicit\' for user-stated information, observed_at when the information was true, and expires_at for temporary facts. Keep memory_write only for legacy/free-form notes."],"omitted_lines":0},{"id":"system.Tool usage SOP","source":"lib/agents/prepare/system-prompt.ts","change":"changed","added_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"removed_lines":["0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. Use only these operation labels when describing work: read, write, execute, send, schedu…"],"omitted_lines":0}],"tools":[{"name":"memory_upsert","change":"changed","description_changed":true,"description":"Store a durable, structured memory record for proactive semantic recall. Use namespace=\'facts\' for information that should surface in future conversations. Store explicit user preferences, verified facts, decisions, constraints, and reusable project context; do not store transient chat details or secrets. Use an expiry for temporary facts, and status=\'archived\' to soft-retire a record instead of deleting it. Save proactively in the same turn the information appears so other agents can use it immediately; do not defer to background compaction.","previous_description":"Store a durable, structured memory record for proactive semantic recall. Use namespace=\'facts\' for information that should surface in future conversations. Store explicit user preferences, verified facts, decisions, constraints, and reusable project context; do not store transient chat details or secrets. Use an expiry for temporary facts, and status=\'archived\' to soft-retire a record instead of deleting it.","params_added":[],"params_removed":[],"params_changed":[],"required_added":[],"required_removed":[]},{"name":"workflow_progress","change":"changed","description_changed":true,"description":"Report structured progress for a substantial multi-step task. Use only when the task has several dependent phases, likely spans turns, or needs explicit verification; skip simple tasks and work already covered by native tool progress. For agent-created workflows, send the full current items snapshot on every call and reuse the same workflow_id. Keep secrets and private data out of workflow fields. Mark items done only with observed validation evidence; use needs_attention for blockers; phase=complete requires every item done or skipped. A rejected update, or a step left checking or needs_atte…","previous_description":"Report structured progress for a substantial multi-step task. Use only when the task has several dependent phases, likely spans turns, or needs explicit verification; skip simple tasks and work already covered by native tool progress. For agent-created workflows, send the full current items snapshot on every call and reuse the same workflow_id. Keep secrets and private data out of workflow fields. Mark items done only with observed validation evidence; use needs_attention for blockers; phase=complete requires every item done or skipped. Every item needs input, expected output, and concrete va…","params_added":["needs_user"],"params_removed":[],"params_changed":[],"required_added":[],"required_removed":[]}]},{"version":"2.4.0","previous_version":"2.3.0","date":"2026-10-16","hints":["If an agent\'s instructions or skills tell it not to include links or URLs in replies, decide whether it should now cite sources with the provided `cite_as` and chat links.","If you listed `localhost` or `127.0.0.1` in the proxy bypass list only to reach local services, you can remove them; loopback is always direct now."],"commits":["fix(core): keep proxy loopback direct, unicode fact keys, agent tuning","fix(agents): avoid repeated compaction from bridge rows and topic pins","fix(core): keep per-chat backlog, permalink refs and code fences","fix(core): fix edge cases in edits, paging, bridges and pricing","feat(integrations): add source permalinks to mail, calendar, chats"],"prompts":[{"id":"static.agent.tool-usage-sop","source":"lib/agents/prepare/system-prompt.ts","change":"changed","added_lines":["10. Link the source. When your reply refers to a specific email, calendar event, or chat that a tool result or bridge message gave you, link it: paste the item\'s cite_as value verbatim when present, otherwise use its web_link, html_link, or chat_link URL as a markdown link. Use only links you were …"],"removed_lines":[],"omitted_lines":0},{"id":"system.Delivery channel","source":"lib/agents/prepare/system-prompt.ts","change":"changed","added_lines":["WhatsApp does not render markdown links: write any link as the bare URL, even where a cite_as value is given."],"removed_lines":[],"omitted_lines":0},{"id":"system.Tool usage SOP","source":"lib/agents/prepare/system-prompt.ts","change":"changed","added_lines":["10. Link the source. When your reply refers to a specific email, calendar event, or chat that a tool result or bridge message gave you, link it: paste the item\'s cite_as value verbatim when present, otherwise use its web_link, html_link, or chat_link URL as a markdown link. Use only links you were …"],"removed_lines":[],"omitted_lines":0}],"tools":[]}]}');
|
|
14367
14416
|
;// ./lib/lifecycle/changesets.ts
|
|
14368
14417
|
/**
|
|
14369
14418
|
* Bundled release changesets (docs/adoption/changesets.json), generated at
|
|
@@ -15451,6 +15500,8 @@ const compactContextTool = (0,tools/* tool */.z6)(async (_input, config)=>{
|
|
|
15451
15500
|
var default_packages = __webpack_require__(64611);
|
|
15452
15501
|
// EXTERNAL MODULE: ./lib/tools/communications/gmail.ts
|
|
15453
15502
|
var gmail = __webpack_require__(71941);
|
|
15503
|
+
// EXTERNAL MODULE: ./lib/utils/source-link.ts
|
|
15504
|
+
var source_link = __webpack_require__(76385);
|
|
15454
15505
|
// EXTERNAL MODULE: ./lib/integrations/gmail-oauth.ts
|
|
15455
15506
|
var gmail_oauth = __webpack_require__(7721);
|
|
15456
15507
|
;// ./lib/tools/communications/calendar.ts
|
|
@@ -15481,6 +15532,7 @@ var gmail_oauth = __webpack_require__(7721);
|
|
|
15481
15532
|
|
|
15482
15533
|
|
|
15483
15534
|
|
|
15535
|
+
|
|
15484
15536
|
const CALENDAR_BASE = "https://www.googleapis.com/calendar/v3";
|
|
15485
15537
|
const calendarFetch = (auth, path, init)=>(0,gmail_oauth/* googleFetch */.sI)(auth, "Calendar", CALENDAR_BASE, path, init);
|
|
15486
15538
|
const RFC3339_DATETIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
@@ -15503,7 +15555,8 @@ function slimEvent(e) {
|
|
|
15503
15555
|
response: a.responseStatus ?? null
|
|
15504
15556
|
})),
|
|
15505
15557
|
meet_link: e.hangoutLink ?? null,
|
|
15506
|
-
html_link: e.htmlLink ?? null
|
|
15558
|
+
html_link: e.htmlLink ?? null,
|
|
15559
|
+
cite_as: (0,source_link/* citeAs */.w)(e.summary, e.htmlLink, "Calendar event")
|
|
15507
15560
|
};
|
|
15508
15561
|
}
|
|
15509
15562
|
// ── Tools ───────────────────────────────────────────────────────────────────
|
|
@@ -15785,6 +15838,7 @@ var microsoft_oauth = __webpack_require__(46291);
|
|
|
15785
15838
|
|
|
15786
15839
|
|
|
15787
15840
|
|
|
15841
|
+
|
|
15788
15842
|
function outlook_calendar_slimEvent(e) {
|
|
15789
15843
|
return {
|
|
15790
15844
|
id: e.id,
|
|
@@ -15803,7 +15857,8 @@ function outlook_calendar_slimEvent(e) {
|
|
|
15803
15857
|
is_cancelled: e.isCancelled === true,
|
|
15804
15858
|
show_as: e.showAs ?? null,
|
|
15805
15859
|
teams_link: e.onlineMeeting?.joinUrl ?? null,
|
|
15806
|
-
web_link: e.webLink ?? null
|
|
15860
|
+
web_link: e.webLink ?? null,
|
|
15861
|
+
cite_as: (0,source_link/* citeAs */.w)(e.subject, e.webLink, "Outlook event")
|
|
15807
15862
|
};
|
|
15808
15863
|
}
|
|
15809
15864
|
// ── Tools ───────────────────────────────────────────────────────────────────
|
|
@@ -21782,12 +21837,17 @@ function upsertAgentConfigTransaction(input) {
|
|
|
21782
21837
|
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_0__/* .getDb */ .L)();
|
|
21783
21838
|
const existing = getAgentConfig(input.id);
|
|
21784
21839
|
const created_at = existing?.created_at ?? t;
|
|
21785
|
-
const
|
|
21840
|
+
const existingMbti = toMbti(existing?.adaptive_mbti);
|
|
21841
|
+
const mbti = input.adaptive_mbti ?? existingMbti ?? "INTJ";
|
|
21786
21842
|
const preset = _lib_agents_adaptive_persona_presets__WEBPACK_IMPORTED_MODULE_2__/* .MBTI_PRESETS */ .e[mbti];
|
|
21787
|
-
|
|
21788
|
-
|
|
21789
|
-
|
|
21790
|
-
const
|
|
21843
|
+
// Omitted sliders keep their tuned values; they only fall back to the
|
|
21844
|
+
// preset when the type changes or the agent is new. Otherwise every
|
|
21845
|
+
// partial update (approved proposals, tool edits) reset them.
|
|
21846
|
+
const keepTuned = existing !== null && existing !== undefined && mbti === existingMbti;
|
|
21847
|
+
const strength = input.adaptive_persona_strength ?? (keepTuned ? existing.adaptive_persona_strength : preset.strength);
|
|
21848
|
+
const empathy = input.adaptive_empathy ?? (keepTuned ? existing.adaptive_empathy : preset.empathy);
|
|
21849
|
+
const expressiveness = input.adaptive_expressiveness ?? (keepTuned ? existing.adaptive_expressiveness : preset.expressiveness);
|
|
21850
|
+
const verbosity = input.adaptive_verbosity ?? (keepTuned ? existing.adaptive_verbosity : preset.verbosity);
|
|
21791
21851
|
if (input.is_default) db.prepare("UPDATE agent_configs SET is_default=0").run();
|
|
21792
21852
|
// harness_id: explicit `undefined` means "keep existing"; explicit `null`
|
|
21793
21853
|
// means "use the global default". Empty string is normalised to null too,
|
|
@@ -22023,23 +22083,27 @@ async function readToolResultRef(args) {
|
|
|
22023
22083
|
}
|
|
22024
22084
|
const offset = Math.max(0, Math.floor(args.offset ?? 0));
|
|
22025
22085
|
const limit = Math.min(MAX_READ_BYTES, Math.max(1, Math.floor(args.limit ?? DEFAULT_PREVIEW_BYTES)));
|
|
22026
|
-
let buf;
|
|
22027
22086
|
try {
|
|
22028
22087
|
const file = await node_fs__WEBPACK_IMPORTED_MODULE_0__.promises.open(abs, "r");
|
|
22029
22088
|
try {
|
|
22030
22089
|
const stat = await file.stat();
|
|
22031
|
-
|
|
22032
|
-
|
|
22033
|
-
|
|
22034
|
-
const
|
|
22090
|
+
// Read a few bytes either side so the window can be moved onto UTF-8
|
|
22091
|
+
// character boundaries; paging must never split a multi-byte character.
|
|
22092
|
+
const windowStart = Math.min(Math.max(0, offset - 3), stat.size);
|
|
22093
|
+
const windowLength = Math.max(0, Math.min(stat.size - windowStart, offset - windowStart + limit + 3));
|
|
22094
|
+
const buf = Buffer.alloc(windowLength);
|
|
22095
|
+
if (windowLength > 0) await file.read(buf, 0, windowLength, windowStart);
|
|
22096
|
+
const { start, end } = utf8Window(buf, Math.min(offset, stat.size) - windowStart, limit);
|
|
22097
|
+
const actualOffset = windowStart + start;
|
|
22098
|
+
const nextOffset = windowStart + end;
|
|
22035
22099
|
return {
|
|
22036
22100
|
ok: true,
|
|
22037
22101
|
status: "done",
|
|
22038
22102
|
name: args.name,
|
|
22039
|
-
offset,
|
|
22103
|
+
offset: actualOffset,
|
|
22040
22104
|
limit,
|
|
22041
22105
|
bytes: stat.size,
|
|
22042
|
-
result: buf.toString("utf8"),
|
|
22106
|
+
result: buf.subarray(start, end).toString("utf8"),
|
|
22043
22107
|
next_offset: nextOffset < stat.size ? nextOffset : null,
|
|
22044
22108
|
done: nextOffset >= stat.size
|
|
22045
22109
|
};
|
|
@@ -22055,6 +22119,26 @@ async function readToolResultRef(args) {
|
|
|
22055
22119
|
};
|
|
22056
22120
|
}
|
|
22057
22121
|
}
|
|
22122
|
+
const isUtf8Continuation = (byte)=>byte !== undefined && (byte & 0xc0) === 0x80;
|
|
22123
|
+
// Moves `[start, start + limit)` inside `buf` onto character boundaries: the
|
|
22124
|
+
// start backs up to its lead byte, and the end backs up so it does not cut a
|
|
22125
|
+
// character — unless that character alone exceeds `limit`, in which case the
|
|
22126
|
+
// whole character is returned so paging always makes progress.
|
|
22127
|
+
function utf8Window(buf, start, limit) {
|
|
22128
|
+
let s = Math.max(0, Math.min(start, buf.length));
|
|
22129
|
+
while(s > 0 && isUtf8Continuation(buf[s]))s--;
|
|
22130
|
+
let e = Math.min(buf.length, s + limit);
|
|
22131
|
+
if (e < buf.length && isUtf8Continuation(buf[e])) {
|
|
22132
|
+
let lead = e;
|
|
22133
|
+
while(lead > s && isUtf8Continuation(buf[lead]))lead--;
|
|
22134
|
+
if (lead > s) e = lead;
|
|
22135
|
+
else while(e < buf.length && isUtf8Continuation(buf[e]))e++;
|
|
22136
|
+
}
|
|
22137
|
+
return {
|
|
22138
|
+
start: s,
|
|
22139
|
+
end: e
|
|
22140
|
+
};
|
|
22141
|
+
}
|
|
22058
22142
|
function serializeToolResult(result) {
|
|
22059
22143
|
if (typeof result === "string") return result;
|
|
22060
22144
|
return JSON.stringify(result) ?? String(result);
|
|
@@ -22072,10 +22156,21 @@ function buildPreview(value, mimeType) {
|
|
|
22072
22156
|
try {
|
|
22073
22157
|
const parsed = JSON.parse(value);
|
|
22074
22158
|
if (Array.isArray(parsed)) {
|
|
22075
|
-
|
|
22159
|
+
// Cap by bytes as well as items: a few huge rows must not smuggle the
|
|
22160
|
+
// whole result back inline.
|
|
22161
|
+
for(let n = Math.min(parsed.length, JSON_ARRAY_PREVIEW_ITEMS); n > 0; n--){
|
|
22162
|
+
const preview = parsed.slice(0, n);
|
|
22163
|
+
const bytes = Buffer.byteLength(JSON.stringify(preview));
|
|
22164
|
+
if (bytes <= DEFAULT_PREVIEW_BYTES) return {
|
|
22165
|
+
value: preview,
|
|
22166
|
+
bytes,
|
|
22167
|
+
total_count: parsed.length
|
|
22168
|
+
};
|
|
22169
|
+
}
|
|
22170
|
+
const text = takeUtf8Prefix(value, DEFAULT_PREVIEW_BYTES);
|
|
22076
22171
|
return {
|
|
22077
|
-
value:
|
|
22078
|
-
bytes: Buffer.byteLength(
|
|
22172
|
+
value: text,
|
|
22173
|
+
bytes: Buffer.byteLength(text),
|
|
22079
22174
|
total_count: parsed.length
|
|
22080
22175
|
};
|
|
22081
22176
|
}
|
|
@@ -22098,6 +22193,8 @@ function takeUtf8Prefix(value, maxBytes) {
|
|
|
22098
22193
|
if (Buffer.byteLength(value.slice(0, mid)) <= maxBytes) lo = mid;
|
|
22099
22194
|
else hi = mid - 1;
|
|
22100
22195
|
}
|
|
22196
|
+
const code = value.charCodeAt(lo - 1);
|
|
22197
|
+
if (lo > 0 && code >= 0xd800 && code <= 0xdbff) lo--;
|
|
22101
22198
|
return value.slice(0, lo);
|
|
22102
22199
|
}
|
|
22103
22200
|
function safeToolName(name) {
|
|
@@ -23830,7 +23927,7 @@ var external_node_os_ = __webpack_require__(48161);
|
|
|
23830
23927
|
var external_node_path_ = __webpack_require__(76760);
|
|
23831
23928
|
var external_node_path_default = /*#__PURE__*/__webpack_require__.n(external_node_path_);
|
|
23832
23929
|
// EXTERNAL MODULE: ./node_modules/@langchain/core/dist/tools/index.js
|
|
23833
|
-
var tools = __webpack_require__(
|
|
23930
|
+
var tools = __webpack_require__(71966);
|
|
23834
23931
|
// EXTERNAL MODULE: ./node_modules/zod/v4/classic/schemas.js + 4 modules
|
|
23835
23932
|
var schemas = __webpack_require__(17033);
|
|
23836
23933
|
// EXTERNAL MODULE: ./lib/stores/integrations.ts
|
|
@@ -26018,8 +26115,21 @@ const MEMORY_WRITE_NAMESPACES = new Set([
|
|
|
26018
26115
|
function rowsInRange(rows, topic) {
|
|
26019
26116
|
return rows.filter((row)=>row.seq >= (topic.start_seq ?? Infinity) && row.seq <= (topic.end_seq ?? -Infinity));
|
|
26020
26117
|
}
|
|
26118
|
+
// Unicode-aware so non-Latin subjects get distinct keys; an ASCII-only slug
|
|
26119
|
+
// collapsed them all to "" and the uplift skipped them. Subjects with no
|
|
26120
|
+
// letters or digits fall back to a stable hash.
|
|
26021
26121
|
function slugifyForMemoryKey(subject) {
|
|
26022
|
-
|
|
26122
|
+
const slug = subject.normalize("NFC").toLowerCase().replace(/[^\p{L}\p{M}\p{N}]+/gu, "-").replace(/^-+|-+$/g, "");
|
|
26123
|
+
const capped = Array.from(slug).slice(0, 80).join("").replace(/-+$/, "");
|
|
26124
|
+
return capped || `fact-${fnv1a(subject)}`;
|
|
26125
|
+
}
|
|
26126
|
+
function fnv1a(text) {
|
|
26127
|
+
let hash = 0x811c9dc5;
|
|
26128
|
+
for(let i = 0; i < text.length; i++){
|
|
26129
|
+
hash ^= text.charCodeAt(i);
|
|
26130
|
+
hash = Math.imul(hash, 0x01000193);
|
|
26131
|
+
}
|
|
26132
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
26023
26133
|
}
|
|
26024
26134
|
/**
|
|
26025
26135
|
* Merge facts by subject (case-insensitive) and memory key. Later entries win,
|
|
@@ -26031,9 +26141,18 @@ function slugifyForMemoryKey(subject) {
|
|
|
26031
26141
|
for (const list of lists){
|
|
26032
26142
|
for (const fact of list){
|
|
26033
26143
|
const subjectId = fact.subject.trim().toLowerCase();
|
|
26034
|
-
const
|
|
26035
|
-
|
|
26036
|
-
|
|
26144
|
+
const sameKeySubject = fact.key ? keyToSubject.get(fact.key) : undefined;
|
|
26145
|
+
for (const replaced of [
|
|
26146
|
+
sameKeySubject,
|
|
26147
|
+
subjectId
|
|
26148
|
+
]){
|
|
26149
|
+
if (replaced === undefined) continue;
|
|
26150
|
+
// Drop the replaced fact's key mapping too, so a later fact reusing
|
|
26151
|
+
// that key cannot delete whatever now lives under this subject.
|
|
26152
|
+
const previousKey = merged.get(replaced)?.key;
|
|
26153
|
+
if (previousKey) keyToSubject.delete(previousKey);
|
|
26154
|
+
merged.delete(replaced);
|
|
26155
|
+
}
|
|
26037
26156
|
merged.set(subjectId, fact);
|
|
26038
26157
|
if (fact.key) keyToSubject.set(fact.key, subjectId);
|
|
26039
26158
|
}
|
|
@@ -29572,7 +29691,7 @@ function truncateBytes(s, maxBytes) {
|
|
|
29572
29691
|
/* harmony export */ });
|
|
29573
29692
|
/* unused harmony exports DEFAULT_MAX_DEADLINE_MS, getMaxDeadlineMs, __DEFAULT_DEADLINE_MS */
|
|
29574
29693
|
/* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(17033);
|
|
29575
|
-
/* harmony import */ var _langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
|
|
29694
|
+
/* harmony import */ var _langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(71966);
|
|
29576
29695
|
/* harmony import */ var _async_results__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(68182);
|
|
29577
29696
|
/* harmony import */ var _tool_metadata__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(48271);
|
|
29578
29697
|
/* harmony import */ var _result_refs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(26481);
|
|
@@ -29862,14 +29981,15 @@ function stripWrapperFields(args) {
|
|
|
29862
29981
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
29863
29982
|
/* harmony export */ Wz: () => (/* binding */ _resolveGmailAuth)
|
|
29864
29983
|
/* harmony export */ });
|
|
29865
|
-
/* unused harmony exports buildRawMessage, gmailSearchTool, gmailGetMessageTool, gmailListLabelsTool, gmailModifyMessageTool, gmailCreateDraftTool, gmailSendEmailTool, gmailTrashMessageTool */
|
|
29866
|
-
/* harmony import */ var _langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(
|
|
29867
|
-
/* harmony import */ var
|
|
29984
|
+
/* unused harmony exports gmailWebLink, buildRawMessage, gmailSearchTool, gmailGetMessageTool, gmailListLabelsTool, gmailModifyMessageTool, gmailCreateDraftTool, gmailSendEmailTool, gmailTrashMessageTool */
|
|
29985
|
+
/* harmony import */ var _langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(71966);
|
|
29986
|
+
/* harmony import */ var zod__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(17033);
|
|
29868
29987
|
/* harmony import */ var _lib_utils_html__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(85212);
|
|
29869
|
-
/* harmony import */ var
|
|
29988
|
+
/* harmony import */ var _lib_utils_text__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(69494);
|
|
29870
29989
|
/* harmony import */ var _packages_langchain_package__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(18932);
|
|
29871
29990
|
/* harmony import */ var _lib_integrations_gmail_oauth__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7721);
|
|
29872
29991
|
/* harmony import */ var _lib_utils_error__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4379);
|
|
29992
|
+
/* harmony import */ var _lib_utils_source_link__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(76385);
|
|
29873
29993
|
/**
|
|
29874
29994
|
* Native Gmail tools — direct REST API calls to gmail.googleapis.com, no MCP.
|
|
29875
29995
|
*
|
|
@@ -29897,6 +30017,7 @@ function stripWrapperFields(args) {
|
|
|
29897
30017
|
|
|
29898
30018
|
|
|
29899
30019
|
|
|
30020
|
+
|
|
29900
30021
|
// Exposed for the integrations test endpoint.
|
|
29901
30022
|
function _resolveGmailAuth() {
|
|
29902
30023
|
return (0,_lib_integrations_gmail_oauth__WEBPACK_IMPORTED_MODULE_2__/* .resolveGoogleAuth */ .wq)();
|
|
@@ -29921,6 +30042,31 @@ function resolveGmailAuthForTool() {
|
|
|
29921
30042
|
};
|
|
29922
30043
|
}
|
|
29923
30044
|
}
|
|
30045
|
+
// ── Source links ────────────────────────────────────────────────────────────
|
|
30046
|
+
// Gmail's web URL scheme is undocumented. `#all/<threadId>` opens the
|
|
30047
|
+
// conversation from All Mail whatever its labels, and `/u/<email>/` selects
|
|
30048
|
+
// the signed-in account (`/u/0/` is whichever account signed in first).
|
|
30049
|
+
const GMAIL_API_ID = /^[0-9a-f]{8,32}$/i;
|
|
30050
|
+
function gmailWebLink(threadId, account) {
|
|
30051
|
+
if (!threadId || !GMAIL_API_ID.test(threadId)) return null;
|
|
30052
|
+
const slot = account ? encodeURIComponent(account) : "0";
|
|
30053
|
+
return `https://mail.google.com/mail/u/${slot}/#all/${threadId}`;
|
|
30054
|
+
}
|
|
30055
|
+
const accountEmailCache = new Map();
|
|
30056
|
+
// getProfile works with every Gmail scope; a failure only drops the account
|
|
30057
|
+
// from the link, so it is not retried within the process.
|
|
30058
|
+
function gmailAccountEmail(auth) {
|
|
30059
|
+
const key = auth.refresh_token.slice(0, 20);
|
|
30060
|
+
let pending = accountEmailCache.get(key);
|
|
30061
|
+
if (!pending) {
|
|
30062
|
+
pending = gmailFetch(auth, "/profile").then((p)=>{
|
|
30063
|
+
const email = p.emailAddress;
|
|
30064
|
+
return typeof email === "string" && email.includes("@") ? email : null;
|
|
30065
|
+
}).catch(()=>null);
|
|
30066
|
+
accountEmailCache.set(key, pending);
|
|
30067
|
+
}
|
|
30068
|
+
return pending;
|
|
30069
|
+
}
|
|
29924
30070
|
// ── Decoders / helpers ──────────────────────────────────────────────────────
|
|
29925
30071
|
// Gmail uses base64url (no padding, +/ → -_). Node's Buffer handles it directly.
|
|
29926
30072
|
function decodeBase64Url(s) {
|
|
@@ -29993,6 +30139,7 @@ const gmailSearchTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/*
|
|
|
29993
30139
|
messages: []
|
|
29994
30140
|
});
|
|
29995
30141
|
}
|
|
30142
|
+
const account = await gmailAccountEmail(auth);
|
|
29996
30143
|
// Parallel metadata fetch; the API recommends batching but for ≤100 ids
|
|
29997
30144
|
// parallel single calls are simpler and well within quota.
|
|
29998
30145
|
const details = await Promise.all(ids.map(async (id)=>{
|
|
@@ -30001,15 +30148,19 @@ const gmailSearchTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/*
|
|
|
30001
30148
|
id,
|
|
30002
30149
|
error: m.error
|
|
30003
30150
|
};
|
|
30151
|
+
const subject = header(m.payload?.headers, "Subject");
|
|
30152
|
+
const webLink = gmailWebLink(m.threadId, account);
|
|
30004
30153
|
return {
|
|
30005
30154
|
id: m.id,
|
|
30006
30155
|
thread_id: m.threadId,
|
|
30007
30156
|
from: header(m.payload?.headers, "From"),
|
|
30008
30157
|
to: header(m.payload?.headers, "To"),
|
|
30009
|
-
subject
|
|
30158
|
+
subject,
|
|
30010
30159
|
date: header(m.payload?.headers, "Date"),
|
|
30011
30160
|
snippet: m.snippet ?? null,
|
|
30012
|
-
labels: m.labelIds ?? []
|
|
30161
|
+
labels: m.labelIds ?? [],
|
|
30162
|
+
web_link: webLink,
|
|
30163
|
+
cite_as: (0,_lib_utils_source_link__WEBPACK_IMPORTED_MODULE_5__/* .citeAs */ .w)(subject, webLink, "Gmail message")
|
|
30013
30164
|
};
|
|
30014
30165
|
}));
|
|
30015
30166
|
return JSON.stringify({
|
|
@@ -30021,9 +30172,9 @@ const gmailSearchTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/*
|
|
|
30021
30172
|
}, {
|
|
30022
30173
|
name: "gmail_search",
|
|
30023
30174
|
description: "Search the user's Gmail with Gmail query syntax. Returns message metadata (from, to, subject, " + "date, snippet, labels) plus Gmail's resultSizeEstimate and next page token so '1 result' " + "doesn't get mistaken for '1 unread email'. Examples: 'is:unread newer_than:1d', " + "'from:notifications@github.com', 'subject:invoice has:attachment', 'in:inbox -category:promotions'. " + "Use this before calling gmail_get_message — the snippet is often enough.",
|
|
30024
|
-
schema:
|
|
30025
|
-
query:
|
|
30026
|
-
max_results:
|
|
30175
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_6__/* .object */ .Ikc({
|
|
30176
|
+
query: zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP().describe("Gmail query string"),
|
|
30177
|
+
max_results: zod__WEBPACK_IMPORTED_MODULE_6__/* .number */ .aig().int().optional().describe("Max messages (default 25, max 100)")
|
|
30027
30178
|
})
|
|
30028
30179
|
});
|
|
30029
30180
|
const gmailGetMessageTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/* .tool */ .z6)(async ({ id })=>{
|
|
@@ -30032,15 +30183,19 @@ const gmailGetMessageTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0_
|
|
|
30032
30183
|
const m = await gmailFetch(auth, `/messages/${encodeURIComponent(id)}?format=full`);
|
|
30033
30184
|
if (m.error) return JSON.stringify(m);
|
|
30034
30185
|
const body = extractBody(m.payload);
|
|
30035
|
-
const { text: capped, truncated } = (0,
|
|
30186
|
+
const { text: capped, truncated } = (0,_lib_utils_text__WEBPACK_IMPORTED_MODULE_7__/* .truncateBytes */ .Q)(body, MAX_BODY_BYTES);
|
|
30187
|
+
const subject = header(m.payload?.headers, "Subject");
|
|
30188
|
+
const webLink = gmailWebLink(m.threadId, await gmailAccountEmail(auth));
|
|
30036
30189
|
return JSON.stringify({
|
|
30037
30190
|
id: m.id,
|
|
30038
30191
|
thread_id: m.threadId,
|
|
30192
|
+
web_link: webLink,
|
|
30193
|
+
cite_as: (0,_lib_utils_source_link__WEBPACK_IMPORTED_MODULE_5__/* .citeAs */ .w)(subject, webLink, "Gmail message"),
|
|
30039
30194
|
labels: m.labelIds ?? [],
|
|
30040
30195
|
from: header(m.payload?.headers, "From"),
|
|
30041
30196
|
to: header(m.payload?.headers, "To"),
|
|
30042
30197
|
cc: header(m.payload?.headers, "Cc"),
|
|
30043
|
-
subject
|
|
30198
|
+
subject,
|
|
30044
30199
|
date: header(m.payload?.headers, "Date"),
|
|
30045
30200
|
message_id: header(m.payload?.headers, "Message-Id") ?? header(m.payload?.headers, "Message-ID"),
|
|
30046
30201
|
snippet: m.snippet ?? null,
|
|
@@ -30050,8 +30205,8 @@ const gmailGetMessageTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0_
|
|
|
30050
30205
|
}, {
|
|
30051
30206
|
name: "gmail_get_message",
|
|
30052
30207
|
description: "Fetch one Gmail message by id, including full headers and the decoded text body (text/plain " + "preferred, HTML stripped if only HTML is available). Body capped at 30KB with `truncated:true` " + "when cut off.",
|
|
30053
|
-
schema:
|
|
30054
|
-
id:
|
|
30208
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_6__/* .object */ .Ikc({
|
|
30209
|
+
id: zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP().describe("Gmail message id (from gmail_search results)")
|
|
30055
30210
|
})
|
|
30056
30211
|
});
|
|
30057
30212
|
const gmailListLabelsTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/* .tool */ .z6)(async ()=>{
|
|
@@ -30069,7 +30224,7 @@ const gmailListLabelsTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0_
|
|
|
30069
30224
|
}, {
|
|
30070
30225
|
name: "gmail_list_labels",
|
|
30071
30226
|
description: "List all Gmail labels (system + user). System label ids are uppercase (INBOX, UNREAD, " + "STARRED, IMPORTANT, SPAM, TRASH, SENT, DRAFT, CATEGORY_*). User labels have lowercase " + "alphanumeric ids like 'Label_42'. Use the id values with gmail_modify_message.",
|
|
30072
|
-
schema:
|
|
30227
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_6__/* .object */ .Ikc({})
|
|
30073
30228
|
});
|
|
30074
30229
|
const gmailModifyMessageTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/* .tool */ .z6)(async ({ id, add_labels, remove_labels })=>{
|
|
30075
30230
|
const auth = resolveGmailAuthForTool();
|
|
@@ -30095,10 +30250,10 @@ const gmailModifyMessageTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE
|
|
|
30095
30250
|
}, {
|
|
30096
30251
|
name: "gmail_modify_message",
|
|
30097
30252
|
description: "Add or remove labels on a Gmail message. Common patterns: " + "archive = remove_labels=['INBOX']; mark read = remove_labels=['UNREAD']; " + "star = add_labels=['STARRED']; mark important = add_labels=['IMPORTANT']. " + "Use gmail_list_labels first if you don't know a user label id.",
|
|
30098
|
-
schema:
|
|
30099
|
-
id:
|
|
30100
|
-
add_labels:
|
|
30101
|
-
remove_labels:
|
|
30253
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_6__/* .object */ .Ikc({
|
|
30254
|
+
id: zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP().describe("Gmail message id"),
|
|
30255
|
+
add_labels: zod__WEBPACK_IMPORTED_MODULE_6__/* .array */ .YOg(zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP()).optional().describe("Label ids to add"),
|
|
30256
|
+
remove_labels: zod__WEBPACK_IMPORTED_MODULE_6__/* .array */ .YOg(zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP()).optional().describe("Label ids to remove")
|
|
30102
30257
|
})
|
|
30103
30258
|
});
|
|
30104
30259
|
const gmailCreateDraftTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/* .tool */ .z6)(async ({ to, cc, bcc, subject, body, content_type, in_reply_to_id })=>{
|
|
@@ -30153,17 +30308,17 @@ const gmailCreateDraftTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0
|
|
|
30153
30308
|
}, {
|
|
30154
30309
|
name: "gmail_create_draft",
|
|
30155
30310
|
description: "Create a Gmail draft. Prefer drafts unless the user explicitly asks to send immediately. " + "`content_type` defaults to 'text'; pass 'html' if `body` contains HTML markup. " + "When replying to an existing message, pass `in_reply_to_id` (the parent " + "message id from gmail_search/gmail_get_message) — the tool will set Message-Id/References/" + "threadId so the draft appears inside the right Gmail thread.",
|
|
30156
|
-
schema:
|
|
30157
|
-
to:
|
|
30158
|
-
cc:
|
|
30159
|
-
bcc:
|
|
30160
|
-
subject:
|
|
30161
|
-
body:
|
|
30162
|
-
content_type:
|
|
30311
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_6__/* .object */ .Ikc({
|
|
30312
|
+
to: zod__WEBPACK_IMPORTED_MODULE_6__/* .array */ .YOg(zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP()).describe("Recipient email addresses"),
|
|
30313
|
+
cc: zod__WEBPACK_IMPORTED_MODULE_6__/* .array */ .YOg(zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP()).optional(),
|
|
30314
|
+
bcc: zod__WEBPACK_IMPORTED_MODULE_6__/* .array */ .YOg(zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP()).optional(),
|
|
30315
|
+
subject: zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP(),
|
|
30316
|
+
body: zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP().max(DRAFT_BODY_MAX_CHARS).describe("Email body (max 100,000 characters)"),
|
|
30317
|
+
content_type: zod__WEBPACK_IMPORTED_MODULE_6__/* ["enum"] */ .k5n([
|
|
30163
30318
|
"text",
|
|
30164
30319
|
"html"
|
|
30165
30320
|
]).optional().describe("Body content type (default 'text')"),
|
|
30166
|
-
in_reply_to_id:
|
|
30321
|
+
in_reply_to_id: zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP().optional().describe("Gmail message id to reply to (for threading)")
|
|
30167
30322
|
})
|
|
30168
30323
|
});
|
|
30169
30324
|
const gmailSendEmailTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/* .tool */ .z6)(async ({ to, cc, bcc, subject, body, content_type, in_reply_to_id })=>{
|
|
@@ -30213,17 +30368,17 @@ const gmailSendEmailTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__
|
|
|
30213
30368
|
}, {
|
|
30214
30369
|
name: "gmail_send_email",
|
|
30215
30370
|
description: "Send a Gmail email immediately. Only use when the user explicitly asks to send now; " + "otherwise create a draft with gmail_create_draft. Supports text or HTML bodies via `content_type`. " + "When replying, pass `in_reply_to_id` so Gmail threads the sent message correctly.",
|
|
30216
|
-
schema:
|
|
30217
|
-
to:
|
|
30218
|
-
cc:
|
|
30219
|
-
bcc:
|
|
30220
|
-
subject:
|
|
30221
|
-
body:
|
|
30222
|
-
content_type:
|
|
30371
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_6__/* .object */ .Ikc({
|
|
30372
|
+
to: zod__WEBPACK_IMPORTED_MODULE_6__/* .array */ .YOg(zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP()).min(1).describe("Recipient email addresses"),
|
|
30373
|
+
cc: zod__WEBPACK_IMPORTED_MODULE_6__/* .array */ .YOg(zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP()).optional(),
|
|
30374
|
+
bcc: zod__WEBPACK_IMPORTED_MODULE_6__/* .array */ .YOg(zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP()).optional(),
|
|
30375
|
+
subject: zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP(),
|
|
30376
|
+
body: zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP().max(SEND_BODY_MAX_CHARS).describe("Email body (max 100,000 characters)"),
|
|
30377
|
+
content_type: zod__WEBPACK_IMPORTED_MODULE_6__/* ["enum"] */ .k5n([
|
|
30223
30378
|
"text",
|
|
30224
30379
|
"html"
|
|
30225
30380
|
]).optional().describe("Body content type (default 'text')"),
|
|
30226
|
-
in_reply_to_id:
|
|
30381
|
+
in_reply_to_id: zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP().optional().describe("Gmail message id to reply to (for threading)")
|
|
30227
30382
|
})
|
|
30228
30383
|
});
|
|
30229
30384
|
const gmailTrashMessageTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_0__/* .tool */ .z6)(async ({ id })=>{
|
|
@@ -30241,8 +30396,8 @@ const gmailTrashMessageTool = (0,_langchain_core_tools__WEBPACK_IMPORTED_MODULE_
|
|
|
30241
30396
|
}, {
|
|
30242
30397
|
name: "gmail_trash_message",
|
|
30243
30398
|
description: "Move a Gmail message to Trash (reversible for 30 days, not permanent delete). Only call this " + "when the user has explicitly asked to trash/delete a message — never on your own initiative " + "as part of a triage flow. Prefer gmail_modify_message remove_labels=['INBOX'] to archive.",
|
|
30244
|
-
schema:
|
|
30245
|
-
id:
|
|
30399
|
+
schema: zod__WEBPACK_IMPORTED_MODULE_6__/* .object */ .Ikc({
|
|
30400
|
+
id: zod__WEBPACK_IMPORTED_MODULE_6__/* .string */ .YjP().describe("Gmail message id")
|
|
30246
30401
|
})
|
|
30247
30402
|
});
|
|
30248
30403
|
(0,_packages_langchain_package__WEBPACK_IMPORTED_MODULE_1__/* .registerLangChainPackage */ .p)({
|
|
@@ -31422,6 +31577,51 @@ async function indexAllSources(opts) {
|
|
|
31422
31577
|
}
|
|
31423
31578
|
|
|
31424
31579
|
|
|
31580
|
+
/***/ }),
|
|
31581
|
+
|
|
31582
|
+
/***/ 76385:
|
|
31583
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
31584
|
+
|
|
31585
|
+
"use strict";
|
|
31586
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
31587
|
+
/* harmony export */ w: () => (/* binding */ citeAs)
|
|
31588
|
+
/* harmony export */ });
|
|
31589
|
+
/* unused harmony export httpsUrlOrNull */
|
|
31590
|
+
/**
|
|
31591
|
+
* Source-link fields for tool results, so an agent can link a reply back to
|
|
31592
|
+
* the email, calendar event, or chat it came from without building URLs.
|
|
31593
|
+
*
|
|
31594
|
+
* `cite_as` is a ready-made markdown link the system prompt tells agents to
|
|
31595
|
+
* paste verbatim. Building it in code keeps the label and URL well-formed:
|
|
31596
|
+
* a stray `]` in a subject or `)` in a URL would otherwise break the link.
|
|
31597
|
+
*/ const MAX_LABEL_CHARS = 80;
|
|
31598
|
+
/** Returns `url` when it is an absolute https URL, otherwise null. */ function httpsUrlOrNull(url) {
|
|
31599
|
+
if (!url) return null;
|
|
31600
|
+
try {
|
|
31601
|
+
const parsed = new URL(url);
|
|
31602
|
+
return parsed.protocol === "https:" ? parsed.href : null;
|
|
31603
|
+
} catch {
|
|
31604
|
+
return null;
|
|
31605
|
+
}
|
|
31606
|
+
}
|
|
31607
|
+
function markdownLabel(label, fallback) {
|
|
31608
|
+
const flat = (label ?? "").replace(/\s+/g, " ").trim();
|
|
31609
|
+
const capped = flat.length > MAX_LABEL_CHARS ? `${flat.slice(0, MAX_LABEL_CHARS - 1).trimEnd()}…` : flat;
|
|
31610
|
+
return (capped || fallback).replace(/[\\[\]]/g, (c)=>`\\${c}`);
|
|
31611
|
+
}
|
|
31612
|
+
function markdownDestination(url) {
|
|
31613
|
+
return url.replace(/[()\s<>]/g, (c)=>`%${c.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`);
|
|
31614
|
+
}
|
|
31615
|
+
/**
|
|
31616
|
+
* Pre-built markdown link for `cite_as`, or null when there is no usable URL.
|
|
31617
|
+
* Only https URLs qualify: the chat renderer drops other schemes.
|
|
31618
|
+
*/ function citeAs(label, url, fallbackLabel = "source") {
|
|
31619
|
+
const safe = httpsUrlOrNull(url);
|
|
31620
|
+
if (!safe) return null;
|
|
31621
|
+
return `[${markdownLabel(label, fallbackLabel)}](${markdownDestination(safe)})`;
|
|
31622
|
+
}
|
|
31623
|
+
|
|
31624
|
+
|
|
31425
31625
|
/***/ }),
|
|
31426
31626
|
|
|
31427
31627
|
/***/ 82703:
|
|
@@ -32138,7 +32338,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
32138
32338
|
IC: () => (/* binding */ withInterruptMarker)
|
|
32139
32339
|
});
|
|
32140
32340
|
|
|
32141
|
-
// UNUSED EXPORTS: INTERRUPT_MARKER, MAX_RATE_LIMIT_RETRY_AFTER_MS, RunThreadError, appendHistoryMessage, buildFabricationNudge, buildRetryContextSummary, contentText, isHotContextNearBudget, looksLikeStall, persistThreadRunUserMessage, rateLimitRetryDelayMs, retryTextOverlapRatio, shouldEmitChunk, shouldRetryTransientError, toolCallSignature, transientRetryDelayMs
|
|
32341
|
+
// UNUSED EXPORTS: INTERRUPT_MARKER, MAX_RATE_LIMIT_RETRY_AFTER_MS, RunThreadError, appendHistoryMessage, buildFabricationNudge, buildRetryContextSummary, contentText, hotTurnCooldownUntil, isHotContextNearBudget, looksLikeStall, persistThreadRunUserMessage, rateLimitRetryDelayMs, retryTextOverlapRatio, shouldEmitChunk, shouldRetryTransientError, toolCallSignature, transientRetryDelayMs
|
|
32142
32342
|
|
|
32143
32343
|
// EXTERNAL MODULE: ./lib/agents/action-vocabulary.ts
|
|
32144
32344
|
var action_vocabulary = __webpack_require__(56033);
|
|
@@ -35867,7 +36067,8 @@ function buildSharedToolCatalogContext() {
|
|
|
35867
36067
|
"6. Read large results by reference. A tool result with truncated=true is only a preview; do not treat it as complete. Use result_ref.name with tool_result_get and offset/limit to read only the slice you need.",
|
|
35868
36068
|
"7. Verify before reporting. A read-only result does not prove a new write. Claim a new write, send, schedule, delete, or configuration change only after the matching state-changing tool returns success in this turn. Trusted runtime system signals and their matching retrieved results can substantiate earlier named operations; attribute those outcomes to their receipts, never imply a new action or repeat completed work for proof.",
|
|
35869
36069
|
"8. Stop and ask. Do not retry a tool denied for agent_not_allowed, category_disabled, dropin_tool_disabled, credentials_missing or integration_unconfigured. The first three are permission decisions and the last two mean the integration is not set up \u2014 propose a configuration change or tell the user what to configure.",
|
|
35870
|
-
"9. Completion-reporting turns are read-only. permission_reason=signal_continuation_read_only forbids state-changing tools in this turn, including through invoke_tool. Do not bypass it with shell commands or treat an old user message as renewed permission; report the completed outcome and wait for a new user turn."
|
|
36070
|
+
"9. Completion-reporting turns are read-only. permission_reason=signal_continuation_read_only forbids state-changing tools in this turn, including through invoke_tool. Do not bypass it with shell commands or treat an old user message as renewed permission; report the completed outcome and wait for a new user turn.",
|
|
36071
|
+
"10. Link the source. When your reply refers to a specific email, calendar event, or chat that a tool result or bridge message gave you, link it: paste the item's cite_as value verbatim when present, otherwise use its web_link, html_link, or chat_link URL as a markdown link. Use only links you were given; never construct, guess, or edit one. If the item has no link, name it without one."
|
|
35871
36072
|
].join("\n");
|
|
35872
36073
|
}
|
|
35873
36074
|
function compareToolPermissionEntries(a, b) {
|
|
@@ -35947,9 +36148,14 @@ function buildDeliveryChannelContext(channel) {
|
|
|
35947
36148
|
return [
|
|
35948
36149
|
"--- Delivery channel ---",
|
|
35949
36150
|
`This message reached you over ${platform}${named}, not the regular chat UI.`,
|
|
35950
|
-
`You DO have access to ${platform} for this conversation: any reply you produce is sent back through that channel automatically. Do not tell the user the platform is unavailable; just answer the message
|
|
35951
|
-
|
|
36151
|
+
`You DO have access to ${platform} for this conversation: any reply you produce is sent back through that channel automatically. Do not tell the user the platform is unavailable; just answer the message.`,
|
|
36152
|
+
PLAIN_TEXT_DELIVERY_KINDS.has(channel.kind) ? `${platform} does not render markdown links: write any link as the bare URL, even where a cite_as value is given.` : ""
|
|
36153
|
+
].filter(Boolean).join("\n");
|
|
35952
36154
|
}
|
|
36155
|
+
const PLAIN_TEXT_DELIVERY_KINDS = new Set([
|
|
36156
|
+
"whatsapp",
|
|
36157
|
+
"sms"
|
|
36158
|
+
]);
|
|
35953
36159
|
function buildUserContext() {
|
|
35954
36160
|
const userProfile = (0,user_profile/* getUserProfile */.VM)();
|
|
35955
36161
|
const parts = [];
|
|
@@ -36033,7 +36239,7 @@ function buildSourceLinkContext(agent, manifest) {
|
|
|
36033
36239
|
"--- Citation format ---",
|
|
36034
36240
|
intro,
|
|
36035
36241
|
"PRIMARY (inline links): cite by writing a standard markdown link inline: `[short label](https://example.com/path)` or `[file name](/abs/path.ts)` or `[earlier reply](#msg-<id>)`. Wrap the cited PHRASE itself as the link text when natural — `Jade has [ice skating at 16:00](?thread=…&agent=…)` reads better than a trailing `[1]`.",
|
|
36036
|
-
"When a tool result contains a `cite_as` field (delegate_to_agent does, and so do
|
|
36242
|
+
"When a tool result contains a `cite_as` field (delegate_to_agent does, and so do the email and calendar tools), paste that exact value somewhere in your reply — it's a pre-built markdown link to the source. Anything you summarize from a delegate or from a web/file tool result MUST carry at least one inline link back to where it came from; a summary with zero links reads as if you made the facts up.",
|
|
36037
36243
|
"For web_search / fetch_webpage results, the URL is right there in the tool output — use it: `[headline or short label](https://...)`. For file_read results, link the absolute path: `[filename.ext](/abs/path/filename.ext)`.",
|
|
36038
36244
|
"FALLBACK (declared refs block): if a source is awkward to cite inline (e.g. you summarized 4 articles in one paragraph), you MAY end your reply with a fenced block exactly like this:",
|
|
36039
36245
|
"```jarela-references",
|
|
@@ -36532,17 +36738,27 @@ const SOURCE_PRODUCING_TOOLS_RESULT = new Set([
|
|
|
36532
36738
|
"fetch_webpage",
|
|
36533
36739
|
"web_fetch"
|
|
36534
36740
|
]);
|
|
36535
|
-
|
|
36536
|
-
//
|
|
36537
|
-
//
|
|
36538
|
-
//
|
|
36741
|
+
const TRACKING_PARAM_RE = /^(?:utm(?:_.*)?|fbclid|gclid|dclid|msclkid|mc_cid|mc_eid|igshid|ref_src)$/i;
|
|
36742
|
+
// Drop tracking params and in-page anchors for URLs and normalize
|
|
36743
|
+
// backslashes for paths so a citation that adds `?utm_source=...` or uses
|
|
36744
|
+
// forward slashes on Windows still matches the visited entry. Identifying
|
|
36745
|
+
// query params (Outlook `?ItemID=`, `watch?v=`) and hash routes (Gmail
|
|
36746
|
+
// `#all/<id>`) are kept verbatim: they are case-sensitive and are the only
|
|
36747
|
+
// thing that distinguishes two message permalinks. Also fold `~/...` to the
|
|
36748
|
+
// resolved home dir so `~/Downloads/x` and `C:\Users\andre\Downloads\x` de-dupe.
|
|
36539
36749
|
function normalizeSource(raw) {
|
|
36540
36750
|
const trimmed = raw.trim();
|
|
36541
36751
|
if (!trimmed) return "";
|
|
36542
36752
|
if (/^https?:\/\//i.test(trimmed)) {
|
|
36543
36753
|
try {
|
|
36544
36754
|
const u = new URL(trimmed);
|
|
36545
|
-
|
|
36755
|
+
const base = `${u.protocol}//${u.host}${u.pathname}`.replace(/\/+$/, "").toLowerCase();
|
|
36756
|
+
const params = [
|
|
36757
|
+
...u.searchParams
|
|
36758
|
+
].filter(([key])=>!TRACKING_PARAM_RE.test(key)).sort(([a], [b])=>a < b ? -1 : a > b ? 1 : 0);
|
|
36759
|
+
const query = params.length > 0 ? `?${new URLSearchParams(params).toString()}` : "";
|
|
36760
|
+
const hashRoute = u.hash.includes("/") ? u.hash : "";
|
|
36761
|
+
return base + query + hashRoute;
|
|
36546
36762
|
} catch {
|
|
36547
36763
|
return trimmed.toLowerCase();
|
|
36548
36764
|
}
|
|
@@ -36891,15 +37107,8 @@ ${sent}`;
|
|
|
36891
37107
|
*/ function parseCitationVerdict(text) {
|
|
36892
37108
|
if (!text) return null;
|
|
36893
37109
|
const stripped = text.replace(/```(?:json)?\s*/gi, "").replace(/```/g, "").trim();
|
|
36894
|
-
const
|
|
36895
|
-
if (!
|
|
36896
|
-
let parsed;
|
|
36897
|
-
try {
|
|
36898
|
-
parsed = JSON.parse(m[0]);
|
|
36899
|
-
} catch {
|
|
36900
|
-
return null;
|
|
36901
|
-
}
|
|
36902
|
-
if (!parsed || typeof parsed !== "object") return null;
|
|
37110
|
+
const parsed = findClaimsObject(stripped);
|
|
37111
|
+
if (!parsed) return null;
|
|
36903
37112
|
const claimsRaw = parsed.claims;
|
|
36904
37113
|
if (!Array.isArray(claimsRaw)) return null;
|
|
36905
37114
|
const claims = [];
|
|
@@ -36926,6 +37135,41 @@ ${sent}`;
|
|
|
36926
37135
|
}
|
|
36927
37136
|
return claims;
|
|
36928
37137
|
}
|
|
37138
|
+
// Models often wrap the verdict in prose that itself contains braces, so a
|
|
37139
|
+
// single greedy `{...}` match can start or end in the wrong place. Try each
|
|
37140
|
+
// `{` as a start and parse the balanced object it opens (string-aware).
|
|
37141
|
+
function findClaimsObject(text) {
|
|
37142
|
+
for(let start = text.indexOf("{"); start !== -1; start = text.indexOf("{", start + 1)){
|
|
37143
|
+
const end = balancedObjectEnd(text, start);
|
|
37144
|
+
if (end === -1) continue;
|
|
37145
|
+
const candidate = text.slice(start, end + 1);
|
|
37146
|
+
if (!candidate.includes('"claims"')) continue;
|
|
37147
|
+
try {
|
|
37148
|
+
const parsed = JSON.parse(candidate);
|
|
37149
|
+
if (parsed && typeof parsed === "object" && "claims" in parsed) return parsed;
|
|
37150
|
+
} catch {}
|
|
37151
|
+
}
|
|
37152
|
+
return null;
|
|
37153
|
+
}
|
|
37154
|
+
function balancedObjectEnd(text, start) {
|
|
37155
|
+
let depth = 0;
|
|
37156
|
+
let inString = false;
|
|
37157
|
+
for(let i = start; i < text.length; i++){
|
|
37158
|
+
const ch = text[i];
|
|
37159
|
+
if (inString) {
|
|
37160
|
+
if (ch === "\\") i++;
|
|
37161
|
+
else if (ch === '"') inString = false;
|
|
37162
|
+
} else if (ch === '"') {
|
|
37163
|
+
inString = true;
|
|
37164
|
+
} else if (ch === "{") {
|
|
37165
|
+
depth++;
|
|
37166
|
+
} else if (ch === "}") {
|
|
37167
|
+
depth--;
|
|
37168
|
+
if (depth === 0) return i;
|
|
37169
|
+
}
|
|
37170
|
+
}
|
|
37171
|
+
return -1;
|
|
37172
|
+
}
|
|
36929
37173
|
function collectStringsFromPayload(payload, out) {
|
|
36930
37174
|
if (!payload) return;
|
|
36931
37175
|
if (typeof payload === "string") {
|
|
@@ -37089,17 +37333,31 @@ function hotTurnBoundary(threadId, agentCfg, scope, bridgeKey) {
|
|
|
37089
37333
|
const boundary = userMessages[userMessages.length - turnLimit];
|
|
37090
37334
|
return boundary?.seq ?? null;
|
|
37091
37335
|
}
|
|
37092
|
-
|
|
37336
|
+
// The topic-aware boundary keeps the whole active topic hot, so user turns
|
|
37337
|
+
// since the pin usually still exceed the limit right after a commit. Without a
|
|
37338
|
+
// cooldown every following turn re-runs the topic LLM pass only to land on the
|
|
37339
|
+
// same pin. Skip the next half-limit turns (2 rows per turn) before re-checking.
|
|
37340
|
+
function hotTurnCooldownUntil(messageCount, hotTurnLimit) {
|
|
37341
|
+
const turnLimit = hotTurnLimit ?? types/* DEFAULT_HOT_TURN_LIMIT */.u_;
|
|
37342
|
+
const skipTurns = Math.max(1, Math.ceil(Math.max(1, turnLimit) / 2));
|
|
37343
|
+
return messageCount + skipTurns * 2 + 1;
|
|
37344
|
+
}
|
|
37345
|
+
async function maybeAutoCompactOversizedThread(agentId, threadId, onCompacting, preserveNewestMessages = 0) {
|
|
37093
37346
|
const cap = (0,config/* getConfig */.z)().maxThreadMessages;
|
|
37094
37347
|
const keepLast = autoCompactionKeepLast(cap);
|
|
37095
37348
|
const retainedMessages = keepLast + preserveNewestMessages;
|
|
37096
37349
|
const triggerAt = cap + (cap - keepLast);
|
|
37097
|
-
if (!Number.isFinite(cap) || cap <= 0
|
|
37350
|
+
if (!Number.isFinite(cap) || cap <= 0) return;
|
|
37351
|
+
// Only foreground rows are ever pruned; counting bridge/watcher/scheduled
|
|
37352
|
+
// rows would re-trigger an LLM compaction on every turn of a busy bridge
|
|
37353
|
+
// agent without ever bringing the count back under the cap.
|
|
37354
|
+
const messageCount = (0,threads/* countForegroundThreadMessages */.Tb)(threadId);
|
|
37355
|
+
if (messageCount < triggerAt) return;
|
|
37098
37356
|
try {
|
|
37099
37357
|
// A pin that already keeps the hot tier within the retained range must not
|
|
37100
37358
|
// be pulled back to the cutoff, nor re-summarised by an LLM on every turn.
|
|
37101
37359
|
const pinSeq = (0,threads/* getThread */.fG)(threadId)?.hot_since_seq ?? null;
|
|
37102
|
-
if (pinSeq !== null && (0,threads/*
|
|
37360
|
+
if (pinSeq !== null && (0,threads/* countForegroundThreadMessages */.Tb)(threadId, pinSeq) <= retainedMessages) {
|
|
37103
37361
|
(0,threads/* pruneThreadMessages */.vC)(threadId, retainedMessages, pinSeq);
|
|
37104
37362
|
return;
|
|
37105
37363
|
}
|
|
@@ -37138,7 +37396,6 @@ async function persistThreadRunUserMessage(req) {
|
|
|
37138
37396
|
if (!trimmed && !req.attachments?.length) {
|
|
37139
37397
|
throw new RunThreadError(400, "message required", "message_required");
|
|
37140
37398
|
}
|
|
37141
|
-
const messageCountBefore = thread.message_count;
|
|
37142
37399
|
const autoBoundaryScope = req.context_profile?.history_scope ?? (req.user_category === "bridge" ? "bridge" : "foreground");
|
|
37143
37400
|
const idleMsBefore = isAutoBoundaryEligibleCategory(req.user_category) ? conversationIdleMs(req.thread_id, autoBoundaryScope, req.history_bridge_key ?? undefined) : null;
|
|
37144
37401
|
const spilledAttachments = req.attachments?.length ? await spillAttachments(req.attachments) : undefined;
|
|
@@ -37158,7 +37415,6 @@ async function persistThreadRunUserMessage(req) {
|
|
|
37158
37415
|
});
|
|
37159
37416
|
return {
|
|
37160
37417
|
attachments: spilledAttachments,
|
|
37161
|
-
messageCountBefore,
|
|
37162
37418
|
idleMsBefore,
|
|
37163
37419
|
userMessageId: userMessage.msg_id,
|
|
37164
37420
|
storedContent: stored
|
|
@@ -37305,7 +37561,7 @@ function appendHistoryMessage(history, injected) {
|
|
|
37305
37561
|
let toolPermissionMap = baseToolPermissionMap;
|
|
37306
37562
|
let allowedTools = requestedAllowedTools;
|
|
37307
37563
|
if (!req._skip_persist_message && isAutoBoundaryEligibleCategory(req.user_category) && !hasPendingQueuedUserMessage(req.thread_id)) {
|
|
37308
|
-
await maybeAutoCompactOversizedThread(agentCfg.id, req.thread_id, req.
|
|
37564
|
+
await maybeAutoCompactOversizedThread(agentCfg.id, req.thread_id, req._onCompacting, req._user_message_persisted ? 2 : 0);
|
|
37309
37565
|
}
|
|
37310
37566
|
// Persist the user turn (including any attachments) before the LLM stream
|
|
37311
37567
|
// so reload-mid-stream still shows the prompt. The stall-retry path sets
|
|
@@ -37347,7 +37603,11 @@ function appendHistoryMessage(history, injected) {
|
|
|
37347
37603
|
const locked = !!latestThread && latestThread.message_count < (latestThread.auto_boundary_locked_until_msg_count ?? 0);
|
|
37348
37604
|
if (!locked) {
|
|
37349
37605
|
const boundary = hotTurnBoundary(req.thread_id, agentCfg, autoBoundaryScope);
|
|
37350
|
-
if (boundary !== null)
|
|
37606
|
+
if (boundary !== null) {
|
|
37607
|
+
(0,warm_summary_background/* kickBoundaryCompaction */.Wg)(req.thread_id, boundary, {
|
|
37608
|
+
autoBoundaryLockedUntilMessageCount: hotTurnCooldownUntil(latestThread?.message_count ?? 0, agentCfg.hot_turn_limit)
|
|
37609
|
+
});
|
|
37610
|
+
}
|
|
37351
37611
|
}
|
|
37352
37612
|
}
|
|
37353
37613
|
}
|
|
@@ -38814,12 +39074,11 @@ function isBasicToolCategory(category) {
|
|
|
38814
39074
|
|
|
38815
39075
|
// Every caller of moveThreadContextBoundary represents a user-initiated
|
|
38816
39076
|
// boundary change (drag the line, the manual /compact command, or the agent's
|
|
38817
|
-
// compact_context tool acting on the user's say-so)
|
|
38818
|
-
//
|
|
38819
|
-
//
|
|
38820
|
-
//
|
|
38821
|
-
//
|
|
38822
|
-
// choice doesn't get silently re-moved on the very next turn.
|
|
39077
|
+
// compact_context tool acting on the user's say-so). Suppresses the
|
|
39078
|
+
// hot-turn-limit compaction in lib/agents/run-thread.ts for the next N
|
|
39079
|
+
// eligible turns so a manual choice doesn't get silently re-moved on the very
|
|
39080
|
+
// next turn. The auto-detector arms a shorter cooldown of its own
|
|
39081
|
+
// (hotTurnCooldownUntil) so it doesn't re-run on every turn either.
|
|
38823
39082
|
// Counted in messages (~2 per turn: one user + one assistant row) since
|
|
38824
39083
|
// that's what's already on the thread row — no extra query or per-turn
|
|
38825
39084
|
// write needed to check it.
|