@lanes-sh/link 0.6.10 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/.gcloudignore +25 -15
  2. package/README.md +62 -45
  3. package/instructions/skills/lanes-link/SKILL.md +25 -0
  4. package/package.json +3 -2
  5. package/src/audit/conformance.ts +1 -1
  6. package/src/cli/argv.ts +14 -1
  7. package/src/cli/commands/connect/acquire.ts +100 -0
  8. package/src/cli/commands/connect/custom/index.ts +1 -1
  9. package/src/cli/commands/connect/declare.ts +19 -0
  10. package/src/cli/commands/connect/index.ts +54 -56
  11. package/src/cli/commands/connect/requirements.ts +23 -1
  12. package/src/cli/commands/connect/setup.ts +1 -1
  13. package/src/cli/commands/connect/variables.ts +220 -0
  14. package/src/cli/commands/knowledge/index.ts +22 -4
  15. package/src/cli/commands/knowledge/migrate.ts +61 -43
  16. package/src/cli/commands/operate/tools.ts +1 -1
  17. package/src/cli/commands/owner/entities.ts +244 -0
  18. package/src/cli/commands/owner/shared.ts +14 -0
  19. package/src/cli/commands/owner/vault.ts +2 -2
  20. package/src/cli/commands/owner.ts +13 -3
  21. package/src/cli/commands/setup.ts +12 -0
  22. package/src/cli/config-edit.ts +16 -6
  23. package/src/cli/config-repair.ts +10 -0
  24. package/src/cli/dispatch-owner.ts +30 -1
  25. package/src/cli/main.ts +2 -1
  26. package/src/cli/runtime/open.ts +14 -7
  27. package/src/cli/runtime/registry.ts +6 -1
  28. package/src/cli/selection.ts +11 -0
  29. package/src/cli/usage.ts +13 -2
  30. package/src/connectivity/auth/strategy/index.ts +1 -1
  31. package/src/connectivity/capability.ts +1 -1
  32. package/src/connectivity/context.ts +1 -1
  33. package/src/connectivity/index.ts +1 -1
  34. package/src/connectivity/mail/attachments.ts +42 -73
  35. package/src/connectivity/mail/content-type.ts +71 -0
  36. package/src/connectivity/mail/index.ts +1 -1
  37. package/src/connectivity/manifest/provider.ts +50 -0
  38. package/src/connectivity/manifest/variables.ts +173 -0
  39. package/src/connectivity/transports/factory.ts +74 -1
  40. package/src/connectivity/transports/http/index.ts +8 -2
  41. package/src/connectivity/transports/http/keys.ts +83 -0
  42. package/src/connectivity/transports/imap/attachment.ts +53 -10
  43. package/src/connectivity/transports/imap/capabilities.ts +28 -0
  44. package/src/connectivity/transports/imap/download.ts +111 -0
  45. package/src/connectivity/transports/imap/index.ts +13 -0
  46. package/src/connectivity/transports/imap/operations.ts +1 -0
  47. package/src/deployments/adapters/s3.ts +1 -1
  48. package/src/deployments/gcp/provision.ts +1 -1
  49. package/src/deployments/knowledge.ts +44 -18
  50. package/src/deployments/prepare.ts +1 -1
  51. package/src/deployments/serving.ts +1 -1
  52. package/src/dispatch/dispatch.ts +17 -10
  53. package/src/dispatch/staging.ts +76 -1
  54. package/src/profile/knowledge.ts +19 -11
  55. package/src/profile/schema.ts +2 -2
  56. package/src/providers/README.md +189 -0
  57. package/src/providers/airtable/index.ts +10 -0
  58. package/src/providers/algolia/index.ts +10 -0
  59. package/src/providers/amplitude/index.ts +10 -0
  60. package/src/providers/apify/index.ts +10 -0
  61. package/src/providers/asana/index.ts +10 -0
  62. package/src/providers/assets/provider.ts +11 -4
  63. package/src/providers/atlassian/index.ts +19 -0
  64. package/src/providers/attio/index.ts +10 -0
  65. package/src/providers/betterstack/index.ts +10 -0
  66. package/src/providers/box/index.ts +64 -0
  67. package/src/providers/brightdata/index.ts +10 -0
  68. package/src/providers/buildkite/index.ts +10 -0
  69. package/src/providers/bunq/index.ts +2 -2
  70. package/src/providers/calendly/index.ts +10 -0
  71. package/src/providers/canva/index.ts +10 -0
  72. package/src/providers/circleci/index.ts +10 -0
  73. package/src/providers/clickup/index.ts +10 -0
  74. package/src/providers/close/index.ts +10 -0
  75. package/src/providers/cloudflare_bindings/index.ts +14 -0
  76. package/src/providers/cloudflare_observability/index.ts +10 -0
  77. package/src/providers/contentful/index.ts +10 -0
  78. package/src/providers/custom/load.ts +1 -1
  79. package/src/providers/datadog/index.ts +10 -0
  80. package/src/providers/discord/index.ts +1 -1
  81. package/src/providers/discord/specs/discord.v10.json +0 -88
  82. package/src/providers/discord/specs/vendor.ts +1 -1
  83. package/src/providers/dropbox/index.ts +10 -0
  84. package/src/providers/entities/catalogue.ts +366 -0
  85. package/src/providers/entities/find.ts +279 -0
  86. package/src/providers/entities/provider.ts +334 -0
  87. package/src/providers/entities/render.ts +142 -0
  88. package/src/providers/entities/store.ts +276 -0
  89. package/src/providers/entities/writes.ts +279 -0
  90. package/src/providers/example/provider.ts +1 -1
  91. package/src/providers/expensify/index.ts +10 -0
  92. package/src/providers/fastmail/calendar/index.ts +21 -0
  93. package/src/providers/fastmail/contacts/index.ts +17 -0
  94. package/src/providers/fastmail/index.ts +4 -0
  95. package/src/providers/fastmail/mail/index.ts +38 -0
  96. package/src/providers/fastmail/shared/setup.ts +52 -0
  97. package/src/providers/figma/index.ts +10 -0
  98. package/src/providers/fireflies/index.ts +10 -0
  99. package/src/providers/flagsmith/index.ts +10 -0
  100. package/src/providers/gamma/index.ts +10 -0
  101. package/src/providers/github/index.ts +2 -2
  102. package/src/providers/google/gmail/attachment.ts +16 -1
  103. package/src/providers/google/gmail-imap/index.ts +7 -2
  104. package/src/providers/google/shared/oauth.ts +1 -1
  105. package/src/providers/google/shared/service-account.ts +1 -1
  106. package/src/providers/google/shared/setup.ts +1 -1
  107. package/src/providers/google/specs/calendar.v3.json +0 -32
  108. package/src/providers/google/specs/docs.v1.json +0 -76
  109. package/src/providers/google/specs/drive.v3.json +0 -32
  110. package/src/providers/google/specs/gmail.v1.json +0 -76
  111. package/src/providers/google/specs/people.v1.json +0 -77
  112. package/src/providers/google/specs/sheets.v4.json +0 -76
  113. package/src/providers/google/specs/tasks.v1.json +0 -76
  114. package/src/providers/grafana/index.ts +10 -0
  115. package/src/providers/heroku/index.ts +10 -0
  116. package/src/providers/hubspot/index.ts +75 -0
  117. package/src/providers/hygraph/index.ts +10 -0
  118. package/src/providers/icloud/mail/index.ts +5 -0
  119. package/src/providers/icloud/shared/setup.ts +1 -1
  120. package/src/providers/index.ts +255 -0
  121. package/src/providers/insightly/index.ts +10 -0
  122. package/src/providers/jam/index.ts +10 -0
  123. package/src/providers/klaviyo/index.ts +10 -0
  124. package/src/providers/mailbox/index.ts +87 -0
  125. package/src/providers/memory/provider.ts +3 -8
  126. package/src/providers/mercury/index.ts +10 -0
  127. package/src/providers/microsoft/calendar/index.ts +49 -0
  128. package/src/providers/microsoft/contacts/index.ts +50 -0
  129. package/src/providers/microsoft/drive/index.ts +62 -0
  130. package/src/providers/microsoft/index.ts +12 -0
  131. package/src/providers/microsoft/mail/index.ts +76 -0
  132. package/src/providers/microsoft/shared/oauth.ts +58 -0
  133. package/src/providers/microsoft/shared/scopes.ts +56 -0
  134. package/src/providers/microsoft/shared/setup.ts +45 -0
  135. package/src/providers/microsoft/specs/microsoft-todo.v1.json +755 -0
  136. package/src/providers/microsoft/specs/onedrive.v1.json +993 -0
  137. package/src/providers/microsoft/specs/outlook-calendar.v1.json +1743 -0
  138. package/src/providers/microsoft/specs/outlook-contacts.v1.json +430 -0
  139. package/src/providers/microsoft/specs/outlook-mail.v1.json +901 -0
  140. package/src/providers/microsoft/specs/vendor.ts +232 -0
  141. package/src/providers/microsoft/todo/index.ts +54 -0
  142. package/src/providers/miro/index.ts +10 -0
  143. package/src/providers/mixpanel/index.ts +10 -0
  144. package/src/providers/monday/index.ts +10 -0
  145. package/src/providers/mux/index.ts +10 -0
  146. package/src/providers/navan/index.ts +10 -0
  147. package/src/providers/neon/index.ts +10 -0
  148. package/src/providers/netlify/index.ts +10 -0
  149. package/src/providers/nextcloud/calendar/index.ts +28 -0
  150. package/src/providers/nextcloud/contacts/index.ts +18 -0
  151. package/src/providers/nextcloud/index.ts +3 -0
  152. package/src/providers/nextcloud/shared/setup.ts +59 -0
  153. package/src/providers/owner.ts +15 -3
  154. package/src/providers/paddle/index.ts +10 -0
  155. package/src/providers/paypal/index.ts +10 -0
  156. package/src/providers/posthog/index.ts +10 -0
  157. package/src/providers/prisma/index.ts +10 -0
  158. package/src/providers/ramp/index.ts +10 -0
  159. package/src/providers/recurly/index.ts +10 -0
  160. package/src/providers/reddit/index.ts +1 -1
  161. package/src/providers/remote/index.ts +10 -0
  162. package/src/providers/render/index.ts +35 -0
  163. package/src/providers/replicate/index.ts +10 -0
  164. package/src/providers/resend/index.ts +10 -0
  165. package/src/providers/riverside/index.ts +10 -0
  166. package/src/providers/rootly/index.ts +10 -0
  167. package/src/providers/rudderstack/index.ts +10 -0
  168. package/src/providers/salesloft/index.ts +10 -0
  169. package/src/providers/sanity/index.ts +10 -0
  170. package/src/providers/scopes.ts +2 -0
  171. package/src/providers/sentry/index.ts +10 -0
  172. package/src/providers/setup/plan.ts +11 -0
  173. package/src/providers/setup/provider.ts +12 -0
  174. package/src/providers/shared/openapi.ts +70 -0
  175. package/src/providers/shared/slug.ts +28 -0
  176. package/src/providers/shared/vendor-operations.ts +43 -1
  177. package/src/providers/shared/vendor-spec.ts +98 -17
  178. package/src/providers/shortcut/index.ts +10 -0
  179. package/src/providers/slack/index.ts +2 -2
  180. package/src/providers/square/index.ts +10 -0
  181. package/src/providers/storyblok/index.ts +10 -0
  182. package/src/providers/stripe/index.ts +10 -0
  183. package/src/providers/supabase/index.ts +10 -0
  184. package/src/providers/tasks/store.ts +2 -7
  185. package/src/providers/tavily/index.ts +10 -0
  186. package/src/providers/todoist/index.ts +10 -0
  187. package/src/providers/untested.ts +105 -0
  188. package/src/providers/vault/provider.ts +1 -1
  189. package/src/providers/vercel/index.ts +10 -0
  190. package/src/providers/vimeo/index.ts +10 -0
  191. package/src/providers/webflow/index.ts +10 -0
  192. package/src/providers/whimsical/index.ts +10 -0
  193. package/src/providers/wix/index.ts +10 -0
  194. package/src/providers/workable/index.ts +10 -0
  195. package/src/providers/yahoo_mail/index.ts +73 -0
  196. package/src/providers/zapier/index.ts +10 -0
  197. package/src/providers/zoho_mail/index.ts +79 -0
  198. package/src/secrets/document.ts +1 -1
  199. package/src/server/attachments.ts +129 -5
  200. package/src/server/index.ts +3 -3
  201. package/src/server/mcp/instructions.ts +88 -18
  202. package/src/server/stdio.ts +1 -1
