@withbuddi/buddi 0.1.0-pre.45 → 0.1.0-pre.47
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/extension/background.js +157 -1
- package/extension/manifest.json +5 -2
- package/extension/popup.html +4 -0
- package/extension/popup.js +18 -0
- package/node_modules/@buddi/cli/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/cli/dist/mcp/tools.d.ts +3 -8
- package/node_modules/@buddi/cli/dist/mcp/tools.d.ts.map +1 -1
- package/node_modules/@buddi/cli/dist/mcp/tools.js +22 -4
- package/node_modules/@buddi/cli/dist/mcp/tools.js.map +1 -1
- package/node_modules/@buddi/core/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/core/dist/artifacts/orphans.d.ts +6 -4
- package/node_modules/@buddi/core/dist/artifacts/orphans.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/artifacts/orphans.js +10 -3
- package/node_modules/@buddi/core/dist/artifacts/orphans.js.map +1 -1
- package/node_modules/@buddi/core/dist/groups.d.ts +0 -9
- package/node_modules/@buddi/core/dist/groups.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/groups.js +13 -1
- package/node_modules/@buddi/core/dist/groups.js.map +1 -1
- package/node_modules/@buddi/core/dist/onboarding/index.d.ts +1 -0
- package/node_modules/@buddi/core/dist/onboarding/index.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/onboarding/index.js +1 -0
- package/node_modules/@buddi/core/dist/onboarding/index.js.map +1 -1
- package/node_modules/@buddi/core/dist/pages.d.ts +24 -1
- package/node_modules/@buddi/core/dist/pages.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/pages.js +61 -1
- package/node_modules/@buddi/core/dist/pages.js.map +1 -1
- package/node_modules/@buddi/core/dist/pending-input.d.ts +13 -2
- package/node_modules/@buddi/core/dist/pending-input.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/pending-input.js +57 -12
- package/node_modules/@buddi/core/dist/pending-input.js.map +1 -1
- package/node_modules/@buddi/core/dist/plugin/version.d.ts +1 -1
- package/node_modules/@buddi/core/dist/plugin/version.js +1 -1
- package/node_modules/@buddi/core/dist/system-context.d.ts +6 -0
- package/node_modules/@buddi/core/dist/system-context.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/web-settings.d.ts +8 -0
- package/node_modules/@buddi/core/dist/web-settings.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/web-settings.js +14 -0
- package/node_modules/@buddi/core/dist/web-settings.js.map +1 -1
- package/node_modules/@buddi/core/migrations/078_pending_input_files.sql +8 -0
- package/node_modules/@buddi/gateway/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/gateway/dist/browser-host.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/browser-host.js +1 -0
- package/node_modules/@buddi/gateway/dist/browser-host.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions/agent-run.d.ts +6 -0
- package/node_modules/@buddi/gateway/dist/missions/agent-run.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions/agent-run.js +2 -1
- package/node_modules/@buddi/gateway/dist/missions/agent-run.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions/execute.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions/execute.js +4 -2
- package/node_modules/@buddi/gateway/dist/missions/execute.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions/reminders.d.ts +1 -0
- package/node_modules/@buddi/gateway/dist/missions/reminders.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions/reminders.js +2 -0
- package/node_modules/@buddi/gateway/dist/missions/reminders.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/owner-profile-edit.d.ts +3 -2
- package/node_modules/@buddi/gateway/dist/owner-profile-edit.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/owner-profile-edit.js +4 -2
- package/node_modules/@buddi/gateway/dist/owner-profile-edit.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/serve.js +1 -1
- package/node_modules/@buddi/gateway/dist/serve.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/system-context.d.ts +10 -2
- package/node_modules/@buddi/gateway/dist/system-context.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/system-context.js +24 -10
- package/node_modules/@buddi/gateway/dist/system-context.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/api-routes.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/api-routes.js +19 -1
- package/node_modules/@buddi/gateway/dist/web/api-routes.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/attention.d.ts +37 -0
- package/node_modules/@buddi/gateway/dist/web/attention.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/attention.js +54 -10
- package/node_modules/@buddi/gateway/dist/web/attention.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/canvas-tabs.d.ts +41 -0
- package/node_modules/@buddi/gateway/dist/web/canvas-tabs.d.ts.map +1 -0
- package/node_modules/@buddi/gateway/dist/web/canvas-tabs.js +68 -0
- package/node_modules/@buddi/gateway/dist/web/canvas-tabs.js.map +1 -0
- package/node_modules/@buddi/gateway/dist/web/chat.d.ts +0 -9
- package/node_modules/@buddi/gateway/dist/web/chat.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/chat.js +33 -19
- package/node_modules/@buddi/gateway/dist/web/chat.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/extension.d.ts +11 -1
- package/node_modules/@buddi/gateway/dist/web/extension.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/extension.js +51 -0
- package/node_modules/@buddi/gateway/dist/web/extension.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/pages.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/pages.js +10 -1
- package/node_modules/@buddi/gateway/dist/web/pages.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/server.d.ts +0 -4
- package/node_modules/@buddi/gateway/dist/web/server.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/server.js +72 -2
- package/node_modules/@buddi/gateway/dist/web/server.js.map +1 -1
- package/node_modules/@buddi/install/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/runtime/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/runtime/dist/index.d.ts +1 -0
- package/node_modules/@buddi/runtime/dist/index.d.ts.map +1 -1
- package/node_modules/@buddi/runtime/dist/index.js +1 -0
- package/node_modules/@buddi/runtime/dist/index.js.map +1 -1
- package/node_modules/@buddi/runtime/dist/language.d.ts +65 -0
- package/node_modules/@buddi/runtime/dist/language.d.ts.map +1 -0
- package/node_modules/@buddi/runtime/dist/language.js +191 -0
- package/node_modules/@buddi/runtime/dist/language.js.map +1 -0
- package/node_modules/@buddi/runtime/dist/loop.d.ts +15 -1
- package/node_modules/@buddi/runtime/dist/loop.d.ts.map +1 -1
- package/node_modules/@buddi/runtime/dist/loop.js +103 -14
- package/node_modules/@buddi/runtime/dist/loop.js.map +1 -1
- package/node_modules/@buddi/tool-artifacts/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-artifacts/dist/extract.d.ts +6 -0
- package/node_modules/@buddi/tool-artifacts/dist/extract.d.ts.map +1 -1
- package/node_modules/@buddi/tool-artifacts/dist/extract.js +6 -0
- package/node_modules/@buddi/tool-artifacts/dist/extract.js.map +1 -1
- package/node_modules/@buddi/tool-artifacts/dist/tools/artifacts.d.ts +1 -0
- package/node_modules/@buddi/tool-artifacts/dist/tools/artifacts.d.ts.map +1 -1
- package/node_modules/@buddi/tool-artifacts/dist/tools/artifacts.js +30 -8
- package/node_modules/@buddi/tool-artifacts/dist/tools/artifacts.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-browser/dist/controller.d.ts +25 -0
- package/node_modules/@buddi/tool-browser/dist/controller.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/controller.js +25 -1
- package/node_modules/@buddi/tool-browser/dist/controller.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/downloads.d.ts +138 -0
- package/node_modules/@buddi/tool-browser/dist/downloads.d.ts.map +1 -0
- package/node_modules/@buddi/tool-browser/dist/downloads.js +529 -0
- package/node_modules/@buddi/tool-browser/dist/downloads.js.map +1 -0
- package/node_modules/@buddi/tool-browser/dist/driver.d.ts +17 -1
- package/node_modules/@buddi/tool-browser/dist/driver.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/driver.js +48 -0
- package/node_modules/@buddi/tool-browser/dist/driver.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/extension.d.ts +23 -0
- package/node_modules/@buddi/tool-browser/dist/extension.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/extension.js +20 -0
- package/node_modules/@buddi/tool-browser/dist/extension.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/host.d.ts +3 -1
- package/node_modules/@buddi/tool-browser/dist/host.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/host.js +9 -2
- package/node_modules/@buddi/tool-browser/dist/host.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/index.d.ts +7 -3
- package/node_modules/@buddi/tool-browser/dist/index.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/index.js +5 -3
- package/node_modules/@buddi/tool-browser/dist/index.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/service.d.ts +28 -0
- package/node_modules/@buddi/tool-browser/dist/service.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/service.js +58 -1
- package/node_modules/@buddi/tool-browser/dist/service.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/settings.d.ts +8 -0
- package/node_modules/@buddi/tool-browser/dist/settings.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/settings.js +9 -0
- package/node_modules/@buddi/tool-browser/dist/settings.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/types.d.ts +31 -24
- package/node_modules/@buddi/tool-browser/dist/types.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/types.js.map +1 -1
- package/node_modules/@buddi/tool-email/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-host/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-mcp/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-memory/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-web/dist/.tsbuildinfo +1 -1
- package/node_modules/express-rate-limit/dist/index.cjs +9 -7
- package/node_modules/express-rate-limit/dist/index.mjs +9 -7
- package/node_modules/express-rate-limit/package.json +9 -9
- package/node_modules/nanoid/README.md +3 -3
- package/node_modules/nanoid/index.browser.js +4 -5
- package/node_modules/nanoid/index.d.ts +3 -3
- package/node_modules/nanoid/index.js +2 -3
- package/node_modules/nanoid/nanoid.js +1 -1
- package/node_modules/nanoid/package.json +2 -2
- package/node_modules/nanoid/url-alphabet/index.js +1 -1
- package/package.json +2 -2
- package/packages/cli/dist/.tsbuildinfo +1 -1
- package/packages/cli/dist/mcp/tools.d.ts +3 -8
- package/packages/cli/dist/mcp/tools.d.ts.map +1 -1
- package/packages/cli/dist/mcp/tools.js +22 -4
- package/packages/cli/dist/mcp/tools.js.map +1 -1
- package/packages/core/dist/.tsbuildinfo +1 -1
- package/packages/core/dist/artifacts/orphans.d.ts +6 -4
- package/packages/core/dist/artifacts/orphans.d.ts.map +1 -1
- package/packages/core/dist/artifacts/orphans.js +10 -3
- package/packages/core/dist/artifacts/orphans.js.map +1 -1
- package/packages/core/dist/groups.d.ts +0 -9
- package/packages/core/dist/groups.d.ts.map +1 -1
- package/packages/core/dist/groups.js +13 -1
- package/packages/core/dist/groups.js.map +1 -1
- package/packages/core/dist/onboarding/index.d.ts +1 -0
- package/packages/core/dist/onboarding/index.d.ts.map +1 -1
- package/packages/core/dist/onboarding/index.js +1 -0
- package/packages/core/dist/onboarding/index.js.map +1 -1
- package/packages/core/dist/pages.d.ts +24 -1
- package/packages/core/dist/pages.d.ts.map +1 -1
- package/packages/core/dist/pages.js +61 -1
- package/packages/core/dist/pages.js.map +1 -1
- package/packages/core/dist/pending-input.d.ts +13 -2
- package/packages/core/dist/pending-input.d.ts.map +1 -1
- package/packages/core/dist/pending-input.js +57 -12
- package/packages/core/dist/pending-input.js.map +1 -1
- package/packages/core/dist/plugin/version.d.ts +1 -1
- package/packages/core/dist/plugin/version.js +1 -1
- package/packages/core/dist/system-context.d.ts +6 -0
- package/packages/core/dist/system-context.d.ts.map +1 -1
- package/packages/core/dist/web-settings.d.ts +8 -0
- package/packages/core/dist/web-settings.d.ts.map +1 -1
- package/packages/core/dist/web-settings.js +14 -0
- package/packages/core/dist/web-settings.js.map +1 -1
- package/packages/core/migrations/078_pending_input_files.sql +8 -0
- package/packages/gateway/dist/.tsbuildinfo +1 -1
- package/packages/gateway/dist/browser-host.d.ts.map +1 -1
- package/packages/gateway/dist/browser-host.js +1 -0
- package/packages/gateway/dist/browser-host.js.map +1 -1
- package/packages/gateway/dist/missions/agent-run.d.ts +6 -0
- package/packages/gateway/dist/missions/agent-run.d.ts.map +1 -1
- package/packages/gateway/dist/missions/agent-run.js +2 -1
- package/packages/gateway/dist/missions/agent-run.js.map +1 -1
- package/packages/gateway/dist/missions/execute.d.ts.map +1 -1
- package/packages/gateway/dist/missions/execute.js +4 -2
- package/packages/gateway/dist/missions/execute.js.map +1 -1
- package/packages/gateway/dist/missions/reminders.d.ts +1 -0
- package/packages/gateway/dist/missions/reminders.d.ts.map +1 -1
- package/packages/gateway/dist/missions/reminders.js +2 -0
- package/packages/gateway/dist/missions/reminders.js.map +1 -1
- package/packages/gateway/dist/owner-profile-edit.d.ts +3 -2
- package/packages/gateway/dist/owner-profile-edit.d.ts.map +1 -1
- package/packages/gateway/dist/owner-profile-edit.js +4 -2
- package/packages/gateway/dist/owner-profile-edit.js.map +1 -1
- package/packages/gateway/dist/serve.js +1 -1
- package/packages/gateway/dist/serve.js.map +1 -1
- package/packages/gateway/dist/system-context.d.ts +10 -2
- package/packages/gateway/dist/system-context.d.ts.map +1 -1
- package/packages/gateway/dist/system-context.js +24 -10
- package/packages/gateway/dist/system-context.js.map +1 -1
- package/packages/gateway/dist/web/api-routes.d.ts.map +1 -1
- package/packages/gateway/dist/web/api-routes.js +19 -1
- package/packages/gateway/dist/web/api-routes.js.map +1 -1
- package/packages/gateway/dist/web/attention.d.ts +37 -0
- package/packages/gateway/dist/web/attention.d.ts.map +1 -1
- package/packages/gateway/dist/web/attention.js +54 -10
- package/packages/gateway/dist/web/attention.js.map +1 -1
- package/packages/gateway/dist/web/canvas-tabs.d.ts +41 -0
- package/packages/gateway/dist/web/canvas-tabs.d.ts.map +1 -0
- package/packages/gateway/dist/web/canvas-tabs.js +68 -0
- package/packages/gateway/dist/web/canvas-tabs.js.map +1 -0
- package/packages/gateway/dist/web/chat.d.ts +0 -9
- package/packages/gateway/dist/web/chat.d.ts.map +1 -1
- package/packages/gateway/dist/web/chat.js +33 -19
- package/packages/gateway/dist/web/chat.js.map +1 -1
- package/packages/gateway/dist/web/extension.d.ts +11 -1
- package/packages/gateway/dist/web/extension.d.ts.map +1 -1
- package/packages/gateway/dist/web/extension.js +51 -0
- package/packages/gateway/dist/web/extension.js.map +1 -1
- package/packages/gateway/dist/web/pages.d.ts.map +1 -1
- package/packages/gateway/dist/web/pages.js +10 -1
- package/packages/gateway/dist/web/pages.js.map +1 -1
- package/packages/gateway/dist/web/server.d.ts +0 -4
- package/packages/gateway/dist/web/server.d.ts.map +1 -1
- package/packages/gateway/dist/web/server.js +72 -2
- package/packages/gateway/dist/web/server.js.map +1 -1
- package/packages/install/dist/.tsbuildinfo +1 -1
- package/packages/runtime/dist/.tsbuildinfo +1 -1
- package/packages/runtime/dist/index.d.ts +1 -0
- package/packages/runtime/dist/index.d.ts.map +1 -1
- package/packages/runtime/dist/index.js +1 -0
- package/packages/runtime/dist/index.js.map +1 -1
- package/packages/runtime/dist/language.d.ts +65 -0
- package/packages/runtime/dist/language.d.ts.map +1 -0
- package/packages/runtime/dist/language.js +191 -0
- package/packages/runtime/dist/language.js.map +1 -0
- package/packages/runtime/dist/loop.d.ts +15 -1
- package/packages/runtime/dist/loop.d.ts.map +1 -1
- package/packages/runtime/dist/loop.js +103 -14
- package/packages/runtime/dist/loop.js.map +1 -1
- package/packages/tools/artifacts/dist/.tsbuildinfo +1 -1
- package/packages/tools/artifacts/dist/extract.d.ts +6 -0
- package/packages/tools/artifacts/dist/extract.d.ts.map +1 -1
- package/packages/tools/artifacts/dist/extract.js +6 -0
- package/packages/tools/artifacts/dist/extract.js.map +1 -1
- package/packages/tools/artifacts/dist/tools/artifacts.d.ts +1 -0
- package/packages/tools/artifacts/dist/tools/artifacts.d.ts.map +1 -1
- package/packages/tools/artifacts/dist/tools/artifacts.js +30 -8
- package/packages/tools/artifacts/dist/tools/artifacts.js.map +1 -1
- package/packages/tools/browser/dist/.tsbuildinfo +1 -1
- package/packages/tools/browser/dist/controller.d.ts +25 -0
- package/packages/tools/browser/dist/controller.d.ts.map +1 -1
- package/packages/tools/browser/dist/controller.js +25 -1
- package/packages/tools/browser/dist/controller.js.map +1 -1
- package/packages/tools/browser/dist/downloads.d.ts +138 -0
- package/packages/tools/browser/dist/downloads.d.ts.map +1 -0
- package/packages/tools/browser/dist/downloads.js +529 -0
- package/packages/tools/browser/dist/downloads.js.map +1 -0
- package/packages/tools/browser/dist/driver.d.ts +17 -1
- package/packages/tools/browser/dist/driver.d.ts.map +1 -1
- package/packages/tools/browser/dist/driver.js +48 -0
- package/packages/tools/browser/dist/driver.js.map +1 -1
- package/packages/tools/browser/dist/extension.d.ts +23 -0
- package/packages/tools/browser/dist/extension.d.ts.map +1 -1
- package/packages/tools/browser/dist/extension.js +20 -0
- package/packages/tools/browser/dist/extension.js.map +1 -1
- package/packages/tools/browser/dist/host.d.ts +3 -1
- package/packages/tools/browser/dist/host.d.ts.map +1 -1
- package/packages/tools/browser/dist/host.js +9 -2
- package/packages/tools/browser/dist/host.js.map +1 -1
- package/packages/tools/browser/dist/index.d.ts +7 -3
- package/packages/tools/browser/dist/index.d.ts.map +1 -1
- package/packages/tools/browser/dist/index.js +5 -3
- package/packages/tools/browser/dist/index.js.map +1 -1
- package/packages/tools/browser/dist/service.d.ts +28 -0
- package/packages/tools/browser/dist/service.d.ts.map +1 -1
- package/packages/tools/browser/dist/service.js +58 -1
- package/packages/tools/browser/dist/service.js.map +1 -1
- package/packages/tools/browser/dist/settings.d.ts +8 -0
- package/packages/tools/browser/dist/settings.d.ts.map +1 -1
- package/packages/tools/browser/dist/settings.js +9 -0
- package/packages/tools/browser/dist/settings.js.map +1 -1
- package/packages/tools/browser/dist/types.d.ts +31 -24
- package/packages/tools/browser/dist/types.d.ts.map +1 -1
- package/packages/tools/browser/dist/types.js.map +1 -1
- package/packages/tools/email/dist/.tsbuildinfo +1 -1
- package/packages/tools/host/dist/.tsbuildinfo +1 -1
- package/packages/tools/mcp/dist/.tsbuildinfo +1 -1
- package/packages/tools/memory/dist/.tsbuildinfo +1 -1
- package/packages/tools/web/dist/.tsbuildinfo +1 -1
- package/packages/web/dist/assets/index-Bxcetnpt.js +150 -0
- package/packages/web/dist/assets/index-CkzsX0YQ.css +1 -0
- package/packages/web/dist/assets/{lottie_light-DxWeiVDC.js → lottie_light-CM_Bp6rc.js} +1 -1
- package/packages/web/dist/build.json +1 -1
- package/packages/web/dist/index.html +2 -2
- package/packages/web/dist/precache.json +4 -4
- package/packages/web/dist/assets/index-CPFSREcP.css +0 -1
- package/packages/web/dist/assets/index-DYUn1V0x.js +0 -150
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reply-language guard's eye: which language is a piece of text written in?
|
|
3
|
+
*
|
|
4
|
+
* Agent Father answered an English question in Spanish; the concierge answered
|
|
5
|
+
* in French after reading French news. The prompt already says to answer in
|
|
6
|
+
* the owner's language (the reply-language line in every agent's platform
|
|
7
|
+
* context); this is the deterministic check behind it, run by the loop on the
|
|
8
|
+
* final text of a turn. No model: a small stopword count for six languages.
|
|
9
|
+
*
|
|
10
|
+
* Biased hard toward precision, because a false positive costs the owner a
|
|
11
|
+
* second model call and a rewrite of an answer that was fine:
|
|
12
|
+
*
|
|
13
|
+
* - code, links, email addresses, blockquotes and quoted passages are not the
|
|
14
|
+
* answer's own words, so they are not counted;
|
|
15
|
+
* - a word several languages share ("de", "la", "que") counts for each of
|
|
16
|
+
* them by a fraction, so only the words that tell languages apart decide;
|
|
17
|
+
* - a language is named only with enough evidence (`minHits`), twice the
|
|
18
|
+
* evidence of the runner-up, and a tenth of the words at least;
|
|
19
|
+
* - anything else is "cannot tell", and "cannot tell" never fires the guard.
|
|
20
|
+
*/
|
|
21
|
+
import { languageTag } from '@buddi/core';
|
|
22
|
+
/** The name the model is asked to answer in. */
|
|
23
|
+
export const LANGUAGE_NAMES = {
|
|
24
|
+
en: 'English', fr: 'French', es: 'Spanish', de: 'German', pt: 'Portuguese', it: 'Italian',
|
|
25
|
+
};
|
|
26
|
+
/** What the model is told when its answer is in the wrong language. */
|
|
27
|
+
export function languageRetryText(language) {
|
|
28
|
+
return `Answer in ${language}.`;
|
|
29
|
+
}
|
|
30
|
+
/** The guard never looks at a reply shorter than this. */
|
|
31
|
+
export const MIN_REPLY_WORDS = 12;
|
|
32
|
+
const STOPWORDS = {
|
|
33
|
+
en: 'the and of to in is are was were be been being have has had it its this that these those with for on at by from you your yours i we our they their them he she his her not but or if what which who whom when where why how can will would should could do does did done there here an as about just than then my me so all any into because very also only some more most other such no yes please thanks thank hello hi let get got make made want need know think see one two today tomorrow yesterday out up down over again still much many each every',
|
|
34
|
+
fr: 'le la les des du un une est et en que qui dans pour pas sur au aux avec ce cet cette ces je tu il elle nous vous ils elles mais ou où sont été être avoir ont fait faire plus ne se sa son ses leur leurs mon ma mes ton ta tes votre vos notre nos très aussi comme tout tous toute toutes bien à c est j suis peux peut quel quelle quels quelles merci bonjour oui non salut voici voilà cela ça déjà encore aujourd hui demain hier chez donc alors sans sous entre après avant',
|
|
35
|
+
es: 'el la los las un una unos unas es y en que de del al por para con no se lo le les su sus está están estoy son ser fue pero como más muy este esta estos estas ese esa eso esto yo tú él ella nosotros ustedes usted hay también porque cuando donde dónde qué cómo cuál todo todos toda puede puedo tiene tengo hola gracias sí ya hoy mañana ayer sobre entre sin desde hasta muchas mucho',
|
|
36
|
+
de: 'der die das und in im ist nicht ein eine einen einem einer dem den des zu mit von auf für sich ich du er sie wir ihr es sind war wird werden haben hat habe auch als aber oder wenn noch nur schon wie bei aus nach kann können über dass diese dieser dieses mein meine dein ihre unser sehr hier bitte danke ja nein hallo heute morgen gestern gibt kein keine was wer wo warum mir mich dir dich uns euch',
|
|
37
|
+
pt: 'o a os as um uma uns umas é e em que de do da dos das no na nos nas por para com não se seu sua seus suas está estão estou são ser foi mas como mais muito muita este esta isso isto eu você vocês ele ela nós eles elas também quando onde porque tem tenho pode posso ao à olá obrigado obrigada sim já hoje amanhã ontem sobre entre sem até pelo pela',
|
|
38
|
+
it: 'il lo la i gli le un una uno è e a in che di del della dello dei degli delle nel nella per con non si suo sua suoi sono essere stato stata ma come più molto molta questo questa quello quella io tu lui lei noi voi loro anche quando dove perché ha hanno ho può posso al alla ci sei ciao grazie sì oggi domani ieri sono tra fra senza fino cosa qui',
|
|
39
|
+
};
|
|
40
|
+
/** Each word, with the languages it belongs to and the share each one gets. */
|
|
41
|
+
const WEIGHTS = (() => {
|
|
42
|
+
const owners = new Map();
|
|
43
|
+
for (const [code, words] of Object.entries(STOPWORDS)) {
|
|
44
|
+
for (const word of new Set(words.split(/\s+/)))
|
|
45
|
+
owners.set(word, [...(owners.get(word) ?? []), code]);
|
|
46
|
+
}
|
|
47
|
+
return new Map([...owners].map(([word, codes]) => [word, codes.map((c) => [c, 1 / codes.length])]));
|
|
48
|
+
})();
|
|
49
|
+
/** Letters only one of the six languages uses. */
|
|
50
|
+
const MARKS = [[/[ñ¿¡]/, 'es'], [/[ãõ]/, 'pt'], [/[ßäö]/, 'de'], [/[œ]/, 'fr']];
|
|
51
|
+
const FENCE = /```[\s\S]*?(?:```|$)/g;
|
|
52
|
+
const INLINE = /`[^`\n]*`/g;
|
|
53
|
+
/** How much of a text is code, 0..1. */
|
|
54
|
+
export function codeShare(text) {
|
|
55
|
+
const total = text.replace(/\s+/g, '').length;
|
|
56
|
+
if (total === 0)
|
|
57
|
+
return 0;
|
|
58
|
+
let code = 0;
|
|
59
|
+
for (const m of text.matchAll(FENCE))
|
|
60
|
+
code += m[0].replace(/\s+/g, '').length;
|
|
61
|
+
for (const m of text.replace(FENCE, ' ').matchAll(INLINE))
|
|
62
|
+
code += m[0].replace(/\s+/g, '').length;
|
|
63
|
+
return code / total;
|
|
64
|
+
}
|
|
65
|
+
/** The text's own words: no code, links, addresses, blockquotes or quoted passages. */
|
|
66
|
+
export function ownWords(text) {
|
|
67
|
+
const prose = text
|
|
68
|
+
.replace(FENCE, ' ')
|
|
69
|
+
.replace(INLINE, ' ')
|
|
70
|
+
.replace(/^\s*>.*$/gm, ' ')
|
|
71
|
+
.replace(/\]\([^)]*\)/g, ' ')
|
|
72
|
+
.replace(/https?:\/\/\S+/gi, ' ')
|
|
73
|
+
.replace(/\S+@\S+\.\S+/g, ' ')
|
|
74
|
+
// A complete quotation goes whatever its length or line breaks: a long
|
|
75
|
+
// French passage quoted in an English answer is not the answer's French.
|
|
76
|
+
.replace(/"[^"]+"|“[^”]+”|«[^»]+»|„[^“”]+[“”]/g, ' ');
|
|
77
|
+
return prose.toLowerCase().match(/\p{L}+/gu) ?? [];
|
|
78
|
+
}
|
|
79
|
+
/** The language a text is in, with the evidence; `language` is null when it cannot tell. */
|
|
80
|
+
export function scoreLanguage(text, opts = {}) {
|
|
81
|
+
const minHits = opts.minHits ?? 3;
|
|
82
|
+
const words = ownWords(text);
|
|
83
|
+
const scores = { en: 0, fr: 0, es: 0, de: 0, pt: 0, it: 0 };
|
|
84
|
+
for (const word of words) {
|
|
85
|
+
for (const [code, share] of WEIGHTS.get(word) ?? [])
|
|
86
|
+
scores[code] += share;
|
|
87
|
+
for (const [mark, code] of MARKS)
|
|
88
|
+
if (mark.test(word))
|
|
89
|
+
scores[code] += 0.5;
|
|
90
|
+
}
|
|
91
|
+
const ranked = Object.entries(scores).sort((a, b) => b[1] - a[1]);
|
|
92
|
+
const [best, second] = [ranked[0], ranked[1]];
|
|
93
|
+
const confident = best[1] >= minHits && best[1] >= 2 * second[1] && best[1] >= 0.1 * words.length;
|
|
94
|
+
return { language: confident ? best[0] : null, words: words.length, scores };
|
|
95
|
+
}
|
|
96
|
+
/** `scoreLanguage`, the verdict only. */
|
|
97
|
+
export function detectLanguage(text, opts = {}) {
|
|
98
|
+
return scoreLanguage(text, opts).language;
|
|
99
|
+
}
|
|
100
|
+
const LANG = 'english|anglais|inglés|ingles|englisch|inglese|french|français|francais|francés|frances|französisch|francese|' +
|
|
101
|
+
'spanish|español|espanol|espagnol|spanisch|spagnolo|espanhol|german|deutsch|allemand|alemán|aleman|tedesco|alemão|alemao|' +
|
|
102
|
+
'italian|italiano|italien|italienisch|portuguese|português|portugues|portugais|portugiesisch|portoghese';
|
|
103
|
+
/** Feminine and inflected adjectives that follow their noun ("une version française"). */
|
|
104
|
+
const LANG_ADJ = `${LANG}|anglaise|française|francaise|espagnole|allemande|italienne|portugaise|inglesa|francesa|española|espanola|alemana|italiana|portuguesa|englische|französische|spanische|deutsche|italienische|portugiesische|englischen|französischen|spanischen|deutschen`;
|
|
105
|
+
/** Words that can follow "in French" in an instruction without making it a noun phrase. */
|
|
106
|
+
const AFTER = 'please|pls|now|instead|too|also|only|again|anymore|from|for|to|of|and|then|thanks|thank|' +
|
|
107
|
+
's|svp|merci|maintenant|désormais|dorénavant|aussi|seulement|pour|de|du|à|stp|' +
|
|
108
|
+
'bitte|jetzt|ab|danke|nur|auch|por|favor|ahora|gracias|solo|también|per|favore|ora|adesso|grazie|agora|obrigado|obrigada';
|
|
109
|
+
/** Verbs of answering, writing or saying, in the six languages. */
|
|
110
|
+
const VERB = 'answer|reply|respond|write|rewrite|say|speak|talk|tell|explain|summari[sz]e|give|send|draft|' +
|
|
111
|
+
'réponds|répondez|répondre|écris|écrivez|parle|parlez|dis|dites|explique|expliquez|résume|résumez|' +
|
|
112
|
+
'antworte|antworten|schreib|schreibe|sprich|erkläre|erklär|' +
|
|
113
|
+
'responde|responda|escribe|escriba|habla|hable|dime|explica|resume|' +
|
|
114
|
+
'rispondi|scrivi|parla|parli|dimmi|spiega|riassumi|' +
|
|
115
|
+
'escreva|escreve|fala|fale|diga|explique|resuma';
|
|
116
|
+
/** Object pronouns that may sit between the verb and "in French" ("tell me in Spanish"). */
|
|
117
|
+
const PRONOUN = 'me|us|him|her|them|it|this|that|back|moi|nous|lui|leur|le|la|les|ça|mir|uns|ihm|ihr|es|das|nos|lo|mi|ci|gli|lhe';
|
|
118
|
+
const NOUN = 'summary|version|translation|reply|answer|response|text|copy|draft|edition|' +
|
|
119
|
+
'résumé|resume|traduction|réponse|texte|' +
|
|
120
|
+
'zusammenfassung|fassung|übersetzung|antwort|' +
|
|
121
|
+
'resumen|versión|traducción|respuesta|riassunto|versione|traduzione|risposta|resumo|versão|tradução|resposta';
|
|
122
|
+
const INSTRUCTIONS = [
|
|
123
|
+
// "translate to German", "traduis", "übersetzen", "the Spanish translation".
|
|
124
|
+
/(?<!\p{L})(?:translat\p{L}*|tradu\p{L}*|übersetz\p{L}*|uebersetz\p{L}*)/iu,
|
|
125
|
+
// "answer in French", "write the mail in Spanish to Ana", "en français
|
|
126
|
+
// s'il te plaît": the language at the end of a clause, or followed by
|
|
127
|
+
// "please", "from now on", "to"; never by a noun ("in French politics").
|
|
128
|
+
new RegExp(`(?<!\\p{L})(?:in|into|en|auf|em|al|para)\\s+(?:${LANG})(?:\\s*(?:[.,!?;:)\\]]|$)|\\s+(?:${AFTER})(?!\\p{L}))`, 'imu'),
|
|
129
|
+
// "tell me in Spanish what is on", "réponds-moi en anglais": a verb of
|
|
130
|
+
// answering, at most two pronouns, then the language.
|
|
131
|
+
new RegExp(`(?<!\\p{L})(?:${VERB})(?:[\\s-]+(?:${PRONOUN})){0,2}\\s+(?:in|into|en|auf|em|al|para)\\s+(?:${LANG})(?!\\p{L})`, 'iu'),
|
|
132
|
+
// "a Spanish summary", "the French version".
|
|
133
|
+
new RegExp(`(?<!\\p{L})(?:${LANG})\\s+(?:${NOUN})(?!\\p{L})`, 'iu'),
|
|
134
|
+
// "une version française", "una respuesta española".
|
|
135
|
+
new RegExp(`(?<!\\p{L})(?:${NOUN})\\s+(?:${LANG_ADJ})(?!\\p{L})`, 'iu'),
|
|
136
|
+
];
|
|
137
|
+
/**
|
|
138
|
+
* Does the owner's message tell buddi which language to answer in ("answer in
|
|
139
|
+
* French", "give me a Spanish summary", "en français s'il te plaît") or ask
|
|
140
|
+
* for a translation? Then the answer's language is the owner's call, not the
|
|
141
|
+
* guard's. A language named as a subject ("what happened in French politics
|
|
142
|
+
* today?", "the French news") is no instruction.
|
|
143
|
+
*/
|
|
144
|
+
export function namesALanguage(message) {
|
|
145
|
+
return INSTRUCTIONS.some((re) => re.test(message));
|
|
146
|
+
}
|
|
147
|
+
/** The six-language code the profile's "Answer me in" names, if it names one of them. */
|
|
148
|
+
export function profileLanguageCode(profile) {
|
|
149
|
+
const base = languageTag(profile)?.split('-')[0];
|
|
150
|
+
return base && base in LANGUAGE_NAMES ? base : null;
|
|
151
|
+
}
|
|
152
|
+
/** Below this many own words, a message too short to tell leans on the profile language. */
|
|
153
|
+
export const SHORT_MESSAGE_WORDS = 8;
|
|
154
|
+
/**
|
|
155
|
+
* The language the owner's message is in, read from its opening: the
|
|
156
|
+
* instruction comes first ("Résume cet article :" over a pasted English
|
|
157
|
+
* article). Text before the first blank line when the message has more than
|
|
158
|
+
* one paragraph, else its first forty own words.
|
|
159
|
+
*/
|
|
160
|
+
export function messageLanguage(message) {
|
|
161
|
+
const head = message.split(/\n\s*\n/)[0] ?? '';
|
|
162
|
+
return detectLanguage(ownWords(head).slice(0, 40).join(' '), { minHits: 2 });
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Is this reply in the wrong language? Only when its language is confidently
|
|
166
|
+
* one of the six and differs from the anchor: the owner's message when it
|
|
167
|
+
* can be told, else the profile language, and the profile only for a short
|
|
168
|
+
* message (a long one that cannot be told is likely in a seventh language).
|
|
169
|
+
* Never for a short reply, a code-dominant one, a message that tells buddi
|
|
170
|
+
* which language to answer in or asks for a translation, or when nothing
|
|
171
|
+
* anchors the answer. A message, or an earlier one, that names an answer
|
|
172
|
+
* language hands the choice to the owner.
|
|
173
|
+
*/
|
|
174
|
+
export function offLanguage(reply, message, profile,
|
|
175
|
+
/** The owner's earlier words in the conversation: "answer in French from now on" still holds. */
|
|
176
|
+
earlier = '') {
|
|
177
|
+
if (codeShare(reply) >= 0.4)
|
|
178
|
+
return null;
|
|
179
|
+
const scored = scoreLanguage(reply);
|
|
180
|
+
if (scored.words < MIN_REPLY_WORDS || !scored.language)
|
|
181
|
+
return null;
|
|
182
|
+
if ((message && namesALanguage(message)) || namesALanguage(earlier))
|
|
183
|
+
return null;
|
|
184
|
+
const asked = message ? messageLanguage(message) : null;
|
|
185
|
+
const short = !message || ownWords(message).length < SHORT_MESSAGE_WORDS;
|
|
186
|
+
const anchor = asked ?? (short ? profileLanguageCode(profile) : null);
|
|
187
|
+
if (!anchor || scored.language === anchor)
|
|
188
|
+
return null;
|
|
189
|
+
return { reply: scored.language, target: LANGUAGE_NAMES[anchor] };
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=language.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language.js","sourceRoot":"","sources":["../src/language.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1C,gDAAgD;AAChD,MAAM,CAAC,MAAM,cAAc,GAA2C;IACpE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,SAAS;CAC1F,CAAC;AAEF,uEAAuE;AACvE,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,OAAO,aAAa,QAAQ,GAAG,CAAC;AAClC,CAAC;AAED,0DAA0D;AAC1D,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAElC,MAAM,SAAS,GAA2C;IACxD,EAAE,EAAE,6hBAA6hB;IACjiB,EAAE,EAAE,qdAAqd;IACzd,EAAE,EAAE,6XAA6X;IACjY,EAAE,EAAE,+YAA+Y;IACnZ,EAAE,EAAE,2VAA2V;IAC/V,EAAE,EAAE,0VAA0V;CAC/V,CAAC;AAEF,+EAA+E;AAC/E,MAAM,OAAO,GAA+D,CAAC,GAAG,EAAE;IAChF,MAAM,MAAM,GAAG,IAAI,GAAG,EAA0B,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAkC,EAAE,CAAC;QACvF,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAAE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACxG,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAA2B,CAAC,CAAC,CAAC,CAAC,CAAC;AAChI,CAAC,CAAC,EAAE,CAAC;AAEL,kDAAkD;AAClD,MAAM,KAAK,GAA0C,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAEvH,MAAM,KAAK,GAAG,uBAAuB,CAAC;AACtC,MAAM,MAAM,GAAG,YAAY,CAAC;AAE5B,wCAAwC;AACxC,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC;IAC9C,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAC1B,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC;IAC9E,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC;IACnG,OAAO,IAAI,GAAG,KAAK,CAAC;AACtB,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,MAAM,KAAK,GAAG,IAAI;SACf,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC;SAC1B,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC;SAC5B,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC;SAChC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC;QAC9B,uEAAuE;QACvE,yEAAyE;SACxE,OAAO,CAAC,sCAAsC,EAAE,GAAG,CAAC,CAAC;IACxD,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;AACrD,CAAC;AAUD,4FAA4F;AAC5F,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAA6B,EAAE;IACzE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAiC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;IAC1F,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;QAC3E,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK;YAAE,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,MAAM,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;IAC7E,CAAC;IACD,MAAM,MAAM,GAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAmC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrG,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAE,EAAE,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC;IAClG,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;AAC/E,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,OAA6B,EAAE;IAC1E,OAAO,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC;AAC5C,CAAC;AAED,MAAM,IAAI,GACR,+GAA+G;IAC/G,0HAA0H;IAC1H,wGAAwG,CAAC;AAC3G,0FAA0F;AAC1F,MAAM,QAAQ,GAAG,GAAG,IAAI,2PAA2P,CAAC;AACpR,2FAA2F;AAC3F,MAAM,KAAK,GACT,0FAA0F;IAC1F,+EAA+E;IAC/E,yHAAyH,CAAC;AAC5H,mEAAmE;AACnE,MAAM,IAAI,GACR,8FAA8F;IAC9F,mGAAmG;IACnG,4DAA4D;IAC5D,oEAAoE;IACpE,oDAAoD;IACpD,gDAAgD,CAAC;AACnD,4FAA4F;AAC5F,MAAM,OAAO,GAAG,iHAAiH,CAAC;AAClI,MAAM,IAAI,GACR,4EAA4E;IAC5E,yCAAyC;IACzC,8CAA8C;IAC9C,6GAA6G,CAAC;AAEhH,MAAM,YAAY,GAAsB;IACtC,6EAA6E;IAC7E,2EAA2E;IAC3E,uEAAuE;IACvE,sEAAsE;IACtE,yEAAyE;IACzE,IAAI,MAAM,CAAC,kDAAkD,IAAI,qCAAqC,KAAK,cAAc,EAAE,KAAK,CAAC;IACjI,uEAAuE;IACvE,sDAAsD;IACtD,IAAI,MAAM,CAAC,iBAAiB,IAAI,iBAAiB,OAAO,kDAAkD,IAAI,aAAa,EAAE,IAAI,CAAC;IAClI,6CAA6C;IAC7C,IAAI,MAAM,CAAC,iBAAiB,IAAI,WAAW,IAAI,aAAa,EAAE,IAAI,CAAC;IACnE,qDAAqD;IACrD,IAAI,MAAM,CAAC,iBAAiB,IAAI,WAAW,QAAQ,aAAa,EAAE,IAAI,CAAC;CACxE,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,mBAAmB,CAAC,OAAkC;IACpE,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,OAAO,IAAI,IAAI,IAAI,IAAI,cAAc,CAAC,CAAC,CAAE,IAAqB,CAAC,CAAC,CAAC,IAAI,CAAC;AACxE,CAAC;AASD,4FAA4F;AAC5F,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,OAAO,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CACzB,KAAa,EACb,OAA2B,EAC3B,OAAkC;AAClC,iGAAiG;AACjG,OAAO,GAAG,EAAE;IAEZ,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC;IACzC,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,KAAK,GAAG,eAAe,IAAI,CAAC,MAAM,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IACpE,IAAI,CAAC,OAAO,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACjF,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,MAAM,KAAK,GAAG,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,mBAAmB,CAAC;IACzE,MAAM,MAAM,GAAG,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACtE,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACvD,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;AACpE,CAAC"}
|
|
@@ -31,6 +31,13 @@ export interface RunAgentOptions {
|
|
|
31
31
|
conversationId: string;
|
|
32
32
|
/** The owner's turn. Omitted only when `resume` carries the turn instead. */
|
|
33
33
|
userMessage?: string;
|
|
34
|
+
/**
|
|
35
|
+
* The owner's own words in `userMessage`, when buddi composed more around
|
|
36
|
+
* them (a mission's prompt under its context material and buddi's English
|
|
37
|
+
* instructions). The reply-language guard reads these, not buddi's text.
|
|
38
|
+
* Defaults to `userMessage`.
|
|
39
|
+
*/
|
|
40
|
+
ownerText?: string;
|
|
34
41
|
/**
|
|
35
42
|
* An extra system line appended to the agent's prompt for this run only.
|
|
36
43
|
*
|
|
@@ -79,7 +86,8 @@ export interface RunAgentOptions {
|
|
|
79
86
|
/**
|
|
80
87
|
* The words streamed through `onDelta` for the turn just written are
|
|
81
88
|
* withdrawn: the grounding guard held that answer back (it cited sources
|
|
82
|
-
* nothing in the run had read)
|
|
89
|
+
* nothing in the run had read), or the reply-language guard did (it was in
|
|
90
|
+
* the wrong language), and the model is answering again. A surface
|
|
83
91
|
* drawing the live text clears it; nothing of it was stored. Never awaited.
|
|
84
92
|
*/
|
|
85
93
|
onRetract?: () => void;
|
|
@@ -220,6 +228,12 @@ export interface Interjection {
|
|
|
220
228
|
/** Whoever queued it knows it by this. The loop only hands it back. */
|
|
221
229
|
id?: string;
|
|
222
230
|
text: string;
|
|
231
|
+
/**
|
|
232
|
+
* Files the owner sent with it. Hydrated when the loop takes the line — the
|
|
233
|
+
* bytes go to the model in the same tool-results turn as the words — and
|
|
234
|
+
* stored as references, the way an opening turn's files are.
|
|
235
|
+
*/
|
|
236
|
+
attachments?: readonly AttachmentRef[];
|
|
223
237
|
}
|
|
224
238
|
/**
|
|
225
239
|
* Where a run hears about what the owner said while it worked.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAA0G,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEzN,OAAO,KAAK,EAGV,YAAY,EAEZ,cAAc,EACd,eAAe,EACf,UAAU,EACV,KAAK,EACL,eAAe,EAChB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,8 +14,9 @@ import { primeSecretScrubber, scrubDeep, scrubText } from '@buddi/core';
|
|
|
14
14
|
import { ProviderError, isThinkingBlock } from './anthropic.js';
|
|
15
15
|
import { NATIVE_SEARCH_SYSTEM_NOTE, planNativeSearch } from './search.js';
|
|
16
16
|
import { GROUNDING_RETRY_TEXT, citationSignals, citesUnread } from './grounding.js';
|
|
17
|
+
import { languageRetryText, offLanguage } from './language.js';
|
|
17
18
|
import { compactObservations } from './projection.js';
|
|
18
|
-
import { degradeMessages, DEFAULT_CAPABILITIES, } from './capabilities.js';
|
|
19
|
+
import { degradeContent, degradeMessages, DEFAULT_CAPABILITIES, } from './capabilities.js';
|
|
19
20
|
import { assertAttachmentCount, hydrateContent, hydrateMessages, toArtifactRefBlocks, } from './attachments.js';
|
|
20
21
|
/**
|
|
21
22
|
* The in-memory queue a surface with no durable store of its own hands to a
|
|
@@ -575,8 +576,10 @@ async function runAgentOnce(opts) {
|
|
|
575
576
|
const history = compactObservations(opts.transcript ? await opts.transcript.load() : await loadMessages(pool, conversationId));
|
|
576
577
|
// Stored history carries artifact_ref blocks; the provider needs the bytes.
|
|
577
578
|
const replayed = await hydrateMessages(history, opts.loadArtifact);
|
|
579
|
+
// Files sent with no words: the turn is the files alone. Providers refuse an
|
|
580
|
+
// empty text block, and each file already carries its own note to the model.
|
|
578
581
|
const userBlocks = [
|
|
579
|
-
{ type: 'text', text: openingText },
|
|
582
|
+
...(openingText.trim() === '' && attachments.length > 0 ? [] : [{ type: 'text', text: openingText }]),
|
|
580
583
|
...toArtifactRefBlocks(attachments),
|
|
581
584
|
];
|
|
582
585
|
const sentUserBlocks = await hydrateContent(userBlocks, opts.loadArtifact, {
|
|
@@ -685,9 +688,20 @@ async function runAgentOnce(opts) {
|
|
|
685
688
|
*/
|
|
686
689
|
let read = false;
|
|
687
690
|
let regrounded = false;
|
|
688
|
-
/**
|
|
691
|
+
/**
|
|
692
|
+
* The latest answer a guard held back (grounding or language), delivered if
|
|
693
|
+
* the retry says nothing. One slot for both, so a fallback never brings
|
|
694
|
+
* back an answer an earlier guard had already replaced.
|
|
695
|
+
*/
|
|
689
696
|
let heldBack;
|
|
690
697
|
let unchecked = false;
|
|
698
|
+
/**
|
|
699
|
+
* The reply-language guard (docs/system-context.md, Reply language).
|
|
700
|
+
* `relanguaged`: an answer in the wrong language was held back once and the
|
|
701
|
+
* model asked to answer in the owner's; whatever comes next is delivered.
|
|
702
|
+
* One retry per turn across both guards: neither fires after the other.
|
|
703
|
+
*/
|
|
704
|
+
let relanguaged = false;
|
|
691
705
|
/**
|
|
692
706
|
* What the owner added, leased for the step that has not happened yet.
|
|
693
707
|
*
|
|
@@ -816,14 +830,16 @@ async function runAgentOnce(opts) {
|
|
|
816
830
|
const finalAnswer = toolUses.length === 0 && res.stopReason !== 'pause_turn' && res.stopReason !== 'max_tokens';
|
|
817
831
|
if (finalAnswer && !read && resume === undefined && !waitingForOwner && (turnText !== '' || regrounded)) {
|
|
818
832
|
if (regrounded) {
|
|
819
|
-
unchecked = true;
|
|
820
833
|
// A retry that said nothing: the held-back answer goes out, flagged,
|
|
821
834
|
// rather than an empty reply.
|
|
822
835
|
if (turnText === '' && heldBack) {
|
|
823
836
|
delivered = heldBack.content;
|
|
824
837
|
turnText = heldBack.text;
|
|
825
838
|
}
|
|
826
|
-
|
|
839
|
+
if (!unchecked) {
|
|
840
|
+
unchecked = true;
|
|
841
|
+
await appendEvent(pool, 'run.grounding', { stage: 'unchecked', agentId: agent.id, ...(opts.runId ? { runId: opts.runId } : {}) }, conversationId);
|
|
842
|
+
}
|
|
827
843
|
}
|
|
828
844
|
else {
|
|
829
845
|
// What the agent legitimately carries counts as held too: its own
|
|
@@ -831,7 +847,9 @@ async function runAgentOnce(opts) {
|
|
|
831
847
|
const known = [knownText(messages.slice(0, -1)), agent.systemPrompt, memory, platformContext?.prompt ?? ''].join('\n');
|
|
832
848
|
if (citesUnread(turnText, known)) {
|
|
833
849
|
regrounded = true;
|
|
834
|
-
|
|
850
|
+
// One retry per turn: a language rewrite that cites unread sources
|
|
851
|
+
// is delivered flagged, not sent back a second time.
|
|
852
|
+
const budgetLeft = !relanguaged && turns - exemptTurns < agent.maxTurns && turns < agent.maxTurns + MAX_EXEMPT_TURNS;
|
|
835
853
|
await appendEvent(pool, 'run.grounding', {
|
|
836
854
|
stage: budgetLeft ? 'retried' : 'unchecked',
|
|
837
855
|
agentId: agent.id,
|
|
@@ -851,6 +869,49 @@ async function runAgentOnce(opts) {
|
|
|
851
869
|
}
|
|
852
870
|
}
|
|
853
871
|
}
|
|
872
|
+
/*
|
|
873
|
+
* The reply-language guard. A final answer whose language is clearly one
|
|
874
|
+
* of six, and matches neither the owner's message (when that can be
|
|
875
|
+
* told) nor their profile language, is held back the way the grounding
|
|
876
|
+
* guard holds one back: not stored, not said, its streamed words
|
|
877
|
+
* withdrawn. The model is told "Answer in <language>." once, in a turn
|
|
878
|
+
* the transcript does not keep, and whatever it answers is delivered.
|
|
879
|
+
* Only the run the owner reads: a delegate's answer is quoted into its
|
|
880
|
+
* caller's, and a decided approval coming back carries no owner message.
|
|
881
|
+
* `offLanguage` is precision-first; see language.ts.
|
|
882
|
+
*/
|
|
883
|
+
if (finalAnswer && resume === undefined && (ctx.delegationDepth ?? 0) === 0 && !regrounded) {
|
|
884
|
+
if (relanguaged) {
|
|
885
|
+
// A rewrite that said nothing: the held-back answer goes out.
|
|
886
|
+
if (turnText === '' && heldBack) {
|
|
887
|
+
delivered = heldBack.content;
|
|
888
|
+
turnText = heldBack.text;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
else if (turnText !== '') {
|
|
892
|
+
const off = offLanguage(turnText, opts.ownerText ?? userMessage, platformContext?.language, ownerWords(messages.slice(0, -1)));
|
|
893
|
+
if (off) {
|
|
894
|
+
relanguaged = true;
|
|
895
|
+
const budgetLeft = turns - exemptTurns < agent.maxTurns && turns < agent.maxTurns + MAX_EXEMPT_TURNS;
|
|
896
|
+
await appendEvent(pool, 'run.language', {
|
|
897
|
+
stage: budgetLeft ? 'retried' : 'kept',
|
|
898
|
+
agentId: agent.id,
|
|
899
|
+
reply: off.reply,
|
|
900
|
+
target: off.target,
|
|
901
|
+
...(opts.runId ? { runId: opts.runId } : {}),
|
|
902
|
+
}, conversationId);
|
|
903
|
+
if (budgetLeft) {
|
|
904
|
+
heldBack = { content: delivered, text: turnText };
|
|
905
|
+
try {
|
|
906
|
+
opts.onRetract?.();
|
|
907
|
+
}
|
|
908
|
+
catch { /* a surface's drawing never decides a run */ }
|
|
909
|
+
messages.push({ role: 'user', content: [{ type: 'text', text: languageRetryText(off.target) }] });
|
|
910
|
+
continue;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
}
|
|
854
915
|
await persistMessage(pool, conversationId, 'assistant', persistable(delivered), opts.transcript?.speaker);
|
|
855
916
|
if (turnText) {
|
|
856
917
|
spoken.push({ text: turnText, beforeToolCall: toolUses.length > 0 });
|
|
@@ -1041,17 +1102,30 @@ async function runAgentOnce(opts) {
|
|
|
1041
1102
|
if (toolUses.length > 0 && toolUses.every((call) => registry.hasOwnBudget(call.name)))
|
|
1042
1103
|
exemptTurns++;
|
|
1043
1104
|
const lastTurn = turns - exemptTurns >= agent.maxTurns || turns >= agent.maxTurns + MAX_EXEMPT_TURNS || pendingActionId !== undefined || ctx.signal?.aborted === true;
|
|
1044
|
-
const leased = lastTurn ? [] : ((await opts.interjections?.lease()) ?? [])
|
|
1105
|
+
const leased = lastTurn ? [] : ((await opts.interjections?.lease()) ?? [])
|
|
1106
|
+
.filter((item) => item.text.trim() !== '' || (item.attachments?.length ?? 0) > 0);
|
|
1045
1107
|
// What the model is shown, and what the transcript keeps: the framing is
|
|
1046
1108
|
// for the model — the record holds the owner's own words.
|
|
1047
|
-
const
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1109
|
+
const said = leased.map((item) => item.text).filter((text) => text.trim() !== '');
|
|
1110
|
+
// Files that came with them: references in the record, the bytes (or the
|
|
1111
|
+
// note, for what a model cannot look at) in what is sent. Never capped
|
|
1112
|
+
// into a failure here — each file was accepted when it was uploaded, and
|
|
1113
|
+
// a run must not die between two tool calls over one; an oversize one
|
|
1114
|
+
// goes as a placeholder, the way a replayed one does.
|
|
1115
|
+
const leasedRefs = toArtifactRefBlocks(leased.flatMap((item) => item.attachments ?? []));
|
|
1116
|
+
const sentRefs = leasedRefs.length === 0 ? [] : degradeContent(await hydrateContent(leasedRefs, opts.loadArtifact), capabilities);
|
|
1117
|
+
const spokenBlocks = [
|
|
1118
|
+
...(said.length === 0 ? [] : [{ type: 'text', text: interjectionText(said) }]),
|
|
1119
|
+
...sentRefs,
|
|
1120
|
+
];
|
|
1121
|
+
const storedBlocks = [
|
|
1122
|
+
...(said.length === 0 ? [] : [{ type: 'text', text: said.map((text) => text.trim()).join('\n\n') }]),
|
|
1123
|
+
...leasedRefs,
|
|
1124
|
+
];
|
|
1125
|
+
const uploaded = leased.flatMap((item) => item.attachments ?? [])
|
|
1126
|
+
.map((a) => ({ artifactId: a.artifactId, kind: 'uploaded', agentId: null }));
|
|
1053
1127
|
messages.push({ role: 'user', content: [...results, ...spokenBlocks] });
|
|
1054
|
-
const turnMessageId = await persistMessage(pool, conversationId, 'user', [...results, ...storedBlocks], opts.transcript?.speaker, produced);
|
|
1128
|
+
const turnMessageId = await persistMessage(pool, conversationId, 'user', [...results, ...storedBlocks], opts.transcript?.speaker, [...produced, ...uploaded]);
|
|
1055
1129
|
if (leased.length > 0) {
|
|
1056
1130
|
inFlight = leased;
|
|
1057
1131
|
inFlightMessageId = turnMessageId;
|
|
@@ -1155,6 +1229,21 @@ async function runAgentOnce(opts) {
|
|
|
1155
1229
|
...(unchecked ? { unchecked: true } : {}),
|
|
1156
1230
|
};
|
|
1157
1231
|
}
|
|
1232
|
+
/**
|
|
1233
|
+
* The owner's last few messages, for the reply-language guard: an owner who
|
|
1234
|
+
* said "answer in Spanish from now on" a turn ago still meant it.
|
|
1235
|
+
*/
|
|
1236
|
+
function ownerWords(messages) {
|
|
1237
|
+
const said = [];
|
|
1238
|
+
for (const message of messages) {
|
|
1239
|
+
if (message.role !== 'user')
|
|
1240
|
+
continue;
|
|
1241
|
+
const text = message.content.filter((b) => b.type === 'text').map((b) => b.text).join('\n');
|
|
1242
|
+
if (text.trim() !== '')
|
|
1243
|
+
said.push(text);
|
|
1244
|
+
}
|
|
1245
|
+
return said.slice(-6).join('\n');
|
|
1246
|
+
}
|
|
1158
1247
|
/**
|
|
1159
1248
|
* Everything the conversation held before an answer, as one string, for the
|
|
1160
1249
|
* grounding guard: a source the owner named, or a tool returned earlier, is
|