@sagentlab/navarch-runtime 0.1.143 → 0.1.144
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.
|
@@ -225,9 +225,11 @@ class ConversationLoop {
|
|
|
225
225
|
...(shutdownSignal ? { signal: shutdownSignal } : {}),
|
|
226
226
|
...this.options.turnOverrides,
|
|
227
227
|
log: this.log,
|
|
228
|
-
prepareWorkspace: async ({ conversationId, repositoryUrl, workingBranch, mode, signal }) => {
|
|
228
|
+
prepareWorkspace: async ({ conversationId, repositoryUrl, workingBranch, gitCredential, mode, signal }) => {
|
|
229
|
+
if (!gitCredential)
|
|
230
|
+
throw new Error("Control plane did not provide the conversation Git credential");
|
|
229
231
|
const workspace = await (0, workspace_cjs_1.prepareConversationWorkspace)({
|
|
230
|
-
workspaceRoot: config.workspaceRoot, conversationId, repositoryUrl, workingBranch, env, signal, mode,
|
|
232
|
+
workspaceRoot: config.workspaceRoot, conversationId, repositoryUrl, workingBranch, gitCredential, env, signal, mode,
|
|
231
233
|
...(this.options.gitRunner ? { runner: this.options.gitRunner } : {}),
|
|
232
234
|
...(this.mirrors ? { mirrors: this.mirrors } : {}),
|
|
233
235
|
});
|
|
@@ -300,7 +300,7 @@ async function runConversationTurn(deps, conversationId, turnId) {
|
|
|
300
300
|
prompt = (0, prompt_cjs_1.buildConversationPrompt)(snapshot, journal.turnId, deps.adapter.agentType === "codex");
|
|
301
301
|
// Older servers omit the working branch: the checkout stays on the default branch.
|
|
302
302
|
const workingBranch = (0, workspace_cjs_1.validWorkingBranch)(claim.workingBranch);
|
|
303
|
-
prepared = await deps.prepareWorkspace({ conversationId, repositoryUrl, workingBranch, mode: snapshot.mode ?? "read_only", signal: controller.signal });
|
|
303
|
+
prepared = await deps.prepareWorkspace({ conversationId, repositoryUrl, workingBranch, gitCredential: claim.gitCredential, mode: snapshot.mode ?? "read_only", signal: controller.signal });
|
|
304
304
|
}
|
|
305
305
|
catch (error) {
|
|
306
306
|
if (!run.lost)
|
|
@@ -76,9 +76,8 @@ function conversationRoot(workspaceRoot, conversationId) {
|
|
|
76
76
|
* The first turn clones; later turns of the same conversation reuse the
|
|
77
77
|
* checkout so a follow-up sees the same revision as the first answer.
|
|
78
78
|
*
|
|
79
|
-
* The
|
|
80
|
-
*
|
|
81
|
-
* A repository this machine cannot read fails the turn instead of falling back.
|
|
79
|
+
* The control plane's project credential is used only by Git checkout subprocesses.
|
|
80
|
+
* It never enters the checkout URL, git config, journal or agent environment.
|
|
82
81
|
* With `mirrors`, a new checkout is seeded from this machine's refreshed
|
|
83
82
|
* mirror of the repository instead of a full network clone (see mirror.cts).
|
|
84
83
|
*/
|
|
@@ -127,15 +126,36 @@ async function prepareConversationWorkspace(options) {
|
|
|
127
126
|
GIT_CONFIG_COUNT: "1",
|
|
128
127
|
GIT_CONFIG_KEY_0: "core.hooksPath",
|
|
129
128
|
GIT_CONFIG_VALUE_0: process.platform === "win32" ? "NUL" : "/dev/null",
|
|
129
|
+
...(options.gitCredential ? {
|
|
130
|
+
NAVARCH_CONVERSATION_GIT_TOKEN: options.gitCredential,
|
|
131
|
+
GIT_CONFIG_COUNT: "5",
|
|
132
|
+
GIT_CONFIG_KEY_1: "credential.helper", GIT_CONFIG_VALUE_1: "",
|
|
133
|
+
GIT_CONFIG_KEY_2: `credential.${url}.helper`,
|
|
134
|
+
GIT_CONFIG_VALUE_2: `!f() { if [ "$1" = get ]; then printf '%s\\n' 'username=x-access-token' "password=$NAVARCH_CONVERSATION_GIT_TOKEN"; fi; }; f`,
|
|
135
|
+
GIT_CONFIG_KEY_3: "credential.useHttpPath", GIT_CONFIG_VALUE_3: "true",
|
|
136
|
+
GIT_CONFIG_KEY_4: "http.followRedirects", GIT_CONFIG_VALUE_4: "false",
|
|
137
|
+
} : {}),
|
|
130
138
|
};
|
|
131
|
-
|
|
139
|
+
let seeded;
|
|
140
|
+
try {
|
|
141
|
+
seeded = await options.mirrors?.seedCheckout({ url, branch, checkout: workspace.checkout, env, signal: options.signal }) ?? false;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
throw new Error("Conversation git mirror checkout could not run");
|
|
145
|
+
}
|
|
132
146
|
if (!seeded) {
|
|
133
|
-
|
|
147
|
+
let result;
|
|
148
|
+
try {
|
|
149
|
+
result = await runner.run("git", ["clone", "--quiet", "--filter=blob:none", "--no-tags", ...(branch ? ["--branch", branch] : []), "--", url, workspace.checkout], { cwd: root, env, timeoutMs: CLONE_TIMEOUT_MS, signal: options.signal });
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// A command runner or credential helper can put secrets in an exception.
|
|
153
|
+
throw new Error("Conversation git clone could not run");
|
|
154
|
+
}
|
|
134
155
|
if (result.code !== 0) {
|
|
135
156
|
await node_fs_1.promises.rm(workspace.checkout, { recursive: true, force: true }).catch(() => undefined);
|
|
136
|
-
throw new Error(`git clone failed with exit ${result.code}
|
|
157
|
+
throw new Error(`git clone failed with exit ${result.code}; check the project's GitHub connection and repository access`);
|
|
137
158
|
}
|
|
138
|
-
// This machine can read the repository: build the mirror for the next conversation.
|
|
139
159
|
void options.mirrors?.warm(url, env, options.signal);
|
|
140
160
|
}
|
|
141
161
|
await node_fs_1.promises.writeFile(marker, identity, { encoding: "utf8", mode: 0o600 });
|
package/package.json
CHANGED