Skip to content

Commit cc92bee

Browse files
committed
Release v0.2.6
1 parent 99d0ec6 commit cc92bee

28 files changed

Lines changed: 201 additions & 79 deletions

‎RELEASE.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
2-
"version": "0.2.5",
2+
"version": "0.2.6",
33
"license": "FSL-1.1-ALv2",
44
"baselineSha256": "7847f65a9b20b366a60d52d19ca3cd6bdd1bb09b8cb506659a270f27a21d8877",
55
"e2b": {
66
"recipeSha256": "761809ee2efa2b6c750451ace29283cbb8e55b6ce3b5b14c2bb4509df71df801",
77
"profileSha256": "414dbecee2d47de36016ea05c736e2edff3a0deb298babf923887ea184a01c10"
88
},
99
"dxd": {
10-
"url": "https://github.com/dxcode-dev/dxcode/releases/download/v0.2.5/dxd-linux-x64",
11-
"sha256": "810626730c00c4bbe3952566b2ebfdc92bf375fd87446fb61d6c0a8041e65bac"
10+
"url": "https://github.com/dxcode-dev/dxcode/releases/download/v0.2.6/dxd-linux-x64",
11+
"sha256": "2e3408e65cad33ccea13ba9f95321693cb22beb7944d5e02438184921190c700"
1212
},
1313
"toolchain": {
1414
"node": ">=22.19.0",

‎apps/core/package.json‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@dx/core",
33
"private": true,
4-
"version": "0.2.5",
4+
"version": "0.2.6",
55
"license": "FSL-1.1-ALv2",
66
"type": "module",
77
"scripts": {
@@ -20,7 +20,7 @@
2020
"@dx/api": "workspace:^",
2121
"@dx/domain": "workspace:^",
2222
"@effect/sql-d1": "4.0.0-rc.110",
23-
"@flue/runtime": "file:../../third-party/flue/runtime-11963758a85ad512c317d4d3ea7d8955bde01432.tgz",
23+
"@flue/runtime": "file:../../third-party/flue/runtime-86c9c05b22514ea646aedff869d1579a99d8eab9.tgz",
2424
"@jitl/quickjs-wasmfile-release-sync": "0.32.0",
2525
"@logtape/logtape": "2.3.1",
2626
"@modelcontextprotocol/client": "2.0.0",
@@ -41,8 +41,8 @@
4141
"@cloudflare/vitest-plugin": "1.0.0",
4242
"@cloudflare/workers-types": "5.20260820.1",
4343
"@earendil-works/pi-ai": "0.85.1",
44-
"@flue/sdk": "file:../../third-party/flue/sdk-11963758a85ad512c317d4d3ea7d8955bde01432.tgz",
45-
"@flue/vite": "file:../../third-party/flue/vite-11963758a85ad512c317d4d3ea7d8955bde01432.tgz",
44+
"@flue/sdk": "file:../../third-party/flue/sdk-86c9c05b22514ea646aedff869d1579a99d8eab9.tgz",
45+
"@flue/vite": "file:../../third-party/flue/vite-86c9c05b22514ea646aedff869d1579a99d8eab9.tgz",
4646
"@msw/cloudflare": "^0.0.1",
4747
"@types/ws": "8.18.1",
4848
"@valibot/to-json-schema": "1.7.1",

‎apps/core/src/execution/dxd/protocol.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
} from "../../thread-changes/candidate.js";
2525

2626
export const DXD_PROTOCOL_MAJOR = 2;
27-
export const DXD_RELEASE = "0.8.0";
27+
export const DXD_RELEASE = "0.8.1";
2828
export const DXD_TERMINAL_VERSION = 1;
2929
export const DXD_WORKLOAD_IDENTITY_VERSION = 1;
3030
export const DXD_HEARTBEAT_INTERVAL_MS = 2_000;

‎apps/core/src/observability/flue.test.ts‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,55 @@ describe("Flue observation", () => {
226226
);
227227
});
228228

