@bivy/bivy 0.10.1-staging.359 → 0.10.1-staging.360
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.
|
@@ -185,6 +185,9 @@ function handleCompletedItem(params) {
|
|
|
185
185
|
if (!item || typeof item !== "object" || !itemId) return;
|
|
186
186
|
switch (item.type) {
|
|
187
187
|
case "agentMessage":
|
|
188
|
+
// Child-thread prose belongs to the delegated agent, not the parent's
|
|
189
|
+
// answer stream. Its lifecycle is represented by the collaboration items.
|
|
190
|
+
if (params?.threadId && threadId && params.threadId !== threadId) return;
|
|
188
191
|
if (!agentMessageItems.has(itemId) && item.text) {
|
|
189
192
|
agentMessageItems.add(itemId);
|
|
190
193
|
bivy({ type: "message.delta", text: String(item.text) });
|
|
@@ -317,20 +320,29 @@ function onServerRequest(m) {
|
|
|
317
320
|
|
|
318
321
|
function onNotification(m) {
|
|
319
322
|
const { method, params } = m;
|
|
323
|
+
// Codex publishes child-thread prose on the same app-server connection as the
|
|
324
|
+
// parent. It is not a continuation of the parent's assistant message: folding
|
|
325
|
+
// both token streams together produces character-level corruption whenever a
|
|
326
|
+
// delegated agent answers concurrently. Child lifecycle remains visible via
|
|
327
|
+
// collabAgentToolCall/subAgentActivity; only prose/reasoning is scoped here.
|
|
328
|
+
const fromCurrentThread = !params?.threadId || !threadId || params.threadId === threadId;
|
|
320
329
|
switch (method) {
|
|
321
|
-
case "item/agentMessage/delta":
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
330
|
+
case "item/agentMessage/delta": {
|
|
331
|
+
const itemId = paramsItemId(params);
|
|
332
|
+
// Remember ignored child items too so their later item/completed echo is
|
|
333
|
+
// not mistaken for a parent message and replayed wholesale.
|
|
334
|
+
if (itemId) agentMessageItems.add(itemId);
|
|
335
|
+
if (fromCurrentThread && typeof params.delta === "string" && params.delta) {
|
|
325
336
|
bivy({ type: "message.delta", text: params.delta });
|
|
326
337
|
}
|
|
327
338
|
return;
|
|
339
|
+
}
|
|
328
340
|
case "item/plan/delta":
|
|
329
|
-
emitReasoning(paramsItemId(params), params.delta);
|
|
341
|
+
if (fromCurrentThread) emitReasoning(paramsItemId(params), params.delta);
|
|
330
342
|
return;
|
|
331
343
|
case "item/reasoning/summaryTextDelta":
|
|
332
344
|
case "item/reasoning/textDelta":
|
|
333
|
-
emitReasoning(paramsItemId(params), params.delta);
|
|
345
|
+
if (fromCurrentThread) emitReasoning(paramsItemId(params), params.delta);
|
|
334
346
|
return;
|
|
335
347
|
case "item/commandExecution/outputDelta": {
|
|
336
348
|
const itemId = paramsItemId(params);
|
|
@@ -4,7 +4,7 @@ import { defineAgentIntegration } from "../definition.js";
|
|
|
4
4
|
import { withExactCapabilitySurface } from "../../runtime/types.js";
|
|
5
5
|
import { createCredentialStore } from "../../runtime/credentials.js";
|
|
6
6
|
import { ClaudeCodeRuntime, claudeRuntimeFromEnv, claudeSdkInstalled, } from "./runtime.js";
|
|
7
|
-
export const CLAUDE_TESTED_VERSION = "0.3.
|
|
7
|
+
export const CLAUDE_TESTED_VERSION = "0.3.233";
|
|
8
8
|
const CLAUDE_CAPABILITIES = withExactCapabilitySurface({
|
|
9
9
|
toolInterception: true,
|
|
10
10
|
modelSelection: true,
|
|
@@ -484,7 +484,15 @@ export class PiRuntime {
|
|
|
484
484
|
return this.build(sessionManager, options);
|
|
485
485
|
}
|
|
486
486
|
openSession(options) {
|
|
487
|
-
|
|
487
|
+
// Pi intentionally defers writing a new transcript until the first assistant
|
|
488
|
+
// response. A named empty session can therefore outlive its in-memory host
|
|
489
|
+
// (restart/detach) while its metadata path does not exist yet. Recreate that
|
|
490
|
+
// empty shell with Bivy's canonical id instead of letting SessionManager.open
|
|
491
|
+
// assign a new id, which would duplicate the sidebar row. Existing files keep
|
|
492
|
+
// Pi's normal full-fidelity resume path.
|
|
493
|
+
const sessionManager = !fs.existsSync(options.sessionFile) && options.canonicalId
|
|
494
|
+
? SessionManager.create(options.workspace, this.options.sessionsDir, { id: options.canonicalId })
|
|
495
|
+
: SessionManager.open(options.sessionFile, this.options.sessionsDir);
|
|
488
496
|
return this.build(sessionManager, options);
|
|
489
497
|
}
|
|
490
498
|
/**
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
export const CERTIFICATION_MATRIX = {
|
|
4
4
|
schemaVersion: 1,
|
|
5
5
|
agents: [
|
|
6
|
-
{ id: "claude-code-sdk", status: "active", executionMode: "protocol", pinnedVersion: "0.3.
|
|
6
|
+
{ id: "claude-code-sdk", status: "active", executionMode: "protocol", pinnedVersion: "0.3.233", capabilities: ["toolInterception", "modelSelection", "resume"] },
|
|
7
7
|
{ id: "codex-approvals", status: "active", executionMode: "protocol", pinnedVersion: "0.147.0", capabilities: ["toolInterception", "modelSelection", "resume"] },
|
|
8
8
|
{ id: "pi", status: "active", executionMode: "protocol", pinnedVersion: "0.84.2", capabilities: ["toolInterception", "modelSelection", "resume"] },
|
|
9
9
|
{ id: "opencode", status: "active", executionMode: "protocol", pinnedVersion: "1.18.18", capabilities: ["toolInterception", "modelSelection", "resume"] },
|
package/dist/server.js
CHANGED
|
@@ -101,7 +101,7 @@ import { createGithubCommands } from "./controllers/github-commands.js";
|
|
|
101
101
|
import { createCredentialCommands } from "./controllers/credential-commands.js";
|
|
102
102
|
import { createCustomModelCommands } from "./controllers/custom-model-commands.js";
|
|
103
103
|
import { MetadataStore } from "./metadata.js";
|
|
104
|
-
import { resolveResumeRef, resumeRefFor } from "./session-ref.js";
|
|
104
|
+
import { resolveResumeRef, resumeRefFor, storedResumeRef } from "./session-ref.js";
|
|
105
105
|
import { materializeFork } from "./session/fork.js";
|
|
106
106
|
import { applyDirtyPatch } from "./session/fork-dirty.js";
|
|
107
107
|
import { normalizeMessages } from "./session/transcript-normal.js";
|
|
@@ -7719,9 +7719,17 @@ async function createSession(workspace = defaultWorkspace, sessionFile, opts = {
|
|
|
7719
7719
|
// made Claude Code (and any id-based runtime) sessions un-resumable with
|
|
7720
7720
|
// "Session file is outside the sessions directory".
|
|
7721
7721
|
const requestedRef = typeof sessionFile === "string" && sessionFile.trim() ? sessionFile.trim() : undefined;
|
|
7722
|
-
const
|
|
7723
|
-
const
|
|
7724
|
-
|
|
7722
|
+
const requestedMeta = requestedRef ? metadata.getSession(requestedRef) : undefined;
|
|
7723
|
+
const refRuntimeId = opts.runtimeId ?? requestedMeta?.runtimeId;
|
|
7724
|
+
// Some callers (notably the local CLI HTTP API) name a closed session by its
|
|
7725
|
+
// Bivy id and enter createSession directly rather than resolveOrResumeSession.
|
|
7726
|
+
// Translate that id to the owning runtime's durable ref before applying the
|
|
7727
|
+
// path guard/opening it. Without this, a valid empty Pi session was interpreted
|
|
7728
|
+
// as a relative filename and rejected as outside pi/sessions; id-based native
|
|
7729
|
+
// refs could likewise resume the wrong id. Explicit path refs remain unchanged.
|
|
7730
|
+
const durableRef = requestedRef ? storedResumeRef(requestedRef, requestedMeta) : undefined;
|
|
7731
|
+
const requestedSessionFile = durableRef
|
|
7732
|
+
? resolveResumeRef({ ref: durableRef, resumesByPath: runtimeResumesByPath(refRuntimeId), sessionsDir })
|
|
7725
7733
|
: undefined;
|
|
7726
7734
|
const storedMeta = requestedSessionFile ? metadata.getSession(requestedSessionFile) : undefined;
|
|
7727
7735
|
const restoredWorktree = requestedSessionFile ? restoredWorktreeFromMetadata(storedMeta) : undefined;
|
package/dist/session-ref.js
CHANGED
|
@@ -40,6 +40,20 @@ export function resolveResumeRef(opts) {
|
|
|
40
40
|
}
|
|
41
41
|
return resolved;
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Replace a client-supplied session id with the runtime resume ref stored for
|
|
45
|
+
* that exact metadata row. Callers that already supply a path keep that path:
|
|
46
|
+
* metadata stores are commonly indexed by both id and path, and treating a path
|
|
47
|
+
* lookup as an id lookup would make an explicit ref unexpectedly change.
|
|
48
|
+
*
|
|
49
|
+
* This is intentionally runtime-neutral. Pi stores a transcript path, while
|
|
50
|
+
* Codex/OpenCode can store a provider-native thread id; both are opaque refs at
|
|
51
|
+
* this layer.
|
|
52
|
+
*/
|
|
53
|
+
export function storedResumeRef(requestedRef, meta) {
|
|
54
|
+
const stored = meta?.path?.trim();
|
|
55
|
+
return meta?.id === requestedRef && stored ? stored : requestedRef;
|
|
56
|
+
}
|
|
43
57
|
/**
|
|
44
58
|
* Decide what to resume a client-named session from when the node isn't holding
|
|
45
59
|
* it in memory (a restart, an idle close, or a session this process never
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bivy/bivy",
|
|
3
|
-
"version": "0.10.1-staging.
|
|
3
|
+
"version": "0.10.1-staging.360",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"description": "Run coding agents on machines you own. Open-source, self-hostable agent workspace.",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"postinstall": "node bin/patch-pi-dependencies.mjs"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@anthropic-ai/claude-agent-sdk": "0.3.
|
|
41
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.233",
|
|
42
42
|
"@earendil-works/pi-ai": "0.84.2",
|
|
43
43
|
"@earendil-works/pi-coding-agent": "0.84.2",
|
|
44
44
|
"@modelcontextprotocol/sdk": "1.30.0",
|