Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions src/adapters/command-code.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { randomUUID } from "node:crypto";
import { createHash, randomUUID } from "node:crypto";
import { execFile as execFileCallback } from "node:child_process";
import { promisify } from "node:util";
import { opendir } from "node:fs/promises";
Expand Down Expand Up @@ -211,6 +211,27 @@ function projectSlug(cwd: string): string {
return cwd.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-|-$/g, "").toLowerCase().slice(0, 64) || "workspace";
}

export function commandCodeSessionId(parsed: OcxParsedRequest): string {
// Shared prompt-cache cohorts identify a cache population, not one conversation. Using one
// for session affinity would pin unrelated conversations to the same upstream worker.
const threadId = parsed._clientThreadId?.trim();
const replayId = parsed._reasoningReplayScope?.clientThreadId?.trim();
const cacheKey = parsed._promptCacheKeyIsSharedCohort === false
? parsed.options.promptCacheKey?.trim()
: undefined;
const identity = threadId
? ["thread", threadId]
: replayId
? ["replay", replayId]
: cacheKey
? ["cache", cacheKey]
: undefined;
if (!identity) return randomUUID();
const hex = createHash("sha256").update(`command-code:${identity[0]}\0${identity[1]}`).digest("hex");
// Replace the digest nibbles at the UUID version and variant positions; the skipped hex characters are intentional.
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-4${hex.slice(13, 16)}-8${hex.slice(17, 20)}-${hex.slice(20, 32)}`;
}

interface GitWorkspaceInfo {
isGitRepo: boolean;
currentBranch: string;
Expand Down Expand Up @@ -523,7 +544,7 @@ export function createCommandCodeAdapter(provider: OcxProviderConfig): ProviderA
"x-cli-environment": "production",
"x-taste-learning": "false",
"x-co-flag": "false",
"x-session-id": randomUUID(),
"x-session-id": commandCodeSessionId(parsed),
};
if (cwd) headers["x-project-slug"] = projectSlug(cwd);
return {
Expand Down
1 change: 1 addition & 0 deletions src/providers/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2175,6 +2175,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
liveModels: true,
preserveCustomDestination: true,
defaultModel: "deepseek/deepseek-v4-flash",
promptCacheKey: true,
// The default is also the cold-start seed: live discovery failure must not empty the catalog
// for a freshly configured provider with no stale cache (issue #308 pattern).
models: ["deepseek/deepseek-v4-flash"],
Expand Down
2 changes: 2 additions & 0 deletions src/server/responses/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2896,6 +2896,7 @@ async function handleResponsesInner(
let toolBridgeMaps: ReturnType<typeof buildToolBridgeMaps>;
try {
parsed = parseRequest(body);
parsed._promptCacheKeyIsSharedCohort = options.promptCacheKeyIsSharedCohort;
// Captured before any parser mutates it, so both grammars see the client's id.
const { fastRow, effortRow } = parseSyntheticRowId(parsed.modelId, config);
if (fastRow) {
Expand Down Expand Up @@ -3210,6 +3211,7 @@ async function handleResponsesInner(
"_providerContinuationOwner",
"_cursorConversationId",
"_clientThreadId",
"_promptCacheKeyIsSharedCohort",
"_cursorClientThreadId",
"_reasoningReplayScope",
"_cursorIsolateConversation",
Expand Down
2 changes: 2 additions & 0 deletions src/types/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ export interface OcxParsedRequest {
_cursorConversationId?: string;
/** Stable upstream client thread identity, used only to derive provider-scoped continuation ids. */
_clientThreadId?: string;
/** True when promptCacheKey identifies a shared cache cohort rather than one conversation. */
_promptCacheKeyIsSharedCohort?: boolean;
/** Cursor-only thread owner; may be an opaque process-local Desktop session/thread identity. */
_cursorClientThreadId?: string;
/** Conversation/provider/account/model-bound namespace for reasoning replay state. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,19 @@ describe("Claude Code Anthropic inbound reasoning-replay scope", () => {
const parsed = await drive({ promptCacheKey: "session-key-123", promptCacheKeyIsSharedCohort: false });
expect(parsed._clientThreadId).toBeUndefined();
expect(parsed._reasoningReplayScope?.clientThreadId).toBe("session-key-123");
expect(parsed._promptCacheKeyIsSharedCohort).toBe(false);
});

test("the shared Desktop prompt_cache_key cohort does not create a scope", async () => {
const parsed = await drive({ promptCacheKey: "shared-cohort-key", promptCacheKeyIsSharedCohort: true });
expect(parsed._reasoningReplayScope).toBeUndefined();
expect(parsed._promptCacheKeyIsSharedCohort).toBe(true);
});

test("an Anthropic replay without prompt_cache_key does not create a scope", async () => {
const parsed = await drive({});
expect(parsed._reasoningReplayScope).toBeUndefined();
expect(parsed._promptCacheKeyIsSharedCohort).toBeUndefined();
});

test("an overlong prompt_cache_key is hashed, not stored raw", async () => {
Expand Down
66 changes: 65 additions & 1 deletion tests/providers/command-code-provider.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { afterEach, describe, expect, test } from "bun:test";
import { createCommandCodeAdapter } from "../../src/adapters/command-code";
import { commandCodeSessionId, createCommandCodeAdapter } from "../../src/adapters/command-code";
import { loginCommandCode, parseCommandCodeCallback, shouldImportLocalCommandCodeAuth } from "../../src/oauth/command-code";
import { buildModelsRequest, OAUTH_PROVIDERS } from "../../src/oauth";
import {
Expand Down Expand Up @@ -658,4 +658,68 @@ describe("Command Code provider", () => {
const built = await builtRequest({ ...parsed(), stream: false });
expect(JSON.parse(built.body).params.stream).toBe(true);
});

test("derives an opaque stable session id from trusted conversation identity", async () => {
const uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-8[0-9a-f]{3}-[0-9a-f]{12}$/i;
const identities = {
thread: "thread-secret-value",
replay: "replay-secret-value",
cache: "cache-secret-value",
};
const thread = {
...parsed(),
_clientThreadId: ` ${identities.thread} `,
_reasoningReplayScope: { clientThreadId: identities.replay },
options: { ...parsed().options, promptCacheKey: identities.cache },
};
const sameThread = {
...thread,
_reasoningReplayScope: { clientThreadId: "different-replay" },
options: { ...thread.options, promptCacheKey: "different-cache" },
};
const replay = {
...parsed(),
_reasoningReplayScope: { clientThreadId: identities.replay },
options: { ...parsed().options, promptCacheKey: identities.cache },
};
const sameReplay = { ...replay, options: { ...replay.options, promptCacheKey: "different-cache" } };
const cache = {
...parsed(),
options: { ...parsed().options, promptCacheKey: ` ${identities.cache} ` },
_promptCacheKeyIsSharedCohort: false,
};
const sameCache = {
...cache,
options: { ...cache.options, promptCacheKey: identities.cache },
};

const threadId = commandCodeSessionId(thread);
expect(threadId).toBe(commandCodeSessionId(sameThread));
expect(threadId).not.toBe(commandCodeSessionId({ ...thread, _clientThreadId: "different-thread" }));
expect(commandCodeSessionId(replay)).toBe(commandCodeSessionId(sameReplay));
expect(commandCodeSessionId(cache)).toBe(commandCodeSessionId(sameCache));
expect(commandCodeSessionId(replay)).not.toBe(commandCodeSessionId(cache));
expect(threadId).toMatch(uuid);
expect(commandCodeSessionId(replay)).toMatch(uuid);
expect(commandCodeSessionId(cache)).toMatch(uuid);
for (const raw of Object.values(identities)) expect(threadId).not.toContain(raw);

const built = await builtRequest(thread);
expect(built.headers["x-session-id"]).toBe(threadId);
});

test("does not derive affinity from a shared cohort or prompt text", () => {
const shared = {
...parsed(),
options: { ...parsed().options, promptCacheKey: "shared-cache-key" },
_promptCacheKeyIsSharedCohort: true,
};
expect(commandCodeSessionId(shared)).not.toBe(commandCodeSessionId(shared));
const unclassifiedCache = {
...parsed(),
options: { ...parsed().options, promptCacheKey: "possibly-shared-cache-key" },
};
expect(commandCodeSessionId(unclassifiedCache)).not.toBe(commandCodeSessionId(unclassifiedCache));
expect(commandCodeSessionId(parsed())).not.toBe(commandCodeSessionId(parsed()));
});
});
15 changes: 15 additions & 0 deletions tests/providers/commandcode-provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ describe("Command Code provider", () => {
liveModels: true,
preserveCustomDestination: true,
defaultModel: "deepseek/deepseek-v4-flash",
promptCacheKey: true,
apiKeyValidation: "unknown",
reasoningEfforts: [],
modelReasoningEfforts: {
Expand Down Expand Up @@ -176,6 +177,20 @@ describe("Command Code provider", () => {
expect(body).not.toHaveProperty("parallel_tool_calls");
});

test("forwards the enabled prompt cache key to chat completions", () => {
const route = routeModel(
commandcodeConfig(),
"commandcode/deepseek/deepseek-v4-flash",
);
const request = createOpenAIChatAdapter(route.provider).buildRequest({
modelId: route.modelId,
context: { messages: [{ role: "user", content: "ping", timestamp: 0 }] },
stream: true,
options: { promptCacheKey: "command-code-session-cache" },
});
expect(JSON.parse(String(request.body)).prompt_cache_key).toBe("command-code-session-cache");
});

test("discovers the live catalog with context windows and preserves slash ids", async () => {
globalThis.fetch = (async (input, init) => {
expect(String(input)).toBe("https://api.commandcode.ai/provider/v1/models");
Expand Down
Loading