@psnext/slingcli 2.5.20260722-2 → 2.5.20260722-3
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/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +9 -7
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +25 -23
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js +32 -19
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.js +6 -7
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +75 -26
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/utils.js +6 -17
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/jsonl-storage.js +56 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/memory-storage.js +56 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo-utils.js +2 -2
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.js +30 -14
- package/node_modules/@earendil-works/pi-agent-core/dist/index.js +4 -2
- package/node_modules/@earendil-works/pi-agent-core/dist/stream-fn.js +17 -0
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +2 -7
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +14 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/pi-messages.js +2 -4
- package/node_modules/@earendil-works/pi-ai/dist/auth/helpers.js +3 -2
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js +249 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.js +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +60 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.js +8 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js +3 -2
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cerebras.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/groq.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/kimi-coding.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/moonshotai-cn.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/moonshotai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan-cn.json +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan.json +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/xai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.js +10 -2
- package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan-cn.js +15 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan-cn.models.js +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan.js +15 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/qwen-token-plan.models.js +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/radius-config.js +18 -14
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +79 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/text.js +10 -0
- package/node_modules/@earendil-works/{pi-agent-core/dist/harness/session → pi-ai/dist/utils}/uuid.js +4 -8
- package/node_modules/@earendil-works/pi-ai/package.json +8 -5
- package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.js +2 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js +72 -57
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/branch-summarization.js +8 -11
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js +63 -26
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/utils.js +6 -17
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.js +5 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js +2 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-runtime.js +18 -15
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/project-trust.js +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/remote-catalog-provider.js +26 -7
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.js +6 -2
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.js +100 -24
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/usage-totals.js +52 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/extensions/llama/client.js +3 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/extensions/llama/index.js +3 -3
- package/node_modules/@earendil-works/pi-coding-agent/dist/index.js +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/main.js +5 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/footer.js +20 -21
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js +69 -25
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.js +7 -0
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js +4 -0
- package/node_modules/@earendil-works/pi-coding-agent/npm-shrinkwrap.json +16 -31
- package/node_modules/@earendil-works/pi-coding-agent/package.json +4 -4
- package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/cli.js +5 -5
- package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/config.js +9 -9
- package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/ipc/client.js +1 -1
- package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/ipc/server.js +1 -1
- package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/radius.js +8 -8
- package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/rpc-process.js +1 -1
- package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/serve.js +3 -3
- package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/storage.js +7 -7
- package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/supervisor.js +2 -2
- package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/package.json +9 -6
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +16 -10
- package/node_modules/@earendil-works/pi-tui/dist/tui.js +4 -2
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
- package/slingshot/index.js +253 -250
- /package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/handler.js +0 -0
- /package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/index.js +0 -0
- /package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/ipc/protocol.js +0 -0
- /package/node_modules/@earendil-works/{pi-orchestrator → pi-server}/dist/types.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { uuidv7 } from "@earendil-works/pi-ai";
|
|
1
2
|
import { SessionError, toError } from "../types.js";
|
|
2
3
|
import { getFileSystemResultOrThrow } from "./repo-utils.js";
|
|
3
|
-
import { uuidv7 } from "./uuid.js";
|
|
4
4
|
function updateLabelCache(labelsById, entry) {
|
|
5
5
|
if (entry.type !== "label")
|
|
6
6
|
return;
|
|
@@ -216,15 +216,65 @@ export class JsonlSessionStorage {
|
|
|
216
216
|
async getLabel(id) {
|
|
217
217
|
return this.labelsById.get(id);
|
|
218
218
|
}
|
|
219
|
-
async
|
|
219
|
+
async getSessionName() {
|
|
220
|
+
const entries = await this.findEntries("session_info");
|
|
221
|
+
return entries[entries.length - 1]?.name?.trim() || undefined;
|
|
222
|
+
}
|
|
223
|
+
async getSessionStats() {
|
|
224
|
+
let messageCount = 0;
|
|
225
|
+
let cachedTokens = 0;
|
|
226
|
+
let uncachedTokens = 0;
|
|
227
|
+
let totalTokens = 0;
|
|
228
|
+
let costTotal = 0;
|
|
229
|
+
for (const entry of this.entries) {
|
|
230
|
+
if (entry.type === "message") {
|
|
231
|
+
messageCount += 1;
|
|
232
|
+
}
|
|
233
|
+
const usage = entry.type === "message"
|
|
234
|
+
? entry.message.role === "assistant"
|
|
235
|
+
? entry.message.usage
|
|
236
|
+
: undefined
|
|
237
|
+
: entry.type === "compaction" || entry.type === "branch_summary"
|
|
238
|
+
? entry.usage
|
|
239
|
+
: undefined;
|
|
240
|
+
if (!usage ||
|
|
241
|
+
typeof usage.input !== "number" ||
|
|
242
|
+
typeof usage.output !== "number" ||
|
|
243
|
+
typeof usage.cacheRead !== "number" ||
|
|
244
|
+
typeof usage.cacheWrite !== "number" ||
|
|
245
|
+
typeof usage.cost?.total !== "number") {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
cachedTokens += usage.cacheRead;
|
|
249
|
+
uncachedTokens += usage.input + usage.cacheWrite;
|
|
250
|
+
totalTokens += usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
251
|
+
costTotal += usage.cost.total;
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
messageCount,
|
|
255
|
+
cachedTokens,
|
|
256
|
+
uncachedTokens,
|
|
257
|
+
totalTokens,
|
|
258
|
+
costTotal,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
async getPathToRootOrCompaction(leafId) {
|
|
220
262
|
if (leafId === null)
|
|
221
263
|
return [];
|
|
222
264
|
const path = [];
|
|
265
|
+
let stopAtEntryId = null;
|
|
223
266
|
let current = this.byId.get(leafId);
|
|
224
267
|
if (!current)
|
|
225
268
|
throw new SessionError("not_found", `Entry ${leafId} not found`);
|
|
226
269
|
while (current) {
|
|
227
270
|
path.unshift(current);
|
|
271
|
+
if (stopAtEntryId !== null && current.id === stopAtEntryId)
|
|
272
|
+
break;
|
|
273
|
+
if (current.type === "compaction") {
|
|
274
|
+
if (current.retainedTail)
|
|
275
|
+
break;
|
|
276
|
+
stopAtEntryId = current.firstKeptEntryId ?? null;
|
|
277
|
+
}
|
|
228
278
|
if (!current.parentId)
|
|
229
279
|
break;
|
|
230
280
|
const parent = this.byId.get(current.parentId);
|
|
@@ -234,8 +284,10 @@ export class JsonlSessionStorage {
|
|
|
234
284
|
}
|
|
235
285
|
return path;
|
|
236
286
|
}
|
|
237
|
-
async getEntries() {
|
|
238
|
-
|
|
287
|
+
async getEntries(options) {
|
|
288
|
+
const start = options?.afterEntrySeq ?? 0;
|
|
289
|
+
const end = options?.limit === undefined ? undefined : start + options.limit;
|
|
290
|
+
return this.entries.slice(start, end);
|
|
239
291
|
}
|
|
240
292
|
}
|
|
241
293
|
//# sourceMappingURL=jsonl-storage.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { uuidv7 } from "@earendil-works/pi-ai";
|
|
1
2
|
import { SessionError, } from "../types.js";
|
|
2
|
-
import { uuidv7 } from "./uuid.js";
|
|
3
3
|
function updateLabelCache(labelsById, entry) {
|
|
4
4
|
if (entry.type !== "label")
|
|
5
5
|
return;
|
|
@@ -91,15 +91,65 @@ export class InMemorySessionStorage {
|
|
|
91
91
|
async getLabel(id) {
|
|
92
92
|
return this.labelsById.get(id);
|
|
93
93
|
}
|
|
94
|
-
async
|
|
94
|
+
async getSessionName() {
|
|
95
|
+
const entries = await this.findEntries("session_info");
|
|
96
|
+
return entries[entries.length - 1]?.name?.trim() || undefined;
|
|
97
|
+
}
|
|
98
|
+
async getSessionStats() {
|
|
99
|
+
let messageCount = 0;
|
|
100
|
+
let cachedTokens = 0;
|
|
101
|
+
let uncachedTokens = 0;
|
|
102
|
+
let totalTokens = 0;
|
|
103
|
+
let costTotal = 0;
|
|
104
|
+
for (const entry of this.entries) {
|
|
105
|
+
if (entry.type === "message") {
|
|
106
|
+
messageCount += 1;
|
|
107
|
+
}
|
|
108
|
+
const usage = entry.type === "message"
|
|
109
|
+
? entry.message.role === "assistant"
|
|
110
|
+
? entry.message.usage
|
|
111
|
+
: undefined
|
|
112
|
+
: entry.type === "compaction" || entry.type === "branch_summary"
|
|
113
|
+
? entry.usage
|
|
114
|
+
: undefined;
|
|
115
|
+
if (!usage ||
|
|
116
|
+
typeof usage.input !== "number" ||
|
|
117
|
+
typeof usage.output !== "number" ||
|
|
118
|
+
typeof usage.cacheRead !== "number" ||
|
|
119
|
+
typeof usage.cacheWrite !== "number" ||
|
|
120
|
+
typeof usage.cost?.total !== "number") {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
cachedTokens += usage.cacheRead;
|
|
124
|
+
uncachedTokens += usage.input + usage.cacheWrite;
|
|
125
|
+
totalTokens += usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
126
|
+
costTotal += usage.cost.total;
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
messageCount,
|
|
130
|
+
cachedTokens,
|
|
131
|
+
uncachedTokens,
|
|
132
|
+
totalTokens,
|
|
133
|
+
costTotal,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
async getPathToRootOrCompaction(leafId) {
|
|
95
137
|
if (leafId === null)
|
|
96
138
|
return [];
|
|
97
139
|
const path = [];
|
|
140
|
+
let stopAtEntryId = null;
|
|
98
141
|
let current = this.byId.get(leafId);
|
|
99
142
|
if (!current)
|
|
100
143
|
throw new SessionError("not_found", `Entry ${leafId} not found`);
|
|
101
144
|
while (current) {
|
|
102
145
|
path.unshift(current);
|
|
146
|
+
if (stopAtEntryId !== null && current.id === stopAtEntryId)
|
|
147
|
+
break;
|
|
148
|
+
if (current.type === "compaction") {
|
|
149
|
+
if (current.retainedTail)
|
|
150
|
+
break;
|
|
151
|
+
stopAtEntryId = current.firstKeptEntryId ?? null;
|
|
152
|
+
}
|
|
103
153
|
if (!current.parentId)
|
|
104
154
|
break;
|
|
105
155
|
const parent = this.byId.get(current.parentId);
|
|
@@ -109,8 +159,10 @@ export class InMemorySessionStorage {
|
|
|
109
159
|
}
|
|
110
160
|
return path;
|
|
111
161
|
}
|
|
112
|
-
async getEntries() {
|
|
113
|
-
|
|
162
|
+
async getEntries(options) {
|
|
163
|
+
const start = options?.afterEntrySeq ?? 0;
|
|
164
|
+
const end = options?.limit === undefined ? undefined : start + options.limit;
|
|
165
|
+
return this.entries.slice(start, end);
|
|
114
166
|
}
|
|
115
167
|
}
|
|
116
168
|
//# sourceMappingURL=memory-storage.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { uuidv7 } from "@earendil-works/pi-ai";
|
|
1
2
|
import { SessionError, } from "../types.js";
|
|
2
3
|
import { Session } from "./session.js";
|
|
3
|
-
import { uuidv7 } from "./uuid.js";
|
|
4
4
|
export function createSessionId() {
|
|
5
5
|
return uuidv7();
|
|
6
6
|
}
|
|
@@ -34,6 +34,6 @@ export async function getEntriesToFork(storage, options) {
|
|
|
34
34
|
}
|
|
35
35
|
effectiveLeafId = target.parentId;
|
|
36
36
|
}
|
|
37
|
-
return storage.
|
|
37
|
+
return storage.getPathToRootOrCompaction(effectiveLeafId);
|
|
38
38
|
}
|
|
39
39
|
//# sourceMappingURL=repo-utils.js.map
|
|
@@ -32,13 +32,21 @@ export function defaultContextEntryTransform(pathEntries) {
|
|
|
32
32
|
}
|
|
33
33
|
const entries = [compaction];
|
|
34
34
|
const compactionIdx = pathEntries.findIndex((entry) => entry.type === "compaction" && entry.id === compaction.id);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
if (compaction.retainedTail) {
|
|
36
|
+
for (let i = compactionIdx + 1; i < pathEntries.length; i++) {
|
|
37
|
+
entries.push(pathEntries[i]);
|
|
38
|
+
}
|
|
39
|
+
return entries;
|
|
40
|
+
}
|
|
41
|
+
if (compaction.firstKeptEntryId) {
|
|
42
|
+
let foundFirstKept = false;
|
|
43
|
+
for (let i = 0; i < compactionIdx; i++) {
|
|
44
|
+
const entry = pathEntries[i];
|
|
45
|
+
if (entry.id === compaction.firstKeptEntryId)
|
|
46
|
+
foundFirstKept = true;
|
|
47
|
+
if (foundFirstKept)
|
|
48
|
+
entries.push(entry);
|
|
49
|
+
}
|
|
42
50
|
}
|
|
43
51
|
for (let i = compactionIdx + 1; i < pathEntries.length; i++) {
|
|
44
52
|
entries.push(pathEntries[i]);
|
|
@@ -62,7 +70,10 @@ export function sessionEntryToContextMessages(entry, index, entries, options = {
|
|
|
62
70
|
];
|
|
63
71
|
}
|
|
64
72
|
if (entry.type === "compaction") {
|
|
65
|
-
return [
|
|
73
|
+
return [
|
|
74
|
+
createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp),
|
|
75
|
+
...(entry.retainedTail ?? []),
|
|
76
|
+
];
|
|
66
77
|
}
|
|
67
78
|
if (entry.type === "branch_summary" && entry.summary) {
|
|
68
79
|
return [createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp)];
|
|
@@ -97,12 +108,12 @@ export class Session {
|
|
|
97
108
|
getEntry(id) {
|
|
98
109
|
return this.storage.getEntry(id);
|
|
99
110
|
}
|
|
100
|
-
getEntries() {
|
|
101
|
-
return this.storage.getEntries();
|
|
111
|
+
getEntries(options) {
|
|
112
|
+
return this.storage.getEntries(options);
|
|
102
113
|
}
|
|
103
114
|
async getBranch(fromId) {
|
|
104
115
|
const leafId = fromId ?? (await this.storage.getLeafId());
|
|
105
|
-
return this.storage.
|
|
116
|
+
return this.storage.getPathToRootOrCompaction(leafId);
|
|
106
117
|
}
|
|
107
118
|
async buildContextEntries(options = {}) {
|
|
108
119
|
return buildContextEntries(await this.getBranch(), this.mergeContextBuildOptions(options));
|
|
@@ -122,9 +133,11 @@ export class Session {
|
|
|
122
133
|
getLabel(id) {
|
|
123
134
|
return this.storage.getLabel(id);
|
|
124
135
|
}
|
|
136
|
+
getSessionStats() {
|
|
137
|
+
return this.storage.getSessionStats();
|
|
138
|
+
}
|
|
125
139
|
async getSessionName() {
|
|
126
|
-
|
|
127
|
-
return entries[entries.length - 1]?.name?.trim() || undefined;
|
|
140
|
+
return this.storage.getSessionName();
|
|
128
141
|
}
|
|
129
142
|
async appendTypedEntry(entry) {
|
|
130
143
|
await this.storage.appendEntry(entry);
|
|
@@ -167,7 +180,7 @@ export class Session {
|
|
|
167
180
|
activeToolNames: [...activeToolNames],
|
|
168
181
|
});
|
|
169
182
|
}
|
|
170
|
-
async appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook) {
|
|
183
|
+
async appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook, usage, retainedTail) {
|
|
171
184
|
return this.appendTypedEntry({
|
|
172
185
|
type: "compaction",
|
|
173
186
|
id: await this.storage.createEntryId(),
|
|
@@ -176,7 +189,9 @@ export class Session {
|
|
|
176
189
|
summary,
|
|
177
190
|
firstKeptEntryId,
|
|
178
191
|
tokensBefore,
|
|
192
|
+
retainedTail,
|
|
179
193
|
details,
|
|
194
|
+
usage,
|
|
180
195
|
fromHook,
|
|
181
196
|
});
|
|
182
197
|
}
|
|
@@ -240,6 +255,7 @@ export class Session {
|
|
|
240
255
|
fromId: entryId ?? "root",
|
|
241
256
|
summary: summary.summary,
|
|
242
257
|
details: summary.details,
|
|
258
|
+
usage: summary.usage,
|
|
243
259
|
fromHook: summary.fromHook,
|
|
244
260
|
});
|
|
245
261
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// Core Agent
|
|
2
|
+
export { uuidv7 } from "@earendil-works/pi-ai";
|
|
2
3
|
export * from "./agent.js";
|
|
3
4
|
// Loop functions
|
|
4
5
|
export * from "./agent-loop.js";
|
|
5
6
|
export * from "./harness/agent-harness.js";
|
|
6
7
|
export { collectEntriesForBranchSummary, generateBranchSummary, prepareBranchEntries, } from "./harness/compaction/branch-summarization.js";
|
|
7
|
-
export { calculateContextTokens, compact, DEFAULT_COMPACTION_SETTINGS, estimateContextTokens, estimateTokens, findCutPoint, findTurnStartIndex, generateSummary, getLastAssistantUsage, prepareCompaction, serializeConversation, shouldCompact, } from "./harness/compaction/compaction.js";
|
|
8
|
+
export { calculateContextTokens, compact, DEFAULT_COMPACTION_SETTINGS, estimateContextTokens, estimateTokens, findCutPoint, findTurnStartIndex, generateSummary, generateSummaryWithUsage, getLastAssistantUsage, prepareCompaction, serializeConversation, shouldCompact, } from "./harness/compaction/compaction.js";
|
|
8
9
|
export * from "./harness/messages.js";
|
|
9
10
|
export * from "./harness/prompt-templates.js";
|
|
10
11
|
export * from "./harness/session/jsonl-repo.js";
|
|
@@ -13,7 +14,6 @@ export * from "./harness/session/memory-repo.js";
|
|
|
13
14
|
export * from "./harness/session/memory-storage.js";
|
|
14
15
|
export * from "./harness/session/repo-utils.js";
|
|
15
16
|
export * from "./harness/session/session.js";
|
|
16
|
-
export { uuidv7 } from "./harness/session/uuid.js";
|
|
17
17
|
export * from "./harness/skills.js";
|
|
18
18
|
export * from "./harness/system-prompt.js";
|
|
19
19
|
// Harness
|
|
@@ -22,6 +22,8 @@ export * from "./harness/utils/shell-output.js";
|
|
|
22
22
|
export * from "./harness/utils/truncate.js";
|
|
23
23
|
// Proxy utilities
|
|
24
24
|
export * from "./proxy.js";
|
|
25
|
+
// Stream defaults
|
|
26
|
+
export { setDefaultStreamFn } from "./stream-fn.js";
|
|
25
27
|
// Types
|
|
26
28
|
export * from "./types.js";
|
|
27
29
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
let defaultStreamFn;
|
|
2
|
+
/**
|
|
3
|
+
* Configure the fallback used by Agent and low-level loops when callers omit streamFn.
|
|
4
|
+
*
|
|
5
|
+
* Hosts that provide a default model runtime can install its stream function here
|
|
6
|
+
* without making pi-agent-core depend on a provider catalog or compatibility layer.
|
|
7
|
+
*/
|
|
8
|
+
export function setDefaultStreamFn(streamFn) {
|
|
9
|
+
defaultStreamFn = streamFn;
|
|
10
|
+
}
|
|
11
|
+
export function getDefaultStreamFn() {
|
|
12
|
+
if (!defaultStreamFn) {
|
|
13
|
+
throw new Error("No default stream function configured. Pass streamFn explicitly or call setDefaultStreamFn().");
|
|
14
|
+
}
|
|
15
|
+
return defaultStreamFn;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=stream-fn.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@earendil-works/pi-agent-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.81.1",
|
|
4
4
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"test": "vitest --run",
|
|
27
27
|
"test:harness": "vitest --run --config vitest.harness.config.ts",
|
|
28
28
|
"coverage:harness": "vitest --run --config vitest.harness.config.ts --coverage",
|
|
29
|
-
"prepublishOnly": "npm run
|
|
29
|
+
"prepublishOnly": "npm run build"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@earendil-works/pi-ai": "^0.
|
|
32
|
+
"@earendil-works/pi-ai": "^0.81.1",
|
|
33
33
|
"ignore": "7.0.5",
|
|
34
34
|
"typebox": "1.1.38",
|
|
35
35
|
"yaml": "2.9.0"
|
|
@@ -15,6 +15,7 @@ import { formatProviderError, normalizeProviderError } from "../utils/error-body
|
|
|
15
15
|
import { AssistantMessageEventStream } from "../utils/event-stream.js";
|
|
16
16
|
import { headersToRecord } from "../utils/headers.js";
|
|
17
17
|
import { resolveHttpProxyUrlForTarget } from "../utils/node-http-proxy.js";
|
|
18
|
+
import { uuidv7 } from "../utils/uuid.js";
|
|
18
19
|
import { clampOpenAIPromptCacheKey } from "./openai-prompt-cache.js";
|
|
19
20
|
import { convertResponsesMessages, convertResponsesTools, processResponsesStream } from "./openai-responses-shared.js";
|
|
20
21
|
import { buildBaseOptions } from "./simple-options.js";
|
|
@@ -162,7 +163,7 @@ export const stream = (model, context, options) => {
|
|
|
162
163
|
body = nextBody;
|
|
163
164
|
}
|
|
164
165
|
const codexSessionId = clampOpenAIPromptCacheKey(options?.sessionId);
|
|
165
|
-
const websocketRequestId = codexSessionId ||
|
|
166
|
+
const websocketRequestId = codexSessionId || uuidv7();
|
|
166
167
|
const sseHeaders = buildSSEHeaders(model.headers, options?.headers, accountId, apiKey, codexSessionId);
|
|
167
168
|
const websocketHeaders = buildWebSocketHeaders(model.headers, options?.headers, accountId, apiKey, websocketRequestId);
|
|
168
169
|
const bodyJson = JSON.stringify(body);
|
|
@@ -1179,12 +1180,6 @@ function extractAccountId(token) {
|
|
|
1179
1180
|
throw new Error("Failed to extract accountId from token");
|
|
1180
1181
|
}
|
|
1181
1182
|
}
|
|
1182
|
-
function createCodexRequestId() {
|
|
1183
|
-
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
1184
|
-
return globalThis.crypto.randomUUID();
|
|
1185
|
-
}
|
|
1186
|
-
return `codex_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
|
|
1187
|
-
}
|
|
1188
1183
|
function buildBaseCodexHeaders(initHeaders, additionalHeaders, accountId, token) {
|
|
1189
1184
|
const headers = new Headers(initHeaders);
|
|
1190
1185
|
for (const [key, value] of Object.entries(additionalHeaders || {})) {
|
|
@@ -2,6 +2,7 @@ import OpenAI from "openai";
|
|
|
2
2
|
import { calculateCost, clampThinkingLevel } from "../models.js";
|
|
3
3
|
import { formatProviderError, normalizeProviderError } from "../utils/error-body.js";
|
|
4
4
|
import { AssistantMessageEventStream } from "../utils/event-stream.js";
|
|
5
|
+
import { shortHash } from "../utils/hash.js";
|
|
5
6
|
import { headersToRecord } from "../utils/headers.js";
|
|
6
7
|
import { parseStreamingJson } from "../utils/json-parse.js";
|
|
7
8
|
import { getProviderEnvValue } from "../utils/provider-env.js";
|
|
@@ -699,10 +700,21 @@ export function convertMessages(model, context, compat) {
|
|
|
699
700
|
// Format: {call_id}|{id} where {id} can be 400+ chars with special chars (+, /, =)
|
|
700
701
|
// These come from providers like github-copilot, openai-codex, opencode
|
|
701
702
|
// Extract just the call_id part and normalize it
|
|
703
|
+
// Multiple tool calls in the same turn can share call_id but differ by item_id.
|
|
704
|
+
// Preserve item-level uniqueness when replaying into Chat Completions, which
|
|
705
|
+
// requires distinct tool call ids.
|
|
702
706
|
if (id.includes("|")) {
|
|
703
|
-
const [callId] = id.split("|");
|
|
704
707
|
// Sanitize to allowed chars and truncate to 40 chars (OpenAI limit)
|
|
705
|
-
|
|
708
|
+
const separatorIndex = id.indexOf("|");
|
|
709
|
+
const callId = id.slice(0, separatorIndex).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
710
|
+
const itemId = id.slice(separatorIndex + 1).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
711
|
+
const combinedId = itemId.length > 0 ? `${callId}_${itemId}` : callId;
|
|
712
|
+
if (combinedId.length <= 40) {
|
|
713
|
+
return combinedId;
|
|
714
|
+
}
|
|
715
|
+
const hash = shortHash(id).slice(0, 8);
|
|
716
|
+
const prefix = callId.slice(0, Math.max(1, 40 - hash.length - 1));
|
|
717
|
+
return `${prefix}_${hash}`;
|
|
706
718
|
}
|
|
707
719
|
if (model.provider === "openai")
|
|
708
720
|
return id.length > 40 ? id.slice(0, 40) : id;
|
|
@@ -23,13 +23,11 @@ export class PiMessagesResponseError extends Error {
|
|
|
23
23
|
this.diagnosticDetails = diagnosticDetails;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
function isRecord(value) {
|
|
27
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28
|
-
}
|
|
29
26
|
function parsePiMessagesErrorBody(body) {
|
|
30
27
|
try {
|
|
31
28
|
const parsed = JSON.parse(body);
|
|
32
|
-
|
|
29
|
+
const error = parsed?.error;
|
|
30
|
+
return parsed && typeof error === "object" && error !== null && !Array.isArray(error) ? parsed : undefined;
|
|
33
31
|
}
|
|
34
32
|
catch {
|
|
35
33
|
return undefined;
|
|
@@ -12,8 +12,9 @@ export function envApiKeyAuth(name, envVars) {
|
|
|
12
12
|
return { type: "api_key", key };
|
|
13
13
|
},
|
|
14
14
|
resolve: async ({ ctx, credential }) => {
|
|
15
|
-
if (credential?.key)
|
|
16
|
-
return { auth: { apiKey: credential.key }, source: "stored credential" };
|
|
15
|
+
if (credential?.key) {
|
|
16
|
+
return { auth: { apiKey: credential.key }, env: credential.env, source: "stored credential" };
|
|
17
|
+
}
|
|
17
18
|
for (const envVar of envVars) {
|
|
18
19
|
const value = await ctx.env(envVar);
|
|
19
20
|
if (value)
|