@epilot/cli 0.1.10 → 0.1.12

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 (89) hide show
  1. package/README.md +18 -21
  2. package/definitions/app.json +56 -6
  3. package/definitions/automation.json +214 -1
  4. package/definitions/blueprint-manifest.json +1303 -60
  5. package/definitions/customer-portal.json +757 -81
  6. package/definitions/data-governance.json +1126 -0
  7. package/definitions/deduplication.json +135 -4
  8. package/definitions/design.json +103 -57
  9. package/definitions/email-settings.json +150 -0
  10. package/definitions/email-template.json +25 -3
  11. package/definitions/entity.json +405 -5
  12. package/definitions/erp-integration.json +3140 -1049
  13. package/definitions/integration-toolkit.json +7998 -0
  14. package/definitions/journey.json +18 -1
  15. package/definitions/kanban.json +25 -1
  16. package/definitions/message.json +202 -0
  17. package/definitions/organization.json +35 -1
  18. package/definitions/partner-directory.json +795 -229
  19. package/definitions/permissions.json +41 -6
  20. package/definitions/sharing.json +956 -0
  21. package/definitions/template-variables.json +12 -4
  22. package/definitions/webhooks.json +111 -2
  23. package/definitions/workflow-definition.json +87 -202
  24. package/definitions/workflow.json +142 -0
  25. package/dist/{access-token-PTTCRMGK.js → access-token-CIM4RLBP.js} +1 -1
  26. package/dist/add-component-AAVQVPKK.js +296 -0
  27. package/dist/{address-2FDPEPR6.js → address-EDRTUWTP.js} +1 -1
  28. package/dist/{address-suggestions-XBEK5DDQ.js → address-suggestions-S5WEST2N.js} +1 -1
  29. package/dist/{ai-agents-ZY5BNVTN.js → ai-agents-RXDDJDAR.js} +1 -1
  30. package/dist/{app-IT5FWGUK.js → api-36XROHLK.js} +5 -5
  31. package/dist/app-I3XXHZLD.js +24 -0
  32. package/dist/{audit-logs-FB4TE4TI.js → audit-logs-PXGDGJGV.js} +1 -1
  33. package/dist/{automation-JE5LDKJM.js → automation-LS6MVLP2.js} +1 -1
  34. package/dist/{billing-GOFCP5T3.js → billing-KVYFUKZK.js} +1 -1
  35. package/dist/bin/epilot.js +53 -52
  36. package/dist/{blueprint-manifest-WJIQKFYK.js → blueprint-manifest-W4ZGJD2Z.js} +1 -1
  37. package/dist/{chunk-P5IZZW4Y.js → chunk-BYAEI4Z2.js} +1 -1
  38. package/dist/chunk-CEP7S7X3.js +366 -0
  39. package/dist/{chunk-MNSG22DM.js → chunk-F6KWKTQJ.js} +124 -63
  40. package/dist/{completion-HZNPHJI4.js → completion-QP4IYMVI.js} +1 -1
  41. package/dist/{consent-DSMWWHUL.js → consent-M4QB2HPM.js} +1 -1
  42. package/dist/{customer-portal-IJYTJYUZ.js → customer-portal-SVO2YCXA.js} +1 -1
  43. package/dist/{dashboard-DOAX6XDG.js → dashboard-CYCXIX74.js} +1 -1
  44. package/dist/{data-management-C4JPPUPD.js → data-governance-DJAAIE6F.js} +6 -6
  45. package/dist/{deduplication-7OGLZLAC.js → deduplication-M3KEVJRG.js} +1 -1
  46. package/dist/deploy-4XDFWOEV.js +214 -0
  47. package/dist/{design-3CAYTWFY.js → design-UVJJ2KO2.js} +1 -1
  48. package/dist/{document-NT5JOJQV.js → document-5HB632XE.js} +1 -1
  49. package/dist/{email-settings-2M3WJTQS.js → email-settings-H7HQTDYE.js} +1 -1
  50. package/dist/{email-template-F4PLBPPC.js → email-template-2DHZ3VKF.js} +1 -1
  51. package/dist/{entity-32LKMZAU.js → entity-HED6QHG7.js} +1 -1
  52. package/dist/{entity-mapping-OBCZDYQJ.js → entity-mapping-QP22B65Z.js} +1 -1
  53. package/dist/{environments-H3TBCDQE.js → environments-6LLEIGWV.js} +1 -1
  54. package/dist/{event-catalog-NVAPTZ4M.js → event-catalog-2ZCZTATY.js} +1 -1
  55. package/dist/export-JA5N4JCJ.js +44 -0
  56. package/dist/{file-US2HR4SV.js → file-R6IIXOIZ.js} +1 -1
  57. package/dist/{iban-7QUCOULB.js → iban-EQD2VROZ.js} +1 -1
  58. package/dist/init-5KGNJEWF.js +524 -0
  59. package/dist/integration-toolkit-4CLQDSK7.js +54 -0
  60. package/dist/{journey-E5T4BZZX.js → journey-V7X2KUKH.js} +1 -1
  61. package/dist/{kanban-7UHU5VE6.js → kanban-EPI6C3FR.js} +1 -1
  62. package/dist/{message-7KY33RJE.js → message-477EJ5JO.js} +1 -1
  63. package/dist/{metering-P7BZGMY7.js → metering-5EAEKRSL.js} +1 -1
  64. package/dist/{notes-TNJ7FPA3.js → notes-CVXNRULU.js} +1 -1
  65. package/dist/{notification-6KXEFVO5.js → notification-6HXS76XP.js} +1 -1
  66. package/dist/{organization-FF4Y3PBO.js → organization-O33CZQKD.js} +1 -1
  67. package/dist/{partner-directory-VH2SBAS2.js → partner-directory-NZWGCKSB.js} +2 -2
  68. package/dist/{permissions-KENZ4HNY.js → permissions-6QEOBJ6M.js} +1 -1
  69. package/dist/{pricing-P6QZ77VJ.js → pricing-KNYSULCW.js} +1 -1
  70. package/dist/{pricing-tier-2IRJMTM6.js → pricing-tier-OCHP6SHT.js} +1 -1
  71. package/dist/{purpose-IHROR6LQ.js → purpose-NGM42XWB.js} +1 -1
  72. package/dist/remove-component-LXSRR23E.js +89 -0
  73. package/dist/review-HFOO3NXE.js +69 -0
  74. package/dist/{sandbox-62XQPOU6.js → sandbox-YX3VVAQG.js} +1 -1
  75. package/dist/sharing-X5U53KSU.js +54 -0
  76. package/dist/{submission-PUWGOYQB.js → submission-YOWVSZNA.js} +1 -1
  77. package/dist/{targeting-QB3DFYNI.js → targeting-BMZCOG72.js} +1 -1
  78. package/dist/{template-variables-IPKRUJ4E.js → template-variables-YTABZL3E.js} +1 -1
  79. package/dist/{upgrade-TNDH4WGQ.js → upgrade-SYSSIAQC.js} +1 -1
  80. package/dist/{user-2CP75TFC.js → user-3N5ZOUYS.js} +1 -1
  81. package/dist/validate-TUMXW56Y.js +53 -0
  82. package/dist/{validation-rules-GNI4EEG5.js → validation-rules-QVS7LKEP.js} +1 -1
  83. package/dist/versions-ZTWQAGXY.js +109 -0
  84. package/dist/{webhooks-2OWUX7UL.js → webhooks-6WMWACOW.js} +1 -1
  85. package/dist/{workflow-WSLERVJI.js → workflow-ZO2MKDBS.js} +1 -1
  86. package/dist/{workflow-definition-FP3WKHGG.js → workflow-definition-RCWKIPYI.js} +1 -1
  87. package/package.json +2 -1
  88. package/definitions/data-management.json +0 -962
  89. package/dist/erp-integration-UW6H55EK.js +0 -54
