Skip to content

Commit cf82f74

Browse files
committed
chore(vendor): re-pin Interchange trees to main head with the director loader
1 parent 9e2774f commit cf82f74

77 files changed

Lines changed: 3257 additions & 670 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 & 40 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
@@ -1514,13 +1514,13 @@ describe("buildOpenAISource", () => {
15141514
expect(source.baseURL).toBe("http://localhost:11434/v1");
15151515
});
15161516

1517-
test("substitutes a placeholder apiKey when none is provided (keyless)", () => {
1517+
test("substitutes a placeholder credentialId when none is provided (keyless)", () => {
15181518
const source = buildOpenAISource({
15191519
id: "local",
15201520
baseURL: "http://localhost:8080/v1",
15211521
model: "local-model",
15221522
});
1523-
expect(source.apiKey).toBe(KEYLESS_API_KEY);
1523+
expect(source.credentialId).toBe(KEYLESS_API_KEY);
15241524
});
15251525
});
15261526

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

@@ -259,7 +259,7 @@ export function buildOpenAISource(fields: {
259259
baseURL: isOllamaProviderId(fields.id)
260260
? ollamaOpenAIBaseURL(fields.baseURL)
261261
: normalizeOpenAICompatibleBaseURL(fields.baseURL),
262-
apiKey:
262+
credentialId:
263263
fields.apiKey !== undefined && fields.apiKey.length > 0
264264
? fields.apiKey
265265
: KEYLESS_API_KEY,
@@ -338,7 +338,7 @@ export function buildCodexSource(fields: {
338338
id: fields.id,
339339
provider: CODEX_RESPONSES_PROVIDER,
340340
baseURL: CODEX_BASE_URL,
341-
apiKey: fields.apiKey,
341+
credentialId: fields.apiKey,
342342
model: fields.model,
343343
defaults: { maxTokens: SOURCE_MAX_TOKENS, providerOptions },
344344
};
@@ -368,7 +368,7 @@ export function buildXaiSource(fields: {
368368
id: fields.id,
369369
provider: GROK_RESPONSES_PROVIDER,
370370
baseURL: XAI_BASE_URL,
371-
apiKey: fields.apiKey,
371+
credentialId: fields.apiKey,
372372
model: fields.model,
373373
defaults: { maxTokens: SOURCE_MAX_TOKENS, providerOptions },
374374
};
@@ -392,7 +392,7 @@ export function buildBifrostSource(fields: {
392392
id: fields.id,
393393
provider: BIFROST_PROVIDER,
394394
baseURL: normalizeOpenAICompatibleBaseURL(fields.baseURL),
395-
apiKey:
395+
credentialId:
396396
fields.apiKey !== undefined && fields.apiKey.length > 0
397397
? fields.apiKey
398398
: KEYLESS_API_KEY,
@@ -412,7 +412,7 @@ export function buildAnthropicSource(fields: {
412412
id: fields.id,
413413
provider: "anthropic",
414414
baseURL: fields.baseURL.replace(/\/+$/, ""),
415-
apiKey:
415+
credentialId:
416416
fields.apiKey !== undefined && fields.apiKey.length > 0
417417
? fields.apiKey
418418
: KEYLESS_API_KEY,
@@ -440,7 +440,7 @@ export function buildGoSource(fields: {
440440
id: fields.id,
441441
provider: OPENCODE_GO_MESSAGES_PROVIDER,
442442
baseURL: endpoint.baseURL,
443-
apiKey,
443+
credentialId: apiKey,
444444
model: fields.model,
445445
defaults: {
446446
maxTokens: SOURCE_MAX_TOKENS,
@@ -455,7 +455,7 @@ export function buildGoSource(fields: {
455455
id: fields.id,
456456
provider: OPENAI_RESPONSES_PROVIDER,
457457
baseURL: endpoint.baseURL,
458-
apiKey,
458+
credentialId: apiKey,
459459
model: fields.model,
460460
defaults: {
461461
maxTokens: SOURCE_MAX_TOKENS,
@@ -509,7 +509,7 @@ export function buildZenSource(fields: {
509509
id: fields.id,
510510
provider: ZEN_MESSAGES_PROVIDER,
511511
baseURL: endpoint.baseURL,
512-
apiKey,
512+
credentialId: apiKey,
513513
model: fields.model,
514514
defaults: {
515515
maxTokens: SOURCE_MAX_TOKENS,
@@ -524,7 +524,7 @@ export function buildZenSource(fields: {
524524
id: fields.id,
525525
provider: OPENAI_RESPONSES_PROVIDER,
526526
baseURL: endpoint.baseURL,
527-
apiKey,
527+
credentialId: apiKey,
528528
model: fields.model,
529529
defaults: {
530530
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
@@ -772,7 +772,7 @@ export async function runExec(config: Config): Promise<ExecResult> {
772772
const { access } = await refreshSelectedProviderCredential(() =>
773773
getValidCodexToken(initialCodexProfile),
774774
);
775-
liveSource = { ...liveSource, apiKey: access };
775+
liveSource = { ...liveSource, credentialId: access };
776776
liveSubAgentProvider.current = {
777777
...liveSubAgentProvider.current,
778778
apiKey: access,
@@ -782,7 +782,7 @@ export async function runExec(config: Config): Promise<ExecResult> {
782782
const { access } = await refreshSelectedProviderCredential(() =>
783783
getValidXaiToken(initialXaiProfile),
784784
);
785-
liveSource = { ...liveSource, apiKey: access };
785+
liveSource = { ...liveSource, credentialId: access };
786786
liveSubAgentProvider.current = {
787787
...liveSubAgentProvider.current,
788788
apiKey: access,
@@ -802,7 +802,7 @@ export async function runExec(config: Config): Promise<ExecResult> {
802802
liveSource,
803803
config.providers,
804804
);
805-
if (fresh.apiKey === liveSource.apiKey) return;
805+
if (fresh.credentialId === liveSource.credentialId) return;
806806
liveSource = fresh;
807807
if (currentAgent !== null)
808808
setAgentSourceUnlessClosed(currentAgent, fresh);
@@ -861,7 +861,9 @@ export async function runExec(config: Config): Promise<ExecResult> {
861861
const sources = liveSources.length > 0 ? liveSources : [liveSource];
862862
// Prefer liveSource credentials on the active id when OAuth was refreshed.
863863
return sources.map((s) =>
864-
s.id === liveSource.id ? { ...s, apiKey: liveSource.apiKey } : s,
864+
s.id === liveSource.id
865+
? { ...s, credentialId: liveSource.credentialId }
866+
: s,
865867
);
866868
},
867869
getDefaultSource: () =>
@@ -1005,15 +1007,15 @@ export async function runExec(config: Config): Promise<ExecResult> {
10051007
// Final OAuth refresh immediately before send (token may have aged during MCP).
10061008
if (initialCodexProfile !== undefined) {
10071009
const { access } = await getValidCodexToken(initialCodexProfile);
1008-
if (access !== liveSource.apiKey) {
1009-
liveSource = { ...liveSource, apiKey: access };
1010+
if (access !== liveSource.credentialId) {
1011+
liveSource = { ...liveSource, credentialId: access };
10101012
setAgentSourceUnlessClosed(activeAgent, liveSource);
10111013
}
10121014
}
10131015
if (initialXaiProfile !== undefined) {
10141016
const { access } = await getValidXaiToken(initialXaiProfile);
1015-
if (access !== liveSource.apiKey) {
1016-
liveSource = { ...liveSource, apiKey: access };
1017+
if (access !== liveSource.credentialId) {
1018+
liveSource = { ...liveSource, credentialId: access };
10171019
setAgentSourceUnlessClosed(activeAgent, liveSource);
10181020
}
10191021
}

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)