pi-commandcode-provider 0.5.1 → 0.6.1

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.
@@ -0,0 +1,140 @@
1
+ import type {
2
+ AssistantMessageEvent,
3
+ AssistantMessageEventStreamLike,
4
+ ContextLike,
5
+ ModelLike,
6
+ StreamOptions,
7
+ } from "./types.ts"
8
+
9
+ export type CommandCodeTransport = "unknown" | "provider" | "generate"
10
+
11
+ interface TransportDependencies {
12
+ createStream: () => AssistantMessageEventStreamLike
13
+ streamProvider: (
14
+ model: ModelLike,
15
+ context: ContextLike,
16
+ options?: StreamOptions,
17
+ ) => AssistantMessageEventStreamLike
18
+ streamGenerate: (
19
+ model: ModelLike,
20
+ context: ContextLike,
21
+ options?: StreamOptions,
22
+ ) => AssistantMessageEventStreamLike
23
+ }
24
+
25
+ function isRecord(value: unknown): value is Record<string, unknown> {
26
+ return typeof value === "object" && value !== null && !Array.isArray(value)
27
+ }
28
+
29
+ async function isUpgradeRequired(response: Response): Promise<boolean> {
30
+ if (response.status !== 403) return false
31
+
32
+ try {
33
+ const body: unknown = await response.clone().json()
34
+ if (!isRecord(body)) return false
35
+ const error = isRecord(body.error) ? body.error : body
36
+ return error.code === "upgrade_required"
37
+ } catch {
38
+ return false
39
+ }
40
+ }
41
+
42
+ export function createCommandCodeTransportRouter(deps: TransportDependencies) {
43
+ let transport: CommandCodeTransport = "unknown"
44
+ let apiKey: string | undefined
45
+
46
+ function pipe(
47
+ source: AssistantMessageEventStreamLike,
48
+ target: AssistantMessageEventStreamLike,
49
+ ): Promise<void> {
50
+ return (async () => {
51
+ for await (const event of source) target.push(event)
52
+ })()
53
+ }
54
+
55
+ return {
56
+ getTransport(): CommandCodeTransport {
57
+ return transport
58
+ },
59
+
60
+ reset(): void {
61
+ transport = "unknown"
62
+ apiKey = undefined
63
+ },
64
+
65
+ stream(
66
+ model: ModelLike,
67
+ context: ContextLike,
68
+ options?: StreamOptions,
69
+ ): AssistantMessageEventStreamLike {
70
+ if (options?.apiKey !== apiKey) {
71
+ apiKey = options?.apiKey
72
+ transport = "unknown"
73
+ }
74
+ const requestApiKey = options?.apiKey
75
+ if (transport === "generate") return deps.streamGenerate(model, context, options)
76
+
77
+ const output = deps.createStream()
78
+ let upgradeRequired = false
79
+ const fetchImpl = options?.fetch ?? fetch
80
+ const providerOptions: StreamOptions = {
81
+ ...options,
82
+ fetch: async (input, init) => {
83
+ const response = await fetchImpl(input, init)
84
+ if (await isUpgradeRequired(response)) upgradeRequired = true
85
+ return response
86
+ },
87
+ onResponse: async (response, responseModel) => {
88
+ if (upgradeRequired) return
89
+ await options?.onResponse?.(response, responseModel)
90
+ },
91
+ }
92
+
93
+ const run = async () => {
94
+ const providerStream = deps.streamProvider(model, context, providerOptions)
95
+
96
+ for await (const event of providerStream) {
97
+ if (!upgradeRequired) {
98
+ if (apiKey === requestApiKey) transport = "provider"
99
+ output.push(event)
100
+ }
101
+ }
102
+
103
+ if (upgradeRequired) {
104
+ if (apiKey === requestApiKey) transport = "generate"
105
+ await pipe(deps.streamGenerate(model, context, options), output)
106
+ }
107
+ output.end()
108
+ }
109
+
110
+ run().catch((error: unknown) => {
111
+ const message = error instanceof Error ? error.message : String(error)
112
+ output.push({
113
+ type: "error",
114
+ reason: "error",
115
+ error: {
116
+ role: "assistant",
117
+ content: [],
118
+ api: model.api,
119
+ provider: model.provider,
120
+ model: model.id,
121
+ usage: {
122
+ input: 0,
123
+ output: 0,
124
+ cacheRead: 0,
125
+ cacheWrite: 0,
126
+ totalTokens: 0,
127
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
128
+ },
129
+ stopReason: "error",
130
+ errorMessage: message,
131
+ timestamp: Date.now(),
132
+ },
133
+ })
134
+ output.end()
135
+ })
136
+
137
+ return output
138
+ },
139
+ }
140
+ }
package/src/types.ts CHANGED
@@ -110,7 +110,10 @@ export interface StreamOptions {
110
110
  apiKey?: string
111
111
  signal?: AbortSignal
112
112
  headers?: Record<string, string>
113
+ fetch?: typeof fetch
113
114
  maxTokens?: number
115
+ temperature?: number
116
+ sessionId?: string
114
117
  /** Resolved pi thinking level; forwarded only through the model's map. */
115
118
  reasoning?: string
116
119
  onPayload?: (payload: unknown, model: ModelLike) => unknown | Promise<unknown>
@@ -171,6 +174,12 @@ export type AssistantMessageEvent =
171
174
  contentIndex: number
172
175
  partial: AssistantMessageLike
173
176
  }
177
+ | {
178
+ type: "toolcall_delta"
179
+ contentIndex: number
180
+ delta: string
181
+ partial: AssistantMessageLike
182
+ }
174
183
  | {
175
184
  type: "toolcall_end"
176
185
  contentIndex: number