continuation-scenarios.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import { LLM, Message, ToolCallPart, ToolDefinition, ToolResultPart, type ContentPart, type Model } from "../src"
  2. export const basicContinuation = ["system", "user-text", "assistant-text", "user-follow-up"] as const
  3. export const toolContinuation = ["tool-call", "tool-result"] as const
  4. export const reasoningContinuation = ["assistant-reasoning", "encrypted-reasoning"] as const
  5. export const mediaContinuation = ["user-image"] as const
  6. export const maximalContinuation = [
  7. ...basicContinuation,
  8. ...toolContinuation,
  9. ...reasoningContinuation,
  10. ...mediaContinuation,
  11. ] as const
  12. export type ContinuationFeature = (typeof maximalContinuation)[number]
  13. export const nativeOpenAIResponsesContinuation = [
  14. ...basicContinuation,
  15. ...toolContinuation,
  16. "encrypted-reasoning",
  17. ...mediaContinuation,
  18. ] as const satisfies ReadonlyArray<ContinuationFeature>
  19. export const nativeAnthropicMessagesContinuation = [
  20. ...basicContinuation,
  21. ...toolContinuation,
  22. "assistant-reasoning",
  23. ...mediaContinuation,
  24. ] as const satisfies ReadonlyArray<ContinuationFeature>
  25. export const continuationTool = ToolDefinition.make({
  26. name: "get_weather",
  27. description: "Get current weather for a city.",
  28. inputSchema: {
  29. type: "object",
  30. properties: { city: { type: "string" } },
  31. required: ["city"],
  32. additionalProperties: false,
  33. },
  34. })
  35. export function continuationRequest(input: {
  36. readonly id: string
  37. readonly model: Model
  38. readonly features: ReadonlyArray<ContinuationFeature>
  39. readonly image?: string
  40. }) {
  41. const features = new Set(input.features)
  42. const messages = []
  43. const firstUser: ContentPart[] = []
  44. const firstAssistant: ContentPart[] = []
  45. if (features.has("user-text")) firstUser.push({ type: "text", text: "What is shown here?" })
  46. if (features.has("user-image"))
  47. firstUser.push({ type: "media", mediaType: "image/png", data: input.image ?? "AAECAw==" })
  48. if (firstUser.length > 0) messages.push(Message.user(firstUser))
  49. if (features.has("assistant-reasoning"))
  50. firstAssistant.push({
  51. type: "reasoning",
  52. text: "I inspected the previous turn.",
  53. providerMetadata: { anthropic: { signature: "sig_continuation_1" } },
  54. })
  55. if (features.has("encrypted-reasoning"))
  56. firstAssistant.push({
  57. type: "reasoning",
  58. text: "I inspected the previous turn.",
  59. providerMetadata: {
  60. openai: {
  61. itemId: "rs_continuation_1",
  62. reasoningEncryptedContent: "encrypted-continuation-state",
  63. },
  64. },
  65. })
  66. if (features.has("assistant-text")) firstAssistant.push({ type: "text", text: "It shows a small test image." })
  67. if (firstAssistant.length > 0) messages.push(Message.assistant(firstAssistant))
  68. if (features.has("tool-call")) {
  69. messages.push(Message.user("Check the weather in Paris before continuing."))
  70. messages.push(
  71. Message.assistant([ToolCallPart.make({ id: "call_weather_1", name: "get_weather", input: { city: "Paris" } })]),
  72. )
  73. }
  74. if (features.has("tool-result")) {
  75. messages.push(
  76. Message.tool(ToolResultPart.make({ id: "call_weather_1", name: "get_weather", result: { temperature: 22 } })),
  77. )
  78. if (features.has("assistant-text")) messages.push(Message.assistant("Paris is 22 degrees."))
  79. }
  80. if (features.has("user-follow-up"))
  81. messages.push(Message.user("Continue from this conversation in one short sentence."))
  82. return LLM.request({
  83. id: input.id,
  84. model: input.model,
  85. system: features.has("system") ? "You are concise. Continue from the provided history." : undefined,
  86. messages,
  87. tools: features.has("tool-call") ? [continuationTool] : [],
  88. cache: "none",
  89. providerOptions: features.has("encrypted-reasoning")
  90. ? { openai: { store: false, include: ["reasoning.encrypted_content"], reasoningSummary: "auto" } }
  91. : undefined,
  92. generation: { maxTokens: 80, temperature: 0 },
  93. })
  94. }