@vellumai/assistant 0.4.48 → 0.4.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (423) hide show
  1. package/ARCHITECTURE.md +26 -35
  2. package/README.md +5 -26
  3. package/docs/architecture/integrations.md +45 -41
  4. package/docs/architecture/keychain-broker.md +3 -3
  5. package/docs/architecture/memory.md +180 -119
  6. package/docs/runbook-trusted-contacts.md +3 -8
  7. package/hook-templates/debug-prompt-logger/hook.json +1 -1
  8. package/hook-templates/debug-prompt-logger/run.sh +1 -3
  9. package/package.json +2 -2
  10. package/src/__tests__/actor-token-service.test.ts +0 -1
  11. package/src/__tests__/agent-loop.test.ts +3 -1
  12. package/src/__tests__/anthropic-provider.test.ts +249 -2
  13. package/src/__tests__/approval-cascade.test.ts +796 -0
  14. package/src/__tests__/approval-primitive.test.ts +0 -1
  15. package/src/__tests__/approval-routes-http.test.ts +4 -0
  16. package/src/__tests__/assistant-attachments.test.ts +12 -34
  17. package/src/__tests__/assistant-feature-flag-guard.test.ts +0 -23
  18. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +76 -0
  19. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -1
  20. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
  21. package/src/__tests__/canonical-guardian-store.test.ts +95 -0
  22. package/src/__tests__/channel-guardian.test.ts +0 -2
  23. package/src/__tests__/channel-readiness-routes.test.ts +15 -6
  24. package/src/__tests__/channel-readiness-service.test.ts +10 -9
  25. package/src/__tests__/checker.test.ts +13 -20
  26. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
  27. package/src/__tests__/computer-use-tools.test.ts +2 -19
  28. package/src/__tests__/config-schema.test.ts +1 -68
  29. package/src/__tests__/config-watcher.test.ts +0 -1
  30. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  31. package/src/__tests__/context-image-dimensions.test.ts +332 -0
  32. package/src/__tests__/context-memory-e2e.test.ts +11 -100
  33. package/src/__tests__/context-token-estimator.test.ts +196 -13
  34. package/src/__tests__/conversation-attention-store.test.ts +0 -1
  35. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  36. package/src/__tests__/conversation-routes-guardian-reply.test.ts +152 -0
  37. package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
  38. package/src/__tests__/credential-metadata-store.test.ts +64 -73
  39. package/src/__tests__/credential-security-e2e.test.ts +1 -0
  40. package/src/__tests__/credential-security-invariants.test.ts +13 -7
  41. package/src/__tests__/credential-vault-unit.test.ts +284 -49
  42. package/src/__tests__/credential-vault.test.ts +150 -16
  43. package/src/__tests__/credentials-cli.test.ts +71 -0
  44. package/src/__tests__/cu-unified-flow.test.ts +532 -0
  45. package/src/__tests__/date-context.test.ts +93 -77
  46. package/src/__tests__/deterministic-verification-control-plane.test.ts +64 -0
  47. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  48. package/src/__tests__/ephemeral-permissions.test.ts +3 -3
  49. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  50. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
  51. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
  52. package/src/__tests__/guardian-routing-invariants.test.ts +93 -1
  53. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  54. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -39
  55. package/src/__tests__/heartbeat-service.test.ts +0 -1
  56. package/src/__tests__/history-repair.test.ts +245 -0
  57. package/src/__tests__/host-cu-proxy.test.ts +791 -0
  58. package/src/__tests__/host-shell-tool.test.ts +27 -15
  59. package/src/__tests__/http-user-message-parity.test.ts +2 -0
  60. package/src/__tests__/ingress-url-consistency.test.ts +14 -21
  61. package/src/__tests__/integration-status.test.ts +32 -51
  62. package/src/__tests__/intent-routing.test.ts +0 -1
  63. package/src/__tests__/invite-redemption-service.test.ts +65 -1
  64. package/src/__tests__/invite-routes-http.test.ts +10 -9
  65. package/src/__tests__/keychain-broker-client.test.ts +14 -46
  66. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +56 -18
  67. package/src/__tests__/memory-lifecycle-e2e.test.ts +244 -387
  68. package/src/__tests__/memory-recall-quality.test.ts +244 -407
  69. package/src/__tests__/memory-regressions.experimental.test.ts +126 -101
  70. package/src/__tests__/memory-regressions.test.ts +477 -2841
  71. package/src/__tests__/memory-retrieval.benchmark.test.ts +33 -150
  72. package/src/__tests__/memory-upsert-concurrency.test.ts +5 -244
  73. package/src/__tests__/mime-builder.test.ts +28 -0
  74. package/src/__tests__/native-web-search.test.ts +1 -0
  75. package/src/__tests__/notification-routing-intent.test.ts +0 -1
  76. package/src/__tests__/oauth-cli.test.ts +941 -15
  77. package/src/__tests__/oauth-provider-profiles.test.ts +9 -9
  78. package/src/__tests__/oauth-scope-policy.test.ts +4 -6
  79. package/src/__tests__/oauth-store.test.ts +870 -0
  80. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
  81. package/src/__tests__/provider-error-scenarios.test.ts +0 -1
  82. package/src/__tests__/provider-streaming.benchmark.test.ts +0 -1
  83. package/src/__tests__/public-ingress-urls.test.ts +15 -21
  84. package/src/__tests__/qdrant-collection-migration.test.ts +53 -8
  85. package/src/__tests__/recording-handler.test.ts +3 -4
  86. package/src/__tests__/registry.test.ts +2 -3
  87. package/src/__tests__/relay-server.test.ts +46 -1
  88. package/src/__tests__/runtime-events-sse.test.ts +55 -7
  89. package/src/__tests__/schedule-store.test.ts +0 -1
  90. package/src/__tests__/schedule-tools.test.ts +32 -0
  91. package/src/__tests__/scheduler-recurrence.test.ts +0 -1
  92. package/src/__tests__/scoped-approval-grants.test.ts +0 -1
  93. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
  94. package/src/__tests__/script-proxy-certs.test.ts +1 -1
  95. package/src/__tests__/secret-ingress-handler.test.ts +0 -1
  96. package/src/__tests__/secret-onetime-send.test.ts +1 -0
  97. package/src/__tests__/secure-keys.test.ts +7 -2
  98. package/src/__tests__/send-endpoint-busy.test.ts +24 -6
  99. package/src/__tests__/sequence-store.test.ts +0 -1
  100. package/src/__tests__/session-abort-tool-results.test.ts +1 -14
  101. package/src/__tests__/session-agent-loop-overflow.test.ts +1583 -0
  102. package/src/__tests__/session-agent-loop.test.ts +19 -15
  103. package/src/__tests__/session-confirmation-signals.test.ts +1 -15
  104. package/src/__tests__/session-error.test.ts +124 -2
  105. package/src/__tests__/session-history-web-search.test.ts +918 -0
  106. package/src/__tests__/session-init.benchmark.test.ts +4 -5
  107. package/src/__tests__/session-pre-run-repair.test.ts +1 -14
  108. package/src/__tests__/session-provider-retry-repair.test.ts +25 -28
  109. package/src/__tests__/session-queue.test.ts +37 -27
  110. package/src/__tests__/session-runtime-assembly.test.ts +54 -0
  111. package/src/__tests__/session-slash-known.test.ts +1 -15
  112. package/src/__tests__/session-slash-queue.test.ts +1 -15
  113. package/src/__tests__/session-slash-unknown.test.ts +1 -15
  114. package/src/__tests__/session-workspace-cache-state.test.ts +3 -33
  115. package/src/__tests__/session-workspace-injection.test.ts +3 -37
  116. package/src/__tests__/session-workspace-tool-tracking.test.ts +3 -37
  117. package/src/__tests__/skill-include-graph.test.ts +66 -0
  118. package/src/__tests__/skill-load-feature-flag.test.ts +0 -1
  119. package/src/__tests__/skill-load-tool.test.ts +149 -1
  120. package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
  121. package/src/__tests__/skills-install-extract.test.ts +93 -0
  122. package/src/__tests__/skills-uninstall.test.ts +1 -1
  123. package/src/__tests__/skills.test.ts +3 -3
  124. package/src/__tests__/skillssh-registry.test.ts +451 -0
  125. package/src/__tests__/slack-channel-config.test.ts +67 -3
  126. package/src/__tests__/slack-share-routes.test.ts +17 -19
  127. package/src/__tests__/system-prompt.test.ts +0 -1
  128. package/src/__tests__/telegram-invite-adapter.test.ts +18 -22
  129. package/src/__tests__/terminal-tools.test.ts +4 -3
  130. package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
  131. package/src/__tests__/tool-approval-handler.test.ts +0 -1
  132. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
  133. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
  134. package/src/__tests__/tool-executor-shell-integration.test.ts +0 -1
  135. package/src/__tests__/tool-executor.test.ts +0 -1
  136. package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
  137. package/src/__tests__/trust-store-pattern-matches.test.ts +29 -0
  138. package/src/__tests__/trust-store.test.ts +7 -13
  139. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  140. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  141. package/src/__tests__/twilio-routes.test.ts +0 -16
  142. package/src/__tests__/verification-control-plane-policy.test.ts +0 -1
  143. package/src/__tests__/voice-invite-redemption.test.ts +32 -1
  144. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
  145. package/src/agent/ax-tree-compaction.test.ts +286 -0
  146. package/src/agent/loop.ts +104 -131
  147. package/src/approvals/AGENTS.md +1 -1
  148. package/src/approvals/guardian-request-resolvers.ts +14 -2
  149. package/src/bundler/compiler-tools.ts +66 -2
  150. package/src/calls/call-domain.ts +133 -6
  151. package/src/calls/call-store.ts +6 -0
  152. package/src/calls/relay-server.ts +52 -18
  153. package/src/calls/relay-setup-router.ts +17 -1
  154. package/src/calls/twilio-config.ts +3 -8
  155. package/src/calls/twilio-routes.ts +1 -2
  156. package/src/calls/types.ts +3 -1
  157. package/src/calls/voice-ingress-preflight.ts +1 -1
  158. package/src/cli/commands/browser-relay.ts +18 -12
  159. package/src/cli/commands/completions.ts +0 -3
  160. package/src/cli/commands/credentials.ts +101 -15
  161. package/src/cli/commands/doctor.ts +4 -3
  162. package/src/cli/commands/mcp.ts +46 -59
  163. package/src/cli/commands/memory.ts +16 -165
  164. package/src/cli/commands/oauth/apps.ts +284 -0
  165. package/src/cli/commands/oauth/connections.ts +633 -0
  166. package/src/cli/commands/oauth/index.ts +52 -0
  167. package/src/cli/commands/oauth/providers.ts +256 -0
  168. package/src/cli/commands/sessions.ts +5 -2
  169. package/src/cli/commands/skills.ts +177 -339
  170. package/src/cli/http-client.ts +0 -20
  171. package/src/cli/main-screen.tsx +2 -2
  172. package/src/cli/program.ts +6 -11
  173. package/src/cli/reference.ts +1 -3
  174. package/src/cli.ts +4 -10
  175. package/src/config/assistant-feature-flags.ts +0 -3
  176. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
  177. package/src/config/bundled-skills/computer-use/SKILL.md +3 -6
  178. package/src/config/bundled-skills/computer-use/TOOLS.json +23 -5
  179. package/src/config/bundled-skills/computer-use/tools/{computer-use-request-control.ts → computer-use-observe.ts} +1 -5
  180. package/src/config/bundled-skills/google-calendar/calendar-client.ts +21 -16
  181. package/src/config/bundled-skills/messaging/tools/shared.ts +1 -4
  182. package/src/config/bundled-skills/settings/SKILL.md +1 -1
  183. package/src/config/bundled-skills/settings/TOOLS.json +2 -8
  184. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +5 -33
  185. package/src/config/bundled-tool-registry.ts +2 -5
  186. package/src/config/env-registry.ts +14 -83
  187. package/src/config/env.ts +11 -50
  188. package/src/config/feature-flag-registry.json +16 -16
  189. package/src/config/loader.ts +0 -6
  190. package/src/config/schema.ts +4 -13
  191. package/src/config/schemas/memory-lifecycle.ts +0 -9
  192. package/src/config/schemas/memory-processing.ts +0 -180
  193. package/src/config/schemas/memory-retrieval.ts +32 -104
  194. package/src/config/schemas/memory.ts +0 -10
  195. package/src/config/skills.ts +21 -2
  196. package/src/config/types.ts +0 -4
  197. package/src/context/image-dimensions.ts +229 -0
  198. package/src/context/token-estimator.ts +75 -12
  199. package/src/context/window-manager.ts +53 -11
  200. package/src/daemon/assistant-attachments.ts +1 -13
  201. package/src/daemon/config-watcher.ts +61 -3
  202. package/src/daemon/daemon-control.ts +1 -1
  203. package/src/daemon/date-context.ts +114 -31
  204. package/src/daemon/handlers/config-ingress.ts +8 -33
  205. package/src/daemon/handlers/config-slack-channel.ts +49 -46
  206. package/src/daemon/handlers/config-telegram.ts +32 -16
  207. package/src/daemon/handlers/sessions.ts +27 -36
  208. package/src/daemon/handlers/shared.ts +0 -130
  209. package/src/daemon/handlers/skills.ts +20 -1
  210. package/src/daemon/history-repair.ts +72 -8
  211. package/src/daemon/host-cu-proxy.ts +430 -0
  212. package/src/daemon/lifecycle.ts +67 -71
  213. package/src/daemon/mcp-reload-service.ts +2 -2
  214. package/src/daemon/message-protocol.ts +3 -0
  215. package/src/daemon/message-types/computer-use.ts +1 -129
  216. package/src/daemon/message-types/host-cu.ts +19 -0
  217. package/src/daemon/message-types/memory.ts +4 -16
  218. package/src/daemon/message-types/messages.ts +4 -0
  219. package/src/daemon/message-types/sessions.ts +4 -0
  220. package/src/daemon/server.ts +25 -21
  221. package/src/daemon/session-agent-loop-handlers.ts +40 -0
  222. package/src/daemon/session-agent-loop.ts +334 -48
  223. package/src/daemon/session-attachments.ts +1 -2
  224. package/src/daemon/session-error.ts +89 -6
  225. package/src/daemon/session-history.ts +17 -7
  226. package/src/daemon/session-media-retry.ts +6 -2
  227. package/src/daemon/session-memory.ts +69 -149
  228. package/src/daemon/session-process.ts +10 -1
  229. package/src/daemon/session-runtime-assembly.ts +49 -19
  230. package/src/daemon/session-slash.ts +1 -1
  231. package/src/daemon/session-surfaces.ts +43 -28
  232. package/src/daemon/session-tool-setup.ts +9 -10
  233. package/src/daemon/session.ts +150 -17
  234. package/src/daemon/tool-side-effects.ts +2 -8
  235. package/src/daemon/watch-handler.ts +2 -2
  236. package/src/events/tool-metrics-listener.ts +2 -2
  237. package/src/hooks/manager.ts +1 -4
  238. package/src/inbound/public-ingress-urls.ts +7 -7
  239. package/src/instrument.ts +61 -1
  240. package/src/logfire.ts +16 -5
  241. package/src/memory/admin.ts +2 -191
  242. package/src/memory/canonical-guardian-store.ts +38 -2
  243. package/src/memory/conversation-crud.ts +0 -33
  244. package/src/memory/conversation-key-store.ts +21 -0
  245. package/src/memory/conversation-queries.ts +22 -3
  246. package/src/memory/db-init.ts +32 -0
  247. package/src/memory/embedding-backend.ts +84 -8
  248. package/src/memory/embedding-types.ts +9 -1
  249. package/src/memory/indexer.ts +7 -46
  250. package/src/memory/items-extractor.ts +274 -76
  251. package/src/memory/job-handlers/backfill.ts +2 -127
  252. package/src/memory/job-handlers/cleanup.ts +2 -16
  253. package/src/memory/job-handlers/extraction.ts +2 -138
  254. package/src/memory/job-handlers/index-maintenance.ts +1 -6
  255. package/src/memory/job-handlers/summarization.ts +3 -148
  256. package/src/memory/job-utils.ts +21 -59
  257. package/src/memory/jobs-store.ts +1 -159
  258. package/src/memory/jobs-worker.ts +9 -52
  259. package/src/memory/migrations/104-core-indexes.ts +3 -3
  260. package/src/memory/migrations/149-oauth-tables.ts +62 -0
  261. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +98 -0
  262. package/src/memory/migrations/151-oauth-providers-ping-url.ts +11 -0
  263. package/src/memory/migrations/152-memory-item-supersession.ts +44 -0
  264. package/src/memory/migrations/153-drop-entity-tables.ts +15 -0
  265. package/src/memory/migrations/154-drop-fts.ts +20 -0
  266. package/src/memory/migrations/155-drop-conflicts.ts +7 -0
  267. package/src/memory/migrations/156-call-session-invite-metadata.ts +24 -0
  268. package/src/memory/migrations/index.ts +8 -0
  269. package/src/memory/qdrant-client.ts +148 -51
  270. package/src/memory/raw-query.ts +1 -1
  271. package/src/memory/retriever.test.ts +294 -273
  272. package/src/memory/retriever.ts +421 -645
  273. package/src/memory/schema/calls.ts +2 -0
  274. package/src/memory/schema/index.ts +1 -0
  275. package/src/memory/schema/memory-core.ts +3 -48
  276. package/src/memory/schema/oauth.ts +67 -0
  277. package/src/memory/search/formatting.ts +263 -176
  278. package/src/memory/search/lexical.ts +1 -254
  279. package/src/memory/search/ranking.ts +0 -455
  280. package/src/memory/search/semantic.ts +100 -14
  281. package/src/memory/search/staleness.ts +47 -0
  282. package/src/memory/search/tier-classifier.ts +21 -0
  283. package/src/memory/search/types.ts +15 -77
  284. package/src/memory/task-memory-cleanup.ts +4 -6
  285. package/src/messaging/provider.ts +4 -4
  286. package/src/messaging/providers/gmail/client.ts +82 -2
  287. package/src/messaging/providers/gmail/mime-builder.ts +17 -7
  288. package/src/messaging/providers/gmail/people-client.ts +10 -10
  289. package/src/messaging/providers/telegram-bot/adapter.ts +17 -17
  290. package/src/messaging/providers/whatsapp/adapter.ts +11 -8
  291. package/src/messaging/registry.ts +2 -32
  292. package/src/notifications/copy-composer.ts +0 -5
  293. package/src/notifications/signal.ts +4 -5
  294. package/src/oauth/byo-connection.test.ts +133 -25
  295. package/src/oauth/byo-connection.ts +22 -6
  296. package/src/oauth/connect-orchestrator.ts +113 -57
  297. package/src/oauth/connect-types.ts +17 -23
  298. package/src/oauth/connection-resolver.ts +35 -11
  299. package/src/oauth/connection.ts +1 -1
  300. package/src/oauth/manual-token-connection.ts +104 -0
  301. package/src/oauth/oauth-store.ts +582 -0
  302. package/src/oauth/platform-connection.test.ts +29 -0
  303. package/src/oauth/platform-connection.ts +6 -5
  304. package/src/oauth/provider-behaviors.ts +124 -0
  305. package/src/oauth/scope-policy.ts +9 -2
  306. package/src/oauth/seed-providers.ts +167 -0
  307. package/src/oauth/token-persistence.ts +81 -77
  308. package/src/permissions/checker.ts +3 -3
  309. package/src/permissions/defaults.ts +1 -1
  310. package/src/permissions/prompter.ts +10 -1
  311. package/src/permissions/trust-store.ts +36 -1
  312. package/src/playbooks/playbook-compiler.ts +1 -1
  313. package/src/prompts/__tests__/build-cli-reference-section.test.ts +3 -1
  314. package/src/prompts/system-prompt.ts +46 -42
  315. package/src/providers/anthropic/client.ts +59 -20
  316. package/src/providers/retry.ts +1 -27
  317. package/src/providers/types.ts +7 -1
  318. package/src/runtime/AGENTS.md +9 -0
  319. package/src/runtime/auth/route-policy.ts +6 -6
  320. package/src/runtime/channel-reply-delivery.ts +0 -40
  321. package/src/runtime/gateway-client.ts +0 -7
  322. package/src/runtime/guardian-reply-router.ts +24 -22
  323. package/src/runtime/http-server.ts +10 -8
  324. package/src/runtime/http-types.ts +2 -2
  325. package/src/runtime/invite-redemption-service.ts +19 -1
  326. package/src/runtime/invite-service.ts +25 -0
  327. package/src/runtime/middleware/twilio-validation.ts +1 -11
  328. package/src/runtime/pending-interactions.ts +14 -12
  329. package/src/runtime/routes/brain-graph-routes.ts +10 -90
  330. package/src/runtime/routes/channel-delivery-routes.ts +0 -1
  331. package/src/runtime/routes/conversation-routes.ts +81 -19
  332. package/src/runtime/routes/events-routes.ts +21 -11
  333. package/src/runtime/routes/host-cu-routes.ts +97 -0
  334. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -12
  335. package/src/runtime/routes/inbound-stages/background-dispatch.ts +12 -111
  336. package/src/runtime/routes/integrations/slack/share.ts +6 -7
  337. package/src/runtime/routes/log-export-routes.ts +126 -8
  338. package/src/runtime/routes/memory-item-routes.test.ts +754 -0
  339. package/src/runtime/routes/memory-item-routes.ts +503 -0
  340. package/src/runtime/routes/session-management-routes.ts +3 -3
  341. package/src/runtime/routes/settings-routes.ts +55 -48
  342. package/src/runtime/routes/surface-action-routes.ts +1 -1
  343. package/src/runtime/routes/trust-rules-routes.ts +14 -0
  344. package/src/runtime/routes/watch-routes.ts +128 -0
  345. package/src/runtime/routes/workspace-routes.ts +2 -1
  346. package/src/schedule/integration-status.ts +10 -9
  347. package/src/security/credential-key.ts +0 -156
  348. package/src/security/keychain-broker-client.ts +22 -10
  349. package/src/security/oauth2.ts +1 -1
  350. package/src/security/secure-keys.ts +25 -3
  351. package/src/security/token-manager.ts +137 -64
  352. package/src/skills/catalog-install.ts +414 -0
  353. package/src/skills/include-graph.ts +32 -0
  354. package/src/skills/skillssh-registry.ts +503 -0
  355. package/src/telegram/bot-username.ts +2 -3
  356. package/src/tools/assets/search.ts +5 -1
  357. package/src/tools/browser/network-recorder.ts +1 -1
  358. package/src/tools/browser/network-recording-types.ts +1 -1
  359. package/src/tools/computer-use/definitions.ts +36 -11
  360. package/src/tools/computer-use/registry.ts +5 -6
  361. package/src/tools/credentials/broker.ts +1 -2
  362. package/src/tools/credentials/metadata-store.ts +17 -121
  363. package/src/tools/credentials/vault.ts +92 -167
  364. package/src/tools/memory/definitions.ts +4 -13
  365. package/src/tools/memory/handlers.test.ts +83 -103
  366. package/src/tools/memory/handlers.ts +50 -85
  367. package/src/tools/registry.ts +2 -7
  368. package/src/tools/schedule/create.ts +8 -1
  369. package/src/tools/schedule/update.ts +8 -1
  370. package/src/tools/skills/load.ts +85 -3
  371. package/src/tools/watch/watch-state.ts +0 -12
  372. package/src/util/logger.ts +7 -41
  373. package/src/util/platform.ts +9 -28
  374. package/src/watcher/providers/google-calendar.ts +2 -1
  375. package/src/__tests__/clarification-resolver.test.ts +0 -193
  376. package/src/__tests__/computer-use-session-compaction.test.ts +0 -143
  377. package/src/__tests__/computer-use-session-lifecycle.test.ts +0 -322
  378. package/src/__tests__/computer-use-session-working-dir.test.ts +0 -166
  379. package/src/__tests__/computer-use-skill-baseline.test.ts +0 -78
  380. package/src/__tests__/computer-use-skill-endstate.test.ts +0 -105
  381. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +0 -249
  382. package/src/__tests__/conflict-intent-tokenization.test.ts +0 -160
  383. package/src/__tests__/conflict-policy.test.ts +0 -269
  384. package/src/__tests__/conflict-store.test.ts +0 -372
  385. package/src/__tests__/contradiction-checker.test.ts +0 -361
  386. package/src/__tests__/entity-extractor.test.ts +0 -211
  387. package/src/__tests__/entity-search.test.ts +0 -1117
  388. package/src/__tests__/profile-compiler.test.ts +0 -392
  389. package/src/__tests__/ride-shotgun-handler.test.ts +0 -452
  390. package/src/__tests__/session-conflict-gate.test.ts +0 -1228
  391. package/src/__tests__/session-profile-injection.test.ts +0 -557
  392. package/src/cli/commands/dev.ts +0 -129
  393. package/src/cli/commands/map.ts +0 -391
  394. package/src/cli/commands/oauth.ts +0 -77
  395. package/src/config/bundled-skills/knowledge-graph/SKILL.md +0 -25
  396. package/src/config/bundled-skills/knowledge-graph/TOOLS.json +0 -66
  397. package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +0 -211
  398. package/src/daemon/computer-use-session.ts +0 -1026
  399. package/src/daemon/ride-shotgun-handler.ts +0 -569
  400. package/src/daemon/session-conflict-gate.ts +0 -167
  401. package/src/daemon/session-dynamic-profile.ts +0 -77
  402. package/src/memory/clarification-resolver.ts +0 -417
  403. package/src/memory/conflict-intent.ts +0 -205
  404. package/src/memory/conflict-policy.ts +0 -127
  405. package/src/memory/conflict-store.ts +0 -410
  406. package/src/memory/contradiction-checker.ts +0 -508
  407. package/src/memory/entity-extractor.ts +0 -535
  408. package/src/memory/format-recall.ts +0 -47
  409. package/src/memory/fts-reconciler.ts +0 -165
  410. package/src/memory/job-handlers/conflict.ts +0 -200
  411. package/src/memory/profile-compiler.ts +0 -195
  412. package/src/memory/recall-cache.ts +0 -117
  413. package/src/memory/search/entity.ts +0 -535
  414. package/src/memory/search/query-expansion.test.ts +0 -70
  415. package/src/memory/search/query-expansion.ts +0 -118
  416. package/src/oauth/provider-base-urls.ts +0 -21
  417. package/src/oauth/provider-profiles.ts +0 -192
  418. package/src/prompts/computer-use-prompt.ts +0 -98
  419. package/src/runtime/routes/computer-use-routes.ts +0 -641
  420. package/src/runtime/routes/mcp-routes.ts +0 -20
  421. package/src/runtime/telegram-streaming-delivery.test.ts +0 -729
  422. package/src/runtime/telegram-streaming-delivery.ts +0 -393
  423. package/src/tools/computer-use/request-computer-control.ts +0 -56
