@keystrokehq/cli 0.0.1 → 0.0.2

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 (151) hide show
  1. package/AGENTS-blurb.md +1 -1
  2. package/LICENSE +0 -21
  3. package/README.md +14 -6
  4. package/dist/accept.handler-DFtM0IuO.mjs +22 -0
  5. package/dist/admin-D_7tenRC.mjs +208 -0
  6. package/dist/{agent-manifest-CDnbkR2f.mjs → agent-manifest-Bfa3DBgc.mjs} +4 -4
  7. package/dist/{agents-CZJGxVqV.mjs → agents-DMEo-6QB.mjs} +8 -8
  8. package/dist/api-keys-BThGvtdn.mjs +58 -0
  9. package/dist/{auth-DN2VusyU.mjs → auth-Byry35LJ.mjs} +7 -11
  10. package/dist/{auth.handler-CT1BQUvu.mjs → auth.handler-BBPObKwk.mjs} +5 -5
  11. package/dist/{build-agents-BmM_AsSd-BGi9wtzt.mjs → build-agents-DfbiMZ_e-CRnzruSu.mjs} +7 -7
  12. package/dist/{build-metadata-BWS7uhd_-DR8gJjTX.mjs → build-metadata-zidV9Cai-RgG4ndIH.mjs} +11 -11
  13. package/dist/{build-progress-DgYKb4hB.mjs → build-progress-Cn2j1LqF.mjs} +1 -1
  14. package/dist/{build-tasks-CdihpudT-D5r5HUHe.mjs → build-tasks-O1jYtlv1-Y65uGWuz.mjs} +4 -5
  15. package/dist/{build-workflows-CfxBnIWh-CdYPv8w2.mjs → build-workflows-3fdvdHHf-DJ_lH1NH.mjs} +9 -9
  16. package/dist/{build.handler-4799CjWH.mjs → build.handler-Tb3IpABI.mjs} +5 -5
  17. package/dist/{clear-cache.handler-B9tqSoSM.mjs → clear-cache.handler-BEbPz5Ej.mjs} +1 -1
  18. package/dist/{clear.handler-BydlX-zE.mjs → clear.handler-CtOZ4aRn.mjs} +1 -1
  19. package/dist/{clear.handler-BTIXXPTJ.mjs → clear.handler-YS8gPriq.mjs} +2 -2
  20. package/dist/{commander-DfTVqQ-3.mjs → commander-DZ3F3CVq.mjs} +6 -5
  21. package/dist/common-BrVAdUyD.mjs +20 -0
  22. package/dist/{connect-BUXkeH0F.mjs → connect-DpQgYg8z.mjs} +3 -3
  23. package/dist/{connect.handler-CYel9cy6.mjs → connect.handler-DuRr_yyN.mjs} +5 -5
  24. package/dist/{context-T7HZuB97.mjs → context-Y1f1hGYy.mjs} +7 -7
  25. package/dist/create.handler-uNG3I4wS.mjs +24 -0
  26. package/dist/credential-requirements-DjDFthio.mjs +480 -0
  27. package/dist/{credential-schema-mismatch-BKo5PjcQ.mjs → credential-schema-mismatch-B-wwbCvw.mjs} +2 -2
  28. package/dist/{credentials-OfVHOtG3.mjs → credentials-DHlK_O4L.mjs} +823 -14
  29. package/dist/{credentials-CvmjU0lK.mjs → credentials-UpgEcaub.mjs} +7 -7
  30. package/dist/{current-deployment-workflow-poHt27i3.mjs → current-deployment-workflow-M8GEIHxv.mjs} +5 -5
  31. package/dist/{current.handler-B8zKzfPp.mjs → current.handler-BqPUKCvn.mjs} +1 -1
  32. package/dist/declared-credential-requirements-Bwlb-KZE.mjs +132 -0
  33. package/dist/default-urls-BS4twrsS.mjs +7 -0
  34. package/dist/{delete.handler-bAu1iXVQ.mjs → delete.handler-CJTHVZaz.mjs} +1 -1
  35. package/dist/{deploy-7Jjls436.mjs → deploy-CdnaZY3s.mjs} +1 -1
  36. package/dist/{deploy-BOPIpRWm.mjs → deploy-Gw0KPrkf.mjs} +2 -2
  37. package/dist/{deploy-progress-BmGUNFKg.mjs → deploy-progress-CZ2rPlOj.mjs} +1 -1
  38. package/dist/{deploy.handler-BAzgiNhd.mjs → deploy.handler-zzFAt7pp.mjs} +18 -18
  39. package/dist/{detect-env-access-CwkOYeYM-D_BCZqV6.mjs → detect-env-access-CwkOYeYM-h2W05D_Q.mjs} +1 -1
  40. package/dist/{diff.handler-Du7SY8K4.mjs → diff.handler--zdSkUnK.mjs} +5 -5
  41. package/dist/{dist-CUK7yBM0.mjs → dist-BF6r1hfv.mjs} +3 -3
  42. package/dist/{dist-BkJUoBiG.mjs → dist-C2Dq_nx3.mjs} +12 -12
  43. package/dist/{env-91KwMKov.mjs → env-YTZGKGIu.mjs} +9 -10
  44. package/dist/{env.handler-BAzBuMzQ.mjs → env.handler-d4sJ706C.mjs} +8 -8
  45. package/dist/{error-boundary-VL-JLfIa.mjs → error-boundary-B9PgBkv8.mjs} +2 -2
  46. package/dist/{file-metadata-D1vm-XY2.mjs → file-metadata-CdFXMMIw.mjs} +1 -1
  47. package/dist/hosted-action-dispatcher-registry-TOVzMhUR.mjs +126 -0
  48. package/dist/iam-command-utils-CNC8JfZ5.mjs +72 -0
  49. package/dist/{import-module-CV84H5fZ-B_CBCmb4.mjs → import-module-DDPnzlJ1-CYJD2n2b.mjs} +395 -10
  50. package/dist/{init-DpMCotSK.mjs → init-C0sps8R7.mjs} +2 -2
  51. package/dist/{init.handler-CPRnif52.mjs → init.handler-DSW6XFZn.mjs} +17 -17
  52. package/dist/{inspect.handler-DT_cD036.mjs → inspect.handler-DbN0ZVTh.mjs} +5 -5
  53. package/dist/{integration-catalog-Bt-L3GjF.mjs → integration-catalog-DFlytKJS.mjs} +2 -2
  54. package/dist/{integrations-DlatPK4W.mjs → integrations-Dcadds2b.mjs} +5 -5
  55. package/dist/invites-DvsxTRAb.mjs +44 -0
  56. package/dist/invites.list.handler-B5quln3m.mjs +43 -0
  57. package/dist/invites.resend.handler-CSpj7bQ5.mjs +23 -0
  58. package/dist/invites.revoke.handler-_hdEkBdO.mjs +28 -0
  59. package/dist/keystroke.mjs +31 -22
  60. package/dist/{list-enrichment-y-cwizLr.mjs → list-enrichment-CTqx0Rk_.mjs} +1 -1
  61. package/dist/{list.handler-CWF_Dj15.mjs → list.handler-08GY-wnx.mjs} +1 -1
  62. package/dist/{list.handler-DWaQkJaR.mjs → list.handler-20v4uRMk.mjs} +2 -2
  63. package/dist/{list.handler-BTWvCyjA.mjs → list.handler-BRq-nScx.mjs} +5 -5
  64. package/dist/{list.handler-lq3ZGAn4.mjs → list.handler-CWO6DExh.mjs} +3 -3
  65. package/dist/{list.handler-CZ6G2x_G.mjs → list.handler-DAiJtW20.mjs} +3 -3
  66. package/dist/list.handler-DLl8ca6F.mjs +42 -0
  67. package/dist/{list.handler-DqbFcBW7.mjs → list.handler-DSPr0OxS.mjs} +7 -7
  68. package/dist/{logs-BEg9L5l8.mjs → logs-D_48skmi.mjs} +3 -3
  69. package/dist/{logs.handler-BD_dXiL1.mjs → logs.handler-4ctMVYMj.mjs} +3 -3
  70. package/dist/{logs.handler-6hoMBzqw.mjs → logs.handler-C3QnSCaH.mjs} +1 -1
  71. package/dist/members.add.handler-Dq_giQ8g.mjs +31 -0
  72. package/dist/members.invite.handler-v404bUsq.mjs +32 -0
  73. package/dist/members.list.handler-D6TE0yp8.mjs +43 -0
  74. package/dist/members.remove.handler-BhQ3cyeR.mjs +28 -0
  75. package/dist/members.update.handler-BVy2cv1K.mjs +28 -0
  76. package/dist/{metadata-layout-GUYIUo0i-_aG2zjue.mjs → metadata-layout-C6ed-9dl-aBmqqvD5.mjs} +2 -2
  77. package/dist/{normalize-path-CojS-CgQ-DLCOvnD1.mjs → normalize-path-CojS-CgQ-BKRFUzWW.mjs} +1 -1
  78. package/dist/org-CkRr-f3S.mjs +234 -0
  79. package/dist/orgs.create.handler-swGnT2ce.mjs +26 -0
  80. package/dist/orgs.get.handler-ClAqYTH0.mjs +28 -0
  81. package/dist/orgs.list.handler-D-ptz8It.mjs +41 -0
  82. package/dist/{paused.handler-BMFm9Cff.mjs → paused.handler-B3aVqw-m.mjs} +2 -2
  83. package/dist/{project-config-D1qsQlO7.mjs → project-config-opj6DsPF.mjs} +2 -2
  84. package/dist/{projects-CHkRE9rS.mjs → projects-Bdl6-Z8l.mjs} +2 -2
  85. package/dist/{projects-Cjb7sovS.mjs → projects-yA9AAaDM.mjs} +5 -5
  86. package/dist/{register.handler-BPCdor1_.mjs → register.handler-WzpvVXHx.mjs} +1 -1
  87. package/dist/{requirements.handler-DPXdSks3.mjs → requirements.handler-coArDE8x.mjs} +7 -7
  88. package/dist/{resolve-project-DDJ29sCF.mjs → resolve-project-DgfftdPm.mjs} +2 -2
  89. package/dist/{runs-D9hNLb9A.mjs → runs-B8mW4PqP.mjs} +3 -3
  90. package/dist/schedule-BRN4hzQM.mjs +505 -0
  91. package/dist/schema-_FQrHcIS.mjs +17 -0
  92. package/dist/schema-kbMHVnhm.mjs +81 -0
  93. package/dist/schemas-DsvCZfF0.mjs +42 -0
  94. package/dist/{skills-sync.handler-DIy8GR16.mjs → skills-sync.handler-C2faeat-.mjs} +2 -2
  95. package/dist/{skills.command-CrjI2dN9.mjs → skills.command-DWxcc3Ui.mjs} +4 -4
  96. package/dist/source-analysis-BspLa3E5.mjs +75 -0
  97. package/dist/{source-analysis-Cj-ADyu--BJQcFPCG.mjs → source-analysis-DEEChuND-eixwPnPP.mjs} +5 -5
  98. package/dist/{src-eHwu-Gfw.mjs → src-J09NGJ6Z.mjs} +42 -6
  99. package/dist/{switch.handler-D_9213Vf.mjs → switch.handler-C4hgbhcH.mjs} +2 -2
  100. package/dist/{sync-BL_Mo5st.mjs → sync-CL6zXiiA.mjs} +2 -2
  101. package/dist/{sync.handler-BUFPdzWz.mjs → sync.handler-D1uF8E8I.mjs} +8 -8
  102. package/dist/{schemas-CDib1RhE.mjs → task-DsrXI6XH.mjs} +10 -39
  103. package/dist/{task-target-build-CBeCKbu2.mjs → task-target-build-DTzz4fpG.mjs} +4 -4
  104. package/dist/task-target-deploy-BPLlP__P.mjs +4 -0
  105. package/dist/{task-target-deploy-CA6elFpF-BEr4gkol.mjs → task-target-deploy-Bf5i3ox1-BU16VPsE.mjs} +2 -3
  106. package/dist/task-target-deploy-runner.mjs +15 -14
  107. package/dist/{test-BHTgR3UA.mjs → test-BsTLXIPB.mjs} +31 -31
  108. package/dist/{test.handler-BcPQ8b74.mjs → test.handler-D25kziPi.mjs} +1 -1
  109. package/dist/{trigger-artifacts-DQPbQNqC-B4yeeFBY.mjs → trigger-artifacts-B3OCTX9K-DG-FGGJT.mjs} +5 -5
  110. package/dist/{trigger-manifest-CY7brZeg.mjs → trigger-manifest-CXD9I7Rb.mjs} +1 -2
  111. package/dist/{try-deploy.handler-DqybNhXx.mjs → try-deploy.handler-2aX5TmLk.mjs} +11 -11
  112. package/dist/{upload.handler-DCtiznQp.mjs → upload.handler-CqProKVJ.mjs} +10 -10
  113. package/dist/users.get.handler-C_d2GWKX.mjs +24 -0
  114. package/dist/users.list.handler-DXAsO8Yk.mjs +36 -0
  115. package/dist/users.set-role.handler-Bn_yV4RI.mjs +27 -0
  116. package/dist/{utils-CywxCDM7.mjs → utils-DlYHjGg9.mjs} +2 -2
  117. package/dist/{validate.handler-DOcTaJL0.mjs → validate.handler-CGD6GttR.mjs} +5 -5
  118. package/dist/{workflow-build-DBQaBfnn.mjs → workflow-build-BcaIdRR6.mjs} +22 -45
  119. package/dist/{workflow-bundler-BPiqVscj-X1PFFAuP.mjs → workflow-bundler-BzHk73PM-Cde7cKiU.mjs} +4 -4
  120. package/dist/{_manifest-JSRE3H8k.mjs → workflow-manifest-CAW5FlX0.mjs} +7 -131
  121. package/dist/{workflows-g9z87AJJ.mjs → workflows-S-gbfw8f.mjs} +16 -15
  122. package/dist/{writer-BG8poUm3-BbXlU2kI.mjs → writer-CtvttJdP-DrJruQgR.mjs} +8 -8
  123. package/package.json +9 -11
  124. package/THIRD_PARTY_NOTICES.md +0 -16
  125. package/dist/api-keys-D2lgguuY.mjs +0 -40
  126. package/dist/org-xLzBtt2_.mjs +0 -41
  127. package/dist/schedule-BXx3uXwr.mjs +0 -1142
  128. package/dist/src-C0X6u_Mw.mjs +0 -1340
  129. package/dist/task-B2sZMaZu.mjs +0 -8
  130. package/dist/task-target-deploy-C5X-USeR.mjs +0 -4
  131. /package/dist/{agent-bundle-package-DWV6B_5q-BtV7Xycc.mjs → agent-bundle-package-DWV6B_5q-FPT0bJaA.mjs} +0 -0
  132. /package/dist/{browser-qwFrUH82.mjs → browser-gddMccBQ.mjs} +0 -0
  133. /package/dist/{concurrency-gXn9Rw8x-DNl2YtrS.mjs → concurrency-gXn9Rw8x-BTlfau8D.mjs} +0 -0
  134. /package/dist/{constants-CPpPdSNg.mjs → constants-DHdiT5hc.mjs} +0 -0
  135. /package/dist/{credential-env-map-CI8yWHVy.mjs → credential-env-map-C8P7uTD-.mjs} +0 -0
  136. /package/dist/{diff-utils-NEfcjqxt.mjs → diff-utils-DWNcRA8g.mjs} +0 -0
  137. /package/dist/{get-intrinsic-zLxwtrLK.mjs → get-intrinsic-ZMBBjBEr.mjs} +0 -0
  138. /package/dist/{layout-CbMtQ2tm.mjs → layout-B95Tku8F.mjs} +0 -0
  139. /package/dist/{options-CeaTcFxP.mjs → options-Dn9t3K4a.mjs} +0 -0
  140. /package/dist/{output-DM4b7KgY.mjs → output-q4KljAhu.mjs} +0 -0
  141. /package/dist/{oxc-B3KI3rf_-n9d1hKNq.mjs → oxc-B3KI3rf_-BeimiQ2U.mjs} +0 -0
  142. /package/dist/{read-credential-keys-77a91T8M-KA0Iw0Z1.mjs → read-credential-keys-77a91T8M-CAJLnMRi.mjs} +0 -0
  143. /package/dist/{rolldown-runtime-twds-ZHy-BWWzu8VG.mjs → rolldown-runtime-twds-ZHy-8uqgIurC.mjs} +0 -0
  144. /package/dist/{run-polling-CAgFRdK3.mjs → run-polling-CTzhTgyN.mjs} +0 -0
  145. /package/dist/{schema-17qMfNyI.mjs → schema-Di90TXoX.mjs} +0 -0
  146. /package/dist/{schema-display-CgmeKigW.mjs → schema-display-D4A1gQEM.mjs} +0 -0
  147. /package/dist/{skills.handler-Bz8bJKql.mjs → skills.handler-8KCSF7wp.mjs} +0 -0
  148. /package/dist/{spinner-progress-DMVwgqO9.mjs → spinner-progress-bvKd1jXc.mjs} +0 -0
  149. /package/dist/{status.handler-BO4nwvWn.mjs → status.handler-D9GBEmao.mjs} +0 -0
  150. /package/dist/{sync-keystroke-agent-skills-Kx_H7UTd.mjs → sync-keystroke-agent-skills-CY9h25_5.mjs} +0 -0
  151. /package/dist/{upload-CkU--iDC.mjs → upload-B8fiWveA.mjs} +0 -0