@@ -1317,6 +1317,76 @@
1317
1317
  }
1318
1318
  }
1319
1319
  },
1320
+ "/v2/flows/executions/{execution_id}/tasks/{task_id}/schedule/run-now": {
1321
+ "post": {
1322
+ "operationId": "runTaskScheduleNow",
1323
+ "summary": "runTaskScheduleNow",
1324
+ "description": "Cancels the pending schedule for a task and immediately triggers its automation execution.",
1325
+ "tags": [
1326
+ "Flows V2"
1327
+ ],
1328
+ "parameters": [
1329
+ {
1330
+ "$ref": "#/components/parameters/ExecutionIdParam"
1331
+ },
1332
+ {
1333
+ "$ref": "#/components/parameters/TaskIdParam"
1334
+ }
1335
+ ],
1336
+ "responses": {
1337
+ "200": {
1338
+ "description": "Success - task automation has been triggered",
1339
+ "content": {
1340
+ "application/json": {
1341
+ "schema": {
1342
+ "$ref": "#/components/schemas/Task"
1343
+ }
1344
+ }
1345
+ }
1346
+ },
1347
+ "400": {
1348
+ "description": "Validation Errors",
1349
+ "content": {
1350
+ "application/json": {
1351
+ "schema": {
1352
+ "$ref": "#/components/schemas/ErrorResp"
1353
+ }
1354
+ }
1355
+ }
1356
+ },
1357
+ "401": {
1358
+ "description": "Authentication Errors",
1359
+ "content": {
1360
+ "application/json": {
1361
+ "schema": {
1362
+ "$ref": "#/components/schemas/ErrorResp"
1363
+ }
1364
+ }
1365
+ }
1366
+ },
1367
+ "404": {
1368
+ "description": "Not Found",
1369
+ "content": {
1370
+ "application/json": {
1371
+ "schema": {
1372
+ "$ref": "#/components/schemas/ErrorResp"
1373
+ }
1374
+ }
1375
+ }
1376
+ },
1377
+ "500": {
1378
+ "description": "Other errors",
1379
+ "content": {
1380
+ "application/json": {
1381
+ "schema": {
1382
+ "$ref": "#/components/schemas/ErrorResp"
1383
+ }
1384
+ }
1385
+ }
1386
+ }
1387
+ }
1388
+ }
1389
+ },
1320
1390
  "/v2/flows/executions/{execution_id}/schedules/{schedule_id}": {
1321
1391
  "post": {
1322
1392
  "operationId": "cancelSchedule",
@@ -1978,6 +2048,10 @@
1978
2048
  "installer": {
1979
2049
  "$ref": "#/components/schemas/ECPDetails"
1980
2050
  },
2051
+ "partner": {
2052
+ "$ref": "#/components/schemas/PartnerDetails",
2053
+ "description": "Partner-specific task details shown to partner org users viewing shared resources"
2054
+ },
1981
2055
  "enabled": {
1982
2056
  "type": "boolean"
1983
2057
  },
@@ -2030,6 +2104,10 @@
2030
2104
  "description": "The user which moved the step/task to the IN_PROGRESS state. The user should also be present in the assignedTo property of the step/task",
2031
2105
  "type": "string"
2032
2106
  },
2107
+ "assignedToOnHold": {
2108
+ "description": "The user which moved the step/task to the ON_HOLD state. The user should also be present in the assignedTo property of the step/task",
2109
+ "type": "string"
2110
+ },
2033
2111
  "status": {
2034
2112
  "$ref": "#/components/schemas/StepStatus"
2035
2113
  },
@@ -2205,6 +2283,21 @@
2205
2283
  }