@@ -127,6 +127,49 @@ const IDENTITY = `**Identity is declared, not inferred.** Where a name, address
127
127
  owner's is needed, call \`identity_list\`: a profile may hold several, each with a
128
128
  note on when it applies.`;
129
129
 
130
+ /**
131
+ * The one about addressing the wrong person.
132
+ *
133
+ * `IDENTITY` prevents an agent signing as the wrong person; this prevents it
134
+ * writing *to* the wrong one, which is the same mistake pointed outward and is
135
+ * the more expensive of the two — a message signed wrongly is embarrassing, a
136
+ * message sent to the wrong Jan has left.
137
+ *
138
+ * It carries two rules rather than one, because dropping the refusal made the
139
+ * second necessary. `entities_find` returns every match and sets no error, so a
140
+ * client is not stopped by anything: nothing but this sentence stands between
141
+ * "two candidates" and an agent using the first. The count and the wording of
142
+ * the tool result say it too, and this says it before the first call rather
143
+ * than after.
144
+ *
145
+ * Names nothing, for `IDENTITY`'s reason: a per-profile list inside a string
146
+ * with a fixed ceiling is summarised away first in exactly the workspace that
147
+ * has the most people to keep straight.
148
+ */
149
+ const ENTITIES = `**Who you are writing to is declared.** Before using anyone's address or handle,
150
+ call \`entities_find\` — the people, companies and projects this owner deals with
151
+ are there. It returns every match and never chooses: more than one means ask
152
+ which is meant, not take the first.`;
153
+
154
+ /**
155
+ * The pair, when both are reachable.
156
+ *
157
+ * The same argument `MEMORY_AND_TASKS` makes. The mistake is a routing one —
158
+ * reaching for the wrong side of "the owner" and "everybody else" — and a
159
+ * routing rule is shorter and clearer said once, naming both, than implied by
160
+ * two paragraphs that each describe only themselves. It replaces `IDENTITY`
161
+ * rather than joining it, and measures 161 characters cheaper than the two
162
+ * apart (see `MAX_INSTRUCTIONS`).
163
+ *
164
+ * Worth noting which case is ordinary: `entities` is granted on a fresh profile
165
+ * and `identity` is not (ADR-050, ADR-056), so `ENTITIES` alone is the common
166
+ * form and this one arrives only once the owner has declared themselves.
167
+ */
168
+ const IDENTITY_AND_ENTITIES = `**Who someone is, is declared rather than inferred.** For the owner's own name,
169
+ address or handle, call \`identity_list\`. For anyone else — a person, a company,
170
+ a project — call \`entities_find\`, which returns every match and never chooses:
171
+ more than one means ask which is meant, not take the first.`;
172
+
130
173
  const FILES = `**Files are named, not carried.** Where a tool takes attachments, give a path, an
131
174
  HTTPS URL, or an attachment already on another message; the endpoint reads the
132
175
  bytes. Never encode a file into a call — that is the thing this replaces.`;