229+
it("logs compaction start and outcome without the summary or error", () => {
230+
subscriber(
231+
observation({
232+
type: "compaction_start",
233+
agentName: "dx-agent",
234+
instanceId: "thr_test",
235+
submissionId: "sub_test",
236+
reason: "threshold",
237+
estimatedTokens: 251_000,
238+
}),
239+
{} as never,
240+
);
241+
subscriber(
242+
observation({
243+
type: "compaction",
244+
agentName: "dx-agent",
245+
instanceId: "thr_test",
246+
submissionId: "sub_test",
247+
messagesBefore: 120,
248+
messagesAfter: 9,
249+
durationMs: 4_200,
250+
isError: true,
251+
error: { message: "secret summary failure" },
252+
}),
253+
{} as never,
254+
);
255+
256+
const correlation = {
257+
agentName: "dx-agent",
258+
threadId: "thr_test",
259+
submissionId: "sub_test",
260+
};
261+
expect(mocks.modelInfo).toHaveBeenCalledWith("Flue compaction started.", {
262+
event: "compaction_start",
263+
...correlation,
264+
reason: "threshold",
265+
estimatedTokens: 251_000,
266+
});
267+
expect(mocks.modelInfo).toHaveBeenCalledWith("Flue compaction completed.", {
268+
event: "compaction",
269+
...correlation,
270+
isError: true,
271+
messagesBefore: 120,
272+
messagesAfter: 9,
273+
durationMs: 4_200,
274+
});
275+
expect(JSON.stringify(mocks.modelInfo.mock.calls)).not.toContain("secret");
276+
});
277+
229278
it("maps tool outcome without arguments or results", () => {
230279
subscriber(
231280
observation({

‎apps/core/src/observability/flue.ts‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,24 @@ const observeFlueEvent = (
197197
});
198198
return persistence;
199199
}
200+
case "compaction_start":
201+
agentModelLogger.info("Flue compaction started.", {
202+
event: event.type,
203+
...correlations(event),
204+
reason: event.reason,
205+
estimatedTokens: event.estimatedTokens,
206+
});
207+
return persistence;
208+
case "compaction":
209+
agentModelLogger.info("Flue compaction completed.", {
210+
event: event.type,
211+
...correlations(event),
212+
isError: event.isError,
213+
messagesBefore: event.messagesBefore,
214+
messagesAfter: event.messagesAfter,
215+
durationMs: event.durationMs,
216+
});
217+
return persistence;
200218
case "tool_start":
201219
agentToolLogger.info("Flue tool execution started.", {
202220
event: event.type,

‎apps/core/src/source-control/bitbucket/git-gateway.ts‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,15 @@ bitbucketGitGatewayRoutes.all("/*", async (context) => {
100100
)
101101
return failure(403);
102102
if (write && lease.operation !== "contents-push") return failure(403);
103-
if (context.req.header("content-encoding")) return failure(403);
104-
const body =
103+
// Git gzips smart-HTTP request bodies over 1 KiB, so any non-shallow
104+
// fetch of a repository with a few refs sends one. Forward it decoded.
105+
const encoding = context.req.header("content-encoding")?.toLowerCase();
106+
const gzip = encoding === "gzip" && context.req.method === "POST" && !lfs;
107+
if (encoding !== undefined && !gzip) return failure(403);
108+
const raw =
105109
context.req.method === "POST" ? context.req.raw.body : undefined;
110+
const body =
111+
gzip && raw ? raw.pipeThrough(new DecompressionStream("gzip")) : raw;
106112
const control = await bitbucketControlPlaneFor(db, context.env);
107113
const response = await control.withConnection(
108114
lease.actor_user_id,

‎apps/core/src/source-control/bitbucket/lifecycle.test.ts‎

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -864,11 +864,44 @@ describe("Bitbucket OAuth and source lifecycle with migrated SQLite", () => {
864864
.status,
865865
).toBe(200);
866866
expect(upstream[1]?.body).toBe(body);
867+
// Git gzips upload-pack bodies over 1 KiB; Bitbucket gets them decoded.
868+
const wants = `0032want ${"c".repeat(40)}\n`.repeat(40);
869+
const gzipped = new Response(
870+
new Blob([wants])
871+
.stream()
872+
.pipeThrough(new CompressionStream("gzip")),
873+
).body;
874+
const decoded = await app.request(
875+
"https://dx.example/api/source/bitbucket/git/space/repo.git/git-upload-pack",
876+
{
877+
method: "POST",
878+
body: gzipped,
879+
headers: { ...headers, "content-encoding": "gzip" },
880+
duplex: "half",
881+
} as RequestInit,
882+
{ ...bindings, DB: f.db },
883+
);
884+
expect(decoded.status).toBe(200);
885+
expect(upstream[2]?.body).toBe(wants);
886+
expect(upstream[2]?.headers.get("content-encoding")).toBeNull();
887+
expect(
888+
(
889+
await app.request(
890+
"https://dx.example/api/source/bitbucket/git/space/repo.git/git-upload-pack",
891+
{
892+
method: "POST",
893+
body: wants,
894+
headers: { ...headers, "content-encoding": "br" },
895+
},
896+
{ ...bindings, DB: f.db },
897+
)
898+
).status,
899+
).toBe(403);
867900
allowed = false;
868901
expect(
869902
(await request("info/refs?service=git-upload-pack")).status,
870903
).toBe(403);
871-
expect(upstream).toHaveLength(2);
904+
expect(upstream).toHaveLength(3);
872905
expect((await readBitbucketConnection(f.db, userId))?.status).toBe(
873906
"active",
874907
);

‎apps/core/src/threads/terminal-object.ts‎

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ import {
7979
} from "../settings/environment-variables/execution.js";
8080
import { resolveExecutionSigningPlan } from "../settings/keys/execution.js";
8181
import { signGitPayload } from "../settings/keys/ssh-ed25519.js";
82+
import { bitbucketControlPlaneFor } from "../source-control/bitbucket/control-plane.js";
8283
import {
8384
BITBUCKET_GIT_PATH,
8485
bitbucketRuntimeBroker,
@@ -2038,8 +2039,8 @@ export class ThreadExecutionObject extends DurableObject<Bindings> {
20382039
);
20392040
// Independent D1 reads: a wake waits for the slowest, not their sum.
20402041
const db = await Effect.runPromise(decodeD1Binding(this.env.DB));
2041-
// Every bitbucket.org remote routes through the dx gateway while the
2042-
// Thread owner has an active Bitbucket connection.
2042+
// While the Thread owner has an active Bitbucket connection, SSH
2043+
// bitbucket.org remotes use HTTPS so the native credential helper applies.
20432044
const [snapshot, signing, bitbucketConnection] = await Promise.all([
20442045
Effect.runPromise(resolveExecutionEnvironment(this.env, threadId)),
20452046
Effect.runPromise(resolveExecutionSigningPlan(this.env, threadId)),
@@ -2426,6 +2427,22 @@ export class ThreadExecutionObject extends DurableObject<Bindings> {
24262427
});
24272428
return { username: "x-access-token", password };
24282429
}
2430+
if (host === "bitbucket.org") {
2431+
const control = await bitbucketControlPlaneFor(db, this.env);
2432+
const password = await control.withConnection(
2433+
thread.owner_user_id,
2434+
undefined,
2435+
async (token) => token,
2436+
);
2437+
threadDaemonLogger.info("Native Bitbucket credential issued.", {
2438+
event: "native_git_credential",
2439+
threadId,
2440+
actorUserId: thread.owner_user_id,
2441+
provider: "bitbucket",
2442+
});
2443+
return { username: "x-token-auth", password };
2444+
}
2445+
// dxd releases that still rewrite bitbucket.org remotes to the gateway.
24292446
const gateway = new URL(this.env.DX_AUTH_URL as string);
24302447
if (
24312448
host !== gateway.host.toLowerCase() ||

‎apps/docs/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@dx/docs",
33
"private": true,
4-
"version": "0.2.5",
4+
"version": "0.2.6",
55
"license": "FSL-1.1-ALv2",
66
"type": "module",
77
"scripts": {

‎apps/dxd/Cargo.lock‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)