@keystrokehq/hosting 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -4393,12 +4393,34 @@ function superRefine(fn, params) {
4393
4393
  return /* @__PURE__ */ _superRefine(fn, params);
4394
4394
  }
4395
4395
  //#endregion
4396
+ //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/compat.js
4397
+ /** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
4398
+ const ZodIssueCode = {
4399
+ invalid_type: "invalid_type",
4400
+ too_big: "too_big",
4401
+ too_small: "too_small",
4402
+ invalid_format: "invalid_format",
4403
+ not_multiple_of: "not_multiple_of",
4404
+ unrecognized_keys: "unrecognized_keys",
4405
+ invalid_union: "invalid_union",
4406
+ invalid_key: "invalid_key",
4407
+ invalid_element: "invalid_element",
4408
+ invalid_value: "invalid_value",
4409
+ custom: "custom"
4410
+ };
4411
+ /** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
4412
+ var ZodFirstPartyTypeKind;
4413
+ (function(ZodFirstPartyTypeKind) {})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
4414
+ //#endregion
4396
4415
  //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/coerce.js
4397
4416
  function number(params) {
4398
4417
  return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
4399
4418
  }
4400
- //#endregion
4401
- //#region ../shared/dist/index.mjs
4419
+ new Set([
4420
+ "hello",
4421
+ "greeting",
4422
+ "greet"
4423
+ ]);
4402
4424
  /** Auth, session, and account-entry URL segments. */