@@ -165,26 +208,34 @@ const OWNER_HABITS: Record<string, string> = {
165
208
  vault: VAULT,
166
209
  setup: SETUP,
167
210
  identity: IDENTITY,
211
+ entities: ENTITIES,
168
212
  };
169
213
 
170
214
  /**
171
215
  * The paragraphs this principal should be told, in `RESERVED_PROVIDER_IDS` order.
172
216
  *
173
217
  * A lookup per provider would be enough if every paragraph described exactly one
174
- * provider, and one does not: memory and tasks are only worth distinguishing
175
- * from each other, so when both are reachable they collapse into one. The
176
- * substitution is conditional rather than unconditional for the reason the
177
- * docstring at the top of this file gives — prose describing a tool that is not
178
- * there is worse than absent prose, and a profile carrying `deny: [tasks.*]` is
179
- * exactly the case that would produce it.
218
+ * provider, and two do not. Memory and tasks are only worth distinguishing from
219
+ * each other; identity and entities are the same question about different
220
+ * people. Each pair collapses into one paragraph when both halves are
221
+ * reachable. The substitutions are conditional rather than unconditional for
222
+ * the reason the docstring at the top of this file gives prose describing a
223
+ * tool that is not there is worse than absent prose, and a profile carrying
224
+ * `deny: [tasks.*]` is exactly the case that would produce it.
225
+ *
226
+ * The two pairs are independent, which is why the budget below is certified
227
+ * against four combinations rather than two.
180
228
  */
