eve 0.42.0 → 0.44.0

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 (211) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/src/channel/adapter.d.ts +2 -1
  3. package/dist/src/channel/forwarded-principal.d.ts +4 -4
  4. package/dist/src/channel/instrumentation.js +1 -1
  5. package/dist/src/cli/commands/registry-project.d.ts +3 -0
  6. package/dist/src/cli/commands/registry-project.js +2 -1
  7. package/dist/src/cli/commands/registry.d.ts +2 -0
  8. package/dist/src/cli/commands/registry.js +1 -1
  9. package/dist/src/cli/dev/tui/traces/trace-view.js +1 -1
  10. package/dist/src/compiled/.vendor-stamp.json +1 -1
  11. package/dist/src/compiled/jsonc-parser/index.d.ts +19 -0
  12. package/dist/src/compiler/extension-compatibility.d.ts +7 -5
  13. package/dist/src/compiler/extension-compatibility.js +1 -1
  14. package/dist/src/compiler/manifest.d.ts +3 -0
  15. package/dist/src/compiler/manifest.js +1 -1
  16. package/dist/src/compiler/normalize-manifest.js +1 -1
  17. package/dist/src/compiler/normalize-tool.js +1 -1
  18. package/dist/src/context/build-dynamic-tools.d.ts +5 -5
  19. package/dist/src/context/build-dynamic-tools.js +1 -1
  20. package/dist/src/context/dynamic-subagent-lifecycle.js +1 -1
  21. package/dist/src/context/dynamic-tool-lifecycle.d.ts +8 -27
  22. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  23. package/dist/src/context/keys.d.ts +10 -14
  24. package/dist/src/context/keys.js +1 -1
  25. package/dist/src/context/provider.d.ts +5 -1
  26. package/dist/src/context/run-step.d.ts +3 -2
  27. package/dist/src/context/run-step.js +1 -1
  28. package/dist/src/execution/agent-handle-dispatch.d.ts +3 -0
  29. package/dist/src/execution/agent-handle-dispatch.js +1 -1
  30. package/dist/src/execution/delegation-tool.d.ts +9 -1
  31. package/dist/src/execution/delegation-tool.js +1 -1
  32. package/dist/src/execution/dispatch-runtime-actions-shared.d.ts +14 -1
  33. package/dist/src/execution/dispatch-runtime-actions-shared.js +1 -1
  34. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  35. package/dist/src/execution/history-view.d.ts +9 -0
  36. package/dist/src/execution/history-view.js +1 -0
  37. package/dist/src/execution/next-driver-action.d.ts +33 -1
  38. package/dist/src/execution/node-step.d.ts +5 -2
  39. package/dist/src/execution/node-step.js +1 -1
  40. package/dist/src/execution/remote-agent-dispatch.d.ts +2 -0
  41. package/dist/src/execution/remote-agent-dispatch.js +1 -1
  42. package/dist/src/execution/session-callback-step.d.ts +2 -2
  43. package/dist/src/execution/session-callback-step.js +1 -1
  44. package/dist/src/execution/tasks/child/steps.js +1 -1
  45. package/dist/src/execution/tasks/child/update.d.ts +2 -2
  46. package/dist/src/execution/tasks/child/update.js +1 -1
  47. package/dist/src/execution/tasks/child/workflow.js +1 -1
  48. package/dist/src/execution/tasks/parent/agent-views.d.ts +2 -1
  49. package/dist/src/execution/tasks/parent/agent-views.js +1 -1
  50. package/dist/src/execution/tasks/parent/continuation-dispatch.d.ts +6 -0
  51. package/dist/src/execution/tasks/parent/continuation-dispatch.js +1 -1
  52. package/dist/src/execution/tasks/parent/control-shared.d.ts +1 -1
  53. package/dist/src/execution/tasks/parent/control-shared.js +1 -1
  54. package/dist/src/execution/tasks/parent/delegate.d.ts +20 -6
  55. package/dist/src/execution/tasks/parent/delegate.js +1 -1
  56. package/dist/src/execution/tasks/parent/dispatch-task-step.js +1 -1
  57. package/dist/src/execution/tasks/parent/dispatch.d.ts +13 -1
  58. package/dist/src/execution/tasks/parent/dispatch.js +1 -1
  59. package/dist/src/execution/tasks/parent/hitl-proxy-steps.js +1 -1
  60. package/dist/src/execution/tasks/parent/tool-execution.d.ts +46 -0
  61. package/dist/src/execution/tasks/parent/tool-execution.js +1 -0
  62. package/dist/src/execution/tool-auth.d.ts +12 -3
  63. package/dist/src/execution/tool-auth.js +1 -1
  64. package/dist/src/execution/turn-cancellation-control.js +1 -1
  65. package/dist/src/execution/turn-workflow.js +1 -1
  66. package/dist/src/execution/wire/session-inbox-wire.v1.js +1 -1
  67. package/dist/src/execution/workflow-steps.d.ts +1 -54
  68. package/dist/src/execution/workflow-steps.js +1 -1
  69. package/dist/src/execution/workflow-trace-context.js +1 -1
  70. package/dist/src/harness/advertised-tools.js +1 -1
  71. package/dist/src/harness/background-tools.d.ts +37 -0
  72. package/dist/src/harness/background-tools.js +1 -0
  73. package/dist/src/harness/channel-delivery-instrumentation.js +1 -1
  74. package/dist/src/harness/execute-tool.d.ts +10 -1
  75. package/dist/src/harness/handles/transitions.d.ts +36 -0
  76. package/dist/src/harness/handles/transitions.js +1 -1
  77. package/dist/src/harness/instrumentation/lifecycle.d.ts +4 -0
  78. package/dist/src/harness/instrumentation/native-events.d.ts +2 -0
  79. package/dist/src/harness/instrumentation/native-events.js +1 -1
  80. package/dist/src/harness/messages.d.ts +2 -0
  81. package/dist/src/harness/messages.js +1 -1
  82. package/dist/src/harness/prepare-trace-context.d.ts +2 -0
  83. package/dist/src/harness/prepare-trace-context.js +1 -1
  84. package/dist/src/harness/tool-loop.js +2 -2
  85. package/dist/src/harness/tools.d.ts +5 -1
  86. package/dist/src/harness/tools.js +1 -1
  87. package/dist/src/harness/types.d.ts +13 -0
  88. package/dist/src/internal/application/package.js +1 -1
  89. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  90. package/dist/src/internal/authored-module-loader.js +1 -1
  91. package/dist/src/internal/workflow-bundle/dynamic-capability-transform-plugin.js +1 -1
  92. package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.d.ts +13 -0
  93. package/dist/src/internal/workflow-bundle/dynamic-tool-transform.d.ts +7 -31
  94. package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +4 -4
  95. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  96. package/dist/src/public/channels/chat-sdk/audience.d.ts +2 -0
  97. package/dist/src/public/channels/chat-sdk/audience.js +1 -0
  98. package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +2 -0
  99. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
  100. package/dist/src/public/channels/discord/audience.d.ts +5 -0
  101. package/dist/src/public/channels/discord/audience.js +1 -0
  102. package/dist/src/public/channels/discord/discordChannel.d.ts +2 -0
  103. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  104. package/dist/src/public/channels/discord/inbound.d.ts +1 -0
  105. package/dist/src/public/channels/discord/inbound.js +1 -1
  106. package/dist/src/public/channels/discord/index.d.ts +1 -0
  107. package/dist/src/public/channels/eve.d.ts +7 -7
  108. package/dist/src/public/channels/eve.js +1 -1
  109. package/dist/src/public/channels/index.d.ts +3 -2
  110. package/dist/src/public/channels/slack/slackChannel.d.ts +4 -0
  111. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  112. package/dist/src/public/channels/teams/index.d.ts +1 -0
  113. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  114. package/dist/src/public/channels/telegram/audience.d.ts +3 -0
  115. package/dist/src/public/channels/telegram/audience.js +1 -0
  116. package/dist/src/public/channels/telegram/index.d.ts +1 -0
  117. package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
  118. package/dist/src/public/channels/twilio/twilioChannel.d.ts +2 -0
  119. package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
  120. package/dist/src/public/definitions/channel.d.ts +1 -0
  121. package/dist/src/public/definitions/remote-agent.d.ts +7 -5
  122. package/dist/src/public/definitions/tool.d.ts +23 -0
  123. package/dist/src/public/definitions/tool.js +1 -1
  124. package/dist/src/public/instrumentation/otel.d.ts +6 -10
  125. package/dist/src/public/instrumentation/otel.js +1 -1
  126. package/dist/src/public/tools/approval/approval-helpers.js +1 -1
  127. package/dist/src/public/tools/index.d.ts +1 -1
  128. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +2 -2
  129. package/dist/src/runtime/framework-tools/subagent/local.d.ts +41 -0
  130. package/dist/src/runtime/framework-tools/subagent/local.js +1 -0
  131. package/dist/src/runtime/framework-tools/subagent/remote.d.ts +23 -0
  132. package/dist/src/runtime/framework-tools/subagent/remote.js +1 -0
  133. package/dist/src/runtime/framework-tools/tasks.d.ts +11 -2
  134. package/dist/src/runtime/framework-tools/tasks.js +1 -1
  135. package/dist/src/runtime/resolve-tool.js +1 -1
  136. package/dist/src/runtime/session-callback-route.js +1 -1
  137. package/dist/src/setup/integrations/linq/management.d.ts +5 -0
  138. package/dist/src/setup/integrations/linq/management.js +1 -0
  139. package/dist/src/setup/integrations/linq/setup.d.ts +5 -1
  140. package/dist/src/setup/integrations/linq/setup.js +3 -3
  141. package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
  142. package/dist/src/setup/scaffold/create/project.js +4 -10
  143. package/dist/src/setup/scaffold/create/web-template.d.ts +2 -2
  144. package/dist/src/setup/scaffold/create/web-template.js +374 -2
  145. package/dist/src/setup/scaffold/update/channels.d.ts +1 -1
  146. package/dist/src/setup/scaffold/update/channels.js +2 -2
  147. package/dist/src/setup/scaffold/update/package-json.d.ts +0 -2
  148. package/dist/src/setup/scaffold/update/package-json.js +1 -1
  149. package/dist/src/setup/scaffold/workspace-root.d.ts +0 -1
  150. package/dist/src/setup/scaffold/workspace-root.js +1 -1
  151. package/dist/src/shared/channel-audience.d.ts +7 -0
  152. package/dist/src/shared/channel-audience.js +1 -0
  153. package/dist/src/shared/channel-definition.d.ts +2 -1
  154. package/dist/src/shared/durable-dynamic-tool-callbacks.d.ts +34 -0
  155. package/dist/src/shared/durable-dynamic-tool-callbacks.js +1 -0
  156. package/dist/src/shared/dynamic-tool-definition.d.ts +2 -4
  157. package/dist/src/shared/empty-delivery.js +1 -1
  158. package/dist/src/shared/history-view.d.ts +22 -0
  159. package/dist/src/shared/history-view.js +1 -0
  160. package/dist/src/shared/json.d.ts +2 -0
  161. package/dist/src/shared/json.js +1 -1
  162. package/dist/src/shared/tool-definition.d.ts +4 -1
  163. package/dist/src/shared/tool-task.d.ts +107 -0
  164. package/dist/src/shared/tool-task.js +1 -0
  165. package/dist/src/tasks/delivery-context.d.ts +12 -0
  166. package/dist/src/tasks/delivery-context.js +17 -0
  167. package/dist/src/tasks/json.d.ts +25 -10
  168. package/dist/src/tasks/json.js +1 -1
  169. package/dist/src/tasks/session-index.d.ts +5 -3
  170. package/dist/src/tasks/session-index.js +1 -1
  171. package/dist/src/tasks/transitions.d.ts +40 -5
  172. package/dist/src/tasks/transitions.js +1 -1
  173. package/dist/src/tasks/types.d.ts +46 -4
  174. package/dist/src/tasks/types.js +1 -1
  175. package/dist/src/tracing/agent-action-instrumentation.js +1 -1
  176. package/dist/src/tracing/agent-approval-instrumentation.js +1 -1
  177. package/dist/src/tracing/agent-channel-delivery-instrumentation.js +1 -1
  178. package/dist/src/tracing/agent-otel-provider.d.ts +2 -0
  179. package/dist/src/tracing/agent-otel-provider.js +2 -2
  180. package/dist/src/tracing/agent-otel-session-context.d.ts +2 -0
  181. package/dist/src/tracing/agent-otel-session-context.js +1 -1
  182. package/dist/src/tracing/agent-trace-context-store.js +1 -1
  183. package/dist/src/tracing/agent-trace-state.d.ts +3 -0
  184. package/dist/src/tracing/channel-audience-context.d.ts +4 -0
  185. package/dist/src/tracing/channel-audience-context.js +1 -0
  186. package/dist/src/tracing/content-attributes.js +1 -1
  187. package/dist/src/tracing/content-span-processor.d.ts +7 -7
  188. package/dist/src/tracing/content-span-processor.js +1 -1
  189. package/dist/src/tracing/install-instrumentation-runtime.js +1 -1
  190. package/dist/src/tracing/local-instrumentation-runtime.d.ts +3 -0
  191. package/dist/src/tracing/local-instrumentation-runtime.js +1 -1
  192. package/dist/src/tracing/local-traces.d.ts +1 -10
  193. package/dist/src/tracing/local-traces.js +1 -1
  194. package/dist/src/tracing/otel-declaration.d.ts +34 -27
  195. package/dist/src/tracing/otel-declaration.js +1 -1
  196. package/dist/src/tracing/sampled-trace.d.ts +2 -0
  197. package/dist/src/tracing/sampled-trace.js +1 -0
  198. package/dist/src/tracing/span-export-policy.d.ts +41 -0
  199. package/dist/src/tracing/span-export-policy.js +1 -0
  200. package/dist/src/tracing/suppress-tracing.d.ts +2 -0
  201. package/dist/src/tracing/suppress-tracing.js +1 -0
  202. package/docs/channels/custom.mdx +2 -0
  203. package/docs/channels/linq.mdx +1 -1
  204. package/docs/getting-started.mdx +36 -36
  205. package/docs/guides/auth-and-route-protection.md +6 -2
  206. package/docs/guides/dynamic-capabilities.md +12 -10
  207. package/docs/guides/instrumentation.md +2 -0
  208. package/docs/guides/remote-agents.md +10 -2
  209. package/docs/tools/overview.mdx +19 -0
  210. package/docs/tutorial/ship-it.mdx +1 -1
  211. package/package.json +1 -1
