clay-server 5.2.0-beta.4 → 5.2.0-beta.6

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 (301) hide show
  1. package/lib/account-auth-socket.js +1 -0
  2. package/lib/builtin-mates.js +17 -14
  3. package/lib/canonical-clay-record-authority.js +15 -0
  4. package/lib/canonical-clay-scheduling-authority.js +19 -0
  5. package/lib/claude-hook-installer.js +1 -239
  6. package/lib/claude-jsonl-watcher.js +1 -204
  7. package/lib/clay-mate-chat-receipts.js +26 -0
  8. package/lib/clay-mate-chat.js +87 -0
  9. package/lib/clay-mate-knowledge-input.js +26 -0
  10. package/lib/clay-mate-knowledge.js +95 -0
  11. package/lib/clay-mate-lifecycle.js +95 -0
  12. package/lib/clay-product-control-input.js +33 -0
  13. package/lib/clay-product-control-tools.js +51 -0
  14. package/lib/clay-product-control.js +237 -0
  15. package/lib/clay-project-lifecycle.js +154 -0
  16. package/lib/clay-project-record-input.js +44 -0
  17. package/lib/clay-project-records.js +83 -0
  18. package/lib/clay-scheduling-input.js +21 -0
  19. package/lib/clay-scheduling-receipts.js +26 -0
  20. package/lib/clay-scheduling.js +119 -0
  21. package/lib/clay-screen-controls.js +96 -0
  22. package/lib/clay-skill-install.js +1 -33
  23. package/lib/clay-workspace-controls.js +83 -0
  24. package/lib/clay-workspace-input.js +17 -0
  25. package/lib/clay-workspace-receipts.js +26 -0
  26. package/lib/cli-sessions.js +1 -300
  27. package/lib/codex-defaults.js +1 -28
  28. package/lib/context-usage.js +3 -2
  29. package/lib/daemon-project-access.js +11 -0
  30. package/lib/daemon-project-lifecycle-callbacks.js +15 -0
  31. package/lib/daemon-project-lifecycle.js +262 -0
  32. package/lib/daemon-projects.js +1 -1
  33. package/lib/daemon.js +78 -276
  34. package/lib/default-ai-runtime.js +4 -8
  35. package/lib/email-mcp-server.js +1 -1
  36. package/lib/issues-service.js +29 -15
  37. package/lib/kiro-defaults.js +1 -22
  38. package/lib/knowledge-db-import.js +5 -4
  39. package/lib/knowledge-db-service.js +9 -6
  40. package/lib/knowledge-document-index.js +2 -1
  41. package/lib/knowledge-product-operations.js +46 -0
  42. package/lib/mate-creation-mcp-server.js +2 -0
  43. package/lib/mate-knowledge-canonical-access.js +10 -0
  44. package/lib/mate-knowledge-service.js +7 -4
  45. package/lib/mate-lifecycle-service.js +94 -0
  46. package/lib/mate-message-delivery.js +43 -0
  47. package/lib/mate-ready-creation.js +9 -1
  48. package/lib/mate-schedule-input.js +29 -0
  49. package/lib/mate-schedule-lifecycle.js +151 -0
  50. package/lib/mate-scheduling.js +103 -0
  51. package/lib/mates.js +4 -3
  52. package/lib/mcp-proxy.js +2 -32
  53. package/lib/mcp-query-bridge.js +1 -1
  54. package/lib/mcp-source-adapters.js +1 -91
  55. package/lib/mcp-source-context.js +1 -42
  56. package/lib/mcp-source-discovery.js +1 -169
  57. package/lib/mcp-source-plugins.js +1 -68
  58. package/lib/mcp-source-restrictions.js +1 -47
  59. package/lib/mcp-tool-policy.js +1 -26
  60. package/lib/notes-checklist.js +50 -0
  61. package/lib/notes.js +49 -3
  62. package/lib/os-user-diagnostics.js +2 -4
  63. package/lib/os-users.js +24 -70
  64. package/lib/project-admin-overview.js +51 -0
  65. package/lib/project-ask-user.js +4 -2
  66. package/lib/project-connection.js +8 -7
  67. package/lib/project-delegated-follow-up.js +2 -1
  68. package/lib/project-directory-claim.js +65 -0
  69. package/lib/project-file-operations.js +61 -0
  70. package/lib/project-filesystem.js +13 -87
  71. package/lib/project-full-access.js +23 -2
  72. package/lib/project-http.js +4 -4
  73. package/lib/project-knowledge.js +32 -18
  74. package/lib/project-lifecycle-operations.js +98 -0
  75. package/lib/project-lifecycle-process-witness.js +32 -0
  76. package/lib/project-lifecycle-runtime.js +50 -0
  77. package/lib/project-linux-access.js +22 -0
  78. package/lib/project-logs-canonical-clay.js +27 -0
  79. package/lib/project-logs-clay-query.js +16 -0
  80. package/lib/project-logs-schema.js +4 -2
  81. package/lib/project-logs-service.js +8 -7
  82. package/lib/project-logs.js +1 -0
  83. package/lib/project-loop.js +1 -0
  84. package/lib/project-mate-chat-control.js +55 -0
  85. package/lib/project-mate-creation-proposal.js +18 -3
  86. package/lib/project-mcp.js +2 -2
  87. package/lib/project-models.js +14 -31
  88. package/lib/project-notifications.js +74 -16
  89. package/lib/project-ownership.js +77 -0
  90. package/lib/project-pair-result-delivery.js +14 -3
  91. package/lib/project-pair-usage.js +12 -13
  92. package/lib/project-pending-message-queue.js +4 -1
  93. package/lib/project-product-control.js +87 -0
  94. package/lib/project-product-session-queue.js +46 -0
  95. package/lib/project-push-access.js +28 -0
  96. package/lib/project-scheduled-message-queue.js +30 -0
  97. package/lib/project-scheduled-messages.js +63 -64
  98. package/lib/project-scheduled-task-control.js +83 -0
  99. package/lib/project-scheduled-tasks.js +13 -2
  100. package/lib/project-scheduling-access.js +10 -0
  101. package/lib/project-session-actions.js +65 -0
  102. package/lib/project-session-delete.js +8 -1
  103. package/lib/project-session-github.js +47 -12
  104. package/lib/project-session-history-actions.js +167 -0
  105. package/lib/project-session-pair.js +1 -1
  106. package/lib/project-session-runtime-actions.js +64 -0
  107. package/lib/project-session-spawn.js +2 -3
  108. package/lib/project-session-vendor.js +55 -0
  109. package/lib/project-sessions.js +82 -267
  110. package/lib/project-user-message.js +31 -1
  111. package/lib/project-vendor-login.js +6 -36
  112. package/lib/project-workspace-operations.js +126 -0
  113. package/lib/project-workspace-query.js +9 -2
  114. package/lib/project.js +95 -3
  115. package/lib/public/app.js +1 -0
  116. package/lib/public/css/clay-tool-activity.css +51 -0
  117. package/lib/public/css/home-mate-creation.css +5 -0
  118. package/lib/public/css/messages.css +6 -2
  119. package/lib/public/css/overlays.css +4 -2
  120. package/lib/public/css/project-admin-overview.css +13 -0
  121. package/lib/public/css/session-folders.css +11 -0
  122. package/lib/public/css/session-github.css +3 -0
  123. package/lib/public/css/sticky-notes.css +61 -1
  124. package/lib/public/index.html +1 -1
  125. package/lib/public/modules/admin-settings-projects.js +6 -2
  126. package/lib/public/modules/app-connection.js +8 -1
  127. package/lib/public/modules/app-favicon.js +11 -2
  128. package/lib/public/modules/app-header.js +4 -2
  129. package/lib/public/modules/app-loop-ui.js +2 -0
  130. package/lib/public/modules/app-message-router.js +1 -1
  131. package/lib/public/modules/app-messages.js +54 -8
  132. package/lib/public/modules/app-notifications.js +1 -2
  133. package/lib/public/modules/app-panels.js +61 -123
  134. package/lib/public/modules/app-projects.js +5 -0
  135. package/lib/public/modules/app-rate-limit.js +7 -27
  136. package/lib/public/modules/chat-render-runtime.js +3 -0
  137. package/lib/public/modules/clay-owner-navigation.js +27 -0
  138. package/lib/public/modules/clay-tool-activity.js +140 -0
  139. package/lib/public/modules/clay-tool-presentation.js +338 -0
  140. package/lib/public/modules/command-palette.js +1 -1
  141. package/lib/public/modules/default-ai.js +11 -3
  142. package/lib/public/modules/home-debate-planning.js +5 -5
  143. package/lib/public/modules/home-mate-chat.js +8 -6
  144. package/lib/public/modules/home-mate-creation.js +73 -1
  145. package/lib/public/modules/mcp-connection-view.js +1 -1
  146. package/lib/public/modules/permission-control.js +5 -4
  147. package/lib/public/modules/personal-settings-dialog.js +7 -1
  148. package/lib/public/modules/project-access-recovery.js +17 -0
  149. package/lib/public/modules/project-admin-overview.js +21 -0
  150. package/lib/public/modules/scheduler.js +2 -0
  151. package/lib/public/modules/session-create-form.js +10 -10
  152. package/lib/public/modules/session-folder-layout.js +1 -1
  153. package/lib/public/modules/session-folder-view-menu.js +9 -0
  154. package/lib/public/modules/session-github.js +65 -8
  155. package/lib/public/modules/settings-defaults.js +27 -28
  156. package/lib/public/modules/sidebar-session-folders-ui.js +1 -1
  157. package/lib/public/modules/sticky-note-markdown.js +72 -6
  158. package/lib/public/modules/sticky-notes-actions.js +30 -0
  159. package/lib/public/modules/sticky-notes-browser.js +9 -2
  160. package/lib/public/modules/sticky-notes-card.js +23 -7
  161. package/lib/public/modules/sticky-notes-checklist.js +71 -0
  162. package/lib/public/modules/sticky-notes-editor.js +108 -44
  163. package/lib/public/modules/sticky-notes-shared.js +50 -2
  164. package/lib/public/modules/sticky-notes-state.js +66 -0
  165. package/lib/public/modules/sticky-notes.js +34 -51
  166. package/lib/public/modules/thinking-lifecycle.js +33 -3
  167. package/lib/public/modules/thinking-view.js +23 -1
  168. package/lib/public/modules/tools.js +36 -7
  169. package/lib/public/modules/tui-grab.js +1 -2
  170. package/lib/public/modules/user-settings-appearance.js +10 -3
  171. package/lib/public/modules/user-settings-editors.js +1 -1
  172. package/lib/public/modules/user-settings-layout.js +11 -2
  173. package/lib/public/modules/user-settings-preferences.js +6 -2
  174. package/lib/public/modules/user-settings-profile.js +12 -2
  175. package/lib/public/modules/user-settings.js +3 -2
  176. package/lib/public/modules/vendor-login-browser.js +5 -3
  177. package/lib/public/modules/vendor-login.js +2 -2
  178. package/lib/public/modules/vendor-priority.js +15 -1
  179. package/lib/public/muse-avatar.svg +4 -0
  180. package/lib/public/style.css +2 -0
  181. package/lib/safe-bash-commands.js +3 -45
  182. package/lib/scheduled-task-records.js +3 -1
  183. package/lib/scheduler.js +2 -0
  184. package/lib/sdk-bridge.js +334 -403
  185. package/lib/sdk-foreground-admission.js +16 -0
  186. package/lib/sdk-mcp-descriptors.js +2 -37
  187. package/lib/sdk-message-processor.js +52 -17
  188. package/lib/sdk-quota-snapshot.js +1 -1
  189. package/lib/sdk-response-recovery.js +1 -0
  190. package/lib/sdk-worker.js +2 -677
  191. package/lib/server-admin.js +63 -16
  192. package/lib/server-dm.js +1 -1
  193. package/lib/server-global-ws.js +10 -20
  194. package/lib/server-home-chat-events.js +7 -3
  195. package/lib/server-home-chat.js +4 -16
  196. package/lib/server-home-mate-creation.js +1 -0
  197. package/lib/server-home-mcp-consent.js +3 -3
  198. package/lib/server-mates.js +25 -67
  199. package/lib/server-owner-ui.js +77 -0
  200. package/lib/server-path-access.js +38 -0
  201. package/lib/server-project-removal.js +22 -0
  202. package/lib/server.js +100 -30
  203. package/lib/session-config-transition.js +45 -0
  204. package/lib/session-folders.js +7 -2
  205. package/lib/session-fork-history.js +21 -0
  206. package/lib/session-github.js +9 -2
  207. package/lib/session-hygiene.js +3 -35
  208. package/lib/session-permission-mode.js +4 -3
  209. package/lib/session-skill-scope.js +11 -0
  210. package/lib/session-visibility.js +5 -2
  211. package/lib/sessions.js +27 -89
  212. package/lib/terminal-manager.js +52 -0
  213. package/lib/tool-llm.js +1 -1
  214. package/lib/tui-transcript-index.js +1 -132
  215. package/lib/users-permissions.js +2 -8
  216. package/lib/users.js +4 -0
  217. package/lib/vendor-login-browser.js +1 -11
  218. package/lib/workspace-query-access.js +4 -1
  219. package/lib/ws-schema.js +8 -2
  220. package/lib/yoke/acp-agent-profiles.js +5 -3
  221. package/lib/yoke/adapters/antigravity.js +3 -14
  222. package/lib/yoke/adapters/claude-query-contract.js +9 -0
  223. package/lib/yoke/adapters/claude.js +54 -50
  224. package/lib/yoke/adapters/codex-query-contract.js +24 -0
  225. package/lib/yoke/adapters/codex.js +53 -111
  226. package/lib/yoke/adapters/kiro.js +3 -1
  227. package/lib/yoke/adapters/muse-query-contract.js +7 -0
  228. package/lib/yoke/adapters/muse.js +122 -0
  229. package/lib/yoke/auth-events.js +17 -0
  230. package/lib/yoke/claude-hook-installer.js +267 -0
  231. package/lib/yoke/claude-jsonl-watcher.js +204 -0
  232. package/lib/yoke/claude-maintenance.js +55 -0
  233. package/lib/yoke/claude-permission-patterns.js +53 -0
  234. package/lib/yoke/claude-response-recovery.js +155 -0
  235. package/lib/yoke/claude-transcript-hygiene.js +34 -0
  236. package/lib/yoke/claude-worker-startup.js +28 -0
  237. package/lib/yoke/clay-skill-install.js +33 -0
  238. package/lib/yoke/cli-sessions.js +300 -0
  239. package/lib/yoke/codex-app-server.js +7 -12
  240. package/lib/yoke/codex-idle-recovery.js +81 -1
  241. package/lib/yoke/codex-recovery-admission.js +164 -0
  242. package/lib/yoke/configuration.js +13 -0
  243. package/lib/yoke/discovery.js +70 -0
  244. package/lib/yoke/errors.js +8 -0
  245. package/lib/yoke/host-environment.js +7 -0
  246. package/lib/yoke/index.js +9 -51
  247. package/lib/yoke/interface.js +116 -0
  248. package/lib/yoke/kiro-acp-server.js +5 -5
  249. package/lib/yoke/legacy-sessions.js +89 -0
  250. package/lib/yoke/login-protocol.js +25 -0
  251. package/lib/yoke/maintenance.js +12 -0
  252. package/lib/yoke/mcp-proxy.js +32 -0
  253. package/lib/yoke/mcp-source-adapters.js +91 -0
  254. package/lib/yoke/mcp-source-context.js +42 -0
  255. package/lib/yoke/mcp-source-discovery.js +169 -0
  256. package/lib/yoke/mcp-source-plugins.js +68 -0
  257. package/lib/yoke/mcp-source-restrictions.js +47 -0
  258. package/lib/yoke/mcp-tool-policy-normalize.js +28 -0
  259. package/lib/yoke/model-preferences.js +6 -0
  260. package/lib/yoke/muse-artifacts.js +36 -0
  261. package/lib/yoke/muse-controls.js +50 -0
  262. package/lib/yoke/muse-input.js +64 -0
  263. package/lib/yoke/muse-items.js +157 -0
  264. package/lib/yoke/muse-policy.js +52 -0
  265. package/lib/yoke/muse-query.js +428 -0
  266. package/lib/yoke/muse-runtime.js +211 -0
  267. package/lib/yoke/muse-services.js +79 -0
  268. package/lib/yoke/muse-skills.js +79 -0
  269. package/lib/yoke/muse-turns.js +71 -0
  270. package/lib/yoke/options/acp.js +2 -0
  271. package/lib/yoke/options/antigravity.js +2 -0
  272. package/lib/yoke/options/claude.js +21 -0
  273. package/lib/yoke/options/codex-defaults.js +29 -0
  274. package/lib/yoke/options/codex-settings.js +21 -0
  275. package/lib/yoke/options/codex.js +6 -0
  276. package/lib/yoke/options/kiro-defaults.js +22 -0
  277. package/lib/yoke/options/kiro.js +5 -0
  278. package/lib/yoke/options/muse.js +5 -0
  279. package/lib/yoke/provider-contract.js +5 -0
  280. package/lib/yoke/providers/antigravity-executable.js +8 -0
  281. package/lib/yoke/providers/claude-executable.js +40 -0
  282. package/lib/yoke/providers/claude-model-descriptions.js +14 -0
  283. package/lib/yoke/providers/claude-process.js +97 -0
  284. package/lib/yoke/providers/claude-provision.js +75 -0
  285. package/lib/yoke/providers/codex-errors.js +8 -0
  286. package/lib/yoke/providers/muse-executable.js +17 -0
  287. package/lib/yoke/provisioning.js +6 -0
  288. package/lib/yoke/query-options.js +10 -0
  289. package/lib/yoke/response-recovery.js +41 -0
  290. package/lib/yoke/sdk-mcp-descriptors.js +37 -0
  291. package/lib/yoke/sdk-server-factory.js +7 -0
  292. package/lib/yoke/session-history.js +8 -0
  293. package/lib/yoke/session-tool-transport.js +34 -13
  294. package/lib/yoke/settings.js +23 -0
  295. package/lib/yoke/source-locations.js +4 -0
  296. package/lib/yoke/title-query.js +18 -7
  297. package/lib/yoke/tui-transcript-index.js +132 -0
  298. package/lib/yoke/usage.js +48 -0
  299. package/lib/yoke/user-input.js +13 -0
  300. package/lib/yoke/vendor-registry.js +81 -1
  301. package/package.json +3 -2
