@keystrokehq/hosting 0.1.12 → 0.1.14

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
@@ -4397,8 +4397,11 @@ function superRefine(fn, params) {
4397
4397
  function number(params) {
4398
4398
  return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
4399
4399
  }
4400
- //#endregion
4401
- //#region ../shared/dist/index.mjs
4400
+ new Set([
4401
+ "hello",
4402
+ "greeting",
4403
+ "greet"
4404
+ ]);
4402
4405
  /** Auth, session, and account-entry URL segments. */
4403
4406
  const AUTH_ACCOUNT_SLUGS = [
4404
4407
  "2fa",
@@ -4510,6 +4513,7 @@ const PRODUCT_SLUGS = [
4510
4513
  "execution",
4511
4514
  "executions",
4512
4515
  "explore",
4516
+ "forms",
4513
4517
  "get-started",
4514
4518
  "history",
4515
4519
  "inbox",
@@ -5377,6 +5381,8 @@ const storedRouteManifestEntryV2Schema = discriminatedUnion("kind", [
5377
5381
  moduleFile: string(),
5378
5382
  sourceHash: string().optional(),
5379
5383
  schedule: string(),
5384
+ /** IANA timezone for schedule wall-clock fields. When omitted, UTC. */
5385
+ timezone: string().optional(),
5380
5386
  name: requiredDisplayTextSchema,
5381
5387
  description: requiredDisplayTextSchema
5382
5388
  }),
@@ -5385,7 +5391,9 @@ const storedRouteManifestEntryV2Schema = discriminatedUnion("kind", [
5385
5391
  pollId: string(),
5386
5392
  attachmentIds: array(string()),
5387
5393
  moduleFile: string(),
5388
- schedule: string()
5394
+ schedule: string(),
5395
+ /** IANA timezone for schedule wall-clock fields. When omitted, UTC. */
5396
+ timezone: string().optional()
5389
5397
  }),
5390
5398
  object({
5391
5399
  kind: literal("cron-schedule"),
@@ -5394,6 +5402,8 @@ const storedRouteManifestEntryV2Schema = discriminatedUnion("kind", [
5394
5402
  moduleFile: string(),
5395
5403
  sourceHash: string().optional(),
5396
5404
  schedule: string(),
5405
+ /** IANA timezone for schedule wall-clock fields. When omitted, UTC. */
5406
+ timezone: string().optional(),
5397
5407
  /** Static cron payload from `defineCronSource({ payload })` — omitted when the source has none. */
5398
5408
  payload: unknown().optional(),
5399
5409
  name: requiredDisplayTextSchema,
@@ -5438,6 +5448,8 @@ const AutoTopupSummarySchema = object({
5438
5448
  const PlanLimitsSchema = object({
5439
5449
  includedStorageGb: number$1(),
5440
5450
  concurrencyLimit: number$1(),
5451
+ /** Max non-deleted projects; enforced on create only. */
5452
+ maxProjects: number$1(),
5441
5453
  agentTimeoutMs: number$1(),
5442
5454
  workflowTimeoutMs: number$1(),
5443
5455
  pollTimeoutMs: number$1(),
@@ -5451,8 +5463,15 @@ const PlanLimitsSchema = object({
5451
5463
  object({
5452
5464
  planKey: string(),
5453
5465
  subscriptionStatus: subscriptionStatusSchema,
5466
+ /** Remaining plan-bucket balance this period (µc). */
5454
5467
  planCreditMicroCredits: number$1(),
5468
+ /** Remaining prepaid balance (µc). Never expires. */
5455
5469
  prepaidCreditMicroCredits: number$1(),
5470
+ /**
5471
+ * Resolved monthly plan allotment (µc) — override ?? preset. Powers the
5472
+ * credit-usage progress denominator (`used = allotment − remaining`).
5473
+ */
5474
+ monthlyCreditMicroCredits: number$1(),
5456
5475
  periodStart: isoDateTime$6.nullable(),
5457
5476
  periodEnd: isoDateTime$6.nullable(),
5458
5477
  autoTopup: AutoTopupSummarySchema,
@@ -5695,7 +5714,8 @@ object({
5695
5714
  });
5696
5715
  const NewChannelBindingInputSchema = object({
5697
5716
  channelId: string().min(1),
5698
- channelName: string().min(1),
5717
+ /** Display name. When omitted or equal to `channelId`, the server resolves it from Slack. */
5718
+ channelName: string().min(1).optional(),
5699
5719
  channelKind: ChannelBindingKindSchema.optional(),
5700
5720
  mode: ChannelListenModeSchema.optional(),
5701
5721
  subscribeOnMention: boolean().optional()
@@ -5757,12 +5777,13 @@ const AppAuthKindSchema = _enum([
5757
5777
  "api_key",
5758
5778
  "keystroke"
5759
5779
  ]);
5760
- /** Composio auth scheme for API-key style connections. */
5780
+ /** Composio auth scheme for API-key / no-auth style connections. */
5761
5781
  const AppCredentialSchemeSchema = _enum([
5762
5782
  "API_KEY",
5763
5783
  "BEARER_TOKEN",
5764
5784
  "BASIC",
5765
- "BASIC_WITH_JWT"
5785
+ "BASIC_WITH_JWT",
5786
+ "NO_AUTH"
5766
5787
  ]);
5767
5788
  /**
5768
5789
  * Where app metadata and execution are sourced (e.g. native, composio, pipedream, custom).
@@ -5804,6 +5825,7 @@ object({
5804
5825
  "graphql"
5805
5826
  ]).default("custom"),
5806
5827
  url: string().url().optional(),
5828
+ logo: string().url().optional(),
5807
5829
  authKind: AppAuthKindSchema.optional(),
5808
5830
  fields: optionalCredentialFieldsSchema.optional(),
5809
5831
  credentialScheme: AppCredentialSchemeSchema.optional(),
@@ -5839,6 +5861,7 @@ object({
5839
5861
  authKind: AppAuthKindSchema,
5840
5862
  source: AppSourceSchema,
5841
5863
  url: string().url().nullable().optional(),
5864
+ logo: string().url().nullable().optional(),
5842
5865
  credentialFields: optionalCredentialFieldsSchema.optional(),
5843
5866
  credentialScheme: AppCredentialSchemeSchema.optional(),
5844
5867
  oauthScopes: array(OAuthScopeOptionSchema).optional(),
@@ -5875,12 +5898,14 @@ object({
5875
5898
  /** Endpoint URL for MCP, OpenAPI, or GraphQL custom apps. */
5876
5899
  url: string().url().nullable().optional(),
5877
5900
  /** True when the app has a non-empty credential field template. */
5878
- hasCredentialFields: boolean().optional()
5901
+ hasCredentialFields: boolean().optional(),
5902
+ /** Composio auth scheme — present for API-key and NO_AUTH apps so the picker can choose a flow. */
5903
+ credentialScheme: AppCredentialSchemeSchema.optional()
5879
5904
  }).extend({
5880
5905
  oauthScopes: array(OAuthScopeOptionSchema),
5881
5906
  /** Custom api_key apps — vault field template for connect UI and sync. */
5882
5907
  credentialFields: AppCredentialFieldsSchema.optional(),
5883
- /** Composio auth scheme when credentialFields are present. */
5908
+ /** Composio auth scheme for API-key or NO_AUTH connections. */
5884
5909
  credentialScheme: AppCredentialSchemeSchema.optional(),
5885
5910
  /** When present, the app supports agent gateway bindings (external channels). */
5886
5911
  gateway: AppGatewaySchema.optional()
@@ -5997,8 +6022,12 @@ const AppCredentialScopeSchema = _enum([
5997
6022
  "project",
5998
6023
  "organization"
5999
6024
  ]);
6000
- /** How the credential was connected (OAuth vs manual api-key entry). */
6001
- const AppCredentialConnectionKindSchema = _enum(["oauth", "manual"]);
6025
+ /** How the credential was connected (OAuth, manual api-key entry, or no-auth). */
6026
+ const AppCredentialConnectionKindSchema = _enum([
6027
+ "oauth",
6028
+ "manual",
6029
+ "none"
6030
+ ]);
6002
6031
  /** Connect-dialog permission preset for OAuth scope selection. */
6003
6032
  const OAuthPermissionModeSchema = _enum(["default", "restricted"]);
6004
6033
  const optionalTimestamp$1 = string().optional();
@@ -6092,12 +6121,39 @@ CredentialTargetsFieldsSchema.extend({
6092
6121
  message: "OAuth credentials are created via the OAuth callback",
6093
6122
  path: ["connectionKind"]
6094
6123
  });
6124
+ if (input.connectionKind === "none" && input.value) ctx.addIssue({
6125
+ code: "custom",
6126
+ message: "value is not allowed for no-auth connections",
6127
+ path: ["value"]
6128
+ });
6095
6129
  });
6096
6130
  object({
6097
6131
  label: string().trim().min(1).optional(),
6098
6132
  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" });
6133
+ value: credentialSecretValueSchema.optional(),
6134
+ /** Move this credential to a different scope in place. */
6135
+ scope: AppCredentialScopeSchema.optional(),
6136
+ /** Required when `scope` is `project`. */
6137
+ projectSlug: string().trim().min(1).optional()
6138
+ }).superRefine((input, ctx) => {
6139
+ if (!(input.label !== void 0 || input.isDefault !== void 0 || input.value !== void 0 || input.scope !== void 0)) ctx.addIssue({
6140
+ code: "custom",
6141
+ message: "At least one field is required"
6142
+ });
6143
+ if (input.scope === "project" && !input.projectSlug) ctx.addIssue({
6144
+ code: "custom",
6145
+ message: "projectSlug is required when scope is project",
6146
+ path: ["projectSlug"]
6147
+ });
6148
+ if (input.scope !== "project" && input.projectSlug !== void 0) ctx.addIssue({
6149
+ code: "custom",
6150
+ message: "projectSlug is only valid when scope is project",
6151
+ path: ["projectSlug"]
6152
+ });
6153
+ });
6154
+ CredentialTargetsFieldsSchema.omit({ credentialInstanceId: true }).superRefine((input, ctx) => {
6155
+ if (!hasCredentialTarget(input)) addMissingCredentialTargetIssue(ctx);
6156
+ });
6101
6157
  object({
6102
6158
  limit: number().int().min(1).max(200).optional(),
6103
6159
  cursor: string().min(1).optional()
@@ -6199,11 +6255,46 @@ object({
6199
6255
  "org-deletion",
6200
6256
  "contact",
6201
6257
  "enterprise-upgrade",
6202
- "verification"
6258
+ "verification",
6259
+ "slack-connect"
6203
6260
  ]),
6204
6261
  message: string().trim().max(5e3).optional()
6205
6262
  });
6206
6263
  object({ ok: literal(true) });
6264
+ const TemplateKindSchema = _enum([
6265
+ "agent",
6266
+ "workflow",
6267
+ "both"
6268
+ ]);
6269
+ object({
6270
+ kind: TemplateKindSchema,
6271
+ title: string().min(1),
6272
+ description: string().min(1),
6273
+ tags: array(string().min(1)).default([]),
6274
+ requiredApps: array(string().min(1)).default([])
6275
+ });
6276
+ object({
6277
+ slug: string().min(1),
6278
+ kind: TemplateKindSchema,
6279
+ title: string().min(1),
6280
+ description: string().min(1),
6281
+ tags: array(string()),
6282
+ requiredApps: array(string()),
6283
+ updatedAt: string().datetime()
6284
+ }).extend({ files: record(string(), string()) });
6285
+ object({
6286
+ slug: string().min(1),
6287
+ files: record(string(), string())
6288
+ });
6289
+ object({
6290
+ slug: string().min(1),
6291
+ kind: TemplateKindSchema,
6292
+ title: string().min(1),
6293
+ description: string().min(1),
6294
+ tags: array(string()).default([]),
6295
+ requiredApps: array(string()).default([]),
6296
+ files: record(string(), string())
6297
+ });
6207
6298
  const MarketingContactCompanySizeSchema = _enum([
6208
6299
  "1-10",
6209
6300
  "11-50",
@@ -6228,7 +6319,14 @@ const ValidationErrorDetailSchema = object({
6228
6319
  const ErrorResponseCodeSchema = OrganizationSlugErrorCodeSchema.or(_enum([
6229
6320
  "needs_org_selection",
6230
6321
  "org_unverified",
6231
- "connector_unavailable"
6322
+ "connector_unavailable",
6323
+ "invalid_url",
6324
+ "url_not_allowed",
6325
+ "url_unreachable",
6326
+ "upstream_http_error",
6327
+ "spec_too_large",
6328
+ "spec_parse_error",
6329
+ "invalid_openapi"
6232
6330
  ]));
6233
6331
  object({
6234
6332
  error: string(),
@@ -6265,6 +6363,12 @@ const ChatAttachmentInputSchema = object({
6265
6363
  mediaType: string().min(1),
6266
6364
  filename: string().optional()
6267
6365
  });
6366
+ object({
6367
+ type: literal("file"),
6368
+ mediaType: string().min(1),
6369
+ url: string().min(1),
6370
+ filename: string().optional()
6371
+ });
6268
6372
  object({
6269
6373
  contentType: string().min(1),
6270
6374
  filename: string().min(1),
@@ -6345,12 +6449,7 @@ object({
6345
6449
  params: array(unknown()).default([]),
6346
6450
  method: string().min(1).optional()
6347
6451
  });
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()) })) });
6452
+ object({ rows: array(unknown()) });
6354
6453
  const RunSourceKindSchema = _enum([
6355
6454
  "api",
6356
6455
  "trigger",
@@ -6380,6 +6479,10 @@ object({
6380
6479
  description: string().nullable().optional(),
6381
6480
  type: AgentTriggerTypeSchema,
6382
6481
  schedule: string().nullable(),
6482
+ /** IANA timezone for schedule wall-clock fields. Null when omitted (evaluates in UTC). */
6483
+ timezone: string().nullable(),
6484
+ /** ISO timestamptz of the next scheduled fire. Null for webhooks / unset. */
6485
+ nextRunAt: string().nullable(),
6383
6486
  endpoint: string().nullable(),
6384
6487
  origin: AgentTriggerOriginSchema,
6385
6488
  prompt: string().nullable(),
@@ -6395,6 +6498,7 @@ const HistoryRunStatusSchema = _enum([
6395
6498
  "running",
6396
6499
  "sleeping",
6397
6500
  "waiting_hook",
6501
+ "waiting_children",
6398
6502
  "completed",
6399
6503
  "failed",
6400
6504
  "canceled"
@@ -6535,6 +6639,26 @@ const HistoryAgentCompactionEventSchema = object({
6535
6639
  retainedTailEstimate: number$1().optional(),
6536
6640
  durable: boolean()
6537
6641
  });
6642
+ /** Compact abnormal prompt-finish diagnostics from `agent_end` (optional on older events). */
6643
+ const HistoryAgentPromptFinishEventSchema = object({
6644
+ seq: number$1(),
6645
+ createdAt: string(),
6646
+ promptId: string().optional(),
6647
+ outcome: _enum([
6648
+ "completed",
6649
+ "error",
6650
+ "aborted"
6651
+ ]),
6652
+ finishReason: string().nullable(),
6653
+ rawFinishReason: string().optional(),
6654
+ stepCount: number$1(),
6655
+ maxSteps: number$1(),
6656
+ hitStepLimit: boolean(),
6657
+ error: object({
6658
+ name: string().optional(),
6659
+ message: string()
6660
+ }).optional()
6661
+ });
6538
6662
  const HistoryRunDetailSchema = discriminatedUnion("kind", [HistoryWorkflowRunDetailSchema, object({
6539
6663
  kind: literal("agent"),
6540
6664
  runId: string(),
@@ -6562,6 +6686,8 @@ const HistoryRunDetailSchema = discriminatedUnion("kind", [HistoryWorkflowRunDet
6562
6686
  messages: array(record(string(), unknown())),
6563
6687
  /** Sanitized context-compaction markers for the conversation timeline. */
6564
6688
  compactionEvents: array(HistoryAgentCompactionEventSchema).default([]),
6689
+ /** Abnormal prompt-finish diagnostics from `agent_end` (missing on historical events). */
6690
+ promptFinishEvents: array(HistoryAgentPromptFinishEventSchema).default([]),
6565
6691
  trace: HistoryTraceSchema.nullable(),
6566
6692
  ranAs: HistoryRunActorSchema.nullable().optional(),
6567
6693
  usage: HistoryRunUsageSchema.nullable().optional()
@@ -6579,6 +6705,7 @@ const WorkflowRunStatusSchema = _enum([
6579
6705
  "running",
6580
6706
  "sleeping",
6581
6707
  "waiting_hook",
6708
+ "waiting_children",
6582
6709
  "completed",
6583
6710
  "failed",
6584
6711
  "canceled"
@@ -6599,6 +6726,7 @@ _enum([
6599
6726
  "sleep_completed",
6600
6727
  "hook_created",
6601
6728
  "hook_resumed",
6729
+ "child_dispatched",
6602
6730
  "run_completed",
6603
6731
  "run_failed",
6604
6732
  "run_canceled"
@@ -6804,6 +6932,7 @@ object({
6804
6932
  * log. Defaulted so older servers remain compatible.
6805
6933
  */
6806
6934
  compactionEvents: array(HistoryAgentCompactionEventSchema).default([]),
6935
+ promptFinishEvents: array(HistoryAgentPromptFinishEventSchema).default([]),
6807
6936
  trace: TraceResponseSchema.nullable()
6808
6937
  });
6809
6938
  const SlackGatewayModeSchema = _enum([
@@ -7058,6 +7187,10 @@ object({
7058
7187
  webhookUrl: string().nullable(),
7059
7188
  /** Cron expression or poll cadence label (cron/poll triggers only). */
7060
7189
  schedule: string().nullable(),
7190
+ /** IANA timezone for schedule wall-clock fields. Null when omitted (evaluates in UTC). */
7191
+ timezone: string().nullable(),
7192
+ /** ISO timestamptz of the next scheduled fire. Null for webhooks / unset. */
7193
+ nextRunAt: string().nullable(),
7061
7194
  /** Workflows + agents currently bound to this source. */
7062
7195
  assignments: array(TriggerAssignmentSchema),
7063
7196
  lastFiredAt: string().nullable(),
@@ -7098,6 +7231,8 @@ const TriggerOverviewInputSchema = object({
7098
7231
  description: string().nullable(),
7099
7232
  type: TriggerTypeSchema,
7100
7233
  schedule: string().nullable(),
7234
+ /** IANA timezone for schedule wall-clock fields. Null/omitted → UTC. */
7235
+ timezone: string().nullable().optional(),
7101
7236
  sourcePath: string(),
7102
7237
  sourceContents: string(),
7103
7238
  assignments: array(TriggerAssignmentSchema)
@@ -7283,6 +7418,13 @@ object({
7283
7418
  uploadUrl: url(),
7284
7419
  storageKey: string().min(1)
7285
7420
  });
7421
+ object({ contentType: string().trim().min(1) });
7422
+ object({
7423
+ uploadUrl: url(),
7424
+ storageKey: string().min(1)
7425
+ });
7426
+ object({ storageKey: string().min(1) });
7427
+ object({ logo: url() });
7286
7428
  const UserInterfaceThemeSchema = _enum([
7287
7429
  "system",
7288
7430
  "light",
@@ -7463,90 +7605,6 @@ object({
7463
7605
  lastOpenedAt: string().min(1),
7464
7606
  lastModifiedAt: string().min(1)
7465
7607
  });
7466
- const isoDateTime = string().datetime();
7467
- const sha256Hex = string().regex(/^[a-f0-9]{64}$/, "Expected a lowercase hex sha256 digest");
7468
- /**
7469
- * A single entry in a deploy's file tree, as served to the dashboard. Carries
7470
- * no contents: `id` is a stable, path-derived handle used for selection and
7471
- * `?file=` deep links; `hash` is the content address used to fetch the bytes
7472
- * lazily and to cache them immutably in the browser.
7473
- */
7474
- const ProjectFileSummarySchema = object({
7475
- id: string(),
7476
- path: string().min(1),
7477
- hash: sha256Hex
7478
- });
7479
- /** Maps a runtime resource slug (agent/workflow/skill) to its source file path. */
7480
- const ProjectSourceResourceRefSchema = object({
7481
- slug: string().min(1),
7482
- path: string().min(1)
7483
- });
7484
- const ProjectSourceResourcesSchema = object({
7485
- agents: array(ProjectSourceResourceRefSchema).default([]),
7486
- workflows: array(ProjectSourceResourceRefSchema).default([]),
7487
- skills: array(ProjectSourceResourceRefSchema).default([])
7488
- });
7489
- const emptyResources = () => ({
7490
- agents: [],
7491
- workflows: [],
7492
- skills: []
7493
- });
7494
- object({
7495
- artifactId: string().nullable(),
7496
- files: array(ProjectFileSummarySchema),
7497
- resources: ProjectSourceResourcesSchema.default(emptyResources())
7498
- });
7499
- object({
7500
- path: string().min(1),
7501
- contents: string(),
7502
- hash: sha256Hex
7503
- });
7504
- object({ blobs: array(object({
7505
- hash: sha256Hex,
7506
- size: number$1().int().nonnegative()
7507
- })) });
7508
- object({ uploads: array(object({
7509
- hash: sha256Hex,
7510
- url: string().url()
7511
- })) });
7512
- object({ files: array(object({
7513
- path: string().min(1),
7514
- hash: sha256Hex
7515
- })) });
7516
- object({
7517
- ok: literal(true),
7518
- fileCount: number$1().int().nonnegative()
7519
- });
7520
- object({
7521
- files: array(object({
7522
- id: string(),
7523
- path: string().min(1),
7524
- hash: sha256Hex
7525
- })),
7526
- generatedAt: isoDateTime
7527
- });
7528
- /** A single source file returned by the bulk active-source download endpoint. */
7529
- const DownloadActiveProjectSourceFileSchema = object({
7530
- path: string().min(1),
7531
- contents: string()
7532
- });
7533
- object({
7534
- artifactId: string(),
7535
- files: array(DownloadActiveProjectSourceFileSchema)
7536
- });
7537
- object({
7538
- projectId: string(),
7539
- artifactId: string(),
7540
- pulledAt: string().datetime()
7541
- });
7542
- object({ files: array(object({
7543
- id: string(),
7544
- path: string().min(1)
7545
- })) });
7546
- object({ files: array(object({
7547
- id: string(),
7548
- path: string().min(1)
7549
- })) });
7550
7608
  /** Whether the overview is still being produced or finished. */
7551
7609
  const WorkflowOverviewStatusSchema = _enum(["generating", "ready"]);
7552
7610
  /** One phase of the guided-tour overview. */
@@ -7571,7 +7629,8 @@ const WorkflowInputFieldTypeSchema = _enum([
7571
7629
  "boolean",
7572
7630
  "enum",
7573
7631
  "object",
7574
- "array"
7632
+ "array",
7633
+ "file"
7575
7634
  ]);
7576
7635
  const WorkflowInputFieldSchema = lazy(() => object({
7577
7636
  key: string(),
@@ -7586,6 +7645,8 @@ const WorkflowInputFieldSchema = lazy(() => object({
7586
7645
  number$1(),
7587
7646
  boolean()
7588
7647
  ]).optional(),
7648
+ minimum: number$1().optional(),
7649
+ maximum: number$1().optional(),
7589
7650
  children: array(WorkflowInputFieldSchema).optional(),
7590
7651
  format: string().optional()
7591
7652
  }));
@@ -7785,6 +7846,159 @@ const WorkflowCanvasCredentialBindingSchema = union([
7785
7846
  })
7786
7847
  ]);
7787
7848
  record(string(), array(WorkflowCanvasCredentialBindingSchema));
7849
+ const FormControlSchema = _enum([
7850
+ "input",
7851
+ "textarea",
7852
+ "select",
7853
+ "radio",
7854
+ "stepper",
7855
+ "slider",
7856
+ "checkbox",
7857
+ "switch"
7858
+ ]);
7859
+ const FormFieldConfigEntrySchema = object({
7860
+ label: string().trim().min(1).max(120).optional(),
7861
+ helpText: string().trim().min(1).max(300).optional(),
7862
+ placeholder: string().trim().min(1).max(200).optional(),
7863
+ control: FormControlSchema.optional()
7864
+ });
7865
+ const FormFieldConfigSchema = record(string(), FormFieldConfigEntrySchema);
7866
+ const PublicFormFieldSchema = WorkflowInputFieldSchema.and(object({
7867
+ control: FormControlSchema.optional(),
7868
+ helpText: string().optional()
7869
+ }));
7870
+ const PublishedFormSchema = object({
7871
+ id: string().min(1),
7872
+ workflowId: string().min(1),
7873
+ workflowSlug: string().min(1),
7874
+ enabled: boolean(),
7875
+ title: string().min(1).nullable(),
7876
+ description: string().min(1).nullable(),
7877
+ fieldConfig: FormFieldConfigSchema,
7878
+ publicUrl: string().url(),
7879
+ createdAt: string().min(1),
7880
+ updatedAt: string().min(1)
7881
+ });
7882
+ object({
7883
+ id: string().min(1),
7884
+ projectId: string().min(1),
7885
+ workflowSlug: string().min(1),
7886
+ enabled: boolean(),
7887
+ title: string().min(1).nullable(),
7888
+ description: string().min(1).nullable(),
7889
+ fieldConfig: FormFieldConfigSchema,
7890
+ publicUrl: string().url(),
7891
+ createdAt: string().min(1),
7892
+ updatedAt: string().min(1)
7893
+ });
7894
+ PublishedFormSchema.nullable();
7895
+ object({
7896
+ enabled: boolean().optional(),
7897
+ title: string().trim().min(1).max(120).nullable().optional(),
7898
+ description: string().trim().min(1).max(500).nullable().optional(),
7899
+ fieldConfig: FormFieldConfigSchema.optional()
7900
+ });
7901
+ object({
7902
+ title: string().min(1),
7903
+ description: string().nullable(),
7904
+ fields: array(PublicFormFieldSchema),
7905
+ branding: object({
7906
+ organizationName: string().min(1),
7907
+ projectName: string().min(1),
7908
+ logoLightUrl: string().url().nullable(),
7909
+ logoDarkUrl: string().url().nullable(),
7910
+ logoHeightPx: number$1().int().positive()
7911
+ })
7912
+ });
7913
+ object({
7914
+ values: record(string(), unknown()),
7915
+ website: string().max(200).optional()
7916
+ });
7917
+ object({ ok: literal(true) });
7918
+ const isoDateTime = string().datetime();
7919
+ const sha256Hex = string().regex(/^[a-f0-9]{64}$/, "Expected a lowercase hex sha256 digest");
7920
+ /**
7921
+ * A single entry in a deploy's file tree, as served to the dashboard. Carries
7922
+ * no contents: `id` is a stable, path-derived handle used for selection and
7923
+ * `?file=` deep links; `hash` is the content address used to fetch the bytes
7924
+ * lazily and to cache them immutably in the browser.
7925
+ */
7926
+ const ProjectFileSummarySchema = object({
7927
+ id: string(),
7928
+ path: string().min(1),
7929
+ hash: sha256Hex
7930
+ });
7931
+ /** Maps a runtime resource slug (agent/workflow/skill) to its source file path. */
7932
+ const ProjectSourceResourceRefSchema = object({
7933
+ slug: string().min(1),
7934
+ path: string().min(1)
7935
+ });
7936
+ const ProjectSourceResourcesSchema = object({
7937
+ agents: array(ProjectSourceResourceRefSchema).default([]),
7938
+ workflows: array(ProjectSourceResourceRefSchema).default([]),
7939
+ skills: array(ProjectSourceResourceRefSchema).default([])
7940
+ });
7941
+ const emptyResources = () => ({
7942
+ agents: [],
7943
+ workflows: [],
7944
+ skills: []
7945
+ });
7946
+ object({
7947
+ artifactId: string().nullable(),
7948
+ files: array(ProjectFileSummarySchema),
7949
+ resources: ProjectSourceResourcesSchema.default(emptyResources())
7950
+ });
7951
+ object({
7952
+ path: string().min(1),
7953
+ contents: string(),
7954
+ hash: sha256Hex
7955
+ });
7956
+ object({ blobs: array(object({
7957
+ hash: sha256Hex,
7958
+ size: number$1().int().nonnegative()
7959
+ })) });
7960
+ object({ uploads: array(object({
7961
+ hash: sha256Hex,
7962
+ url: string().url()
7963
+ })) });
7964
+ object({ files: array(object({
7965
+ path: string().min(1),
7966
+ hash: sha256Hex
7967
+ })) });
7968
+ object({
7969
+ ok: literal(true),
7970
+ fileCount: number$1().int().nonnegative()
7971
+ });
7972
+ object({
7973
+ files: array(object({
7974
+ id: string(),
7975
+ path: string().min(1),
7976
+ hash: sha256Hex
7977
+ })),
7978
+ generatedAt: isoDateTime
7979
+ });
7980
+ /** A single source file returned by the bulk active-source download endpoint. */
7981
+ const DownloadActiveProjectSourceFileSchema = object({
7982
+ path: string().min(1),
7983
+ contents: string()
7984
+ });
7985
+ object({
7986
+ artifactId: string(),
7987
+ files: array(DownloadActiveProjectSourceFileSchema)
7988
+ });
7989
+ object({
7990
+ projectId: string(),
7991
+ artifactId: string(),
7992
+ pulledAt: string().datetime()
7993
+ });
7994
+ object({ files: array(object({
7995
+ id: string(),
7996
+ path: string().min(1)
7997
+ })) });
7998
+ object({ files: array(object({
7999
+ id: string(),
8000
+ path: string().min(1)
8001
+ })) });
7788
8002
  record(string(), unknown());
7789
8003
  //#endregion
7790
8004
  //#region src/runtime.ts
@@ -7836,10 +8050,22 @@ const RUNTIME_ENV_KEYS = [
7836
8050
  "REDIS_URL",
7837
8051
  "KEYSTROKE_QUEUE_PREFIX"
7838
8052
  ];
8053
+ /**
8054
+ * Observability ingest config for org workers (PostHog error tracking + crash reports).
8055
+ * Ingest tokens only — never forward `POSTHOG_API_KEY` (management) into workers.
8056
+ */
8057
+ const OBSERVABILITY_ENV_KEYS = [
8058
+ "POSTHOG_PROJECT_TOKEN",
8059
+ "POSTHOG_HOST",
8060
+ "POSTHOG_FLUSH_MODE",
8061
+ "KEYSTROKE_ENVIRONMENT",
8062
+ "KEYSTROKE_RELEASE"
8063
+ ];
7839
8064
  /** Env keys that must never be forwarded into untrusted org workers. */
7840
8065
  const FORBIDDEN_WORKER_ENV_KEYS = [
7841
8066
  "BETTER_AUTH_SECRET",
7842
8067
  "DATABASE_URL",
8068
+ "POSTHOG_API_KEY",
7843
8069
  "POSTGRES_PASSWORD",
7844
8070
  "PLATFORM_WORKER_TOKEN",
7845
8071
  "STRIPE_SECRET_KEY",
@@ -7883,6 +8109,11 @@ function buildRuntimeEnv(source, artifacts, database, extraEnv) {
7883
8109
  if (!value) continue;
7884
8110
  entries.set(key, value);
7885
8111
  }
8112
+ for (const key of OBSERVABILITY_ENV_KEYS) {
8113
+ const value = source[key]?.trim();
8114
+ if (!value) continue;
8115
+ entries.set(key, value);
8116
+ }
7886
8117
  if (!extraEnv) for (const key of PROVIDER_ENV_KEYS) {
7887
8118
  const value = source[key]?.trim();
7888
8119
  if (value) entries.set(key, value);