2206
2284
  }
2207
2285
  },
2286
+ "PartnerDetails": {
2287
+ "type": "object",
2288
+ "description": "Details regarding partner for the workflow step",
2289
+ "properties": {
2290
+ "enabled": {
2291
+ "type": "boolean"
2292
+ },
2293
+ "label": {
2294
+ "type": "string"
2295
+ },
2296
+ "description": {
2297
+ "type": "string"
2298
+ }
2299
+ }
2300
+ },
2208
2301
  "StepDescription": {
2209
2302
  "type": "object",
2210
2303
  "description": "Longer information regarding Task",
@@ -2306,6 +2399,10 @@
2306
2399
  "description": "The user which moved the step/task to the IN_PROGRESS state. The user should also be present in the assignedTo property of the step/task",
2307
2400
  "type": "string"
2308
2401
  },
2402
+ "assignedToOnHold": {
2403
+ "description": "The user which moved the step/task to the ON_HOLD state. The user should also be present in the assignedTo property of the step/task",
2404
+ "type": "string"
2405
+ },
2309
2406
  "status": {
2310
2407
  "$ref": "#/components/schemas/StepStatus"
2311
2408
  },
@@ -2860,6 +2957,7 @@
2860
2957
  },
2861
2958
  "contexts": {
2862
2959
  "type": "array",
2960
+ "minItems": 1,
2863
2961
  "items": {
2864
2962
  "$ref": "#/components/schemas/FlowContext"
2865
2963
  }
@@ -3396,6 +3494,11 @@
3396
3494
  "$ref": "#/components/schemas/Condition"
3397
3495
  }