@@ -0,0 +1,29 @@
1
+ var rules = require('./schedule-rule');
2
+ function normalize(input, previous) {
3
+ input = input || {};
4
+ var message = input.message === undefined && previous ? previous.message : input.message;
5
+ if (typeof message !== 'string' || !message.trim() || message.length > 1200 || message.indexOf('\u0000') >= 0) throw new Error('A message of 1 to 1200 characters is required.');
6
+ var source = input.scheduleRule || (previous && previous.rule) || {
7
+ version: 1, timezone: 'server-local', anchorDate: input.date, time: input.time, recurrence: null,
8
+ };
9
+ source = Object.assign({}, source);
10
+ if (input.date !== undefined) source.anchorDate = input.date;
11
+ if (input.time !== undefined) source.time = input.time;
12
+ var checked = rules.validateScheduleRule(source);
13
+ if (!checked.ok) throw new Error(checked.error);
14
+ return { message: message.trim(), rule: checked.value };
15
+ }
16
+ function timezone() { return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'; }
17
+ function review(value) {
18
+ var rule = value.rule;
19
+ var repeat = rule.recurrence ? 'Every ' + rule.recurrence.every + ' ' + rule.recurrence.unit +
20
+ (rule.recurrence.weekdays ? ' on ' + rule.recurrence.weekdays.map(function (day) { return ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][day]; }).join(', ') : '') : 'Once';
21
+ if (rule.recurrenceEnd) repeat += rule.recurrenceEnd.type === 'after' ? ', ' + rule.recurrenceEnd.count + ' deliveries' : ', through ' + rule.recurrenceEnd.date;
22
+ if (rule.interval) {
23
+ var ending = rule.interval.end;
24
+ repeat += '; every ' + rule.interval.every + ' ' + rule.interval.unit;
25
+ repeat += !ending ? ', until end of day' : ending.type === 'after' ? ', ' + ending.count + ' deliveries per day' : ', until ' + ending.time;
26
+ }
27
+ return value.message + '\n' + rule.anchorDate + ' at ' + rule.time + ' (' + timezone() + ')\n' + repeat;
28
+ }
29
+ module.exports = { normalize: normalize, timezone: timezone, review: review };
@@ -0,0 +1,151 @@
1
+ var crypto = require('crypto');
2
+ var rule = require('./schedule-rule');
3
+
4
+ function copy(value) { return JSON.parse(JSON.stringify(value)); }
5
+ function attachMateScheduleLifecycle(ctx) {
6
+ var now = ctx.now || Date.now;
7
+ function save(session, records) {
8
+ var previous = session.mateSchedules;
9
+ session.mateSchedules = records;
10
+ if (ctx.sm.saveSessionFile(session) !== true) {
11
+ session.mateSchedules = previous;
12
+ throw new Error('The Mate schedule could not be saved.');
13
+ }
14
+ }
15
+ function records(session) { return copy(session.mateSchedules || []); }
16
+ function find(session, id) {
17
+ return records(session).find(function (record) { return record.id === id; }) || null;
18
+ }
19
+ function replace(session, record) {
20
+ var all = records(session);
21
+ var index = all.findIndex(function (item) { return item.id === record.id; });
22
+ if (index < 0) all.push(record); else all[index] = record;
23
+ save(session, all);
24
+ }
25
+ function jobFor(record) {
26
+ return ctx.scheduler.listJobs().reverse().find(function (job) {
27
+ return job.projectId === ctx.slug && job.payload && job.payload.mateScheduleId === record.id &&
28
+ job.payload.logicalRevision === record.revision && job.payload.occurrence === record.occurrence;
29
+ });
30
+ }
31
+ function current(session, job) {
32
+ var record = job && job.payload && find(session, job.payload.mateScheduleId);
33
+ if (record && record.createdBy && record.createdBy.type === 'canonicalClay') { try { (ctx.authorizeRuntime || ctx.authorize)(session); } catch (error) { return false; } }
34
+ return !!(record && record.state === 'active' && record.revision === job.payload.logicalRevision &&
35
+ record.occurrence === job.payload.occurrence && record.ownerId === job.ownerId);
36
+ }
37
+ function admit(session, record) {
38
+ if (record.state !== 'active') return null;
39
+ var existing = jobFor(record);
40
+ if (existing && !(existing.state === 'cancelled' && existing.cancelledReason === 'queue_admission_failed')) {
41
+ if (['failed', 'cancelled', 'interrupted'].indexOf(existing.state) >= 0) throw new Error('The occurrence requires recovery; it was not scheduled.');
42
+ return existing;
43
+ }
44
+ var job = ctx.schedule(session, record.message, Math.max(record.runAt, now() + 1),
45
+ { id: record.ownerId }, null, null, 'mate-' + record.id + '-' + record.revision + '-' + record.occurrence,
46
+ null, { exact: true, scheduleRule: record.rule, mateScheduleId: record.id,
47
+ logicalScheduleId: record.id, logicalRevision: record.revision, occurrence: record.occurrence });
48
+ if (!job) throw new Error('The occurrence could not be admitted. The saved schedule needs retry.');
49
+ return job;
50
+ }
51
+ function create(session, value, id, control) {
52
+ var actor = ctx.authorize(session, control);
53
+ var existing = find(session, id);
54
+ if (existing) { if (existing.message !== value.message || JSON.stringify(existing.rule) !== JSON.stringify(value.rule)) throw new Error('Schedule request already names another intent.'); admit(session, existing); return existing; }
55
+ var runAt = rule.nextScheduleRuleTime(value.rule, now(), [], {});
56
+ if (!Number.isFinite(runAt)) throw new Error('The schedule time has expired.');
57
+ var record = { id: id, revision: crypto.randomUUID(), ownerId: ctx.owner(session), message: value.message,
58
+ createdBy: actor || null, updatedBy: actor || null, rule: value.rule, state: 'active', occurrence: 0, count: 0, dateCounts: {}, runAt: runAt };
59
+ replace(session, record);
60
+ admit(session, record);
61
+ return record;
62
+ }
63
+ function checked(session, args, control) {
64
+ ctx.authorize(session, control);
65
+ var record = find(session, args.id);
66
+ if (!record || record.ownerId !== ctx.owner(session)) throw new Error('Schedule not found.');
67
+ if (args.revision && args.revision !== record.revision) throw new Error('The schedule revision is stale.');
68
+ return record;
69
+ }
70
+ function cancel(session, args, control) {
71
+ var record = checked(session, args, control);
72
+ var actor = ctx.authorize(session, control);
73
+ if (record.state === 'cancelled') return record;
74
+ // Persist the tombstone before touching occurrences. Dispatch rechecks it.
75
+ record.state = 'cancelled';
76
+ if (actor) record.updatedBy = actor;
77
+ replace(session, record);
78
+ var job = jobFor(record);
79
+ if (job && job.state === 'queued' && !ctx.cancelJob(session, job)) throw new Error('Cancellation was saved, but occurrence cleanup failed.');
80
+ return record;
81
+ }
82
+ function update(session, args, value, control) {
83
+ var previous = checked(session, args, control);
84
+ var actor = ctx.authorize(session, control);
85
+ if (previous.state !== 'active') throw new Error('Only active schedules can be updated.');
86
+ var runAt = rule.nextScheduleRuleTime(value.rule, now(), [], {});
87
+ if (!Number.isFinite(runAt)) throw new Error('The schedule time has expired.');
88
+ var record = Object.assign({}, previous, { revision: crypto.randomUUID(), updatedBy: actor || previous.updatedBy || null, message: value.message,
89
+ rule: value.rule, count: 0, dateCounts: {}, occurrence: 0, runAt: runAt });
90
+ replace(session, record);
91
+ var oldJob = jobFor(previous);
92
+ if (oldJob && oldJob.state === 'queued' && !ctx.cancelJob(session, oldJob)) throw new Error('Update saved, but previous occurrence cleanup failed.');
93
+ admit(session, record);
94
+ return record;
95
+ }
96
+ function consumed(session, job) {
97
+ if (!current(session, job)) return false;
98
+ var record = find(session, job.payload.mateScheduleId);
99
+ record.count++;
100
+ var date = new Date(record.runAt);
101
+ var key = date.getFullYear() + '-' + String(date.getMonth() + 1).padStart(2, '0') + '-' + String(date.getDate()).padStart(2, '0');
102
+ record.dateCounts[key] = Number(record.dateCounts[key] || 0) + 1;
103
+ // Coalesce missed times: deliver the admitted occurrence once, then choose
104
+ // the next future time. Counts represent deliveries, not missed slots.
105
+ record.runAt = rule.nextScheduleRuleTime(record.rule, Math.max(record.runAt, now()), [],
106
+ { startCount: record.count, dateStartCounts: record.dateCounts });
107
+ record.occurrence++;
108
+ if (!Number.isFinite(record.runAt)) record.state = 'completed';
109
+ replace(session, record);
110
+ admit(session, record);
111
+ return true;
112
+ }
113
+ function reconcile(session) {
114
+ records(session).forEach(function (record) {
115
+ if (record.state !== 'active') return;
116
+ (ctx.authorizeRuntime || ctx.authorize)(session);
117
+ var job = jobFor(record);
118
+ var item = job && ctx.queueItem(session, job);
119
+ if (item && item.state === 'consumed') consumed(session, job);
120
+ else if (item && (item.state === 'cancelled' || item.state === 'failed')) {
121
+ record.state = item.state;
122
+ replace(session, record);
123
+ } else if (job && ['failed', 'cancelled', 'interrupted'].indexOf(job.state) >= 0 && (!item || item.state !== 'pending')) {
124
+ record.state = 'interrupted';
125
+ replace(session, record);
126
+ } else admit(session, record);
127
+ });
128
+ }
129
+ function onConsumed(session, job) {
130
+ try { return consumed(session, job); }
131
+ catch (error) {
132
+ // Queue consumption is already durable. Keep the accepted provider turn
133
+ // running; reconciliation repairs the saved next occurrence after restart.
134
+ ctx.sm.sendAndRecord(session, { type: 'error', text: 'The scheduled message was delivered, but its next occurrence needs recovery: ' + error.message });
135
+ return false;
136
+ }
137
+ }
138
+ return { create: create, read: checked, list: function (session, control) { ctx.authorize(session, control); return records(session); },
139
+ update: update, cancel: cancel, failed: function (session, job, error) {
140
+ if (!current(session, job)) return;
141
+ var record = find(session, job.payload.mateScheduleId);
142
+ record.state = 'failed'; record.error = error.message;
143
+ replace(session, record);
144
+ }, cancelled: function (session, job) {
145
+ if (!current(session, job)) return;
146
+ var record = find(session, job.payload.mateScheduleId);
147
+ record.state = 'cancelled';
148
+ replace(session, record);
149
+ }, current: current, consumed: onConsumed, reconcile: reconcile };
150
+ }
151
+ module.exports = { attachMateScheduleLifecycle: attachMateScheduleLifecycle };
@@ -0,0 +1,103 @@
1
+ var crypto = require('crypto');
2
+ var userInput = require('./yoke/user-input');
3
+ var input = require('./mate-schedule-input');
4
+ var personal = require('./mcp-session-access');
5
+
6
+ function attachMateScheduling(ctx) {
7
+ function owner(session) { return ctx.users.isMultiUser() ? session.ownerId : 'local-user'; }
8
+ function privateSession(session) {
9
+ if (!ctx.isMate || !session || ctx.sm.sessions.get(session.localId) !== session ||
10
+ session.destroying || session.mateCreationMode || session.taskStopRequested || session._mcpForeignInput ||
11
+ session.sessionVisibility === 'shared' || session.delegated || session._delegatedBy || session._pairDelegation) throw new Error('An active private Mate conversation is required.');
12
+ if (ctx.users.isMultiUser() && (session.ownerId !== ctx.projectOwnerId || !personal.canUsePersonalConnections(session, ctx.sm.sessions))) throw new Error('Only the Mate owner can schedule messages.');
13
+ if (!ctx.users.isMultiUser() && (session.ownerId || (session.history || []).some(function (event) { return event.type === 'user_message' && event.from && event.from !== 'default'; }))) throw new Error('Foreign input cannot authorize Mate schedules.');
14
+ ctx.authorizeAccess(session, owner(session));
15
+ }
16
+ function authorize(session) {
17
+ if (ctx.isHostAgent) throw new Error('Canonical Clay scheduling requires its separate owner-reviewed controls.');
18
+ privateSession(session);
19
+ }
20
+ function authorizeControl(session, control) {
21
+ privateSession(session);
22
+ return require('./canonical-clay-scheduling-authority').validate(control, ctx.slug, session);
23
+ }
24
+ function authorizeLifecycle(session) {
25
+ privateSession(session);
26
+ require('./canonical-clay-scheduling-authority').assertMate(ctx.projectOwnerId, ctx.mateId, ctx.users.isMultiUser());
27
+ if (ctx.isHostAgent) require('./canonical-clay-scheduling-authority').assertHost(ctx.projectOwnerId, ctx.mateId, ctx.users.isMultiUser());
28
+ }
29
+ function persistDraft(session, draft) {
30
+ var previous = session.mateScheduleDraft;
31
+ session.mateScheduleDraft = draft;
32
+ if (ctx.sm.saveSessionFile(session) !== true) {
33
+ session.mateScheduleDraft = previous;
34
+ throw new Error('The schedule draft could not be saved.');
35
+ }
36
+ }
37
+ function result(value) { return { content: [{ type: 'text', text: JSON.stringify(value) }] }; }
38
+ function getToolDefs(session) {
39
+ try { authorize(session); } catch (error) { return []; }
40
+ var generation = Number(session._sdkQueryGeneration || 0);
41
+ var originalOwner = owner(session);
42
+ function current() {
43
+ authorize(session);
44
+ if (generation !== Number(session._sdkQueryGeneration || 0) || owner(session) !== originalOwner) throw new Error('The schedule query is stale.');
45
+ }
46
+ function tool(name, description, properties, required, handler) {
47
+ return { name: name, queryBound: true, inputSchema: { type: 'object', properties: properties, required: required, additionalProperties: false },
48
+ description: description, handler: async function (args) {
49
+ try { current(); return result(await handler(args || {})); }
50
+ catch (error) { return result({ status: 'rejected', reason: error.message }); }
51
+ } };
52
+ }
53
+ var str = { type: 'string' };
54
+ var fields = { message: str, date: str, time: str, scheduleRule: { type: ['object', 'null'] } };
55
+ async function approve(draft, question, label, other) {
56
+ persistDraft(session, draft);
57
+ var reply = await userInput.dispatchUserInput(ctx.userInput(session), { questions: [{
58
+ id: 'approve', header: 'Mate schedule', question: question,
59
+ options: [{ label: label }, { label: other || 'Cancel' }], allowOther: false,
60
+ }] }, { source: 'mate-schedule', signal: session.abortController && session.abortController.signal });
61
+ current();
62
+ if (!session.mateScheduleDraft || session.mateScheduleDraft.id !== draft.id || session.mateScheduleDraft.revision !== draft.revision) throw new Error('The schedule draft is stale.');
63
+ var accepted = reply.status === 'submitted' && reply.answers.approve && reply.answers.approve.length === 1 && reply.answers.approve[0] === label;
64
+ if (!accepted) persistDraft(session, null);
65
+ return accepted;
66
+ }
67
+ async function review(args, update) {
68
+ var previous = update ? ctx.lifecycle.read(session, args) : null;
69
+ var value = input.normalize(args, previous);
70
+ var draft = { id: crypto.randomUUID(), revision: crypto.randomUUID(), value: value,
71
+ targetId: previous && previous.id, targetRevision: previous && previous.revision };
72
+ if (!await approve(draft, (update ? 'Update this schedule?\n' : 'Create this schedule?\n') + input.review(value), update ? 'Update schedule' : 'Create schedule')) return { status: 'cancelled' };
73
+ var record = update ? ctx.lifecycle.update(session, { id: draft.targetId, revision: draft.targetRevision }, value) : ctx.lifecycle.create(session, value, draft.id);
74
+ persistDraft(session, null);
75
+ return { status: update ? 'updated' : 'created', schedule: record, timezone: input.timezone() };
76
+ }
77
+ async function cancel(args) {
78
+ var record = ctx.lifecycle.read(session, args);
79
+ if (record.state === 'cancelled') return { status: 'cancelled', schedule: record };
80
+ var draft = { id: crypto.randomUUID(), revision: crypto.randomUUID(), targetId: record.id, targetRevision: record.revision };
81
+ if (!await approve(draft, 'Cancel this schedule?\n' + input.review({ message: record.message, rule: record.rule }), 'Cancel schedule', 'Keep schedule')) return { status: 'unchanged' };
82
+ record = ctx.lifecycle.cancel(session, { id: draft.targetId, revision: draft.targetRevision });
83
+ persistDraft(session, null);
84
+ return { status: 'cancelled', schedule: record };
85
+ }
86
+ var begin = tool('begin_mate_schedule_interview', 'Begin scheduling for this Mate. Ask exactly one structured question at a time. Never assume repetition.', {}, [], function () {
87
+ return { status: 'interview_started', timezone: input.timezone(), guidance: 'Collect the message, date/time, and explicitly requested repetition one question at a time. Then propose the complete schedule for the human approval card.' };
88
+ });
89
+ begin.structuredQuestionLimit = function () { try { current(); return 1; } catch (error) { return null; } };
90
+ return [begin,
91
+ tool('propose_mate_schedule', 'Review a complete message schedule in a server-owned approval card. Only authenticated human approval persists a schedule.', fields, ['message'], function (args) { return review(args, false); }),
92
+ tool('list_mate_schedules', 'List logical schedules and their stable IDs, revisions and lifecycle states in this private conversation.', {}, [], function () { return { schedules: ctx.lifecycle.list(session) }; }),
93
+ tool('read_mate_schedule', 'Read one logical schedule using its listed ID.', { id: str }, ['id'], function (args) { return { schedule: ctx.lifecycle.read(session, args) }; }),
94
+ tool('update_mate_schedule', 'Propose changes to an active schedule by listed ID and revision, with a fresh human approval card.', Object.assign({ id: str, revision: str }, fields), ['id', 'revision'], function (args) { return review(args, true); }),
95
+ tool('cancel_mate_schedule', 'Review cancellation by listed ID and revision in an authenticated human approval card. Cancellation persists across restart.', { id: str, revision: str }, ['id', 'revision'], cancel),
96
+ ];
97
+ }
98
+ return { authorize: authorize, authorizeControl: authorizeControl, authorizeLifecycle: authorizeLifecycle, owner: owner, getToolDefs: getToolDefs, getSystemPrompt: function (session) {
99
+ try { authorize(session); } catch (error) { return ''; }
100
+ return 'When scheduling for this Mate, call begin_mate_schedule_interview, ask exactly one structured question at a time, and clarify the message, local date/time in ' + input.timezone() + ', and explicitly requested repetition. Use scheduleRule for recurrence and count/until limits. propose_mate_schedule and update_mate_schedule present the exact authenticated human approval card. Chat text and model flags never approve schedules. Use listed logical IDs and revisions to read, update or cancel. Scheduled output uses this private Mate runtime and tools. Project Scheduled Tasks Driver/Worker tools remain unavailable.';
101
+ } };
102
+ }
103
+ module.exports = { attachMateScheduling: attachMateScheduling };
package/lib/mates.js CHANGED
@@ -246,7 +246,7 @@ function updateMate(ctx, id, updates) {
246
246
  return null;
247
247
  }
