patchwork-os 0.2.0-alpha.26 → 0.2.0-alpha.27

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 (55) hide show
  1. package/deploy/bootstrap-vps.sh +1 -1
  2. package/deploy/deploy-dashboard.sh +164 -0
  3. package/deploy/deploy-landing.sh +79 -0
  4. package/dist/ccPermissions.js +6 -4
  5. package/dist/ccPermissions.js.map +1 -1
  6. package/dist/commands/recipe.js +1 -1
  7. package/dist/commands/recipe.js.map +1 -1
  8. package/dist/commands/recipeInstall.d.ts +72 -0
  9. package/dist/commands/recipeInstall.js +339 -0
  10. package/dist/commands/recipeInstall.js.map +1 -0
  11. package/dist/connectors/datadog.d.ts +116 -0
  12. package/dist/connectors/datadog.js +385 -0
  13. package/dist/connectors/datadog.js.map +1 -0
  14. package/dist/connectors/hubspot.d.ts +112 -0
  15. package/dist/connectors/hubspot.js +408 -0
  16. package/dist/connectors/hubspot.js.map +1 -0
  17. package/dist/connectors/intercom.d.ts +102 -0
  18. package/dist/connectors/intercom.js +402 -0
  19. package/dist/connectors/intercom.js.map +1 -0
  20. package/dist/connectors/stripe.d.ts +116 -0
  21. package/dist/connectors/stripe.js +379 -0
  22. package/dist/connectors/stripe.js.map +1 -0
  23. package/dist/index.js +33 -26
  24. package/dist/index.js.map +1 -1
  25. package/dist/recipes/manifest.d.ts +47 -0
  26. package/dist/recipes/manifest.js +141 -0
  27. package/dist/recipes/manifest.js.map +1 -0
  28. package/dist/recipes/schemaGenerator.js +3 -3
  29. package/dist/recipes/schemaGenerator.js.map +1 -1
  30. package/dist/recipes/tools/datadog.d.ts +6 -0
  31. package/dist/recipes/tools/datadog.js +239 -0
  32. package/dist/recipes/tools/datadog.js.map +1 -0
  33. package/dist/recipes/tools/hubspot.d.ts +6 -0
  34. package/dist/recipes/tools/hubspot.js +232 -0
  35. package/dist/recipes/tools/hubspot.js.map +1 -0
  36. package/dist/recipes/tools/index.d.ts +4 -0
  37. package/dist/recipes/tools/index.js +4 -0
  38. package/dist/recipes/tools/index.js.map +1 -1
  39. package/dist/recipes/tools/intercom.d.ts +6 -0
  40. package/dist/recipes/tools/intercom.js +226 -0
  41. package/dist/recipes/tools/intercom.js.map +1 -0
  42. package/dist/recipes/tools/stripe.d.ts +6 -0
  43. package/dist/recipes/tools/stripe.js +265 -0
  44. package/dist/recipes/tools/stripe.js.map +1 -0
  45. package/dist/recipes/yamlRunner.js +28 -0
  46. package/dist/recipes/yamlRunner.js.map +1 -1
  47. package/dist/schemas/dry-run-plan.v1.json +1 -1
  48. package/dist/schemas/recipe.v1.json +1 -1
  49. package/dist/server.js +155 -1
  50. package/dist/server.js.map +1 -1
  51. package/dist/tools/searchTools.js +1 -1
  52. package/dist/tools/searchTools.js.map +1 -1
  53. package/dist/tools/testTraceToSource.js +2 -2
  54. package/dist/tools/testTraceToSource.js.map +1 -1
  55. package/package.json +1 -1
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Intercom tools — list/get conversations, reply, close, list contacts.
3
+ *
4
+ * Self-registering tool module for the recipe tool registry.
5
+ */
6
+ import { assertWriteAllowed } from "../../featureFlags.js";
7
+ import { CommonSchemas, registerTool } from "../toolRegistry.js";
8
+ // ============================================================================
9
+ // intercom.listConversations
10
+ // ============================================================================
11
+ registerTool({
12
+ id: "intercom.listConversations",
13
+ namespace: "intercom",
14
+ description: "List Intercom conversations, optionally filtered by status or assignee.",
15
+ paramsSchema: {
16
+ type: "object",
17
+ properties: {
18
+ status: {
19
+ type: "string",
20
+ enum: ["open", "closed", "snoozed", "pending"],
21
+ description: "Filter by conversation status",
22
+ },
23
+ assigneeId: {
24
+ type: "string",
25
+ description: "Filter by assignee ID",
26
+ },
27
+ perPage: {
28
+ type: "number",
29
+ description: "Results per page (default 20)",
30
+ default: 20,
31
+ },
32
+ into: CommonSchemas.into,
33
+ },
34
+ required: [],
35
+ },
36
+ outputSchema: {
37
+ type: "object",
38
+ properties: {
39
+ conversations: { type: "array", items: { type: "object" } },
40
+ total_count: { type: "number" },
41
+ pages: { type: "object" },
42
+ },
43
+ },
44
+ riskDefault: "low",
45
+ isWrite: false,
46
+ isConnector: true,
47
+ execute: async ({ params }) => {
48
+ const { getIntercomConnector } = await import("../../connectors/intercom.js");
49
+ const connector = getIntercomConnector();
50
+ const result = await connector.listConversations({
51
+ status: params.status,
52
+ assigneeId: typeof params.assigneeId === "string" ? params.assigneeId : undefined,
53
+ perPage: typeof params.perPage === "number" ? params.perPage : 20,
54
+ });
55
+ return JSON.stringify(result);
56
+ },
57
+ });
58
+ // ============================================================================
59
+ // intercom.getConversation
60
+ // ============================================================================
61
+ registerTool({
62
+ id: "intercom.getConversation",
63
+ namespace: "intercom",
64
+ description: "Fetch a single Intercom conversation by ID, including parts.",
65
+ paramsSchema: {
66
+ type: "object",
67
+ properties: {
68
+ conversationId: {
69
+ type: "string",
70
+ description: "Intercom conversation ID",
71
+ },
72
+ into: CommonSchemas.into,
73
+ },
74
+ required: ["conversationId"],
75
+ },
76
+ outputSchema: {
77
+ type: "object",
78
+ properties: {
79
+ id: { type: "string" },
80
+ state: { type: "string" },
81
+ title: { type: ["string", "null"] },
82
+ },
83
+ },
84
+ riskDefault: "low",
85
+ isWrite: false,
86
+ isConnector: true,
87
+ execute: async ({ params }) => {
88
+ const { getIntercomConnector } = await import("../../connectors/intercom.js");
89
+ const connector = getIntercomConnector();
90
+ const conversation = await connector.getConversation(params.conversationId);
91
+ return JSON.stringify(conversation);
92
+ },
93
+ });
94
+ // ============================================================================
95
+ // intercom.replyToConversation
96
+ // ============================================================================
97
+ registerTool({
98
+ id: "intercom.replyToConversation",
99
+ namespace: "intercom",
100
+ description: "Reply to an Intercom conversation as a comment or internal note.",
101
+ paramsSchema: {
102
+ type: "object",
103
+ properties: {
104
+ conversationId: {
105
+ type: "string",
106
+ description: "Intercom conversation ID",
107
+ },
108
+ body: { type: "string", description: "Reply body text" },
109
+ type: {
110
+ type: "string",
111
+ enum: ["comment", "note"],
112
+ description: "Reply type: comment (visible to user) or note (internal)",
113
+ default: "comment",
114
+ },
115
+ into: CommonSchemas.into,
116
+ },
117
+ required: ["conversationId", "body"],
118
+ },
119
+ outputSchema: {
120
+ type: "object",
121
+ properties: {
122
+ id: { type: "string" },
123
+ state: { type: "string" },
124
+ },
125
+ },
126
+ riskDefault: "medium",
127
+ isWrite: true,
128
+ isConnector: true,
129
+ execute: async ({ params }) => {
130
+ assertWriteAllowed("intercom.replyToConversation");
131
+ const { getIntercomConnector } = await import("../../connectors/intercom.js");
132
+ const connector = getIntercomConnector();
133
+ const conversation = await connector.replyToConversation(params.conversationId, params.body, params.type ?? "comment");
134
+ return JSON.stringify({ id: conversation.id, state: conversation.state });
135
+ },
136
+ });
137
+ // ============================================================================
138
+ // intercom.closeConversation
139
+ // ============================================================================
140
+ registerTool({
141
+ id: "intercom.closeConversation",
142
+ namespace: "intercom",
143
+ description: "Close an open Intercom conversation.",
144
+ paramsSchema: {
145
+ type: "object",
146
+ properties: {
147
+ conversationId: {
148
+ type: "string",
149
+ description: "Intercom conversation ID",
150
+ },
151
+ into: CommonSchemas.into,
152
+ },
153
+ required: ["conversationId"],
154
+ },
155
+ outputSchema: {
156
+ type: "object",
157
+ properties: {
158
+ id: { type: "string" },
159
+ state: { type: "string" },
160
+ },
161
+ },
162
+ riskDefault: "medium",
163
+ isWrite: true,
164
+ isConnector: true,
165
+ execute: async ({ params }) => {
166
+ assertWriteAllowed("intercom.closeConversation");
167
+ const { getIntercomConnector } = await import("../../connectors/intercom.js");
168
+ const connector = getIntercomConnector();
169
+ const conversation = await connector.closeConversation(params.conversationId);
170
+ return JSON.stringify({ id: conversation.id, state: conversation.state });
171
+ },
172
+ });
173
+ // ============================================================================
174
+ // intercom.listContacts
175
+ // ============================================================================
176
+ registerTool({
177
+ id: "intercom.listContacts",
178
+ namespace: "intercom",
179
+ description: "List Intercom contacts, optionally filtered by name query.",
180
+ paramsSchema: {
181
+ type: "object",
182
+ properties: {
183
+ query: {
184
+ type: "string",
185
+ description: "Filter contacts by name (partial match)",
186
+ },
187
+ perPage: {
188
+ type: "number",
189
+ description: "Results per page (default 20)",
190
+ default: 20,
191
+ },
192
+ into: CommonSchemas.into,
193
+ },
194
+ required: [],
195
+ },
196
+ outputSchema: {
197
+ type: "object",
198
+ properties: {
199
+ contacts: {
200
+ type: "array",
201
+ items: {
202
+ type: "object",
203
+ properties: {
204
+ id: { type: "string" },
205
+ name: { type: ["string", "null"] },
206
+ email: { type: ["string", "null"] },
207
+ },
208
+ },
209
+ },
210
+ total_count: { type: "number" },
211
+ },
212
+ },
213
+ riskDefault: "low",
214
+ isWrite: false,
215
+ isConnector: true,
216
+ execute: async ({ params }) => {
217
+ const { getIntercomConnector } = await import("../../connectors/intercom.js");
218
+ const connector = getIntercomConnector();
219
+ const result = await connector.listContacts({
220
+ query: params.query,
221
+ perPage: typeof params.perPage === "number" ? params.perPage : 20,
222
+ });
223
+ return JSON.stringify(result);
224
+ },
225
+ });
226
+ //# sourceMappingURL=intercom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intercom.js","sourceRoot":"","sources":["../../../src/recipes/tools/intercom.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Stripe tools — read-only access to charges, customers, subscriptions, invoices.
3
+ *
4
+ * Self-registering tool module for the recipe tool registry.
5
+ */
6
+ export {};
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Stripe tools — read-only access to charges, customers, subscriptions, invoices.
3
+ *
4
+ * Self-registering tool module for the recipe tool registry.
5
+ */
6
+ import { CommonSchemas, registerTool } from "../toolRegistry.js";
7
+ // ============================================================================
8
+ // stripe.listCharges
9
+ // ============================================================================
10
+ registerTool({
11
+ id: "stripe.listCharges",
12
+ namespace: "stripe",
13
+ description: "List Stripe charges, optionally filtered by customer ID or status.",
14
+ paramsSchema: {
15
+ type: "object",
16
+ properties: {
17
+ limit: {
18
+ type: "number",
19
+ description: "Max number of charges to return (default 10, max 100)",
20
+ default: 10,
21
+ },
22
+ customerId: {
23
+ type: "string",
24
+ description: "Filter by Stripe customer ID",
25
+ },
26
+ status: {
27
+ type: "string",
28
+ description: "Filter by charge status (e.g. succeeded, failed)",
29
+ },
30
+ into: CommonSchemas.into,
31
+ },
32
+ required: [],
33
+ },
34
+ outputSchema: {
35
+ type: "object",
36
+ properties: {
37
+ data: { type: "array", items: { type: "object" } },
38
+ has_more: { type: "boolean" },
39
+ },
40
+ },
41
+ riskDefault: "low",
42
+ isWrite: false,
43
+ isConnector: true,
44
+ execute: async ({ params }) => {
45
+ const { getStripeConnector } = await import("../../connectors/stripe.js");
46
+ const connector = getStripeConnector();
47
+ const result = await connector.listCharges({
48
+ limit: typeof params.limit === "number" ? params.limit : undefined,
49
+ customerId: typeof params.customerId === "string" ? params.customerId : undefined,
50
+ status: typeof params.status === "string" ? params.status : undefined,
51
+ });
52
+ return JSON.stringify(result);
53
+ },
54
+ });
55
+ // ============================================================================
56
+ // stripe.getCharge
57
+ // ============================================================================
58
+ registerTool({
59
+ id: "stripe.getCharge",
60
+ namespace: "stripe",
61
+ description: "Fetch a single Stripe charge by ID.",
62
+ paramsSchema: {
63
+ type: "object",
64
+ properties: {
65
+ chargeId: { type: "string", description: "Stripe charge ID (ch_...)" },
66
+ into: CommonSchemas.into,
67
+ },
68
+ required: ["chargeId"],
69
+ },
70
+ outputSchema: {
71
+ type: "object",
72
+ properties: {
73
+ id: { type: "string" },
74
+ amount: { type: "number" },
75
+ currency: { type: "string" },
76
+ status: { type: "string" },
77
+ },
78
+ },
79
+ riskDefault: "low",
80
+ isWrite: false,
81
+ isConnector: true,
82
+ execute: async ({ params }) => {
83
+ const { getStripeConnector } = await import("../../connectors/stripe.js");
84
+ const connector = getStripeConnector();
85
+ const result = await connector.getCharge(params.chargeId);
86
+ return JSON.stringify(result);
87
+ },
88
+ });
89
+ // ============================================================================
90
+ // stripe.listCustomers
91
+ // ============================================================================
92
+ registerTool({
93
+ id: "stripe.listCustomers",
94
+ namespace: "stripe",
95
+ description: "List Stripe customers, optionally filtered by email.",
96
+ paramsSchema: {
97
+ type: "object",
98
+ properties: {
99
+ limit: {
100
+ type: "number",
101
+ description: "Max number of customers to return (default 10, max 100)",
102
+ default: 10,
103
+ },
104
+ email: {
105
+ type: "string",
106
+ description: "Filter by customer email address",
107
+ },
108
+ into: CommonSchemas.into,
109
+ },
110
+ required: [],
111
+ },
112
+ outputSchema: {
113
+ type: "object",
114
+ properties: {
115
+ data: { type: "array", items: { type: "object" } },
116
+ has_more: { type: "boolean" },
117
+ },
118
+ },
119
+ riskDefault: "low",
120
+ isWrite: false,
121
+ isConnector: true,
122
+ execute: async ({ params }) => {
123
+ const { getStripeConnector } = await import("../../connectors/stripe.js");
124
+ const connector = getStripeConnector();
125
+ const result = await connector.listCustomers({
126
+ limit: typeof params.limit === "number" ? params.limit : undefined,
127
+ email: typeof params.email === "string" ? params.email : undefined,
128
+ });
129
+ return JSON.stringify(result);
130
+ },
131
+ });
132
+ // ============================================================================
133
+ // stripe.getCustomer
134
+ // ============================================================================
135
+ registerTool({
136
+ id: "stripe.getCustomer",
137
+ namespace: "stripe",
138
+ description: "Fetch a single Stripe customer by ID.",
139
+ paramsSchema: {
140
+ type: "object",
141
+ properties: {
142
+ customerId: {
143
+ type: "string",
144
+ description: "Stripe customer ID (cus_...)",
145
+ },
146
+ into: CommonSchemas.into,
147
+ },
148
+ required: ["customerId"],
149
+ },
150
+ outputSchema: {
151
+ type: "object",
152
+ properties: {
153
+ id: { type: "string" },
154
+ email: { type: ["string", "null"] },
155
+ name: { type: ["string", "null"] },
156
+ balance: { type: "number" },
157
+ },
158
+ },
159
+ riskDefault: "low",
160
+ isWrite: false,
161
+ isConnector: true,
162
+ execute: async ({ params }) => {
163
+ const { getStripeConnector } = await import("../../connectors/stripe.js");
164
+ const connector = getStripeConnector();
165
+ const result = await connector.getCustomer(params.customerId);
166
+ return JSON.stringify(result);
167
+ },
168
+ });
169
+ // ============================================================================
170
+ // stripe.listSubscriptions
171
+ // ============================================================================
172
+ registerTool({
173
+ id: "stripe.listSubscriptions",
174
+ namespace: "stripe",
175
+ description: "List Stripe subscriptions, optionally filtered by customer ID or status.",
176
+ paramsSchema: {
177
+ type: "object",
178
+ properties: {
179
+ limit: {
180
+ type: "number",
181
+ description: "Max number of subscriptions to return (default 10, max 100)",
182
+ default: 10,
183
+ },
184
+ customerId: {
185
+ type: "string",
186
+ description: "Filter by Stripe customer ID",
187
+ },
188
+ status: {
189
+ type: "string",
190
+ description: "Filter by status: active, past_due, canceled, trialing, all",
191
+ },
192
+ into: CommonSchemas.into,
193
+ },
194
+ required: [],
195
+ },
196
+ outputSchema: {
197
+ type: "object",
198
+ properties: {
199
+ data: { type: "array", items: { type: "object" } },
200
+ has_more: { type: "boolean" },
201
+ },
202
+ },
203
+ riskDefault: "low",
204
+ isWrite: false,
205
+ isConnector: true,
206
+ execute: async ({ params }) => {
207
+ const { getStripeConnector } = await import("../../connectors/stripe.js");
208
+ const connector = getStripeConnector();
209
+ const result = await connector.listSubscriptions({
210
+ limit: typeof params.limit === "number" ? params.limit : undefined,
211
+ customerId: typeof params.customerId === "string" ? params.customerId : undefined,
212
+ status: typeof params.status === "string" ? params.status : undefined,
213
+ });
214
+ return JSON.stringify(result);
215
+ },
216
+ });
217
+ // ============================================================================
218
+ // stripe.listInvoices
219
+ // ============================================================================
220
+ registerTool({
221
+ id: "stripe.listInvoices",
222
+ namespace: "stripe",
223
+ description: "List Stripe invoices, optionally filtered by customer ID or status.",
224
+ paramsSchema: {
225
+ type: "object",
226
+ properties: {
227
+ limit: {
228
+ type: "number",
229
+ description: "Max number of invoices to return (default 10, max 100)",
230
+ default: 10,
231
+ },
232
+ customerId: {
233
+ type: "string",
234
+ description: "Filter by Stripe customer ID",
235
+ },
236
+ status: {
237
+ type: "string",
238
+ description: "Filter by invoice status (draft, open, paid, uncollectible, void)",
239
+ },
240
+ into: CommonSchemas.into,
241
+ },
242
+ required: [],
243
+ },
244
+ outputSchema: {
245
+ type: "object",
246
+ properties: {
247
+ data: { type: "array", items: { type: "object" } },
248
+ has_more: { type: "boolean" },
249
+ },
250
+ },
251
+ riskDefault: "low",
252
+ isWrite: false,
253
+ isConnector: true,
254
+ execute: async ({ params }) => {
255
+ const { getStripeConnector } = await import("../../connectors/stripe.js");
256
+ const connector = getStripeConnector();
257
+ const result = await connector.listInvoices({
258
+ limit: typeof params.limit === "number" ? params.limit : undefined,
259
+ customerId: typeof params.customerId === "string" ? params.customerId : undefined,
260
+ status: typeof params.status === "string" ? params.status : undefined,
261
+ });
262
+ return JSON.stringify(result);
263
+ },
264
+ });
265
+ //# sourceMappingURL=stripe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripe.js","sourceRoot":"","sources":["../../../src/recipes/tools/stripe.ts"],"names":[],"mappings":"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"}
@@ -710,6 +710,34 @@ export function buildChainedDeps(runnerDeps, claudeCodeFnOverride) {
710
710
  const loadNestedRecipe = async (name) => {
711
711
  const { homedir } = await import("node:os");
712
712
  const recipesDir = path.join(homedir(), ".patchwork", "recipes");
713
+ // Check for manifest-based package directory first.
714
+ // Supports both plain names ("morning-brief") and scoped names ("@acme/morning-brief").
715
+ const pkgDirCandidates = [
716
+ path.join(recipesDir, name),
717
+ // scoped: @acme/morning-brief → recipesDir/@acme/morning-brief
718
+ ];
719
+ for (const pkgDir of pkgDirCandidates) {
720
+ try {
721
+ const { loadManifestFromDir } = await import("./manifest.js");
722
+ const manifest = loadManifestFromDir(pkgDir);
723
+ if (manifest) {
724
+ const mainPath = path.join(pkgDir, manifest.recipes.main);
725
+ try {
726
+ const raw = stepDeps.readFile(mainPath);
727
+ const { parse } = await import("yaml");
728
+ const parsed = parse(raw);
729
+ if (parsed?.steps)
730
+ return parsed;
731
+ }
732
+ catch {
733
+ // manifest found but main recipe unreadable — fall through
734
+ }
735
+ }
736
+ }
737
+ catch {
738
+ // not a manifest dir — try flat file candidates
739
+ }
740
+ }
713
741
  const candidates = [
714
742
  path.join(recipesDir, `${name}.yaml`),
715
743
  path.join(recipesDir, `${name}.yml`),