3398
3496
  },
3497
+ "allow_parallel_execution": {
3498
+ "type": "boolean",
3499
+ "description": "When true, all branches with met conditions execute in parallel. When false, only the first branch with a met condition is executed. Defaults to true for backwards compatibility.",
3500
+ "default": true
3501
+ },
3399
3502
  "schedule": {
3400
3503
  "anyOf": [
3401
3504
  {
@@ -3541,6 +3644,10 @@
3541
3644
  "installer": {
3542
3645
  "$ref": "#/components/schemas/ECPDetails"
3543
3646
  },
3647
+ "partner": {
3648
+ "$ref": "#/components/schemas/PartnerDetails",
3649
+ "description": "Partner-specific task details shown to partner org users viewing shared resources"
3650
+ },
3544
3651
  "taxonomies": {
3545
3652
  "type": "array",
3546
3653
  "items": {
@@ -3694,6 +3801,10 @@
3694
3801
  "skipped_by": {
3695
3802
  "$ref": "#/components/schemas/UserId",
3696
3803
  "description": "The user which moved the task/phase to SKIPPED state."
3804
+ },
3805
+ "on_hold_by": {
3806
+ "$ref": "#/components/schemas/UserId",
3807
+ "description": "The user which moved the task/phase to ON_HOLD state."
3697
3808
  }
3698
3809
  }
3699
3810
  },
@@ -3761,6 +3872,14 @@
3761
3872
  "items": {
3762
3873
  "type": "string"
3763
3874
  }
3875
+ },
3876
+ "value_type": {
3877
+ "type": "string",
3878
+ "enum": [
3879
+ "static",
3880
+ "relative_date"
3881
+ ],
3882
+ "description": "How to interpret values. \"static\" (default) means literal values. \"relative_date\" means values[0] is a dynamic date token like \"today\"."
3764
3883
  }
3765
3884
  },
3766
3885
  "required": [
@@ -3838,6 +3957,25 @@
3838
3957
  "attribute_sub_field": {
3839
3958
  "type": "string",
3840
3959
  "description": "For complex attribute types, specifies which sub-field to extract (e.g., 'address', 'name', 'email_type')"
3960
+ },
3961
+ "date_offset": {
3962
+ "type": "object",
3963
+ "description": "Offset to apply to the source date value before comparison (e.g., +18 years for age check, +30 days for expiry)",
3964
+ "properties": {
3965
+ "amount": {
3966
+ "type": "integer",
3967
+ "description": "Number of units to offset"
3968
+ },
3969
+ "unit": {
3970
+ "type": "string",
3971
+ "enum": [
3972
+ "days",
3973
+ "months",
3974
+ "years"
3975
+ ],
3976
+ "description": "Unit of the offset"
3977
+ }
3978
+ }
3841
3979
  }
3842
3980
  }
3843
3981
  },
@@ -4010,6 +4148,10 @@
4010
4148
  "installer": {
4011
4149
  "$ref": "#/components/schemas/ECPDetails"
4012
4150
  },
4151
+ "partner": {
4152
+ "$ref": "#/components/schemas/PartnerDetails",
4153
+ "description": "Partner-specific task details shown to partner org users viewing shared resources"
4154
+ },
4013
4155
  "next_condition_id": {
4014
4156
  "type": "string",
4015
4157
  "description": "Condition to evaluate as true for a decision task with a manual trigger mode"
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  callApi
4
- } from "./chunk-P5IZZW4Y.js";
4
+ } from "./chunk-BYAEI4Z2.js";
5
5
  import "./chunk-RSA7K5HB.js";
6
6
  import "./chunk-PDMWUCWD.js";
7
7
  import "./chunk-IOLKUHUB.js";