4403
4425
  const AUTH_ACCOUNT_SLUGS = [
4404
4426
  "2fa",
@@ -4510,6 +4532,7 @@ const PRODUCT_SLUGS = [
4510
4532
  "execution",
4511
4533
  "executions",
4512
4534
  "explore",
4535
+ "forms",
4513
4536
  "get-started",
4514
4537
  "history",
4515
4538
  "inbox",
@@ -5329,7 +5352,9 @@ const storedRouteManifestEntryV2Schema = discriminatedUnion("kind", [
5329
5352
  appSlugs: array(string()).default([]),
5330
5353
  toolSlugs: array(string()).default([]),
5331
5354
  /** Credential requirements per tool slug (the agent's credential consumer key). */
5332
- toolRequirements: record(string(), array(CredentialRequirementSummarySchema)).optional()
5355
+ toolRequirements: record(string(), array(CredentialRequirementSummarySchema)).optional(),
5356
+ /** Credential requirements for the agent's VM sandbox env / git bootstrap. */
5357
+ sandboxRequirements: array(CredentialRequirementSummarySchema).optional()
5333
5358
  }),
5334
5359
  object({
5335
5360
  kind: literal("action"),
@@ -5377,6 +5402,8 @@ const storedRouteManifestEntryV2Schema = discriminatedUnion("kind", [
5377
5402
  moduleFile: string(),
5378
5403
  sourceHash: string().optional(),
5379
5404
  schedule: string(),
5405
+ /** IANA timezone for schedule wall-clock fields. When omitted, UTC. */
5406
+ timezone: string().optional(),
5380
5407
  name: requiredDisplayTextSchema,
5381
5408
  description: requiredDisplayTextSchema
5382
5409
  }),
@@ -5385,7 +5412,9 @@ const storedRouteManifestEntryV2Schema = discriminatedUnion("kind", [
5385
5412
  pollId: string(),
5386
5413
  attachmentIds: array(string()),
5387
5414
  moduleFile: string(),
5388
- schedule: string()
5415
+ schedule: string(),
5416
+ /** IANA timezone for schedule wall-clock fields. When omitted, UTC. */
5417
+ timezone: string().optional()
5389
5418
  }),
5390
5419
  object({
5391
5420
  kind: literal("cron-schedule"),
@@ -5394,6 +5423,8 @@ const storedRouteManifestEntryV2Schema = discriminatedUnion("kind", [
5394
5423
  moduleFile: string(),
5395
5424
  sourceHash: string().optional(),
5396
5425
  schedule: string(),
5426
+ /** IANA timezone for schedule wall-clock fields. When omitted, UTC. */
5427
+ timezone: string().optional(),
5397
5428
  /** Static cron payload from `defineCronSource({ payload })` — omitted when the source has none. */
5398
5429
  payload: unknown().optional(),
5399
5430
  name: requiredDisplayTextSchema,
@@ -5438,6 +5469,8 @@ const AutoTopupSummarySchema = object({
5438
5469
  const PlanLimitsSchema = object({
5439
5470
  includedStorageGb: number$1(),
5440
5471
  concurrencyLimit: number$1(),
5472
+ /** Max non-deleted projects; enforced on create only. */
5473
+ maxProjects: number$1(),
5441
5474
  agentTimeoutMs: number$1(),
5442
5475
  workflowTimeoutMs: number$1(),
5443
5476
  pollTimeoutMs: number$1(),
@@ -5451,8 +5484,15 @@ const PlanLimitsSchema = object({
5451
5484
  object({
5452
5485
  planKey: string(),
5453
5486
  subscriptionStatus: subscriptionStatusSchema,
5487
+ /** Remaining plan-bucket balance this period (µc). */
5454
5488
  planCreditMicroCredits: number$1(),
5489
+ /** Remaining prepaid balance (µc). Never expires. */
5455
5490
  prepaidCreditMicroCredits: number$1(),
5491
+ /**
5492
+ * Resolved monthly plan allotment (µc) — override ?? preset. Powers the
5493
+ * credit-usage progress denominator (`used = allotment − remaining`).
5494
+ */
5495
+ monthlyCreditMicroCredits: number$1(),
5456
5496
  periodStart: isoDateTime$6.nullable(),
5457
5497
  periodEnd: isoDateTime$6.nullable(),
5458
5498
  autoTopup: AutoTopupSummarySchema,
@@ -5695,7 +5735,8 @@ object({
5695
5735
  });
5696
5736
  const NewChannelBindingInputSchema = object({
5697
5737
  channelId: string().min(1),
5698
- channelName: string().min(1),
5738
+ /** Display name. When omitted or equal to `channelId`, the server resolves it from Slack. */
5739
+ channelName: string().min(1).optional(),
5699
5740
  channelKind: ChannelBindingKindSchema.optional(),
5700
5741
  mode: ChannelListenModeSchema.optional(),
5701
5742
  subscribeOnMention: boolean().optional()
@@ -5757,12 +5798,13 @@ const AppAuthKindSchema = _enum([
5757
5798
  "api_key",
5758
5799
  "keystroke"
5759
5800
  ]);
5760
- /** Composio auth scheme for API-key style connections. */
5801
+ /** Composio auth scheme for API-key / no-auth style connections. */
5761
5802
  const AppCredentialSchemeSchema = _enum([
5762
5803
  "API_KEY",
5763
5804
  "BEARER_TOKEN",
5764
5805
  "BASIC",
5765
- "BASIC_WITH_JWT"
5806
+ "BASIC_WITH_JWT",
5807
+ "NO_AUTH"
5766
5808
  ]);
5767
5809
  /**
5768
5810
  * Where app metadata and execution are sourced (e.g. native, composio, pipedream, custom).
@@ -5804,6 +5846,7 @@ object({
5804
5846
  "graphql"
5805
5847
  ]).default("custom"),
5806
5848
  url: string().url().optional(),
5849
+ logo: string().url().optional(),
5807
5850
  authKind: AppAuthKindSchema.optional(),
5808
5851
  fields: optionalCredentialFieldsSchema.optional(),
5809
5852
  credentialScheme: AppCredentialSchemeSchema.optional(),
@@ -5839,6 +5882,7 @@ object({
5839
5882
  authKind: AppAuthKindSchema,
5840
5883
  source: AppSourceSchema,
5841
5884
  url: string().url().nullable().optional(),
5885
+ logo: string().url().nullable().optional(),
5842
5886
  credentialFields: optionalCredentialFieldsSchema.optional(),
5843
5887
  credentialScheme: AppCredentialSchemeSchema.optional(),
5844
5888
  oauthScopes: array(OAuthScopeOptionSchema).optional(),
@@ -5875,12 +5919,14 @@ object({
5875
5919
  /** Endpoint URL for MCP, OpenAPI, or GraphQL custom apps. */
5876
5920
  url: string().url().nullable().optional(),
5877
5921
  /** True when the app has a non-empty credential field template. */
5878
- hasCredentialFields: boolean().optional()
5922
+ hasCredentialFields: boolean().optional(),
5923
+ /** Composio auth scheme — present for API-key and NO_AUTH apps so the picker can choose a flow. */
5924
+ credentialScheme: AppCredentialSchemeSchema.optional()
5879
5925
  }).extend({
5880
5926
  oauthScopes: array(OAuthScopeOptionSchema),
5881
5927
  /** Custom api_key apps — vault field template for connect UI and sync. */
5882
5928
  credentialFields: AppCredentialFieldsSchema.optional(),
5883
- /** Composio auth scheme when credentialFields are present. */
5929
+ /** Composio auth scheme for API-key or NO_AUTH connections. */
5884
5930
  credentialScheme: AppCredentialSchemeSchema.optional(),
5885
5931
  /** When present, the app supports agent gateway bindings (external channels). */
5886
5932
  gateway: AppGatewaySchema.optional()
@@ -5997,8 +6043,12 @@ const AppCredentialScopeSchema = _enum([
5997
6043
  "project",
5998
6044
  "organization"
5999
6045
  ]);
6000
- /** How the credential was connected (OAuth vs manual api-key entry). */
6001
- const AppCredentialConnectionKindSchema = _enum(["oauth", "manual"]);
6046
+ /** How the credential was connected (OAuth, manual api-key entry, or no-auth). */
6047
+ const AppCredentialConnectionKindSchema = _enum([
6048
+ "oauth",
6049
+ "manual",
6050
+ "none"
6051
+ ]);
6002
6052
  /** Connect-dialog permission preset for OAuth scope selection. */
6003
6053
  const OAuthPermissionModeSchema = _enum(["default", "restricted"]);
6004
6054
  const optionalTimestamp$1 = string().optional();
@@ -6092,12 +6142,39 @@ CredentialTargetsFieldsSchema.extend({
6092
6142
  message: "OAuth credentials are created via the OAuth callback",
6093
6143
  path: ["connectionKind"]
6094
6144
  });
6145
+ if (input.connectionKind === "none" && input.value) ctx.addIssue({
6146
+ code: "custom",
6147
+ message: "value is not allowed for no-auth connections",
6148
+ path: ["value"]
6149
+ });
6095
6150
  });
6096
6151
  object({
6097
6152
  label: string().trim().min(1).optional(),
6098
6153
  isDefault: boolean().optional(),
6099
- value: credentialSecretValueSchema.optional()
6100
- }).refine((input) => input.label !== void 0 || input.isDefault !== void 0 || input.value !== void 0, { message: "At least one field is required" });
6154
+ value: credentialSecretValueSchema.optional(),
6155
+ /** Move this credential to a different scope in place. */
6156
+ scope: AppCredentialScopeSchema.optional(),
6157
+ /** Required when `scope` is `project`. */
6158
+ projectSlug: string().trim().min(1).optional()
6159
+ }).superRefine((input, ctx) => {
6160
+ if (!(input.label !== void 0 || input.isDefault !== void 0 || input.value !== void 0 || input.scope !== void 0)) ctx.addIssue({
6161
+ code: "custom",
6162
+ message: "At least one field is required"
6163
+ });
6164
+ if (input.scope === "project" && !input.projectSlug) ctx.addIssue({
6165
+ code: "custom",
6166
+ message: "projectSlug is required when scope is project",
6167
+ path: ["projectSlug"]
6168
+ });
6169
+ if (input.scope !== "project" && input.projectSlug !== void 0) ctx.addIssue({
6170
+ code: "custom",
6171
+ message: "projectSlug is only valid when scope is project",
6172
+ path: ["projectSlug"]
6173
+ });
6174
+ });
6175
+ CredentialTargetsFieldsSchema.omit({ credentialInstanceId: true }).superRefine((input, ctx) => {
6176
+ if (!hasCredentialTarget(input)) addMissingCredentialTargetIssue(ctx);
6177
+ });
6101
6178
  object({
6102
6179
  limit: number().int().min(1).max(200).optional(),
6103
6180
  cursor: string().min(1).optional()
@@ -6199,11 +6276,61 @@ object({
6199
6276
  "org-deletion",
6200
6277
  "contact",
6201
6278
  "enterprise-upgrade",
6202
- "verification"
6279
+ "verification",
6280
+ "slack-connect",
6281
+ "connector-access"
6203
6282
  ]),
6204
- message: string().trim().max(5e3).optional()
6283
+ message: string().trim().max(5e3).optional(),
6284
+ /** Required for connector-access requests (sandbox VM secret exposure). */
6285
+ appSlug: string().trim().min(1).optional()
6286
+ }).superRefine((value, ctx) => {
6287
+ if (value.type === "connector-access" && !value.appSlug) ctx.addIssue({
6288
+ code: ZodIssueCode.custom,
6289
+ path: ["appSlug"],
6290
+ message: "appSlug is required for connector-access requests"
6291
+ });
6205
6292
  });
6206
6293
  object({ ok: literal(true) });
6294
+ object({
6295
+ message: string().trim().min(1).max(1e4),
6296
+ cliVersion: string().trim().min(1).max(64).optional(),
6297
+ projectSlug: string().trim().min(1).max(128).optional()
6298
+ });
6299
+ object({ ok: literal(true) });
6300
+ const TemplateKindSchema = _enum([
6301
+ "agent",
6302
+ "workflow",
6303
+ "both"
6304
+ ]);
6305
+ object({
6306
+ kind: TemplateKindSchema,
6307
+ title: string().min(1),
6308
+ description: string().min(1),
6309
+ tags: array(string().min(1)).default([]),
6310
+ requiredApps: array(string().min(1)).default([])
6311
+ });
6312
+ object({
6313
+ slug: string().min(1),
6314
+ kind: TemplateKindSchema,
6315
+ title: string().min(1),
6316
+ description: string().min(1),
6317
+ tags: array(string()),
6318
+ requiredApps: array(string()),
6319
+ updatedAt: string().datetime()
6320
+ }).extend({ files: record(string(), string()) });
6321
+ object({
6322
+ slug: string().min(1),
6323
+ files: record(string(), string())
6324
+ });
6325
+ object({
6326
+ slug: string().min(1),
6327
+ kind: TemplateKindSchema,
6328
+ title: string().min(1),
6329
+ description: string().min(1),
6330
+ tags: array(string()).default([]),
6331
+ requiredApps: array(string()).default([]),
6332
+ files: record(string(), string())
6333
+ });
6207
6334
  const MarketingContactCompanySizeSchema = _enum([
6208
6335
  "1-10",
6209
6336
  "11-50",
@@ -6220,6 +6347,46 @@ object({
6220
6347
  companyWebsite: string().optional()
6221
6348
  });
6222
6349
  object({ models: array(string()) });
6350
+ object({ accessToken: string() });
6351
+ const CredentialAccessUnavailableReasonSchema = _enum(["request_access", "reconnect_required"]);
6352
+ object({
6353
+ error: literal("credential_access_unavailable"),
6354
+ code: literal("credential_access_unavailable"),
6355
+ appSlug: string().min(1),
6356
+ reason: CredentialAccessUnavailableReasonSchema,
6357
+ requestAccessUrl: string().url().optional(),
6358
+ message: string().optional()
6359
+ });
6360
+ discriminatedUnion("kind", [
6361
+ object({
6362
+ kind: literal("api_key"),
6363
+ instanceId: string().min(1)
6364
+ }),
6365
+ object({
6366
+ kind: literal("oauth"),
6367
+ connectionId: string().min(1)
6368
+ }),
6369
+ object({
6370
+ kind: literal("keystroke"),
6371
+ instanceId: string().min(1),
6372
+ connectionId: string().min(1),
6373
+ appSlug: string().min(1)
6374
+ })
6375
+ ]);
6376
+ discriminatedUnion("kind", [
6377
+ object({
6378
+ kind: literal("api_key"),
6379
+ value: unknown()
6380
+ }),
6381
+ object({
6382
+ kind: literal("oauth"),
6383
+ accessToken: string().min(1)
6384
+ }),
6385
+ object({
6386
+ kind: literal("keystroke"),
6387
+ value: unknown()
6388
+ })
6389
+ ]);
6223
6390
  const ValidationErrorDetailSchema = object({
6224
6391
  path: string(),
6225
6392
  message: string()
@@ -6228,7 +6395,14 @@ const ValidationErrorDetailSchema = object({
6228
6395
  const ErrorResponseCodeSchema = OrganizationSlugErrorCodeSchema.or(_enum([
6229
6396
  "needs_org_selection",
6230
6397
  "org_unverified",
6231
- "connector_unavailable"
6398
+ "connector_unavailable",
6399
+ "invalid_url",
6400
+ "url_not_allowed",
6401
+ "url_unreachable",
6402
+ "upstream_http_error",
6403
+ "spec_too_large",
6404
+ "spec_parse_error",
6405
+ "invalid_openapi"
6232
6406
  ]));
6233
6407
  object({
6234
6408
  error: string(),
@@ -6265,6 +6439,12 @@ const ChatAttachmentInputSchema = object({
6265
6439
  mediaType: string().min(1),
6266
6440
  filename: string().optional()
6267
6441
  });
6442
+ object({
6443
+ type: literal("file"),
6444
+ mediaType: string().min(1),
6445
+ url: string().min(1),
6446
+ filename: string().optional()
6447
+ });
6268
6448
  object({
6269
6449
  contentType: string().min(1),
6270
6450
  filename: string().min(1),
@@ -6345,12 +6525,7 @@ object({
6345
6525
  params: array(unknown()).default([]),
6346
6526
  method: string().min(1).optional()
6347
6527
  });
6348
- object({ migrations: array(object({
6349
- sql: array(string().min(1)),
6350
- hash: string().min(1),
6351
- folderMillis: number$1()
6352
- })) });
6353
- object({ results: array(object({ rows: array(unknown()) })) });
6528
+ object({ rows: array(unknown()) });
6354
6529
  const RunSourceKindSchema = _enum([
6355
6530
  "api",
6356
6531
  "trigger",
@@ -6380,6 +6555,10 @@ object({
6380
6555
  description: string().nullable().optional(),
6381
6556
  type: AgentTriggerTypeSchema,
6382
6557
  schedule: string().nullable(),
6558
+ /** IANA timezone for schedule wall-clock fields. Null when omitted (evaluates in UTC). */
6559
+ timezone: string().nullable(),
6560
+ /** ISO timestamptz of the next scheduled fire. Null for webhooks / unset. */
6561
+ nextRunAt: string().nullable(),
6383
6562
  endpoint: string().nullable(),
6384
6563
  origin: AgentTriggerOriginSchema,
6385
6564
  prompt: string().nullable(),
@@ -6536,6 +6715,26 @@ const HistoryAgentCompactionEventSchema = object({
6536
6715
  retainedTailEstimate: number$1().optional(),
6537
6716
  durable: boolean()
6538
6717
  });
6718
+ /** Compact abnormal prompt-finish diagnostics from `agent_end` (optional on older events). */
6719
+ const HistoryAgentPromptFinishEventSchema = object({
6720
+ seq: number$1(),
6721
+ createdAt: string(),
6722
+ promptId: string().optional(),
6723
+ outcome: _enum([
6724
+ "completed",
6725
+ "error",
6726
+ "aborted"
6727
+ ]),
6728
+ finishReason: string().nullable(),
6729
+ rawFinishReason: string().optional(),
6730
+ stepCount: number$1(),
6731
+ maxSteps: number$1(),
6732
+ hitStepLimit: boolean(),
6733
+ error: object({
6734
+ name: string().optional(),
6735
+ message: string()
6736
+ }).optional()
6737
+ });
6539
6738
  const HistoryRunDetailSchema = discriminatedUnion("kind", [HistoryWorkflowRunDetailSchema, object({
6540
6739
  kind: literal("agent"),
6541
6740
  runId: string(),
@@ -6563,6 +6762,8 @@ const HistoryRunDetailSchema = discriminatedUnion("kind", [HistoryWorkflowRunDet
6563
6762
  messages: array(record(string(), unknown())),
6564
6763
  /** Sanitized context-compaction markers for the conversation timeline. */
6565
6764
  compactionEvents: array(HistoryAgentCompactionEventSchema).default([]),
6765
+ /** Abnormal prompt-finish diagnostics from `agent_end` (missing on historical events). */
6766
+ promptFinishEvents: array(HistoryAgentPromptFinishEventSchema).default([]),
6566
6767
  trace: HistoryTraceSchema.nullable(),
6567
6768
  ranAs: HistoryRunActorSchema.nullable().optional(),
6568
6769
  usage: HistoryRunUsageSchema.nullable().optional()
@@ -6807,6 +7008,7 @@ object({
6807
7008
  * log. Defaulted so older servers remain compatible.
6808
7009
  */
6809
7010
  compactionEvents: array(HistoryAgentCompactionEventSchema).default([]),
7011
+ promptFinishEvents: array(HistoryAgentPromptFinishEventSchema).default([]),
6810
7012
  trace: TraceResponseSchema.nullable()
6811
7013
  });
6812
7014
  const SlackGatewayModeSchema = _enum([
@@ -7061,6 +7263,10 @@ object({
7061
7263
  webhookUrl: string().nullable(),
7062
7264
  /** Cron expression or poll cadence label (cron/poll triggers only). */
7063
7265
  schedule: string().nullable(),
7266
+ /** IANA timezone for schedule wall-clock fields. Null when omitted (evaluates in UTC). */
7267
+ timezone: string().nullable(),
7268
+ /** ISO timestamptz of the next scheduled fire. Null for webhooks / unset. */
7269
+ nextRunAt: string().nullable(),
7064
7270
  /** Workflows + agents currently bound to this source. */
7065
7271
  assignments: array(TriggerAssignmentSchema),
7066
7272
  lastFiredAt: string().nullable(),
@@ -7101,6 +7307,8 @@ const TriggerOverviewInputSchema = object({
7101
7307
  description: string().nullable(),
7102
7308
  type: TriggerTypeSchema,
7103
7309
  schedule: string().nullable(),
7310
+ /** IANA timezone for schedule wall-clock fields. Null/omitted → UTC. */
7311
+ timezone: string().nullable().optional(),
7104
7312
  sourcePath: string(),
7105
7313
  sourceContents: string(),
7106
7314
  assignments: array(TriggerAssignmentSchema)
@@ -7286,6 +7494,13 @@ object({
7286
7494
  uploadUrl: url(),
7287
7495
  storageKey: string().min(1)
7288
7496
  });
7497
+ object({ contentType: string().trim().min(1) });
7498
+ object({
7499
+ uploadUrl: url(),
7500
+ storageKey: string().min(1)
7501
+ });
7502
+ object({ storageKey: string().min(1) });
7503
+ object({ logo: url() });
7289
7504
  const UserInterfaceThemeSchema = _enum([
7290
7505
  "system",
7291
7506
  "light",
@@ -7466,90 +7681,6 @@ object({
7466
7681
  lastOpenedAt: string().min(1),
7467
7682
  lastModifiedAt: string().min(1)
7468
7683
  });
7469
- const isoDateTime = string().datetime();
7470
- const sha256Hex = string().regex(/^[a-f0-9]{64}$/, "Expected a lowercase hex sha256 digest");
7471
- /**
7472
- * A single entry in a deploy's file tree, as served to the dashboard. Carries
7473
- * no contents: `id` is a stable, path-derived handle used for selection and
7474
- * `?file=` deep links; `hash` is the content address used to fetch the bytes
7475
- * lazily and to cache them immutably in the browser.
7476
- */
7477
- const ProjectFileSummarySchema = object({
7478
- id: string(),
7479
- path: string().min(1),
7480
- hash: sha256Hex
7481
- });
7482
- /** Maps a runtime resource slug (agent/workflow/skill) to its source file path. */
7483
- const ProjectSourceResourceRefSchema = object({
7484
- slug: string().min(1),
7485
- path: string().min(1)
7486
- });
7487
- const ProjectSourceResourcesSchema = object({
7488
- agents: array(ProjectSourceResourceRefSchema).default([]),
7489
- workflows: array(ProjectSourceResourceRefSchema).default([]),
7490
- skills: array(ProjectSourceResourceRefSchema).default([])
7491
- });
7492
- const emptyResources = () => ({
7493
- agents: [],
7494
- workflows: [],
7495
- skills: []
7496
- });
7497
- object({
7498
- artifactId: string().nullable(),
7499
- files: array(ProjectFileSummarySchema),
7500
- resources: ProjectSourceResourcesSchema.default(emptyResources())
7501
- });
7502
- object({
7503
- path: string().min(1),
7504
- contents: string(),
7505
- hash: sha256Hex
7506
- });
7507
- object({ blobs: array(object({
7508
- hash: sha256Hex,
7509
- size: number$1().int().nonnegative()
7510
- })) });
7511
- object({ uploads: array(object({
7512
- hash: sha256Hex,
7513
- url: string().url()
7514
- })) });
7515
- object({ files: array(object({
7516
- path: string().min(1),
7517
- hash: sha256Hex
7518
- })) });
7519
- object({
7520
- ok: literal(true),
7521
- fileCount: number$1().int().nonnegative()
7522
- });
7523
- object({
7524
- files: array(object({
7525
- id: string(),
7526
- path: string().min(1),
7527
- hash: sha256Hex
7528
- })),
7529
- generatedAt: isoDateTime
7530
- });
7531
- /** A single source file returned by the bulk active-source download endpoint. */
7532
- const DownloadActiveProjectSourceFileSchema = object({
7533
- path: string().min(1),
7534
- contents: string()
7535
- });
7536
- object({
7537
- artifactId: string(),
7538
- files: array(DownloadActiveProjectSourceFileSchema)
7539
- });
7540
- object({
7541
- projectId: string(),
7542
- artifactId: string(),
7543
- pulledAt: string().datetime()
7544
- });
7545
- object({ files: array(object({
7546
- id: string(),
7547
- path: string().min(1)
7548
- })) });
7549
- object({ files: array(object({
7550
- id: string(),
7551
- path: string().min(1)
7552
- })) });
7553
7684
  /** Whether the overview is still being produced or finished. */
7554
7685
  const WorkflowOverviewStatusSchema = _enum(["generating", "ready"]);
7555
7686
  /** One phase of the guided-tour overview. */
@@ -7574,7 +7705,8 @@ const WorkflowInputFieldTypeSchema = _enum([
7574
7705
  "boolean",
7575
7706
  "enum",
7576
7707
  "object",
7577
- "array"
7708
+ "array",
7709
+ "file"
7578
7710
  ]);
7579
7711
  const WorkflowInputFieldSchema = lazy(() => object({
7580
7712
  key: string(),
@@ -7589,6 +7721,8 @@ const WorkflowInputFieldSchema = lazy(() => object({
7589
7721
  number$1(),
7590
7722
  boolean()
7591
7723
  ]).optional(),
7724
+ minimum: number$1().optional(),
7725
+ maximum: number$1().optional(),
7592
7726
  children: array(WorkflowInputFieldSchema).optional(),
7593
7727
  format: string().optional()
7594
7728
  }));
@@ -7788,6 +7922,159 @@ const WorkflowCanvasCredentialBindingSchema = union([
7788
7922
  })
7789
7923
  ]);
7790
7924
  record(string(), array(WorkflowCanvasCredentialBindingSchema));
7925
+ const FormControlSchema = _enum([
7926
+ "input",
7927
+ "textarea",
7928
+ "select",
7929
+ "radio",
7930
+ "stepper",
7931
+ "slider",
7932
+ "checkbox",
7933
+ "switch"
7934
+ ]);
7935
+ const FormFieldConfigEntrySchema = object({
7936
+ label: string().trim().min(1).max(120).optional(),
7937
+ helpText: string().trim().min(1).max(300).optional(),
7938
+ placeholder: string().trim().min(1).max(200).optional(),
7939
+ control: FormControlSchema.optional()
7940
+ });
7941
+ const FormFieldConfigSchema = record(string(), FormFieldConfigEntrySchema);
7942
+ const PublicFormFieldSchema = WorkflowInputFieldSchema.and(object({
7943
+ control: FormControlSchema.optional(),
7944
+ helpText: string().optional()
7945
+ }));
7946
+ const PublishedFormSchema = object({
7947
+ id: string().min(1),
7948
+ workflowId: string().min(1),
7949
+ workflowSlug: string().min(1),
7950
+ enabled: boolean(),
7951
+ title: string().min(1).nullable(),
7952
+ description: string().min(1).nullable(),
7953
+ fieldConfig: FormFieldConfigSchema,
7954
+ publicUrl: string().url(),
7955
+ createdAt: string().min(1),
7956
+ updatedAt: string().min(1)
7957
+ });
7958
+ object({
7959
+ id: string().min(1),
7960
+ projectId: string().min(1),
7961
+ workflowSlug: string().min(1),
7962
+ enabled: boolean(),
7963
+ title: string().min(1).nullable(),
7964
+ description: string().min(1).nullable(),
7965
+ fieldConfig: FormFieldConfigSchema,
7966
+ publicUrl: string().url(),
7967
+ createdAt: string().min(1),
7968
+ updatedAt: string().min(1)
7969
+ });
7970
+ PublishedFormSchema.nullable();
7971
+ object({
7972
+ enabled: boolean().optional(),
7973
+ title: string().trim().min(1).max(120).nullable().optional(),
7974
+ description: string().trim().min(1).max(500).nullable().optional(),
7975
+ fieldConfig: FormFieldConfigSchema.optional()
7976
+ });
7977
+ object({
7978
+ title: string().min(1),
7979
+ description: string().nullable(),
7980
+ fields: array(PublicFormFieldSchema),
7981
+ branding: object({
7982
+ organizationName: string().min(1),
7983
+ projectName: string().min(1),
7984
+ logoLightUrl: string().url().nullable(),
7985
+ logoDarkUrl: string().url().nullable(),
7986
+ logoHeightPx: number$1().int().positive()
7987
+ })
7988
+ });
7989
+ object({
7990
+ values: record(string(), unknown()),
7991
+ website: string().max(200).optional()
7992
+ });
7993
+ object({ ok: literal(true) });
7994
+ const isoDateTime = string().datetime();
7995
+ const sha256Hex = string().regex(/^[a-f0-9]{64}$/, "Expected a lowercase hex sha256 digest");
7996
+ /**
7997
+ * A single entry in a deploy's file tree, as served to the dashboard. Carries
7998
+ * no contents: `id` is a stable, path-derived handle used for selection and
7999
+ * `?file=` deep links; `hash` is the content address used to fetch the bytes
8000
+ * lazily and to cache them immutably in the browser.
8001
+ */
8002
+ const ProjectFileSummarySchema = object({
8003
+ id: string(),
8004
+ path: string().min(1),
8005
+ hash: sha256Hex
8006
+ });
8007
+ /** Maps a runtime resource slug (agent/workflow/skill) to its source file path. */
8008
+ const ProjectSourceResourceRefSchema = object({
8009
+ slug: string().min(1),
8010
+ path: string().min(1)
8011
+ });
8012
+ const ProjectSourceResourcesSchema = object({
8013
+ agents: array(ProjectSourceResourceRefSchema).default([]),
8014
+ workflows: array(ProjectSourceResourceRefSchema).default([]),
8015
+ skills: array(ProjectSourceResourceRefSchema).default([])
8016
+ });
8017
+ const emptyResources = () => ({
8018
+ agents: [],
8019
+ workflows: [],
8020
+ skills: []
8021
+ });
8022
+ object({
8023
+ artifactId: string().nullable(),
8024
+ files: array(ProjectFileSummarySchema),
8025
+ resources: ProjectSourceResourcesSchema.default(emptyResources())
8026
+ });
8027
+ object({
8028
+ path: string().min(1),
8029
+ contents: string(),
8030
+ hash: sha256Hex
8031
+ });
8032
+ object({ blobs: array(object({
8033
+ hash: sha256Hex,
8034
+ size: number$1().int().nonnegative()
8035
+ })) });
8036
+ object({ uploads: array(object({
8037
+ hash: sha256Hex,
8038
+ url: string().url()
8039
+ })) });
8040
+ object({ files: array(object({
8041
+ path: string().min(1),
8042
+ hash: sha256Hex
8043
+ })) });
8044
+ object({
8045
+ ok: literal(true),
8046
+ fileCount: number$1().int().nonnegative()
8047
+ });
8048
+ object({
8049
+ files: array(object({
8050
+ id: string(),
8051
+ path: string().min(1),
8052
+ hash: sha256Hex
8053
+ })),
8054
+ generatedAt: isoDateTime
8055
+ });
8056
+ /** A single source file returned by the bulk active-source download endpoint. */
8057
+ const DownloadActiveProjectSourceFileSchema = object({
8058
+ path: string().min(1),
8059
+ contents: string()
8060
+ });
8061
+ object({
8062
+ artifactId: string(),
8063
+ files: array(DownloadActiveProjectSourceFileSchema)
8064
+ });
8065
+ object({
8066
+ projectId: string(),
8067
+ artifactId: string(),
8068
+ pulledAt: string().datetime()
8069
+ });
8070
+ object({ files: array(object({
8071
+ id: string(),
8072
+ path: string().min(1)
8073
+ })) });
8074
+ object({ files: array(object({
8075
+ id: string(),
8076
+ path: string().min(1)
8077
+ })) });
7791
8078
  record(string(), unknown());
7792
8079
  //#endregion
7793
8080
  //#region src/runtime.ts
@@ -7801,7 +8088,7 @@ function parseOrgArtifactsFromEnv(env = process.env) {
7801
8088
  const parsed = JSON.parse(Buffer.from(raw, "base64").toString("utf8"));
7802
8089
  if (!Array.isArray(parsed)) throw new Error("KEYSTROKE_ORG_ARTIFACTS must decode to a JSON array");
7803
8090
  return parsed.map((entry) => {
7804
- if (!entry || typeof entry !== "object" || typeof entry.projectId !== "string" || typeof entry.artifactStorageKey !== "string") throw new Error("KEYSTROKE_ORG_ARTIFACTS entries require projectId and artifactStorageKey");
8091
+ if (!entry || typeof entry !== "object" || typeof entry.projectId !== "string" || typeof entry.artifactStorageKey !== "string" || typeof entry.artifactId !== "string" || typeof entry.artifactVersion !== "number") throw new Error("KEYSTROKE_ORG_ARTIFACTS entries require projectId, artifactStorageKey, artifactId, and artifactVersion");
7805
8092
  return entry;
7806
8093
  });
7807
8094
  }
@@ -7839,10 +8126,22 @@ const RUNTIME_ENV_KEYS = [
7839
8126
  "REDIS_URL",
7840
8127
  "KEYSTROKE_QUEUE_PREFIX"
7841
8128
  ];
8129
+ /**
8130
+ * Observability ingest config for org workers (PostHog error tracking + crash reports).
8131
+ * Ingest tokens only — never forward `POSTHOG_API_KEY` (management) into workers.
8132
+ */
8133
+ const OBSERVABILITY_ENV_KEYS = [
8134
+ "POSTHOG_PROJECT_TOKEN",
8135
+ "POSTHOG_HOST",
8136
+ "POSTHOG_FLUSH_MODE",
8137
+ "KEYSTROKE_ENVIRONMENT",
8138
+ "KEYSTROKE_RELEASE"
8139
+ ];
7842
8140
  /** Env keys that must never be forwarded into untrusted org workers. */
7843
8141
  const FORBIDDEN_WORKER_ENV_KEYS = [
7844
8142
  "BETTER_AUTH_SECRET",
7845
8143
  "DATABASE_URL",
8144
+ "POSTHOG_API_KEY",
7846
8145
  "POSTGRES_PASSWORD",
7847
8146
  "PLATFORM_WORKER_TOKEN",
7848
8147
  "STRIPE_SECRET_KEY",
@@ -7886,6 +8185,11 @@ function buildRuntimeEnv(source, artifacts, database, extraEnv) {
7886
8185
  if (!value) continue;
7887
8186
  entries.set(key, value);
7888
8187
  }
8188
+ for (const key of OBSERVABILITY_ENV_KEYS) {
8189
+ const value = source[key]?.trim();
8190
+ if (!value) continue;
8191
+ entries.set(key, value);
8192
+ }
7889
8193
  if (!extraEnv) for (const key of PROVIDER_ENV_KEYS) {
7890
8194
  const value = source[key]?.trim();
7891
8195
  if (value) entries.set(key, value);
@@ -7986,7 +8290,9 @@ function createDockerRuntime(options = {}) {
7986
8290
  if (input.projects.length === 0) throw new Error("Docker org runtime requires at least one project deploy");
7987
8291
  let launch = resolveRuntimeLaunch(options, input.projects.map((project) => ({
7988
8292
  projectId: project.projectId,
7989
- artifactStorageKey: project.artifactStorageKey
8293
+ artifactStorageKey: project.artifactStorageKey,
8294
+ artifactId: project.artifactId,
8295
+ artifactVersion: project.artifactVersion
7990
8296
  })), input.database, input.env);
7991
8297
  if (options.workspacesMount) {
7992
8298
  const { hostPath, containerPath } = options.workspacesMount;