@@ -1,16 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { i as __toESM, n as __exportAll$1, r as __require, t as __commonJSMin$1 } from "./chunk-CH6r78ws.mjs";
4
- import { g as collectCredentialRequirementEntries } from "./schedule-BXx3uXwr.mjs";
5
- import "./_manifest-JSRE3H8k.mjs";
6
- import { i as Operation, p as CredentialSet, v as registerOfficialIntegrationOperation } from "./src-C0X6u_Mw.mjs";
7
- import { a as require_type, i as require_shams$1, n as require_hasown, t as require_get_intrinsic } from "./get-intrinsic-zLxwtrLK.mjs";
4
+ import { n as RetryConfigSchema } from "./common-BrVAdUyD.mjs";
5
+ import { d as schemaToJsonSchema, f as trimmedNonEmptyString, i as descriptionString, m as validateConfig, n as createStructuralSchema, o as jsonSchemaObject, t as anyZodSchemaSchema } from "./schema-kbMHVnhm.mjs";
6
+ import { _ as CREDENTIAL_VISIBILITIES, f as collectCredentialRequirementEntries, g as CREDENTIAL_KINDS, h as credentialSetConfigSchema, m as CredentialSetManifestSchema } from "./credential-requirements-DjDFthio.mjs";
7
+ import { r as toDeclaredCredentialRequirements } from "./declared-credential-requirements-Bwlb-KZE.mjs";
8
+ import { i as parseDurationToMs, t as DurationSchema } from "./schedule-BRN4hzQM.mjs";
9
+ import { _ as registerOfficialIntegrationOperation, d as getRegisteredOperationContext, g as getOfficialIntegrationMetadata, i as getRegisteredHostedActionDispatcher, l as resolveRegisteredOperationCredentials, m as getRegisteredRuntime, r as getHostedActionExecutionPolicy } from "./hosted-action-dispatcher-registry-TOVzMhUR.mjs";
10
+ import { a as require_type, i as require_shams$1, n as require_hasown, t as require_get_intrinsic } from "./get-intrinsic-ZMBBjBEr.mjs";
8
11
  import { readFile } from "node:fs/promises";
