terse-cli 0.3.2 → 0.3.4

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 (189) hide show
  1. package/dist/codegen.d.ts +0 -15
  2. package/dist/codegen.d.ts.map +1 -1
  3. package/dist/codegen.js +81 -466
  4. package/dist/codegen.js.map +1 -1
  5. package/dist/commands/install.d.ts.map +1 -1
  6. package/dist/commands/install.js +1 -18
  7. package/dist/commands/install.js.map +1 -1
  8. package/dist/commands/integrate.d.ts.map +1 -1
  9. package/dist/commands/integrate.js +5 -1
  10. package/dist/commands/integrate.js.map +1 -1
  11. package/dist/deploy.d.ts +1 -2
  12. package/dist/deploy.d.ts.map +1 -1
  13. package/dist/deploy.js +38 -61
  14. package/dist/deploy.js.map +1 -1
  15. package/dist/generate.d.ts +1 -2
  16. package/dist/generate.d.ts.map +1 -1
  17. package/dist/generate.js +69 -67
  18. package/dist/generate.js.map +1 -1
  19. package/dist/init.d.ts +1 -2
  20. package/dist/init.d.ts.map +1 -1
  21. package/dist/init.js +96 -45
  22. package/dist/init.js.map +1 -1
  23. package/dist/integrate.d.ts +0 -1
  24. package/dist/integrate.d.ts.map +1 -1
  25. package/dist/integrate.js +11 -191
  26. package/dist/integrate.js.map +1 -1
  27. package/dist/jsonOutput.d.ts +19 -0
  28. package/dist/jsonOutput.d.ts.map +1 -0
  29. package/dist/jsonOutput.js +25 -0
  30. package/dist/jsonOutput.js.map +1 -0
  31. package/dist/nonInteractive.d.ts +2 -4
  32. package/dist/nonInteractive.d.ts.map +1 -1
  33. package/dist/nonInteractive.js +2 -5
  34. package/dist/nonInteractive.js.map +1 -1
  35. package/dist/providers/python/PythonProvider.js +0 -1
  36. package/dist/providers/python/PythonProvider.js.map +1 -1
  37. package/dist/providers/typescript/modules/registry.d.ts.map +1 -1
  38. package/dist/providers/typescript/modules/registry.js +3 -1
  39. package/dist/providers/typescript/modules/registry.js.map +1 -1
  40. package/dist/providers/typescript/parkSignals.d.ts +7 -0
  41. package/dist/providers/typescript/parkSignals.d.ts.map +1 -0
  42. package/dist/providers/typescript/parkSignals.js +45 -0
  43. package/dist/providers/typescript/parkSignals.js.map +1 -0
  44. package/dist/replay.d.ts +3 -0
  45. package/dist/replay.d.ts.map +1 -0
  46. package/dist/replay.js +20 -0
  47. package/dist/replay.js.map +1 -0
  48. package/dist/run.d.ts +11 -2
  49. package/dist/run.d.ts.map +1 -1
  50. package/dist/run.js +153 -42
  51. package/dist/run.js.map +1 -1
  52. package/dist/sampleEventId.d.ts +4 -0
  53. package/dist/sampleEventId.d.ts.map +1 -1
  54. package/dist/sampleEventId.js +4 -0
  55. package/dist/sampleEventId.js.map +1 -1
  56. package/dist/shared/ApiRoutes.d.ts +0 -19
  57. package/dist/shared/ApiRoutes.d.ts.map +1 -1
  58. package/dist/shared/ApiRoutes.js +1 -17
  59. package/dist/shared/ApiRoutes.js.map +1 -1
  60. package/dist/shared/Configs.d.ts +2 -24
  61. package/dist/shared/Configs.d.ts.map +1 -1
  62. package/dist/shared/Configs.js +2 -32
  63. package/dist/shared/Configs.js.map +1 -1
  64. package/dist/shared/Integrations.d.ts +1 -18
  65. package/dist/shared/Integrations.d.ts.map +1 -1
  66. package/dist/shared/Integrations.js +1 -10
  67. package/dist/shared/Integrations.js.map +1 -1
  68. package/dist/shared/InvalidationKeys.d.ts +0 -1
  69. package/dist/shared/InvalidationKeys.d.ts.map +1 -1
  70. package/dist/shared/InvalidationKeys.js +0 -3
  71. package/dist/shared/InvalidationKeys.js.map +1 -1
  72. package/dist/shared/ModelEvents.d.ts +0 -9
  73. package/dist/shared/ModelEvents.d.ts.map +1 -1
  74. package/dist/shared/ModelEvents.js +0 -15
  75. package/dist/shared/ModelEvents.js.map +1 -1
  76. package/dist/shared/ToolDisplayUtils.d.ts.map +1 -1
  77. package/dist/shared/ToolDisplayUtils.js +11 -107
  78. package/dist/shared/ToolDisplayUtils.js.map +1 -1
  79. package/dist/shared/types.d.ts +108 -1013
  80. package/dist/shared/types.d.ts.map +1 -1
  81. package/dist/shared/types.js.map +1 -1
  82. package/dist/test.d.ts +1 -2
  83. package/dist/test.d.ts.map +1 -1
  84. package/dist/test.js +23 -43
  85. package/dist/test.js.map +1 -1
  86. package/dist/testRelay.d.ts +6 -0
  87. package/dist/testRelay.d.ts.map +1 -0
  88. package/dist/testRelay.js +91 -0
  89. package/dist/testRelay.js.map +1 -0
  90. package/dist/urls.d.ts +3 -0
  91. package/dist/urls.d.ts.map +1 -0
  92. package/dist/urls.js +27 -0
  93. package/dist/urls.js.map +1 -0
  94. package/dist/util.d.ts +3 -2
  95. package/dist/util.d.ts.map +1 -1
  96. package/dist/util.js +3 -3
  97. package/dist/util.js.map +1 -1
  98. package/package.json +3 -3
  99. package/src/providers/typescript/modules/apollo/apollo.tools.hbs +12 -0
  100. package/dist/_tmp_create_project.d.ts +0 -2
  101. package/dist/_tmp_create_project.d.ts.map +0 -1
  102. package/dist/_tmp_create_project.js +0 -17
  103. package/dist/_tmp_create_project.js.map +0 -1
  104. package/dist/_tmp_delete_agent.d.ts +0 -2
  105. package/dist/_tmp_delete_agent.d.ts.map +0 -1
  106. package/dist/_tmp_delete_agent.js +0 -14
  107. package/dist/_tmp_delete_agent.js.map +0 -1
  108. package/dist/_tmp_manual_trigger.d.ts +0 -2
  109. package/dist/_tmp_manual_trigger.d.ts.map +0 -1
  110. package/dist/_tmp_manual_trigger.js +0 -17
  111. package/dist/_tmp_manual_trigger.js.map +0 -1
  112. package/dist/_tmp_patch_active.d.ts +0 -2
  113. package/dist/_tmp_patch_active.d.ts.map +0 -1
  114. package/dist/_tmp_patch_active.js +0 -21
  115. package/dist/_tmp_patch_active.js.map +0 -1
  116. package/dist/commands/deployTheme.d.ts +0 -28
  117. package/dist/commands/deployTheme.d.ts.map +0 -1
  118. package/dist/commands/deployTheme.js +0 -68
  119. package/dist/commands/deployTheme.js.map +0 -1
  120. package/dist/commands/dev.d.ts +0 -3
  121. package/dist/commands/dev.d.ts.map +0 -1
  122. package/dist/commands/dev.js +0 -47
  123. package/dist/commands/dev.js.map +0 -1
  124. package/dist/commands/fsExec.d.ts +0 -8
  125. package/dist/commands/fsExec.d.ts.map +0 -1
  126. package/dist/commands/fsExec.js +0 -46
  127. package/dist/commands/fsExec.js.map +0 -1
  128. package/dist/commands/serve.d.ts +0 -1
  129. package/dist/commands/serve.d.ts.map +0 -1
  130. package/dist/commands/serve.js +0 -2
  131. package/dist/commands/serve.js.map +0 -1
  132. package/dist/commands/terseCliTheme.d.ts +0 -28
  133. package/dist/commands/terseCliTheme.d.ts.map +0 -1
  134. package/dist/commands/terseCliTheme.js +0 -68
  135. package/dist/commands/terseCliTheme.js.map +0 -1
  136. package/dist/commands/tool.d.ts +0 -6
  137. package/dist/commands/tool.d.ts.map +0 -1
  138. package/dist/commands/tool.js +0 -34
  139. package/dist/commands/tool.js.map +0 -1
  140. package/dist/data/standardSlackEmoji.d.ts +0 -2
  141. package/dist/data/standardSlackEmoji.d.ts.map +0 -1
  142. package/dist/data/standardSlackEmoji.js +0 -1978
  143. package/dist/data/standardSlackEmoji.js.map +0 -1
  144. package/dist/data/standardSlackEmoji.json +0 -1974
  145. package/dist/perf.d.ts +0 -9
  146. package/dist/perf.d.ts.map +0 -1
  147. package/dist/perf.js +0 -59
  148. package/dist/perf.js.map +0 -1
  149. package/dist/providers/codegen.test.d.ts +0 -2
  150. package/dist/providers/codegen.test.d.ts.map +0 -1
  151. package/dist/providers/codegen.test.js +0 -45
  152. package/dist/providers/codegen.test.js.map +0 -1
  153. package/dist/providers/python/PythonProvider.test.d.ts +0 -2
  154. package/dist/providers/python/PythonProvider.test.d.ts.map +0 -1
  155. package/dist/providers/python/PythonProvider.test.js +0 -169
  156. package/dist/providers/python/PythonProvider.test.js.map +0 -1
  157. package/dist/providers/typescript/attioProjection.d.ts +0 -50
  158. package/dist/providers/typescript/attioProjection.d.ts.map +0 -1
  159. package/dist/providers/typescript/attioProjection.js +0 -358
  160. package/dist/providers/typescript/attioProjection.js.map +0 -1
  161. package/dist/providers/typescript/prepareCodegenData.test.d.ts +0 -2
  162. package/dist/providers/typescript/prepareCodegenData.test.d.ts.map +0 -1
  163. package/dist/providers/typescript/prepareCodegenData.test.js +0 -54
  164. package/dist/providers/typescript/prepareCodegenData.test.js.map +0 -1
  165. package/dist/providers/typescript/projectedTypes.d.ts +0 -11
  166. package/dist/providers/typescript/projectedTypes.d.ts.map +0 -1
  167. package/dist/providers/typescript/projectedTypes.js +0 -53
  168. package/dist/providers/typescript/projectedTypes.js.map +0 -1
  169. package/dist/providers/typescript/projectionPrinter.d.ts +0 -26
  170. package/dist/providers/typescript/projectionPrinter.d.ts.map +0 -1
  171. package/dist/providers/typescript/projectionPrinter.js +0 -110
  172. package/dist/providers/typescript/projectionPrinter.js.map +0 -1
  173. package/dist/providers/typescript/replayLogDedupe.d.ts +0 -6
  174. package/dist/providers/typescript/replayLogDedupe.d.ts.map +0 -1
  175. package/dist/providers/typescript/replayLogDedupe.js +0 -156
  176. package/dist/providers/typescript/replayLogDedupe.js.map +0 -1
  177. package/dist/providers/typescript/triggerPayloads.d.ts +0 -7
  178. package/dist/providers/typescript/triggerPayloads.d.ts.map +0 -1
  179. package/dist/providers/typescript/triggerPayloads.js +0 -60
  180. package/dist/providers/typescript/triggerPayloads.js.map +0 -1
  181. package/dist/providers/typescript/triggerTypeRegistry.d.ts +0 -7
  182. package/dist/providers/typescript/triggerTypeRegistry.d.ts.map +0 -1
  183. package/dist/providers/typescript/triggerTypeRegistry.js +0 -198
  184. package/dist/providers/typescript/triggerTypeRegistry.js.map +0 -1
  185. package/dist/triggerParseDetail.d.ts +0 -8
  186. package/dist/triggerParseDetail.d.ts.map +0 -1
  187. package/dist/triggerParseDetail.js +0 -30
  188. package/dist/triggerParseDetail.js.map +0 -1
  189. package/templates/typescript/codegen/.impeccable/hook.cache.json +0 -1
