terse-cli 0.3.7 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_tmp_create_project.d.ts +2 -0
- package/dist/_tmp_create_project.d.ts.map +1 -0
- package/dist/_tmp_create_project.js +17 -0
- package/dist/_tmp_create_project.js.map +1 -0
- package/dist/_tmp_delete_agent.d.ts +2 -0
- package/dist/_tmp_delete_agent.d.ts.map +1 -0
- package/dist/_tmp_delete_agent.js +14 -0
- package/dist/_tmp_delete_agent.js.map +1 -0
- package/dist/_tmp_manual_trigger.d.ts +2 -0
- package/dist/_tmp_manual_trigger.d.ts.map +1 -0
- package/dist/_tmp_manual_trigger.js +17 -0
- package/dist/_tmp_manual_trigger.js.map +1 -0
- package/dist/_tmp_patch_active.d.ts +2 -0
- package/dist/_tmp_patch_active.d.ts.map +1 -0
- package/dist/_tmp_patch_active.js +21 -0
- package/dist/_tmp_patch_active.js.map +1 -0
- package/dist/codegen.d.ts +15 -0
- package/dist/codegen.d.ts.map +1 -1
- package/dist/codegen.js +466 -81
- package/dist/codegen.js.map +1 -1
- package/dist/commands/auth.js +3 -3
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/authOrg.js +3 -3
- package/dist/commands/authOrg.js.map +1 -1
- package/dist/commands/authStatus.d.ts.map +1 -1
- package/dist/commands/authStatus.js +2 -3
- package/dist/commands/authStatus.js.map +1 -1
- package/dist/commands/deploy.js +1 -2
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/deployTheme.d.ts +28 -0
- package/dist/commands/deployTheme.d.ts.map +1 -0
- package/dist/commands/deployTheme.js +68 -0
- package/dist/commands/deployTheme.js.map +1 -0
- package/dist/commands/dev.d.ts +3 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +47 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/fsExec.d.ts +8 -0
- package/dist/commands/fsExec.d.ts.map +1 -0
- package/dist/commands/fsExec.js +46 -0
- package/dist/commands/fsExec.js.map +1 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +2 -2
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/metaAdsScope.d.ts +12 -0
- package/dist/commands/metaAdsScope.d.ts.map +1 -0
- package/dist/commands/metaAdsScope.js +120 -0
- package/dist/commands/metaAdsScope.js.map +1 -0
- package/dist/commands/serve.d.ts +1 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +2 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/terseCliTheme.d.ts +28 -0
- package/dist/commands/terseCliTheme.d.ts.map +1 -0
- package/dist/commands/terseCliTheme.js +68 -0
- package/dist/commands/terseCliTheme.js.map +1 -0
- package/dist/commands/tool.d.ts +6 -0
- package/dist/commands/tool.d.ts.map +1 -0
- package/dist/commands/tool.js +34 -0
- package/dist/commands/tool.js.map +1 -0
- package/dist/data/standardSlackEmoji.d.ts +2 -0
- package/dist/data/standardSlackEmoji.d.ts.map +1 -0
- package/dist/data/standardSlackEmoji.js +1978 -0
- package/dist/data/standardSlackEmoji.js.map +1 -0
- package/dist/data/standardSlackEmoji.json +1974 -0
- package/dist/deploy.d.ts +2 -1
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +61 -38
- package/dist/deploy.js.map +1 -1
- package/dist/generate.d.ts +2 -1
- package/dist/generate.d.ts.map +1 -1
- package/dist/generate.js +67 -69
- package/dist/generate.js.map +1 -1
- package/dist/init.d.ts +2 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +45 -96
- package/dist/init.js.map +1 -1
- package/dist/integrate.d.ts +1 -0
- package/dist/integrate.d.ts.map +1 -1
- package/dist/integrate.js +191 -11
- package/dist/integrate.js.map +1 -1
- package/dist/nonInteractive.d.ts +4 -2
- package/dist/nonInteractive.d.ts.map +1 -1
- package/dist/nonInteractive.js +5 -2
- package/dist/nonInteractive.js.map +1 -1
- package/dist/perf.d.ts +9 -0
- package/dist/perf.d.ts.map +1 -0
- package/dist/perf.js +59 -0
- package/dist/perf.js.map +1 -0
- package/dist/providers/codegen.test.d.ts +2 -0
- package/dist/providers/codegen.test.d.ts.map +1 -0
- package/dist/providers/codegen.test.js +45 -0
- package/dist/providers/codegen.test.js.map +1 -0
- package/dist/providers/python/PythonProvider.js +1 -0
- package/dist/providers/python/PythonProvider.js.map +1 -1
- package/dist/providers/python/PythonProvider.test.d.ts +2 -0
- package/dist/providers/python/PythonProvider.test.d.ts.map +1 -0
- package/dist/providers/python/PythonProvider.test.js +169 -0
- package/dist/providers/python/PythonProvider.test.js.map +1 -0
- package/dist/providers/typescript/TypeScriptProvider.js +1 -1
- package/dist/providers/typescript/TypeScriptProvider.js.map +1 -1
- package/dist/providers/typescript/attioProjection.d.ts +50 -0
- package/dist/providers/typescript/attioProjection.d.ts.map +1 -0
- package/dist/providers/typescript/attioProjection.js +358 -0
- package/dist/providers/typescript/attioProjection.js.map +1 -0
- package/dist/providers/typescript/modules/cursor/CursorModule.d.ts +20 -0
- package/dist/providers/typescript/modules/cursor/CursorModule.d.ts.map +1 -0
- package/dist/providers/typescript/modules/cursor/CursorModule.js +27 -0
- package/dist/providers/typescript/modules/cursor/CursorModule.js.map +1 -0
- package/dist/providers/typescript/prepareCodegenData.test.d.ts +2 -0
- package/dist/providers/typescript/prepareCodegenData.test.d.ts.map +1 -0
- package/dist/providers/typescript/prepareCodegenData.test.js +54 -0
- package/dist/providers/typescript/prepareCodegenData.test.js.map +1 -0
- package/dist/providers/typescript/projectedTypes.d.ts +11 -0
- package/dist/providers/typescript/projectedTypes.d.ts.map +1 -0
- package/dist/providers/typescript/projectedTypes.js +53 -0
- package/dist/providers/typescript/projectedTypes.js.map +1 -0
- package/dist/providers/typescript/projectionPrinter.d.ts +26 -0
- package/dist/providers/typescript/projectionPrinter.d.ts.map +1 -0
- package/dist/providers/typescript/projectionPrinter.js +110 -0
- package/dist/providers/typescript/projectionPrinter.js.map +1 -0
- package/dist/providers/typescript/replayLogDedupe.d.ts +6 -0
- package/dist/providers/typescript/replayLogDedupe.d.ts.map +1 -0
- package/dist/providers/typescript/replayLogDedupe.js +156 -0
- package/dist/providers/typescript/replayLogDedupe.js.map +1 -0
- package/dist/providers/typescript/triggerPayloads.d.ts +7 -0
- package/dist/providers/typescript/triggerPayloads.d.ts.map +1 -0
- package/dist/providers/typescript/triggerPayloads.js +60 -0
- package/dist/providers/typescript/triggerPayloads.js.map +1 -0
- package/dist/providers/typescript/triggerTypeRegistry.d.ts +7 -0
- package/dist/providers/typescript/triggerTypeRegistry.d.ts.map +1 -0
- package/dist/providers/typescript/triggerTypeRegistry.js +198 -0
- package/dist/providers/typescript/triggerTypeRegistry.js.map +1 -0
- package/dist/run.d.ts +2 -11
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +42 -153
- package/dist/run.js.map +1 -1
- package/dist/sampleEventId.d.ts +0 -4
- package/dist/sampleEventId.d.ts.map +1 -1
- package/dist/sampleEventId.js +0 -4
- package/dist/sampleEventId.js.map +1 -1
- package/dist/shared/ApiRoutes.d.ts +19 -0
- package/dist/shared/ApiRoutes.d.ts.map +1 -1
- package/dist/shared/ApiRoutes.js +17 -1
- package/dist/shared/ApiRoutes.js.map +1 -1
- package/dist/shared/Configs.d.ts +24 -2
- package/dist/shared/Configs.d.ts.map +1 -1
- package/dist/shared/Configs.js +32 -2
- package/dist/shared/Configs.js.map +1 -1
- package/dist/shared/Integrations.d.ts +18 -1
- package/dist/shared/Integrations.d.ts.map +1 -1
- package/dist/shared/Integrations.js +10 -1
- package/dist/shared/Integrations.js.map +1 -1
- package/dist/shared/InvalidationKeys.d.ts +1 -0
- package/dist/shared/InvalidationKeys.d.ts.map +1 -1
- package/dist/shared/InvalidationKeys.js +3 -0
- package/dist/shared/InvalidationKeys.js.map +1 -1
- package/dist/shared/ModelEvents.d.ts +9 -0
- package/dist/shared/ModelEvents.d.ts.map +1 -1
- package/dist/shared/ModelEvents.js +15 -0
- package/dist/shared/ModelEvents.js.map +1 -1
- package/dist/shared/ToolDisplayUtils.d.ts.map +1 -1
- package/dist/shared/ToolDisplayUtils.js +107 -11
- package/dist/shared/ToolDisplayUtils.js.map +1 -1
- package/dist/shared/types.d.ts +1013 -108
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js.map +1 -1
- package/dist/test.d.ts +2 -1
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +43 -23
- package/dist/test.js.map +1 -1
- package/dist/triggerParseDetail.d.ts +8 -0
- package/dist/triggerParseDetail.d.ts.map +1 -0
- package/dist/triggerParseDetail.js +30 -0
- package/dist/triggerParseDetail.js.map +1 -0
- package/dist/util.d.ts +2 -3
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +3 -3
- package/dist/util.js.map +1 -1
- package/package.json +3 -3
- package/templates/typescript/codegen/.impeccable/hook.cache.json +1 -0
- package/dist/jsonOutput.d.ts +0 -19
- package/dist/jsonOutput.d.ts.map +0 -1
- package/dist/jsonOutput.js +0 -25
- package/dist/jsonOutput.js.map +0 -1
- package/dist/providers/typescript/parkSignals.d.ts +0 -7
- package/dist/providers/typescript/parkSignals.d.ts.map +0 -1
- package/dist/providers/typescript/parkSignals.js +0 -45
- package/dist/providers/typescript/parkSignals.js.map +0 -1
- package/dist/replay.d.ts +0 -3
- package/dist/replay.d.ts.map +0 -1
- package/dist/replay.js +0 -20
- package/dist/replay.js.map +0 -1
- package/dist/testRelay.d.ts +0 -6
- package/dist/testRelay.d.ts.map +0 -1
- package/dist/testRelay.js +0 -91
- package/dist/testRelay.js.map +0 -1
- package/dist/urls.d.ts +0 -3
- package/dist/urls.d.ts.map +0 -1
- package/dist/urls.js +0 -27
- package/dist/urls.js.map +0 -1
package/dist/codegen.js
CHANGED
|
@@ -19,6 +19,82 @@ 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
|
+
}
|
|
22
98
|
/** Map a tool's integration key back to the IntegrationType enum value used by ConfigInstance. */
|
|
23
99
|
function toolIntegrationToIntegrationType(toolIntegration) {
|
|
24
100
|
switch (toolIntegration) {
|
|
@@ -29,6 +105,19 @@ function toolIntegrationToIntegrationType(toolIntegration) {
|
|
|
29
105
|
return toolIntegration;
|
|
30
106
|
}
|
|
31
107
|
}
|
|
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
|
+
}
|
|
32
121
|
function generateResourceClass(className, fields, staticNameField, items) {
|
|
33
122
|
const lines = [];
|
|
34
123
|
lines.push(`export class ${className} {`);
|
|
@@ -57,13 +146,14 @@ function generateResourceClass(className, fields, staticNameField, items) {
|
|
|
57
146
|
return lines.join("\n");
|
|
58
147
|
}
|
|
59
148
|
// ── GitHub ────────────────────────────────────────────────────────────
|
|
60
|
-
function generateGitHubSection(instances) {
|
|
149
|
+
function generateGitHubSection(instances, tools) {
|
|
61
150
|
if (instances.length === 0)
|
|
62
151
|
return EMPTY_SECTION;
|
|
63
152
|
const inst = instances[0];
|
|
64
153
|
const imports = new Set(["GitHubConfig"]);
|
|
65
154
|
const parts = [sectionHeader("GitHub"), ""];
|
|
66
155
|
const id = inst.integration.id;
|
|
156
|
+
const skillToolType = buildSkillToolTypeForIntegration(tools, "github");
|
|
67
157
|
const toStaticName = (raw, fallback) => {
|
|
68
158
|
let name = toPascalCase(raw || fallback);
|
|
69
159
|
if (!name)
|
|
@@ -125,6 +215,7 @@ function generateGitHubSection(instances) {
|
|
|
125
215
|
parts.push("");
|
|
126
216
|
imports.add("GitHubEventType");
|
|
127
217
|
imports.add("TypedTrigger");
|
|
218
|
+
imports.add("TypedSkill");
|
|
128
219
|
imports.add("GithubPRInputEvent");
|
|
129
220
|
imports.add("GithubPushInputEvent");
|
|
130
221
|
imports.add("GithubInputEvent");
|
|
@@ -155,20 +246,21 @@ function generateGitHubSection(instances) {
|
|
|
155
246
|
parts.push(` return new GitHubConfig("${id}", opts.repos.map(r => r.repositoryId), opts.eventTypes) as TypedTrigger<GithubInputEvent>`);
|
|
156
247
|
parts.push(" },");
|
|
157
248
|
parts.push(` /** Use in \`skills[]\` */`);
|
|
158
|
-
parts.push(` skill(opts: { repos: Repos[] }):
|
|
159
|
-
parts.push(` return new GitHubConfig("${id}", opts.repos.map(r => r.repositoryId))
|
|
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}>`);
|
|
160
251
|
parts.push(" },");
|
|
161
252
|
parts.push("}");
|
|
162
253
|
parts.push("");
|
|
163
254
|
return { code: parts.join("\n"), imports };
|
|
164
255
|
}
|
|
165
256
|
// ── Gmail ─────────────────────────────────────────────────────────────
|
|
166
|
-
function generateGmailSection(instances) {
|
|
257
|
+
function generateGmailSection(instances, tools) {
|
|
167
258
|
if (instances.length === 0)
|
|
168
259
|
return EMPTY_SECTION;
|
|
169
|
-
const imports = new Set(["GmailConfig", "GmailOutputConfig", "GmailDraftOutputConfig"]);
|
|
260
|
+
const imports = new Set(["GmailConfig", "GmailOutputConfig", "GmailDraftOutputConfig", "TypedSkill"]);
|
|
170
261
|
const parts = [sectionHeader("Gmail"), ""];
|
|
171
262
|
const id = instances[0].id;
|
|
263
|
+
const skillToolType = buildSkillToolTypeForIntegration(tools, "gmail");
|
|
172
264
|
imports.add("GmailEventType");
|
|
173
265
|
parts.push("export const Gmail = {");
|
|
174
266
|
parts.push(` /** Trigger when a new email is received */`);
|
|
@@ -180,25 +272,26 @@ function generateGmailSection(instances) {
|
|
|
180
272
|
parts.push(` return new GmailConfig("${id}", opts?.eventTypes)`);
|
|
181
273
|
parts.push(" },");
|
|
182
274
|
parts.push(` /** Use in \`skills[]\` */`);
|
|
183
|
-
parts.push(` skill():
|
|
184
|
-
parts.push(` return new GmailOutputConfig("${id}")
|
|
275
|
+
parts.push(` skill(): TypedSkill<${skillToolType}> {`);
|
|
276
|
+
parts.push(` return new GmailOutputConfig("${id}") as TypedSkill<${skillToolType}>`);
|
|
185
277
|
parts.push(" },");
|
|
186
278
|
parts.push(` /** Use in \`skills[]\` — creates draft emails */`);
|
|
187
|
-
parts.push(` draftSkill():
|
|
188
|
-
parts.push(` return new GmailDraftOutputConfig("${id}")
|
|
279
|
+
parts.push(` draftSkill(): TypedSkill<${skillToolType}> {`);
|
|
280
|
+
parts.push(` return new GmailDraftOutputConfig("${id}") as TypedSkill<${skillToolType}>`);
|
|
189
281
|
parts.push(" },");
|
|
190
282
|
parts.push("}");
|
|
191
283
|
parts.push("");
|
|
192
284
|
return { code: parts.join("\n"), imports };
|
|
193
285
|
}
|
|
194
286
|
// ── Slack ──────────────────────────────────────────────────────────────
|
|
195
|
-
function generateSlackSection(instances) {
|
|
287
|
+
function generateSlackSection(instances, tools) {
|
|
196
288
|
if (instances.length === 0)
|
|
197
289
|
return EMPTY_SECTION;
|
|
198
290
|
const inst = instances[0];
|
|
199
|
-
const imports = new Set(["SlackConfig", "SlackOutputConfig"]);
|
|
291
|
+
const imports = new Set(["SlackConfig", "SlackOutputConfig", "TypedSkill"]);
|
|
200
292
|
const parts = [sectionHeader("Slack"), ""];
|
|
201
293
|
const id = inst.id;
|
|
294
|
+
const skillToolType = buildSkillToolTypeForIntegration(tools, "slack");
|
|
202
295
|
parts.push(generateResourceClass("SlackChannel", [
|
|
203
296
|
{ classField: "channelId", type: "string", sourceField: "id" },
|
|
204
297
|
{ classField: "name", type: "string", sourceField: "name" },
|
|
@@ -220,8 +313,8 @@ function generateSlackSection(instances) {
|
|
|
220
313
|
parts.push(` return new SlackConfig("${id}", opts?.channel?.channelId, opts?.channel?.name, opts?.listenToUserDms, opts?.userIds, opts?.eventTypes)`);
|
|
221
314
|
parts.push(" },");
|
|
222
315
|
parts.push(` /** Use in \`skills[]\` */`);
|
|
223
|
-
parts.push(` skill(opts?: { channel?: SlackChannel; userIds?: string[]; userNames?: string[]; listenToUserDms?: boolean }):
|
|
224
|
-
parts.push(` return new SlackOutputConfig("${id}", opts?.channel?.channelId, opts?.channel?.name, opts?.userIds, opts?.userNames, opts?.listenToUserDms)
|
|
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}>`);
|
|
225
318
|
parts.push(" },");
|
|
226
319
|
parts.push("}");
|
|
227
320
|
parts.push("");
|
|
@@ -249,13 +342,14 @@ function generateFigmaSection(instances) {
|
|
|
249
342
|
return { code: parts.join("\n"), imports };
|
|
250
343
|
}
|
|
251
344
|
// ── Linear ────────────────────────────────────────────────────────────
|
|
252
|
-
function generateLinearSection(instances) {
|
|
345
|
+
function generateLinearSection(instances, tools) {
|
|
253
346
|
if (instances.length === 0)
|
|
254
347
|
return EMPTY_SECTION;
|
|
255
348
|
const inst = instances[0];
|
|
256
|
-
const imports = new Set(["LinearInputConfig", "LinearOutputConfig"]);
|
|
349
|
+
const imports = new Set(["LinearInputConfig", "LinearOutputConfig", "TypedSkill"]);
|
|
257
350
|
const parts = [sectionHeader("Linear"), ""];
|
|
258
351
|
const id = inst.id;
|
|
352
|
+
const skillToolType = buildSkillToolTypeForIntegration(tools, "linear");
|
|
259
353
|
parts.push(generateResourceClass("LinearTeam", [
|
|
260
354
|
{ classField: "teamId", type: "string", sourceField: "id" },
|
|
261
355
|
{ classField: "name", type: "string", sourceField: "name" },
|
|
@@ -281,21 +375,22 @@ function generateLinearSection(instances) {
|
|
|
281
375
|
parts.push(` return new LinearInputConfig("${id}", opts?.projectId, opts?.projectName, opts?.eventTypes)`);
|
|
282
376
|
parts.push(" },");
|
|
283
377
|
parts.push(` /** Use in \`skills[]\` */`);
|
|
284
|
-
parts.push(` skill(opts?: { team?: LinearTeam; projectId?: string; projectName?: string }):
|
|
285
|
-
parts.push(` return new LinearOutputConfig("${id}", opts?.team?.teamId, opts?.team?.name, opts?.projectId, opts?.projectName)
|
|
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}>`);
|
|
286
380
|
parts.push(" },");
|
|
287
381
|
parts.push("}");
|
|
288
382
|
parts.push("");
|
|
289
383
|
return { code: parts.join("\n"), imports };
|
|
290
384
|
}
|
|
291
385
|
// ── Jira & Confluence (Atlassian) ─────────────────────────────────────
|
|
292
|
-
function generateAtlassianSection(instances) {
|
|
386
|
+
function generateAtlassianSection(instances, tools) {
|
|
293
387
|
if (instances.length === 0)
|
|
294
388
|
return EMPTY_SECTION;
|
|
295
389
|
const inst = instances[0];
|
|
296
|
-
const imports = new Set(["JiraConfig", "ConfluenceConfig"]);
|
|
390
|
+
const imports = new Set(["JiraConfig", "ConfluenceConfig", "TypedSkill"]);
|
|
297
391
|
const parts = [sectionHeader("Jira & Confluence"), ""];
|
|
298
392
|
const id = inst.id;
|
|
393
|
+
const atlassianSkillToolType = buildSkillToolTypeForIntegration(tools, "atlassian");
|
|
299
394
|
parts.push(generateResourceClass("JiraProject", [
|
|
300
395
|
{ classField: "projectKey", type: "string", sourceField: "key" },
|
|
301
396
|
{ classField: "projectId", type: "string", sourceField: "id" },
|
|
@@ -324,28 +419,29 @@ function generateAtlassianSection(instances) {
|
|
|
324
419
|
parts.push(` return new JiraConfig("${id}", opts?.project?.projectKey, opts?.project?.projectId, opts?.eventTypes)`);
|
|
325
420
|
parts.push(" },");
|
|
326
421
|
parts.push(` /** Use in \`skills[]\` */`);
|
|
327
|
-
parts.push(` skill(opts?: { project?: JiraProject }):
|
|
328
|
-
parts.push(` return new JiraConfig("${id}", opts?.project?.projectKey, opts?.project?.projectId)
|
|
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}>`);
|
|
329
424
|
parts.push(" },");
|
|
330
425
|
parts.push("}");
|
|
331
426
|
parts.push("");
|
|
332
427
|
parts.push("export const Confluence = {");
|
|
333
428
|
parts.push(` /** Use in \`skills[]\` */`);
|
|
334
|
-
parts.push(` skill(opts: { page: ConfluencePage }):
|
|
335
|
-
parts.push(` return new ConfluenceConfig("${id}", opts.page.spaceName, opts.page.spaceId, opts.page.pageId, opts.page.title)
|
|
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}>`);
|
|
336
431
|
parts.push(" },");
|
|
337
432
|
parts.push("}");
|
|
338
433
|
parts.push("");
|
|
339
434
|
return { code: parts.join("\n"), imports };
|
|
340
435
|
}
|
|
341
436
|
// ── Notion ────────────────────────────────────────────────────────────
|
|
342
|
-
function generateNotionSection(instances) {
|
|
437
|
+
function generateNotionSection(instances, tools) {
|
|
343
438
|
if (instances.length === 0)
|
|
344
439
|
return EMPTY_SECTION;
|
|
345
440
|
const inst = instances[0];
|
|
346
|
-
const imports = new Set(["NotionConfig"]);
|
|
441
|
+
const imports = new Set(["NotionConfig", "TypedSkill"]);
|
|
347
442
|
const parts = [sectionHeader("Notion"), ""];
|
|
348
443
|
const id = inst.id;
|
|
444
|
+
const skillToolType = buildSkillToolTypeForIntegration(tools, "notion");
|
|
349
445
|
parts.push(generateResourceClass("NotionDatabase", [
|
|
350
446
|
{ classField: "databaseId", type: "string", sourceField: "id" },
|
|
351
447
|
{ classField: "title", type: "string", sourceField: "title" },
|
|
@@ -358,23 +454,24 @@ function generateNotionSection(instances) {
|
|
|
358
454
|
parts.push("");
|
|
359
455
|
parts.push("export const Notion = {");
|
|
360
456
|
parts.push(` /** Use in \`skills[]\` */`);
|
|
361
|
-
parts.push(` skill(opts?: { databases?: NotionDatabase[]; pages?: NotionPage[] }):
|
|
457
|
+
parts.push(` skill(opts?: { databases?: NotionDatabase[]; pages?: NotionPage[] }): TypedSkill<${skillToolType}> {`);
|
|
362
458
|
parts.push(` return new NotionConfig("${id}",`);
|
|
363
459
|
parts.push(` opts?.databases?.map(d => d.databaseId), opts?.databases?.map(d => d.title),`);
|
|
364
|
-
parts.push(` opts?.pages?.map(p => p.pageId), opts?.pages?.map(p => p.title))
|
|
460
|
+
parts.push(` opts?.pages?.map(p => p.pageId), opts?.pages?.map(p => p.title)) as TypedSkill<${skillToolType}>`);
|
|
365
461
|
parts.push(" },");
|
|
366
462
|
parts.push("}");
|
|
367
463
|
parts.push("");
|
|
368
464
|
return { code: parts.join("\n"), imports };
|
|
369
465
|
}
|
|
370
466
|
// ── PostHog ───────────────────────────────────────────────────────────
|
|
371
|
-
function generatePosthogSection(instances) {
|
|
467
|
+
function generatePosthogSection(instances, tools) {
|
|
372
468
|
if (instances.length === 0)
|
|
373
469
|
return EMPTY_SECTION;
|
|
374
470
|
const inst = instances[0];
|
|
375
|
-
const imports = new Set(["PosthogConfig"]);
|
|
471
|
+
const imports = new Set(["PosthogConfig", "TypedSkill"]);
|
|
376
472
|
const parts = [sectionHeader("PostHog"), ""];
|
|
377
473
|
const id = inst.id;
|
|
474
|
+
const skillToolType = buildSkillToolTypeForIntegration(tools, "posthog");
|
|
378
475
|
parts.push(generateResourceClass("PosthogProject", [
|
|
379
476
|
{ classField: "projectId", type: "string", sourceField: "id" },
|
|
380
477
|
{ classField: "name", type: "string", sourceField: "name" },
|
|
@@ -382,42 +479,44 @@ function generatePosthogSection(instances) {
|
|
|
382
479
|
parts.push("");
|
|
383
480
|
parts.push("export const Posthog = {");
|
|
384
481
|
parts.push(` /** Use in \`skills[]\` */`);
|
|
385
|
-
parts.push(` skill(opts: { project: PosthogProject }):
|
|
386
|
-
parts.push(` return new PosthogConfig("${id}", opts.project.projectId, opts.project.name)
|
|
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}>`);
|
|
387
484
|
parts.push(" },");
|
|
388
485
|
parts.push("}");
|
|
389
486
|
parts.push("");
|
|
390
487
|
return { code: parts.join("\n"), imports };
|
|
391
488
|
}
|
|
392
489
|
// ── Datadog ───────────────────────────────────────────────────────────
|
|
393
|
-
function generateDatadogSection(instances) {
|
|
490
|
+
function generateDatadogSection(instances, tools) {
|
|
394
491
|
if (instances.length === 0)
|
|
395
492
|
return EMPTY_SECTION;
|
|
396
493
|
const inst = instances[0];
|
|
397
|
-
const imports = new Set(["DatadogConfig"]);
|
|
494
|
+
const imports = new Set(["DatadogConfig", "TypedSkill"]);
|
|
398
495
|
const parts = [sectionHeader("Datadog"), ""];
|
|
399
496
|
const id = inst.id;
|
|
497
|
+
const skillToolType = buildSkillToolTypeForIntegration(tools, "datadog");
|
|
400
498
|
parts.push(generateResourceClass("DatadogIndex", [
|
|
401
499
|
{ classField: "name", type: "string", sourceField: "name" },
|
|
402
500
|
], "name", inst.indexes));
|
|
403
501
|
parts.push("");
|
|
404
502
|
parts.push("export const Datadog = {");
|
|
405
503
|
parts.push(` /** Use in \`skills[]\` */`);
|
|
406
|
-
parts.push(` skill(opts?: { indexes?: DatadogIndex[] }):
|
|
407
|
-
parts.push(` return new DatadogConfig("${id}", opts?.indexes?.map(i => i.name))
|
|
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}>`);
|
|
408
506
|
parts.push(" },");
|
|
409
507
|
parts.push("}");
|
|
410
508
|
parts.push("");
|
|
411
509
|
return { code: parts.join("\n"), imports };
|
|
412
510
|
}
|
|
413
511
|
// ── LaunchDarkly ──────────────────────────────────────────────────────
|
|
414
|
-
function generateLaunchDarklySection(instances) {
|
|
512
|
+
function generateLaunchDarklySection(instances, tools) {
|
|
415
513
|
if (instances.length === 0)
|
|
416
514
|
return EMPTY_SECTION;
|
|
417
515
|
const inst = instances[0];
|
|
418
|
-
const imports = new Set(["LaunchDarklyConfig"]);
|
|
516
|
+
const imports = new Set(["LaunchDarklyConfig", "TypedSkill"]);
|
|
419
517
|
const parts = [sectionHeader("LaunchDarkly"), ""];
|
|
420
518
|
const id = inst.id;
|
|
519
|
+
const skillToolType = buildSkillToolTypeForIntegration(tools, "launchdarkly");
|
|
421
520
|
parts.push(generateResourceClass("LaunchDarklyProject", [
|
|
422
521
|
{ classField: "projectKey", type: "string", sourceField: "key" },
|
|
423
522
|
{ classField: "name", type: "string", sourceField: "name" },
|
|
@@ -425,70 +524,160 @@ function generateLaunchDarklySection(instances) {
|
|
|
425
524
|
parts.push("");
|
|
426
525
|
parts.push("export const LaunchDarkly = {");
|
|
427
526
|
parts.push(` /** Use in \`skills[]\` */`);
|
|
428
|
-
parts.push(` skill(opts: { project: LaunchDarklyProject; environmentKeys: string[] }):
|
|
429
|
-
parts.push(` return new LaunchDarklyConfig("${id}", opts.project.projectKey, opts.environmentKeys)
|
|
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}>`);
|
|
430
529
|
parts.push(" },");
|
|
431
530
|
parts.push("}");
|
|
432
531
|
parts.push("");
|
|
433
532
|
return { code: parts.join("\n"), imports };
|
|
434
533
|
}
|
|
435
534
|
// ── WorkOS ────────────────────────────────────────────────────────────
|
|
436
|
-
function generateWorkOSSection(instances) {
|
|
535
|
+
function generateWorkOSSection(instances, tools) {
|
|
437
536
|
if (instances.length === 0)
|
|
438
537
|
return EMPTY_SECTION;
|
|
439
|
-
const imports = new Set(["WorkOSInputConfig", "WorkOSOutputConfig", "WorkOSEventType"]);
|
|
538
|
+
const imports = new Set(["WorkOSInputConfig", "WorkOSOutputConfig", "WorkOSEventType", "TypedSkill"]);
|
|
440
539
|
const parts = [sectionHeader("WorkOS"), ""];
|
|
441
540
|
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");
|
|
442
548
|
parts.push("export const WorkOS = {");
|
|
443
549
|
parts.push(` /** Trigger on user creation */`);
|
|
444
|
-
parts.push(` onUserCreated():
|
|
445
|
-
parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.USER_CREATED])
|
|
550
|
+
parts.push(` onUserCreated(): TypedTrigger<WorkOSUserInputEvent> {`);
|
|
551
|
+
parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.USER_CREATED]) as TypedTrigger<WorkOSUserInputEvent>`);
|
|
446
552
|
parts.push(" },");
|
|
447
553
|
parts.push(` /** Trigger on user update */`);
|
|
448
|
-
parts.push(` onUserUpdated():
|
|
449
|
-
parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.USER_UPDATED])
|
|
554
|
+
parts.push(` onUserUpdated(): TypedTrigger<WorkOSUserInputEvent> {`);
|
|
555
|
+
parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.USER_UPDATED]) as TypedTrigger<WorkOSUserInputEvent>`);
|
|
450
556
|
parts.push(" },");
|
|
451
557
|
parts.push(` /** Trigger on user deletion */`);
|
|
452
|
-
parts.push(` onUserDeleted():
|
|
453
|
-
parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.USER_DELETED])
|
|
558
|
+
parts.push(` onUserDeleted(): TypedTrigger<WorkOSUserInputEvent> {`);
|
|
559
|
+
parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.USER_DELETED]) as TypedTrigger<WorkOSUserInputEvent>`);
|
|
454
560
|
parts.push(" },");
|
|
455
561
|
parts.push(` /** Trigger on organization membership change */`);
|
|
456
|
-
parts.push(` onMembershipChanged():
|
|
457
|
-
parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.ORGANIZATION_MEMBERSHIP_CREATED, WorkOSEventType.ORGANIZATION_MEMBERSHIP_UPDATED, WorkOSEventType.ORGANIZATION_MEMBERSHIP_DELETED])
|
|
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>`);
|
|
458
576
|
parts.push(" },");
|
|
459
577
|
parts.push(` /** Trigger on invitation accepted */`);
|
|
460
|
-
parts.push(` onInvitationAccepted():
|
|
461
|
-
parts.push(` return new WorkOSInputConfig("${id}", [WorkOSEventType.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>`);
|
|
462
588
|
parts.push(" },");
|
|
463
589
|
parts.push(` /** Trigger on specific WorkOS event types */`);
|
|
464
|
-
parts.push(` trigger(opts?: { eventTypes?: WorkOSEventType[] }):
|
|
465
|
-
parts.push(` return new WorkOSInputConfig("${id}", opts?.eventTypes)
|
|
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>`);
|
|
466
592
|
parts.push(" },");
|
|
467
593
|
parts.push(` /** Use in \`skills[]\` */`);
|
|
468
|
-
parts.push(` skill():
|
|
469
|
-
parts.push(` return new WorkOSOutputConfig("${id}")
|
|
594
|
+
parts.push(` skill(): TypedSkill<${skillToolType}> {`);
|
|
595
|
+
parts.push(` return new WorkOSOutputConfig("${id}") as TypedSkill<${skillToolType}>`);
|
|
470
596
|
parts.push(" },");
|
|
471
597
|
parts.push("}");
|
|
472
598
|
parts.push("");
|
|
473
599
|
return { code: parts.join("\n"), imports };
|
|
474
600
|
}
|
|
475
601
|
// ── Attio ─────────────────────────────────────────────────────────────
|
|
476
|
-
function generateAttioSection(instances) {
|
|
602
|
+
function generateAttioSection(instances, tools) {
|
|
477
603
|
if (instances.length === 0)
|
|
478
604
|
return EMPTY_SECTION;
|
|
479
605
|
const inst = instances[0];
|
|
480
|
-
const imports = new Set(["AttioOutputConfig"]);
|
|
606
|
+
const imports = new Set(["AttioOutputConfig", "TypedSkill"]);
|
|
481
607
|
const parts = [sectionHeader("Attio"), ""];
|
|
482
608
|
const id = inst.id;
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
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("}");
|
|
487
658
|
parts.push("");
|
|
488
659
|
parts.push("export const Attio = {");
|
|
489
660
|
parts.push(` /** Use in \`skills[]\` */`);
|
|
490
|
-
parts.push(` skill(opts
|
|
491
|
-
parts.push(` return new AttioOutputConfig("${id}", opts
|
|
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}>`);
|
|
492
681
|
parts.push(" },");
|
|
493
682
|
parts.push("}");
|
|
494
683
|
parts.push("");
|
|
@@ -584,6 +773,7 @@ function generateToolsSection(tools, input) {
|
|
|
584
773
|
instanceMap.set("launchdarkly", input.launchdarkly.map(l => ({ id: l.id, displayName: l.displayName })));
|
|
585
774
|
instanceMap.set("workos", input.workos.map(w => ({ id: w.id, displayName: w.displayName })));
|
|
586
775
|
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 })));
|
|
587
777
|
// Group tools by integration
|
|
588
778
|
const byIntegration = new Map();
|
|
589
779
|
for (const tool of tools) {
|
|
@@ -625,8 +815,178 @@ function generateToolsSection(tools, input) {
|
|
|
625
815
|
return "params";
|
|
626
816
|
}
|
|
627
817
|
};
|
|
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
|
+
}
|
|
628
986
|
// Generate per-tool param types (with integrationId omitted where applicable)
|
|
629
987
|
for (const tool of tools) {
|
|
988
|
+
if (isAttioTool(tool))
|
|
989
|
+
continue;
|
|
630
990
|
const typeName = toolNameToInterfaceName(tool.name);
|
|
631
991
|
const schema = hasAutoFillId(tool) ? omitIntegrationId(tool.parameters) : tool.parameters;
|
|
632
992
|
const tsType = jsonSchemaToTs(schema, 0);
|
|
@@ -700,7 +1060,18 @@ function generateToolsSection(tools, input) {
|
|
|
700
1060
|
if (tool.description) {
|
|
701
1061
|
parts.push(` /** ${tool.description} */`);
|
|
702
1062
|
}
|
|
703
|
-
|
|
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
|
+
}
|
|
704
1075
|
}
|
|
705
1076
|
parts.push(" }");
|
|
706
1077
|
}
|
|
@@ -725,7 +1096,19 @@ function generateToolsSection(tools, input) {
|
|
|
725
1096
|
const methodName = toCamelCase(tool.displayName);
|
|
726
1097
|
const paramsType = toolNameToInterfaceName(tool.name);
|
|
727
1098
|
const normalizedParamsExpr = group.integration === "github" ? normalizeGitHubReposParams(tool.name) : "params";
|
|
728
|
-
if (group.
|
|
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)) {
|
|
729
1112
|
parts.push(` ${methodName}: (params: ${paramsType}) =>`);
|
|
730
1113
|
parts.push(` agent.executeTool<ToolOutputByName["${escapeString(tool.name)}"]>("${escapeString(tool.name)}", { ...(${normalizedParamsExpr}), integrationId: "${escapeString(group.integrationId)}" }),`);
|
|
731
1114
|
}
|
|
@@ -745,9 +1128,10 @@ function generateToolsSection(tools, input) {
|
|
|
745
1128
|
return { code: parts.join("\n"), imports };
|
|
746
1129
|
}
|
|
747
1130
|
// ── System (always included) ──────────────────────────────────────────
|
|
748
|
-
function generateSystemSection() {
|
|
749
|
-
const imports = new Set(["TimeTriggerConfig", "TerseConfig"]);
|
|
1131
|
+
function generateSystemSection(tools) {
|
|
1132
|
+
const imports = new Set(["TimeTriggerConfig", "TerseConfig", "TypedSkill"]);
|
|
750
1133
|
const parts = [];
|
|
1134
|
+
const skillToolType = buildSkillToolTypeForIntegration(tools, "terse");
|
|
751
1135
|
parts.push(sectionHeader("Schedule"));
|
|
752
1136
|
parts.push("");
|
|
753
1137
|
parts.push("export const Schedule = {");
|
|
@@ -761,8 +1145,8 @@ function generateSystemSection() {
|
|
|
761
1145
|
parts.push("");
|
|
762
1146
|
parts.push("export const Terse = {");
|
|
763
1147
|
parts.push(` /** Use in \`skills[]\` — built-in web search */`);
|
|
764
|
-
parts.push(
|
|
765
|
-
parts.push(
|
|
1148
|
+
parts.push(` skill(): TypedSkill<${skillToolType}> {`);
|
|
1149
|
+
parts.push(` return new TerseConfig() as TypedSkill<${skillToolType}>`);
|
|
766
1150
|
parts.push(" },");
|
|
767
1151
|
parts.push("}");
|
|
768
1152
|
parts.push("");
|
|
@@ -773,20 +1157,21 @@ export function generateCode(input) {
|
|
|
773
1157
|
const allImports = new Set();
|
|
774
1158
|
const sections = [];
|
|
775
1159
|
const sectionGenerators = [
|
|
776
|
-
generateGitHubSection(input.github),
|
|
777
|
-
generateGmailSection(input.gmail),
|
|
778
|
-
generateSlackSection(input.slack),
|
|
1160
|
+
generateGitHubSection(input.github, input.tools),
|
|
1161
|
+
generateGmailSection(input.gmail, input.tools),
|
|
1162
|
+
generateSlackSection(input.slack, input.tools),
|
|
779
1163
|
generateFigmaSection(input.figma),
|
|
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),
|
|
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),
|
|
788
1173
|
generateToolsSection(input.tools, input),
|
|
789
|
-
generateSystemSection(),
|
|
1174
|
+
generateSystemSection(input.tools),
|
|
790
1175
|
];
|
|
791
1176
|
for (const section of sectionGenerators) {
|
|
792
1177
|
if (section.code) {
|