9
12
  import { ZodType, z } from "zod";
10
13
  import { createHmac, timingSafeEqual } from "node:crypto";
11
14
  import { EventEmitter } from "events";
12
15
  import util from "util";
13
16
  import stream, { Readable } from "stream";
17
+ import { AsyncLocalStorage } from "node:async_hooks";
14
18
  import https from "https";
15
19
  import process$1 from "process";
16
20
  import crypto$1 from "crypto";
@@ -20,7 +24,812 @@ import url from "url";
20
24
  import zlib from "zlib";
21
25
  import { ZodFirstPartyTypeKind } from "zod/v3";
22
26
  import http2 from "http2";
23
- //#region ../../packages/workflow-core/src/errors/credential-revoked-error.ts
27
+ //#region ../../packages/core/src/internal/runtime-call-interceptor.ts
28
+ const ASYNC_STORAGE_KEY = "__ks_runtime_call_interceptor_async_storage";
29
+ const STACK_KEY = "__ks_runtime_call_interceptor_stack";
30
+ function getAsyncStorage() {
31
+ const g = globalThis;
32
+ if (ASYNC_STORAGE_KEY in g) return g[ASYNC_STORAGE_KEY];
33
+ const AsyncLocalStorage = g.process?.getBuiltinModule?.("async_hooks")?.AsyncLocalStorage;
34
+ const storage = AsyncLocalStorage ? new AsyncLocalStorage() : void 0;
35
+ g[ASYNC_STORAGE_KEY] = storage;
36
+ return storage;
37
+ }
38
+ function getStack() {
39
+ const g = globalThis;
40
+ if (!g[STACK_KEY]) g[STACK_KEY] = [];
41
+ return g[STACK_KEY];
42
+ }
43
+ function getActiveRuntimeCallInterceptor() {
44
+ const asyncStorage = getAsyncStorage();
45
+ if (asyncStorage) return asyncStorage.getStore()?.at(-1);
46
+ const stack = getStack();
47
+ return stack.length > 0 ? stack[stack.length - 1] : void 0;
48
+ }
49
+ //#endregion
50
+ //#region ../../packages/core/src/shared/primitive.ts
51
+ /**
52
+ * Base class for all Keystroke primitives. The `kind` discriminator lets
53
+ * downstream code narrow primitive unions (e.g. `AnyAgentToolEntry =
54
+ * AnyOperation | AnyWorkflow`) without resorting to structural `'x' in tool`
55
+ * checks. Each subclass declares a literal `kind` matching its identity.
56
+ */
57
+ var Primitive = class {};
58
+ //#endregion
59
+ //#region ../../packages/core/src/credential-set/zod-shape.ts
60
+ /**
61
+ * Shape-reflection helpers for `CredentialSet` schemas.
62
+ *
63
+ * Shared between the `CredentialSet` constructor (which memoizes the key
64
+ * lists onto the instance) and the construction-time identity registry
65
+ * (which hashes the same shape into a fingerprint). Kept in its own
66
+ * module to avoid an import cycle between `CredentialSet.ts` and
67
+ * `registry.ts`.
68
+ */
69
+ /**
70
+ * Inspect a `z.ZodObject` once and return its sorted property keys plus the
71
+ * subset wrapped in `.optional()` / `.default()`.
72
+ *
73
+ * Tolerates both the Zod v3 `.shape` getter and the Zod v4 `_def.shape`
74
+ * thunk so the helper stays stable across schema versions.
75
+ */
76
+ function readZodObjectKeyMetadata(schema) {
77
+ const resolvedShape = resolveZodObjectShape(schema);
78
+ if (resolvedShape === null || typeof resolvedShape !== "object") return {
79
+ all: [],
80
+ optional: []
81
+ };
82
+ const entries = Object.entries(resolvedShape);
83
+ return {
84
+ all: entries.map(([key]) => key).sort(),
85
+ optional: entries.filter(([, field]) => field instanceof z.ZodOptional || field instanceof z.ZodDefault).map(([key]) => key).sort()
86
+ };
87
+ }
88
+ /**
89
+ * Resolve the raw shape record of a `z.ZodObject` tolerating v3 and v4
90
+ * internal layouts. Returns `null` when the object cannot be reflected.
91
+ */
92
+ function resolveZodObjectShape(schema) {
93
+ const internals = schema;
94
+ const rawShape = internals._def?.shape ?? internals.shape;
95
+ const resolved = typeof rawShape === "function" ? rawShape() : rawShape;
96
+ if (resolved === null || typeof resolved !== "object") return null;
97
+ return resolved;
98
+ }
99
+ //#endregion
100
+ //#region ../../packages/core/src/credential-set/registry.ts
101
+ /**
102
+ * The backing map is keyed on `globalThis` under a well-known
103
+ * `Symbol.for(...)` so (a) multiple bundles/subpaths of this package share
104
+ * a single registry instance at runtime and (b) host-side test harnesses
105
+ * that cannot take a direct dependency on `@keystrokehq/core`
106
+ * (e.g. `@keystroke/test-utils`, which would otherwise form a cycle
107
+ * through `@keystroke/local-memory`) can still drive the reset hook by
108
+ * clearing the same `Map` via the exported {@link CREDENTIAL_SET_REGISTRY_SYMBOL}.
109
+ */
110
+ const CREDENTIAL_SET_REGISTRY_SYMBOL = Symbol.for("@keystrokehq/core/credential-set-registry");
111
+ function getRegistry$1() {
112
+ const globalWithRegistry = globalThis;
113
+ const existing = globalWithRegistry[CREDENTIAL_SET_REGISTRY_SYMBOL];
114
+ if (existing) return existing;
115
+ const fresh = /* @__PURE__ */ new Map();
116
+ globalWithRegistry[CREDENTIAL_SET_REGISTRY_SYMBOL] = fresh;
117
+ return fresh;
118
+ }
119
+ /**
120
+ * Thrown when two `CredentialSet` instances share the same
121
+ * `resolvedCredentialSetId` but declare different shapes.
122
+ *
123
+ * @example
124
+ * ```ts
125
+ * new CredentialSet({ id: 'stripe', auth: z.object({ STRIPE_SECRET_KEY: z.string() }) });
126
+ * // later, in a maintenance script:
127
+ * new CredentialSet({ id: 'stripe', auth: z.object({ STRIPE_API_KEY: z.string() }) });
128
+ * // -> throws DuplicateCredentialSetDefinitionError
129
+ * ```
130
+ */
131
+ var DuplicateCredentialSetDefinitionError = class extends Error {
132
+ manifestId;
133
+ firstDeclaredAt;
134
+ secondDeclaredAt;
135
+ firstFingerprint;
136
+ secondFingerprint;
137
+ constructor(options) {
138
+ super([
139
+ `Two CredentialSet instances were declared with the same manifestId "${options.manifestId}",`,
140
+ `but they have different shapes:`,
141
+ ` first (${options.firstDeclaredAt}): ${options.firstFingerprint}`,
142
+ ` second (${options.secondDeclaredAt}): ${options.secondFingerprint}`,
143
+ "",
144
+ "If you meant to share these credentials, import the same instance from a single module.",
145
+ "If you meant two distinct credential sets, give them different ids (or namespaces)."
146
+ ].join("\n"));
147
+ this.name = "DuplicateCredentialSetDefinitionError";
148
+ this.manifestId = options.manifestId;
149
+ this.firstDeclaredAt = options.firstDeclaredAt;
150
+ this.secondDeclaredAt = options.secondDeclaredAt;
151
+ this.firstFingerprint = options.firstFingerprint;
152
+ this.secondFingerprint = options.secondFingerprint;
153
+ }
154
+ };
155
+ /**
156
+ * Register a newly constructed credential set by its
157
+ * `resolvedCredentialSetId`. Called once per `CredentialSet` constructor.
158
+ *
159
+ * @throws {DuplicateCredentialSetDefinitionError} when the id was
160
+ * previously registered with a different schema fingerprint.
161
+ */
162
+ function registerCredentialSet(params) {
163
+ const registry = getRegistry$1();
164
+ const existing = registry.get(params.manifestId);
165
+ if (existing && existing.fingerprint !== params.fingerprint) throw new DuplicateCredentialSetDefinitionError({
166
+ manifestId: params.manifestId,
167
+ firstDeclaredAt: existing.sourceHint,
168
+ secondDeclaredAt: params.sourceHint,
169
+ firstFingerprint: existing.fingerprint,
170
+ secondFingerprint: params.fingerprint
171
+ });
172
+ registry.set(params.manifestId, {
173
+ fingerprint: params.fingerprint,
174
+ sourceHint: params.sourceHint
175
+ });
176
+ }
177
+ /**
178
+ * Produce a deterministic fingerprint of a `CredentialSet`'s auth (and
179
+ * `stored`, when present) schema. The fingerprint is a stable string of
180
+ * sorted `key:typeTag` pairs separated by `|`, with the stored shape
181
+ * concatenated after a `#` delimiter when the credential set declares a
182
+ * `stored` schema.
183
+ *
184
+ * Refinements (`.min(1)`, regex, etc.) are intentionally ignored — they
185
+ * are not breaking changes for vault compatibility. Structural changes
186
+ * (added keys, renamed keys, changed underlying Zod types, flipping
187
+ * required ↔ optional) produce a different fingerprint.
188
+ *
189
+ * @see registerCredentialSet
190
+ */
191
+ function fingerprintAuthShape(auth, stored) {
192
+ const authPart = shapeSignature(auth);
193
+ if (!stored) return authPart;
194
+ return `${authPart}#${shapeSignature(stored)}`;
195
+ }
196
+ function shapeSignature(schema) {
197
+ const resolvedShape = resolveZodObjectShape(schema);
198
+ if (!resolvedShape) return "";
199
+ return readZodObjectKeyMetadata(schema).all.map((key) => `${key}:${typeTag(resolvedShape[key])}`).sort().join("|");
200
+ }
201
+ function typeTag(zodType) {
202
+ if (zodType === null || zodType === void 0) return "Unknown";
203
+ const def = zodType._def;
204
+ return def?.typeName ?? def?.type ?? "Unknown";
205
+ }
206
+ /**
207
+ * Best-effort source hint — a short file:line string recovered from a
208
+ * lightweight stack trace at call time. Used only in the error message;
209
+ * does not affect correctness of the registry comparison.
210
+ *
211
+ * @remarks
212
+ * The hint format is `path/to/file.ts:line:col` when a repo frame can
213
+ * be isolated, and `'unknown'` otherwise. Callers should treat the
214
+ * value as opaque.
215
+ */
216
+ function captureStackOrigin() {
217
+ const frame = ((/* @__PURE__ */ new Error()).stack?.split("\n") ?? []).slice(1).find((line) => (line.includes("/packages/") || line.includes("/apps/")) && !/\/credential-set\/registry\.[mc]?[jt]s/.test(line) && !/\/credential-set\/CredentialSet\.[mc]?[jt]s/.test(line));
218
+ if (!frame) return "unknown";
219
+ const parens = frame.match(/\(([^)]+)\)/);
220
+ if (parens?.[1]) return parens[1];
221
+ const bare = frame.match(/at\s+(.+)$/);
222
+ if (bare?.[1]) return bare[1];
223
+ return "unknown";
224
+ }
225
+ //#endregion
226
+ //#region ../../packages/core/src/credential-set/CredentialSet.ts
227
+ var CredentialSet = class extends Primitive {
228
+ kind = "credential-set";
229
+ id;
230
+ /** Optional namespace. Official Keystroke integrations use 'keystroke'. */
231
+ namespace;
232
+ /**
233
+ * Computed namespaced identifier used for storage and manifest-facing wiring.
234
+ *
235
+ * Use this value for DB storage, manifest entries, and explicit credential
236
+ * bindings. Do not use it as the runtime `ctx.credentials` key inside authored
237
+ * code.
238
+ *
239
+ * @remarks
240
+ * Runtime credential context is keyed by the raw `id`, not this field. That
241
+ * is why `ctx.credentials.slack` uses `slack` rather than `keystroke:slack`.
242
+ */
243
+ resolvedCredentialSetId;
244
+ name;
245
+ description;
246
+ auth;
247
+ stored;
248
+ resolve;
249
+ /**
250
+ * Run-scoped cache TTL in milliseconds for the {@link resolve} output.
251
+ *
252
+ * Always a number; `0` means "no cache". Consumed by the credential
253
+ * runtime's `ResolveCache` when present.
254
+ *
255
+ * @see {@link CredentialSetConfig.resolveCacheMs}
256
+ */
257
+ resolveCacheMs;
258
+ /**
259
+ * Platform-side `stored`→`auth` transform. Mutually exclusive with
260
+ * {@link resolve}. Runs on the trusted host via
261
+ * `@keystroke/credential-runtime`'s `executePlatformResolve` helper.
262
+ *
263
+ * @see {@link resolveLocation}
264
+ * @see {@link platformEnvAllowlist}
265
+ */
266
+ resolveAtPlatform;
267
+ /**
268
+ * Resolved description of where the `stored`→`auth` transform runs.
269
+ *
270
+ * Computed at construction as `'platform'` when `resolveAtPlatform`
271
+ * is declared, `'sandbox'` when `resolve` is declared, `'none'`
272
+ * otherwise. The credential runtime's phase 3 branches on this value
273
+ * to pick the right execution location.
274
+ *
275
+ * @see {@link CredentialResolveLocation}
276
+ */
277
+ resolveLocation;
278
+ /**
279
+ * Env-var names `resolveAtPlatform` may read through `ctx.env`.
280
+ * Frozen at construction. Empty when `resolveLocation !== 'platform'`.
281
+ *
282
+ * @see {@link PlatformResolveContext.env}
283
+ */
284
+ platformEnvAllowlist;
285
+ needsResolve;
286
+ /** Required when namespace is 'keystroke'. Optional for user-authored credential sets. */
287
+ platformMetadata;
288
+ proxy;
289
+ needsRawSecret;
290
+ /**
291
+ * Policy when a step throws `CredentialRevokedError` against this credential set.
292
+ *
293
+ * @see {@link import('./types').CredentialSetConfig.onCredentialRevoked}
294
+ */
295
+ onCredentialRevoked;
296
+ /**
297
+ * Describe the optional user-facing connect flow for this credential set.
298
+ *
299
+ * Set this when the credential should be uploaded through a manual form or an
300
+ * OAuth handshake. Omit it for platform-seeded or internal credentials that do
301
+ * not expose a user-facing connect flow.
302
+ *
303
+ * @see {@link CredentialSetConfig.connection}
304
+ */
305
+ connection;
306
+ /** Sorted keys declared on the `auth` schema. Source of truth for what the
307
+ * built manifest advertises this credential set requires. Memoized at
308
+ * construction so neither the build pipeline nor the runtime needs to walk
309
+ * the Zod schema again. */
310
+ credentialKeys;
311
+ /** Subset of `credentialKeys` declared as `z.optional()` / `z.default()` on
312
+ * `auth`. Used by the build pipeline to record which vault keys may be
313
+ * absent without failing manifest declaration. */
314
+ optionalCredentialKeys;
315
+ /** Sorted keys declared on `stored` (or `auth` when no `stored` schema is
316
+ * provided). This is what the runtime credential resolver actually fetches
317
+ * from the vault, since `stored` represents the persisted shape. */
318
+ storedCredentialKeys;
319
+ /** Subset of `storedCredentialKeys` declared as `z.optional()` /
320
+ * `z.default()`. Tells the runtime resolver which vault keys are allowed to
321
+ * be missing. */
322
+ optionalStoredCredentialKeys;
323
+ #manifest;
324
+ constructor(config) {
325
+ super();
326
+ const validatedConfig = validateConfig(credentialSetConfigSchema, (() => {
327
+ if (config.platformMetadata !== void 0) return config;
328
+ if (config.namespace === "keystroke") return config;
329
+ if (config.connection !== void 0) return {
330
+ ...config,
331
+ platformMetadata: {
332
+ kind: CREDENTIAL_KINDS["user-connection"],
333
+ visibility: CREDENTIAL_VISIBILITIES["user-visible"]
334
+ }
335
+ };
336
+ return config;
337
+ })());
338
+ const hasStored = validatedConfig.stored !== void 0;
339
+ const hasResolve = validatedConfig.resolve !== void 0;
340
+ const hasResolveAtPlatform = validatedConfig.resolveAtPlatform !== void 0;
341
+ if (hasResolve && hasResolveAtPlatform) throw new Error(`CredentialSet "${validatedConfig.id}": "resolve" and "resolveAtPlatform" are mutually exclusive.`);
342
+ if ((hasResolve || hasResolveAtPlatform) && !hasStored) throw new Error(`CredentialSet "${validatedConfig.id}": "resolve" / "resolveAtPlatform" require "stored".`);
343
+ if (hasStored && !hasResolve && !hasResolveAtPlatform) throw new Error(`CredentialSet "${validatedConfig.id}": "stored" requires either "resolve" or "resolveAtPlatform".`);
344
+ if (validatedConfig.platformEnvAllowlist !== void 0 && validatedConfig.platformEnvAllowlist.length > 0 && !hasResolveAtPlatform) throw new Error(`CredentialSet "${validatedConfig.id}": "platformEnvAllowlist" requires "resolveAtPlatform".`);
345
+ this.id = validatedConfig.id;
346
+ this.namespace = validatedConfig.namespace;
347
+ this.resolvedCredentialSetId = this.namespace ? `${this.namespace}:${this.id}` : this.id;
348
+ registerCredentialSet({
349
+ manifestId: this.resolvedCredentialSetId,
350
+ fingerprint: fingerprintAuthShape(validatedConfig.auth, validatedConfig.stored),
351
+ sourceHint: captureStackOrigin()
352
+ });
353
+ this.name = validatedConfig.name ?? validatedConfig.id;
354
+ this.description = validatedConfig.description;
355
+ this.auth = validatedConfig.auth;
356
+ this.stored = validatedConfig.stored;
357
+ this.resolve = validatedConfig.resolve;
358
+ this.resolveCacheMs = hasResolve && typeof validatedConfig.resolveCacheMs === "number" ? validatedConfig.resolveCacheMs : 0;
359
+ this.resolveAtPlatform = validatedConfig.resolveAtPlatform;
360
+ this.resolveLocation = hasResolve ? "sandbox" : hasResolveAtPlatform ? "platform" : "none";
361
+ this.platformEnvAllowlist = Object.freeze(validatedConfig.platformEnvAllowlist ? [...validatedConfig.platformEnvAllowlist] : []);
362
+ this.needsResolve = hasStored && (hasResolve || hasResolveAtPlatform);
363
+ this.platformMetadata = validatedConfig.platformMetadata;
364
+ this.proxy = validatedConfig.proxy;
365
+ this.needsRawSecret = validatedConfig.needsRawSecret;
366
+ this.onCredentialRevoked = validatedConfig.onCredentialRevoked;
367
+ this.connection = validatedConfig.connection;
368
+ if (this.onCredentialRevoked === "retry-once" && !this.resolve) warnRetryOnceWithoutResolve(this.resolvedCredentialSetId);
369
+ const authKeyMetadata = readZodObjectKeyMetadata(this.auth);
370
+ const storedKeyMetadata = this.stored ? readZodObjectKeyMetadata(this.stored) : authKeyMetadata;
371
+ this.credentialKeys = Object.freeze(authKeyMetadata.all);
372
+ this.optionalCredentialKeys = Object.freeze(authKeyMetadata.optional);
373
+ this.storedCredentialKeys = Object.freeze(storedKeyMetadata.all);
374
+ this.optionalStoredCredentialKeys = Object.freeze(storedKeyMetadata.optional);
375
+ if (this.connection?.kind === "oauth") {
376
+ assertDeclarativeVaultKeysAreKnown(validatedConfig.id, this.connection.vault, this.storedCredentialKeys);
377
+ assertOAuthClientSourceIsWellFormed(validatedConfig.id, this.connection);
378
+ }
379
+ this.#manifest = Object.freeze(CredentialSetManifestSchema.parse({
380
+ manifestVersion: 1,
381
+ type: "credentialSet",
382
+ id: this.id,
383
+ namespace: this.namespace,
384
+ resolvedCredentialSetId: this.resolvedCredentialSetId,
385
+ name: this.name,
386
+ auth: schemaToJsonSchema(this.auth),
387
+ ...this.description ? { description: this.description } : {},
388
+ ...this.stored ? { stored: schemaToJsonSchema(this.stored) } : {},
389
+ ...this.needsResolve ? { needsResolve: true } : {},
390
+ ...this.resolveCacheMs > 0 ? { resolveCacheMs: this.resolveCacheMs } : {},
391
+ ...this.resolveLocation !== "none" ? { resolveLocation: this.resolveLocation } : {},
392
+ ...this.platformEnvAllowlist.length > 0 ? { platformEnvAllowlist: [...this.platformEnvAllowlist] } : {},
393
+ ...this.platformMetadata ? { platformMetadata: this.platformMetadata } : {},
394
+ ...this.proxy ? { proxy: this.proxy } : {},
395
+ ...this.needsRawSecret === true ? { needsRawSecret: true } : {},
396
+ ...this.onCredentialRevoked ? { onCredentialRevoked: this.onCredentialRevoked } : {},
397
+ ...this.connection ? { connection: serializeConnectionForManifest(this.connection) } : {}
398
+ }));
399
+ Object.freeze(this);
400
+ }
401
+ describe() {
402
+ return `CredentialSet "${this.name}" (${this.resolvedCredentialSetId})`;
403
+ }
404
+ toManifest() {
405
+ return this.#manifest;
406
+ }
407
+ };
408
+ /** Strip runtime hooks from the connection config before serializing to the
409
+ * manifest. Hooks are functions and not manifest-safe; the manifest captures
410
+ * only declarative metadata (kind, URLs, scopes, etc.).
411
+ *
412
+ * Declarative {@link Vault} mappings serialize as-is. Function-form vault
413
+ * mappings cannot be serialized (they are runtime closures); the serialized
414
+ * manifest records only the kind marker so the shape stays well-typed. */
415
+ function serializeConnectionForManifest(connection) {
416
+ if (connection.kind === "manual") return {
417
+ kind: "manual",
418
+ ...connection.instructions ? { instructions: connection.instructions } : {}
419
+ };
420
+ if (connection.kind === "oauth") return {
421
+ kind: "oauth",
422
+ authUrl: connection.authUrl,
423
+ tokenUrl: connection.tokenUrl,
424
+ scopes: connection.scopes,
425
+ tokenType: connection.tokenType,
426
+ vault: serializeVaultForManifest(connection.vault),
427
+ ...connection.revokeUrl !== void 0 ? { revokeUrl: connection.revokeUrl } : {},
428
+ ...connection.pkce === true ? { pkce: true } : {},
429
+ ...typeof connection.defaultExpiresInSeconds === "number" ? { defaultExpiresInSeconds: connection.defaultExpiresInSeconds } : {},
430
+ ...connection.oauthClientSource ? { oauthClientSource: serializeOAuthClientSourceForManifest(connection.oauthClientSource) } : {}
431
+ };
432
+ if (connection.kind === "credentials-exchange") return {
433
+ kind: "credentials-exchange",
434
+ input: schemaToJsonSchema(connection.input),
435
+ ...connection.instructions ? { instructions: connection.instructions } : {}
436
+ };
437
+ throw new Error(`Unknown connection kind: ${JSON.stringify(connection)}`);
438
+ }
439
+ /** Project the live {@link OAuthClientSource} into its manifest-safe form.
440
+ * The workspace variant substitutes the object reference with the
441
+ * referenced credential set's `resolvedCredentialSetId` so the manifest
442
+ * carries a stable, persistable id instead of a closure-backed object. */
443
+ function serializeOAuthClientSourceForManifest(source) {
444
+ if (source.kind === "keystroke-platform") return { kind: "keystroke-platform" };
445
+ return {
446
+ kind: "workspace-provider-app",
447
+ credentialSetId: source.credentialSet.resolvedCredentialSetId,
448
+ ...source.keyMap ? { keyMap: source.keyMap } : {}
449
+ };
450
+ }
451
+ function serializeVaultForManifest(vault) {
452
+ if ("build" in vault) return {
453
+ kind: "function",
454
+ accessTokenKey: vault.accessTokenKey
455
+ };
456
+ return {
457
+ kind: "declarative",
458
+ accessToken: vault.accessToken,
459
+ ...vault.instanceUrl !== void 0 ? { instanceUrl: vault.instanceUrl } : {},
460
+ ...vault.raw !== void 0 ? { raw: { ...vault.raw } } : {}
461
+ };
462
+ }
463
+ /** Tracks credential-set ids that already emitted the `retry-once + no resolve`
464
+ * construction warning so repeated tree-shake re-registration in the same
465
+ * process does not spam the log. */
466
+ const warnedRetryOnceWithoutResolve = /* @__PURE__ */ new Set();
467
+ function warnRetryOnceWithoutResolve(resolvedCredentialSetId) {
468
+ if (warnedRetryOnceWithoutResolve.has(resolvedCredentialSetId)) return;
469
+ warnedRetryOnceWithoutResolve.add(resolvedCredentialSetId);
470
+ console.warn(`CredentialSet "${resolvedCredentialSetId}": onCredentialRevoked: 'retry-once' is set but no resolve is declared. The retry will be a no-op because re-resolving stored values would produce the same result.`);
471
+ }
472
+ /** Runtime safety net: the referenced `clientApp` for a
473
+ * `workspace-provider-app` `oauthClientSource` must declare both the
474
+ * clientId and clientSecret keys (either under the default names or via
475
+ * `keyMap` aliases). The `visibility: 'internal'` check happens earlier at
476
+ * the Zod refinement layer; this validator covers the deeper schema-shape
477
+ * check so authors catch mismatches at construction rather than at
478
+ * handshake time. */
479
+ function assertOAuthClientSourceIsWellFormed(credentialSetId, connection) {
480
+ const source = connection.oauthClientSource;
481
+ if (!source || source.kind !== "workspace-provider-app") return;
482
+ const clientIdKey = source.keyMap?.clientId ?? "clientId";
483
+ const clientSecretKey = source.keyMap?.clientSecret ?? "clientSecret";
484
+ const referenced = source.credentialSet;
485
+ const keys = new Set(referenced.credentialKeys);
486
+ const missing = [];
487
+ if (!keys.has(clientIdKey)) missing.push(`clientId key "${clientIdKey}"`);
488
+ if (!keys.has(clientSecretKey)) missing.push(`clientSecret key "${clientSecretKey}"`);
489
+ if (missing.length > 0) throw new Error(`CredentialSet "${credentialSetId}": oauthClientSource.credentialSet "${referenced.id}" does not declare ${missing.join(" or ")}. Adjust the referenced credential set's auth schema or pass an explicit keyMap.`);
490
+ }
491
+ /** Runtime safety net: when a caller constructs with a typed-erased shape
492
+ * (e.g. via `as never`), verify every declared vault slot still maps to a
493
+ * known stored/auth schema key. The static `CredentialVaultKeys` parameter on
494
+ * `CredentialSetConfig.connection` catches typos at the construction site;
495
+ * this runtime check catches the erased case. */
496
+ function assertDeclarativeVaultKeysAreKnown(credentialSetId, vault, knownKeys) {
497
+ if ("build" in vault) return;
498
+ const known = new Set(knownKeys);
499
+ const invalid = [];
500
+ if (!known.has(vault.accessToken)) invalid.push(`vault.accessToken="${vault.accessToken}"`);
501
+ if (vault.instanceUrl !== void 0 && !known.has(vault.instanceUrl)) invalid.push(`vault.instanceUrl="${vault.instanceUrl}"`);
502
+ if (vault.raw) {
503
+ for (const rawKey of Object.keys(vault.raw)) if (!known.has(rawKey)) invalid.push(`vault.raw.${rawKey}`);
504
+ }
505
+ if (invalid.length > 0) throw new Error(`CredentialSet "${credentialSetId}": OAuth vault references unknown credential keys (${invalid.join(", ")}). Valid keys are [${[...known].sort().join(", ")}].`);
506
+ }
507
+ //#endregion
508
+ //#region ../../packages/core/src/shared/credential-sets.ts
509
+ function cloneCredentialSets(credentialSets) {
510
+ return credentialSets ? [...credentialSets] : void 0;
511
+ }
512
+ function assertUniqueCredentialSetIds(credentialSets, ownerKind, ownerName) {
513
+ const seenCredentialSetIds = /* @__PURE__ */ new Set();
514
+ for (const credentialSet of credentialSets) {
515
+ if (seenCredentialSetIds.has(credentialSet.id)) throw new Error(`${ownerKind} "${ownerName}" declares duplicate credential set id "${credentialSet.id}".`);
516
+ seenCredentialSetIds.add(credentialSet.id);
517
+ }
518
+ }
519
+ //#endregion
520
+ //#region ../../packages/core/src/operation/nesting-guard.ts
521
+ const NESTING_GUARD_KEY = "__ks_operation_nesting_guard__";
522
+ function getStorage() {
523
+ const g = globalThis;
524
+ if (!g[NESTING_GUARD_KEY]) g[NESTING_GUARD_KEY] = new AsyncLocalStorage();
525
+ return g[NESTING_GUARD_KEY];
526
+ }
527
+ function getActiveOperationRun() {
528
+ return getStorage().getStore()?.operationName;
529
+ }
530
+ function runWithOperationScope(operationName, fn) {
531
+ return getStorage().run({ operationName }, fn);
532
+ }
533
+ //#endregion
534
+ //#region ../../packages/core/src/operation/schemas.ts
535
+ const credentialSetInstanceSchema = createStructuralSchema([
536
+ "id",
537
+ "auth",
538
+ "needsResolve"
539
+ ], "a CredentialSet instance");
540
+ const operationConfigSchema = z.object({
541
+ credentialSets: z.array(credentialSetInstanceSchema).optional(),
542
+ description: descriptionString("Operation description"),
543
+ id: trimmedNonEmptyString("Operation id"),
544
+ input: anyZodSchemaSchema,
545
+ name: trimmedNonEmptyString("Operation name"),
546
+ needsApproval: z.boolean().optional(),
547
+ output: anyZodSchemaSchema,
548
+ requiredOAuthScopes: z.array(z.string()).optional(),
549
+ retries: RetryConfigSchema.optional(),
550
+ run: z.function(),
551
+ tags: z.array(z.string()).optional(),
552
+ timeout: DurationSchema.optional(),
553
+ maxDurationMs: z.number().int().positive().optional(),
554
+ workflowGlobals: anyZodSchemaSchema.optional()
555
+ });
556
+ const OperationManifestSchema = z.object({
557
+ manifestVersion: z.literal(1),
558
+ type: z.literal("operation"),
559
+ name: trimmedNonEmptyString("Operation name"),
560
+ id: trimmedNonEmptyString("Operation id"),
561
+ description: descriptionString("Operation description"),
562
+ credentialSets: z.array(CredentialSetManifestSchema),
563
+ input: jsonSchemaObject,
564
+ output: jsonSchemaObject,
565
+ timeout: DurationSchema.optional(),
566
+ tags: z.array(z.string()).optional(),
567
+ retries: RetryConfigSchema.optional(),
568
+ needsApproval: z.boolean().optional(),
569
+ requiredOAuthScopes: z.array(z.string()).optional(),
570
+ maxDurationMs: z.number().int().positive().optional(),
571
+ workflowGlobals: jsonSchemaObject.optional()
572
+ });
573
+ //#endregion
574
+ //#region ../../packages/core/src/operation/step-registry.ts
575
+ const REGISTRY_KEY = "__ks_step_registry";
576
+ function getRegistry() {
577
+ const g = globalThis;
578
+ if (!g[REGISTRY_KEY]) g[REGISTRY_KEY] = [];
579
+ return g[REGISTRY_KEY];
580
+ }
581
+ function registerStep(step) {
582
+ getRegistry().push(step);
583
+ }
584
+ //#endregion
585
+ //#region ../../packages/core/src/operation/Operation.ts
586
+ function createHostedOperationExecutionError(integrationId, detail) {
587
+ return /* @__PURE__ */ new Error(`Hosted integration "${integrationId}" cannot run locally in this environment. ${detail}`);
588
+ }
589
+ var Operation = class Operation extends Primitive {
590
+ kind = "operation";
591
+ credentialSets;
592
+ description;
593
+ id;
594
+ input;
595
+ name;
596
+ needsApproval;
597
+ output;
598
+ requiredOAuthScopes;
599
+ retries;
600
+ tags;
601
+ timeout;
602
+ /**
603
+ * Upper bound on the operation's expected duration, in milliseconds.
604
+ * See {@link OperationConfig.maxDurationMs}.
605
+ */
606
+ maxDurationMs;
607
+ workflowGlobals;
608
+ #manifest;
609
+ #runImplementation;
610
+ #config;
611
+ constructor(config) {
612
+ super();
613
+ const validatedConfig = validateConfig(operationConfigSchema, {
614
+ ...config,
615
+ credentialSets: cloneCredentialSets(config.credentialSets),
616
+ tags: config.tags ? [...config.tags] : void 0,
617
+ requiredOAuthScopes: config.requiredOAuthScopes ? [...config.requiredOAuthScopes] : void 0
618
+ });
619
+ this.#config = {
620
+ ...config,
621
+ ...validatedConfig,
622
+ credentialSets: validatedConfig.credentialSets ?? config.credentialSets ?? [],
623
+ timeout: validatedConfig.timeout,
624
+ input: validatedConfig.input,
625
+ output: validatedConfig.output,
626
+ run: config.run,
627
+ workflowGlobals: validatedConfig.workflowGlobals
628
+ };
629
+ this.credentialSets = this.#config.credentialSets ?? [];
630
+ assertUniqueCredentialSetIds(this.credentialSets, "Operation", this.#config.name);
631
+ this.description = validatedConfig.description;
632
+ this.id = validatedConfig.id;
633
+ this.input = this.#config.input;
634
+ this.name = validatedConfig.name;
635
+ this.needsApproval = validatedConfig.needsApproval;
636
+ this.output = this.#config.output;
637
+ this.requiredOAuthScopes = validatedConfig.requiredOAuthScopes ? [...validatedConfig.requiredOAuthScopes] : void 0;
638
+ this.retries = validatedConfig.retries;
639
+ this.tags = [...validatedConfig.tags ?? []];
640
+ this.timeout = validatedConfig.timeout;
641
+ this.maxDurationMs = validatedConfig.maxDurationMs;
642
+ this.workflowGlobals = this.#config.workflowGlobals;
643
+ this.#runImplementation = this.#config.run;
644
+ registerStep(this);
645
+ this.#manifest = Object.freeze(OperationManifestSchema.parse({
646
+ manifestVersion: 1,
647
+ type: "operation",
648
+ name: this.name,
649
+ id: this.id,
650
+ description: this.description,
651
+ credentialSets: this.credentialSets.map((cs) => cs.toManifest()),
652
+ input: schemaToJsonSchema(this.input),
653
+ output: schemaToJsonSchema(this.output),
654
+ tags: [...this.tags],
655
+ ...this.timeout ? { timeout: this.timeout } : {},
656
+ ...this.retries ? { retries: this.retries } : {},
657
+ ...typeof this.maxDurationMs === "number" ? { maxDurationMs: this.maxDurationMs } : {},
658
+ ...this.needsApproval !== void 0 ? { needsApproval: this.needsApproval } : {},
659
+ ...this.requiredOAuthScopes?.length ? { requiredOAuthScopes: [...this.requiredOAuthScopes] } : {},
660
+ ...this.workflowGlobals ? { workflowGlobals: schemaToJsonSchema(this.workflowGlobals) } : {}
661
+ }));
662
+ Object.freeze(this);
663
+ }
664
+ withTimeout(duration) {
665
+ return new Operation({
666
+ ...this.#config,
667
+ timeout: duration
668
+ });
669
+ }
670
+ retry(policy) {
671
+ return new Operation({
672
+ ...this.#config,
673
+ retries: policy
674
+ });
675
+ }
676
+ configure(config) {
677
+ return new Operation({
678
+ ...this.#config,
679
+ ...config
680
+ });
681
+ }
682
+ getCredentialRequirements() {
683
+ return toDeclaredCredentialRequirements(this.credentialSets);
684
+ }
685
+ /** @internal Used by the flow graph builder for nesting detection. */
686
+ getRunFunctionSource() {
687
+ return this.#runImplementation.toString();
688
+ }
689
+ mapInput(schema, fn) {
690
+ const originalRun = this.#runImplementation;
691
+ return new Operation({
692
+ ...this.#config,
693
+ input: schema,
694
+ run: async (input, ctx) => {
695
+ return originalRun(fn(input), ctx);
696
+ }
697
+ });
698
+ }
699
+ mapOutput(schema, fn) {
700
+ const originalRun = this.#runImplementation;
701
+ return new Operation({
702
+ ...this.#config,
703
+ output: schema,
704
+ run: async (input, ctx) => {
705
+ return fn(await originalRun(input, ctx));
706
+ }
707
+ });
708
+ }
709
+ async run(input, ctx) {
710
+ const parsedInput = this.input.parse(input);
711
+ const interceptor = getActiveRuntimeCallInterceptor();
712
+ if (interceptor) {
713
+ const intercepted = await interceptor({
714
+ instance: this,
715
+ kind: "workflow-step",
716
+ name: this.name,
717
+ input: parsedInput,
718
+ outputSchema: this.output
719
+ });
720
+ return this.output.parse(intercepted);
721
+ }
722
+ if (!ctx) {
723
+ const workflowRuntime = getRegisteredRuntime();
724
+ if (workflowRuntime?.handleStep) {
725
+ const intercepted = await workflowRuntime.handleStep(this, parsedInput);
726
+ return this.output.parse(intercepted);
727
+ }
728
+ }
729
+ const integrationMetadata = getOfficialIntegrationMetadata(this);
730
+ if (integrationMetadata?.hosted) {
731
+ const hostedActionExecutionPolicy = getHostedActionExecutionPolicy();
732
+ const dispatcher = getRegisteredHostedActionDispatcher();
733
+ if (!dispatcher) {
734
+ if (hostedActionExecutionPolicy === "strict") throw createHostedOperationExecutionError(integrationMetadata.integrationId, "Use `keystrokeTestPlugin()` in auto mode, run `keystroke auth`, and ensure the Keystroke dev server is running.");
735
+ } else {
736
+ const dispatchResult = await dispatcher.dispatch(this, integrationMetadata.integrationId, parsedInput);
737
+ if (dispatchResult.handled) return this.output.parse(dispatchResult.result);
738
+ if (hostedActionExecutionPolicy === "strict") throw createHostedOperationExecutionError(integrationMetadata.integrationId, "The hosted-action dispatcher declined execution. Hosted integrations must execute through the Keystroke dev server.");
739
+ }
740
+ }
741
+ const execute = async () => {
742
+ const parentOperation = getActiveOperationRun();
743
+ if (parentOperation) throw new Error(`Operation "${this.name}" was called inside the run function of "${parentOperation}". Steps and Operations cannot call other Operations inside their run function. Move the "${this.name}" call into the Workflow's run function, or use a plain async helper function instead of a Step.`);
744
+ return runWithOperationScope(this.name, async () => {
745
+ const result = await this.#runImplementation(parsedInput, await this.#resolveRuntimeContext(ctx));
746
+ return this.output.parse(result);
747
+ });
748
+ };
749
+ if (this.timeout) {
750
+ const ms = parseDurationToMs(this.timeout);
751
+ return Promise.race([execute(), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error(`Operation "${this.name}" timed out after ${ms}ms`)), ms))]);
752
+ }
753
+ return execute();
754
+ }
755
+ /**
756
+ * Execute the step implementation directly, bypassing interceptors and
757
+ * runtime checks. Used by the inline step execution runtime to avoid
758
+ * recursion through handleStep.
759
+ * @internal
760
+ */
761
+ async executeDirectly(input, ctx) {
762
+ const parsedInput = this.input.parse(input);
763
+ const result = await this.#runImplementation(parsedInput, await this.#resolveRuntimeContext(ctx));
764
+ return this.output.parse(result);
765
+ }
766
+ describe() {
767
+ return `Operation "${this.name}"`;
768
+ }
769
+ toManifest() {
770
+ return this.#manifest;
771
+ }
772
+ #createImplicitRuntimeContext() {
773
+ return {
774
+ credentials: {},
775
+ workflowGlobals: void 0
776
+ };
777
+ }
778
+ #normalizeRuntimeContext(ctx) {
779
+ const tracing = ctx;
780
+ return {
781
+ attempt: ctx.attempt,
782
+ credentials: ctx.credentials ?? {},
783
+ maxAttempts: ctx.maxAttempts,
784
+ stepId: ctx.stepId,
785
+ toolCallId: tracing.toolCallId,
786
+ traceparent: tracing.traceparent,
787
+ tracestate: tracing.tracestate,
788
+ workflowGlobals: ctx.workflowGlobals
789
+ };
790
+ }
791
+ async #resolveRuntimeContext(ctx) {
792
+ const runtimeContext = ctx ?? getRegisteredOperationContext(this);
793
+ if (runtimeContext) {
794
+ const normalizedContext = this.#normalizeRuntimeContext(runtimeContext);
795
+ return this.#validateRuntimeContext(await this.#resolveMissingCredentials(normalizedContext));
796
+ }
797
+ if (this.credentialSets.length === 0 && !this.workflowGlobals) return this.#createImplicitRuntimeContext();
798
+ throw new Error(`Operation "${this.name}" was executed without a runtime context. Pass one explicitly to .run(input, ctx), or use keystrokeTestPlugin() from "@keystrokehq/core/vitest" in Vitest.`);
799
+ }
800
+ async #resolveMissingCredentials(ctx) {
801
+ if (this.credentialSets.map((credentialSet) => credentialSet.id).filter((credentialSetId) => ctx.credentials[credentialSetId] === void 0).length === 0) return ctx;
802
+ const resolvedCredentials = await resolveRegisteredOperationCredentials(this, ctx);
803
+ if (!resolvedCredentials) return ctx;
804
+ return {
805
+ ...ctx,
806
+ credentials: {
807
+ ...resolvedCredentials,
808
+ ...ctx.credentials
809
+ }
810
+ };
811
+ }
812
+ #validateRuntimeContext(ctx) {
813
+ const validatedCredentials = {};
814
+ for (const credentialSet of this.credentialSets) {
815
+ const credentialId = credentialSet.id;
816
+ const rawCredential = ctx.credentials[credentialId];
817
+ validatedCredentials[credentialSet.id] = credentialSet.auth.parse(rawCredential);
818
+ }
819
+ return {
820
+ attempt: ctx.attempt,
821
+ credentials: validatedCredentials,
822
+ maxAttempts: ctx.maxAttempts,
823
+ stepId: ctx.stepId,
824
+ ...ctx.toolCallId !== void 0 ? { toolCallId: ctx.toolCallId } : {},
825
+ ...ctx.traceparent !== void 0 ? { traceparent: ctx.traceparent } : {},
826
+ ...ctx.tracestate !== void 0 ? { tracestate: ctx.tracestate } : {},
827
+ workflowGlobals: this.workflowGlobals ? this.workflowGlobals.parse(ctx.workflowGlobals) : ctx.workflowGlobals
828
+ };
829
+ }
830
+ };
831
+ //#endregion
832
+ //#region ../../packages/core/src/errors/credential-revoked-error.ts
24
833
  /**
25
834
  * Thrown by integration client wrappers when a provider returns 401/403,
26
835
  * indicating the stored credentials have been revoked or expired.
@@ -45538,7 +46347,7 @@ const gustoBundle = defineOfficialIntegration({
45538
46347
  });
45539
46348
  gustoBundle.connection;
45540
46349
  //#endregion
45541
- //#region ../../packages/integrations/integration-hubspot/dist/integration-Dr8wpq1-.mjs
46350
+ //#region ../../packages/integrations/integration-hubspot/dist/integration-C4wYr0hZ.mjs
45542
46351
  /**
45543
46352
  * Internal credential set for the Keystroke-managed HubSpot OAuth app.
45544
46353
  * Used for webhook signature verification on inbound webhooks.
@@ -54244,7 +55053,7 @@ const linearAppCredentialSet = new CredentialSet({
54244
55053
  });
54245
55054
  z.string().optional(), z.string().optional(), z.string().optional();
54246
55055
  //#endregion
54247
- //#region ../../packages/workflow-core/src/shared/create-error-normalizing-proxy.ts
55056
+ //#region ../../packages/core/src/shared/create-error-normalizing-proxy.ts
54248
55057
  function isThenable$1(value) {
54249
55058
  return !!value && typeof value === "object" && "then" in value && typeof value.then === "function";
54250
55059
  }
@@ -139221,7 +140030,7 @@ var LinearClient = class extends LinearSdk {
139221
140030
  }
139222
140031
  };
139223
140032
  //#endregion
139224
- //#region ../../packages/integrations/integration-linear/dist/schemas-gcIdf9Pt.mjs
140033
+ //#region ../../packages/integrations/integration-linear/dist/schemas-aVLy3iV7.mjs
139225
140034
  /**
139226
140035
  * Linear OAuth connection configuration.
139227
140036
  *
@@ -141575,7 +142384,7 @@ z.string().optional(), z.string().optional(), z.string().optional();
141575
142384
  */
