Skip to content

Commit ca3e28c

Browse files
committed
chore(vendor): re-pin Interchange trees to main head with the director loader
1 parent 35c8cd6 commit ca3e28c

77 files changed

Lines changed: 3257 additions & 669 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/VENDORING.md

Lines changed: 73 additions & 39 deletions
Large diffs are not rendered by default.

src/config.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,13 +1505,13 @@ describe("buildOpenAISource", () => {
15051505
expect(source.baseURL).toBe("http://localhost:11434/v1");
15061506
});
15071507

1508-
test("substitutes a placeholder apiKey when none is provided (keyless)", () => {
1508+
test("substitutes a placeholder credentialId when none is provided (keyless)", () => {
15091509
const source = buildOpenAISource({
15101510
id: "local",
15111511
baseURL: "http://localhost:8080/v1",
15121512
model: "local-model",
15131513
});
1514-
expect(source.apiKey).toBe(KEYLESS_API_KEY);
1514+
expect(source.credentialId).toBe(KEYLESS_API_KEY);
15151515
});
15161516
});
15171517

src/config/credential-material.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { CredentialMaterialResolver } from "@intx/types";
2+
3+
// Every source builder in `src/config` stores secret material directly in
4+
// `credentialId` (API keys, OAuth access tokens, the keyless placeholder), so
5+
// resolving a credential is an identity read. A live credential cell would
6+
// replace this; until then the resolver echoes the id.
7+
export const resolveInlineCredentialMaterial: CredentialMaterialResolver = (
8+
credentialId,
9+
) => ({ secret: credentialId });

src/config/index.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export const SOURCE_MAX_TOKENS = 16384;
107107

108108
// Placeholder sent in the Authorization header for keyless local providers
109109
// (e.g. Ollama). The runtime's InferenceSource type requires a non-empty
110-
// apiKey string; the value is injected as `Bearer <key>` by the harness but
110+
// credentialId string; the value is injected as `Bearer <key>` by the harness but
111111
// keyless servers ignore it entirely.
112112
export const KEYLESS_API_KEY = "keyless";
113113