248
248
 
249
- function deleteMate(ctx, id) {
249
+ function deleteMate(ctx, id, options) {
250
250
  var data = loadMates(ctx);
251
251
  // Primary mates cannot be deleted (they are system infrastructure)
252
252
  for (var di = 0; di < data.mates.length; di++) {
@@ -259,15 +259,16 @@ function deleteMate(ctx, id) {
259
259
  return m.id !== id;
260
260
  });
261
261
  if (data.mates.length === before) return { error: "Mate not found" };
262
- saveMates(ctx, data);
262
+ if (!options || !options.strictCleanup) saveMates(ctx, data);
263
263
 
264
264
  // Remove mate directory
265
265
  var mateDir = getMateDir(ctx, id);
266
266
  try {
267
267
  fs.rmSync(mateDir, { recursive: true, force: true });
268
268
  } catch (e) {
269
- // Directory may not exist
269
+ if (options && options.strictCleanup) throw e;
270
270
  }
271
+ if (options && options.strictCleanup) saveMates(ctx, data);
271
272
 
272
273
  return { ok: true };
273
274
  }
package/lib/mcp-proxy.js CHANGED
@@ -1,32 +1,2 @@
1
- // Preserve the server's JSON Schema across SDK and stdio projections.
2
- function validateDefinitions(definitions) {
3
- var z = require('zod');
4
- var names = new Set();
5
- return definitions.map(function (definition) {
6
- if (!definition || !/^[a-zA-Z0-9_.-]{1,128}$/.test(definition.name) || names.has(definition.name) || Object.prototype.hasOwnProperty.call(Object.prototype, definition.name)) throw new Error('Unsupported MCP tool catalog.');
7
- names.add(definition.name);
8
- var parsed = z.fromJSONSchema(definition.inputSchema || { type: 'object', properties: {} });
9
- if (!parsed.shape) throw new Error('MCP tools must accept an object.');
10
- return parsed;
11
- });
12
- }
13
- function createProxy(name, definitions, invoke) {
14
- var sdk = require('@anthropic-ai/claude-agent-sdk');
15
- var schemas = validateDefinitions(definitions);
16
- var tools = definitions.map(function (definition, index) {
17
- return sdk.tool(definition.name, definition.description || definition.name, schemas[index].shape, function (args) { return invoke(definition.name, args); });
18
- });
19
- var server = sdk.createSdkMcpServer({ name: name, version: '1.0.0', tools: tools });
20
- definitions.forEach(function (definition, index) {
21
- var tool = server.instance._registeredTools[definition.name];
22
- tool.inputSchema = schemas[index];
23
- tool._clayInputSchema = definition.inputSchema || { type: 'object', properties: {} };
24
- });
25
- server.instance.server.setRequestHandler(require('@modelcontextprotocol/sdk/types.js').ListToolsRequestSchema, function () {
26
- return { tools: definitions.map(function (definition) {
27
- return { name: definition.name, description: definition.description, inputSchema: definition.inputSchema || { type: 'object', properties: {} } };
28
- }) };
29
- });
30
- return server;
31
- }
32
- module.exports = { createProxy: createProxy, validateDefinitions: validateDefinitions };
1
+ // Compatibility export for the YOKE SDK/stdio tool projection.
2
+ module.exports = require("./yoke/mcp-proxy");
@@ -1,4 +1,4 @@
1
- var descriptors = require('./sdk-mcp-descriptors').extractMcpDescriptors;
1
+ var descriptors = require('./yoke/sdk-mcp-descriptors').extractMcpDescriptors;
2
2
  function createQueryBridge(ctx) {
3
3
  function valid() {
4
4
  if (!ctx.valid()) throw new Error('MCP tools require the current authorized query.');
@@ -1,91 +1 @@
1
- // File-only adapters. Discovery never loads vendor code, plugins, or OAuth stores.
2
- var path = require('path');
3
- var toml = require('@iarna/toml');
4
- var jsonc = require('jsonc-parser');
5
- var yaml = require('yaml');
6
- var network = require('./mcp-network');
7
- var crypto = require('crypto');
8
- var ADAPTERS = {
9
- claude: { user: ['.claude.json'], project: ['.mcp.json'], key: 'mcpServers' },
10
- codex: { user: ['.codex/config.toml'], project: ['.codex/config.toml'], key: 'mcp_servers' },
11
- kiro: { user: ['.kiro/settings/mcp.json', '.kiro/mcp.json'], project: ['.kiro/settings/mcp.json', '.kiro/mcp.json'], key: 'mcpServers', agents: '.kiro/agents' },
12
- opencode: { user: ['.config/opencode/opencode.json', '.config/opencode/opencode.jsonc'], project: ['opencode.json', 'opencode.jsonc'], key: 'mcp' },
13
- kimi: { user: ['.kimi-code/mcp.json', '.kimi/mcp.json'], project: ['.kimi-code/mcp.json'], key: 'mcpServers' },
14
- copilot: { user: ['.copilot/mcp-config.json'], project: ['.mcp.json', '.github/mcp.json'], key: 'mcpServers' },
15
- qwen: { user: ['.qwen/settings.json'], project: ['.qwen/settings.json'], key: 'mcpServers' },
16
- junie: { user: ['.junie/mcp/mcp.json'], project: ['.junie/mcp/mcp.json'], key: 'mcpServers' },
17
- grok: { user: ['.grok/config.toml'], project: ['.grok/config.toml'], key: 'mcp_servers' },
18
- antigravity: { user: ['.gemini/config/mcp_config.json', '.gemini/antigravity-cli/mcp_config.json'], project: ['.agents/mcp_config.json'], key: 'mcpServers', plugins: '.gemini/antigravity-cli/plugins' },
19
- acp: { user: [], project: [], key: 'mcpServers' },
20
- };
21
- function parse(file, content) {
22
- if (file.endsWith('.md')) {
23
- var match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(content);
24
- if (!match) throw new Error('Agent profile requires YAML frontmatter.');
25
- var document = yaml.parseDocument(match[1]);
26
- if (document.errors.length) throw new Error('Invalid agent frontmatter.');
27
- return document.toJS({ maxAliasCount: 50 });
28
- }
29
- if (file.endsWith('.toml')) return toml.parse(content);
30
- var errors = [], value = jsonc.parse(content, errors, { allowTrailingComma: true });
31
- if (errors.length || !value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Invalid MCP source format.');
32
- return value;
33
- }
34
- function stringMap(value) {
35
- if (!value) return {};
36
- if (Array.isArray(value)) {
37
- var map = {}; value.forEach(function (entry) { if (!entry || typeof entry.name !== 'string' || typeof entry.value !== 'string') throw new Error('Invalid name/value field.'); map[entry.name] = entry.value; });
38
- return map;
39
- }
40
- if (typeof value !== 'object') throw new Error('Invalid environment or headers.');
41
- Object.keys(value).forEach(function (name) { if (typeof value[name] !== 'string') throw new Error('Invalid environment or headers.'); });
42
- return Object.assign({}, value);
43
- }
44
- function normalize(vendor, name, value, source) {
45
- if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Invalid server definition.');
46
- ['enabled', 'disabled'].forEach(function (key) { if (value[key] !== undefined && typeof value[key] !== 'boolean') throw new Error('Invalid source enablement: ' + key); });
47
- if (value.oauth !== undefined && value.oauth !== true) throw new Error('Vendor OAuth policy requires reviewed Clay-owned authentication setup.');
48
- var command = value.command, args = value.args || [];
49
- if (vendor === 'opencode' && Array.isArray(command)) { args = command.slice(1); command = command[0]; }
50
- var url = value.url || value.httpUrl || value.serverUrl;
51
- if (command && url) throw new Error('Conflicting stdio and remote transport definitions.');
52
- var type = value.type || value.transport || (url ? vendor === 'qwen' && !value.httpUrl ? 'sse' : 'http' : 'stdio');
53
- if (type === 'local') type = 'stdio'; if (type === 'remote' || type === 'streamable-http') type = 'http';
54
- if (['stdio', 'http', 'sse'].indexOf(type) < 0) throw new Error('Unsupported transport. Clay supports stdio, HTTP and SSE.');
55
- if (value.headersHelper || value.oauth && (value.oauth.clientSecret || value.oauth.clientId)) throw new Error('Vendor authentication helper requires Clay-owned credential setup.');
56
- var policy = require('./mcp-tool-policy').normalize(vendor, value);
57
- var config = { transport: type, enabled: false, label: name, source: type === 'stdio' ? 'local' : 'url',
58
- provenance: source, sourceEnabled: value.enabled === false || value.disabled === true ? false : source.scope.indexOf('plugin') === 0 ? null : true };
59
- if (type === 'stdio') {
60
- if (typeof command !== 'string' || !command || command.includes('\0') || !Array.isArray(args) || args.some(function (arg) { return typeof arg !== 'string' || arg.includes('\0'); })) throw new Error('Invalid stdio command or arguments.');
61
- config.command = command; config.args = args; config.env = stringMap(value.env || value.environment); config.cwd = value.cwd || source.cwd;
62
- if (typeof config.cwd !== 'string' || !path.isAbsolute(config.cwd)) throw new Error('Stdio working directory must be absolute.');
63
- } else {
64
- // Do not expand credential references during inspection.
65
- config.url = network.remoteUrl(url).href; config.headers = stringMap(value.headers || value.http_headers);
66
- config.envHeaders = stringMap(value.env_http_headers);
67
- var bearer = value.bearer_token_env_var || value.bearerTokenEnvVar;
68
- if (bearer) { config.bearerTokenEnv = bearer; config.envHeaders.Authorization = bearer; }
69
- }
70
- config.environmentNames = (value.env_vars || []).concat(Object.keys(config.env || {}));
71
- if (value.env_vars !== undefined && !Array.isArray(value.env_vars)) throw new Error('Invalid environment allowlist.');
72
- Object.assign(config, policy);
73
- if (source.sourceEnabled !== undefined) config.sourceEnabled = config.sourceEnabled === false || source.sourceEnabled === false ? false : source.sourceEnabled;
74
- var references = JSON.stringify([config.command, config.args, config.env, config.headers, config.url]).match(/\$\{[A-Za-z_][A-Za-z0-9_]*(?::-[^}]*)?\}|\$[A-Z_][A-Z0-9_]*|\{env:[^}]+\}|\{file:[^}]+\}|\{\{[^}]+\}\}/g) || [];
75
- config.references = Array.from(new Set(references.concat(Object.values(config.envHeaders || {})).concat(value.env_vars || [])));
76
- // Plugins may reference their own installed directory without reading any credential file.
77
- if (source.pluginRoot) {
78
- function pluginValue(value) {
79
- if (typeof value === 'string') return value.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, function () { return source.pluginRoot; }).replace(/\$\{CLAUDE_PROJECT_DIR\}/g, function () { return source.cwd; });
80
- if (Array.isArray(value)) return value.map(pluginValue);
81
- if (value && typeof value === 'object') { var next = {}; Object.keys(value).forEach(function (key) { next[key] = pluginValue(value[key]); }); return next; }
82
- return value;
83
- }
84
- config = pluginValue(config); config.references = config.references.filter(function (ref) { return ref !== source.pluginRoot && ref !== source.cwd; });
85
- }
86
- return config;
87
- }
88
- function signature(config) {
89
- return crypto.createHash('sha256').update(JSON.stringify([config.transport, config.url, config.command, config.args, config.env, config.headers, config.envHeaders, config.cwd, config.disabledTools, config.enabledTools, config.toolPatterns, config.toolPrefix, config.references])).digest('hex');
90
- }
91
- module.exports = { adapters: ADAPTERS, parse: parse, normalize: normalize, signature: signature };
1
+ module.exports = require("./yoke/mcp-source-adapters");
@@ -1,42 +1 @@
1
- var path = require('path');
2
- var crypto = require('crypto');
3
- var adapters = require('./mcp-source-adapters').adapters;
4
- var KEYS = ['CODEX_HOME', 'CLAUDE_CONFIG_DIR', 'OPENCODE_CONFIG', 'OPENCODE_CONFIG_DIR', 'OPENCODE_CONFIG_CONTENT', 'XDG_CONFIG_HOME', 'KIMI_CODE_HOME', 'COPILOT_HOME', 'GROK_HOME', 'QWEN_HOME', 'QWEN_CODE_SYSTEM_SETTINGS_PATH', 'QWEN_CODE_SYSTEM_DEFAULTS_PATH'];
5
- function resolve(ctx, owner, ws, home, identity) {
6
- // Only the production runtime resolver may supply mapped-user overrides.
7
- var env = ctx.runtimeEnv ? ctx.runtimeEnv(owner, ws) : identity ? {} : ctx.home ? {} : process.env;
8
- var selected = {};
9
- KEYS.forEach(function (key) { if (env[key] !== undefined) selected[key] = env[key]; });
10
- function qwenRoot(value) { if (!value) return path.join(home, '.qwen'); return path.resolve(ctx.cwd, value.replace(/^~(?=\/|$)/, home)); }
11
- var roots = { copilot: path.resolve(home, env.COPILOT_HOME || '.copilot'), grok: path.resolve(home, env.GROK_HOME || '.grok'), qwen: qwenRoot(env.QWEN_HOME), codex: path.resolve(home, env.CODEX_HOME || '.codex'), claude: path.resolve(home, env.CLAUDE_CONFIG_DIR || '.claude'),
12
- opencode: path.resolve(home, env.XDG_CONFIG_HOME || '.config', 'opencode'), kimi: path.resolve(home, env.KIMI_CODE_HOME || '.kimi-code') };
13
- var sources = [];
14
- function add(vendor, file, scope, extra) { sources.push(Object.assign({ vendor: vendor, file: file, scope: scope, cwd: ctx.cwd }, extra)); }
15
- Object.keys(adapters).forEach(function (vendor) {
16
- var files = adapters[vendor].user;
17
- if (vendor === 'codex') files = [path.join(roots.codex, 'config.toml')];
18
- if (vendor === 'claude') files = [env.CLAUDE_CONFIG_DIR ? path.join(roots.claude, '.claude.json') : path.join(home, '.claude.json')];
19
- if (vendor === 'opencode') files = ['opencode.json', 'opencode.jsonc'].map(function (file) { return path.join(roots.opencode, file); });
20
- if (vendor === 'copilot') files = [path.join(roots.copilot, 'mcp-config.json')];
21
- if (vendor === 'grok') files = [path.join(roots.grok, 'config.toml')];
22
- if (vendor === 'qwen') files = [path.join(roots.qwen, 'settings.json')];
23
- if (vendor === 'kimi' && env.KIMI_CODE_HOME) files = [path.join(roots.kimi, 'mcp.json')];
24
- files.forEach(function (file) { add(vendor, path.resolve(home, file), 'user'); });
25
- adapters[vendor].project.forEach(function (file) { add(vendor, path.join(ctx.cwd, file), 'project'); });
26
- });
27
- ['opencode.json', 'opencode.jsonc'].forEach(function (file) { add('opencode', path.join(ctx.cwd, '.opencode', file), 'runtime', { configDirectory: true }); });
28
- if (env.OPENCODE_CONFIG) add('opencode', path.resolve(ctx.cwd, env.OPENCODE_CONFIG), 'runtime');
29
- if (env.OPENCODE_CONFIG_DIR) ['opencode.json', 'opencode.jsonc'].forEach(function (file) { add('opencode', path.resolve(ctx.cwd, env.OPENCODE_CONFIG_DIR, file), 'runtime', { configDirectory: true }); });
30
- if (env.OPENCODE_CONFIG_CONTENT) add('opencode', 'runtime:OPENCODE_CONFIG_CONTENT', 'runtime-inline', { inline: env.OPENCODE_CONFIG_CONTENT });
31
- return { roots: roots, policyPaths: { qwenSettings: env.QWEN_CODE_SYSTEM_SETTINGS_PATH && path.resolve(ctx.cwd, env.QWEN_CODE_SYSTEM_SETTINGS_PATH), qwenDefaults: env.QWEN_CODE_SYSTEM_DEFAULTS_PATH && path.resolve(ctx.cwd, env.QWEN_CODE_SYSTEM_DEFAULTS_PATH) }, sources: sources, fingerprint: crypto.createHash('sha256').update(JSON.stringify(selected)).digest('hex') };
32
- }
33
- function priority(source) {
34
- if (source.scope === 'runtime-inline') return 80;
35
- if (source.scope === 'configured') return 70;
36
- if (source.scope === 'runtime') return source.configDirectory ? 65 : 30;
37
- if (source.scope === 'local') return 60;
38
- if (source.scope === 'project') return 50 + (source.vendor === 'copilot' && path.basename(source.file) === '.mcp.json' ? 1 : 0);
39
- if (source.scope === 'project-ancestor') return 40 + source.file.split(path.sep).length * 0.01 + (path.basename(source.file) === '.mcp.json' ? 0.001 : 0);
40
- return source.scope.indexOf('plugin') === 0 ? 10 : 20;
41
- }
42
- module.exports = { resolve: resolve, priority: priority };
1
+ module.exports = require("./yoke/mcp-source-context");