141576
142385
  const SENTRY_DEFAULT_BASE_URL = "https://sentry.io";
141577
142386
  //#endregion
141578
- //#region ../../packages/integrations/integration-sentry/dist/integration-DlTslkB6.mjs
142387
+ //#region ../../packages/integrations/integration-sentry/dist/integration-C7EDI5L4.mjs
141579
142388
  const sentryOAuthConnection = {
141580
142389
  kind: "oauth",
141581
142390
  tokenType: "refreshable",
@@ -144409,7 +145218,7 @@ const slackAppCredentialSet = new CredentialSet({
144409
145218
  });
144410
145219
  z.string().optional(), z.string().optional(), z.string().optional(), z.string().optional();
144411
145220
  //#endregion
144412
- //#region ../../packages/integrations/integration-slack/dist/integration-CXzavV_C.mjs
145221
+ //#region ../../packages/integrations/integration-slack/dist/integration-CTNuSaOh.mjs
144413
145222
  /**
144414
145223
  * Slack OAuth connection configuration.
144415
145224
  *
@@ -144465,7 +145274,7 @@ const slackBundle = defineOfficialIntegration({
144465
145274
  });
144466
145275
  slackBundle.connection;
144467
145276
  //#endregion
144468
- //#region ../../packages/integrations/integration-snowflake/dist/integration-Qu0_oO7s.mjs
145277
+ //#region ../../packages/integrations/integration-snowflake/dist/integration-lylQDjSA.mjs
144469
145278
  /**
144470
145279
  * Webhook credential sets for the Snowflake auto-ingest triggers.
144471
145280
  *
@@ -150747,12 +151556,12 @@ zoomBundle.connection;
150747
151556
  * Registry of Keystroke-managed (a.k.a. "official") platform providers.
150748
151557
  *
150749
151558
  * This registry is intentionally part of `@keystroke/official-integrations`
150750
- * (not `@keystroke/workflow-core`) because the providers it lists are platform
151559
+ * (not `@keystrokehq/core`) because the providers it lists are platform
150751
151560
  * concerns: which integrations Keystroke ships out of the box, which of them
150752
151561
  * support a chat-style messaging gateway, and which messaging adapter id
150753
151562
  * each one delivers through.
150754
151563
  *
150755
- * `@keystroke/workflow-core` itself is provider-agnostic: its `MessagingGateway`
151564
+ * `@keystrokehq/core` itself is provider-agnostic: its `MessagingGateway`
150756
151565
  * and `ProviderTrigger` primitives accept any string `provider`, and
150757
151566
  * integration packages narrow that string at their own boundary.
150758
151567
  */
@@ -151163,7 +151972,7 @@ async function verifyCredentialResolvable(params) {
151163
151972
  * Enforces an 8-second platform timeout so a hung provider endpoint cannot
151164
151973
  * stall the CLI indefinitely.
151165
151974
  *
151166
- * @see packages/workflow-core/src/credential-set/connection.ts — `ValidateManualHook`
151975
+ * @see packages/core/src/credential-set/connection.ts — `ValidateManualHook`
151167
151976
  */
151168
151977
  /**
151169
151978
  * Run the manual `validate` hook for an official integration's credential