@code-yeongyu/senpi-ai 2026.9.12-3 → 2026.9.12
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/README.md +4 -39
- package/dist/api/anthropic-messages.d.ts.map +1 -1
- package/dist/api/anthropic-messages.js +1 -8
- package/dist/api/anthropic-messages.js.map +1 -1
- package/dist/api/cloudflare-gateway-binding.d.ts +69 -0
- package/dist/api/cloudflare-gateway-binding.d.ts.map +1 -0
- package/dist/api/cloudflare-gateway-binding.js +159 -0
- package/dist/api/cloudflare-gateway-binding.js.map +1 -0
- package/dist/api/cursor-agent/measure.d.ts +0 -11
- package/dist/api/cursor-agent/measure.d.ts.map +1 -1
- package/dist/api/cursor-agent/measure.js +0 -18
- package/dist/api/cursor-agent/measure.js.map +1 -1
- package/dist/api/cursor-agent.d.ts +1 -1
- package/dist/api/cursor-agent.d.ts.map +1 -1
- package/dist/api/cursor-agent.js +1 -5
- package/dist/api/cursor-agent.js.map +1 -1
- package/dist/api/mistral-conversations.js +1 -4
- package/dist/api/mistral-conversations.js.map +1 -1
- package/dist/api/openai-codex-responses.d.ts.map +1 -1
- package/dist/api/openai-codex-responses.js +3 -6
- package/dist/api/openai-codex-responses.js.map +1 -1
- package/dist/api/openai-responses-shared.d.ts.map +1 -1
- package/dist/api/openai-responses-shared.js +1 -4
- package/dist/api/openai-responses-shared.js.map +1 -1
- package/dist/api/openai-responses.d.ts.map +1 -1
- package/dist/api/openai-responses.js +3 -13
- package/dist/api/openai-responses.js.map +1 -1
- package/dist/cursor/store-migration.d.ts.map +1 -1
- package/dist/cursor/store-migration.js +1 -2
- package/dist/cursor/store-migration.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +0 -1
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +2 -5
- package/dist/models.js.map +1 -1
- package/dist/openai-responses-compat.d.ts +1 -1
- package/dist/openai-responses-compat.d.ts.map +1 -1
- package/dist/openai-responses-compat.js.map +1 -1
- package/dist/providers/cloudflare-ai-gateway.d.ts.map +1 -1
- package/dist/providers/cloudflare-ai-gateway.js +0 -4
- package/dist/providers/cloudflare-ai-gateway.js.map +1 -1
- package/dist/providers/cursor.d.ts.map +1 -1
- package/dist/providers/cursor.js +1 -2
- package/dist/providers/cursor.js.map +1 -1
- package/dist/providers/data/.manifest.json +1 -1
- package/dist/providers/data/azure-openai-responses.json +1 -1
- package/dist/providers/data/baseten.json +1 -1
- package/dist/providers/data/deepseek.json +1 -1
- package/dist/providers/data/fireworks.json +1 -1
- package/dist/providers/data/github-copilot.json +1 -1
- package/dist/providers/data/openai-codex.json +1 -1
- package/dist/providers/data/openrouter.json +1 -1
- package/dist/providers/data/qwen-token-plan-cn.json +1 -1
- package/dist/providers/data/qwen-token-plan-individual.json +1 -1
- package/dist/providers/data/qwen-token-plan.json +1 -1
- package/dist/providers/data/xai.json +1 -1
- package/dist/providers/faux.js +5 -5
- package/dist/providers/faux.js.map +1 -1
- package/dist/providers/opencode-go.d.ts.map +1 -1
- package/dist/providers/opencode-go.js +3 -4
- package/dist/providers/opencode-go.js.map +1 -1
- package/dist/providers/opencode.d.ts.map +1 -1
- package/dist/providers/opencode.js +4 -5
- package/dist/providers/opencode.js.map +1 -1
- package/dist/types.d.ts +6 -16
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/event-stream.d.ts.map +1 -1
- package/dist/utils/event-stream.js +5 -25
- package/dist/utils/event-stream.js.map +1 -1
- package/dist/utils/prompt-cache-ttl.d.ts +1 -1
- package/dist/utils/prompt-cache-ttl.d.ts.map +1 -1
- package/dist/utils/prompt-cache-ttl.js +1 -5
- package/dist/utils/prompt-cache-ttl.js.map +1 -1
- package/dist/utils/retry-profile/types.d.ts +1 -10
- package/dist/utils/retry-profile/types.d.ts.map +1 -1
- package/dist/utils/retry-profile/types.js.map +1 -1
- package/dist/utils/retry.d.ts +2 -13
- package/dist/utils/retry.d.ts.map +1 -1
- package/dist/utils/retry.js +7 -18
- package/dist/utils/retry.js.map +1 -1
- package/dist/utils/uuid.d.ts +2 -2
- package/dist/utils/uuid.d.ts.map +1 -1
- package/dist/utils/uuid.js +31 -36
- package/dist/utils/uuid.js.map +1 -1
- package/package.json +6 -6
- package/dist/api/cloudflare-ai-binding.d.ts +0 -77
- package/dist/api/cloudflare-ai-binding.d.ts.map +0 -1
- package/dist/api/cloudflare-ai-binding.js +0 -72
- package/dist/api/cloudflare-ai-binding.js.map +0 -1
- package/dist/cursor/context-limit-store.d.ts +0 -32
- package/dist/cursor/context-limit-store.d.ts.map +0 -1
- package/dist/cursor/context-limit-store.js +0 -62
- package/dist/cursor/context-limit-store.js.map +0 -1
- package/dist/providers/opencode-headers.d.ts +0 -4
- package/dist/providers/opencode-headers.d.ts.map +0 -1
- package/dist/providers/opencode-headers.js +0 -22
- package/dist/providers/opencode-headers.js.map +0 -1
- package/dist/utils/assistant-message-frame.d.ts +0 -77
- package/dist/utils/assistant-message-frame.d.ts.map +0 -1
- package/dist/utils/assistant-message-frame.js +0 -427
- package/dist/utils/assistant-message-frame.js.map +0 -1
- package/dist/utils/cursor-context-limit.d.ts +0 -12
- package/dist/utils/cursor-context-limit.d.ts.map +0 -1
- package/dist/utils/cursor-context-limit.js +0 -93
- package/dist/utils/cursor-context-limit.js.map +0 -1
package/README.md
CHANGED
|
@@ -26,7 +26,6 @@ Unified LLM API with provider collections, automatic auth resolution, token and
|
|
|
26
26
|
- [Streaming Tool Calls with Partial JSON](#streaming-tool-calls-with-partial-json)
|
|
27
27
|
- [Validating Tool Arguments](#validating-tool-arguments)
|
|
28
28
|
- [Complete Event Reference](#complete-event-reference)
|
|
29
|
-
- [Compact Assistant Message Frames](#compact-assistant-message-frames)
|
|
30
29
|
- [Image Input](#image-input)
|
|
31
30
|
- [Image Generation](#image-generation)
|
|
32
31
|
- [Thinking/Reasoning](#thinkingreasoning)
|
|
@@ -663,10 +662,6 @@ for await (const event of s) {
|
|
|
663
662
|
|
|
664
663
|
### Complete Event Reference
|
|
665
664
|
|
|
666
|
-
Successful generation follows `start → updates* → done`. A failure after generation starts follows `start → updates* → error`. Request setup may fail before generation starts, in which case the stream contains only `error`; `done` and update events are invalid before `start`. Direct API `streamSimple()` calls throw synchronously when request auth is missing.
|
|
667
|
-
|
|
668
|
-
Every non-terminal event's `partial` is the shared live response-so-far helper. It is intentionally not an event-time snapshot: providers may mutate the same message and content blocks as generation advances, including while older events wait in the stream queue. Inspect it when handling an event instead of retaining it as historical state. Text and ordinary thinking blocks are empty when their `*_start` event is emitted and grow only through matching `*_delta` events until the authoritative `*_end`; redacted thinking may be complete at start and emit no deltas. Tool-call arguments at `toolcall_start` are provider-specific; `toolcall_delta` carries subsequent JSON updates.
|
|
669
|
-
|
|
670
665
|
All streaming events emitted during assistant message generation:
|
|
671
666
|
|
|
672
667
|
| Event Type | Description | Key Properties |
|
|
@@ -680,40 +675,12 @@ All streaming events emitted during assistant message generation:
|
|
|
680
675
|
| `thinking_end` | Thinking block complete | `content`: Full thinking, `contentIndex`: Position |
|
|
681
676
|
| `toolcall_start` | Tool call begins | `contentIndex`: Position in content array |
|
|
682
677
|
| `toolcall_delta` | Tool arguments streaming | `delta`: JSON chunk, `partial.content[contentIndex].arguments`: Partial parsed args |
|
|
683
|
-
| `toolcall_end` | Tool call complete | `toolCall`: Complete
|
|
678
|
+
| `toolcall_end` | Tool call complete | `toolCall`: Complete validated tool call with `id`, `name`, `arguments` |
|
|
684
679
|
| `done` | Stream complete | `reason`: Stop reason ("stop", "length", "toolUse"), `message`: Final assistant message |
|
|
685
680
|
| `error` | Error occurred | `reason`: Error type ("error" or "aborted"), `error`: AssistantMessage with partial content |
|
|
686
681
|
|
|
687
682
|
Streaming events for different content blocks are not guaranteed to be contiguous. Providers may emit deltas for text, thinking, and tool calls in the same upstream chunk, and pi may surface corresponding events interleaved, for example `text_start`, `text_delta`, `toolcall_start`, `text_delta`, `toolcall_delta`. Consumers must use `contentIndex` to associate each delta/end event with its block and must not assume that a block's `*_start`/`*_delta`/`*_end` sequence is uninterrupted by events for other blocks.
|
|
688
683
|
|
|
689
|
-
### Compact Assistant Message Frames
|
|
690
|
-
|
|
691
|
-
`AssistantMessageFrameEncoder` converts one stream into compact, persistable `AssistantMessageFrame` values. Create one encoder per stream and feed it every event in order. The encoder understands that `partial` is live: a block-start event consumed after the provider has already queued later deltas snapshots the current block once, and covered queued text/thinking deltas produce no duplicate frame. It retains only per-open-block counters plus, temporarily, the raw prefix needed to synchronize an already-advanced tool call. It never clones the growing full partial per token.
|
|
692
|
-
|
|
693
|
-
The start frame contains message metadata with empty content. Text and thinking frames store each generated character at most once before the authoritative end frame. Tool calls that were already advanced when their start event was consumed use one compact JSON checkpoint before ordinary deltas resume. Terminal `done` and `error` events produce no frame because final message settlement is separate. A pre-generation `error` therefore produces no frames.
|
|
694
|
-
|
|
695
|
-
`reduceAssistantMessageFrames()` is the canonical pure reducer. It reconstructs text, thinking, and tool-call arguments, including interleaved blocks identified by `contentIndex`, and rejects malformed sequences. It performs a single pass over the iterable and returns `undefined` when there is no start frame. End frames replace blocks with the provider's authoritative completed content and metadata. The reducer does not validate tool arguments against a TypeBox schema; call `validateToolCall` before execution.
|
|
696
|
-
|
|
697
|
-
```typescript
|
|
698
|
-
import {
|
|
699
|
-
AssistantMessageFrameEncoder,
|
|
700
|
-
reduceAssistantMessageFrames,
|
|
701
|
-
type AssistantMessageFrame,
|
|
702
|
-
} from '@earendil-works/pi-ai';
|
|
703
|
-
|
|
704
|
-
const encoder = new AssistantMessageFrameEncoder();
|
|
705
|
-
const frames: AssistantMessageFrame[] = [];
|
|
706
|
-
for await (const event of s) {
|
|
707
|
-
const frame = encoder.encode(event);
|
|
708
|
-
if (frame) frames.push(frame);
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
const reconstructedPartial = reduceAssistantMessageFrames(frames);
|
|
712
|
-
const finalMessage = await s.result(); // Persist terminal settlement separately.
|
|
713
|
-
```
|
|
714
|
-
|
|
715
|
-
An encoder rejects duplicate starts, updates before start, `done` before start, events after a terminal event, duplicate block starts, and block-kind mismatches. An `error` before start is valid and returns no frame.
|
|
716
|
-
|
|
717
684
|
## Image Input
|
|
718
685
|
|
|
719
686
|
Models with vision capabilities can process images. You can check if a model supports images via the `input` property. If you pass images to a non-vision model, they are silently ignored.
|
|
@@ -938,7 +905,7 @@ Every `AssistantMessage` includes a `stopReason` field that indicates how the ge
|
|
|
938
905
|
|
|
939
906
|
## Error Handling
|
|
940
907
|
|
|
941
|
-
Request failures
|
|
908
|
+
Request failures never throw out of the stream functions: when a request ends with an error (including aborts and tool call validation errors), the streaming API emits an error event and the final message carries the details:
|
|
942
909
|
|
|
943
910
|
```typescript
|
|
944
911
|
// In streaming
|
|
@@ -960,7 +927,7 @@ if (message.stopReason === 'error' || message.stopReason === 'aborted') {
|
|
|
960
927
|
}
|
|
961
928
|
```
|
|
962
929
|
|
|
963
|
-
|
|
930
|
+
Auth failures (no key configured, OAuth refresh failed, unknown provider) surface the same way: as a stream error with `stopReason: "error"`.
|
|
964
931
|
|
|
965
932
|
### Aborting Requests
|
|
966
933
|
|
|
@@ -1220,7 +1187,7 @@ interface OpenAICompletionsCompat {
|
|
|
1220
1187
|
supportsUsageInStreaming?: boolean; // Whether provider supports `stream_options: { include_usage: true }` (default: true)
|
|
1221
1188
|
supportsStrictMode?: boolean; // Whether provider supports `strict` in tool definitions (default: true)
|
|
1222
1189
|
supportsOpenAIGrammarTools?: boolean; // Whether to emit OpenAI custom Lark/regex grammar tools; false falls back to normal function tools (default: false; the generated catalog enables it for capable models)
|
|
1223
|
-
sendSessionAffinityHeaders?: boolean; // Send session-affinity data from `sessionId` (default:
|
|
1190
|
+
sendSessionAffinityHeaders?: boolean; // Send session-affinity data from `sessionId` (default: false)
|
|
1224
1191
|
sessionAffinityFormat?: 'openai' | 'openai-nosession' | 'openrouter'; // Format for session affinity: 'openai' uses `prompt_cache_key`, `session_id`, `x-client-request-id`, and `x-session-affinity`; 'openai-nosession' uses `prompt_cache_key`, `x-client-request-id`, and `x-session-affinity`; 'openrouter' uses `x-session-id` (default: auto-detected)
|
|
1225
1192
|
maxTokensField?: 'max_completion_tokens' | 'max_tokens'; // Which field name to use (default: max_completion_tokens)
|
|
1226
1193
|
requiresToolResultName?: boolean; // Whether tool results require the `name` field (default: false)
|
|
@@ -1246,8 +1213,6 @@ interface OpenAIResponsesCompat {
|
|
|
1246
1213
|
}
|
|
1247
1214
|
```
|
|
1248
1215
|
|
|
1249
|
-
OpenRouter requests send `x-session-id` from `sessionId` when prompt caching is enabled. Chat Completions and Anthropic Messages both auto-detect OpenRouter endpoints unless `sendSessionAffinityHeaders` is explicitly false. On Anthropic-compatible models, `sessionAffinityFormat: "openrouter"` selects `x-session-id`; when unset, the existing `x-session-affinity` format is used. Explicit request headers take precedence over generated headers.
|
|
1250
|
-
|
|
1251
1216
|
If `compat` is not set, the library falls back to URL-based detection. If `compat` is partially set, unspecified fields use the detected defaults. This is useful for:
|
|
1252
1217
|
|
|
1253
1218
|
- **LiteLLM proxies**: May not support `store` field
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic-messages.d.ts","sourceRoot":"","sources":["../../src/api/anthropic-messages.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAC1C,OAAO,KAAK,EAMX,+BAA+B,EAK/B,MAAM,uDAAuD,CAAC;AAG/D,OAAO,KAAK,EACX,wBAAwB,EAKxB,OAAO,EAGP,KAAK,EAGL,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAGb,IAAI,EAIJ,MAAM,aAAa,CAAC;AAsCrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AA0ElE,eAAO,MAAM,gBAAgB,SAAU,MAAM,WAC2B,CAAC;AACzE,eAAO,MAAM,kBAAkB,SAAU,MAAM,UAAU,IAAI,EAAE,WAS9D,CAAC;AA4EF,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAE1E,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG,SAAS,CAAC;AA+FhE,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACtD;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,wBAAwB,CAAC;IAC5C;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACnB;AAmvBD,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,oBAAoB,EAAE,gBAAgB,CAudzE,CAAC;AAyFF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,oBAAoB,EAAE,mBAAmB,CA+ClF,CAAC;
|
|
1
|
+
{"version":3,"file":"anthropic-messages.d.ts","sourceRoot":"","sources":["../../src/api/anthropic-messages.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAC1C,OAAO,KAAK,EAMX,+BAA+B,EAK/B,MAAM,uDAAuD,CAAC;AAG/D,OAAO,KAAK,EACX,wBAAwB,EAKxB,OAAO,EAGP,KAAK,EAGL,mBAAmB,EAEnB,cAAc,EACd,aAAa,EAGb,IAAI,EAIJ,MAAM,aAAa,CAAC;AAsCrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AA0ElE,eAAO,MAAM,gBAAgB,SAAU,MAAM,WAC2B,CAAC;AACzE,eAAO,MAAM,kBAAkB,SAAU,MAAM,UAAU,IAAI,EAAE,WAS9D,CAAC;AA4EF,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAE1E,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG,SAAS,CAAC;AA+FhE,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACtD;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,wBAAwB,CAAC;IAC5C;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACnB;AAmvBD,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,oBAAoB,EAAE,gBAAgB,CAudzE,CAAC;AAyFF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,oBAAoB,EAAE,mBAAmB,CA+ClF,CAAC;AA6IF,wBAAgB,mCAAmC,CAClD,KAAK,EAAE,KAAK,CAAC,oBAAoB,CAAC,EAClC,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,gBAAgB,GACxB,+BAA+B,CAkBjC"}
|
|
@@ -1432,14 +1432,7 @@ function createClient(model, apiKey, interleavedThinking, useFineGrainedToolStre
|
|
|
1432
1432
|
return { client, isOAuthToken: true };
|
|
1433
1433
|
}
|
|
1434
1434
|
// API key auth
|
|
1435
|
-
const
|
|
1436
|
-
const sessionAffinityHeaders = {};
|
|
1437
|
-
if (sessionId && affinityCompat.sendSessionAffinityHeaders) {
|
|
1438
|
-
// OpenRouter routes prompt-cache affinity through its own header name and
|
|
1439
|
-
// rejects x-session-affinity (earendil-works/pi#9102).
|
|
1440
|
-
const header = affinityCompat.sessionAffinityFormat === "openrouter" ? "x-session-id" : "x-session-affinity";
|
|
1441
|
-
sessionAffinityHeaders[header] = sessionId;
|
|
1442
|
-
}
|
|
1435
|
+
const sessionAffinityHeaders = sessionId && getAnthropicCompat(model).sendSessionAffinityHeaders ? { "x-session-affinity": sessionId } : {};
|
|
1443
1436
|
const client = new Anthropic({
|
|
1444
1437
|
apiKey: apiKey ?? null,
|
|
1445
1438
|
authToken: null,
|