181
229
  function habitsFor(reachable: readonly string[]): string[] {
182
230
  const present = new Set(reachable);
183
- const paired = present.has('memory') && present.has('tasks');
231
+ const stores = present.has('memory') && present.has('tasks');
232
+ const people = present.has('identity') && present.has('entities');
184
233
 
185
234
  return reachable.flatMap((id) => {
186
- if (paired && id === 'memory') return [MEMORY_AND_TASKS];
187
- if (paired && id === 'tasks') return [];
235
+ if (stores && id === 'memory') return [MEMORY_AND_TASKS];
236
+ if (stores && id === 'tasks') return [];
237
+ if (people && id === 'identity') return [IDENTITY_AND_ENTITIES];
238
+ if (people && id === 'entities') return [];
188
239
  return OWNER_HABITS[id] ? [OWNER_HABITS[id]!] : [];
189
240
  });
190
241
  }
@@ -214,14 +265,33 @@ function habitsFor(reachable: readonly string[]): string[] {
214
265
  * has already done so by the time a skill would have been loaded. The client
215
266
  * that most needs the rule is the one holding no skills directory.
216
267
  *
217
- * The arithmetic, because the number is a measurement and not a round figure:
218
- * twenty profiles, twenty connections each, every owner provider reachable,
219
- * remote clients, is **2686**. That is the *unpaired* case memory reachable
220
- * and tasks denied which runs three characters longer than the ordinary one
221
- * (2683), because `MEMORY_AND_TASKS` is slightly shorter than `MEMORY` and
222
- * `TASKS` apart. Worth stating, because the last two raises were both certified
223
- * against a case an endpoint does not actually serve, and the widest case here
224
- * is the one that looks like the narrower configuration.
268
+ * Raised a fourth time, to 2900, for `entities` (ADR-056), and the answer is
269
+ * `IDENTITY`'s restated one step outward. An agent that resolves "email Jan" to
270
+ * the wrong address has already sent the message; the mistake happens at the
271
+ * instant of the send, before a skill would have been loaded, and the client
272
+ * most in need of the rule is again the one holding no skills directory. The
273
+ * paragraph also carries a rule nothing else can enforce: `entities_find` sets
274
+ * no error on an ambiguous result, so between "two candidates" and an agent
275
+ * using the first there is only prose.
276
+ *
277
+ * The arithmetic, because the number is a measurement and not a round figure.
278
+ * Twenty profiles, twenty connections each, every owner provider reachable,
279
+ * remote clients:
280
+ *
281
+ * neither identity nor entities reachable 2500
282
+ * + `IDENTITY` alone 2686 (+186)
283
+ * + `ENTITIES` alone 2775 (+275)
284
+ * + both, collapsed 2800 (+300)
285
+ * + both, if they were not collapsed 2961
286
+ *
287
+ * So the maximum is **2800**, and the collapse is worth 161 characters as well
288
+ * as being the clearer prose. Every figure above is the *unpaired* memory case
289
+ * — memory reachable and tasks denied — which runs three characters longer than
290
+ * the ordinary one, because `MEMORY_AND_TASKS` is shorter than `MEMORY` and
291
+ * `TASKS` apart. Worth stating again, because two earlier raises were certified
292
+ * against a case an endpoint does not actually serve, and the widest case is
293
+ * still the one that looks like the narrower configuration. There are now two
294
+ * independent pairs, so the test walks four combinations rather than two.
225
295
  *
226
296
  * Exported because the test asserted `2000` as a literal while the code
227
297
  * reserved room against a second, differently-derived number — so the two could
@@ -230,7 +300,7 @@ function habitsFor(reachable: readonly string[]): string[] {
230
300
  * exactly the final length, because `join` adds the same two characters the
231
301
  * reduce already counted.
232
302
  */
233
- export const MAX_INSTRUCTIONS = 2700;
303
+ export const MAX_INSTRUCTIONS = 2900;
234
304
 
235
305
  /** Which of the owner-layer providers this principal can actually reach. */
236
306
  function ownerProviders(merged: ReadonlyMap<string, MergedCapability>): string[] {
@@ -112,7 +112,7 @@ export function serveOverStdio(options: StdioOptions): StdioSurface {
112
112
  * write it. Policy-filtered discovery means an unpermitted tool is never
113
113
  * advertised, so the protocol layer answers a call naming one before any of our
114
114
  * code runs — and it would otherwise leave no trace at all, which is what
115
- * `audit.every-invocation` in `docs/detailed/security.md` promises it does not.
115
+ * `audit.every-invocation` in `https://lanes.sh/docs/link/security` promises it does not.
116
116
  *
117
117
  * HTTP reads the method and target from the 2026-07-28 headers, which is exact
118
118
  * for an envelope client and blind to a 2025-era one — a documented gap over