package/dist/codegen.js CHANGED
@@ -19,82 +19,6 @@ function sectionHeader(name) {
19
19
  function escapeString(s) {
20
20
  return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
21
21
  }
22
- function toGeneratedIdentifier(raw, fallback) {
23
- let name = toPascalCase(raw || fallback);
24
- if (!name)
25
- name = fallback;
26
- if (/^\d/.test(name))
27
- name = `_${name}`;
28
- return name;
29
- }
30
- function isProbablyAttioMultiValue(attr) {
31
- const slug = (attr.api_slug || "").toLowerCase();
32
- const type = (attr.type || "").toLowerCase();
33
- return (type.includes("multi") ||
34
- type.includes("array") ||
35
- type.includes("list") ||
36
- slug === "email_addresses" ||
37
- slug === "domains" ||
38
- slug === "phone_numbers" ||
39
- slug === "social_profiles" ||
40
- slug === "links" ||
41
- slug === "tags" ||
42
- slug.endsWith("_addresses") ||
43
- slug.endsWith("_ids"));
44
- }
45
- function attioAttributeBaseType(attr) {
46
- const slug = (attr.api_slug || "").toLowerCase();
47
- const type = (attr.type || "").toLowerCase();
48
- if (type.includes("checkbox") || type.includes("boolean"))
49
- return "boolean";
50
- if (type.includes("number") || type.includes("currency") || type.includes("rating") || type.includes("percent"))
51
- return "number";
52
- if (type.includes("date") || type.includes("time"))
53
- return "string";
54
- if (type.includes("email") ||
55
- type.includes("domain") ||
56
- type.includes("phone") ||
57
- type.includes("url") ||
58
- type.includes("select") ||
59
- type.includes("status") ||
60
- type.includes("text") ||
61
- type.includes("string") ||
62
- type.includes("name")) {
63
- return "string";
64
- }
65
- if (type.includes("location") ||
66
- type.includes("address") ||
67
- type.includes("reference") ||
68
- type.includes("record") ||
69
- type.includes("actor")) {
70
- return "Record<string, unknown>";
71
- }
72
- if (slug === "email_addresses" || slug === "domains" || slug === "phone_numbers" || slug === "name") {
73
- return "string";
74
- }
75
- return "unknown";
76
- }
77
- function attioAttributeInputTsType(attr) {
78
- const baseType = attioAttributeBaseType(attr);
79
- if (!isProbablyAttioMultiValue(attr))
80
- return baseType;
81
- return baseType.includes("|") ? `(${baseType})[]` : `${baseType}[]`;
82
- }
83
- function attioAttributeRecordTsType(attr) {
84
- const baseType = attioAttributeBaseType(attr);
85
- if (!isProbablyAttioMultiValue(attr))
86
- return baseType;
87
- return baseType.includes("|") ? `(${baseType})[]` : `${baseType}[]`;
88
- }
89
- function renderAttioObjectValueShape(attributes, mode) {
90
- if (attributes.length === 0)
91
- return "Record<string, unknown>";
92
- const lines = attributes.map(attr => {
93
- const valueType = mode === "input" ? attioAttributeInputTsType(attr) : attioAttributeRecordTsType(attr);
94
- return ` "${escapeString(attr.api_slug || "")}"?: ${valueType}`;
95
- });
96
- return `{\n${lines.join("\n")}\n}`;
97
- }
98
22
  /** Map a tool's integration key back to the IntegrationType enum value used by ConfigInstance. */
99
23
  function toolIntegrationToIntegrationType(toolIntegration) {
100
24
  switch (toolIntegration) {
@@ -105,19 +29,6 @@ function toolIntegrationToIntegrationType(toolIntegration) {
105
29
  return toolIntegration;
106
30
  }
107
31
  }
108
- function renderStringLiteralUnion(values) {
109
- if (values.length === 0)
110
- return "never";
111
- return values.map(value => `"${escapeString(value)}"`).join(" | ");
112
- }
113
- function buildSkillToolTypeForIntegration(tools, integrationType) {
114
- const toolNames = tools
115
- .filter(tool => toolIntegrationToIntegrationType(tool.integration.toLowerCase()) === integrationType)
116
- .filter(tool => !tool.isReadOnly || tool.supportsApproval)
117
- .map(tool => tool.name)
118
- .sort();
119
- return renderStringLiteralUnion(toolNames);
120
- }
121
32
  function generateResourceClass(className, fields, staticNameField, items) {
122
33
  const lines = [];
123
34
  lines.push(`export class ${className} {`);
@@ -146,14 +57,13 @@ function generateResourceClass(className, fields, staticNameField, items) {
146
57
  return lines.join("\n");
147
58
  }
148
59
  // ── GitHub ────────────────────────────────────────────────────────────
149
- function generateGitHubSection(instances, tools) {
60
+ function generateGitHubSection(instances) {
150
61
  if (instances.length === 0)
151
62
  return EMPTY_SECTION;
152
63
  const inst = instances[0];
153
64
  const imports = new Set(["GitHubConfig"]);
154
65
  const parts = [sectionHeader("GitHub"), ""];
155
66
  const id = inst.integration.id;
156
- const skillToolType = buildSkillToolTypeForIntegration(tools, "github");
157
67
  const toStaticName = (raw, fallback) => {
158
68
  let name = toPascalCase(raw || fallback);
159
69
  if (!name)
@@ -215,7 +125,6 @@ function generateGitHubSection(instances, tools) {
215
125
  parts.push("");
216
126
  imports.add("GitHubEventType");
217
127
  imports.add("TypedTrigger");
218
- imports.add("TypedSkill");
219
128
  imports.add("GithubPRInputEvent");
220
129
  imports.add("GithubPushInputEvent");
221
130
  imports.add("GithubInputEvent");
@@ -246,21 +155,20 @@ function generateGitHubSection(instances, tools) {
246
155
  parts.push(` return new GitHubConfig("${id}", opts.repos.map(r => r.repositoryId), opts.eventTypes) as TypedTrigger<GithubInputEvent>`);
247
156
  parts.push(" },");
248
157
  parts.push(` /** Use in \`skills[]\` */`);
249
- parts.push(` skill(opts: { repos: Repos[] }): TypedSkill<${skillToolType}> {`);
250
- parts.push(` return new GitHubConfig("${id}", opts.repos.map(r => r.repositoryId)) as TypedSkill<${skillToolType}>`);
158
+ parts.push(` skill(opts: { repos: Repos[] }): GitHubConfig {`);
159
+ parts.push(` return new GitHubConfig("${id}", opts.repos.map(r => r.repositoryId))`);
251
160
  parts.push(" },");
252
161
  parts.push("}");
253
162
  parts.push("");
254
163
  return { code: parts.join("\n"), imports };
255
164
  }
256
165
  // ── Gmail ─────────────────────────────────────────────────────────────
257
- function generateGmailSection(instances, tools) {
166
+ function generateGmailSection(instances) {
258
167
  if (instances.length === 0)
259
168
  return EMPTY_SECTION;
260
- const imports = new Set(["GmailConfig", "GmailOutputConfig", "GmailDraftOutputConfig", "TypedSkill"]);
169
+ const imports = new Set(["GmailConfig", "GmailOutputConfig", "GmailDraftOutputConfig"]);
261
170
  const parts = [sectionHeader("Gmail"), ""];
262
171
  const id = instances[0].id;
263
- const skillToolType = buildSkillToolTypeForIntegration(tools, "gmail");
264
172
  imports.add("GmailEventType");
265
173
  parts.push("export const Gmail = {");
266
174
  parts.push(` /** Trigger when a new email is received */`);
@@ -272,26 +180,25 @@ function generateGmailSection(instances, tools) {
272
180
  parts.push(` return new GmailConfig("${id}", opts?.eventTypes)`);
273
181
  parts.push(" },");
274
182
  parts.push(` /** Use in \`skills[]\` */`);
275
- parts.push(` skill(): TypedSkill<${skillToolType}> {`);
276
- parts.push(` return new GmailOutputConfig("${id}") as TypedSkill<${skillToolType}>`);
183
+ parts.push(` skill(): GmailOutputConfig {`);
184
+ parts.push(` return new GmailOutputConfig("${id}")`);
277
185
  parts.push(" },");
278
186
  parts.push(` /** Use in \`skills[]\` — creates draft emails */`);
279
- parts.push(` draftSkill(): TypedSkill<${skillToolType}> {`);
280
- parts.push(` return new GmailDraftOutputConfig("${id}") as TypedSkill<${skillToolType}>`);
187
+ parts.push(` draftSkill(): GmailDraftOutputConfig {`);
188
+ parts.push(` return new GmailDraftOutputConfig("${id}")`);
281
189
  parts.push(" },");
282
190
  parts.push("}");
283
191
  parts.push("");
284
192
  return { code: parts.join("\n"), imports };
285
193
  }
286
194
  // ── Slack ──────────────────────────────────────────────────────────────
287
- function generateSlackSection(instances, tools) {
195
+ function generateSlackSection(instances) {
288
196
  if (instances.length === 0)
289
197
  return EMPTY_SECTION;
290
198
  const inst = instances[0];
291
- const imports = new Set(["SlackConfig", "SlackOutputConfig", "TypedSkill"]);
199
+ const imports = new Set(["SlackConfig", "SlackOutputConfig"]);
292
200
  const parts = [sectionHeader("Slack"), ""];
293
201
  const id = inst.id;
294
- const skillToolType = buildSkillToolTypeForIntegration(tools, "slack");
295
202
  parts.push(generateResourceClass("SlackChannel", [
296
203
  { classField: "channelId", type: "string", sourceField: "id" },
297
204
  { classField: "name", type: "string", sourceField: "name" },
@@ -313,8 +220,8 @@ function generateSlackSection(instances, tools) {
313
220
  parts.push(` return new SlackConfig("${id}", opts?.channel?.channelId, opts?.channel?.name, opts?.listenToUserDms, opts?.userIds, opts?.eventTypes)`);
314
221
  parts.push(" },");
315
222
  parts.push(` /** Use in \`skills[]\` */`);
316
- parts.push(` skill(opts?: { channel?: SlackChannel; userIds?: string[]; userNames?: string[]; listenToUserDms?: boolean }): TypedSkill<${skillToolType}> {`);
317
- parts.push(` return new SlackOutputConfig("${id}", opts?.channel?.channelId, opts?.channel?.name, opts?.userIds, opts?.userNames, opts?.listenToUserDms) as TypedSkill<${skillToolType}>`);
223
+ parts.push(` skill(opts?: { channel?: SlackChannel; userIds?: string[]; userNames?: string[]; listenToUserDms?: boolean }): SlackOutputConfig {`);
224
+ parts.push(` return new SlackOutputConfig("${id}", opts?.channel?.channelId, opts?.channel?.name, opts?.userIds, opts?.userNames, opts?.listenToUserDms)`);
318
225
  parts.push(" },");
319
226
  parts.push("}");
320
227
  parts.push("");
@@ -342,14 +249,13 @@ function generateFigmaSection(instances) {
342
249
  return { code: parts.join("\n"), imports };
343
250
  }
344
251
  // ── Linear ────────────────────────────────────────────────────────────
345
- function generateLinearSection(instances, tools) {
252
+ function generateLinearSection(instances) {
346
253
  if (instances.length === 0)
347
254
  return EMPTY_SECTION;
348
255
  const inst = instances[0];
349
- const imports = new Set(["LinearInputConfig", "LinearOutputConfig", "TypedSkill"]);
256
+ const imports = new Set(["LinearInputConfig", "LinearOutputConfig"]);
350
257
  const parts = [sectionHeader("Linear"), ""];
351
258
  const id = inst.id;
352
- const skillToolType = buildSkillToolTypeForIntegration(tools, "linear");
353
259
  parts.push(generateResourceClass("LinearTeam", [
354
260
  { classField: "teamId", type: "string", sourceField: "id" },
355
261
  { classField: "name", type: "string", sourceField: "name" },
@@ -375,22 +281,21 @@ function generateLinearSection(instances, tools) {
375
281
  parts.push(` return new LinearInputConfig("${id}", opts?.projectId, opts?.projectName, opts?.eventTypes)`);
376
282
  parts.push(" },");
377
283
  parts.push(` /** Use in \`skills[]\` */`);
378
- parts.push(` skill(opts?: { team?: LinearTeam; projectId?: string; projectName?: string }): TypedSkill<${skillToolType}> {`);
379
- parts.push(` return new LinearOutputConfig("${id}", opts?.team?.teamId, opts?.team?.name, opts?.projectId, opts?.projectName) as TypedSkill<${skillToolType}>`);
284
+ parts.push(` skill(opts?: { team?: LinearTeam; projectId?: string; projectName?: string }): LinearOutputConfig {`);
285
+ parts.push(` return new LinearOutputConfig("${id}", opts?.team?.teamId, opts?.team?.name, opts?.projectId, opts?.projectName)`);
380
286
  parts.push(" },");
381
287
  parts.push("}");
382
288
  parts.push("");
383
289
  return { code: parts.join("\n"), imports };
384
290
  }
385
291
  // ── Jira & Confluence (Atlassian) ─────────────────────────────────────
386
- function generateAtlassianSection(instances, tools) {
292
+ function generateAtlassianSection(instances) {
387
293
  if (instances.length === 0)
388
294
  return EMPTY_SECTION;
389
295
  const inst = instances[0];
390
- const imports = new Set(["JiraConfig", "ConfluenceConfig", "TypedSkill"]);
296
+ const imports = new Set(["JiraConfig", "ConfluenceConfig"]);
391
297
  const parts = [sectionHeader("Jira & Confluence"), ""];
392
298
  const id = inst.id;
393
- const atlassianSkillToolType = buildSkillToolTypeForIntegration(tools, "atlassian");
394
299
  parts.push(generateResourceClass("JiraProject", [
395
300
  { classField: "projectKey", type: "string", sourceField: "key" },
396
301
  { classField: "projectId", type: "string", sourceField: "id" },
@@ -419,29 +324,28 @@ function generateAtlassianSection(instances, tools) {
419
324
  parts.push(` return new JiraConfig("${id}", opts?.project?.projectKey, opts?.project?.projectId, opts?.eventTypes)`);
420
325
  parts.push(" },");
421
326
  parts.push(` /** Use in \`skills[]\` */`);
422
- parts.push(` skill(opts?: { project?: JiraProject }): TypedSkill<${atlassianSkillToolType}> {`);
423
- parts.push(` return new JiraConfig("${id}", opts?.project?.projectKey, opts?.project?.projectId) as TypedSkill<${atlassianSkillToolType}>`);
327
+ parts.push(` skill(opts?: { project?: JiraProject }): JiraConfig {`);
328
+ parts.push(` return new JiraConfig("${id}", opts?.project?.projectKey, opts?.project?.projectId)`);
424
329
  parts.push(" },");
425
330
  parts.push("}");
426
331
  parts.push("");
427
332
  parts.push("export const Confluence = {");
428
333
  parts.push(` /** Use in \`skills[]\` */`);
429
- parts.push(` skill(opts: { page: ConfluencePage }): TypedSkill<${atlassianSkillToolType}> {`);
430
- parts.push(` return new ConfluenceConfig("${id}", opts.page.spaceName, opts.page.spaceId, opts.page.pageId, opts.page.title) as TypedSkill<${atlassianSkillToolType}>`);
334
+ parts.push(` skill(opts: { page: ConfluencePage }): ConfluenceConfig {`);
335
+ parts.push(` return new ConfluenceConfig("${id}", opts.page.spaceName, opts.page.spaceId, opts.page.pageId, opts.page.title)`);
431
336
  parts.push(" },");
432
337
  parts.push("}");
433
338
  parts.push("");
434
339
  return { code: parts.join("\n"), imports };
435
340
  }
436
341
  // ── Notion ────────────────────────────────────────────────────────────
437
- function generateNotionSection(instances, tools) {
342
+ function generateNotionSection(instances) {
438
343
  if (instances.length === 0)
439
344
  return EMPTY_SECTION;
440
345
  const inst = instances[0];
441
- const imports = new Set(["NotionConfig", "TypedSkill"]);
346
+ const imports = new Set(["NotionConfig"]);
442
347
  const parts = [sectionHeader("Notion"), ""];
443
348
  const id = inst.id;
444
- const skillToolType = buildSkillToolTypeForIntegration(tools, "notion");
445
349
  parts.push(generateResourceClass("NotionDatabase", [
446
350
  { classField: "databaseId", type: "string", sourceField: "id" },
447
351
  { classField: "title", type: "string", sourceField: "title" },
@@ -454,24 +358,23 @@ function generateNotionSection(instances, tools) {
454
358
  parts.push("");
455
359
  parts.push("export const Notion = {");
456
360
  parts.push(` /** Use in \`skills[]\` */`);
457
- parts.push(` skill(opts?: { databases?: NotionDatabase[]; pages?: NotionPage[] }): TypedSkill<${skillToolType}> {`);
361
+ parts.push(` skill(opts?: { databases?: NotionDatabase[]; pages?: NotionPage[] }): NotionConfig {`);
458
362
  parts.push(` return new NotionConfig("${id}",`);
459
363
  parts.push(` opts?.databases?.map(d => d.databaseId), opts?.databases?.map(d => d.title),`);
460
- parts.push(` opts?.pages?.map(p => p.pageId), opts?.pages?.map(p => p.title)) as TypedSkill<${skillToolType}>`);
364
+ parts.push(` opts?.pages?.map(p => p.pageId), opts?.pages?.map(p => p.title))`);
461
365
  parts.push(" },");
462
366
  parts.push("}");
463
367
  parts.push("");
464
368
  return { code: parts.join("\n"), imports };
465
369
  }
466
370
  // ── PostHog ───────────────────────────────────────────────────────────
467
- function generatePosthogSection(instances, tools) {
371
+ function generatePosthogSection(instances) {
468
372
  if (instances.length === 0)
469
373
  return EMPTY_SECTION;
470
374
  const inst = instances[0];
471
- const imports = new Set(["PosthogConfig", "TypedSkill"]);
375
+ const imports = new Set(["PosthogConfig"]);
472
376
  const parts = [sectionHeader("PostHog"), ""];
473
377
  const id = inst.id;
474
- const skillToolType = buildSkillToolTypeForIntegration(tools, "posthog");
475
378
  parts.push(generateResourceClass("PosthogProject", [
476
379
  { classField: "projectId", type: "string", sourceField: "id" },
477
380
  { classField: "name", type: "string", sourceField: "name" },
@@ -479,44 +382,42 @@ function generatePosthogSection(instances, tools) {
479
382
  parts.push("");
480
383
  parts.push("export const Posthog = {");
481
384
  parts.push(` /** Use in \`skills[]\` */`);
482
- parts.push(` skill(opts: { project: PosthogProject }): TypedSkill<${skillToolType}> {`);
483
- parts.push(` return new PosthogConfig("${id}", opts.project.projectId, opts.project.name) as TypedSkill<${skillToolType}>`);
385
+ parts.push(` skill(opts: { project: PosthogProject }): PosthogConfig {`);
386
+ parts.push(` return new PosthogConfig("${id}", opts.project.projectId, opts.project.name)`);
484
387
  parts.push(" },");
485
388
  parts.push("}");
486
389
  parts.push("");
487
390
  return { code: parts.join("\n"), imports };
488
391
  }
489
392
  // ── Datadog ───────────────────────────────────────────────────────────
490
- function generateDatadogSection(instances, tools) {
393
+ function generateDatadogSection(instances) {
491
394
  if (instances.length === 0)
492
395
  return EMPTY_SECTION;
493
396
  const inst = instances[0];
494
- const imports = new Set(["DatadogConfig", "TypedSkill"]);
397
+ const imports = new Set(["DatadogConfig"]);
495
398
  const parts = [sectionHeader("Datadog"), ""];
496
399
  const id = inst.id;
497
- const skillToolType = buildSkillToolTypeForIntegration(tools, "datadog");
498
400
  parts.push(generateResourceClass("DatadogIndex", [
499
401
  { classField: "name", type: "string", sourceField: "name" },
500
402
  ], "name", inst.indexes));
501
403
  parts.push("");
502
404
  parts.push("export const Datadog = {");
503
405
  parts.push(` /** Use in \`skills[]\` */`);
504
- parts.push(` skill(opts?: { indexes?: DatadogIndex[] }): TypedSkill<${skillToolType}> {`);
505
- parts.push(` return new DatadogConfig("${id}", opts?.indexes?.map(i => i.name)) as TypedSkill<${skillToolType}>`);
406
+ parts.push(` skill(opts?: { indexes?: DatadogIndex[] }): DatadogConfig {`);
407
+ parts.push(` return new DatadogConfig("${id}", opts?.indexes?.map(i => i.name))`);
506
408
  parts.push(" },");
507
409
  parts.push("}");
508
410
  parts.push("");
509
411
  return { code: parts.join("\n"), imports };
510
412
  }
511
413
  // ── LaunchDarkly ──────────────────────────────────────────────────────
512
- function generateLaunchDarklySection(instances, tools) {
414
+ function generateLaunchDarklySection(instances) {
513
415
  if (instances.length === 0)
514
416
  return EMPTY_SECTION;
515
417
  const inst = instances[0];
516
- const imports = new Set(["LaunchDarklyConfig", "TypedSkill"]);
418
+ const imports = new Set(["LaunchDarklyConfig"]);
517
419
  const parts = [sectionHeader("LaunchDarkly"), ""];
518
420
  const id = inst.id;
519
- const skillToolType = buildSkillToolTypeForIntegration(tools, "launchdarkly");
520
421
  parts.push(generateResourceClass("LaunchDarklyProject", [
521
422
  { classField: "projectKey", type: "string", sourceField: "key" },
522
423
  { classField: "name", type: "string", sourceField: "name" },
@@ -524,160 +425,70 @@ function generateLaunchDarklySection(instances, tools) {
524
425
  parts.push("");
525
426
  parts.push("export const LaunchDarkly = {");
526
427
  parts.push(` /** Use in \`skills[]\` */`);
527
- parts.push(` skill(opts: { project: LaunchDarklyProject; environmentKeys: string[] }): TypedSkill<${skillToolType}> {`);
528
- parts.push(` return new LaunchDarklyConfig("${id}", opts.project.projectKey, opts.environmentKeys) as TypedSkill<${skillToolType}>`);
428
+ parts.push(` skill(opts: { project: LaunchDarklyProject; environmentKeys: string[] }): LaunchDarklyConfig {`);
429
+ parts.push(` return new LaunchDarklyConfig("${id}", opts.project.projectKey, opts.environmentKeys)`);
529
430
  parts.push(" },");
530
431
  parts.push("}");
531
432
  parts.push("");
532
433
  return { code: parts.join("\n"), imports };
533
434
  }
534
435
  // ── WorkOS ────────────────────────────────────────────────────────────
535
- function generateWorkOSSection(instances, tools) {
436
+ function generateWorkOSSection(instances) {
536
437
  if (instances.length === 0)
537
438
  return EMPTY_SECTION;
538
- const imports = new Set(["WorkOSInputConfig", "WorkOSOutputConfig", "WorkOSEventType", "TypedSkill"]);
439
+ const imports = new Set(["WorkOSInputConfig", "WorkOSOutputConfig", "WorkOSEventType"]);
539
440
  const parts = [sectionHeader("WorkOS"), ""];
540
441
  const id = instances[0].id;
541
- const skillToolType = buildSkillToolTypeForIntegration(tools, "workos");
542
- imports.add("TypedTrigger");
543
- imports.add("WorkOSInputEvent");
544
- imports.add("WorkOSUserInputEvent");
545
- imports.add("WorkOSMembershipInputEvent");
546
- imports.add("WorkOSInvitationInputEvent");
547
- imports.add("WorkOSOrganizationInputEvent");
548
442
  parts.push("export const WorkOS = {");
549
443
  parts.push(` /** Trigger on user creation */`);
550
- parts.push(` onUserCreated(): TypedTrigger<WorkOSUserInputEvent> {`);
551
- parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.USER_CREATED]) as TypedTrigger<WorkOSUserInputEvent>`);
444
+ parts.push(` onUserCreated(): WorkOSInputConfig {`);
445
+ parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.USER_CREATED])`);
552
446
  parts.push(" },");
553
447
  parts.push(` /** Trigger on user update */`);
554
- parts.push(` onUserUpdated(): TypedTrigger<WorkOSUserInputEvent> {`);
555
- parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.USER_UPDATED]) as TypedTrigger<WorkOSUserInputEvent>`);
448
+ parts.push(` onUserUpdated(): WorkOSInputConfig {`);
449
+ parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.USER_UPDATED])`);
556
450
  parts.push(" },");
557
451
  parts.push(` /** Trigger on user deletion */`);
558
- parts.push(` onUserDeleted(): TypedTrigger<WorkOSUserInputEvent> {`);
559
- parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.USER_DELETED]) as TypedTrigger<WorkOSUserInputEvent>`);
452
+ parts.push(` onUserDeleted(): WorkOSInputConfig {`);
453
+ parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.USER_DELETED])`);
560
454
  parts.push(" },");
561
455
  parts.push(` /** Trigger on organization membership change */`);
562
- parts.push(` onMembershipChanged(): TypedTrigger<WorkOSMembershipInputEvent> {`);
563
- parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.ORGANIZATION_MEMBERSHIP_CREATED, WorkOSEventType.ORGANIZATION_MEMBERSHIP_UPDATED, WorkOSEventType.ORGANIZATION_MEMBERSHIP_DELETED]) as TypedTrigger<WorkOSMembershipInputEvent>`);
564
- parts.push(" },");
565
- parts.push(` /** Trigger when an invitation is sent */`);
566
- parts.push(` onInvitationSent(): TypedTrigger<WorkOSInvitationInputEvent> {`);
567
- parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.INVITATION_CREATED, WorkOSEventType.INVITATION_RESENT]) as TypedTrigger<WorkOSInvitationInputEvent>`);
568
- parts.push(" },");
569
- parts.push(` /** Trigger when an invitation is first created */`);
570
- parts.push(` onInvitationCreated(): TypedTrigger<WorkOSInvitationInputEvent> {`);
571
- parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.INVITATION_CREATED]) as TypedTrigger<WorkOSInvitationInputEvent>`);
572
- parts.push(" },");
573
- parts.push(` /** Trigger when an invitation is resent */`);
574
- parts.push(` onInvitationResent(): TypedTrigger<WorkOSInvitationInputEvent> {`);
575
- parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.INVITATION_RESENT]) as TypedTrigger<WorkOSInvitationInputEvent>`);
456
+ parts.push(` onMembershipChanged(): WorkOSInputConfig {`);
457
+ parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.ORGANIZATION_MEMBERSHIP_CREATED, WorkOSEventType.ORGANIZATION_MEMBERSHIP_UPDATED, WorkOSEventType.ORGANIZATION_MEMBERSHIP_DELETED])`);
576
458
  parts.push(" },");
577
459
  parts.push(` /** Trigger on invitation accepted */`);
578
- parts.push(` onInvitationAccepted(): TypedTrigger<WorkOSInvitationInputEvent> {`);
579
- parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.INVITATION_ACCEPTED]) as TypedTrigger<WorkOSInvitationInputEvent>`);
580
- parts.push(" },");
581
- parts.push(` /** Trigger when an invitation is revoked */`);
582
- parts.push(` onInvitationRevoked(): TypedTrigger<WorkOSInvitationInputEvent> {`);
583
- parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.INVITATION_REVOKED]) as TypedTrigger<WorkOSInvitationInputEvent>`);
584
- parts.push(" },");
585
- parts.push(` /** Trigger on organization creation */`);
586
- parts.push(` onOrganizationCreated(): TypedTrigger<WorkOSOrganizationInputEvent> {`);
587
- parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.ORGANIZATION_CREATED]) as TypedTrigger<WorkOSOrganizationInputEvent>`);
460
+ parts.push(` onInvitationAccepted(): WorkOSInputConfig {`);
461
+ parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.INVITATION_ACCEPTED])`);
588
462
  parts.push(" },");
589
463
  parts.push(` /** Trigger on specific WorkOS event types */`);
590
- parts.push(` trigger(opts?: { eventTypes?: WorkOSEventType[] }): TypedTrigger<WorkOSInputEvent | WorkOSUserInputEvent | WorkOSMembershipInputEvent | WorkOSInvitationInputEvent | WorkOSOrganizationInputEvent> {`);
591
- parts.push(` return new WorkOSInputConfig("${id}", opts?.eventTypes) as TypedTrigger<WorkOSInputEvent | WorkOSUserInputEvent | WorkOSMembershipInputEvent | WorkOSInvitationInputEvent | WorkOSOrganizationInputEvent>`);
464
+ parts.push(` trigger(opts?: { eventTypes?: WorkOSEventType[] }): WorkOSInputConfig {`);
465
+ parts.push(` return new WorkOSInputConfig("${id}", opts?.eventTypes)`);
592
466
  parts.push(" },");
593
467
  parts.push(` /** Use in \`skills[]\` */`);
594
- parts.push(` skill(): TypedSkill<${skillToolType}> {`);
595
- parts.push(` return new WorkOSOutputConfig("${id}") as TypedSkill<${skillToolType}>`);
468
+ parts.push(` skill(): WorkOSOutputConfig {`);
469
+ parts.push(` return new WorkOSOutputConfig("${id}")`);
596
470
  parts.push(" },");
597
471
  parts.push("}");
598
472
  parts.push("");
599
473
  return { code: parts.join("\n"), imports };
600
474
  }
601
475
  // ── Attio ─────────────────────────────────────────────────────────────
602
- function generateAttioSection(instances, tools) {
476
+ function generateAttioSection(instances) {
603
477
  if (instances.length === 0)
604
478
  return EMPTY_SECTION;
605
479
  const inst = instances[0];
606
- const imports = new Set(["AttioOutputConfig", "TypedSkill"]);
480
+ const imports = new Set(["AttioOutputConfig"]);
607
481
  const parts = [sectionHeader("Attio"), ""];
608
482
  const id = inst.id;
609
- const skillToolType = buildSkillToolTypeForIntegration(tools, "attio");
610
- parts.push("export type AttioAttributeDefinition<TSlug extends string = string, TType extends string = string> = {");
611
- parts.push(" apiSlug: TSlug");
612
- parts.push(" title?: string");
613
- parts.push(" type?: TType");
614
- parts.push(" isRequired?: boolean");
615
- parts.push(" isUnique?: boolean");
616
- parts.push("}");
617
- parts.push("");
618
- parts.push("export class AttioObject<");
619
- parts.push(" TSlug extends string = string,");
620
- parts.push(" TRecordValues extends Record<string, unknown> = Record<string, unknown>,");
621
- parts.push(" TInputValues extends Record<string, unknown> = TRecordValues");
622
- parts.push("> {");
623
- parts.push(" constructor(");
624
- parts.push(" public readonly apiSlug: TSlug,");
625
- parts.push(" public readonly name: string,");
626
- parts.push(" public readonly attributes: readonly AttioAttributeDefinition[] = []");
627
- parts.push(" ) {}");
628
- parts.push("");
629
- parts.push(" declare readonly __recordValues: TRecordValues");
630
- parts.push(" declare readonly __inputValues: TInputValues");
631
- if (inst.objects.length > 0) {
632
- parts.push("");
633
- const usedNames = new Set();
634
- for (const object of inst.objects) {
635
- let staticName = toGeneratedIdentifier(object.singular_noun || object.api_slug || "Object", "AttioObject");
636
- while (usedNames.has(staticName))
637
- staticName += "_";
638
- usedNames.add(staticName);
639
- const attributes = (object.attributes || []).filter((attr) => !!attr.api_slug);
640
- const attributeSource = attributes.length === 0
641
- ? "[]"
642
- : `[\n${attributes.map(attr => {
643
- const fields = [
644
- `apiSlug: "${escapeString(attr.api_slug)}"`,
645
- attr.title ? `title: "${escapeString(attr.title)}"` : undefined,
646
- attr.type ? `type: "${escapeString(attr.type)}"` : undefined,
647
- attr.is_required !== undefined ? `isRequired: ${attr.is_required ? "true" : "false"}` : undefined,
648
- attr.is_unique !== undefined ? `isUnique: ${attr.is_unique ? "true" : "false"}` : undefined,
649
- ].filter(Boolean).join(", ");
650
- return ` { ${fields} }`;
651
- }).join(",\n")}\n ]`;
652
- const recordValuesType = renderAttioObjectValueShape(attributes, "record");
653
- const inputValuesType = renderAttioObjectValueShape(attributes, "input");
654
- parts.push(` static ${staticName} = new AttioObject<"${escapeString(object.api_slug)}", ${recordValuesType}, ${inputValuesType}>("${escapeString(object.api_slug)}", "${escapeString(object.singular_noun)}", ${attributeSource})`);
655
- }
656
- }
657
- parts.push("}");
483
+ parts.push(generateResourceClass("AttioObject", [
484
+ { classField: "apiSlug", type: "string", sourceField: "api_slug" },
485
+ { classField: "name", type: "string", sourceField: "singular_noun" },
486
+ ], "singular_noun", inst.objects));
658
487
  parts.push("");
659
488
  parts.push("export const Attio = {");
660
489
  parts.push(` /** Use in \`skills[]\` */`);
661
- parts.push(` skill(opts: { object: AttioObject<any> }): TypedSkill<${skillToolType}> {`);
662
- parts.push(` return new AttioOutputConfig("${id}", opts.object.apiSlug) as TypedSkill<${skillToolType}>`);
663
- parts.push(" },");
664
- parts.push("}");
665
- parts.push("");
666
- return { code: parts.join("\n"), imports };
667
- }
668
- // ── Snowflake ─────────────────────────────────────────────────────────
669
- function generateSnowflakeSection(instances, tools) {
670
- if (instances.length === 0)
671
- return EMPTY_SECTION;
672
- const inst = instances[0];
673
- const imports = new Set(["SnowflakeOutputConfig", "TypedSkill"]);
674
- const parts = [sectionHeader("Snowflake"), ""];
675
- const id = inst.id;
676
- const skillToolType = buildSkillToolTypeForIntegration(tools, "snowflake");
677
- parts.push("export const Snowflake = {");
678
- parts.push(` /** Use in \`skills[]\` */`);
679
- parts.push(` skill(): TypedSkill<${skillToolType}> {`);
680
- parts.push(` return new SnowflakeOutputConfig("${id}") as TypedSkill<${skillToolType}>`);
490
+ parts.push(` skill(opts?: { object?: AttioObject }): AttioOutputConfig {`);
491
+ parts.push(` return new AttioOutputConfig("${id}", opts?.object?.apiSlug)`);
681
492
  parts.push(" },");
682
493
  parts.push("}");
683
494
  parts.push("");
@@ -773,7 +584,6 @@ function generateToolsSection(tools, input) {
773
584
  instanceMap.set("launchdarkly", input.launchdarkly.map(l => ({ id: l.id, displayName: l.displayName })));
774
585
  instanceMap.set("workos", input.workos.map(w => ({ id: w.id, displayName: w.displayName })));
775
586
  instanceMap.set("attio", input.attio.map(a => ({ id: a.id, displayName: a.displayName })));
776
- instanceMap.set("snowflake", input.snowflake.map(s => ({ id: s.id, displayName: s.name })));
777
587
  // Group tools by integration
778
588
  const byIntegration = new Map();
779
589
  for (const tool of tools) {
@@ -815,178 +625,8 @@ function generateToolsSection(tools, input) {
815
625
  return "params";
816
626
  }
817
627
  };
818
- const isAttioTool = (tool) => tool.integration.toLowerCase() === "attio";
819
- const attioObjects = input.attio[0]?.objects ?? [];
820
- const attioGeneratedObjects = (() => {
821
- const usedNames = new Set();
822
- return attioObjects.map(object => {
823
- let staticName = toGeneratedIdentifier(object.singular_noun || object.api_slug || "Object", "AttioObject");
824
- while (usedNames.has(staticName))
825
- staticName += "_";
826
- usedNames.add(staticName);
827
- return {
828
- ...object,
829
- staticName,
830
- attributes: (object.attributes || []).filter((attr) => !!attr.api_slug),
831
- };
832
- });
833
- })();
834
- if (tools.some(isAttioTool)) {
835
- parts.push("type __AttioPrimitive = string | number | boolean | null");
836
- parts.push("type __AttioStructuredValue = Record<string, unknown>");
837
- parts.push("type __AttioValue = __AttioPrimitive | __AttioStructuredValue | (__AttioPrimitive | __AttioStructuredValue)[]");
838
- parts.push("type __AttioFilterShorthand<T> = T extends (infer U)[] ? U | T : T");
839
- parts.push('type __AttioFilterValue<T> = __AttioFilterShorthand<T> | { $eq?: __AttioFilterShorthand<T>; $contains?: string; $starts_with?: string; $ends_with?: string } | Record<string, unknown>');
840
- parts.push('type __AttioFilterExpression<TValues extends Record<string, unknown>> = Partial<{ [K in keyof TValues]: __AttioFilterValue<TValues[K]> }> & { $and?: Array<__AttioFilterExpression<TValues>>; $or?: Array<__AttioFilterExpression<TValues>> }');
841
- parts.push('type __AttioRecordBase = NonNullable<NonNullable<ToolOutputByName["attio_upsert_record"]["records"]>[number]>');
842
- parts.push('type __AttioRecordWithValues<TValues extends Record<string, unknown>> = Omit<__AttioRecordBase, "values"> & TValues & { values: TValues; attributes: TValues }');
843
- parts.push("");
844
- if (attioGeneratedObjects.length > 0) {
845
- parts.push("export type GeneratedAttioObject =");
846
- for (const object of attioGeneratedObjects) {
847
- parts.push(` | typeof AttioObject.${object.staticName}`);
848
- }
849
- parts.push("");
850
- parts.push("export type AttioInputValuesByObject = {");
851
- for (const object of attioGeneratedObjects) {
852
- const inputShape = object.attributes.length === 0 ? "Record<string, __AttioValue>" : renderAttioObjectValueShape(object.attributes, "input");
853
- parts.push(` "${escapeString(object.api_slug)}": ${inputShape}`);
854
- }
855
- parts.push("}");
856
- parts.push("");
857
- parts.push("export type AttioRecordValuesByObject = {");
858
- for (const object of attioGeneratedObjects) {
859
- const recordShape = object.attributes.length === 0 ? "Record<string, __AttioValue>" : renderAttioObjectValueShape(object.attributes, "record");
860
- parts.push(` "${escapeString(object.api_slug)}": ${recordShape}`);
861
- }
862
- parts.push("}");
863
- parts.push("");
864
- parts.push("export type AttioFilterByObject = {");
865
- for (const object of attioGeneratedObjects) {
866
- parts.push(` "${escapeString(object.api_slug)}": __AttioFilterExpression<AttioRecordValuesByObject["${escapeString(object.api_slug)}"]>`);
867
- }
868
- parts.push("}");
869
- parts.push("");
870
- parts.push("export type AttioRecordByObject = {");
871
- for (const object of attioGeneratedObjects) {
872
- parts.push(` "${escapeString(object.api_slug)}": __AttioRecordWithValues<AttioRecordValuesByObject["${escapeString(object.api_slug)}"]>`);
873
- }
874
- parts.push("}");
875
- }
876
- else {
877
- parts.push("export type GeneratedAttioObject = AttioObject<string, Record<string, __AttioValue>, Record<string, __AttioValue>>");
878
- parts.push('export type AttioInputValuesByObject = Record<string, Record<string, __AttioValue>>');
879
- parts.push('export type AttioRecordValuesByObject = Record<string, Record<string, __AttioValue>>');
880
- parts.push('export type AttioFilterByObject = Record<string, __AttioFilterExpression<Record<string, __AttioValue>>>');
881
- parts.push('export type AttioRecordByObject = Record<string, __AttioRecordWithValues<Record<string, __AttioValue>>>');
882
- }
883
- parts.push("");
884
- parts.push('export type AttioValuesFor<TObject extends GeneratedAttioObject = GeneratedAttioObject> = TObject extends { __inputValues: infer TInputValues } ? TInputValues : AttioInputValuesByObject[TObject["apiSlug"]]');
885
- parts.push('export type AttioRecordValuesFor<TObject extends GeneratedAttioObject = GeneratedAttioObject> = TObject extends { __recordValues: infer TRecordValues } ? TRecordValues : AttioRecordValuesByObject[TObject["apiSlug"]]');
886
- parts.push('export type AttioAttributeSlug<TObject extends GeneratedAttioObject = GeneratedAttioObject> = Extract<keyof AttioValuesFor<TObject>, string>');
887
- parts.push('export type AttioFilterFor<TObject extends GeneratedAttioObject = GeneratedAttioObject> = __AttioFilterExpression<AttioRecordValuesFor<TObject>>');
888
- parts.push('export type AttioRecordFor<TObject extends GeneratedAttioObject = GeneratedAttioObject> = __AttioRecordWithValues<AttioRecordValuesFor<TObject>>');
889
- parts.push('export type AttioQueryRecordsParams<TObject extends GeneratedAttioObject = GeneratedAttioObject> = { object: TObject; filter?: AttioFilterFor<TObject> | null; limit?: number | null }');
890
- parts.push('export type AttioUpsertRecordParams<TObject extends GeneratedAttioObject = GeneratedAttioObject> = { object: TObject; matchingAttribute: AttioAttributeSlug<TObject>; records: AttioValuesFor<TObject>[] }');
891
- parts.push("export type AttioListObjectsParams = Record<string, never>");
892
- parts.push('export type AttioQueryRecordsResult<TObject extends GeneratedAttioObject = GeneratedAttioObject> = Omit<ToolOutputByName["attio_query_records"], "records"> & { records: Array<AttioRecordFor<TObject>> }');
893
- parts.push('export type AttioUpsertRecordResult<TObject extends GeneratedAttioObject = GeneratedAttioObject> = Omit<ToolOutputByName["attio_upsert_record"], "records"> & { records?: Array<AttioRecordFor<TObject>> }');
894
- parts.push("");
895
- parts.push("const __attioMetadataKeys = new Set([");
896
- parts.push(' "active_from",');
897
- parts.push(' "active_until",');
898
- parts.push(' "attribute_type",');
899
- parts.push(' "created_by_actor",');
900
- parts.push("])");
901
- parts.push("");
902
- parts.push("const __attioMultiValueAttributeSlugsByObject: Record<string, readonly string[]> = {");
903
- for (const object of attioGeneratedObjects) {
904
- const multiValueSlugs = object.attributes.filter(isProbablyAttioMultiValue).map(attr => `"${escapeString(attr.api_slug)}"`).join(", ");
905
- parts.push(` "${escapeString(object.api_slug)}": [${multiValueSlugs}],`);
906
- }
907
- parts.push("}");
908
- parts.push("");
909
- parts.push("function __normalizeAttioObjectSlug(object: unknown): string {");
910
- parts.push(' if (object && typeof object === "object" && "apiSlug" in (object as Record<string, unknown>)) {');
911
- parts.push(' const apiSlug = (object as { apiSlug?: unknown }).apiSlug');
912
- parts.push(' if (typeof apiSlug === "string" && apiSlug.length > 0) return apiSlug');
913
- parts.push(" }");
914
- parts.push(' return typeof object === "string" ? object : ""');
915
- parts.push("}");
916
- parts.push("");
917
- parts.push("function __serializeAttioFilter(filter: unknown): string | null {");
918
- parts.push(" if (filter === undefined || filter === null) return null");
919
- parts.push(" return JSON.stringify(filter)");
920
- parts.push("}");
921
- parts.push("");
922
- parts.push("function __serializeAttioRecords(records: unknown): string {");
923
- parts.push(" if (!Array.isArray(records)) return JSON.stringify([])");
924
- parts.push(' return JSON.stringify(records.filter((record): record is Record<string, unknown> => typeof record === "object" && record !== null && !Array.isArray(record)))');
925
- parts.push("}");
926
- parts.push("");
927
- parts.push("function __isAttioMultiValueAttribute(objectSlug: string, attributeSlug: string): boolean {");
928
- parts.push(" return (__attioMultiValueAttributeSlugsByObject[objectSlug] || []).includes(attributeSlug)");
929
- parts.push("}");
930
- parts.push("");
931
- parts.push("function __flattenAttioLeafValue(value: unknown): unknown {");
932
- parts.push(" if (value === null || value === undefined) return value");
933
- parts.push(" if (Array.isArray(value)) return value.map(entry => __flattenAttioLeafValue(entry))");
934
- parts.push(' if (typeof value !== "object") return value');
935
- parts.push(" const rawObject = value as Record<string, unknown>");
936
- parts.push(' if (typeof rawObject.full_name === "string") return rawObject.full_name');
937
- parts.push(' if (typeof rawObject.email_address === "string") return rawObject.email_address');
938
- parts.push(' if (typeof rawObject.domain === "string") return rawObject.domain');
939
- parts.push(' if (typeof rawObject.phone_number === "string") return rawObject.phone_number');
940
- parts.push(' if ("value" in rawObject) return __flattenAttioLeafValue(rawObject.value)');
941
- parts.push(" const dataEntries = Object.entries(rawObject).filter(([key]) => !__attioMetadataKeys.has(key))");
942
- parts.push(" if (dataEntries.length === 0) return rawObject");
943
- parts.push(" if (dataEntries.length === 1) return __flattenAttioLeafValue(dataEntries[0][1])");
944
- parts.push(" return Object.fromEntries(dataEntries.map(([key, entryValue]) => [key, __flattenAttioLeafValue(entryValue)]))");
945
- parts.push("}");
946
- parts.push("");
947
- parts.push("function __flattenAttioAttributeValue(rawValue: unknown, preferArray: boolean): unknown {");
948
- parts.push(" if (!Array.isArray(rawValue)) return __flattenAttioLeafValue(rawValue)");
949
- parts.push(" const flattened = rawValue");
950
- parts.push(" .map(entry => __flattenAttioLeafValue(entry))");
951
- parts.push(" .filter(entry => entry !== undefined)");
952
- parts.push(" return preferArray ? flattened : flattened[0]");
953
- parts.push("}");
954
- parts.push("");
955
- parts.push("function __getAttioRecordValues<TValues extends Record<string, unknown>>(objectSlug: string, record: unknown): TValues {");
956
- parts.push(' const rawValues = record && typeof record === "object" ? (record as { values?: unknown }).values : undefined');
957
- parts.push(' if (!rawValues || typeof rawValues !== "object" || Array.isArray(rawValues)) return {} as TValues');
958
- parts.push(" const flattenedValues: Record<string, unknown> = {}");
959
- parts.push(" for (const [attributeSlug, rawValue] of Object.entries(rawValues)) {");
960
- parts.push(" flattenedValues[attributeSlug] = __flattenAttioAttributeValue(rawValue, __isAttioMultiValueAttribute(objectSlug, attributeSlug))");
961
- parts.push(" }");
962
- parts.push(" return flattenedValues as TValues");
963
- parts.push("}");
964
- parts.push("");
965
- parts.push("function __enhanceAttioRecord<TObject extends GeneratedAttioObject>(object: TObject, record: unknown): __AttioRecordWithValues<AttioRecordValuesFor<TObject>> | undefined {");
966
- parts.push(' if (!record || typeof record !== "object") return undefined');
967
- parts.push(" const values = __getAttioRecordValues<AttioRecordValuesFor<TObject>>(__normalizeAttioObjectSlug(object), record)");
968
- parts.push(' return { ...values, ...(record as __AttioRecordBase), values, attributes: values } as __AttioRecordWithValues<AttioRecordValuesFor<TObject>>');
969
- parts.push("}");
970
- parts.push("");
971
- parts.push('function __enhanceAttioQueryResult<TObject extends GeneratedAttioObject>(object: TObject, result: ToolOutputByName["attio_query_records"]): AttioQueryRecordsResult<TObject> {');
972
- parts.push(" return {");
973
- parts.push(" ...result,");
974
- parts.push(" records: (result.records || []).map(record => __enhanceAttioRecord(object, record)).filter(Boolean) as Array<AttioRecordFor<TObject>>,");
975
- parts.push(" }");
976
- parts.push("}");
977
- parts.push("");
978
- parts.push('function __enhanceAttioUpsertResult<TObject extends GeneratedAttioObject>(object: TObject, result: ToolOutputByName["attio_upsert_record"]): AttioUpsertRecordResult<TObject> {');
979
- parts.push(" return {");
980
- parts.push(" ...result,");
981
- parts.push(" records: (result.records || []).map(record => __enhanceAttioRecord(object, record)).filter(Boolean) as Array<AttioRecordFor<TObject>>,");
982
- parts.push(" }");
983
- parts.push("}");
984
- parts.push("");
985
- }
986
628
  // Generate per-tool param types (with integrationId omitted where applicable)
987
629
  for (const tool of tools) {
988
- if (isAttioTool(tool))
989
- continue;
990
630
  const typeName = toolNameToInterfaceName(tool.name);
991
631
  const schema = hasAutoFillId(tool) ? omitIntegrationId(tool.parameters) : tool.parameters;
992
632
  const tsType = jsonSchemaToTs(schema, 0);
@@ -1060,18 +700,7 @@ function generateToolsSection(tools, input) {
1060
700
  if (tool.description) {
1061
701
  parts.push(` /** ${tool.description} */`);
1062
702
  }
1063
- if (group.integration === "attio" && tool.name === "attio_query_records") {
1064
- parts.push(` ${methodName}<TObject extends GeneratedAttioObject>(params: AttioQueryRecordsParams<TObject>): Promise<AttioQueryRecordsResult<TObject>>`);
1065
- }
1066
- else if (group.integration === "attio" && tool.name === "attio_upsert_record") {
1067
- parts.push(` ${methodName}<TObject extends GeneratedAttioObject>(params: AttioUpsertRecordParams<TObject>): Promise<AttioUpsertRecordResult<TObject>>`);
1068
- }
1069
- else if (group.integration === "attio" && tool.name === "attio_list_objects") {
1070
- parts.push(` ${methodName}(params?: AttioListObjectsParams): Promise<ToolOutputByName["${escapeString(tool.name)}"]>`);
1071
- }
1072
- else {
1073
- parts.push(` ${methodName}(params: ${paramsType}): Promise<ToolOutputByName["${escapeString(tool.name)}"]>`);
1074
- }
703
+ parts.push(` ${methodName}(params: ${paramsType}): Promise<ToolOutputByName["${escapeString(tool.name)}"]>`);
1075
704
  }
1076
705
  parts.push(" }");
1077
706
  }
@@ -1096,19 +725,7 @@ function generateToolsSection(tools, input) {
1096
725
  const methodName = toCamelCase(tool.displayName);
1097
726
  const paramsType = toolNameToInterfaceName(tool.name);
1098
727
  const normalizedParamsExpr = group.integration === "github" ? normalizeGitHubReposParams(tool.name) : "params";
1099
- if (group.integration === "attio" && tool.name === "attio_query_records" && group.integrationId) {
1100
- parts.push(` ${methodName}: <TObject extends GeneratedAttioObject>(params: AttioQueryRecordsParams<TObject>) =>`);
1101
- parts.push(` agent.executeTool<ToolOutputByName["${escapeString(tool.name)}"]>("${escapeString(tool.name)}", { objectSlug: __normalizeAttioObjectSlug(params.object), filter: __serializeAttioFilter(params.filter), limit: params.limit ?? null, integrationId: "${escapeString(group.integrationId)}" }).then(result => __enhanceAttioQueryResult(params.object, result)),`);
1102
- }
1103
- else if (group.integration === "attio" && tool.name === "attio_upsert_record" && group.integrationId) {
1104
- parts.push(` ${methodName}: <TObject extends GeneratedAttioObject>(params: AttioUpsertRecordParams<TObject>) =>`);
1105
- parts.push(` agent.executeTool<ToolOutputByName["${escapeString(tool.name)}"]>("${escapeString(tool.name)}", { objectSlug: __normalizeAttioObjectSlug(params.object), matchingAttribute: params.matchingAttribute, records: __serializeAttioRecords(params.records), integrationId: "${escapeString(group.integrationId)}" }).then(result => __enhanceAttioUpsertResult(params.object, result)),`);
1106
- }
1107
- else if (group.integration === "attio" && tool.name === "attio_list_objects" && group.integrationId) {
1108
- parts.push(` ${methodName}: (params: AttioListObjectsParams = {}) =>`);
1109
- parts.push(` agent.executeTool<ToolOutputByName["${escapeString(tool.name)}"]>("${escapeString(tool.name)}", { ...params, integrationId: "${escapeString(group.integrationId)}" }),`);
1110
- }
1111
- else if (group.integrationId && hasAutoFillId(tool)) {
728
+ if (group.integrationId && hasAutoFillId(tool)) {
1112
729
  parts.push(` ${methodName}: (params: ${paramsType}) =>`);
1113
730
  parts.push(` agent.executeTool<ToolOutputByName["${escapeString(tool.name)}"]>("${escapeString(tool.name)}", { ...(${normalizedParamsExpr}), integrationId: "${escapeString(group.integrationId)}" }),`);
1114
731
  }
@@ -1128,10 +745,9 @@ function generateToolsSection(tools, input) {
1128
745
  return { code: parts.join("\n"), imports };
1129
746
  }
1130
747
  // ── System (always included) ──────────────────────────────────────────
1131
- function generateSystemSection(tools) {
1132
- const imports = new Set(["TimeTriggerConfig", "TerseConfig", "TypedSkill"]);
748
+ function generateSystemSection() {
749
+ const imports = new Set(["TimeTriggerConfig", "TerseConfig"]);
1133
750
  const parts = [];
1134
- const skillToolType = buildSkillToolTypeForIntegration(tools, "terse");
1135
751
  parts.push(sectionHeader("Schedule"));
1136
752
  parts.push("");
1137
753
  parts.push("export const Schedule = {");
@@ -1145,8 +761,8 @@ function generateSystemSection(tools) {
1145
761
  parts.push("");
1146
762
  parts.push("export const Terse = {");
1147
763
  parts.push(` /** Use in \`skills[]\` — built-in web search */`);
1148
- parts.push(` skill(): TypedSkill<${skillToolType}> {`);
1149
- parts.push(` return new TerseConfig() as TypedSkill<${skillToolType}>`);
764
+ parts.push(" skill(): TerseConfig {");
765
+ parts.push(" return new TerseConfig()");
1150
766
  parts.push(" },");
1151
767
  parts.push("}");
1152
768
  parts.push("");
@@ -1157,21 +773,20 @@ export function generateCode(input) {
1157
773
  const allImports = new Set();
1158
774
  const sections = [];
1159
775
  const sectionGenerators = [
1160
- generateGitHubSection(input.github, input.tools),
1161
- generateGmailSection(input.gmail, input.tools),
1162
- generateSlackSection(input.slack, input.tools),
776
+ generateGitHubSection(input.github),
777
+ generateGmailSection(input.gmail),
778
+ generateSlackSection(input.slack),
1163
779
  generateFigmaSection(input.figma),
1164
- generateLinearSection(input.linear, input.tools),
1165
- generateAtlassianSection(input.atlassian, input.tools),
1166
- generateNotionSection(input.notion, input.tools),
1167
- generatePosthogSection(input.posthog, input.tools),
1168
- generateDatadogSection(input.datadog, input.tools),
1169
- generateLaunchDarklySection(input.launchdarkly, input.tools),
1170
- generateWorkOSSection(input.workos, input.tools),
1171
- generateAttioSection(input.attio, input.tools),
1172
- generateSnowflakeSection(input.snowflake, input.tools),
780
+ generateLinearSection(input.linear),
781
+ generateAtlassianSection(input.atlassian),
782
+ generateNotionSection(input.notion),
783
+ generatePosthogSection(input.posthog),
784
+ generateDatadogSection(input.datadog),
785
+ generateLaunchDarklySection(input.launchdarkly),
786
+ generateWorkOSSection(input.workos),
787
+ generateAttioSection(input.attio),
1173
788
  generateToolsSection(input.tools, input),
1174
- generateSystemSection(input.tools),
789
+ generateSystemSection(),
1175
790
  ];
1176
791
  for (const section of sectionGenerators) {
1177
792
  if (section.code) {