@@ -208,6 +208,7 @@ import type {
208
208
  EveAuthorizationPart,
209
209
  EveDynamicToolPart,
210
210
  EveMessage,
211
+ EveMessageInputRequest,
211
212
  EveMessagePart,
212
213
  } from "eve/react";
213
214
  import {
@@ -219,6 +220,17 @@ import {
219
220
  XCircleIcon,
220
221
  } from "lucide-react";
221
222
  import { Message, MessageContent, MessageResponse } from "@/components/ai-elements/message";
223
+ import {
224
+ Question,
225
+ QuestionActions,
226
+ QuestionDescription,
227
+ QuestionInput,
228
+ QuestionOption,
229
+ QuestionOptions,
230
+ QuestionPrompt,
231
+ type QuestionResponse,
232
+ QuestionSubmit,
233
+ } from "@/components/ai-elements/question";
222
234
  import { Reasoning, ReasoningContent, ReasoningTrigger } from "@/components/ai-elements/reasoning";
223
235
  import {
224
236
  Tool,
@@ -305,7 +317,19 @@ function AgentMessagePart({
305
317
  return <AttachmentPart part={part} />;
306
318
  case "authorization":
307
319
  return <AuthorizationPrompt part={part} />;
308
- case "dynamic-tool":
320
+ case "dynamic-tool": {
321
+ const inputRequest = part.toolMetadata?.eve?.inputRequest;
322
+ if (inputRequest?.kind === "question") {
323
+ return (
324
+ <QuestionRequest
325
+ canRespond={canRespond}
326
+ inputRequest={inputRequest}
327
+ inputResponse={part.toolMetadata?.eve?.inputResponse}
328
+ onInputResponses={onInputResponses}
329
+ />
330
+ );
331
+ }
332
+
309
333
  return (
310
334
  <Tool
311
335
  defaultOpen={part.state === "approval-requested" || part.state === "approval-responded"}
@@ -327,9 +351,76 @@ function AgentMessagePart({
327
351
  </ToolContent>
328
352
  </Tool>
329
353
  );
354
+ }
330
355
  }
331
356
  }
332
357
 
358
+ function QuestionRequest({
359
+ canRespond,
360
+ inputRequest,
361
+ inputResponse,
362
+ onInputResponses,
363
+ }: {
364
+ readonly canRespond: boolean;
365
+ readonly inputRequest: EveMessageInputRequest;
366
+ readonly inputResponse?: AgentInputResponse;
367
+ readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise<void>;
368
+ }) {
369
+ const selectedOption = inputRequest.options?.find(
370
+ (option) => option.id === inputResponse?.optionId,
371
+ );
372
+ const hasOptions = (inputRequest.options?.length ?? 0) > 0;
373
+ const acceptsFreeform = inputRequest.allowFreeform === true || !hasOptions;
374
+
375
+ const submitResponse = ({ selectedValues, text }: QuestionResponse) =>
376
+ onInputResponses([
377
+ {
378
+ optionId: selectedValues[0],
379
+ requestId: inputRequest.requestId,
380
+ text,
381
+ },
382
+ ]);
383
+
384
+ return (
385
+ <Question
386
+ defaultValue={{
387
+ selectedValues: inputResponse?.optionId ? [inputResponse.optionId] : [],
388
+ text: inputResponse?.text ?? "",
389
+ }}
390
+ disabled={!canRespond || inputResponse !== undefined}
391
+ onSubmit={submitResponse}
392
+ >
393
+ <QuestionPrompt>{inputRequest.prompt}</QuestionPrompt>
394
+ {hasOptions ? (
395
+ <QuestionOptions className="flex-col items-stretch" aria-label={inputRequest.prompt}>
396
+ {inputRequest.options?.map((option) => (
397
+ <QuestionOption className="justify-start text-left" key={option.id} value={option.id}>
398
+ <span>
399
+ <span className="block">{option.label}</span>
400
+ {option.description ? (
401
+ <span className="block font-normal text-xs opacity-70">{option.description}</span>
402
+ ) : null}
403
+ </span>
404
+ </QuestionOption>
405
+ ))}
406
+ </QuestionOptions>
407
+ ) : null}
408
+ {acceptsFreeform ? (
409
+ <QuestionInput aria-label="Answer" placeholder="Type your answer…" />
410
+ ) : null}
411
+ {inputResponse ? (
412
+ <QuestionDescription>
413
+ Responded: {selectedOption?.label ?? inputResponse.text ?? inputResponse.optionId}
414
+ </QuestionDescription>
415
+ ) : (
416
+ <QuestionActions>
417
+ <QuestionSubmit>Answer</QuestionSubmit>
418
+ </QuestionActions>
419
+ )}
420
+ </Question>
421
+ );
422
+ }
423
+
333
424
  function AttachmentPart({ part }: { readonly part: EveFilePart }) {
334
425
  const label = part.filename ?? "Attachment";
335
426
  const detail = [part.mediaType, formatBytes(part.size)].filter(Boolean).join(" - ");
@@ -3149,6 +3240,287 @@ export const PromptInputCommandSeparator = ({
3149
3240
  className,
3150
3241
  ...props
3151
3242
  }: PromptInputCommandSeparatorProps) => <CommandSeparator className={cn(className)} {...props} />;
3243
+ `,"components/ai-elements/question.tsx":`"use client";
3244
+
3245
+ import type {
3246
+ ChangeEvent,
3247
+ ComponentProps,
3248
+ FormEvent,
3249
+ HTMLAttributes,
3250
+ MouseEvent,
3251
+ ReactNode,
3252
+ } from "react";
3253
+
3254
+ import { Button } from "@/components/ui/button";
3255
+ import { Textarea } from "@/components/ui/textarea";
3256
+ import { cn } from "@/lib/utils";
3257
+ import { createContext, useCallback, useContext, useMemo, useState } from "react";
3258
+
3259
+ export interface QuestionValue {
3260
+ selectedValues: readonly string[];
3261
+ text: string;
3262
+ }
3263
+
3264
+ export interface QuestionResponse {
3265
+ selectedValues: readonly string[];
3266
+ text?: string;
3267
+ }
3268
+
3269
+ type SelectionMode = "multiple" | "single";
3270
+
3271
+ interface QuestionContextValue {
3272
+ disabled: boolean;
3273
+ selectedValues: readonly string[];
3274
+ selectionMode: SelectionMode;
3275
+ setText: (text: string) => void;
3276
+ text: string;
3277
+ toggleValue: (value: string) => void;
3278
+ }
3279
+
3280
+ const QuestionContext = createContext<QuestionContextValue | null>(null);
3281
+
3282
+ const useQuestion = () => {
3283
+ const context = useContext(QuestionContext);
3284
+
3285
+ if (!context) {
3286
+ throw new Error("Question components must be used within Question");
3287
+ }
3288
+
3289
+ return context;
3290
+ };
3291
+
3292
+ export type QuestionProps = Omit<ComponentProps<"form">, "defaultValue" | "onSubmit" | "value"> & {
3293
+ defaultValue?: QuestionValue;
3294
+ disabled?: boolean;
3295
+ onSubmit?: (
3296
+ response: QuestionResponse,
3297
+ event: FormEvent<HTMLFormElement>,
3298
+ ) => void | Promise<void>;
3299
+ onValueChange?: (value: QuestionValue) => void;
3300
+ selectionMode?: SelectionMode;
3301
+ value?: QuestionValue;
3302
+ };
3303
+
3304
+ const EMPTY_VALUE: QuestionValue = { selectedValues: [], text: "" };
3305
+
3306
+ const getSelectedValues = (
3307
+ currentValues: readonly string[],
3308
+ optionValue: string,
3309
+ selectionMode: SelectionMode,
3310
+ ): readonly string[] => {
3311
+ const isSelected = currentValues.includes(optionValue);
3312
+
3313
+ if (selectionMode === "single") {
3314
+ return isSelected ? [] : [optionValue];
3315
+ }
3316
+
3317
+ if (isSelected) {
3318
+ return currentValues.filter((item) => item !== optionValue);
3319
+ }
3320
+
3321
+ return [...currentValues, optionValue];
3322
+ };
3323
+
3324
+ export const Question = ({
3325
+ children,
3326
+ className,
3327
+ defaultValue = EMPTY_VALUE,
3328
+ disabled = false,
3329
+ onSubmit,
3330
+ onValueChange,
3331
+ selectionMode = "single",
3332
+ value: controlledValue,
3333
+ ...props
3334
+ }: QuestionProps) => {
3335
+ const [internalValue, setInternalValue] = useState(defaultValue);
3336
+ const value = controlledValue ?? internalValue;
3337
+
3338
+ const setValue = useCallback(
3339
+ (nextValue: QuestionValue) => {
3340
+ if (controlledValue === undefined) {
3341
+ setInternalValue(nextValue);
3342
+ }
3343
+ onValueChange?.(nextValue);
3344
+ },
3345
+ [controlledValue, onValueChange],
3346
+ );
3347
+
3348
+ const setText = useCallback(
3349
+ (text: string) => {
3350
+ setValue({ ...value, text });
3351
+ },
3352
+ [setValue, value],
3353
+ );
3354
+
3355
+ const toggleValue = useCallback(
3356
+ (optionValue: string) => {
3357
+ const selectedValues = getSelectedValues(value.selectedValues, optionValue, selectionMode);
3358
+ setValue({ ...value, selectedValues });
3359
+ },
3360
+ [selectionMode, setValue, value],
3361
+ );
3362
+
3363
+ const contextValue = useMemo(
3364
+ () => ({
3365
+ disabled,
3366
+ selectedValues: value.selectedValues,
3367
+ selectionMode,
3368
+ setText,
3369
+ text: value.text,
3370
+ toggleValue,
3371
+ }),
3372
+ [disabled, selectionMode, setText, toggleValue, value],
3373
+ );
3374
+
3375
+ const handleSubmit = useCallback(
3376
+ async (event: FormEvent<HTMLFormElement>) => {
3377
+ event.preventDefault();
3378
+ if (disabled) {
3379
+ return;
3380
+ }
3381
+
3382
+ const text = value.text.trim();
3383
+ if (value.selectedValues.length === 0 && text.length === 0) {
3384
+ return;
3385
+ }
3386
+
3387
+ await onSubmit?.(
3388
+ {
3389
+ selectedValues: value.selectedValues,
3390
+ text: text.length > 0 ? text : undefined,
3391
+ },
3392
+ event,
3393
+ );
3394
+ },
3395
+ [disabled, onSubmit, value],
3396
+ );
3397
+
3398
+ return (
3399
+ <QuestionContext.Provider value={contextValue}>
3400
+ <form
3401
+ className={cn("space-y-4 rounded-lg border bg-background p-4", className)}
3402
+ onSubmit={handleSubmit}
3403
+ {...props}
3404
+ >
3405
+ {children}
3406
+ </form>
3407
+ </QuestionContext.Provider>
3408
+ );
3409
+ };
3410
+
3411
+ export type QuestionPromptProps = HTMLAttributes<HTMLParagraphElement>;
3412
+
3413
+ export const QuestionPrompt = ({ className, ...props }: QuestionPromptProps) => (
3414
+ <p className={cn("font-medium text-sm", className)} {...props} />
3415
+ );
3416
+
3417
+ export type QuestionDescriptionProps = HTMLAttributes<HTMLParagraphElement>;
3418
+
3419
+ export const QuestionDescription = ({ className, ...props }: QuestionDescriptionProps) => (
3420
+ <p className={cn("text-muted-foreground text-sm", className)} {...props} />
3421
+ );
3422
+
3423
+ export type QuestionOptionsProps = HTMLAttributes<HTMLDivElement>;
3424
+
3425
+ export const QuestionOptions = ({ className, ...props }: QuestionOptionsProps) => {
3426
+ const { selectionMode } = useQuestion();
3427
+
3428
+ return (
3429
+ <div
3430
+ className={cn("flex flex-wrap gap-2", className)}
3431
+ role={selectionMode === "single" ? "radiogroup" : "group"}
3432
+ {...props}
3433
+ />
3434
+ );
3435
+ };
3436
+
3437
+ export type QuestionOptionProps = Omit<ComponentProps<typeof Button>, "value"> & {
3438
+ value: string;
3439
+ };
3440
+
3441
+ export const QuestionOption = ({
3442
+ children,
3443
+ className,
3444
+ disabled,
3445
+ onClick,
3446
+ value,
3447
+ variant,
3448
+ ...props
3449
+ }: QuestionOptionProps) => {
3450
+ const question = useQuestion();
3451
+ const isSelected = question.selectedValues.includes(value);
3452
+ const role = question.selectionMode === "single" ? "radio" : "checkbox";
3453
+ const handleClick = useCallback(
3454
+ (event: MouseEvent<HTMLButtonElement>) => {
3455
+ question.toggleValue(value);
3456
+ onClick?.(event);
3457
+ },
3458
+ [onClick, question, value],
3459
+ );
3460
+
3461
+ return (
3462
+ <Button
3463
+ aria-checked={isSelected}
3464
+ className={cn("h-auto whitespace-normal", className)}
3465
+ disabled={question.disabled || disabled}
3466
+ onClick={handleClick}
3467
+ role={role}
3468
+ type="button"
3469
+ variant={variant ?? (isSelected ? "default" : "outline")}
3470
+ {...props}
3471
+ >
3472
+ {children ?? value}
3473
+ </Button>
3474
+ );
3475
+ };
3476
+
3477
+ export type QuestionInputProps = Omit<ComponentProps<typeof Textarea>, "defaultValue" | "value">;
3478
+
3479
+ export const QuestionInput = ({ className, disabled, onChange, ...props }: QuestionInputProps) => {
3480
+ const question = useQuestion();
3481
+ const handleChange = useCallback(
3482
+ (event: ChangeEvent<HTMLTextAreaElement>) => {
3483
+ question.setText(event.currentTarget.value);
3484
+ onChange?.(event);
3485
+ },
3486
+ [onChange, question],
3487
+ );
3488
+
3489
+ return (
3490
+ <Textarea
3491
+ className={cn("min-h-20", className)}
3492
+ disabled={question.disabled || disabled}
3493
+ onChange={handleChange}
3494
+ value={question.text}
3495
+ {...props}
3496
+ />
3497
+ );
3498
+ };
3499
+
3500
+ export type QuestionActionsProps = HTMLAttributes<HTMLDivElement>;
3501
+
3502
+ export const QuestionActions = ({ className, ...props }: QuestionActionsProps) => (
3503
+ <div className={cn("flex items-center justify-end gap-2", className)} {...props} />
3504
+ );
3505
+
3506
+ export type QuestionSubmitProps = ComponentProps<typeof Button> & {
3507
+ children?: ReactNode;
3508
+ };
3509
+
3510
+ export const QuestionSubmit = ({
3511
+ children = "Submit",
3512
+ disabled,
3513
+ ...props
3514
+ }: QuestionSubmitProps) => {
3515
+ const question = useQuestion();
3516
+ const hasResponse = question.selectedValues.length > 0 || question.text.trim().length > 0;
3517
+
3518
+ return (
3519
+ <Button disabled={question.disabled || disabled || !hasResponse} type="submit" {...props}>
3520
+ {children}
3521
+ </Button>
3522
+ );
3523
+ };
3152
3524
  `,"components/ai-elements/reasoning.tsx":`"use client";
3153
3525
 
3154
3526
  import { useControllableState } from "@radix-ui/react-use-controllable-state";
@@ -5235,4 +5607,4 @@ export const auth = betterAuth({
5235
5607
  },
5236
5608
  },
5237
5609
  });
5238
- `},WEB_APP_TEMPLATE_PACKAGE_JSON={scripts:{build:`next build`,"build:eve":`eve build`,dev:`next dev`,"dev:eve":`eve dev`,start:`next start`,"start:eve":`eve start`,typecheck:`tsc --noEmit -p tsconfig.json`},dependencies:{"@radix-ui/react-use-controllable-state":`1.2.2`,"@shikijs/core":`4.1.0`,"@shikijs/engine-javascript":`4.1.0`,"@shikijs/engine-oniguruma":`4.1.0`,"@streamdown/cjk":`1.0.3`,"@streamdown/code":`1.1.1`,"@streamdown/math":`1.0.2`,"@streamdown/mermaid":`1.0.2`,"@tailwindcss/postcss":`4.3.0`,ai:`^7.0.38`,"class-variance-authority":`0.7.1`,clsx:`2.1.1`,cmdk:`1.1.1`,"lucide-react":`1.16.0`,motion:`12.40.0`,nanoid:`5.1.11`,next:`16.3.0-preview.6`,"radix-ui":`1.4.3`,react:`19.2.6`,"react-dom":`19.2.6`,shiki:`4.1.0`,streamdown:`2.5.0`,"tailwind-merge":`3.6.0`,tailwindcss:`4.3.0`,"use-stick-to-bottom":`1.1.4`,zod:`4.4.3`},devDependencies:{"@types/node":`26`,"@types/react":`19.2.15`,"@types/react-dom":`19.2.3`,typescript:`6.0.3`}};export{WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES,WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON};
5610
+ `},WEB_APP_TEMPLATE_PACKAGE_JSON={scripts:{build:`next build`,"build:eve":`eve build`,dev:`next dev`,"dev:eve":`eve dev`,start:`next start`,"start:eve":`eve start`,typecheck:`tsc --noEmit -p tsconfig.json`},dependencies:{"@radix-ui/react-use-controllable-state":`1.2.2`,"@shikijs/core":`4.1.0`,"@shikijs/engine-javascript":`4.1.0`,"@shikijs/engine-oniguruma":`4.1.0`,"@streamdown/cjk":`1.0.3`,"@streamdown/code":`1.1.1`,"@streamdown/math":`1.0.2`,"@streamdown/mermaid":`1.0.2`,"@tailwindcss/postcss":`4.3.0`,"class-variance-authority":`0.7.1`,clsx:`2.1.1`,cmdk:`1.1.1`,"lucide-react":`1.16.0`,motion:`12.40.0`,nanoid:`5.1.11`,next:`16.3.0-preview.6`,"radix-ui":`1.4.3`,react:`19.2.6`,"react-dom":`19.2.6`,shiki:`4.1.0`,streamdown:`2.5.0`,"tailwind-merge":`3.6.0`,tailwindcss:`4.3.0`,"use-stick-to-bottom":`1.1.4`,zod:`4.4.3`},devDependencies:{"@types/node":`26`,"@types/react":`19.2.15`,"@types/react-dom":`19.2.3`,typescript:`6.0.3`}};export{WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES,WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON};
@@ -103,7 +103,7 @@ export interface EnsureChannelOptions {
103
103
  /** When false, Web Chat leaves Vercel Services config unwritten for preview-only scaffolds. */
104
104
  configureVercelServices?: boolean;
105
105
  onWorkspaceRootMutation?: (mutation: WorkspaceRootMutation) => void | Promise<void>;
106
- /** Dependencies are already owned and installed by a registry item. */
106
+ /** Web Chat files and dependencies are already installed by a registry item. */
107
107
  skipDependencyMutation?: boolean;
108
108
  }
109
109
  export declare function ensureChannel(options: EnsureChannelOptions): Promise<ChannelMutationResult>;
@@ -1,10 +1,10 @@
1
- import{appendEnv}from"../../append-env.js";import{pinnedNodeEngineMajor}from"../../node-engine.js";import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{patchPackageJson}from"./package-json.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES,WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"../create/web-template.js";import{resolveEvePackageContract}from"../create/project.js";import{resolveWebPackageVersions}from"./web-options.js";import{readFile,readdir,unlink,writeFile}from"node:fs/promises";import{basename,join,resolve}from"node:path";const SLACK_CHANNEL_DEFAULT_ROUTE=`/eve/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,NEXT_PACKAGE_NAME=`next`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,WEB_COMPETING_NEXT_CONFIG_PATHS=[`next.config.js`,`next.config.mjs`,WEB_NEXT_CONFIG_PATH,`next.config.mts`].filter(e=>e!==WEB_NEXT_CONFIG_PATH);function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readPackageJsonObject(e){if(!await pathExists(e))return;let t=JSON.parse(await readFile(e,`utf8`));return isJsonObject(t)?t:void 0}async function readDependencyVersion(e,t){let n=await readPackageJsonObject(e);if(n===void 0||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,t){let n=await readPackageJsonObject(e);return n!==void 0&&packageJsonHasDependency(n,t)}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),NEXT_PACKAGE_NAME)}const VERCEL_HOST_FRAMEWORK_PRESETS={"@sveltejs/kit":`sveltekit`,[NEXT_PACKAGE_NAME]:`nextjs`,nuxt:`nuxtjs`,nuxt3:`nuxtjs`,"nuxt-edge":`nuxtjs`,"nuxt-nightly":`nuxtjs`};async function resolveVercelHostFrameworkPreset(e){let t=await readPackageJsonObject(join(e,`package.json`));if(t!==void 0){for(let[e,n]of Object.entries(VERCEL_HOST_FRAMEWORK_PRESETS))if(packageJsonHasDependency(t,e))return n}}async function hasVercelHostFramework(e){return await resolveVercelHostFrameworkPreset(e)!==void 0}async function ensurePackageDependency(e,t,n){return!await pathExists(e)||await readDependencyVersion(e,t)===n?[]:(await patchPackageJson(e,{dependencies:{[t]:n}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(e,n,r,a,c,d=!0,f){let h=join(e,`package.json`);if(!await pathExists(h))return{mutations:[]};let g=resolveEvePackageContract(a.evePackage),_=pinnedNodeEngineMajor(g.nodeEngine),v={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:resolveVersionToken(`aiPackageVersion`,a.aiPackageVersion),eve:formatEveDependencySpecifier(g.version),next:resolveVersionToken(`nextPackageVersion`,a.nextPackageVersion),react:resolveVersionToken(`reactPackageVersion`,a.reactPackageVersion),"react-dom":resolveVersionToken(`reactDomPackageVersion`,a.reactDomPackageVersion),streamdown:resolveVersionToken(`streamdownPackageVersion`,a.streamdownPackageVersion),zod:resolveVersionToken(`zodPackageVersion`,a.zodPackageVersion),...f===`sign-in-with-vercel`?{"better-auth":resolveVersionToken(`betterAuthPackageVersion`,a.betterAuthPackageVersion)}:{}},y={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":_,"@types/react":resolveVersionToken(`typesReactPackageVersion`,a.typesReactPackageVersion),"@types/react-dom":resolveVersionToken(`typesReactDomPackageVersion`,a.typesReactDomPackageVersion),typescript:`6.0.3`},b=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts,x=isPackageManagerWorkspaceMember(n,r),S={scripts:b};d&&(S.dependencies=v,S.devDependencies=y),x||(S.nodeEngineRequirement=g.nodeEngine);let C=await patchPackageJson(h,S),w=(await patchWorkspaceRootPackageJson(n,r,{aiPackageVersion:v.ai,nodeEngineRequirement:g.nodeEngine,onWorkspaceRootMutation:c})).nodeEngineOverride??C.nodeEngineOverride;return{mutations:[{path:h,dependencies:d?Object.keys(v):[],devDependencies:d?Object.keys(y):[],scripts:Object.keys(b)}],nodeEngineOverride:w}}function normalizeSlackConnectorSlug(e){return toSlackConnectorSlug((e.trim().replace(/^@/,``).split(`/`).at(-1)??``).toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/[^a-z0-9]+$/,``).slice(0,100).replace(/[^a-z0-9]+$/,``)||`my-agent`)}async function deriveSlackConnectorSlug(e,t){if(t!==void 0&&t.length>0&&t!==`.`)return normalizeSlackConnectorSlug(t);try{let t=await readFile(join(e,`package.json`),`utf8`),n=JSON.parse(t);if(typeof n.name==`string`&&n.name.length>0)return normalizeSlackConnectorSlug(n.name)}catch{}return normalizeSlackConnectorSlug(basename(resolve(e))||`my-agent`)}function buildSlackConnectTemplate(e){if(!e.startsWith(`slack/`)||e.length===6)throw Error(`Invalid Slack connector UID "${e}".`);return`import { connectSlackCredentials } from "@vercel/connect/eve";
1
+ import{appendEnv}from"../../append-env.js";import{pinnedNodeEngineMajor}from"../../node-engine.js";import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{patchPackageJson}from"./package-json.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES,WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"../create/web-template.js";import{resolveEvePackageContract}from"../create/project.js";import{resolveWebPackageVersions}from"./web-options.js";import{readFile,readdir,unlink,writeFile}from"node:fs/promises";import{basename,join,resolve}from"node:path";const SLACK_CHANNEL_DEFAULT_ROUTE=`/eve/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,NEXT_PACKAGE_NAME=`next`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,WEB_COMPETING_NEXT_CONFIG_PATHS=[`next.config.js`,`next.config.mjs`,WEB_NEXT_CONFIG_PATH,`next.config.mts`].filter(e=>e!==WEB_NEXT_CONFIG_PATH);function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readPackageJsonObject(e){if(!await pathExists(e))return;let t=JSON.parse(await readFile(e,`utf8`));return isJsonObject(t)?t:void 0}async function readDependencyVersion(e,t){let n=await readPackageJsonObject(e);if(n===void 0||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,t){let n=await readPackageJsonObject(e);return n!==void 0&&packageJsonHasDependency(n,t)}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),NEXT_PACKAGE_NAME)}const VERCEL_HOST_FRAMEWORK_PRESETS={"@sveltejs/kit":`sveltekit`,[NEXT_PACKAGE_NAME]:`nextjs`,nuxt:`nuxtjs`,nuxt3:`nuxtjs`,"nuxt-edge":`nuxtjs`,"nuxt-nightly":`nuxtjs`};async function resolveVercelHostFrameworkPreset(e){let t=await readPackageJsonObject(join(e,`package.json`));if(t!==void 0){for(let[e,n]of Object.entries(VERCEL_HOST_FRAMEWORK_PRESETS))if(packageJsonHasDependency(t,e))return n}}async function hasVercelHostFramework(e){return await resolveVercelHostFrameworkPreset(e)!==void 0}async function ensurePackageDependency(e,t,n){return!await pathExists(e)||await readDependencyVersion(e,t)===n?[]:(await patchPackageJson(e,{dependencies:{[t]:n}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(e,n,r,a,c,d=!0,f){let h=join(e,`package.json`);if(!await pathExists(h))return{mutations:[]};let g=resolveEvePackageContract(a.evePackage),_=pinnedNodeEngineMajor(g.nodeEngine),v={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:resolveVersionToken(`aiPackageVersion`,a.aiPackageVersion),eve:formatEveDependencySpecifier(g.version),next:resolveVersionToken(`nextPackageVersion`,a.nextPackageVersion),react:resolveVersionToken(`reactPackageVersion`,a.reactPackageVersion),"react-dom":resolveVersionToken(`reactDomPackageVersion`,a.reactDomPackageVersion),streamdown:resolveVersionToken(`streamdownPackageVersion`,a.streamdownPackageVersion),zod:resolveVersionToken(`zodPackageVersion`,a.zodPackageVersion),...f===`sign-in-with-vercel`?{"better-auth":resolveVersionToken(`betterAuthPackageVersion`,a.betterAuthPackageVersion)}:{}},y={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":_,"@types/react":resolveVersionToken(`typesReactPackageVersion`,a.typesReactPackageVersion),"@types/react-dom":resolveVersionToken(`typesReactDomPackageVersion`,a.typesReactDomPackageVersion),typescript:`6.0.3`},b=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts,x=isPackageManagerWorkspaceMember(n,r),S={scripts:b};d&&(S.dependencies=v,S.devDependencies=y),x||(S.nodeEngineRequirement=g.nodeEngine);let C=await patchPackageJson(h,S),w=(await patchWorkspaceRootPackageJson(n,r,{nodeEngineRequirement:g.nodeEngine,onWorkspaceRootMutation:c})).nodeEngineOverride??C.nodeEngineOverride;return{mutations:[{path:h,dependencies:d?Object.keys(v):[],devDependencies:d?Object.keys(y):[],scripts:Object.keys(b)}],nodeEngineOverride:w}}function normalizeSlackConnectorSlug(e){return toSlackConnectorSlug((e.trim().replace(/^@/,``).split(`/`).at(-1)??``).toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/[^a-z0-9]+$/,``).slice(0,100).replace(/[^a-z0-9]+$/,``)||`my-agent`)}async function deriveSlackConnectorSlug(e,t){if(t!==void 0&&t.length>0&&t!==`.`)return normalizeSlackConnectorSlug(t);try{let t=await readFile(join(e,`package.json`),`utf8`),n=JSON.parse(t);if(typeof n.name==`string`&&n.name.length>0)return normalizeSlackConnectorSlug(n.name)}catch{}return normalizeSlackConnectorSlug(basename(resolve(e))||`my-agent`)}function buildSlackConnectTemplate(e){if(!e.startsWith(`slack/`)||e.length===6)throw Error(`Invalid Slack connector UID "${e}".`);return`import { connectSlackCredentials } from "@vercel/connect/eve";
2
2
  import { slackChannel } from "eve/channels/slack";
3
3
 
4
4
  export default slackChannel({
5
5
  credentials: connectSlackCredentials(${JSON.stringify(e)}),
6
6
  });
7
- `}const SLACK_ENV_EXAMPLE_VALUES={SLACK_BOT_TOKEN:``,SLACK_SIGNING_SECRET:``};function renderWebAppTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t).replaceAll(`__EVE_INIT_WITH_EVE_OPTIONS__`,``)}async function ensureWebVercelJson(e){return await pathExists(e)?`skipped`:(await writeTextFile(e,`${JSON.stringify({$schema:`https://openapi.vercel.sh/vercel.json`},null,2)}\n`,{force:!0}),`written`)}async function findCompetingNextConfigFiles(e){let t=[];for(let n of WEB_COMPETING_NEXT_CONFIG_PATHS){let r=join(e,n);await pathExists(r)&&t.push(r)}return t}async function ensureChannel(e){switch(e.kind){case`slack`:return ensureSlackChannel({...e,kind:`slack`});case`web`:return ensureWebChannel({...e,kind:`web`})}}async function ensureWebChannel(e){let t=join(e.projectRoot,`package.json`),n=await pathExists(join(e.projectRoot,`app/page.tsx`));if(!e.force&&await isNextJsProject(e.projectRoot))return{kind:`web`,action:`skipped`,skipReason:`nextjs-project`,filesWritten:[],filesSkipped:[t],packageJsonUpdated:[]};let r=resolveWebPackageVersions(e.webPackageVersions,e.webAuthentication),o=e.packageManager??`pnpm`,s=resolve(e.workspaceProbeDirectory??e.projectRoot),l=await patchWebPackageJson(e.projectRoot,o,s,r,e.onWorkspaceRootMutation,!e.skipDependencyMutation,e.webAuthentication),u=[],p=[],m=[],g=[],_=basename(resolve(e.projectRoot));if(e.configureVercelServices??!0){let t=join(e.projectRoot,`vercel.json`);await ensureWebVercelJson(t)===`written`?u.push(t):g.push(t)}let v=await applyPackageManagerWorkspaceConfiguration({packageManager:o,projectRoot:e.projectRoot,workspaceProbeRoot:s,onWorkspaceRootMutation:e.onWorkspaceRootMutation});if(u.push(...v.filesWritten),g.push(...v.filesSkipped),!e.skipDependencyMutation){let t={...WEB_APP_TEMPLATE_FILES,...e.webAuthentication===`sign-in-with-vercel`?WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES:{}};for(let[n,r]of Object.entries(t)){let t=join(e.projectRoot,n);if(n===`agent/channels/eve.ts`&&!e.force&&await pathExists(t)){g.push(t);continue}let o=await pathExists(t);await writeTextFile(t,renderWebAppTemplate(r,_),{force:!0}),u.push(t),o&&p.push(t)}}m.push(...await findCompetingNextConfigFiles(e.projectRoot));let y=[...new Set(u)],S=[...new Set(g)].filter(e=>!y.includes(e)),C={kind:`web`,action:n?`overwritten`:`created`,filesWritten:y,filesSkipped:S,packageJsonUpdated:l.mutations};return p.length>0&&(C.filesOverwritten=p),m.length>0&&(C.competingNextConfigFiles=m),l.nodeEngineOverride!==void 0&&(C.nodeEngineOverride=l.nodeEngineOverride),C}async function ensureSlackChannel(t){let n=join(t.projectRoot,`agent/channels/slack.ts`),r=await pathExists(n);if(!t.force&&r)return{kind:`slack`,action:`skipped`,filesWritten:[],filesSkipped:[n],packageJsonUpdated:[]};let s=t.slackCredentials??`vercel-connect`,c=t.slackConnectorSlug??await deriveSlackConnectorSlug(t.projectRoot),l,u=[],d=[n],f=[],p;if(s===`vercel-connect`){if(!t.skipDependencyMutation){let e=resolveVersionToken(`connectPackageVersion`,t.connectPackageVersion??`0.4.3`);u=await ensurePackageDependency(join(t.projectRoot,`package.json`),`@vercel/connect`,e)}l=buildSlackConnectTemplate(t.slackConnectorUid??`slack/${c}`)}else{l=`import { slackChannel } from "eve/channels/slack";
7
+ `}const SLACK_ENV_EXAMPLE_VALUES={SLACK_BOT_TOKEN:``,SLACK_SIGNING_SECRET:``};function renderWebAppTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t).replaceAll(`__EVE_INIT_WITH_EVE_OPTIONS__`,``)}async function ensureWebVercelJson(e){return await pathExists(e)?`skipped`:(await writeTextFile(e,`${JSON.stringify({$schema:`https://openapi.vercel.sh/vercel.json`},null,2)}\n`,{force:!0}),`written`)}async function findCompetingNextConfigFiles(e){let t=[];for(let n of WEB_COMPETING_NEXT_CONFIG_PATHS){let r=join(e,n);await pathExists(r)&&t.push(r)}return t}async function ensureChannel(e){switch(e.kind){case`slack`:return ensureSlackChannel({...e,kind:`slack`});case`web`:return ensureWebChannel({...e,kind:`web`})}}async function ensureWebChannel(e){let t=join(e.projectRoot,`package.json`),n=await pathExists(join(e.projectRoot,`app/page.tsx`));if(!e.force&&!e.skipDependencyMutation&&await isNextJsProject(e.projectRoot))return{kind:`web`,action:`skipped`,skipReason:`nextjs-project`,filesWritten:[],filesSkipped:[t],packageJsonUpdated:[]};let r=resolveWebPackageVersions(e.webPackageVersions,e.webAuthentication),o=e.packageManager??`pnpm`,s=resolve(e.workspaceProbeDirectory??e.projectRoot),l=await patchWebPackageJson(e.projectRoot,o,s,r,e.onWorkspaceRootMutation,!e.skipDependencyMutation,e.webAuthentication),u=[],p=[],m=[],g=[],_=basename(resolve(e.projectRoot));if(e.configureVercelServices??!0){let t=join(e.projectRoot,`vercel.json`);await ensureWebVercelJson(t)===`written`?u.push(t):g.push(t)}let v=await applyPackageManagerWorkspaceConfiguration({packageManager:o,projectRoot:e.projectRoot,workspaceProbeRoot:s,onWorkspaceRootMutation:e.onWorkspaceRootMutation});if(u.push(...v.filesWritten),g.push(...v.filesSkipped),!e.skipDependencyMutation){let t={...WEB_APP_TEMPLATE_FILES,...e.webAuthentication===`sign-in-with-vercel`?WEB_APP_SIGN_IN_WITH_VERCEL_TEMPLATE_FILES:{}};for(let[n,r]of Object.entries(t)){let t=join(e.projectRoot,n);if(n===`agent/channels/eve.ts`&&!e.force&&await pathExists(t)){g.push(t);continue}let o=await pathExists(t);await writeTextFile(t,renderWebAppTemplate(r,_),{force:!0}),u.push(t),o&&p.push(t)}}m.push(...await findCompetingNextConfigFiles(e.projectRoot));let y=[...new Set(u)],S=[...new Set(g)].filter(e=>!y.includes(e)),C={kind:`web`,action:n?`overwritten`:`created`,filesWritten:y,filesSkipped:S,packageJsonUpdated:l.mutations};return p.length>0&&(C.filesOverwritten=p),m.length>0&&(C.competingNextConfigFiles=m),l.nodeEngineOverride!==void 0&&(C.nodeEngineOverride=l.nodeEngineOverride),C}async function ensureSlackChannel(t){let n=join(t.projectRoot,`agent/channels/slack.ts`),r=await pathExists(n);if(!t.force&&r)return{kind:`slack`,action:`skipped`,filesWritten:[],filesSkipped:[n],packageJsonUpdated:[]};let s=t.slackCredentials??`vercel-connect`,c=t.slackConnectorSlug??await deriveSlackConnectorSlug(t.projectRoot),l,u=[],d=[n],f=[],p;if(s===`vercel-connect`){if(!t.skipDependencyMutation){let e=resolveVersionToken(`connectPackageVersion`,t.connectPackageVersion??`0.4.3`);u=await ensurePackageDependency(join(t.projectRoot,`package.json`),`@vercel/connect`,e)}l=buildSlackConnectTemplate(t.slackConnectorUid??`slack/${c}`)}else{l=`import { slackChannel } from "eve/channels/slack";
8
8
 
9
9
  export default slackChannel();
10
10
  `;let n=join(t.projectRoot,`.env.example`);p={path:n,...await pathExists(n)?{content:await readFile(n,`utf8`)}:{}},(await appendEnv(n,SLACK_ENV_EXAMPLE_VALUES)).written.length>0?d.push(n):f.push(n)}try{await writeTextFile(n,l,{force:t.force})}catch(e){throw p!==void 0&&(p.content===void 0?await unlink(p.path):await writeFile(p.path,p.content,`utf8`)),e}let m={kind:`slack`,action:r?`overwritten`:`created`,filesWritten:d,filesSkipped:f,packageJsonUpdated:u,slackConnectorSlug:c};return r&&(m.filesOverwritten=[n]),m}async function listAuthoredChannels(e){let t=join(e,`channels`),i;try{i=await readdir(t,{withFileTypes:!0})}catch(e){if(e.code===`ENOENT`)return[];throw e}let a=[];for(let e of i){if(e.isFile()){let t=getSupportedModuleBaseName(e.name);t!==null&&a.push(t);continue}if(e.isDirectory())try{(await readdir(join(t,e.name))).some(e=>matchesSupportedModuleBaseName(e,`connection`))&&a.push(e.name)}catch{}}return a.sort()}export{DEFAULT_SLACK_CONNECTOR_SLUG,SLACK_CHANNEL_DEFAULT_ROUTE,deriveSlackConnectorSlug,ensureChannel,hasVercelHostFramework,isNextJsProject,listAuthoredChannels,normalizeSlackConnectorSlug,resolveVercelHostFrameworkPreset};
@@ -2,8 +2,6 @@ import { type NodeEngineOverride } from "../../node-engine.js";
2
2
  export interface PackageJsonPatch {
3
3
  dependencies?: Record<string, string>;
4
4
  devDependencies?: Record<string, string>;
5
- overrides?: Record<string, string>;
6
- resolutions?: Record<string, string>;
7
5
  scripts?: Record<string, string>;
8
6
  /**
9
7
  * eve's required Node.js range (e.g. `">=24"`). When the target's
@@ -1 +1 @@
1
- import{reconcileNodeEngine}from"../../node-engine.js";import{readFile,writeFile}from"node:fs/promises";function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function patchPackageJson(r,i){let a=await readFile(r,`utf8`),o=JSON.parse(a),s=!1,c;if(i.dependencies!==void 0&&(o.dependencies={...o.dependencies,...i.dependencies},s=!0),i.devDependencies!==void 0&&(o.devDependencies={...o.devDependencies,...i.devDependencies},s=!0),i.overrides!==void 0&&(o.overrides={...isJsonObject(o.overrides)?o.overrides:{},...i.overrides},s=!0),i.resolutions!==void 0&&(o.resolutions={...isJsonObject(o.resolutions)?o.resolutions:{},...i.resolutions},s=!0),i.scripts!==void 0&&(o.scripts={...o.scripts,...i.scripts},s=!0),i.nodeEngineRequirement!==void 0){let t=isJsonObject(o.engines)?o.engines:{},n=reconcileNodeEngine(t.node,i.nodeEngineRequirement);(n.kind===`added`||n.kind===`overridden`)&&(o.engines={...t,node:n.next},s=!0),n.kind===`overridden`&&(c=n)}return s&&await writeFile(r,`${JSON.stringify(o,null,2)}\n`,`utf8`),{changed:s,nodeEngineOverride:c}}export{patchPackageJson};
1
+ import{reconcileNodeEngine}from"../../node-engine.js";import{readFile,writeFile}from"node:fs/promises";function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function patchPackageJson(r,i){let a=await readFile(r,`utf8`),o=JSON.parse(a),s=!1,c;if(i.dependencies!==void 0&&(o.dependencies={...o.dependencies,...i.dependencies},s=!0),i.devDependencies!==void 0&&(o.devDependencies={...o.devDependencies,...i.devDependencies},s=!0),i.scripts!==void 0&&(o.scripts={...o.scripts,...i.scripts},s=!0),i.nodeEngineRequirement!==void 0){let t=isJsonObject(o.engines)?o.engines:{},n=reconcileNodeEngine(t.node,i.nodeEngineRequirement);(n.kind===`added`||n.kind===`overridden`)&&(o.engines={...t,node:n.next},s=!0),n.kind===`overridden`&&(c=n)}return s&&await writeFile(r,`${JSON.stringify(o,null,2)}\n`,`utf8`),{changed:s,nodeEngineOverride:c}}export{patchPackageJson};
@@ -13,7 +13,6 @@ export interface WorkspaceRootPackageJsonPatchResult extends PackageJsonPatchRes
13
13
  export declare function isPackageManagerWorkspaceMember(packageManager: PackageManagerKind, projectRoot: string): boolean;
14
14
  /** Applies root-only package.json fields to an ancestor workspace package.json. */
15
15
  export declare function patchWorkspaceRootPackageJson(packageManager: PackageManagerKind, projectRoot: string, input: {
16
- readonly aiPackageVersion?: string;
17
16
  readonly nodeEngineRequirement?: string;
18
17
  readonly onWorkspaceRootMutation?: (mutation: WorkspaceRootMutation) => void | Promise<void>;
19
18
  }): Promise<WorkspaceRootPackageJsonPatchResult>;
@@ -1 +1 @@
1
- import{isPathInside,workspacePatternForProject,workspacePatternsClaimProject}from"./workspace-glob.js";import{ensurePnpmWorkspaceIncludesProject,findAncestorPnpmWorkspaceRoot}from"../primitives/pm/pnpm.js";import{getPackageManagerStrategy}from"../primitives/pm/index.js";import{patchPackageJson}from"./update/package-json.js";import{readFile,writeFile}from"node:fs/promises";import{dirname,join,resolve}from"node:path";import{existsSync,readFileSync}from"node:fs";function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function packageJsonWorkspacePatterns(e){let t=e.workspaces;return Array.isArray(t)?t.filter(e=>typeof e==`string`):!isJsonObject(t)||!Array.isArray(t.packages)?[]:t.packages.filter(e=>typeof e==`string`)}function readPackageJsonWorkspacePatterns(e){let t=JSON.parse(readFileSync(e,`utf8`));if(!isJsonObject(t))return;let n=packageJsonWorkspacePatterns(t);return n.length===0?void 0:n}function findAncestorPackageJsonWorkspaceRoot(e){let t=dirname(resolve(e));for(;;){let e=join(t,`package.json`);if(existsSync(e))try{if(readPackageJsonWorkspacePatterns(e)!==void 0)return t}catch{}let n=dirname(t);if(n===t)return;t=n}}function findClaimingPackageJsonWorkspaceRoot(e){let t=findAncestorPackageJsonWorkspaceRoot(e);if(t===void 0)return;let r;try{r=readPackageJsonWorkspacePatterns(join(t,`package.json`))}catch{return}return r!==void 0&&workspacePatternsClaimProject(r,t,e)?t:void 0}function findPackageManagerWorkspaceRoot(e,t){switch(e){case`pnpm`:return findAncestorPnpmWorkspaceRoot(t);case`bun`:case`npm`:case`yarn`:return findAncestorPackageJsonWorkspaceRoot(t)}}function isPackageManagerWorkspaceMember(e,t){let n=findPackageManagerWorkspaceRoot(e,t);return n!==void 0&&resolve(n)!==resolve(t)}function workspaceRootPackageJsonPath(e,t){let n=findPackageManagerWorkspaceRoot(e,t);return n===void 0?void 0:join(n,`package.json`)}async function ensurePackageJsonWorkspaceIncludesProject(e){let n=findAncestorPackageJsonWorkspaceRoot(e);if(n===void 0||resolve(n)===resolve(e)||findClaimingPackageJsonWorkspaceRoot(e)===n)return;let r=join(n,`package.json`),i=JSON.parse(await readFile(r,`utf8`)),a=workspacePatternForProject(n,e);if(Array.isArray(i.workspaces))i.workspaces=[...i.workspaces,a];else if(isJsonObject(i.workspaces)&&Array.isArray(i.workspaces.packages))i.workspaces={...i.workspaces,packages:[...i.workspaces.packages,a]};else return;return await writeFile(r,`${JSON.stringify(i,null,2)}\n`,`utf8`),r}async function ensurePackageManagerWorkspaceIncludesProject(e,t){switch(e){case`pnpm`:{let e=findAncestorPnpmWorkspaceRoot(t);return e===void 0?void 0:await ensurePnpmWorkspaceIncludesProject(t)===`written`?join(e,`pnpm-workspace.yaml`):void 0}case`bun`:case`npm`:case`yarn`:return ensurePackageJsonWorkspaceIncludesProject(t)}}function packageManagerRootOnlyPackageJsonPatch(e,t){let n={};if(t.nodeEngineRequirement!==void 0&&(n.nodeEngineRequirement=t.nodeEngineRequirement),t.aiPackageVersion!==void 0)switch(e){case`bun`:case`npm`:n.overrides={ai:t.aiPackageVersion};break;case`yarn`:n.resolutions={ai:t.aiPackageVersion};break;case`pnpm`:break}return n}async function patchWorkspaceRootPackageJson(e,t,n){if(!isPackageManagerWorkspaceMember(e,t))return{changed:!1};let r=workspaceRootPackageJsonPath(e,t);if(r===void 0||!existsSync(r))return{changed:!1};let i=await patchPackageJson(r,packageManagerRootOnlyPackageJsonPatch(e,n));return i.changed&&await n.onWorkspaceRootMutation?.({kind:`package-json`,nodeEngineOverride:i.nodeEngineOverride,path:r}),{...i,path:r}}async function applyPackageManagerWorkspaceConfiguration(t){let n=resolve(t.workspaceProbeRoot??t.projectRoot),r=t.packageManager===`pnpm`?void 0:await ensurePackageManagerWorkspaceIncludesProject(t.packageManager,n),i=await getPackageManagerStrategy(t.packageManager).applyProjectConfiguration(t.projectRoot,{workspaceProbeRoot:n}),o=[...r===void 0?[]:[r],...i.filesWritten],s=[...i.filesSkipped];for(let n of o)isPathInside(t.projectRoot,n)||await t.onWorkspaceRootMutation?.({kind:`workspace-config`,path:n});return{filesSkipped:s,filesWritten:o}}export{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson};
1
+ import{isPathInside,workspacePatternForProject,workspacePatternsClaimProject}from"./workspace-glob.js";import{ensurePnpmWorkspaceIncludesProject,findAncestorPnpmWorkspaceRoot}from"../primitives/pm/pnpm.js";import{getPackageManagerStrategy}from"../primitives/pm/index.js";import{patchPackageJson}from"./update/package-json.js";import{readFile,writeFile}from"node:fs/promises";import{dirname,join,resolve}from"node:path";import{existsSync,readFileSync}from"node:fs";function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function packageJsonWorkspacePatterns(e){let t=e.workspaces;return Array.isArray(t)?t.filter(e=>typeof e==`string`):!isJsonObject(t)||!Array.isArray(t.packages)?[]:t.packages.filter(e=>typeof e==`string`)}function readPackageJsonWorkspacePatterns(e){let t=JSON.parse(readFileSync(e,`utf8`));if(!isJsonObject(t))return;let n=packageJsonWorkspacePatterns(t);return n.length===0?void 0:n}function findAncestorPackageJsonWorkspaceRoot(e){let t=dirname(resolve(e));for(;;){let e=join(t,`package.json`);if(existsSync(e))try{if(readPackageJsonWorkspacePatterns(e)!==void 0)return t}catch{}let n=dirname(t);if(n===t)return;t=n}}function findClaimingPackageJsonWorkspaceRoot(e){let t=findAncestorPackageJsonWorkspaceRoot(e);if(t===void 0)return;let r;try{r=readPackageJsonWorkspacePatterns(join(t,`package.json`))}catch{return}return r!==void 0&&workspacePatternsClaimProject(r,t,e)?t:void 0}function findPackageManagerWorkspaceRoot(e,t){switch(e){case`pnpm`:return findAncestorPnpmWorkspaceRoot(t);case`bun`:case`npm`:case`yarn`:return findAncestorPackageJsonWorkspaceRoot(t)}}function isPackageManagerWorkspaceMember(e,t){let n=findPackageManagerWorkspaceRoot(e,t);return n!==void 0&&resolve(n)!==resolve(t)}function workspaceRootPackageJsonPath(e,t){let n=findPackageManagerWorkspaceRoot(e,t);return n===void 0?void 0:join(n,`package.json`)}async function ensurePackageJsonWorkspaceIncludesProject(e){let n=findAncestorPackageJsonWorkspaceRoot(e);if(n===void 0||resolve(n)===resolve(e)||findClaimingPackageJsonWorkspaceRoot(e)===n)return;let r=join(n,`package.json`),i=JSON.parse(await readFile(r,`utf8`)),a=workspacePatternForProject(n,e);if(Array.isArray(i.workspaces))i.workspaces=[...i.workspaces,a];else if(isJsonObject(i.workspaces)&&Array.isArray(i.workspaces.packages))i.workspaces={...i.workspaces,packages:[...i.workspaces.packages,a]};else return;return await writeFile(r,`${JSON.stringify(i,null,2)}\n`,`utf8`),r}async function ensurePackageManagerWorkspaceIncludesProject(e,t){switch(e){case`pnpm`:{let e=findAncestorPnpmWorkspaceRoot(t);return e===void 0?void 0:await ensurePnpmWorkspaceIncludesProject(t)===`written`?join(e,`pnpm-workspace.yaml`):void 0}case`bun`:case`npm`:case`yarn`:return ensurePackageJsonWorkspaceIncludesProject(t)}}async function patchWorkspaceRootPackageJson(e,t,n){if(!isPackageManagerWorkspaceMember(e,t))return{changed:!1};let r=workspaceRootPackageJsonPath(e,t);if(r===void 0||!existsSync(r))return{changed:!1};let i=await patchPackageJson(r,{nodeEngineRequirement:n.nodeEngineRequirement});return i.changed&&await n.onWorkspaceRootMutation?.({kind:`package-json`,nodeEngineOverride:i.nodeEngineOverride,path:r}),{...i,path:r}}async function applyPackageManagerWorkspaceConfiguration(t){let n=resolve(t.workspaceProbeRoot??t.projectRoot),r=t.packageManager===`pnpm`?void 0:await ensurePackageManagerWorkspaceIncludesProject(t.packageManager,n),i=await getPackageManagerStrategy(t.packageManager).applyProjectConfiguration(t.projectRoot,{workspaceProbeRoot:n}),o=[...r===void 0?[]:[r],...i.filesWritten],s=[...i.filesSkipped];for(let n of o)isPathInside(t.projectRoot,n)||await t.onWorkspaceRootMutation?.({kind:`workspace-config`,path:n});return{filesSkipped:s,filesWritten:o}}export{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson};
@@ -0,0 +1,7 @@
1
+ export declare const CHANNEL_AUDIENCES: readonly ["public", "private", "unknown"];
2
+ /** Who can observe the conversation on its originating channel. */
3
+ export type ChannelAudience = (typeof CHANNEL_AUDIENCES)[number];
4
+ export interface ChannelAudienceMetadata {
5
+ readonly audience?: ChannelAudience;
6
+ }
7
+ export declare function normalizeChannelAudience(value: unknown): ChannelAudience;
@@ -0,0 +1 @@
1
+ const CHANNEL_AUDIENCES=[`public`,`private`,`unknown`];function normalizeChannelAudience(e){return typeof e==`string`&&CHANNEL_AUDIENCES.includes(e)?e:`unknown`}export{CHANNEL_AUDIENCES,normalizeChannelAudience};
@@ -5,6 +5,7 @@ import type { RouteDefinition } from "#channel/routes.js";
5
5
  import type { Session, SessionHandle } from "#channel/session.js";
6
6
  import type { DeliverPayload, SessionAuthContext, TurnPolicy } from "#channel/types.js";
7
7
  import type { StepInput } from "#harness/types.js";
8
+ import type { ChannelAudienceMetadata } from "#shared/channel-audience.js";
8
9
  /**
9
10
  * Enriched return shape from a channel's {@link ChannelAdapter.fetchFile}
10
11
  * function. Return a bare {@link Buffer} when only bytes are known, or
@@ -40,7 +41,7 @@ export interface GenericReceiveInput<TReceiveTarget = Record<string, unknown>> {
40
41
  * `TReceiveTarget` (cross-channel target shape), `TMetadata` (instrumentation
41
42
  * projection).
42
43
  */
43
- export interface GenericChannelDefinition<TEvents, TState = undefined, TCtx = void, TReceiveTarget = Record<string, unknown>, TMetadata extends Record<string, unknown> = Record<string, unknown>> {
44
+ export interface GenericChannelDefinition<TEvents, TState = undefined, TCtx = void, TReceiveTarget = Record<string, unknown>, TMetadata extends Record<string, unknown> & ChannelAudienceMetadata = Record<string, unknown>> {
44
45
  /** Policy used by message sends that do not provide an explicit override. */
45
46
  readonly turnPolicy?: TurnPolicy;
46
47
  deliver?(payload: DeliverPayload, ctx: TCtx): StepInput | void | Promise<StepInput | void>;
@@ -0,0 +1,34 @@
1
+ import type { Approval } from "#public/definitions/approval.js";
2
+ import type { JsonObject } from "#shared/json.js";
3
+ export interface DurableDynamicCallbackReference {
4
+ readonly stepId: string;
5
+ readonly closure: JsonObject;
6
+ }
7
+ export interface DurableDynamicToolCallbacks {
8
+ readonly execute: DurableDynamicCallbackReference;
9
+ readonly approvalRequest?: DurableDynamicCallbackReference;
10
+ readonly approvalResponse?: DurableDynamicCallbackReference;
11
+ readonly toModelOutput?: DurableDynamicCallbackReference;
12
+ }
13
+ export declare const DURABLE_DYNAMIC_TOOL_CALLBACKS: unique symbol;
14
+ type Callback = (...args: never[]) => unknown;
15
+ /** Registers one module-stable replay entry point. Re-registration replaces the same code-owned id. */
16
+ export declare function registerDurableDynamicCallback<TArgs extends unknown[], TResult>(stepId: string, callback: (closure: JsonObject, ...args: TArgs) => TResult): void;
17
+ /** Marks a live callback with the descriptor needed to reconstruct it after a cold start. */
18
+ export declare function stampDurableDynamicCallback<TCallback extends Callback>(callback: TCallback, reference: DurableDynamicCallbackReference): TCallback;
19
+ /** Creates a live callback backed by the same registered function used during durable replay. */
20
+ export declare function createDurableDynamicCallback<TArgs extends unknown[], TResult>(input: {
21
+ readonly closure: JsonObject;
22
+ readonly callback: (closure: JsonObject, ...args: TArgs) => TResult;
23
+ readonly stepId: string;
24
+ }): (...args: TArgs) => TResult;
25
+ export declare function readDurableDynamicCallback(callback: unknown): DurableDynamicCallbackReference | undefined;
26
+ /** Copies phase-specific callback descriptors onto a branded tool definition. */
27
+ export declare function stampDurableDynamicToolCallbacks(definition: object, callbacks: Partial<DurableDynamicToolCallbacks>): void;
28
+ export declare function collectDurableDynamicToolCallbacks(input: {
29
+ readonly approval?: Approval<never>;
30
+ readonly execute: Callback;
31
+ readonly toModelOutput?: Callback;
32
+ }): Partial<DurableDynamicToolCallbacks>;
33
+ export declare function readDurableDynamicToolCallbacks(definition: object): Partial<DurableDynamicToolCallbacks> | undefined;
34
+ export {};
@@ -0,0 +1 @@
1
+ import{resolveApprovalPolicy}from"#public/definitions/approval.js";const DURABLE_CALLBACK_REFERENCE=Symbol.for(`eve:durable-dynamic-callback`),DURABLE_DYNAMIC_TOOL_CALLBACKS=Symbol.for(`eve:durable-dynamic-tool-callbacks`),STEP_REGISTRY=Symbol.for(`@workflow/core//registeredSteps`);function getStepRegistry(){let e=globalThis,t=e[STEP_REGISTRY];if(t!==void 0)return t;let n=new Map;return e[STEP_REGISTRY]=n,n}function registerDurableDynamicCallback(e,t){if(e.length===0)throw Error(`A durable dynamic callback step id cannot be empty.`);getStepRegistry().set(e,t)}function stampDurableDynamicCallback(e,n){return Object.defineProperty(e,DURABLE_CALLBACK_REFERENCE,{configurable:!0,value:n}),e}function createDurableDynamicCallback(e){return registerDurableDynamicCallback(e.stepId,e.callback),stampDurableDynamicCallback((...t)=>e.callback(e.closure,...t),{closure:e.closure,stepId:e.stepId})}function readDurableDynamicCallback(e){if(typeof e==`function`)return Reflect.get(e,DURABLE_CALLBACK_REFERENCE)}function stampDurableDynamicToolCallbacks(e,t){Object.defineProperty(e,DURABLE_DYNAMIC_TOOL_CALLBACKS,{configurable:!0,value:t})}function collectDurableDynamicToolCallbacks(t){let n=t.approval===void 0?void 0:readDurableDynamicCallback(resolveApprovalPolicy(t.approval)),r=t.approval===void 0||typeof t.approval==`function`?void 0:readDurableDynamicCallback(t.approval.response),i=readDurableDynamicCallback(t.execute),a=readDurableDynamicCallback(t.toModelOutput),o={};return i!==void 0&&(o.execute=i),n!==void 0&&(o.approvalRequest=n),r!==void 0&&(o.approvalResponse=r),a!==void 0&&(o.toModelOutput=a),o}function readDurableDynamicToolCallbacks(e){return e[DURABLE_DYNAMIC_TOOL_CALLBACKS]}export{DURABLE_DYNAMIC_TOOL_CALLBACKS,collectDurableDynamicToolCallbacks,createDurableDynamicCallback,readDurableDynamicCallback,readDurableDynamicToolCallbacks,registerDurableDynamicCallback,stampDurableDynamicCallback,stampDurableDynamicToolCallbacks};
@@ -63,10 +63,8 @@ export interface DynamicToolEntry<TInput = Record<string, unknown>, TOutput = an
63
63
  /**
64
64
  * Optional per-call approval gate, mirroring the authored-tool
65
65
  * `approval` contract: return `"user-approval"` to require user approval
66
- * before the call executes. Only honored for step-scoped dynamic
67
- * tools, whose live `execute` closures survive into the harness;
68
- * session/turn-scoped tools replay from durable metadata and cannot
69
- * carry a function across replay.
66
+ * before the call executes. Dynamic approval request and response callbacks
67
+ * use the same durable descriptor boundary as `execute` and `toModelOutput`.
70
68
  */
71
69
  readonly approval?: Approval;
72
70
  }
@@ -1 +1 @@
1
- const EMPTY_DELIVERY_SENTINEL=`<eve-empty-delivery/>`,CONDITIONAL_DELIVERY_INSTRUCTION=`Conditional delivery\nOnly when the current task explicitly makes delivery conditional and there is nothing new to report, reply with exactly ${EMPTY_DELIVERY_SENTINEL} and no other text. This includes results already delivered or incorporated into an earlier response; do not send an acknowledgement of that redundancy. Do not use this marker for ordinary conversations, after input or approval responses, or to omit commentary from a response that still needs delivery. Never return an empty response; use the marker to intentionally deliver nothing.`;function hasEmptyDeliverySentinel(e){return e?.includes(`<eve-empty-delivery/>`)??!1}export{CONDITIONAL_DELIVERY_INSTRUCTION,EMPTY_DELIVERY_SENTINEL,hasEmptyDeliverySentinel};
1
+ const EMPTY_DELIVERY_SENTINEL=`<eve-empty-delivery/>`,CONDITIONAL_DELIVERY_INSTRUCTION=`Conditional delivery\nOnly when the current task explicitly makes delivery conditional and there is nothing new to report, reply with exactly ${EMPTY_DELIVERY_SENTINEL} and no other text. This includes results already delivered or incorporated into an earlier response; do not send an acknowledgement of that redundancy. Do not use this marker for ordinary conversations, after input or approval responses, or to omit commentary from a response that still needs delivery. Never return an empty response; use the marker to intentionally deliver nothing.`;function hasEmptyDeliverySentinel(e){return e?.includes(`<eve-empty-delivery/>`)===!0||e?.includes(`&lt;eve-empty-delivery/&gt;`)===!0}export{CONDITIONAL_DELIVERY_INSTRUCTION,EMPTY_DELIVERY_SENTINEL,hasEmptyDeliverySentinel};
@@ -0,0 +1,22 @@
1
+ import type { ModelMessage } from "ai";
2
+ export interface HistoryViewProjectionInput {
3
+ readonly messages: readonly ModelMessage[];
4
+ readonly state: Readonly<Record<string, unknown>> | undefined;
5
+ }
6
+ export type HistoryViewProjector = (input: HistoryViewProjectionInput) => readonly ModelMessage[];
7
+ export interface PreparedHistoryView {
8
+ readonly messages: readonly ModelMessage[];
9
+ readonly sourceMessages: readonly ModelMessage[];
10
+ readonly sourceState: Readonly<Record<string, unknown>> | undefined;
11
+ }
12
+ export declare const identityHistoryViewProjector: HistoryViewProjector;
13
+ export declare function createHistoryViewPreparer(input?: {
14
+ readonly previous?: PreparedHistoryView;
15
+ readonly projector?: HistoryViewProjector;
16
+ }): (messages: readonly ModelMessage[], state: Readonly<Record<string, unknown>> | undefined) => PreparedHistoryView;
17
+ export declare function prepareHistoryView(input: {
18
+ readonly messages: readonly ModelMessage[];
19
+ readonly previous?: PreparedHistoryView;
20
+ readonly projector?: HistoryViewProjector;
21
+ readonly state?: Readonly<Record<string, unknown>>;
22
+ }): PreparedHistoryView;
@@ -0,0 +1 @@
1
+ const identityHistoryViewProjector=({messages:e})=>e;function createHistoryViewPreparer(e){let t=e?.previous;return(n,r)=>(t=prepareHistoryView({messages:n,previous:t,projector:e?.projector,state:r}),t)}function prepareHistoryView(e){return e.previous?.sourceMessages===e.messages&&e.previous.sourceState===e.state?e.previous:{messages:(e.projector??identityHistoryViewProjector)({messages:e.messages,state:e.state}),sourceMessages:e.messages,sourceState:e.state}}export{createHistoryViewPreparer,identityHistoryViewProjector,prepareHistoryView};