@@ -0,0 +1,296 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ log,
4
+ readManifest,
5
+ writeManifest
6
+ } from "./chunk-CEP7S7X3.js";
7
+ import "./chunk-RSA7K5HB.js";
8
+ import "./chunk-PDMWUCWD.js";
9
+ import "./chunk-7ZQ666ZQ.js";
10
+
11
+ // src/commands/app/add-component.ts
12
+ import { defineCommand } from "citty";
13
+ import { randomUUID } from "crypto";
14
+ import { existsSync, readFileSync, writeFileSync, readdirSync } from "fs";
15
+ import { resolve, join } from "path";
16
+ var TEMPLATES_REPO = "epilot-dev/app-templates";
17
+ var TEMPLATE_REGISTRY = {
18
+ CUSTOM_FLOW_ACTION_SANDBOX: {
19
+ configOnly: false,
20
+ manifestType: "CUSTOM_FLOW_ACTION",
21
+ templateDir: "custom-flow-action-sandbox",
22
+ description: "Sandboxed flow action (JS runs in epilot)",
23
+ configuration: () => ({
24
+ type: "sandbox",
25
+ sandbox_settings: { code: "// code is read from dist/ during deploy" }
26
+ })
27
+ },
28
+ CUSTOM_FLOW_ACTION_EXTERNAL: {
29
+ configOnly: true,
30
+ manifestType: "CUSTOM_FLOW_ACTION",
31
+ templateDir: "custom-flow-action-external",
32
+ description: "External integration webhook (config-only)",
33
+ configuration: () => ({
34
+ type: "external_integration",
35
+ external_integration_settings: { url: "https://api.example.com/webhook" }
36
+ }),
37
+ options: [
38
+ { key: "api_key", label: "API Key", type: "secret", required: true, description: "API key for authentication" }
39
+ ]
40
+ },
41
+ CUSTOM_CAPABILITY: {
42
+ configOnly: false,
43
+ manifestType: "CUSTOM_CAPABILITY",
44
+ templateDir: "custom-capability",
45
+ description: "Custom entity tab or group",
46
+ configuration: () => ({ type: "tab", allowed_schemas: [] }),
47
+ surfaces: (id) => ({ capability_config: { app_url: `./components/${id}/dist/index.html` } }),
48
+ assets: (id) => ({ zip: `./components/${id}/dist/` })
49
+ },
50
+ CUSTOM_JOURNEY_BLOCK: {
51
+ configOnly: false,
52
+ manifestType: "CUSTOM_JOURNEY_BLOCK",
53
+ templateDir: "custom-journey-block",
54
+ description: "Custom journey builder block",
55
+ configuration: (id) => ({
56
+ component_url: `./components/${id}/dist/bundle.js`,
57
+ component_tag: id,
58
+ component_args: []
59
+ }),
60
+ assets: (id) => ({ bundle: `./components/${id}/dist/bundle.js` })
61
+ },
62
+ CUSTOM_PAGE: {
63
+ configOnly: false,
64
+ manifestType: "CUSTOM_PAGE",
65
+ templateDir: "custom-page",
66
+ description: "Custom navigation page",
67
+ configuration: (id) => ({ slug: id, nav_label: toPascalCase(id), nav_icon: "layout" }),
68
+ surfaces: (id) => ({ page: { app_url: `./components/${id}/dist/index.html` } }),
69
+ assets: (id) => ({ zip: `./components/${id}/dist/` })
70
+ },
71
+ CUSTOM_PORTAL_BLOCK: {
72
+ configOnly: false,
73
+ manifestType: "CUSTOM_PORTAL_BLOCK",
74
+ templateDir: "custom-portal-block",
75
+ description: "Custom portal widget",
76
+ configuration: () => ({}),
77
+ surfaces: (id) => ({ portal_block: { app_url: `./components/${id}/dist/index.html` } }),
78
+ assets: (id) => ({ zip: `./components/${id}/dist/` })
79
+ },
80
+ PORTAL_EXTENSION: {
81
+ configOnly: true,
82
+ manifestType: "PORTAL_EXTENSION",
83
+ templateDir: "portal-extension",
84
+ description: "Portal extension hooks (config-only)",
85
+ configuration: () => ({
86
+ hooks: [
87
+ {
88
+ type: "registration_identifiers_check",
89
+ call: {
90
+ method: "POST",
91
+ url: "https://api.example.com/portal/register",
92
+ headers: { "x-api-key": "{{api_key}}" }
93
+ }
94
+ }
95
+ ]
96
+ }),
97
+ options: [
98
+ { key: "api_key", label: "API Key", type: "secret", required: true, description: "API key for your backend" }
99
+ ]
100
+ },
101
+ EXTERNAL_PRODUCT_CATALOG: {
102
+ configOnly: true,
103
+ manifestType: "EXTERNAL_PRODUCT_CATALOG",
104
+ templateDir: "external-product-catalog",
105
+ description: "External product catalog hooks (config-only)",
106
+ configuration: () => ({
107
+ hooks: [
108
+ {
109
+ id: "get-products",
110
+ name: { de: "Produkte abrufen", en: "Get Products" },
111
+ type: "products",
112
+ call: {
113
+ method: "POST",
114
+ url: "https://api.example.com/products",
115
+ headers: { "Content-Type": "application/json", "x-api-key": "{{api_key}}" }
116
+ }
117
+ }
118
+ ]
119
+ }),
120
+ options: [
121
+ { key: "api_key", label: "API Key", type: "secret", required: true, description: "API key for product catalog" }
122
+ ]
123
+ },
124
+ API_PROXY: {
125
+ configOnly: true,
126
+ manifestType: "API_PROXY",
127
+ templateDir: "api-proxy",
128
+ description: "Server-side API proxy with credential injection",
129
+ configuration: () => ({
130
+ name: "",
131
+ target: "",
132
+ auth_type: "none"
133
+ })
134
+ }
135
+ };
136
+ var AVAILABLE_TYPES = Object.keys(TEMPLATE_REGISTRY);
137
+ function toPascalCase(str) {
138
+ return str.replace(/(^|[-_])([a-z])/g, (_, __, c) => c.toUpperCase());
139
+ }
140
+ async function downloadTemplate(templateDir, targetDir, componentName) {
141
+ const { downloadTemplate: giget } = await import("giget");
142
+ await giget(`github:${TEMPLATES_REPO}/${templateDir}`, {
143
+ dir: targetDir,
144
+ force: true
145
+ });
146
+ replaceInDir(targetDir, "{{name}}", componentName);
147
+ }
148
+ function replaceInDir(dir, search, replace) {
149
+ const entries = readdirSync(dir, { withFileTypes: true });
150
+ for (const entry of entries) {
151
+ const fullPath = join(dir, entry.name);
152
+ if (entry.isDirectory()) {
153
+ if (entry.name === "node_modules" || entry.name === ".git") continue;
154
+ replaceInDir(fullPath, search, replace);
155
+ } else {
156
+ try {
157
+ const content = readFileSync(fullPath, "utf-8");
158
+ if (content.includes(search)) {
159
+ writeFileSync(fullPath, content.replaceAll(search, replace));
160
+ }
161
+ } catch {
162
+ }
163
+ }
164
+ }
165
+ }
166
+ var add_component_default = defineCommand({
167
+ meta: { name: "add-component", description: "Add a new component to the app" },
168
+ args: {
169
+ name: { type: "positional", description: "Component name", required: false },
170
+ type: { type: "string", alias: "t", description: "Component type" },
171
+ path: { type: "string", description: "Path to manifest.json (default: manifest.json)" }
172
+ },
173
+ run: async ({ args }) => {
174
+ let componentType = args.type;
175
+ if (!componentType) {
176
+ const { select } = await import("@inquirer/prompts");
177
+ componentType = await select({
178
+ message: "Select component type",
179
+ choices: AVAILABLE_TYPES.map((type) => ({
180
+ value: type,
181
+ name: `${type} \u2014 ${TEMPLATE_REGISTRY[type].description}`
182
+ }))
183
+ });
184
+ }
185
+ if (!AVAILABLE_TYPES.includes(componentType)) {
186
+ log.error(`Invalid component type: ${componentType}`);
187
+ log.info("");
188
+ log.info("Available types:");
189
+ for (const type of AVAILABLE_TYPES) {
190
+ log.info(` ${type} \u2014 ${TEMPLATE_REGISTRY[type].description}`);
191
+ }
192
+ process.exit(1);
193
+ }
194
+ let componentName = args.name;
195
+ if (!componentName) {
196
+ const { input } = await import("@inquirer/prompts");
197
+ componentName = await input({
198
+ message: "Component name",
199
+ validate: (v) => {
200
+ if (!v.trim()) return "Name is required";
201
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(v)) return "Use lowercase letters, numbers, and hyphens";
202
+ return true;
203
+ }
204
+ });
205
+ }
206
+ const manifestPath = resolve(args.path ?? "manifest.json");
207
+ if (!existsSync(manifestPath)) {
208
+ log.error('manifest.json not found. Run "epilot app init" first.');
209
+ process.exit(1);
210
+ }
211
+ const manifest = readManifest(manifestPath);
212
+ const tmpl = TEMPLATE_REGISTRY[componentType];
213
+ const isApiProxy = componentType === "API_PROXY";
214
+ if (!isApiProxy && manifest.components.some((c) => c._dir === componentName)) {
215
+ log.error(`Component "${componentName}" already exists in manifest.`);
216
+ process.exit(1);
217
+ }
218
+ let proxyConfig;
219
+ if (isApiProxy) {
220
+ const { input, select } = await import("@inquirer/prompts");
221
+ const proxyName = await input({
222
+ message: "Proxy name (SDK identifier)",
223
+ default: componentName,
224
+ validate: (v) => {
225
+ if (!v.trim()) return "Name is required";
226
+ if (!/^[a-zA-Z0-9_-]+$/.test(v)) return "Use letters, numbers, hyphens, and underscores";
227
+ if (v.length > 64) return "Max 64 characters";
228
+ return true;
229
+ }
230
+ });
231
+ const target = await input({
232
+ message: "Target URL (must start with https://)",
233
+ validate: (v) => {
234
+ if (!v.trim()) return "Target URL is required";
235
+ if (!v.startsWith("https://")) return "Must start with https://";
236
+ try {
237
+ new URL(v);
238
+ return true;
239
+ } catch {
240
+ return "Must be a valid URL";
241
+ }
242
+ }
243
+ });
244
+ const authType = await select({
245
+ message: "Auth type",
246
+ choices: [
247
+ { value: "none", name: "none" },
248
+ { value: "header", name: "header" },
249
+ { value: "bearer", name: "bearer" },
250
+ { value: "oauth2", name: "oauth2" }
251
+ ]
252
+ });
253
+ proxyConfig = { name: proxyName, target, auth_type: authType };
254
+ } else {
255
+ const componentDir = resolve("components", componentName);
256
+ if (existsSync(componentDir)) {
257
+ log.error(`Directory "components/${componentName}" already exists.`);
258
+ process.exit(1);
259
+ }
260
+ log.dim(`Downloading template from ${TEMPLATES_REPO}/${tmpl.templateDir}...`);
261
+ await downloadTemplate(tmpl.templateDir, componentDir, componentName);
262
+ }
263
+ const componentId = randomUUID();
264
+ const configuration = proxyConfig ? { name: proxyConfig.name, target: proxyConfig.target, auth_type: proxyConfig.auth_type } : tmpl.configuration(componentName);
265
+ const component = {
266
+ id: componentId,
267
+ component_type: tmpl.manifestType,
268
+ ...isApiProxy ? {} : { _dir: componentName },
269
+ name: { de: toPascalCase(componentName), en: toPascalCase(componentName) },
270
+ description: { de: "Description", en: "Description" },
271
+ configuration
272
+ };
273
+ if (tmpl.surfaces) component.surfaces = tmpl.surfaces(componentName);
274
+ if (tmpl.assets) component.assets = tmpl.assets(componentName);
275
+ if (tmpl.options) component.options = tmpl.options;
276
+ manifest.components.push(component);
277
+ writeManifest(manifestPath, manifest);
278
+ log.success(`Added component "${componentName}" (${componentType})`);
279
+ log.info("");
280
+ if (isApiProxy) {
281
+ log.info(` Proxy: ${proxyConfig.name} -> ${proxyConfig.target} (auth: ${proxyConfig.auth_type})`);
282
+ log.dim("Add secret options to the component manually if needed.");
283
+ } else if (tmpl.configOnly) {
284
+ log.info(` components/${componentName}/`);
285
+ log.dim("This is a config-only component. Edit configuration.json to configure it.");
286
+ } else {
287
+ log.info(` components/${componentName}/`);
288
+ log.dim('Run "npm install" to link the new workspace.');
289
+ }
290
+ log.info("");
291
+ log.info(`manifest.json updated (${manifest.components.length} component(s))`);
292
+ }
293
+ });
294
+ export {
295
+ add_component_default as default
296
+ };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  callApi
4
- } from "./chunk-P5IZZW4Y.js";
4
+ } from "./chunk-BYAEI4Z2.js";
5
5
  import "./chunk-RSA7K5HB.js";