@@ -229,7 +229,7 @@ export function buildOpenAISource(fields: {
229229
baseURL: isOllamaProviderId(fields.id)
230230
? ollamaOpenAIBaseURL(fields.baseURL)
231231
: normalizeOpenAICompatibleBaseURL(fields.baseURL),
232-
apiKey:
232+
credentialId:
233233
fields.apiKey !== undefined && fields.apiKey.length > 0
234234
? fields.apiKey
235235
: KEYLESS_API_KEY,
@@ -308,7 +308,7 @@ export function buildCodexSource(fields: {
308308
id: fields.id,
309309
provider: CODEX_RESPONSES_PROVIDER,
310310
baseURL: CODEX_BASE_URL,
311-
apiKey: fields.apiKey,
311+
credentialId: fields.apiKey,
312312
model: fields.model,
313313
defaults: { maxTokens: SOURCE_MAX_TOKENS, providerOptions },
314314
};
@@ -338,7 +338,7 @@ export function buildXaiSource(fields: {
338338
id: fields.id,
339339
provider: GROK_RESPONSES_PROVIDER,
340340
baseURL: XAI_BASE_URL,
341-
apiKey: fields.apiKey,
341+
credentialId: fields.apiKey,
342342
model: fields.model,
343343
defaults: { maxTokens: SOURCE_MAX_TOKENS, providerOptions },
344344
};
@@ -362,7 +362,7 @@ export function buildBifrostSource(fields: {
362362
id: fields.id,
363363
provider: BIFROST_PROVIDER,
364364
baseURL: normalizeOpenAICompatibleBaseURL(fields.baseURL),
365-
apiKey:
365+
credentialId:
366366
fields.apiKey !== undefined && fields.apiKey.length > 0
367367
? fields.apiKey
368368
: KEYLESS_API_KEY,
@@ -382,7 +382,7 @@ export function buildAnthropicSource(fields: {
382382
id: fields.id,
383383
provider: "anthropic",
384384
baseURL: fields.baseURL.replace(/\/+$/, ""),
385-
apiKey:
385+
credentialId:
386386
fields.apiKey !== undefined && fields.apiKey.length > 0
387387
? fields.apiKey
388388
: KEYLESS_API_KEY,
@@ -410,7 +410,7 @@ export function buildGoSource(fields: {
410410
id: fields.id,
411411
provider: OPENCODE_GO_MESSAGES_PROVIDER,
412412
baseURL: endpoint.baseURL,
413-
apiKey,
413+
credentialId: apiKey,
414414
model: fields.model,
415415
defaults: {
416416
maxTokens: SOURCE_MAX_TOKENS,
@@ -425,7 +425,7 @@ export function buildGoSource(fields: {
425425
id: fields.id,
426426
provider: OPENAI_RESPONSES_PROVIDER,
427427
baseURL: endpoint.baseURL,
428-
apiKey,
428+
credentialId: apiKey,
429429
model: fields.model,
430430
defaults: {
431431
maxTokens: SOURCE_MAX_TOKENS,
@@ -479,7 +479,7 @@ export function buildZenSource(fields: {
479479
id: fields.id,
480480
provider: ZEN_MESSAGES_PROVIDER,
481481
baseURL: endpoint.baseURL,
482-
apiKey,
482+
credentialId: apiKey,
483483
model: fields.model,
484484
defaults: {
485485
maxTokens: SOURCE_MAX_TOKENS,
@@ -494,7 +494,7 @@ export function buildZenSource(fields: {
494494
id: fields.id,
495495
provider: OPENAI_RESPONSES_PROVIDER,
496496
baseURL: endpoint.baseURL,
497-
apiKey,
497+
credentialId: apiKey,
498498
model: fields.model,
499499
defaults: {
500500
maxTokens: SOURCE_MAX_TOKENS,

src/context-compactor.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,7 @@ describe("createPruningCompactor — consolidated handoff (CL-7521)", () => {
953953
provider: "openai",
954954
model: "test-model",
955955
baseURL: "http://localhost:1",
956-
apiKey: "k",
956+
credentialId: "k",
957957
};
958958
let calls = 0;
959959
const summarize = createModelSummarizer({

src/exec/runner.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ export async function runExec(config: Config): Promise<ExecResult> {
727727
const { access } = await refreshSelectedProviderCredential(() =>
728728
getValidCodexToken(initialCodexProfile),
729729
);
730-
liveSource = { ...liveSource, apiKey: access };
730+
liveSource = { ...liveSource, credentialId: access };
731731
liveSubAgentProvider.current = {
732732
...liveSubAgentProvider.current,
733733
apiKey: access,
@@ -737,7 +737,7 @@ export async function runExec(config: Config): Promise<ExecResult> {
737737
const { access } = await refreshSelectedProviderCredential(() =>
738738
getValidXaiToken(initialXaiProfile),
739739
);
740-
liveSource = { ...liveSource, apiKey: access };
740+
liveSource = { ...liveSource, credentialId: access };
741741
liveSubAgentProvider.current = {
742742
...liveSubAgentProvider.current,
743743
apiKey: access,
@@ -757,7 +757,7 @@ export async function runExec(config: Config): Promise<ExecResult> {
757757
liveSource,
758758
config.providers,
759759
);
760-
if (fresh.apiKey === liveSource.apiKey) return;
760+
if (fresh.credentialId === liveSource.credentialId) return;
761761
liveSource = fresh;
762762
if (currentAgent !== null)
763763
setAgentSourceUnlessClosed(currentAgent, fresh);
@@ -816,7 +816,9 @@ export async function runExec(config: Config): Promise<ExecResult> {
816816
const sources = liveSources.length > 0 ? liveSources : [liveSource];
817817
// Prefer liveSource credentials on the active id when OAuth was refreshed.
818818
return sources.map((s) =>
819-
s.id === liveSource.id ? { ...s, apiKey: liveSource.apiKey } : s,
819+
s.id === liveSource.id
820+
? { ...s, credentialId: liveSource.credentialId }
821+
: s,
820822
);
821823
},
822824
getDefaultSource: () =>
@@ -958,15 +960,15 @@ export async function runExec(config: Config): Promise<ExecResult> {
958960
// Final OAuth refresh immediately before send (token may have aged during MCP).
959961
if (initialCodexProfile !== undefined) {
960962
const { access } = await getValidCodexToken(initialCodexProfile);
961-
if (access !== liveSource.apiKey) {
962-
liveSource = { ...liveSource, apiKey: access };
963+
if (access !== liveSource.credentialId) {
964+
liveSource = { ...liveSource, credentialId: access };
963965
setAgentSourceUnlessClosed(activeAgent, liveSource);
964966
}
965967
}
966968
if (initialXaiProfile !== undefined) {
967969
const { access } = await getValidXaiToken(initialXaiProfile);
968-
if (access !== liveSource.apiKey) {
969-
liveSource = { ...liveSource, apiKey: access };
970+
if (access !== liveSource.credentialId) {
971+
liveSource = { ...liveSource, credentialId: access };
970972
setAgentSourceUnlessClosed(activeAgent, liveSource);
971973
}
972974
}

src/session/assemble-runtime.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ function stubChatAgentWiring(
219219
id: "s",
220220
provider: "test",
221221
baseURL: "http://localhost",
222-
apiKey: "k",
222+
credentialId: "k",
223223
model: "m",
224224
},
225225
],

src/session/assemble-runtime.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import {
4040
type LocalSettings,
4141
} from "../config/settings.js";
4242
import type { SessionMode } from "../config/session-mode.js";
43+
import { resolveInlineCredentialMaterial } from "../config/credential-material.js";
4344
import {
4445
advertisedTools,
4546
advertisedToolNamesForSessionMode,
@@ -578,6 +579,7 @@ export function assembleChatAgent(wiring: ChatAgentWiring): AssembledChatAgent {
578579
const agent = await createAgentWithLiveToolDispatch(agentDef, {
579580
sources: wiring.getSources(),
580581
defaultSource: wiring.getDefaultSource(),
582+
readCurrentMaterial: resolveInlineCredentialMaterial,
581583
storage: storageForAgent,
582584
workdir,
583585
// contextTransforms ride deps: the published @intx/agent forwards deps

src/session/summarizer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
type RetryPolicy,
2020
} from "@intx/types/runtime";
2121
import { LOG_NAMESPACE_ROOT } from "../branding.js";
22+
import { resolveInlineCredentialMaterial } from "../config/credential-material.js";
2223
import { NOOP_TELEMETRY, type Telemetry } from "../telemetry/index.js";
2324
import {
2425
buildArchiveSummaryExcerpt,
@@ -200,6 +201,7 @@ function defaultComplete(deps: Dependencies, timeoutMs: number): CompletionFn {
200201
signal,
201202
nextSeq: () => seq++,
202203
deps,
204+
readMaterial: resolveInlineCredentialMaterial,
203205
inferenceOptions: {
204206
totalTimeoutMs: timeoutMs,
205207
retryPolicy: NO_HARNESS_RETRY,

src/subagent/refresh-inference-source.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import * as xaiSession from "../auth/xai/session.js";
44

55
import type { InferenceSource } from "@intx/types/runtime";
66

7-
const baseSource = (id: string, apiKey = "stale"): InferenceSource => ({
7+
const baseSource = (id: string, credentialId = "stale"): InferenceSource => ({
88
id,
99
provider: "openai",
1010
baseURL: "https://api.openai.com/v1",
11-
apiKey,
11+
credentialId,
1212
model: "gpt-4o",
1313
});
1414

@@ -18,15 +18,15 @@ describe("refresh-inference-source", () => {
1818
spyOn(xaiSession, "getValidXaiToken").mockRestore();
1919
});
2020

21-
test("ensureFreshInferenceSource replaces stale Codex apiKey after refresh", async () => {
21+
test("ensureFreshInferenceSource replaces stale Codex credentialId after refresh", async () => {
2222
spyOn(codexSession, "getValidCodexToken").mockResolvedValue({
2323
access: "fresh-codex-token",
2424
});
2525
const { ensureFreshInferenceSource } =
2626
await import("./refresh-inference-source.js");
2727
const source = baseSource("codex/default", "stale");
2828
const out = await ensureFreshInferenceSource(source, []);
29-
expect(out.apiKey).toBe("fresh-codex-token");
29+
expect(out.credentialId).toBe("fresh-codex-token");
3030
});
3131

3232
test("refreshInferenceSourceBundle refreshes each leg", async () => {
@@ -53,6 +53,6 @@ describe("refresh-inference-source", () => {
5353
apiKey: "key-abc",
5454
},
5555
]);
56-
expect(out.apiKey).toBe("key-abc");
56+
expect(out.credentialId).toBe("key-abc");
5757
});
5858
});

0 commit comments

Comments
 (0)