@code-yeongyu/senpi 2026.10.18-1 → 2026.10.19
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/CHANGELOG.md +29 -0
- package/dist/bundle/chunks/{anthropic-messages-3CFTFCKV.js → anthropic-messages-EMTBHJMM.js} +2 -2
- package/dist/bundle/chunks/{args-SJWMIH2H.js → args-LWR7VFKS.js} +1 -1
- package/dist/bundle/chunks/{chunk-IRKZ6FVC.js → chunk-35M5MVUZ.js} +149 -145
- package/dist/bundle/chunks/chunk-3DNYAO3P.js +2 -0
- package/dist/bundle/chunks/{chunk-T2BEB5SO.js → chunk-7QPFFAJT.js} +1 -1
- package/dist/bundle/chunks/{chunk-4RUVN7K3.js → chunk-BOCN744P.js} +1 -1
- package/dist/bundle/chunks/{chunk-DDHBG2HU.js → chunk-FM7NDZR5.js} +1 -1
- package/dist/bundle/chunks/{chunk-OMY4EC25.js → chunk-FSENE7JK.js} +2 -2
- package/dist/bundle/chunks/{chunk-Z2LCTXS2.js → chunk-G7LLAQXI.js} +3 -3
- package/dist/bundle/chunks/{chunk-NRHOGI4Z.js → chunk-IM6ZWYTW.js} +2 -2
- package/dist/bundle/chunks/{chunk-MLKYJIUK.js → chunk-KM4FMQII.js} +1 -1
- package/dist/bundle/chunks/{chunk-OOWML2KE.js → chunk-PMGEQYEP.js} +2 -2
- package/dist/bundle/chunks/chunk-QGJLZ6BI.js +2 -0
- package/dist/bundle/chunks/{chunk-6EXDMO4S.js → chunk-QJ6MUFXY.js} +1 -1
- package/dist/bundle/chunks/{chunk-FZTO2ICI.js → chunk-QRGAMVEE.js} +1 -1
- package/dist/bundle/chunks/{chunk-3QVP3ZVI.js → chunk-QXEWAKXA.js} +1 -1
- package/dist/bundle/chunks/{chunk-UUMKAA7S.js → chunk-RL5QMGQD.js} +9 -9
- package/dist/bundle/chunks/chunk-T36LJ6MW.js +3 -0
- package/dist/bundle/chunks/{chunk-GAHIHXVE.js → chunk-VEKNDMUA.js} +1 -1
- package/dist/bundle/chunks/{chunk-TFXUF2IL.js → chunk-VPV7ADF3.js} +1 -1
- package/dist/bundle/chunks/{chunk-RELAITQ7.js → chunk-X6TWPBI6.js} +1 -1
- package/dist/bundle/chunks/{chunk-PKDWFVE4.js → chunk-YUMRZIKJ.js} +6 -6
- package/dist/bundle/chunks/chunk-ZPSJQHDK.js +395 -0
- package/dist/bundle/chunks/{cli-main-JCSB54VT.js → cli-main-EABMHWFV.js} +1 -1
- package/dist/bundle/chunks/{help-fast-path-FVPGRSYA.js → help-fast-path-BYWJN6YX.js} +1 -1
- package/dist/bundle/chunks/{host-command-X2ZZFTME.js → host-command-5T34JLBP.js} +1 -1
- package/dist/bundle/chunks/{host-lifecycle-OKWTQFUJ.js → host-lifecycle-GSRIQP6Z.js} +1 -1
- package/dist/bundle/chunks/host-lifecycle.js +1 -1
- package/dist/bundle/chunks/{host-session-command-HKJKOAVS.js → host-session-command-LF6JODPX.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-GJERAFGV.js → interactive-mode-GMWHBIUC.js} +1 -1
- package/dist/bundle/chunks/{list-tips-AWDAUHF2.js → list-tips-VSWED3PT.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-JWMGLKAG.js → multi-session-host-3J7STKGD.js} +4 -4
- package/dist/bundle/chunks/{openai-codex-responses-RLYFSLK6.js → openai-codex-responses-7YOBPZ2N.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-OWNSXMTD.js → openai-completions-HSZPYXEA.js} +1 -1
- package/dist/bundle/chunks/{package-manager-cli-FSVS2ND2.js → package-manager-cli-LWQZSWKL.js} +1 -1
- package/dist/bundle/chunks/{rotation-stream-M6QV2MMB.js → rotation-stream-QRRWL73X.js} +1 -1
- package/dist/bundle/chunks/{rpc-mode-TPG3J3ZJ.js → rpc-mode-6LSWRKXR.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-PAVLVMWL.js → schedule-command-7CXMW4WK.js} +1 -1
- package/dist/bundle/chunks/{session-control-endpoint-NSMRMKKK.js → session-control-endpoint-E265WAIQ.js} +1 -1
- package/dist/bundle/chunks/{session-picker-UV6IVWJY.js → session-picker-XRB3LP5W.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +298 -293
- package/dist/bundle/cli.js +2 -2
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -1
- package/dist/core/agent-run-continuation.d.ts +24 -0
- package/dist/core/agent-run-continuation.js +57 -0
- package/dist/core/agent-session.d.ts +38 -1
- package/dist/core/agent-session.js +122 -13
- package/dist/core/extension-handler-stall-report.d.ts +11 -0
- package/dist/core/extension-handler-stall-report.js +26 -0
- package/dist/core/extensions/builtin/anthropic-subscription/account-command.js +1 -0
- package/dist/core/extensions/builtin/anthropic-subscription/affinity.d.ts +13 -1
- package/dist/core/extensions/builtin/anthropic-subscription/affinity.js +15 -4
- package/dist/core/extensions/builtin/anthropic-subscription/auth-lane.js +2 -0
- package/dist/core/extensions/builtin/anthropic-subscription/failover.d.ts +2 -0
- package/dist/core/extensions/builtin/anthropic-subscription/failover.js +3 -2
- package/dist/core/extensions/builtin/anthropic-subscription/guidance.d.ts +8 -0
- package/dist/core/extensions/builtin/anthropic-subscription/guidance.js +29 -0
- package/dist/core/extensions/builtin/anthropic-subscription/settings.d.ts +2 -0
- package/dist/core/extensions/builtin/anthropic-subscription/settings.js +4 -0
- package/dist/core/extensions/builtin/anthropic-subscription/stream-guidance.js +4 -2
- package/dist/core/extensions/handler-budget.d.ts +84 -0
- package/dist/core/extensions/handler-budget.js +136 -0
- package/dist/core/extensions/runner.d.ts +23 -0
- package/dist/core/extensions/runner.js +184 -99
- package/dist/core/footer-data-provider.js +2 -1
- package/dist/core/keybindings.d.ts +1 -1
- package/dist/core/keybindings.js +3 -2
- package/dist/core/pending-input-journal.d.ts +6 -1
- package/dist/core/pending-input-journal.js +90 -34
- package/dist/core/pending-input-public.d.ts +11 -0
- package/dist/core/pending-input-public.js +10 -0
- package/dist/core/pending-input-session-port.d.ts +15 -0
- package/dist/core/pending-input-session-port.js +93 -0
- package/dist/core/pending-input-session.d.ts +108 -0
- package/dist/core/pending-input-session.js +220 -0
- package/dist/core/pending-input-store.d.ts +32 -1
- package/dist/core/pending-input-store.js +74 -26
- package/dist/core/pending-input-types.d.ts +25 -4
- package/dist/core/pending-input.js +36 -18
- package/dist/core/session-entry-file.js +1 -0
- package/dist/core/session-log.js +1 -1
- package/dist/core/session-manager.d.ts +1 -0
- package/dist/core/session-manager.js +5 -1
- package/dist/core/session-move/bundle.d.ts +39 -0
- package/dist/core/session-move/bundle.js +108 -0
- package/dist/core/session-move/export.d.ts +18 -0
- package/dist/core/session-move/export.js +83 -0
- package/dist/core/session-move/finish.d.ts +24 -0
- package/dist/core/session-move/finish.js +81 -0
- package/dist/core/session-move/import.d.ts +32 -0
- package/dist/core/session-move/import.js +124 -0
- package/dist/core/session-move/move-ledger.d.ts +47 -0
- package/dist/core/session-move/move-ledger.js +151 -0
- package/dist/core/session-move/ownership.d.ts +61 -0
- package/dist/core/session-move/ownership.js +89 -0
- package/dist/core/session-move/requeue.d.ts +8 -0
- package/dist/core/session-move/requeue.js +18 -0
- package/dist/core/session-move/write-guard.d.ts +22 -0
- package/dist/core/session-move/write-guard.js +44 -0
- package/dist/core/settings-manager.d.ts +13 -0
- package/dist/core/settings-manager.js +17 -0
- package/dist/core/turn-deadline.d.ts +2 -0
- package/dist/core/turn-deadline.js +10 -3
- package/dist/modes/interactive/components/ask-user-async-widget.d.ts +7 -0
- package/dist/modes/interactive/components/ask-user-async-widget.js +20 -6
- package/dist/modes/rpc/connection-handler.js +3 -0
- package/dist/modes/rpc/effect-commands.js +3 -4
- package/dist/modes/rpc/host-observe-request.js +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +10 -0
- package/dist/modes/rpc/rpc-client.js +11 -0
- package/dist/modes/rpc/rpc-input-validation.js +8 -0
- package/dist/modes/rpc/rpc-types.d.ts +25 -1
- package/dist/modes/rpc/session-command-activity.js +1 -0
- package/dist/modes/rpc/session-control-actions-data.js +17 -8
- package/dist/modes/rpc/session-held.js +1 -0
- package/dist/modes/rpc/session-release.js +16 -1
- package/dist/modes/rpc/tool-child/admission.d.ts +42 -0
- package/dist/modes/rpc/tool-child/admission.js +81 -0
- package/dist/modes/rpc/tool-child/admission.test.d.ts +2 -0
- package/dist/modes/rpc/tool-child/admission.test.js +166 -0
- package/dist/modes/rpc/tool-child/codec.d.ts +21 -0
- package/dist/modes/rpc/tool-child/codec.js +137 -0
- package/dist/modes/rpc/tool-child/codec.test.d.ts +2 -0
- package/dist/modes/rpc/tool-child/codec.test.js +234 -0
- package/dist/modes/rpc/tool-child/context.d.ts +42 -0
- package/dist/modes/rpc/tool-child/context.js +23 -0
- package/dist/modes/rpc/tool-child/flow-control.d.ts +24 -0
- package/dist/modes/rpc/tool-child/flow-control.js +80 -0
- package/dist/modes/rpc/tool-child/payload-ref-paths.d.ts +9 -0
- package/dist/modes/rpc/tool-child/payload-ref-paths.js +45 -0
- package/dist/modes/rpc/tool-child/payload-ref.d.ts +58 -0
- package/dist/modes/rpc/tool-child/payload-ref.js +166 -0
- package/dist/modes/rpc/tool-child/payload-ref.test.d.ts +2 -0
- package/dist/modes/rpc/tool-child/payload-ref.test.js +254 -0
- package/dist/modes/rpc/tool-child/payload-wire.d.ts +13 -0
- package/dist/modes/rpc/tool-child/payload-wire.js +22 -0
- package/dist/modes/rpc/tool-child/protocol-guard.d.ts +9 -0
- package/dist/modes/rpc/tool-child/protocol-guard.js +128 -0
- package/dist/modes/rpc/tool-child/protocol.d.ts +192 -0
- package/dist/modes/rpc/tool-child/protocol.js +54 -0
- package/dist/utils/wsl.d.ts +2 -2
- package/dist/utils/wsl.js +4 -4
- package/docs/providers.md +2 -0
- package/docs/rpc.md +16 -2
- package/docs/settings.md +1 -0
- package/docs/terminal-setup.md +2 -0
- package/package.json +10 -6
- package/dist/bundle/chunks/chunk-COJK5FDH.js +0 -2
- package/dist/bundle/chunks/chunk-IDXW4FAO.js +0 -2
- package/dist/bundle/chunks/chunk-PFNBY43W.js +0 -2
- package/dist/bundle/chunks/chunk-QBD4LY7D.js +0 -395
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire vocabulary between the server and a session's tool child (senpi#3566).
|
|
3
|
+
*
|
|
4
|
+
* Every frame crosses the private channel as one length-prefixed binary frame (`codec.ts`), never as NDJSON. Payloads
|
|
5
|
+
* above `REF_THRESHOLD` never travel inline: they move as an acknowledged `PayloadRef` (`payload-ref.ts`) in either
|
|
6
|
+
* direction. `trace` is the only lossy frame class; it never carries a job result, a launch proof or a tick.
|
|
7
|
+
*/
|
|
8
|
+
export declare const TOOL_CHILD_LIMITS: {
|
|
9
|
+
/** Largest encoded frame body, in bytes; a larger length header is refused before its body is allocated. */
|
|
10
|
+
readonly frameBytes: number;
|
|
11
|
+
/** Ordinary jobs one child runs at once; nested jobs are bounded by `hostCallCapacity()` instead. */
|
|
12
|
+
readonly jobs: 32;
|
|
13
|
+
/** Wake notifications awaiting `wake_ack`, by count and by summed size; the next one waits (never dropped). */
|
|
14
|
+
readonly wakePending: 64;
|
|
15
|
+
readonly wakePendingBytes: number;
|
|
16
|
+
readonly HOST_CALL_ACTIVE: 8;
|
|
17
|
+
readonly HOST_CALL_WAITING: 256;
|
|
18
|
+
/** A payload whose JSON exceeds this many bytes moves by reference, never inline. */
|
|
19
|
+
readonly REF_THRESHOLD: number;
|
|
20
|
+
/** A ref still unacknowledged after this long is reported overdue (the writer still does not delete it). */
|
|
21
|
+
readonly refAckMs: 30000;
|
|
22
|
+
/** Bytes of ref files one side may own at once. */
|
|
23
|
+
readonly refsBudget: number;
|
|
24
|
+
readonly tracePerSecond: 1024;
|
|
25
|
+
};
|
|
26
|
+
export declare const LAUNCH_CONTAINMENTS: readonly ["own-group", "inherited", "job", "breakaway"];
|
|
27
|
+
export type LaunchContainment = (typeof LAUNCH_CONTAINMENTS)[number];
|
|
28
|
+
export declare const LAUNCH_LIFETIMES: readonly ["owned", "detached"];
|
|
29
|
+
export type LaunchLifetime = (typeof LAUNCH_LIFETIMES)[number];
|
|
30
|
+
/** Which surface asked for the process. */
|
|
31
|
+
export declare const LAUNCH_ORIGINS: readonly ["tool", "terminal", "user_bash", "interpreter", "monitor", "kernel"];
|
|
32
|
+
export type LaunchOrigin = (typeof LAUNCH_ORIGINS)[number];
|
|
33
|
+
/** The launch API the command came through; group semantics differ per API. */
|
|
34
|
+
export declare const LAUNCH_APIS: readonly ["bun.spawn", "bun.spawnSync", "bun.shell", "cp.spawn", "cp.spawnSync", "cp.execFileSync"];
|
|
35
|
+
export type LaunchApi = (typeof LAUNCH_APIS)[number];
|
|
36
|
+
export declare const REF_NACK_REASONS: readonly ["cancelled", "corrupt", "missing", "budget", "foreign"];
|
|
37
|
+
export type RefNackReason = (typeof REF_NACK_REASONS)[number];
|
|
38
|
+
/** A payload moved through a file in the channel generation's directory. The receiver derives the path itself. */
|
|
39
|
+
export interface PayloadRef {
|
|
40
|
+
refId: string;
|
|
41
|
+
/** The channel's child generation; refs of both directions live under that generation's directory. */
|
|
42
|
+
generation: number;
|
|
43
|
+
bytes: number;
|
|
44
|
+
sha256: string;
|
|
45
|
+
}
|
|
46
|
+
/** One parsed transcript entry, with its canonical identity and its exact place in the file. */
|
|
47
|
+
export interface ParsedEntryMeta {
|
|
48
|
+
id: string;
|
|
49
|
+
/** Canonical parent from the file line, never from a compacted in-memory mirror. */
|
|
50
|
+
parentId: string | null;
|
|
51
|
+
lineOffset: number;
|
|
52
|
+
lineBytes: number;
|
|
53
|
+
/** Wire bytes minus line bytes after the canonical transform. */
|
|
54
|
+
lineDelta: number;
|
|
55
|
+
entry?: unknown;
|
|
56
|
+
}
|
|
57
|
+
export type TraceDetail = Readonly<Record<string, string | number | boolean>>;
|
|
58
|
+
/** Keys a `trace` detail may never carry: the lossy class never transports results, proofs or ticks. */
|
|
59
|
+
export declare const TRACE_RESERVED_KEYS: readonly ["value", "valueRef", "result", "ref", "args", "argsRef", "ackTick", "invokeTick"];
|
|
60
|
+
export type ServerToChild = {
|
|
61
|
+
type: "hello_ack";
|
|
62
|
+
generation: number;
|
|
63
|
+
} | {
|
|
64
|
+
type: "job";
|
|
65
|
+
jobId: string;
|
|
66
|
+
kind: string;
|
|
67
|
+
parentJobId?: string;
|
|
68
|
+
args?: unknown;
|
|
69
|
+
argsRef?: PayloadRef;
|
|
70
|
+
} | {
|
|
71
|
+
type: "cancel";
|
|
72
|
+
jobId: string;
|
|
73
|
+
} | {
|
|
74
|
+
type: "host_reply";
|
|
75
|
+
callId: string;
|
|
76
|
+
value?: unknown;
|
|
77
|
+
valueRef?: PayloadRef;
|
|
78
|
+
error?: string;
|
|
79
|
+
} | {
|
|
80
|
+
type: "host_call_refused";
|
|
81
|
+
callId: string;
|
|
82
|
+
code: string;
|
|
83
|
+
} | {
|
|
84
|
+
type: "launch_ack";
|
|
85
|
+
launchId: string;
|
|
86
|
+
} | {
|
|
87
|
+
type: "wake_ack";
|
|
88
|
+
wakeId: string;
|
|
89
|
+
} | {
|
|
90
|
+
type: "slot_query";
|
|
91
|
+
launchId: string;
|
|
92
|
+
} | {
|
|
93
|
+
type: "shutdown";
|
|
94
|
+
};
|
|
95
|
+
export type ChildToServer = {
|
|
96
|
+
type: "hello";
|
|
97
|
+
generation: number;
|
|
98
|
+
pid: number;
|
|
99
|
+
protocol: number;
|
|
100
|
+
} | {
|
|
101
|
+
type: "heartbeat";
|
|
102
|
+
seq: number;
|
|
103
|
+
} | {
|
|
104
|
+
type: "result";
|
|
105
|
+
jobId: string;
|
|
106
|
+
value: unknown;
|
|
107
|
+
} | {
|
|
108
|
+
type: "result_ref";
|
|
109
|
+
jobId: string;
|
|
110
|
+
ref: PayloadRef;
|
|
111
|
+
} | {
|
|
112
|
+
type: "job_error";
|
|
113
|
+
jobId: string;
|
|
114
|
+
code: string;
|
|
115
|
+
message: string;
|
|
116
|
+
} | {
|
|
117
|
+
type: "job_refused";
|
|
118
|
+
jobId: string;
|
|
119
|
+
code: string;
|
|
120
|
+
} | {
|
|
121
|
+
type: "host_call";
|
|
122
|
+
callId: string;
|
|
123
|
+
jobId: string;
|
|
124
|
+
tool: string;
|
|
125
|
+
args?: unknown;
|
|
126
|
+
argsRef?: PayloadRef;
|
|
127
|
+
} | {
|
|
128
|
+
type: "launch";
|
|
129
|
+
launchId: string;
|
|
130
|
+
jobId: string;
|
|
131
|
+
origin: LaunchOrigin;
|
|
132
|
+
api: LaunchApi;
|
|
133
|
+
containment: LaunchContainment;
|
|
134
|
+
lifetime: LaunchLifetime;
|
|
135
|
+
pid?: number;
|
|
136
|
+
pgid?: number;
|
|
137
|
+
} | {
|
|
138
|
+
type: "launch_proof";
|
|
139
|
+
launchId: string;
|
|
140
|
+
ackTick: number;
|
|
141
|
+
invokeTick: number;
|
|
142
|
+
} | {
|
|
143
|
+
type: "launch_done";
|
|
144
|
+
launchId: string;
|
|
145
|
+
exitCode?: number;
|
|
146
|
+
signal?: string;
|
|
147
|
+
} | {
|
|
148
|
+
type: "command_started";
|
|
149
|
+
launchId: string;
|
|
150
|
+
pid: number;
|
|
151
|
+
startedAtMs: number;
|
|
152
|
+
creatorInJob: boolean;
|
|
153
|
+
breakaway: boolean;
|
|
154
|
+
} | {
|
|
155
|
+
type: "slot_state";
|
|
156
|
+
launchId: string;
|
|
157
|
+
ackTick: number | null;
|
|
158
|
+
invokeTick: number | null;
|
|
159
|
+
invocations: number;
|
|
160
|
+
} | {
|
|
161
|
+
type: "wake";
|
|
162
|
+
wakeId: string;
|
|
163
|
+
source: string;
|
|
164
|
+
bytes: number;
|
|
165
|
+
} | {
|
|
166
|
+
type: "batch";
|
|
167
|
+
jobId: string;
|
|
168
|
+
entries: ParsedEntryMeta[];
|
|
169
|
+
done: boolean;
|
|
170
|
+
} | {
|
|
171
|
+
type: "trace";
|
|
172
|
+
atMs: number;
|
|
173
|
+
event: string;
|
|
174
|
+
detail?: TraceDetail;
|
|
175
|
+
};
|
|
176
|
+
/** Either side acknowledges or refuses a ref the other side wrote. */
|
|
177
|
+
export type RefControl = {
|
|
178
|
+
type: "ref_ack";
|
|
179
|
+
refId: string;
|
|
180
|
+
} | {
|
|
181
|
+
type: "ref_nack";
|
|
182
|
+
refId: string;
|
|
183
|
+
reason: RefNackReason;
|
|
184
|
+
};
|
|
185
|
+
export type ToolChildMessage = ServerToChild | ChildToServer | RefControl;
|
|
186
|
+
export type ToolChildMessageType = ToolChildMessage["type"];
|
|
187
|
+
export type ToolChildMessageOf<T extends ToolChildMessageType> = Extract<ToolChildMessage, {
|
|
188
|
+
type: T;
|
|
189
|
+
}>;
|
|
190
|
+
/** The only frame class a full budget may drop (counted). */
|
|
191
|
+
export declare const LOSSY_FRAME_TYPES: ReadonlySet<ToolChildMessageType>;
|
|
192
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire vocabulary between the server and a session's tool child (senpi#3566).
|
|
3
|
+
*
|
|
4
|
+
* Every frame crosses the private channel as one length-prefixed binary frame (`codec.ts`), never as NDJSON. Payloads
|
|
5
|
+
* above `REF_THRESHOLD` never travel inline: they move as an acknowledged `PayloadRef` (`payload-ref.ts`) in either
|
|
6
|
+
* direction. `trace` is the only lossy frame class; it never carries a job result, a launch proof or a tick.
|
|
7
|
+
*/
|
|
8
|
+
const MIB = 1024 * 1024;
|
|
9
|
+
export const TOOL_CHILD_LIMITS = {
|
|
10
|
+
/** Largest encoded frame body, in bytes; a larger length header is refused before its body is allocated. */
|
|
11
|
+
frameBytes: 16 * MIB,
|
|
12
|
+
/** Ordinary jobs one child runs at once; nested jobs are bounded by `hostCallCapacity()` instead. */
|
|
13
|
+
jobs: 32,
|
|
14
|
+
/** Wake notifications awaiting `wake_ack`, by count and by summed size; the next one waits (never dropped). */
|
|
15
|
+
wakePending: 64,
|
|
16
|
+
wakePendingBytes: 1 * MIB,
|
|
17
|
+
HOST_CALL_ACTIVE: 8,
|
|
18
|
+
HOST_CALL_WAITING: 256,
|
|
19
|
+
/** A payload whose JSON exceeds this many bytes moves by reference, never inline. */
|
|
20
|
+
REF_THRESHOLD: 4 * MIB,
|
|
21
|
+
/** A ref still unacknowledged after this long is reported overdue (the writer still does not delete it). */
|
|
22
|
+
refAckMs: 30_000,
|
|
23
|
+
/** Bytes of ref files one side may own at once. */
|
|
24
|
+
refsBudget: 1024 * MIB,
|
|
25
|
+
tracePerSecond: 1024,
|
|
26
|
+
};
|
|
27
|
+
export const LAUNCH_CONTAINMENTS = ["own-group", "inherited", "job", "breakaway"];
|
|
28
|
+
export const LAUNCH_LIFETIMES = ["owned", "detached"];
|
|
29
|
+
/** Which surface asked for the process. */
|
|
30
|
+
export const LAUNCH_ORIGINS = ["tool", "terminal", "user_bash", "interpreter", "monitor", "kernel"];
|
|
31
|
+
/** The launch API the command came through; group semantics differ per API. */
|
|
32
|
+
export const LAUNCH_APIS = [
|
|
33
|
+
"bun.spawn",
|
|
34
|
+
"bun.spawnSync",
|
|
35
|
+
"bun.shell",
|
|
36
|
+
"cp.spawn",
|
|
37
|
+
"cp.spawnSync",
|
|
38
|
+
"cp.execFileSync",
|
|
39
|
+
];
|
|
40
|
+
export const REF_NACK_REASONS = ["cancelled", "corrupt", "missing", "budget", "foreign"];
|
|
41
|
+
/** Keys a `trace` detail may never carry: the lossy class never transports results, proofs or ticks. */
|
|
42
|
+
export const TRACE_RESERVED_KEYS = [
|
|
43
|
+
"value",
|
|
44
|
+
"valueRef",
|
|
45
|
+
"result",
|
|
46
|
+
"ref",
|
|
47
|
+
"args",
|
|
48
|
+
"argsRef",
|
|
49
|
+
"ackTick",
|
|
50
|
+
"invokeTick",
|
|
51
|
+
];
|
|
52
|
+
/** The only frame class a full budget may drop (counted). */
|
|
53
|
+
export const LOSSY_FRAME_TYPES = new Set(["trace"]);
|
|
54
|
+
//# sourceMappingURL=protocol.js.map
|
package/dist/utils/wsl.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/** Windows Subsystem for Linux, where Windows executables are reachable through interop. */
|
|
2
|
-
export declare function isWSL(env?: NodeJS.ProcessEnv): boolean;
|
|
1
|
+
/** Windows Subsystem for Linux, where Windows executables are reachable through interop. Linux-only by contract: callers on other platforms must guard with a platform check (as keybindings and the footer provider do), because `WSLENV` can also be set on native Windows. */
|
|
2
|
+
export declare function isWSL(env?: NodeJS.ProcessEnv, procVersionPath?: string): boolean;
|
|
3
3
|
//# sourceMappingURL=wsl.d.ts.map
|
package/dist/utils/wsl.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
-
/** Windows Subsystem for Linux, where Windows executables are reachable through interop. */
|
|
3
|
-
export function isWSL(env = process.env) {
|
|
4
|
-
if (env.WSL_DISTRO_NAME || env.WSLENV) {
|
|
2
|
+
/** Windows Subsystem for Linux, where Windows executables are reachable through interop. Linux-only by contract: callers on other platforms must guard with a platform check (as keybindings and the footer provider do), because `WSLENV` can also be set on native Windows. */
|
|
3
|
+
export function isWSL(env = process.env, procVersionPath = "/proc/version") {
|
|
4
|
+
if (env.WSL_DISTRO_NAME || env.WSL_INTEROP || env.WSLENV) {
|
|
5
5
|
return true;
|
|
6
6
|
}
|
|
7
7
|
try {
|
|
8
|
-
const release = readFileSync(
|
|
8
|
+
const release = readFileSync(procVersionPath, "utf-8");
|
|
9
9
|
return /microsoft|wsl/i.test(release);
|
|
10
10
|
}
|
|
11
11
|
catch {
|
package/docs/providers.md
CHANGED
|
@@ -137,6 +137,7 @@ The `anthropic-subscription` provider routes LLM calls through the official [Cla
|
|
|
137
137
|
- Run `/login anthropic-subscription` to sign in with your Claude Pro/Max subscription (PKCE, same OAuth client as the Claude Code CLI). An existing Anthropic OAuth credential is offered as an import.
|
|
138
138
|
- Multiple accounts: each `/login anthropic-subscription` adds another named account. `CLAUDE_CODE_OAUTH_TOKEN` (and `_2`..`_N`) are honored as read-only env accounts. `/claude-account` lists, adds, removes, and pins accounts; `--claude-account <name>` pins one for the session; `anthropicSubscriptionProvider.pinnedAccount` pins one in settings.
|
|
139
139
|
- Session affinity: one senpi session sticks to one account (rendezvous hashing), which keeps Anthropic's prompt cache warm - accounts never rotate mid-session except on automatic failover. Rate limits and auth errors block the account (with cooldown) and retry on the next account, before any visible output; once output has started, the error surfaces instead of replaying.
|
|
140
|
+
- To stop instead of spending another account's allowance, set `anthropicSubscriptionProvider.accountFallback: false`. On managed lanes (`oauth-slots` and `config-dir`), only the explicitly pinned account, otherwise the resident session's account, otherwise the deterministic affinity winner may serve the request. A blocked selected account is not skipped on later requests. Same-account transient retries and credential refresh still work; an explicit account pin can select a different account. The default is `true`. This is independent of `retry.modelFallback` / `--no-model-fallback`; disable model fallback too if you do not want a different model or provider to serve the failed turn. The ambient lane has no managed-account fallback.
|
|
140
141
|
- Default lane: **ambient** - with no `tokenInjection` setting the provider inherits the environment like the upstream extension (Claude Code CLI login or `ANTHROPIC_API_KEY`). Managed lanes (`oauth-slots`, `config-dir`) are opt-in via one settings line until the live subscription spike proves a managed default.
|
|
141
142
|
- Ambient lane is explicit opt-in: a Claude Code CLI login on the host is not consent to spend that subscription, so the ambient lane is gated by `anthropicSubscriptionProvider.enabled` (default `false`, env override `SENPI_CLAUDE_SDK_OAUTH_ENABLED`). Before this gate existed, a logged-in Claude Code CLI made the provider available with no senpi-side action. An explicit senpi-side login is itself an opt-in: stored OAuth accounts in `auth.json` and `CLAUDE_CODE_OAUTH_TOKEN` / `CLAUDE_CODE_OAUTH_TOKEN_<n>` env accounts keep the provider available with the flag unset. Only the host-CLI-derived ambient lane requires the flag.
|
|
142
143
|
- Settings (`anthropicSubscriptionProvider`):
|
|
@@ -154,6 +155,7 @@ The `anthropic-subscription` provider routes LLM calls through the official [Cla
|
|
|
154
155
|
| `SENPI_CLAUDE_SDK_OAUTH_TOKEN_INJECTION` | `oauth-slots` \| `config-dir` \| `ambient` |
|
|
155
156
|
| `SENPI_CLAUDE_SDK_OAUTH_SETTING_SOURCES` | Overrides `settingSources` |
|
|
156
157
|
| `SENPI_CLAUDE_SDK_OAUTH_PINNED_ACCOUNT` | Overrides `pinnedAccount` |
|
|
158
|
+
| `SENPI_CLAUDE_SDK_OAUTH_ACCOUNT_FALLBACK` | `0` / `false` disables managed-account fallback; `1` / `true` enables it |
|
|
157
159
|
| `SENPI_CLAUDE_SDK_OAUTH_COMPACTION_OWNER` | Overrides `compactionOwner` (`senpi` \| `sdk`) |
|
|
158
160
|
|
|
159
161
|
Every `SENPI_*` variable is stripped from the Claude Code subprocess environment on all three lanes; other inherited variables are preserved.
|
package/docs/rpc.md
CHANGED
|
@@ -1836,6 +1836,8 @@ no longer lists it and the handle answers `unknown_session`.
|
|
|
1836
1836
|
`session_released` entry on disk or in memory, and a later release can be retried. A teardown that fails
|
|
1837
1837
|
after it claimed the session leaves it closing.
|
|
1838
1838
|
|
|
1839
|
+
A release with `reason: "move"` (and a `moveId`) seals the session for a move to another device: its `session_released` entry records `move_id`, `target` and `session_id`, and from then on any write to the file is refused with `session_moved_away` until that same move is reclaimed. A later `takeover` release, or any ownership entry for another move, is refused too. A `move` without `moveId` is refused with `invalid_release_reason`.
|
|
1840
|
+
|
|
1839
1841
|
### Host self-observation (event-loop stalls and memory pressure)
|
|
1840
1842
|
|
|
1841
1843
|
Every in-process session shares the host's event loop, so a session that blocks it freezes every other session and the
|
|
@@ -2054,7 +2056,7 @@ names a valid preset.
|
|
|
2054
2056
|
| `close_session` | `sessionId` | `{}` | Refused with `unknown_session` when the requesting connection never attached to that handle (a close releases the CALLER's attachment, and `list_sessions` publishes every handle). Otherwise aborts active work, awaits agent idle + settled persistence for up to the host grace window (default 10s), then quarantines any worker that has not exited without releasing its path reservation; its response is the LAST record tagged with that handle for the first closer — no events after (test-pinned). An admitted concurrent close joins the same teardown and receives its own successful response; output saturation rejects admission with the bounded close-overflow/resync notice described above. |
|
|
2055
2057
|
| `list_sessions` | `include_workers?` (default false) | `{ sessions: [{ sessionId, durableSessionId, sessionPath, cwd, name, status, attachments, kind, context? }] }` | Includes `opening`/`closing` entries. Internally quarantined workers remain externally `closing` until exit. `attachments` is the session's live client attachment count; `0` on an `open` row is a retained session with no client attached. Every row carries `kind`. Rows with `kind: "worker"` are omitted unless `include_workers: true`, and `context` is published ONLY on that listing — a default listing carries no `context` at all. |
|
|
2056
2058
|
| `detach_connection` | - | `{ deferred: string[] }` | Multi-session hosts that advertise `detach_connection`. Meant as the connection's last request: the host releases every session attachment this connection holds and answers only after that, so another connection's next `list_sessions` no longer counts it. `deferred` names the sessions that still count it (see `#### detach_connection`). Closing the socket afterwards releases nothing more. `senpi host session` sends it before closing, bounded at 5 s; on a host without the capability, or after a request timed out or the connection was lost, it relies on the release at socket close. |
|
|
2057
|
-
| `release_session` | `sessionId`, `reason: "takeover"`, `interrupt?`, `force?` | `{ released: true, session_path, attachments }` | Hands the session to a runtime outside this host. See "Handing a session over (`release_session`)" below. |
|
|
2059
|
+
| `release_session` | `sessionId`, `reason: "takeover" \| "move"`, `moveId?` (required for `move`), `target?`, `interrupt?`, `force?` | `{ released: true, session_path, attachments }` | Hands the session to a runtime outside this host. See "Handing a session over (`release_session`)" below. |
|
|
2058
2060
|
| `wake` | `sessionId`, `delivery_ids?` | `{ admitted: [{ delivery_id, kind }] }` | Runs the session's registered inbox drain once. See "Waking a host session (`wake`)" below. |
|
|
2059
2061
|
| `warm` | `cwd?`, `kind?`, `context?` (as on `open_session`; `cwd` MUST be absolute) | `{ state: "warmed" \| "already_warm" \| "unsupported" }` | Loads what the next matching `open_session` needs without opening a session; never listed, never an attachment, idempotent per profile. See "Warming a host" above. Advertised as the `warm` capability by in-process hosts only. |
|
|
2060
2062
|
| every existing command | + `sessionId` (REQUIRED in multi mode) | unchanged | Routed to that session. |
|
|
@@ -2532,6 +2534,18 @@ For both commands, `status` is `removed` / `edited`, or `already_delivered` (the
|
|
|
2532
2534
|
{"type": "response", "command": "edit_queued_message", "success": true, "data": {"queuedId": "q_4", "status": "conflict", "currentRevision": 2, "reason": "conflict", "action": "read the input's current text and revision from get_state or queue_update, then retry with that expectedRevision if the change still applies"}}
|
|
2533
2535
|
```
|
|
2534
2536
|
|
|
2537
|
+
#### get_pending_inputs
|
|
2538
|
+
|
|
2539
|
+
What the engine holds for every pending input, and the outcome of each id a client sent, read in one consistent step (senpi#3549). `inputs` lists every input still queued, sending or failed, each as a projection: `clientMessageId`, `state` (`queued`, `edited`, `sending`, `failed`), `text`, `requestedMode`, `revision`, `statusCode`, `statusText`, `actions` and `pendingDecoration`. `knownClientMessageIds` (at most 64 non-empty ids of at most 256 characters) asks for an outcome per id: `admitted` with its projection, including `delivered` and `removed`, or `not_admitted`. Absence from `inputs` is never an outcome; read the id's outcome instead.
|
|
2540
|
+
|
|
2541
|
+
The answer is consistent through `throughCursor`. To follow changes without a gap, subscribe first, apply the snapshot, then apply only `pending_input_update` events whose `cursor` is later. Each event carries every input one committed change touched, under that change's single `cursor`, with the same `lifetimeId`. A different `lifetimeId` means the session reopened: read the snapshot again.
|
|
2542
|
+
|
|
2543
|
+
```json
|
|
2544
|
+
{"type": "get_pending_inputs", "knownClientMessageIds": ["c-7"]}
|
|
2545
|
+
{"type": "response", "command": "get_pending_inputs", "success": true, "data": {"lifetimeId": "5b0c…", "throughCursor": 4, "inputs": [{"clientMessageId": "c-7", "state": "queued", "text": "also run the tests", "requestedMode": "followUp", "revision": 1, "statusCode": "queued_follow_up", "statusText": "Queued - sent after this turn", "actions": ["edit", "remove", "copy"], "pendingDecoration": true, "supersededVersions": []}], "outcomes": [{"clientMessageId": "c-7", "status": "admitted", "projection": {"clientMessageId": "c-7", "state": "queued"}}]}}
|
|
2546
|
+
{"type": "pending_input_update", "lifetimeId": "5b0c…", "cursor": 5, "changes": [{"clientMessageId": "c-7", "state": "sending"}]}
|
|
2547
|
+
```
|
|
2548
|
+
|
|
2535
2549
|
#### clear_queue
|
|
2536
2550
|
|
|
2537
2551
|
Remove queued steering and follow-up messages and return their text.
|
|
@@ -2791,7 +2805,7 @@ List all configured models, refreshing credential availability on each request s
|
|
|
2791
2805
|
{"type": "get_available_models"}
|
|
2792
2806
|
```
|
|
2793
2807
|
|
|
2794
|
-
Response contains an array of full [Model](#model) objects with supported thinking levels. Each row also carries `supportsAssistantPrefill`: whether the model accepts a request ending with an assistant message, given the session's current thinking level. It is `false` for every model today, so clients continue an edited answer with `continue_from_leaf`:
|
|
2808
|
+
Response contains an array of full [Model](#model) objects with supported thinking levels. A row's `serviceTier` and `upstreamModelId` are the values the session resolves for that model, including ones declared only in `models.json` or by an extension provider, so a `-fast` priority alias names its base model there and a client can tell a child opened on the base model is the alias it asked for. Each row also carries `supportsAssistantPrefill`: whether the model accepts a request ending with an assistant message, given the session's current thinking level. It is `false` for every model today, so clients continue an edited answer with `continue_from_leaf`:
|
|
2795
2809
|
```json
|
|
2796
2810
|
{
|
|
2797
2811
|
"type": "response",
|
package/docs/settings.md
CHANGED
|
@@ -415,6 +415,7 @@ When unset, senpi leaves provider payloads unchanged. This setting currently app
|
|
|
415
415
|
| Setting | Type | Default | Description |
|
|
416
416
|
|---------|------|---------|-------------|
|
|
417
417
|
| `anthropicSubscriptionProvider.enabled` | boolean | `false` | Enable the ambient (host-CLI-derived) lane of `anthropic-subscription`. Env override: `SENPI_CLAUDE_SDK_OAUTH_ENABLED`. Explicit senpi-side logins (stored OAuth accounts in `auth.json`, `CLAUDE_CODE_OAUTH_TOKEN` / `CLAUDE_CODE_OAUTH_TOKEN_<n>` env accounts) keep the provider available with this unset |
|
|
418
|
+
| `anthropicSubscriptionProvider.accountFallback` | boolean | `true` | Allow automatic switching between managed Claude accounts. `false` surfaces failure instead of using another account, including when the selected account is already blocked. Same-account retries and refresh remain enabled. Independent of `retry.modelFallback`. Env override: `SENPI_CLAUDE_SDK_OAUTH_ACCOUNT_FALLBACK` |
|
|
418
419
|
| `cursorCliOauthProvider.enabled` | boolean | `false` | Enable the `cursor-cli-oauth` fallback lane and automatic native credential bootstrap. Env override: `SENPI_CURSOR_CLI_OAUTH_ENABLED` |
|
|
419
420
|
| `providers.<id>.maxConcurrency` | number | unlimited | Cap the streaming requests senpi keeps in flight against one provider, keyed by registry provider id (`anthropic`, `openai`, ...). `0`, a negative value, a fraction, or an absent key all mean unlimited |
|
|
420
421
|
|
package/docs/terminal-setup.md
CHANGED
|
@@ -95,6 +95,8 @@ If you already have a `config.keys` table, add the entry to it.
|
|
|
95
95
|
|
|
96
96
|
On WSL, WezTerm may require a visible hardware cursor for IME candidate window positioning. If CJK IME candidates do not follow the text cursor, set `PI_HARDWARE_CURSOR=1` before running senpi or set `showHardwareCursor` to `true` in settings.
|
|
97
97
|
|
|
98
|
+
On Windows, inline images need WezTerm 20250208-160106 or newer, which today means a [nightly build](https://wezterm.org/install/windows.html). WezTerm runs the shell through the ConPTY it bundles, and the ConPTY in older builds (including the 20240203 stable release) drops Kitty graphics before WezTerm sees them. On those builds senpi shows the image placeholder with a hint to update instead of leaving a blank gap. Running senpi through `wezterm ssh` also bypasses ConPTY.
|
|
99
|
+
|
|
98
100
|
## Alacritty
|
|
99
101
|
|
|
100
102
|
Alacritty usually works out of the box for `Shift+Enter`. On macOS, `Option+Enter` may arrive as plain `Enter`. To use `Option+Enter` for pi follow-up queueing, add to `~/.config/alacritty/alacritty.toml`:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/senpi",
|
|
3
|
-
"version": "2026.10.
|
|
3
|
+
"version": "2026.10.19",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"piConfig": {
|
|
@@ -29,6 +29,10 @@
|
|
|
29
29
|
"types": "./dist/client/index.d.ts",
|
|
30
30
|
"import": "./dist/client/index.js"
|
|
31
31
|
},
|
|
32
|
+
"./pending-input": {
|
|
33
|
+
"types": "./dist/core/pending-input-public.d.ts",
|
|
34
|
+
"import": "./dist/core/pending-input-public.js"
|
|
35
|
+
},
|
|
32
36
|
"./prompt-presets": {
|
|
33
37
|
"types": "./dist/core/extensions/builtin/prompt-preset/public.d.ts",
|
|
34
38
|
"import": "./dist/core/extensions/builtin/prompt-preset/public.js"
|
|
@@ -60,9 +64,9 @@
|
|
|
60
64
|
},
|
|
61
65
|
"dependencies": {
|
|
62
66
|
"@earendil-works/chord": "0.99.1",
|
|
63
|
-
"@earendil-works/pi-agent-core": "npm:@code-yeongyu/senpi-agent-core@2026.10.
|
|
64
|
-
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.10.
|
|
65
|
-
"@earendil-works/pi-tui": "npm:@code-yeongyu/senpi-tui@2026.10.
|
|
67
|
+
"@earendil-works/pi-agent-core": "npm:@code-yeongyu/senpi-agent-core@2026.10.19",
|
|
68
|
+
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.10.19",
|
|
69
|
+
"@earendil-works/pi-tui": "npm:@code-yeongyu/senpi-tui@2026.10.19",
|
|
66
70
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
67
71
|
"chalk": "6.0.0",
|
|
68
72
|
"cross-spawn": "7.0.6",
|
|
@@ -81,8 +85,8 @@
|
|
|
81
85
|
"yaml": "2.9.1",
|
|
82
86
|
"@anthropic-ai/claude-agent-sdk": "0.3.296",
|
|
83
87
|
"@anthropic-ai/sdk": "0.127.0",
|
|
84
|
-
"@code-yeongyu/senpi-codemode": "2026.10.
|
|
85
|
-
"@earendil-works/pi-pty": "npm:@code-yeongyu/senpi-pty@2026.10.
|
|
88
|
+
"@code-yeongyu/senpi-codemode": "2026.10.19",
|
|
89
|
+
"@earendil-works/pi-pty": "npm:@code-yeongyu/senpi-pty@2026.10.19",
|
|
86
90
|
"@modelcontextprotocol/sdk": "1.32.1",
|
|
87
91
|
"@mozilla/readability": "0.6.0",
|
|
88
92
|
"linkedom": "0.18.13",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
-
import{getProviderEnvValue}from"./chunk-5ROMKDLK.js";import{appendAssistantMessageDiagnostic}from"./chunk-DMI55M2N.js";function isObject(value){return typeof value=="object"&&value!==null}function hasMessagesArray(value){return isObject(value)&&Array.isArray(value.messages)}function isContentBlockParam(value){return isObject(value)&&typeof value.type=="string"}function isToolUseBlock(block){return block.type==="tool_use"&&"id"in block&&typeof block.id=="string"}function isToolResultBlock(block){return block.type==="tool_result"}var SYNTHETIC_OUTPUT="Tool output unavailable (interrupted before result)";function cloneWith(block,patch){return{...block,...patch}}function isMessageWithArrayContent(value,role){if(!isObject(value)||value.role!==role||!Array.isArray(value.content))return!1;for(let block of value.content)if(!isContentBlockParam(block))return!1;return!0}function isUserMessageWithStringContent(value){return isObject(value)&&value.role==="user"&&typeof value.content=="string"}function dedupeAssistantToolUses(message,usedIds){let content=[],expectedIds=[],remapQueues=new Map,changed=!1;for(let block of message.content){if(!isToolUseBlock(block)||block.id.length===0){content.push(block);continue}let finalId=block.id;if(usedIds.has(finalId)){let suffix=2;for(;usedIds.has(`${block.id}__dedup${suffix}`);)suffix+=1;finalId=`${block.id}__dedup${suffix}`,changed=!0}usedIds.add(finalId),expectedIds.push(finalId);let queue=remapQueues.get(block.id);queue===void 0?remapQueues.set(block.id,[finalId]):queue.push(finalId),content.push(finalId===block.id?block:cloneWith(block,{id:finalId}))}return changed?{message:{...message,content},changed:!0,expectedIds,remapQueues}:{message,changed:!1,expectedIds,remapQueues}}function syntheticToolResult(toolUseId){return{type:"tool_result",tool_use_id:toolUseId,content:SYNTHETIC_OUTPUT,is_error:!0}}function sameBlocks(left,right){return left.length===right.length&&left.every((block,index)=>block===right[index])}function repairFollowingUserMessage(message,expectedIds,remapQueues){let expected=new Set(expectedIds),found=new Set,results=[],ordinary=[];for(let block of message.content){if(!isToolResultBlock(block)){ordinary.push(block);continue}let rawId=block.tool_use_id,id=rawId;if(typeof rawId=="string"){let queue=remapQueues.get(rawId);queue!==void 0&&queue.length>0&&(id=queue.shift())}typeof id!="string"||!expected.has(id)||found.has(id)||(found.add(id),results.push(id===rawId?block:cloneWith(block,{tool_use_id:id})))}for(let id of expectedIds)found.has(id)||results.push(syntheticToolResult(id));let content=[...results,...ordinary];return sameBlocks(content,message.content)?{message,changed:!1}:{message:{...message,content},changed:!0}}function removeOrphanResults(message){let content=message.content.filter(block=>!isToolResultBlock(block));return content.length===message.content.length?{message,changed:!1}:content.length===0?{changed:!0}:{message:{...message,content},changed:!0}}function sanitizeAnthropicToolPairs(payload){if(!hasMessagesArray(payload))return payload;let changed=!1,usedToolUseIds=new Set,sanitizedMessages=[];for(let index=0;index<payload.messages.length;index++){let unknownMessage=payload.messages[index];if(isMessageWithArrayContent(unknownMessage,"assistant")){let deduped=dedupeAssistantToolUses(unknownMessage,usedToolUseIds);sanitizedMessages.push(deduped.message),changed||=deduped.changed;let expectedIds=deduped.expectedIds;if(expectedIds.length===0)continue;let nextMessage=payload.messages[index+1];if(isMessageWithArrayContent(nextMessage,"user")){let repaired=repairFollowingUserMessage(nextMessage,expectedIds,deduped.remapQueues);sanitizedMessages.push(repaired.message),changed||=repaired.changed,index++;continue}if(isUserMessageWithStringContent(nextMessage)){sanitizedMessages.push({...nextMessage,content:[...expectedIds.map(syntheticToolResult),{type:"text",text:nextMessage.content}]}),changed=!0,index++;continue}sanitizedMessages.push({role:"user",content:expectedIds.map(syntheticToolResult)}),changed=!0;continue}if(isMessageWithArrayContent(unknownMessage,"user")){let repaired=removeOrphanResults(unknownMessage);repaired.message&&sanitizedMessages.push(repaired.message),changed||=repaired.changed;continue}sanitizedMessages.push(unknownMessage)}return changed?{...payload,messages:sanitizedMessages}:payload}var __rewriteRelativeImportExtension=function(path,preserveJsx){return typeof path=="string"&&/^\.\.?\//.test(path)?path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i,function(m,tsx,d,ext,cm){return tsx?preserveJsx?".jsx":".js":d&&(!ext||!cm)?m:d+ext+"."+cm.toLowerCase()+"js"}):path},_existsSync=null,_homedir=null,_join=null,dynamicImport=specifier=>import(__rewriteRelativeImportExtension(specifier)),NODE_FS_SPECIFIER="node:fs",NODE_OS_SPECIFIER="node:os",NODE_PATH_SPECIFIER="node:path";typeof process<"u"&&(process.versions?.node||process.versions?.bun)&&(dynamicImport(NODE_FS_SPECIFIER).then(m=>{_existsSync=m.existsSync}),dynamicImport(NODE_OS_SPECIFIER).then(m=>{_homedir=m.homedir}),dynamicImport(NODE_PATH_SPECIFIER).then(m=>{_join=m.join}));var ANTHROPIC_AUTH_TOKEN_ENV="ANTHROPIC_AUTH_TOKEN",ANTHROPIC_OAUTH_TOKEN_ENV="ANTHROPIC_OAUTH_TOKEN",ANTHROPIC_API_KEY_ENV="ANTHROPIC_API_KEY",ANTHROPIC_FEDERATION_RULE_ID_ENV="ANTHROPIC_FEDERATION_RULE_ID",ANTHROPIC_ORGANIZATION_ID_ENV="ANTHROPIC_ORGANIZATION_ID",ANTHROPIC_SERVICE_ACCOUNT_ID_ENV="ANTHROPIC_SERVICE_ACCOUNT_ID",ANTHROPIC_IDENTITY_TOKEN_FILE_ENV="ANTHROPIC_IDENTITY_TOKEN_FILE",ANTHROPIC_WORKSPACE_ID_ENV="ANTHROPIC_WORKSPACE_ID",cachedVertexAdcCredentialsExists=null;function hasVertexAdcCredentials(env){let explicitCredentialsPath=env?.GOOGLE_APPLICATION_CREDENTIALS;if(explicitCredentialsPath)return _existsSync?_existsSync(explicitCredentialsPath):!1;if(cachedVertexAdcCredentialsExists===null){if(!_existsSync||!_homedir||!_join)return typeof process<"u"&&(process.versions?.node||process.versions?.bun)||(cachedVertexAdcCredentialsExists=!1),!1;let gacPath=getProviderEnvValue("GOOGLE_APPLICATION_CREDENTIALS",env);gacPath?cachedVertexAdcCredentialsExists=_existsSync(gacPath):cachedVertexAdcCredentialsExists=_existsSync(_join(_homedir(),".config","gcloud","application_default_credentials.json"))}return cachedVertexAdcCredentialsExists}var API_KEY_ENV_VARS={"alibaba-token-plan":"ALIBABA_TOKEN_PLAN_API_KEY","ant-ling":"ANT_LING_API_KEY","qwen-token-plan":"QWEN_TOKEN_PLAN_API_KEY","qwen-token-plan-cn":"QWEN_TOKEN_PLAN_CN_API_KEY","qwen-token-plan-individual":"QWEN_TOKEN_PLAN_API_KEY",openai:"OPENAI_API_KEY",ollama:"OLLAMA_API_KEY","azure-openai-responses":"AZURE_OPENAI_API_KEY",nvidia:"NVIDIA_API_KEY",deepseek:"DEEPSEEK_API_KEY",google:"GEMINI_API_KEY","google-vertex":"GOOGLE_CLOUD_API_KEY",groq:"GROQ_API_KEY",cerebras:"CEREBRAS_API_KEY",venice:"VENICE_API_KEY",xai:"XAI_API_KEY",typesafe:"TYPESAFE_API_KEY",radius:"RADIUS_API_KEY",openrouter:"OPENROUTER_API_KEY","vercel-ai-gateway":"AI_GATEWAY_API_KEY",opengateway:"OPENGATEWAY_API_KEY",zai:"ZAI_API_KEY","zai-coding-cn":"ZAI_CODING_CN_API_KEY",mistral:"MISTRAL_API_KEY",minimax:"MINIMAX_API_KEY","minimax-cn":"MINIMAX_CN_API_KEY",moonshotai:"MOONSHOT_API_KEY","moonshotai-cn":"MOONSHOT_API_KEY",huggingface:"HF_TOKEN",fireworks:"FIREWORKS_API_KEY",together:"TOGETHER_API_KEY",baseten:"BASETEN_API_KEY",bai:"BAI_API_KEY",opencode:"OPENCODE_API_KEY","opencode-go":"OPENCODE_API_KEY","kimi-coding":"KIMI_API_KEY",meta:"META_API_KEY","cloudflare-workers-ai":"CLOUDFLARE_API_KEY","cloudflare-ai-gateway":"CLOUDFLARE_API_KEY",xiaomi:"XIAOMI_API_KEY","xiaomi-token-plan-cn":"XIAOMI_TOKEN_PLAN_CN_API_KEY","xiaomi-token-plan-ams":"XIAOMI_TOKEN_PLAN_AMS_API_KEY","xiaomi-token-plan-sgp":"XIAOMI_TOKEN_PLAN_SGP_API_KEY"},VERTEX_ADC_ENV_NAMES=["GOOGLE_APPLICATION_CREDENTIALS","GOOGLE_CLOUD_PROJECT","GCLOUD_PROJECT","GOOGLE_CLOUD_LOCATION"],BEDROCK_CREDENTIAL_ENV_NAMES=["AWS_PROFILE","AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","AWS_BEARER_TOKEN_BEDROCK","AWS_CONTAINER_CREDENTIALS_RELATIVE_URI","AWS_CONTAINER_CREDENTIALS_FULL_URI","AWS_WEB_IDENTITY_TOKEN_FILE"];function apiKeyEnvProviders(){return["github-copilot","anthropic",...Object.keys(API_KEY_ENV_VARS)]}function providerCredentialEnvNames(){let names=new Set([...VERTEX_ADC_ENV_NAMES,...BEDROCK_CREDENTIAL_ENV_NAMES]);for(let provider of apiKeyEnvProviders())for(let name of getApiKeyEnvVars(provider)??[])names.add(name);return[...names]}function getApiKeyEnvVars(provider){if(provider==="github-copilot")return["COPILOT_GITHUB_TOKEN"];if(provider==="anthropic")return[ANTHROPIC_AUTH_TOKEN_ENV,ANTHROPIC_OAUTH_TOKEN_ENV,ANTHROPIC_API_KEY_ENV];let envVar=API_KEY_ENV_VARS[provider];return envVar?[envVar]:void 0}function findEnvKeys(provider,env){let envVars=getApiKeyEnvVars(provider);if(!envVars)return;let found=envVars.filter(envVar=>!!getProviderEnvValue(envVar,env));return found.length>0?found:void 0}function getEnvApiKey(provider,env){let envKeys=findEnvKeys(provider,env);if(envKeys?.[0]){let apiKeyEnv=provider==="anthropic"?envKeys.find(key=>key!==ANTHROPIC_AUTH_TOKEN_ENV):envKeys[0];if(apiKeyEnv)return getProviderEnvValue(apiKeyEnv,env)}if(provider==="google-vertex"){let hasCredentials=hasVertexAdcCredentials(env),hasProject=!!(getProviderEnvValue("GOOGLE_CLOUD_PROJECT",env)||getProviderEnvValue("GCLOUD_PROJECT",env)),hasLocation=!!getProviderEnvValue("GOOGLE_CLOUD_LOCATION",env);if(hasCredentials&&hasProject&&hasLocation)return"<authenticated>"}if(provider==="amazon-bedrock"&&(getProviderEnvValue("AWS_PROFILE",env)||getProviderEnvValue("AWS_ACCESS_KEY_ID",env)&&getProviderEnvValue("AWS_SECRET_ACCESS_KEY",env)||getProviderEnvValue("AWS_BEARER_TOKEN_BEDROCK",env)||getProviderEnvValue("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI",env)||getProviderEnvValue("AWS_CONTAINER_CREDENTIALS_FULL_URI",env)||getProviderEnvValue("AWS_WEB_IDENTITY_TOKEN_FILE",env)))return"<authenticated>"}var SERVER_FALLBACK_ABORTED_DIAGNOSTIC="server_fallback_aborted",BILLING_INCOMPLETE_DIAGNOSTIC="billing_incomplete_after_client_abort";function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function readModel(value){if(isRecord(value))return typeof value.model=="string"&&value.model.length>0?value.model:void 0}function parseServerFallbackReceipt(block){if(!isRecord(block)||block.type!=="fallback")return;let from=readModel(block.from),to=readModel(block.to);return from!==void 0&&to!==void 0?{from,to}:void 0}function parseStickyFallbackReceipt(usage,requestedModel,servedModel){if(!(!isRecord(usage)||!Array.isArray(usage.iterations)))for(let index=usage.iterations.length-1;index>=0;index--){let entry=usage.iterations[index];if(!isRecord(entry)||entry.type!=="fallback_message")continue;let to=(typeof entry.model=="string"&&entry.model.length>0?entry.model:void 0)??servedModel;return to!==void 0?{from:requestedModel,to}:void 0}}function serverFallbackRefusalExplanation(receipt){return`Server-side fallback (${receipt.from} -> ${receipt.to}) aborted by client policy`}function applyServerFallbackContinuation(message,model,receipt){for(let[index,block]of message.content.entries())block.type==="toolCall"&&(message.content[index]={type:"providerNative",subtype:"discarded_tool_call",raw:block});message.model=receipt.to;let fallback=model.compat?.allowedFallbackModels?.find(candidate=>typeof candidate!="string"&&candidate.provider===model.provider&&candidate.model===receipt.to);return{...model,id:receipt.to,cost:fallback&&typeof fallback!="string"?fallback.cost:model.cost}}function applyServerFallbackAbort(message,receipt){let explanation=serverFallbackRefusalExplanation(receipt);message.content=[],message.stopReason="error",message.stopDetails={type:"refusal",explanation},message.errorMessage=explanation,appendAssistantMessageDiagnostic(message,{type:SERVER_FALLBACK_ABORTED_DIAGNOSTIC,timestamp:Date.now(),details:{from:receipt.from,to:receipt.to}}),appendAssistantMessageDiagnostic(message,{type:BILLING_INCOMPLETE_DIAGNOSTIC,timestamp:Date.now(),details:{reason:"per-attempt usage does not arrive after a client abort"}})}export{sanitizeAnthropicToolPairs,ANTHROPIC_AUTH_TOKEN_ENV,ANTHROPIC_OAUTH_TOKEN_ENV,ANTHROPIC_API_KEY_ENV,ANTHROPIC_FEDERATION_RULE_ID_ENV,ANTHROPIC_ORGANIZATION_ID_ENV,ANTHROPIC_SERVICE_ACCOUNT_ID_ENV,ANTHROPIC_IDENTITY_TOKEN_FILE_ENV,ANTHROPIC_WORKSPACE_ID_ENV,apiKeyEnvProviders,providerCredentialEnvNames,getApiKeyEnvVars,findEnvKeys,getEnvApiKey,SERVER_FALLBACK_ABORTED_DIAGNOSTIC,BILLING_INCOMPLETE_DIAGNOSTIC,parseServerFallbackReceipt,parseStickyFallbackReceipt,serverFallbackRefusalExplanation,applyServerFallbackContinuation,applyServerFallbackAbort};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
-
import{KeybindingsManager,TUI_KEYBINDINGS,isWarpWslSession}from"./chunk-UUMKAA7S.js";import{getAgentDir,stripBom}from"./chunk-G3ZEPNGM.js";import{existsSync,readFileSync}from"fs";import{join}from"path";function useWindowsKeybindings(platform=process.platform,env=process.env){return platform==="win32"||platform==="linux"&&!!(env.WSL_DISTRO_NAME||env.WSL_INTEROP)}var windowsKeybindings=useWindowsKeybindings(),QUESTION_ANSWER_PRIMARY_KEY="alt+up",QUESTION_ANSWER_FALLBACK_KEY="alt+a",KEYBINDINGS={...TUI_KEYBINDINGS,"tui.editor.undo":{...TUI_KEYBINDINGS["tui.editor.undo"],defaultKeys:process.platform==="win32"?"ctrl+z":windowsKeybindings?"alt+z":"ctrl+-"},"tui.altScreen.previousPrompt":{...TUI_KEYBINDINGS["tui.altScreen.previousPrompt"],defaultKeys:windowsKeybindings?"ctrl+up":["ctrl+shift+up","ctrl+up"]},"tui.altScreen.nextPrompt":{...TUI_KEYBINDINGS["tui.altScreen.nextPrompt"],defaultKeys:windowsKeybindings?"ctrl+down":["ctrl+shift+down","ctrl+down"]},"tui.altScreen.search":{...TUI_KEYBINDINGS["tui.altScreen.search"],defaultKeys:windowsKeybindings?"ctrl+f":"ctrl+shift+f"},"app.interrupt":{defaultKeys:"escape",description:"Cancel or abort"},"app.clear":{defaultKeys:"ctrl+c",description:"Clear editor"},"app.exit":{defaultKeys:"ctrl+d",description:"Exit when editor is empty"},"app.suspend":{defaultKeys:process.platform==="win32"?[]:"ctrl+z",description:"Suspend to background"},"app.thinking.cycle":{defaultKeys:"shift+tab",description:"Cycle thinking level"},"app.thinking.save":{defaultKeys:"ctrl+s",description:"Save thinking level"},"app.model.cycleForward":{defaultKeys:"ctrl+p",description:"Cycle to next model"},"app.model.cycleBackward":{defaultKeys:windowsKeybindings?"alt+p":"shift+ctrl+p",description:"Cycle to previous model"},"app.model.select":{defaultKeys:"ctrl+l",description:"Open model selector"},"app.history.search":{defaultKeys:"ctrl+r",description:"Search prompt history across sessions"},"app.tools.expand":{defaultKeys:"ctrl+o",description:"Toggle tool output"},"app.thinking.toggle":{defaultKeys:"ctrl+t",description:"Toggle thinking blocks"},"app.session.toggleNamedFilter":{defaultKeys:"ctrl+n",description:"Toggle named session filter"},"app.editor.external":{defaultKeys:"ctrl+g",description:"Open external editor"},"app.message.copy":{defaultKeys:"ctrl+x",description:"Copy selection or last assistant message"},"app.message.followUp":{defaultKeys:windowsKeybindings?"ctrl+q":"alt+enter",description:"Queue follow-up message"},"app.message.dequeue":{defaultKeys:windowsKeybindings?"alt+q":"alt+up",description:"Restore queued messages"},"app.question.answer":{defaultKeys:[QUESTION_ANSWER_PRIMARY_KEY,QUESTION_ANSWER_FALLBACK_KEY],description:"Open the pending question"},"app.question.next":{defaultKeys:"alt+down",description:"Show the next pending question"},"app.clipboard.pasteImage":{defaultKeys:isWarpWslSession()?["ctrl+v","alt+v"]:windowsKeybindings?"alt+v":"ctrl+v",description:"Paste files on macOS, images, or text from clipboard"},"app.session.new":{defaultKeys:[],description:"Start a new session"},"app.session.tree":{defaultKeys:[],description:"Open session tree"},"app.session.fork":{defaultKeys:[],description:"Fork current session"},"app.session.resume":{defaultKeys:[],description:"Resume a session"},"app.session.renameCurrent":{defaultKeys:[],description:"Rename the current session"},"app.tree.foldOrUp":{defaultKeys:process.platform==="darwin"?["alt+left","ctrl+left"]:["ctrl+left","alt+left"],description:"Fold tree branch or move up"},"app.tree.unfoldOrDown":{defaultKeys:process.platform==="darwin"?["alt+right","ctrl+right"]:["ctrl+right","alt+right"],description:"Unfold tree branch or move down"},"app.tree.editLabel":{defaultKeys:"shift+l",description:"Edit tree label"},"app.tree.editMessage":{defaultKeys:"ctrl+e",description:"Edit the selected assistant response, or reopen a user message in the editor"},"app.tree.toggleLabelTimestamp":{defaultKeys:"shift+t",description:"Toggle tree label timestamps"},"app.session.togglePath":{defaultKeys:"ctrl+p",description:"Toggle session path display"},"app.session.toggleSort":{defaultKeys:"ctrl+s",description:"Toggle session sort mode"},"app.session.rename":{defaultKeys:"ctrl+r",description:"Rename session"},"app.session.delete":{defaultKeys:"ctrl+d",description:"Delete session"},"app.session.deleteNoninvasive":{defaultKeys:"ctrl+backspace",description:"Delete session when query is empty"},"app.models.save":{defaultKeys:"ctrl+s",description:"Save model selection"},"app.models.toggleFavorite":{defaultKeys:"ctrl+f",description:"Toggle favorite model"},"app.models.enableAll":{defaultKeys:"ctrl+a",description:"Enable all models"},"app.models.clearAll":{defaultKeys:"ctrl+x",description:"Clear all models"},"app.models.toggleProvider":{defaultKeys:"ctrl+p",description:"Toggle all models for provider"},"app.models.reorderUp":{defaultKeys:"alt+up",description:"Move model up in order"},"app.models.reorderDown":{defaultKeys:"alt+down",description:"Move model down in order"},"app.tree.filter.default":{defaultKeys:"ctrl+d",description:"Tree filter: default view"},"app.tree.filter.noTools":{defaultKeys:"ctrl+t",description:"Tree filter: hide tool results"},"app.tree.filter.userOnly":{defaultKeys:"ctrl+u",description:"Tree filter: user messages only"},"app.tree.filter.labeledOnly":{defaultKeys:"ctrl+l",description:"Tree filter: labeled entries only"},"app.tree.filter.all":{defaultKeys:"ctrl+a",description:"Tree filter: show all entries"},"app.tree.filter.cycleForward":{defaultKeys:"ctrl+o",description:"Tree filter: cycle forward"},"app.tree.filter.cycleBackward":{defaultKeys:"shift+ctrl+o",description:"Tree filter: cycle backward"}},KEYBINDING_NAME_MIGRATIONS={cursorUp:"tui.editor.cursorUp",cursorDown:"tui.editor.cursorDown",cursorLeft:"tui.editor.cursorLeft",cursorRight:"tui.editor.cursorRight",cursorWordLeft:"tui.editor.cursorWordLeft",cursorWordRight:"tui.editor.cursorWordRight",cursorLineStart:"tui.editor.cursorLineStart",cursorLineEnd:"tui.editor.cursorLineEnd",jumpForward:"tui.editor.jumpForward",jumpBackward:"tui.editor.jumpBackward",pageUp:"tui.editor.pageUp",pageDown:"tui.editor.pageDown",deleteCharBackward:"tui.editor.deleteCharBackward",deleteCharForward:"tui.editor.deleteCharForward",deleteWordBackward:"tui.editor.deleteWordBackward",deleteWordForward:"tui.editor.deleteWordForward",deleteToLineStart:"tui.editor.deleteToLineStart",deleteToLineEnd:"tui.editor.deleteToLineEnd",yank:"tui.editor.yank",yankPop:"tui.editor.yankPop",undo:"tui.editor.undo",newLine:"tui.input.newLine",submit:"tui.input.submit",tab:"tui.input.tab",copy:"tui.input.copy",selectUp:"tui.select.up",selectDown:"tui.select.down",selectPageUp:"tui.select.pageUp",selectPageDown:"tui.select.pageDown",selectConfirm:"tui.select.confirm",selectCancel:"tui.select.cancel",interrupt:"app.interrupt",clear:"app.clear",exit:"app.exit",suspend:"app.suspend",cycleThinkingLevel:"app.thinking.cycle",cycleModelForward:"app.model.cycleForward",cycleModelBackward:"app.model.cycleBackward",selectModel:"app.model.select",expandTools:"app.tools.expand",toggleThinking:"app.thinking.toggle",toggleSessionNamedFilter:"app.session.toggleNamedFilter",externalEditor:"app.editor.external",followUp:"app.message.followUp",dequeue:"app.message.dequeue",pasteImage:"app.clipboard.pasteImage",newSession:"app.session.new",tree:"app.session.tree",fork:"app.session.fork",resume:"app.session.resume",treeFoldOrUp:"app.tree.foldOrUp",treeUnfoldOrDown:"app.tree.unfoldOrDown",treeEditLabel:"app.tree.editLabel",treeEditMessage:"app.tree.editMessage",treeToggleLabelTimestamp:"app.tree.toggleLabelTimestamp",toggleSessionPath:"app.session.togglePath",toggleSessionSort:"app.session.toggleSort",renameSession:"app.session.rename",deleteSession:"app.session.delete",deleteSessionNoninvasive:"app.session.deleteNoninvasive"};function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function hasOwn(value,key){return Object.hasOwn(value,key)}function isLegacyKeybindingName(key){return key in KEYBINDING_NAME_MIGRATIONS}function toKeybindingsConfig(value){let config={};for(let[key,binding]of Object.entries(value)){if(typeof binding=="string"){config[key]=binding;continue}Array.isArray(binding)&&binding.every(entry=>typeof entry=="string")&&(config[key]=binding)}return config}function migrateKeybindingsConfig(rawConfig){let config={},migrated=!1;for(let[key,value]of Object.entries(rawConfig)){let nextKey=isLegacyKeybindingName(key)?KEYBINDING_NAME_MIGRATIONS[key]:key;if(nextKey!==key&&(migrated=!0),key!==nextKey&&hasOwn(rawConfig,nextKey)){migrated=!0;continue}config[nextKey]=value}return{config:orderKeybindingsConfig(config),migrated}}function orderKeybindingsConfig(config){let ordered={};for(let keybinding of Object.keys(KEYBINDINGS))hasOwn(config,keybinding)&&(ordered[keybinding]=config[keybinding]);let extras=Object.keys(config).filter(key=>!hasOwn(ordered,key)).sort();for(let key of extras)ordered[key]=config[key];return ordered}function loadRawConfig(path){if(existsSync(path))try{let parsed=JSON.parse(stripBom(readFileSync(path,"utf-8")));return isRecord(parsed)?parsed:void 0}catch{return}}var KeybindingsManager2=class _KeybindingsManager extends KeybindingsManager{constructor(userBindings={},configPath){super(KEYBINDINGS,userBindings),this.configPath=configPath}static create(agentDir=getAgentDir()){let configPath=join(agentDir,"keybindings.json"),userBindings=_KeybindingsManager.loadFromFile(configPath);return new _KeybindingsManager(userBindings,configPath)}reload(){this.configPath&&this.setUserBindings(_KeybindingsManager.loadFromFile(this.configPath))}getEffectiveConfig(){return this.getResolvedBindings()}static loadFromFile(path){let rawConfig=loadRawConfig(path);return rawConfig?toKeybindingsConfig(migrateKeybindingsConfig(rawConfig).config):{}}};export{QUESTION_ANSWER_PRIMARY_KEY,QUESTION_ANSWER_FALLBACK_KEY,KEYBINDINGS,migrateKeybindingsConfig,KeybindingsManager2 as KeybindingsManager};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
-
import{getProviderEnvValue}from"./chunk-5ROMKDLK.js";var PROMPT_CACHE_TTL_SHORT_SECONDS=300,PROMPT_CACHE_TTL_LONG_SECONDS=3600,PROMPT_CACHE_TTL_OPENAI_EXTENDED_SECONDS=1800,NO_PROMPT_CACHE={kind:"none"},BEST_EFFORT_PROMPT_CACHE={kind:"best-effort"};function ttl(ttlSeconds){return{kind:"ttl",ttlSeconds}}function hostnameOf(baseUrl){try{return new URL(baseUrl).hostname.toLowerCase()}catch{return}}function isAnthropicApiBaseUrl(baseUrl){try{return new URL(baseUrl).hostname==="api.anthropic.com"}catch{return!1}}var FORCED_TOOL_CHOICE_REJECTING_MODEL_ID=/^claude-(?:(?:fable|mythos)(?:-|$)|(?:opus|sonnet)-5[.-]5(?:[.-]|$))/i;function defaultSupportsToolReferences(model){if(model.provider!=="anthropic"||model.id.includes("haiku"))return!1;let version=model.id.match(/^claude-(?:opus|sonnet|fable)-(\d+)(?:-(\d+))?(?:-|$)/);if(!version)return!1;let major=Number(version[1]),minor=version[2]&&version[2].length<8?Number(version[2]):0;return major>4||major===4&&minor>=5}function getAnthropicCompat(model){let isFireworks=model.provider==="fireworks",isCloudflareAiGatewayAnthropic=model.provider==="cloudflare-ai-gateway"&&model.baseUrl.includes("anthropic"),isXiaomi=model.provider==="xiaomi"||model.provider.startsWith("xiaomi-token-plan-"),isOpenRouter=model.provider==="openrouter"||model.baseUrl.includes("openrouter.ai");return{supportsEagerToolInputStreaming:model.compat?.supportsEagerToolInputStreaming??!isFireworks,supportsLongCacheRetention:model.compat?.supportsLongCacheRetention??!isFireworks,sendSessionAffinityHeaders:model.compat?.sendSessionAffinityHeaders??!!(isFireworks||isCloudflareAiGatewayAnthropic||isOpenRouter),sessionAffinityFormat:model.compat?.sessionAffinityFormat??(isOpenRouter?"openrouter":void 0),supportsCacheControlOnTools:model.compat?.supportsCacheControlOnTools??!isFireworks,supportsDisabledThinking:model.compat?.supportsDisabledThinking??!isXiaomi,supportsTemperature:model.compat?.supportsTemperature??!0,supportsToolChoice:model.compat?.supportsToolChoice??!0,supportsForcedToolChoice:model.compat?.supportsForcedToolChoice??!FORCED_TOOL_CHOICE_REJECTING_MODEL_ID.test(model.id),allowEmptySignature:model.compat?.allowEmptySignature??!1,unsignedThinkingReplay:model.compat?.unsignedThinkingReplay??(model.compat?.allowEmptySignature?"empty-signature":"text"),allowedFallbackModels:model.compat?.allowedFallbackModels??[],supportsStrictTools:model.compat?.supportsStrictTools??!1,supportsMidConvoSystemMessages:model.compat?.supportsMidConvoSystemMessages??!1,supportsMidConvoToolChanges:model.compat?.supportsMidConvoToolChanges??!1,supportsToolReferences:model.compat?.supportsToolReferences??defaultSupportsToolReferences(model),supportsWebSearch:model.compat?.supportsWebSearch??isAnthropicApiBaseUrl(model.baseUrl)}}function detectOpenAICompletionsCompat(model){let provider=model.provider,baseUrl=model.baseUrl,isZai=provider==="zai"||provider==="zai-coding-cn"||baseUrl.includes("api.z.ai")||baseUrl.includes("open.bigmodel.cn"),isTogether=provider==="together"||baseUrl.includes("api.together.ai")||baseUrl.includes("api.together.xyz"),isMoonshot=provider==="moonshotai"||provider==="moonshotai-cn"||baseUrl.includes("api.moonshot."),isOpenRouter=provider==="openrouter"||baseUrl.includes("openrouter.ai"),isCloudflareWorkersAI=provider==="cloudflare-workers-ai"||baseUrl.includes("api.cloudflare.com"),isCloudflareAiGateway=provider==="cloudflare-ai-gateway"||baseUrl.includes("gateway.ai.cloudflare.com"),isNvidia=provider==="nvidia"||baseUrl.includes("integrate.api.nvidia.com"),isAntLing=provider==="ant-ling"||baseUrl.includes("api.ant-ling.com"),isCerebras=provider==="cerebras"||baseUrl.includes("cerebras.ai"),isDeepSeek=provider==="deepseek"||baseUrl.toLowerCase().includes("deepseek.com"),isNonStandard=isNvidia||isCerebras||provider==="xai"||baseUrl.includes("api.x.ai")||isTogether||baseUrl.includes("chutes.ai")||isDeepSeek||isZai||isMoonshot||provider==="opencode"||baseUrl.includes("opencode.ai")||isCloudflareWorkersAI||isCloudflareAiGateway||isAntLing,useMaxTokens=baseUrl.includes("chutes.ai")||isDeepSeek||isMoonshot||isCloudflareAiGateway||isTogether||isNvidia||isAntLing||isZai,isGrok=provider==="xai"||baseUrl.includes("api.x.ai"),isOpenRouterDeveloperRoleModel=isOpenRouter&&(model.id.startsWith("anthropic/")||model.id.startsWith("openai/")),openRouterCacheControlPrefixes=["anthropic/","qwen/","google/"],cacheControlModelId=model.id.startsWith("~")?model.id.slice(1):model.id,supportsOpenRouterCacheControl=openRouterCacheControlPrefixes.some(prefix=>cacheControlModelId.startsWith(prefix));return{supportsStore:!isNonStandard,supportsDeveloperRole:isOpenRouterDeveloperRoleModel||!isNonStandard&&!isOpenRouter,supportsReasoningEffort:!isGrok&&!isZai&&!isMoonshot&&!isTogether&&!isCloudflareAiGateway&&!isNvidia&&!isAntLing,supportsUsageInStreaming:!0,supportsFinishReason:!0,maxTokensField:useMaxTokens?"max_tokens":"max_completion_tokens",requiresToolResultName:!1,requiresAssistantAfterToolResult:!1,requiresThinkingAsText:!1,requiresReasoningContentOnAssistantMessages:isDeepSeek,thinkingFormat:isDeepSeek?"deepseek":isZai?"zai":isTogether?"together":isAntLing?"ant-ling":isOpenRouter?"openrouter":"openai",openRouterRouting:{},vercelGatewayRouting:{},chatTemplateKwargs:{},zaiToolStream:!1,supportsStrictMode:!1,toolSchemaFlavor:isMoonshot?"moonshot-mfjs":void 0,supportsDisabledThinking:!0,toolCallFormat:void 0,supportsOpenAIGrammarTools:!1,supportsMidConvoSystemMessages:!1,supportsMidConvoToolAdditions:!1,cacheControlFormat:provider==="openrouter"&&supportsOpenRouterCacheControl?"anthropic":void 0,sendSessionAffinityHeaders:isOpenRouter,deferredToolsMode:void 0,sessionAffinityFormat:isOpenRouter?"openrouter":"openai",supportsPromptCacheKey:isMoonshot||baseUrl.includes("api.openai.com"),supportsMaxOutputTokens:!0,supportsLongCacheRetention:!(isTogether||isCloudflareWorkersAI||isCloudflareAiGateway||isNvidia||isAntLing)}}function getOpenAICompletionsCompat(model){let detected=detectOpenAICompletionsCompat(model);return model.compat?{supportsWebSearch:model.compat.supportsWebSearch,supportsStore:model.compat.supportsStore??detected.supportsStore,supportsDeveloperRole:model.compat.supportsDeveloperRole??detected.supportsDeveloperRole,supportsReasoningEffort:model.compat.supportsReasoningEffort??detected.supportsReasoningEffort,supportsUsageInStreaming:model.compat.supportsUsageInStreaming??detected.supportsUsageInStreaming,supportsFinishReason:model.compat.supportsFinishReason??detected.supportsFinishReason,maxTokensField:model.compat.maxTokensField??detected.maxTokensField,requiresToolResultName:model.compat.requiresToolResultName??detected.requiresToolResultName,requiresAssistantAfterToolResult:model.compat.requiresAssistantAfterToolResult??detected.requiresAssistantAfterToolResult,requiresThinkingAsText:model.compat.requiresThinkingAsText??detected.requiresThinkingAsText,requiresReasoningContentOnAssistantMessages:model.compat.requiresReasoningContentOnAssistantMessages??detected.requiresReasoningContentOnAssistantMessages,thinkingFormat:model.compat.thinkingFormat??detected.thinkingFormat,supportsDisabledThinking:model.compat.supportsDisabledThinking??detected.supportsDisabledThinking,openRouterRouting:model.compat.openRouterRouting??detected.openRouterRouting,vercelGatewayRouting:model.compat.vercelGatewayRouting??detected.vercelGatewayRouting,chatTemplateKwargs:model.compat.chatTemplateKwargs??detected.chatTemplateKwargs,chatTemplateArgs:model.compat.chatTemplateArgs??detected.chatTemplateArgs,zaiToolStream:model.compat.zaiToolStream??detected.zaiToolStream,supportsThinkingTokenBudget:model.compat.supportsThinkingTokenBudget??detected.supportsThinkingTokenBudget,thinkingTokenBudgetField:model.compat.thinkingTokenBudgetField??detected.thinkingTokenBudgetField,supportsStrictMode:model.compat.supportsStrictMode??detected.supportsStrictMode,toolSchemaFlavor:model.compat.toolSchemaFlavor??detected.toolSchemaFlavor,toolCallFormat:model.compat.toolCallFormat??detected.toolCallFormat,supportsOpenAIGrammarTools:model.compat.supportsOpenAIGrammarTools??detected.supportsOpenAIGrammarTools,supportsMidConvoSystemMessages:model.compat.supportsMidConvoSystemMessages??detected.supportsMidConvoSystemMessages,supportsMidConvoToolAdditions:model.compat.supportsMidConvoToolAdditions??detected.supportsMidConvoToolAdditions,cacheControlFormat:model.compat.cacheControlFormat??detected.cacheControlFormat,sendSessionAffinityHeaders:model.compat.sendSessionAffinityHeaders??detected.sendSessionAffinityHeaders,deferredToolsMode:model.compat.deferredToolsMode??detected.deferredToolsMode,sessionAffinityFormat:model.compat.sessionAffinityFormat??detected.sessionAffinityFormat,supportsPromptCacheKey:model.compat.supportsPromptCacheKey??detected.supportsPromptCacheKey,supportsMaxOutputTokens:model.compat.supportsMaxOutputTokens??detected.supportsMaxOutputTokens,supportsForcedToolChoice:model.compat.supportsForcedToolChoice,vllmPriority:model.compat.vllmPriority??detected.vllmPriority,supportsLongCacheRetention:model.compat.supportsLongCacheRetention??detected.supportsLongCacheRetention}:detected}function getBedrockModelMatchCandidates(modelId,modelName){return(modelName?[modelId,modelName]:[modelId]).flatMap(value=>{let lower=value.toLowerCase();return[lower,lower.replace(/[\s_.:]+/g,"-")]})}function supportsOneHourCacheTtl(model){return getBedrockModelMatchCandidates(model.id,model.name).some(candidate=>["opus-4-5","sonnet-4-5","haiku-4-5"].some(modelVersion=>candidate.includes(modelVersion)))}function supportsPromptCaching(model,env){let candidates=getBedrockModelMatchCandidates(model.id,model.name);return candidates.some(s=>s.includes("claude"))?!!(candidates.some(s=>s.includes("fable-5")||s.includes("opus-5")||s.includes("sonnet-5"))||candidates.some(s=>s.includes("-4-"))||candidates.some(s=>s.includes("claude-3-7-sonnet"))||candidates.some(s=>s.includes("claude-3-5-haiku"))):getProviderEnvValue("AWS_BEDROCK_FORCE_CACHE",env)==="1"}function resolveAnthropicCacheRetention(cacheRetention,env,fallback="short"){return cacheRetention||(getProviderEnvValue("PI_CACHE_RETENTION",env)==="long"?"long":typeof process<"u"&&process.env.PI_CACHE_RETENTION!==void 0?"short":fallback)}function resolveOpenAICompletionsCacheRetention(cacheRetention,env){return cacheRetention||(getProviderEnvValue("PI_CACHE_RETENTION",env)==="long"?"long":"short")}function resolveBedrockCacheRetention(cacheRetention,env){return cacheRetention||(getProviderEnvValue("PI_CACHE_RETENTION",env)==="long"?"long":"short")}function resolveOpenAIResponsesCacheRetention(cacheRetention,env){return cacheRetention||(getProviderEnvValue("PI_CACHE_RETENTION",env)==="long"?"long":"short")}function isDirectDeepSeekModel(model){return model.provider==="deepseek"||hostnameOf(model.baseUrl)==="api.deepseek.com"}var OPENAI_EXTENDED_CACHE_MODEL_ID=/^gpt-(?:5\.(?:[6-9]|\d{2,})|(?:[6-9]|\d{2,})(?:\.\d+)?)(?:-|$)/i;function hasOpenAIExtendedPromptCache(model){if(model.api==="openai-responses"){let responsesModel=model;if(responsesModel.compat?.supportsExplicitPromptCacheMode===!0)return!0;if(responsesModel.provider!=="openai"&&hostnameOf(responsesModel.baseUrl)!=="api.openai.com")return!1}return OPENAI_EXTENDED_CACHE_MODEL_ID.test(model.id)}var CLAUDE_CODE_API_BILLING_ENV=["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","CLAUDE_CODE_USE_BEDROCK","CLAUDE_CODE_USE_VERTEX","CLAUDE_CODE_USE_FOUNDRY"];function isEnabledFlag(value){return value!==void 0&&!/^(?:|0|false|no|off)$/i.test(value.trim())}function claudeCodePromptCacheTtlSeconds(env){let explicit=getProviderEnvValue("CLAUDE_CODE_PROMPT_CACHE_TTL",env)?.trim().toLowerCase();return explicit==="5m"?PROMPT_CACHE_TTL_SHORT_SECONDS:explicit==="1h"?PROMPT_CACHE_TTL_LONG_SECONDS:isEnabledFlag(getProviderEnvValue("FORCE_PROMPT_CACHING_5M",env))?PROMPT_CACHE_TTL_SHORT_SECONDS:isEnabledFlag(getProviderEnvValue("ENABLE_PROMPT_CACHING_1H",env))?PROMPT_CACHE_TTL_LONG_SECONDS:CLAUDE_CODE_API_BILLING_ENV.some(name=>getProviderEnvValue(name,env)!==void 0)?PROMPT_CACHE_TTL_SHORT_SECONDS:PROMPT_CACHE_TTL_LONG_SECONDS}function resolvePromptCacheLifetime(model,env){switch(model.api){case"claude-sdk-oauth":return ttl(claudeCodePromptCacheTtlSeconds(env));case"anthropic-messages":{let anthropicModel=model,retention=resolveAnthropicCacheRetention(anthropicModel.cacheRetention,env,"short");return retention==="none"?NO_PROMPT_CACHE:retention==="long"&&isAnthropicApiBaseUrl(anthropicModel.baseUrl)&&getAnthropicCompat(anthropicModel).supportsLongCacheRetention?ttl(PROMPT_CACHE_TTL_LONG_SECONDS):ttl(PROMPT_CACHE_TTL_SHORT_SECONDS)}case"bedrock-converse-stream":{let bedrockModel=model,retention=resolveBedrockCacheRetention(bedrockModel.cacheRetention,env);return retention==="none"||!supportsPromptCaching(bedrockModel,env)?NO_PROMPT_CACHE:retention==="long"&&supportsOneHourCacheTtl(bedrockModel)?ttl(PROMPT_CACHE_TTL_LONG_SECONDS):ttl(PROMPT_CACHE_TTL_SHORT_SECONDS)}case"openai-completions":{let completionsModel=model,retention=resolveOpenAICompletionsCacheRetention(completionsModel.cacheRetention,env);if(retention==="none")return NO_PROMPT_CACHE;if(isDirectDeepSeekModel(completionsModel))return BEST_EFFORT_PROMPT_CACHE;let compat=getOpenAICompletionsCompat(completionsModel);return compat.cacheControlFormat==="anthropic"&&retention==="long"&&compat.supportsLongCacheRetention?ttl(PROMPT_CACHE_TTL_LONG_SECONDS):ttl(PROMPT_CACHE_TTL_SHORT_SECONDS)}case"openai-responses":case"openai-codex-responses":case"azure-openai-responses":return resolveOpenAIResponsesCacheRetention(model.cacheRetention,env)==="none"?NO_PROMPT_CACHE:hasOpenAIExtendedPromptCache(model)?ttl(PROMPT_CACHE_TTL_OPENAI_EXTENDED_SECONDS):ttl(PROMPT_CACHE_TTL_SHORT_SECONDS);default:return NO_PROMPT_CACHE}}function resolvePromptCacheTtlSeconds(model,env){let lifetime=resolvePromptCacheLifetime(model,env);return lifetime.kind==="ttl"?lifetime.ttlSeconds:void 0}export{PROMPT_CACHE_TTL_SHORT_SECONDS,PROMPT_CACHE_TTL_LONG_SECONDS,PROMPT_CACHE_TTL_OPENAI_EXTENDED_SECONDS,isAnthropicApiBaseUrl,getAnthropicCompat,getOpenAICompletionsCompat,resolvePromptCacheLifetime,resolvePromptCacheTtlSeconds};
|