6
6
  import "./chunk-PDMWUCWD.js";
7
7
  import "./chunk-IOLKUHUB.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  callApi
4
- } from "./chunk-P5IZZW4Y.js";
4
+ } from "./chunk-BYAEI4Z2.js";
5
5
  import "./chunk-RSA7K5HB.js";
6
6
  import "./chunk-PDMWUCWD.js";
7
7
  import "./chunk-IOLKUHUB.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  callApi
4
- } from "./chunk-P5IZZW4Y.js";
4
+ } from "./chunk-BYAEI4Z2.js";
5
5
  import "./chunk-RSA7K5HB.js";
6
6
  import "./chunk-PDMWUCWD.js";
7
7
  import "./chunk-IOLKUHUB.js";
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  callApi
4
- } from "./chunk-P5IZZW4Y.js";
4
+ } from "./chunk-BYAEI4Z2.js";
5
5
  import "./chunk-RSA7K5HB.js";
6
6
  import "./chunk-PDMWUCWD.js";
7
7
  import "./chunk-IOLKUHUB.js";
8
8
  import "./chunk-7ZQ666ZQ.js";
9
9
 
10
- // src/commands/apis/app.ts
10
+ // src/commands/app/api.ts
11
11
  import { defineCommand } from "citty";
12
- var app_default = defineCommand({
13
- meta: { name: "app", description: "App API" },
12
+ var api_default = defineCommand({
13
+ meta: { name: "api", description: "Call raw App API operations (OpenAPI)" },
14
14
  args: {
15
15
  operation: { type: "positional", description: "operationId to call", required: false },
16
16
  param: { type: "string", alias: "p", description: "Parameter key=value" },
@@ -50,5 +50,5 @@ var app_default = defineCommand({
50
50
  }
51
51
  });
52
52
  export {
53
- app_default as default
53
+ api_default as default
54
54
  };
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/commands/app/index.ts
4
+ import { defineCommand } from "citty";
5
+ var app_default = defineCommand({
6
+ meta: {
7
+ name: "app",
8
+ description: "Manage epilot Apps \u2014 create, deploy, and manage app manifests"
9
+ },
10
+ subCommands: {
11
+ init: () => import("./init-5KGNJEWF.js").then((m) => m.default),
12
+ "add-component": () => import("./add-component-AAVQVPKK.js").then((m) => m.default),
13
+ "remove-component": () => import("./remove-component-LXSRR23E.js").then((m) => m.default),
14
+ validate: () => import("./validate-TUMXW56Y.js").then((m) => m.default),
15
+ deploy: () => import("./deploy-4XDFWOEV.js").then((m) => m.default),
16
+ export: () => import("./export-JA5N4JCJ.js").then((m) => m.default),
17
+ versions: () => import("./versions-ZTWQAGXY.js").then((m) => m.default),
18
+ review: () => import("./review-HFOO3NXE.js").then((m) => m.default),
19
+ api: () => import("./api-36XROHLK.js").then((m) => m.default)
20
+ }
21
+ });
22
+ export {
23
+ app_default as default
24
+ };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  callApi
4
- } from "./chunk-P5IZZW4Y.js";
4
+ } from "./chunk-BYAEI4Z2.js";
5
5
  import "./chunk-RSA7K5HB.js";
6
6
  import "./chunk-PDMWUCWD.js";
7
7
  import "./chunk-IOLKUHUB.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  callApi
4
- } from "./chunk-P5IZZW4Y.js";
4
+ } from "./chunk-BYAEI4Z2.js";
5
5
  import "./chunk-RSA7K5HB.js";
6
6
  import "./chunk-PDMWUCWD.js";
7
7
  import "./chunk-IOLKUHUB.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  callApi
4
- } from "./chunk-P5IZZW4Y.js";
4
+ } from "./chunk-BYAEI4Z2.js";
5
5
  import "./chunk-RSA7K5HB.js";
6
6
  import "./chunk-PDMWUCWD.js";
7
7
  import "./chunk-IOLKUHUB.js";