@@ -48,6 +48,13 @@ export async function handleAddTrustRuleManage(
48
48
  if (!toolName || typeof toolName !== "string") {
49
49
  return httpError("BAD_REQUEST", "toolName is required", 400);
50
50
  }
51
+ if (toolName.startsWith("__internal:")) {
52
+ return httpError(
53
+ "BAD_REQUEST",
54
+ "toolName must not start with __internal:",
55
+ 400,
56
+ );
57
+ }
51
58
  if (!pattern || typeof pattern !== "string") {
52
59
  return httpError("BAD_REQUEST", "pattern is required", 400);
53
60
  }
@@ -124,6 +131,13 @@ export async function handleUpdateTrustRuleManage(
124
131
  priority?: number;
125
132
  };
126
133
 
134
+ if (typeof body.tool === "string" && body.tool.startsWith("__internal:")) {
135
+ return httpError(
136
+ "BAD_REQUEST",
137
+ "tool must not start with __internal:",
138
+ 400,
139
+ );
140
+ }
127
141
  if (body.decision !== undefined) {
128
142
  const validDecisions = ["allow", "deny", "ask"] as const;
129
143
  if (
@@ -0,0 +1,128 @@
1
+ /**
2
+ * HTTP route handler for watch (ambient observation) functionality.
3
+ *
4
+ * Decoupled from computer-use routes so that the watch endpoint has
5
+ * zero dependency on CU session state.
6
+ */
7
+
8
+ import { getLogger } from "../../util/logger.js";
9
+ import { httpError } from "../http-errors.js";
10
+ import type { RouteDefinition } from "../http-router.js";
11
+
12
+ const log = getLogger("watch-routes");
13
+
14
+ // ---------------------------------------------------------------------------
15
+ // Dependency injection interface
16
+ // ---------------------------------------------------------------------------
17
+
18
+ /**
19
+ * Minimal interface for watch observation handling.
20
+ * The daemon wires a concrete implementation at startup.
21
+ */
22
+ export interface WatchDeps {
23
+ /** Handle a watch observation. */
24
+ handleWatchObservation: (params: {
25
+ watchId: string;
26
+ sessionId: string;
27
+ ocrText: string;
28
+ appName?: string;
29
+ windowTitle?: string;
30
+ bundleIdentifier?: string;
31
+ timestamp: number;
32
+ captureIndex: number;
33
+ totalExpected: number;
34
+ }) => Promise<void>;
35
+ }
36
+
37
+ // ---------------------------------------------------------------------------
38
+ // Route handler
39
+ // ---------------------------------------------------------------------------
40
+
41
+ /**
42
+ * POST /v1/computer-use/watch — send a watch observation.
43
+ *
44
+ * Body: { watchId, sessionId, ocrText, appName?, windowTitle?,
45
+ * bundleIdentifier?, timestamp, captureIndex, totalExpected }
46
+ */
47
+ async function handleWatchObservationRoute(
48
+ req: Request,
49
+ deps: WatchDeps,
50
+ ): Promise<Response> {
51
+ const body = (await req.json()) as {
52
+ watchId?: string;
53
+ sessionId?: string;
54
+ ocrText?: string;
55
+ appName?: string;
56
+ windowTitle?: string;
57
+ bundleIdentifier?: string;
58
+ timestamp?: number;
59
+ captureIndex?: number;
60
+ totalExpected?: number;
61
+ };
62
+
63
+ if (!body.watchId || typeof body.watchId !== "string") {
64
+ return httpError("BAD_REQUEST", "watchId is required", 400);
65
+ }
66
+ if (!body.sessionId || typeof body.sessionId !== "string") {
67
+ return httpError("BAD_REQUEST", "sessionId is required", 400);
68
+ }
69
+ if (!body.ocrText || typeof body.ocrText !== "string") {
70
+ return httpError("BAD_REQUEST", "ocrText is required", 400);
71
+ }
72
+ if (typeof body.timestamp !== "number") {
73
+ return httpError("BAD_REQUEST", "timestamp is required", 400);
74
+ }
75
+ if (typeof body.captureIndex !== "number") {
76
+ return httpError("BAD_REQUEST", "captureIndex is required", 400);
77
+ }
78
+ if (typeof body.totalExpected !== "number") {
79
+ return httpError("BAD_REQUEST", "totalExpected is required", 400);
80
+ }
81
+
82
+ try {
83
+ await deps.handleWatchObservation({
84
+ watchId: body.watchId,
85
+ sessionId: body.sessionId,
86
+ ocrText: body.ocrText,
87
+ appName: body.appName,
88
+ windowTitle: body.windowTitle,
89
+ bundleIdentifier: body.bundleIdentifier,
90
+ timestamp: body.timestamp,
91
+ captureIndex: body.captureIndex,
92
+ totalExpected: body.totalExpected,
93
+ });
94
+
95
+ return Response.json({ ok: true });
96
+ } catch (err) {
97
+ const message = err instanceof Error ? err.message : String(err);
98
+ log.error(
99
+ { err, watchId: body.watchId },
100
+ "Failed to handle watch observation via HTTP",
101
+ );
102
+ return httpError("INTERNAL_ERROR", message, 500);
103
+ }
104
+ }
105
+
106
+ // ---------------------------------------------------------------------------
107
+ // Route definitions
108
+ // ---------------------------------------------------------------------------
109
+
110
+ export function watchRouteDefinitions(deps: {
111
+ getWatchDeps?: () => WatchDeps;
112
+ }): RouteDefinition[] {
113
+ const getDeps = (): WatchDeps => {
114
+ if (!deps.getWatchDeps) {
115
+ throw new Error("Watch deps not available");
116
+ }
117
+ return deps.getWatchDeps();
118
+ };
119
+
120
+ return [
121
+ {
122
+ endpoint: "computer-use/watch",
123
+ method: "POST",
124
+ policyKey: "computer-use/watch",
125
+ handler: async ({ req }) => handleWatchObservationRoute(req, getDeps()),
126
+ },
127
+ ];
128
+ }
@@ -33,6 +33,7 @@ interface TreeEntry {
33
33
 
34
34
  function handleWorkspaceTree(ctx: RouteContext): Response {
35
35
  const requestedPath = ctx.url.searchParams.get("path") ?? "";
36
+ const showHidden = ctx.url.searchParams.get("showHidden") === "true";
36
37
  const resolved = resolveWorkspacePath(requestedPath);
37
38
  if (resolved === undefined) {
38
39
  return httpError("BAD_REQUEST", "Invalid path", 400);
@@ -45,7 +46,7 @@ function handleWorkspaceTree(ctx: RouteContext): Response {
45
46
  const entries: TreeEntry[] = [];
46
47
  for (const entry of dirents) {
47
48
  // Filter out dotfiles/directories (.env, .git, .private, etc.)
48
- if (entry.name.startsWith(".")) continue;
49
+ if (!showHidden && entry.name.startsWith(".")) continue;
49
50
 
50
51
  const fullPath = join(resolved, entry.name);
51
52
 
@@ -1,6 +1,8 @@
1
1
  import { hasTwilioCredentials } from "../calls/twilio-rest.js";
2
- import { credentialKey } from "../security/credential-key.js";
3
- import { getSecureKey } from "../security/secure-keys.js";
2
+ import {
3
+ getConnectionByProvider,
4
+ isProviderConnected,
5
+ } from "../oauth/oauth-store.js";
4
6
 
5
7
  interface IntegrationProbe {
6
8
  name: string;
@@ -13,14 +15,12 @@ const INTEGRATION_PROBES: IntegrationProbe[] = [
13
15
  {
14
16
  name: "Gmail",
15
17
  category: "email",
16
- isConnected: () =>
17
- !!getSecureKey(credentialKey("integration:gmail", "access_token")),
18
+ isConnected: () => isProviderConnected("integration:gmail"),
18
19
  },
19
20
  {
20
21
  name: "Slack",
21
22
  category: "messaging",
22
- isConnected: () =>
23
- !!getSecureKey(credentialKey("integration:slack", "access_token")),
23
+ isConnected: () => isProviderConnected("integration:slack"),
24
24
  },
25
25
  {
26
26
  name: "Twilio",
@@ -30,9 +30,10 @@ const INTEGRATION_PROBES: IntegrationProbe[] = [
30
30
  {
31
31
  name: "Telegram",
32
32
  category: "messaging",
33
- isConnected: () =>
34
- !!getSecureKey(credentialKey("telegram", "bot_token")) &&
35
- !!getSecureKey(credentialKey("telegram", "webhook_secret")),
33
+ isConnected: () => {
34
+ const conn = getConnectionByProvider("telegram");
35
+ return !!(conn && conn.status === "active");
36
+ },
36
37
  },
37
38
  ];
38
39
 
@@ -2,23 +2,8 @@
2
2
  * Single source of truth for credential key format in the secure store.
3
3
  *
4
4
  * Keys follow the pattern: credential/{service}/{field}
5
- *
6
- * Previously, keys used colons as delimiters (credential:service:field),
7
- * which was ambiguous when service names contained colons (e.g.
8
- * "integration:gmail"). The slash-delimited format avoids this.
9
5
  */
10
6
 
11
- import { listCredentialMetadata } from "../tools/credentials/metadata-store.js";
12
- import { getLogger } from "../util/logger.js";
13
- import {
14
- deleteSecureKey,
15
- getSecureKey,
16
- listSecureKeys,
17
- setSecureKey,
18
- } from "./secure-keys.js";
19
-
20
- const log = getLogger("credential-key");
21
-
22
7
  /**
23
8
  * Build a credential key for the secure store.
24
9
  *
@@ -27,144 +12,3 @@ const log = getLogger("credential-key");
27
12
  export function credentialKey(service: string, field: string): string {
28
13
  return `credential/${service}/${field}`;
29
14
  }
30
-
31
- // ---------------------------------------------------------------------------
32
- // Migration from colon-delimited keys
33
- // ---------------------------------------------------------------------------
34
-
35
- let migrated = false;
36
-
37
- /**
38
- * Migrate any legacy colon-delimited credential keys to the new
39
- * slash-delimited format. Idempotent: skips keys that already exist
40
- * under the new format, and only runs once per process (guarded by a
41
- * module-level flag).
42
- *
43
- * Legacy key format: `credential:<service>:<field>`
44
- * New key format: `credential/<service>/<field>`
45
- *
46
- * The old colon-delimited format is ambiguous when either the service
47
- * or field name contains colons — for `credential:A:B:C:D`, you can't
48
- * tell where the service ends and the field begins without external
49
- * context.
50
- *
51
- * To resolve this, the function first consults the credential metadata
52
- * store to find which (service, field) pair matches a valid split.
53
- * If no metadata match is found, it falls back to splitting on the
54
- * **first** colon after the prefix — this handles the common case
55
- * where service names are simple (e.g. "doordash.com") and field
56
- * names may contain colons (e.g. "session:cookies").
57
- */
58
- export function migrateKeys(): void {
59
- if (migrated) return;
60
- migrated = true;
61
-
62
- let allKeys: string[];
63
- try {
64
- allKeys = listSecureKeys();
65
- } catch (err) {
66
- log.warn({ err }, "Failed to list secure keys during migration");
67
- return;
68
- }
69
-
70
- const colonKeys = allKeys.filter(
71
- (k) => k.startsWith("credential:") && !k.startsWith("credential/"),
72
- );
73
- if (colonKeys.length === 0) return;
74
-
75
- log.info(
76
- { count: colonKeys.length },
77
- "Migrating colon-delimited credential keys to slash-delimited format",
78
- );
79
-
80
- // Build a set of known (service, field) pairs from credential metadata
81
- // to disambiguate colon-delimited keys.
82
- const knownPairs = new Set<string>();
83
- try {
84
- for (const meta of listCredentialMetadata()) {
85
- knownPairs.add(`${meta.service}\0${meta.field}`);
86
- }
87
- } catch {
88
- // If metadata is unavailable, we'll rely on the first-colon fallback.
89
- }
90
-
91
- for (const oldKey of colonKeys) {
92
- // Strip the "credential:" prefix — `rest` is "service:field" with
93
- // potential colons in either part.
94
- const rest = oldKey.slice("credential:".length);
95
-
96
- const parsed = parseServiceField(rest, knownPairs);
97
- if (parsed === undefined) {
98
- log.warn({ key: oldKey }, "Skipping malformed credential key");
99
- continue;
100
- }
101
-
102
- const { service, field } = parsed;
103
- const newKey = credentialKey(service, field);
104
-
105
- // Skip if the new key already exists (idempotent)
106
- if (getSecureKey(newKey) !== undefined) {
107
- // Clean up old key
108
- deleteSecureKey(oldKey);
109
- continue;
110
- }
111
-
112
- const value = getSecureKey(oldKey);
113
- if (value === undefined) {
114
- continue;
115
- }
116
-
117
- const ok = setSecureKey(newKey, value);
118
- if (ok) {
119
- deleteSecureKey(oldKey);
120
- } else {
121
- log.warn(
122
- { oldKey, newKey },
123
- "Failed to write migrated key; keeping old key",
124
- );
125
- }
126
- }
127
- }
128
-
129
- /**
130
- * Parse a "service:field" string, using known metadata pairs to
131
- * disambiguate when colons appear in either part.
132
- *
133
- * Strategy:
134
- * 1. Try every possible split position and check against metadata.
135
- * 2. If no metadata match, fall back to splitting on the first colon
136
- * (field names with colons are more common than service names with colons).
137
- *
138
- * Returns undefined for malformed keys that have no colon.
139
- */
140
- function parseServiceField(
141
- rest: string,
142
- knownPairs: Set<string>,
143
- ): { service: string; field: string } | undefined {
144
- const firstColon = rest.indexOf(":");
145
- if (firstColon <= 0) return undefined;
146
-
147
- // Try each possible split position against metadata
148
- if (knownPairs.size > 0) {
149
- for (let i = firstColon; i < rest.length; i++) {
150
- if (rest[i] !== ":") continue;
151
- const service = rest.slice(0, i);
152
- const field = rest.slice(i + 1);
153
- if (field.length > 0 && knownPairs.has(`${service}\0${field}`)) {
154
- return { service, field };
155
- }
156
- }
157
- }
158
-
159
- // Fallback: split on first colon — handles simple services with
160
- // compound field names (e.g. "doordash.com:session:cookies").
161
- return {
162
- service: rest.slice(0, firstColon),
163
- field: rest.slice(firstColon + 1),
164
- };
165
- }
166
-
167
- /** @internal Test-only: reset the migration guard so migrateKeys() runs again. */
168
- export function _resetMigrationFlag(): void {
169
- migrated = false;
170
- }
@@ -6,7 +6,7 @@
6
6
  * provides a graceful-fallback interface: every public method returns a
7
7
  * safe default on failure and never throws.
8
8
  *
9
- * Socket path: read from VELLUM_KEYCHAIN_BROKER_SOCKET env var.
9
+ * Socket path: derived from getRootDir() as `~/.vellum/keychain-broker.sock`.
10
10
  * Auth token: read from ~/.vellum/protected/keychain-broker.token on first
11
11
  * connection, cached for process lifetime.
12
12
  */
@@ -33,11 +33,18 @@ const REQUEST_TIMEOUT_MS = 5_000;
33
33
  * back); `{ found: false }` means the key doesn't exist in the keychain. */
34
34
  export type BrokerGetResult = { found: boolean; value?: string } | null;
35
35
 
36
+ /** Result of a `set()` call — distinguishes broker-unreachable from an active
37
+ * rejection so callers can log meaningful diagnostics. */
38
+ export type BrokerSetResult =
39
+ | { status: "ok" }
40
+ | { status: "unreachable" }
41
+ | { status: "rejected"; code: string; message: string };
42
+
36
43
  export interface KeychainBrokerClient {
37
44
  isAvailable(): boolean;
38
45
  ping(): Promise<{ pong: boolean } | null>;
39
46
  get(account: string): Promise<BrokerGetResult>;
40
- set(account: string, value: string): Promise<boolean>;
47
+ set(account: string, value: string): Promise<BrokerSetResult>;
41
48
  del(account: string): Promise<boolean>;
42
49
  list(): Promise<string[]>;
43
50
  }
@@ -70,8 +77,8 @@ function getTokenPath(): string {
70
77
  return join(getRootDir(), "protected", "keychain-broker.token");
71
78
  }
72
79
 
73
- function getSocketPath(): string | undefined {
74
- return process.env.VELLUM_KEYCHAIN_BROKER_SOCKET;
80
+ function getSocketPath(): string {
81
+ return join(getRootDir(), "keychain-broker.sock");
75
82
  }
76
83
 
77
84
  // ---------------------------------------------------------------------------
@@ -172,7 +179,7 @@ export function createBrokerClient(): KeychainBrokerClient {
172
179
  function connect(): Promise<Socket> {
173
180
  return new Promise((resolve, reject) => {
174
181
  const socketPath = getSocketPath();
175
- if (!socketPath) {
182
+ if (!pathExists(socketPath)) {
176
183
  reject(new Error("No socket path"));
177
184
  return;
178
185
  }
@@ -328,8 +335,7 @@ export function createBrokerClient(): KeychainBrokerClient {
328
335
  return {
329
336
  isAvailable(): boolean {
330
337
  if (permanentlyUnavailable) return false;
331
- const socketPath = getSocketPath();
332
- if (!socketPath) return false;
338
+ if (!pathExists(getSocketPath())) return false;
333
339
  return pathExists(getTokenPath());
334
340
  },
335
341
 
@@ -361,12 +367,18 @@ export function createBrokerClient(): KeychainBrokerClient {
361
367
  }
362
368
  },
363
369
 
364
- async set(account: string, value: string): Promise<boolean> {
370
+ async set(account: string, value: string): Promise<BrokerSetResult> {
365
371
  try {
366
372
  const response = await doRequest("key.set", { account, value });
367
- return response?.ok === true;
373
+ if (!response) return { status: "unreachable" };
374
+ if (response.ok) return { status: "ok" };
375
+ return {
376
+ status: "rejected",
377
+ code: response.error?.code ?? "UNKNOWN",
378
+ message: response.error?.message ?? "unknown error",
379
+ };
368
380
  } catch {
369
- return false;
381
+ return { status: "unreachable" };
370
382
  }
371
383
  },
372
384
 
@@ -691,7 +691,7 @@ export async function startOAuth2Flow(
691
691
  if (transport === "gateway") {
692
692
  if (!hasPublicUrl) {
693
693
  throw new Error(
694
- "Gateway transport requires a public ingress URL. Set ingress.publicBaseUrl or INGRESS_PUBLIC_BASE_URL, or use loopback transport.",
694
+ "Gateway transport requires a public ingress URL. Set ingress.publicBaseUrl, or use loopback transport.",
695
695
  );
696
696
  }
697
697
  log.debug({ transport: "gateway" }, "OAuth2 flow starting");
@@ -7,10 +7,13 @@
7
7
  * encrypted store (startup code paths cannot do async I/O).
8
8
  */
9
9
 
10
+ import { getLogger } from "../util/logger.js";
10
11
  import * as encryptedStore from "./encrypted-store.js";
11
12
  import type { KeychainBrokerClient } from "./keychain-broker-client.js";
12
13
  import { createBrokerClient } from "./keychain-broker-client.js";
13
14
 
15
+ const log = getLogger("secure-keys");
16
+
14
17
  let _broker: KeychainBrokerClient | undefined;
15
18
 
16
19
  function getBroker(): KeychainBrokerClient {
@@ -120,13 +123,32 @@ export async function setSecureKeyAsync(
120
123
  ): Promise<boolean> {
121
124
  const broker = getBroker();
122
125
  if (broker.isAvailable()) {
123
- const brokerOk = await broker.set(account, value);
124
- if (!brokerOk) return false;
126
+ const result = await broker.set(account, value);
127
+ if (result.status !== "ok") {
128
+ log.warn(
129
+ {
130
+ account,
131
+ brokerStatus: result.status,
132
+ ...(result.status === "rejected"
133
+ ? { brokerCode: result.code, brokerMessage: result.message }
134
+ : {}),
135
+ },
136
+ "Broker set failed for secure key",
137
+ );
138
+ return false;
139
+ }
125
140
  // Broker succeeded — also persist to encrypted store for sync callers.
126
141
  const encOk = encryptedStore.setKey(account, value);
142
+ if (!encOk) {
143
+ log.warn({ account }, "Encrypted store set failed after broker success");
144
+ }
127
145
  return encOk;
128
146
  }
129
- return encryptedStore.setKey(account, value);
147
+ const encOk = encryptedStore.setKey(account, value);
148
+ if (!encOk) {
149
+ log.warn({ account }, "Encrypted store set failed (broker unavailable)");
150
+ }
151
+ return encOk;
130
152
  }
131
153
 
132
154
  /**