orizu 0.5.48 → 0.5.50
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.
- package/dist/account-directory.d.ts +2 -2
- package/dist/account-directory.d.ts.map +1 -1
- package/dist/account-directory.js +7 -32
- package/dist/auth-commands.d.ts.map +1 -1
- package/dist/auth-commands.js +22 -30
- package/dist/credentials.d.ts +5 -0
- package/dist/credentials.d.ts.map +1 -1
- package/dist/credentials.js +84 -3
- package/dist/dataset-transfer-upload.d.ts.map +1 -1
- package/dist/dataset-transfer-upload.js +6 -1
- package/dist/directory-list-read.d.ts +37 -0
- package/dist/directory-list-read.d.ts.map +1 -0
- package/dist/directory-list-read.js +87 -0
- package/dist/hosted-boot.d.ts.map +1 -1
- package/dist/hosted-boot.js +59 -41
- package/dist/hosted-harness-opencode.d.ts +31 -0
- package/dist/hosted-harness-opencode.d.ts.map +1 -1
- package/dist/hosted-harness-opencode.js +45 -7
- package/dist/hosted-loop.d.ts +39 -2
- package/dist/hosted-loop.d.ts.map +1 -1
- package/dist/hosted-loop.js +127 -18
- package/dist/hosted-optimization.d.ts.map +1 -1
- package/dist/hosted-optimization.js +40 -21
- package/dist/hosted-session-seed.d.ts +2 -0
- package/dist/hosted-session-seed.d.ts.map +1 -1
- package/dist/hosted-session-seed.js +27 -10
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +39 -234
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +83 -68
- package/dist/keyboard-select.d.ts.map +1 -1
- package/dist/keyboard-select.js +23 -45
- package/dist/project-create-workflow.d.ts +18 -0
- package/dist/project-create-workflow.d.ts.map +1 -0
- package/dist/project-create-workflow.js +121 -0
- package/dist/runner-folders.d.ts +61 -0
- package/dist/runner-folders.d.ts.map +1 -0
- package/dist/runner-folders.js +222 -0
- package/dist/runner-version-materialization.d.ts +1 -1
- package/dist/runner-version-materialization.d.ts.map +1 -1
- package/dist/runner-version-materialization.js +20 -38
- package/dist/self-update-command.d.ts +8 -0
- package/dist/self-update-command.d.ts.map +1 -0
- package/dist/self-update-command.js +390 -0
- package/dist/self-update.d.ts +29 -16
- package/dist/self-update.d.ts.map +1 -1
- package/dist/self-update.js +55 -244
- package/dist/setup-account.d.ts.map +1 -1
- package/dist/setup-account.js +4 -1
- package/dist/setup-and-skills-commands.d.ts.map +1 -1
- package/dist/setup-and-skills-commands.js +88 -102
- package/dist/skill-install-workflow.d.ts +23 -0
- package/dist/skill-install-workflow.d.ts.map +1 -0
- package/dist/skill-install-workflow.js +184 -0
- package/dist/skill-installer.d.ts +8 -3
- package/dist/skill-installer.d.ts.map +1 -1
- package/dist/skill-installer.js +26 -33
- package/dist/skilled-proposer-launch.d.ts +11 -1
- package/dist/skilled-proposer-launch.d.ts.map +1 -1
- package/dist/skilled-proposer-launch.js +35 -4
- package/dist/stored-session-requests.d.ts +27 -0
- package/dist/stored-session-requests.d.ts.map +1 -0
- package/dist/stored-session-requests.js +264 -0
- package/dist/terminal-key-session.d.ts +23 -0
- package/dist/terminal-key-session.d.ts.map +1 -0
- package/dist/terminal-key-session.js +74 -0
- package/package.json +1 -1
- package/scripts/build-cli-dist.mjs +46 -8
- package/scripts/vendor-orizu-skill.mjs +52 -7
- package/src/account-directory.ts +8 -42
- package/src/auth-commands.ts +20 -29
- package/src/credentials.ts +83 -3
- package/src/dataset-transfer-upload.ts +7 -1
- package/src/directory-list-read.ts +123 -0
- package/src/hosted-boot.ts +65 -43
- package/src/hosted-harness-opencode.ts +65 -9
- package/src/hosted-loop.ts +152 -18
- package/src/hosted-optimization.ts +49 -31
- package/src/hosted-session-seed.ts +25 -8
- package/src/http.ts +39 -317
- package/src/index.ts +79 -87
- package/src/keyboard-select.ts +18 -55
- package/src/project-create-workflow.ts +139 -0
- package/src/runner-folders.ts +223 -0
- package/src/runner-version-materialization.ts +21 -34
- package/src/self-update-command.ts +419 -0
- package/src/self-update.ts +70 -266
- package/src/setup-account.ts +4 -1
- package/src/setup-and-skills-commands.ts +89 -121
- package/src/skill-install-workflow.ts +215 -0
- package/src/skill-installer.ts +31 -38
- package/src/skilled-proposer-launch.ts +41 -3
- package/src/stored-session-requests.ts +316 -0
- package/src/terminal-key-session.ts +88 -0
package/dist/hosted-boot.js
CHANGED
|
@@ -35,7 +35,7 @@ import { closeSync, existsSync, mkdirSync, openSync, readdirSync, readFileSync,
|
|
|
35
35
|
import { isValidCloudflareArtifactsGitRemote } from './cloudflare-artifacts-git-remote.js';
|
|
36
36
|
import { cloneTeamIntoWorkTree, seedSessionCopy } from './hosted-session-seed.js';
|
|
37
37
|
import { AGENT_GIT_IDENTITY, BEARER_BASENAME, BOOT_CONTEXT_BASENAME, DEFAULT_CACHE_REFRESH_BUFFER_MS, HELPER_SCRIPT_BASENAME, REPO_CRED_CACHE_BASENAME, renderCredentialHelperScript, serializeBootContext, } from './hosted-runtime-assets.js';
|
|
38
|
-
import { INJECTED_ENV_VARS_ENV, closeHostedLoopSession, runHostedLoop, runHostedLoopTurn, startHostedLoopSession, } from './hosted-loop.js';
|
|
38
|
+
import { INJECTED_ENV_VARS_ENV, closeHostedLoopSession, hostedSessionOpenCodeLogPath, prestartHostedOpenCode, runHostedLoop, runHostedLoopTurn, startHostedLoopSession, } from './hosted-loop.js';
|
|
39
39
|
import { DEFAULT_EGRESS_CANARY_HOST, DEFAULT_HOSTED_MODEL } from './hosted-loop-lifecycle.js';
|
|
40
40
|
import { composeHostedAnswerPrompt } from './hosted-question.js';
|
|
41
41
|
import { resumeRunEventSink } from './hosted-run-event-sink.js';
|
|
@@ -675,16 +675,20 @@ export async function runHostedBoot(opts) {
|
|
|
675
675
|
// work and closed however the boot ends.
|
|
676
676
|
const liveChannels = [];
|
|
677
677
|
const idleWait = new AbortController();
|
|
678
|
+
// ORI-2512: stops anything the boot started in the background.
|
|
679
|
+
const bootCleanups = [];
|
|
678
680
|
try {
|
|
679
|
-
return await runHostedBootWithLive(opts, liveChannels, idleWait.signal);
|
|
681
|
+
return await runHostedBootWithLive(opts, liveChannels, idleWait.signal, bootCleanups);
|
|
680
682
|
}
|
|
681
683
|
finally {
|
|
682
684
|
idleWait.abort();
|
|
683
685
|
for (const channel of liveChannels)
|
|
684
686
|
channel.close();
|
|
687
|
+
for (const cleanup of bootCleanups)
|
|
688
|
+
cleanup();
|
|
685
689
|
}
|
|
686
690
|
}
|
|
687
|
-
async function runHostedBootWithLive(opts, liveChannels, idleWaitSignal) {
|
|
691
|
+
async function runHostedBootWithLive(opts, liveChannels, idleWaitSignal, bootCleanups) {
|
|
688
692
|
const env = opts.env;
|
|
689
693
|
const processEnv = opts.processEnv ?? process.env;
|
|
690
694
|
const root = opts.root ?? process.cwd();
|
|
@@ -913,6 +917,43 @@ async function runHostedBootWithLive(opts, liveChannels, idleWaitSignal) {
|
|
|
913
917
|
};
|
|
914
918
|
writeFile(bootContextAbs, serializeBootContext(bootContext));
|
|
915
919
|
const helperValue = `!node ${helperScriptAbs} ${bootContextAbs}`;
|
|
920
|
+
// The loop's context (step 6), built before the clone so the background
|
|
921
|
+
// start below uses the same settings. The bearer PROVIDER keeps the event
|
|
922
|
+
// sink's bearer fresh from the same pull-mode source; the DO-provisioned
|
|
923
|
+
// sandbox always runs the pre-baked image under an enforced egress policy, so
|
|
924
|
+
// the loop's startup egress canary + deferred setup hook are both armed.
|
|
925
|
+
const model = session.model ?? DEFAULT_HOSTED_MODEL;
|
|
926
|
+
const configuredOpenCodePort = resolveTestPositiveInteger(processEnv, 'ORIZU_HOSTED_TEST_OPENCODE_PORT', 65_535) ?? (processEnv.ORIZU_OPENCODE_PORT
|
|
927
|
+
? Number(processEnv.ORIZU_OPENCODE_PORT)
|
|
928
|
+
: undefined);
|
|
929
|
+
if (configuredOpenCodePort !== undefined && (!Number.isInteger(configuredOpenCodePort) || configuredOpenCodePort < 1 || configuredOpenCodePort > 65_535)) {
|
|
930
|
+
throw new Error('ORIZU_OPENCODE_PORT must be a valid TCP port');
|
|
931
|
+
}
|
|
932
|
+
const loopContext = {
|
|
933
|
+
apiBaseUrl: env.baseUrl,
|
|
934
|
+
runId,
|
|
935
|
+
bearerFile: bearerFileAbs,
|
|
936
|
+
taskFile: taskFileAbs,
|
|
937
|
+
workspaceDir,
|
|
938
|
+
sessionBranch: session.repoBranch,
|
|
939
|
+
repositoryRemote: repo.cloneUrl,
|
|
940
|
+
repositoryCredentialHelper: helperValue,
|
|
941
|
+
model,
|
|
942
|
+
reasoningEffort: session.reasoningEffort ?? undefined,
|
|
943
|
+
sessionOrigin: session.surface === 'hosted-web' ? 'hosted-web' : 'cli',
|
|
944
|
+
messageId: `${runId}:task`,
|
|
945
|
+
resumeAgentSessionId: session.agentSessionId ?? undefined,
|
|
946
|
+
author: AGENT_GIT_IDENTITY,
|
|
947
|
+
anthropicDummyKey: env.anthropicDummyKey ?? ANTHROPIC_DUMMY_KEY,
|
|
948
|
+
// Derive the per-prompt max-duration cap from the session duration so a long
|
|
949
|
+
// run is not killed at the hard-coded 90-min prompt cap (ALI-1061). Unset →
|
|
950
|
+
// the harness default (5400s) floor holds.
|
|
951
|
+
sandboxBudgetMs: session.durationMinutes != null ? session.durationMinutes * 60 * 1000 : undefined,
|
|
952
|
+
prebaked: true,
|
|
953
|
+
egressCanaryHost: (processEnv.NODE_ENV === 'test' ? processEnv.ORIZU_HOSTED_TEST_EGRESS_CANARY_HOST : undefined) ?? DEFAULT_EGRESS_CANARY_HOST,
|
|
954
|
+
runSetupHook: true,
|
|
955
|
+
opencodePort: configuredOpenCodePort,
|
|
956
|
+
};
|
|
916
957
|
// 4b — ORI-2118: a hosted session's Artifacts copy is created empty (forks
|
|
917
958
|
// of a busy team copy cannot be cloned). Fill it from the server-selected
|
|
918
959
|
// origin before cloning. Selected saved history is checked on retries too.
|
|
@@ -921,6 +962,18 @@ async function runHostedBootWithLive(opts, liveChannels, idleWaitSignal) {
|
|
|
921
962
|
}
|
|
922
963
|
// ORI-2520: a woken sandbox boots on the disk it slept with (see step 5).
|
|
923
964
|
const wokenDisk = existsSync(workspaceDir) && readdirSync(workspaceDir).length > 0;
|
|
965
|
+
// ORI-2512 cut 3: start the egress canary and then OpenCode while the
|
|
966
|
+
// repository clones. OpenCode runs in the (empty) working folder, which the
|
|
967
|
+
// clone fills in place, and is asked nothing until after the clone. The
|
|
968
|
+
// one-shot test seam (opts.runLoop) starts nothing early, but makes the
|
|
969
|
+
// folder the same way, so it takes production's fill.
|
|
970
|
+
mkdirp(workspaceDir);
|
|
971
|
+
const prestart = opts.runLoop
|
|
972
|
+
? null
|
|
973
|
+
: prestartHostedOpenCode({ ...loopContext, projectId: session.projectId }, { logPath: hostedSessionOpenCodeLogPath({ sessionDir: sessionDirAbs, sessionId: env.sessionId }) });
|
|
974
|
+
// However the boot ends, nothing it started outlives it.
|
|
975
|
+
if (prestart)
|
|
976
|
+
bootCleanups.push(prestart.stop);
|
|
924
977
|
// Set when the working folder came from the team copy (ORI-2512); settles
|
|
925
978
|
// when the background fill of the session copy ends, and never rejects.
|
|
926
979
|
let sessionCopyFilled = null;
|
|
@@ -1053,7 +1106,8 @@ const c = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
|
|
|
1053
1106
|
log(`woken disk: reusing the repo (checked out: ${checkedOut})`);
|
|
1054
1107
|
}
|
|
1055
1108
|
else {
|
|
1056
|
-
|
|
1109
|
+
// Not blocking, so the background start above keeps running (ORI-2512).
|
|
1110
|
+
const clone = await execAsync('git', [
|
|
1057
1111
|
'clone',
|
|
1058
1112
|
'--depth',
|
|
1059
1113
|
'1',
|
|
@@ -1126,42 +1180,6 @@ const c = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
|
|
|
1126
1180
|
fetchImpl,
|
|
1127
1181
|
log,
|
|
1128
1182
|
});
|
|
1129
|
-
// 6 — Launch the hosted loop, reused in-process. The bearer PROVIDER keeps the
|
|
1130
|
-
// event sink's bearer fresh from the same pull-mode source; the DO-provisioned
|
|
1131
|
-
// sandbox always runs the pre-baked image under an enforced egress policy, so
|
|
1132
|
-
// the loop's startup egress canary + deferred setup hook are both armed.
|
|
1133
|
-
const model = session.model ?? DEFAULT_HOSTED_MODEL;
|
|
1134
|
-
const configuredOpenCodePort = resolveTestPositiveInteger(processEnv, 'ORIZU_HOSTED_TEST_OPENCODE_PORT', 65_535) ?? (processEnv.ORIZU_OPENCODE_PORT
|
|
1135
|
-
? Number(processEnv.ORIZU_OPENCODE_PORT)
|
|
1136
|
-
: undefined);
|
|
1137
|
-
if (configuredOpenCodePort !== undefined && (!Number.isInteger(configuredOpenCodePort) || configuredOpenCodePort < 1 || configuredOpenCodePort > 65_535)) {
|
|
1138
|
-
throw new Error('ORIZU_OPENCODE_PORT must be a valid TCP port');
|
|
1139
|
-
}
|
|
1140
|
-
const loopContext = {
|
|
1141
|
-
apiBaseUrl: env.baseUrl,
|
|
1142
|
-
runId,
|
|
1143
|
-
bearerFile: bearerFileAbs,
|
|
1144
|
-
taskFile: taskFileAbs,
|
|
1145
|
-
workspaceDir,
|
|
1146
|
-
sessionBranch: session.repoBranch,
|
|
1147
|
-
repositoryRemote: repo.cloneUrl,
|
|
1148
|
-
repositoryCredentialHelper: helperValue,
|
|
1149
|
-
model,
|
|
1150
|
-
reasoningEffort: session.reasoningEffort ?? undefined,
|
|
1151
|
-
sessionOrigin: session.surface === 'hosted-web' ? 'hosted-web' : 'cli',
|
|
1152
|
-
messageId: `${runId}:task`,
|
|
1153
|
-
resumeAgentSessionId: session.agentSessionId ?? undefined,
|
|
1154
|
-
author: AGENT_GIT_IDENTITY,
|
|
1155
|
-
anthropicDummyKey: env.anthropicDummyKey ?? ANTHROPIC_DUMMY_KEY,
|
|
1156
|
-
// Derive the per-prompt max-duration cap from the session duration so a long
|
|
1157
|
-
// run is not killed at the hard-coded 90-min prompt cap (ALI-1061). Unset →
|
|
1158
|
-
// the harness default (5400s) floor holds.
|
|
1159
|
-
sandboxBudgetMs: session.durationMinutes != null ? session.durationMinutes * 60 * 1000 : undefined,
|
|
1160
|
-
prebaked: true,
|
|
1161
|
-
egressCanaryHost: DEFAULT_EGRESS_CANARY_HOST,
|
|
1162
|
-
runSetupHook: true,
|
|
1163
|
-
opencodePort: configuredOpenCodePort,
|
|
1164
|
-
};
|
|
1165
1183
|
const runLoop = opts.runLoop ??
|
|
1166
1184
|
((input) => runHostedLoop({
|
|
1167
1185
|
context: input.context,
|
|
@@ -1207,7 +1225,7 @@ const c = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
|
|
|
1207
1225
|
projectId: session.projectId,
|
|
1208
1226
|
sessionDir: sessionDirAbs,
|
|
1209
1227
|
};
|
|
1210
|
-
const hostedLoopSession = await startHostedLoopSession(sessionContext);
|
|
1228
|
+
const hostedLoopSession = await startHostedLoopSession(sessionContext, { prestart });
|
|
1211
1229
|
let current = session.pendingTurn?.runId === runId
|
|
1212
1230
|
? { runId, ordinal: session.pendingTurn.ordinal, body: promptForPendingHostedTurn(session.pendingTurn) }
|
|
1213
1231
|
: { runId, ordinal: 1, body: session.task };
|
|
@@ -195,6 +195,8 @@ export interface SpawnOpenCodeOptions extends OpenCodeConfigOptions {
|
|
|
195
195
|
logPath?: string;
|
|
196
196
|
}) => {
|
|
197
197
|
kill: () => void;
|
|
198
|
+
hasExited?: () => boolean;
|
|
199
|
+
exitReason?: () => string | null;
|
|
198
200
|
};
|
|
199
201
|
/** File the spawner should append opencode's stdout/stderr to. On readiness
|
|
200
202
|
* timeout its tail is included in the thrown error — the bare "fetch failed"
|
|
@@ -230,4 +232,33 @@ export interface SpawnedOpenCode {
|
|
|
230
232
|
* (see the SSE-fragility note on that constant).
|
|
231
233
|
*/
|
|
232
234
|
export declare function spawnOpenCode(opts: SpawnOpenCodeOptions): Promise<SpawnedOpenCode>;
|
|
235
|
+
/** A started `opencode serve` that has not been asked anything yet. */
|
|
236
|
+
export interface StartedOpenCode {
|
|
237
|
+
baseUrl: string;
|
|
238
|
+
port: number;
|
|
239
|
+
stop: () => void;
|
|
240
|
+
/** True once the process has exited (when the spawner can tell). */
|
|
241
|
+
hasExited: () => boolean;
|
|
242
|
+
/** Why it could not be started (for example ENOENT), when known. */
|
|
243
|
+
exitReason: () => string | null;
|
|
244
|
+
startedAt: number;
|
|
245
|
+
}
|
|
246
|
+
/** `waitOpenCodeReady` found the process already gone; nothing answered. */
|
|
247
|
+
export declare class OpenCodeExitedError extends Error {
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* The first half of `spawnOpenCode`: refresh the model catalog and start the
|
|
251
|
+
* process, without asking it anything. ORI-2512: the hosted boot calls this
|
|
252
|
+
* while the repository is still cloning. OpenCode ties its folder to a project
|
|
253
|
+
* on the first request it gets, so nothing may ask it anything until the
|
|
254
|
+
* folder holds the repository (measured on 1.18.35: a request into an empty
|
|
255
|
+
* folder binds it to the `global` project for good).
|
|
256
|
+
*/
|
|
257
|
+
export declare function startOpenCodeProcess(opts: SpawnOpenCodeOptions): Promise<StartedOpenCode>;
|
|
258
|
+
/**
|
|
259
|
+
* The second half of `spawnOpenCode`: poll until the started server answers.
|
|
260
|
+
* The budget counts from this call, not from the start, so a long clone
|
|
261
|
+
* before it cannot use the budget up. `readyAfterMs` is from the start.
|
|
262
|
+
*/
|
|
263
|
+
export declare function waitOpenCodeReady(started: StartedOpenCode, opts: Pick<SpawnOpenCodeOptions, 'readyTimeoutMs' | 'readyPollMs' | 'signal' | 'fetchImpl' | 'logPath'>): Promise<SpawnedOpenCode>;
|
|
233
264
|
//# sourceMappingURL=hosted-harness-opencode.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hosted-harness-opencode.d.ts","sourceRoot":"","sources":["../src/hosted-harness-opencode.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"hosted-harness-opencode.d.ts","sourceRoot":"","sources":["../src/hosted-harness-opencode.ts"],"names":[],"mappings":"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"}
|
|
@@ -1035,6 +1035,20 @@ function readLogTail(logPath) {
|
|
|
1035
1035
|
* (see the SSE-fragility note on that constant).
|
|
1036
1036
|
*/
|
|
1037
1037
|
export async function spawnOpenCode(opts) {
|
|
1038
|
+
return waitOpenCodeReady(await startOpenCodeProcess(opts), opts);
|
|
1039
|
+
}
|
|
1040
|
+
/** `waitOpenCodeReady` found the process already gone; nothing answered. */
|
|
1041
|
+
export class OpenCodeExitedError extends Error {
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* The first half of `spawnOpenCode`: refresh the model catalog and start the
|
|
1045
|
+
* process, without asking it anything. ORI-2512: the hosted boot calls this
|
|
1046
|
+
* while the repository is still cloning. OpenCode ties its folder to a project
|
|
1047
|
+
* on the first request it gets, so nothing may ask it anything until the
|
|
1048
|
+
* folder holds the repository (measured on 1.18.35: a request into an empty
|
|
1049
|
+
* folder binds it to the `global` project for good).
|
|
1050
|
+
*/
|
|
1051
|
+
export async function startOpenCodeProcess(opts) {
|
|
1038
1052
|
const port = opts.port ?? DEFAULT_OPENCODE_PORT;
|
|
1039
1053
|
const env = {
|
|
1040
1054
|
OPENCODE_CONFIG_CONTENT: buildOpenCodeConfigContent(opts),
|
|
@@ -1059,14 +1073,29 @@ export async function spawnOpenCode(opts) {
|
|
|
1059
1073
|
});
|
|
1060
1074
|
});
|
|
1061
1075
|
const child = spawnImpl(cmd, { cwd: opts.cwd, env, logPath: opts.logPath });
|
|
1062
|
-
|
|
1076
|
+
return {
|
|
1077
|
+
baseUrl: `http://localhost:${port}`,
|
|
1078
|
+
port,
|
|
1079
|
+
stop: () => child.kill(),
|
|
1080
|
+
hasExited: () => child.hasExited?.() ?? false,
|
|
1081
|
+
exitReason: () => child.exitReason?.() ?? null,
|
|
1082
|
+
startedAt: Date.now(),
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* The second half of `spawnOpenCode`: poll until the started server answers.
|
|
1087
|
+
* The budget counts from this call, not from the start, so a long clone
|
|
1088
|
+
* before it cannot use the budget up. `readyAfterMs` is from the start.
|
|
1089
|
+
*/
|
|
1090
|
+
export async function waitOpenCodeReady(started, opts) {
|
|
1091
|
+
const { baseUrl, port } = started;
|
|
1063
1092
|
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
1064
1093
|
const timeoutMs = opts.readyTimeoutMs ?? OPENCODE_READY_TIMEOUT_MS;
|
|
1065
1094
|
const pollMs = opts.readyPollMs ?? OPENCODE_READY_POLL_MS;
|
|
1066
|
-
const
|
|
1095
|
+
const waitStartedAt = Date.now();
|
|
1067
1096
|
for (;;) {
|
|
1068
1097
|
if (opts.signal?.aborted) {
|
|
1069
|
-
|
|
1098
|
+
started.stop();
|
|
1070
1099
|
throw new Error('opencode serve readiness wait aborted');
|
|
1071
1100
|
}
|
|
1072
1101
|
try {
|
|
@@ -1086,17 +1115,26 @@ export async function spawnOpenCode(opts) {
|
|
|
1086
1115
|
}
|
|
1087
1116
|
}
|
|
1088
1117
|
catch {
|
|
1089
|
-
// not listening yet — fall through to the timeout
|
|
1118
|
+
// not listening yet — fall through to the exit and timeout checks + sleep
|
|
1119
|
+
}
|
|
1120
|
+
// A process that already exited will never answer: say so now rather
|
|
1121
|
+
// than at the end of the budget.
|
|
1122
|
+
if (started.hasExited()) {
|
|
1123
|
+
const tail = readLogTail(opts.logPath);
|
|
1124
|
+
const reason = started.exitReason();
|
|
1125
|
+
throw new OpenCodeExitedError(`opencode serve exited before it answered on ${baseUrl}` +
|
|
1126
|
+
(reason ? `: ${reason}` : '') +
|
|
1127
|
+
(tail ? ` — log tail: ${tail}` : ' (no log output captured)'));
|
|
1090
1128
|
}
|
|
1091
1129
|
// Soft budget: checked between probes, so the total wait can overrun by up
|
|
1092
1130
|
// to one probe timeout + poll interval. Negligible against the default.
|
|
1093
|
-
if (Date.now() -
|
|
1094
|
-
|
|
1131
|
+
if (Date.now() - waitStartedAt >= timeoutMs) {
|
|
1132
|
+
started.stop();
|
|
1095
1133
|
const tail = readLogTail(opts.logPath);
|
|
1096
1134
|
throw new Error(`opencode serve did not become ready on ${baseUrl} within ${timeoutMs}ms` +
|
|
1097
1135
|
(tail ? ` — log tail: ${tail}` : ' (no log output captured)'));
|
|
1098
1136
|
}
|
|
1099
1137
|
await new Promise(resolve => setTimeout(resolve, pollMs));
|
|
1100
1138
|
}
|
|
1101
|
-
return { baseUrl, port, stop:
|
|
1139
|
+
return { baseUrl, port, stop: started.stop, readyAfterMs: Date.now() - started.startedAt };
|
|
1102
1140
|
}
|
package/dist/hosted-loop.d.ts
CHANGED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
*/
|
|
37
37
|
import { type AgentHarness } from './hosted-harness.js';
|
|
38
38
|
import { type HarvestExec } from './hosted-harvest.js';
|
|
39
|
-
import { type ModelValidationOutcome, type SpawnOpenCodeOptions, type SpawnedOpenCode } from './hosted-harness-opencode.js';
|
|
39
|
+
import { type ModelValidationOutcome, type SpawnOpenCodeOptions, type SpawnedOpenCode, type StartedOpenCode } from './hosted-harness-opencode.js';
|
|
40
40
|
import { type HostedFetch, type LiveTextSnapshot, type TerminalStatus } from './hosted-run-event-sink.js';
|
|
41
41
|
import { type EgressProbeResult, type HostedLoopContext, type SetupHookOutcome } from './hosted-loop-lifecycle.js';
|
|
42
42
|
export { DEFAULT_EGRESS_CANARY_HOST, DEFAULT_HOSTED_MODEL, buildOpenCodeSpawnEnv, egressCanaryAllowedHost, runEgressCanary, } from './hosted-loop-lifecycle.js';
|
|
@@ -61,6 +61,28 @@ interface HostedLoopSharedRuntime {
|
|
|
61
61
|
startupComplete: boolean;
|
|
62
62
|
spawnLogPath: string;
|
|
63
63
|
closed: boolean;
|
|
64
|
+
/** ORI-2512: the boot's background start, until the first turn takes it. */
|
|
65
|
+
prestart?: HostedPrestart | null;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* ORI-2512 cut 3: the egress canary's probes and the OpenCode start, begun by
|
|
69
|
+
* the boot while the repository clones. The first turn records the canary's
|
|
70
|
+
* events from the stored answers (same decision, same events) and waits for
|
|
71
|
+
* the started server, which is asked nothing before then.
|
|
72
|
+
*/
|
|
73
|
+
export interface HostedPrestart {
|
|
74
|
+
/** The probes' answers by host, and the canary's verdict. Null when a
|
|
75
|
+
* probe threw: the turn then runs the canary itself. Never rejects. */
|
|
76
|
+
canary: Promise<{
|
|
77
|
+
results: Map<string, EgressProbeResult>;
|
|
78
|
+
checkedAt: number;
|
|
79
|
+
proceed: boolean;
|
|
80
|
+
} | null>;
|
|
81
|
+
/** The started process; null when the canary said no or the start was
|
|
82
|
+
* stopped. Rejects when the background start failed. */
|
|
83
|
+
opencode: Promise<StartedOpenCode | null>;
|
|
84
|
+
/** Stop the process, now or as soon as it starts. */
|
|
85
|
+
stop: () => void;
|
|
64
86
|
}
|
|
65
87
|
export interface HostedLoopSessionContext extends Omit<HostedLoopContext, 'runId' | 'bearerFile' | 'taskFile' | 'messageId'> {
|
|
66
88
|
sessionId: string;
|
|
@@ -206,8 +228,23 @@ export { INJECTED_ENV_VARS_ENV } from './hosted-environment.js';
|
|
|
206
228
|
* allows that one script and the result must print the pinned version
|
|
207
229
|
* (ORI-2523). `env` exists for tests. */
|
|
208
230
|
export declare function installOpenCodePinned(version: string, env?: NodeJS.ProcessEnv): InstallResult;
|
|
231
|
+
/**
|
|
232
|
+
* ORI-2512 cut 3: start the egress canary and then OpenCode in the
|
|
233
|
+
* background, for the boot to call before it clones. The order is the
|
|
234
|
+
* loop's: the canary first, fail-closed, before the models.dev refresh or
|
|
235
|
+
* OpenCode. Nothing here records events; the first turn does. Only for the
|
|
236
|
+
* pre-baked OpenCode runtime under an enforced egress policy; otherwise null
|
|
237
|
+
* and the turn starts everything in order.
|
|
238
|
+
*/
|
|
239
|
+
export declare function prestartHostedOpenCode(context: HostedLoopContext, opts: {
|
|
240
|
+
logPath: string;
|
|
241
|
+
}): HostedPrestart | null;
|
|
209
242
|
export declare function runHostedLoop(opts: RunHostedLoopOptions): Promise<HostedLoopResult>;
|
|
210
|
-
export declare function startHostedLoopSession(context: HostedLoopSessionContext
|
|
243
|
+
export declare function startHostedLoopSession(context: HostedLoopSessionContext, options?: {
|
|
244
|
+
prestart?: HostedPrestart | null;
|
|
245
|
+
}): Promise<HostedLoopSessionHandle>;
|
|
246
|
+
/** Where a hosted session's `opencode serve` writes its output. */
|
|
247
|
+
export declare function hostedSessionOpenCodeLogPath(context: Pick<HostedLoopSessionContext, 'sessionDir' | 'sessionId'>): string;
|
|
211
248
|
export declare function runHostedLoopTurn(session: HostedLoopSessionHandle, turn: HostedLoopTurnContext, options: Omit<RunHostedLoopOptions, 'context' | 'taskPrompt' | 'sharedRuntime'> & {
|
|
212
249
|
taskPrompt: string;
|
|
213
250
|
}): Promise<HostedLoopResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hosted-loop.d.ts","sourceRoot":"","sources":["../src/hosted-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAOH,OAAO,EAAyB,KAAK,YAAY,EAAyC,MAAM,qBAAqB,CAAA;AAQrH,OAAO,EAAoB,KAAK,WAAW,EAAuB,MAAM,qBAAqB,CAAA;AAE7F,OAAO,
|
|
1
|
+
{"version":3,"file":"hosted-loop.d.ts","sourceRoot":"","sources":["../src/hosted-loop.ts"],"names":[],"mappings":"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"}
|
package/dist/hosted-loop.js
CHANGED
|
@@ -42,7 +42,7 @@ import { isHarnessTerminalKind } from './hosted-harness.js';
|
|
|
42
42
|
import { SETUP_HOOK_RELATIVE_PATH, composeHostedTaskPrompt, parsePrebakedMarker, resolveHostedTaskPreamble, resolvePrebakedMarkerPath, } from './hosted-runtime-assets.js';
|
|
43
43
|
import { harvestWorkspace } from './hosted-harvest.js';
|
|
44
44
|
import { annotateHeadlessQuestions, withIdleWatchdog } from './hosted-headless.js';
|
|
45
|
-
import { DEFAULT_PROMPT_MAX_DURATION_MS, OPENCODE_PINNED_VERSION, awaitOpenCodeModelResolvable, createOpenCodeHarness, permissionForOrigin, spawnOpenCode, } from './hosted-harness-opencode.js';
|
|
45
|
+
import { DEFAULT_PROMPT_MAX_DURATION_MS, OPENCODE_PINNED_VERSION, OpenCodeExitedError, awaitOpenCodeModelResolvable, createOpenCodeHarness, permissionForOrigin, spawnOpenCode, startOpenCodeProcess, waitOpenCodeReady, } from './hosted-harness-opencode.js';
|
|
46
46
|
import { createClaudeAgentHarness } from './hosted-harness-claude.js';
|
|
47
47
|
import { INJECTED_ENV_VARS_ENV } from './hosted-environment.js';
|
|
48
48
|
import { interceptHostedQuestions } from './hosted-question.js';
|
|
@@ -199,7 +199,78 @@ function nodeChildSpawner(cmd, opts) {
|
|
|
199
199
|
// already closed
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
|
-
|
|
202
|
+
// ORI-2512: lets the readiness wait stop at once for a process that has
|
|
203
|
+
// gone. The error listener also keeps a failed spawn from crashing the boot.
|
|
204
|
+
let exited = false;
|
|
205
|
+
let spawnError = null;
|
|
206
|
+
child.once('exit', () => { exited = true; });
|
|
207
|
+
child.once('error', error => {
|
|
208
|
+
exited = true;
|
|
209
|
+
spawnError = error instanceof Error ? error.message : String(error);
|
|
210
|
+
});
|
|
211
|
+
return { kill: () => child.kill(), hasExited: () => exited, exitReason: () => spawnError };
|
|
212
|
+
}
|
|
213
|
+
/** The one place the hosted `opencode serve` options come from, for both the
|
|
214
|
+
* boot's background start and the turn's start in order. */
|
|
215
|
+
function openCodeSpawnOptions(context, logPath) {
|
|
216
|
+
return {
|
|
217
|
+
model: context.model,
|
|
218
|
+
permission: permissionForOrigin(context.sessionOrigin),
|
|
219
|
+
projectId: context.projectId,
|
|
220
|
+
cwd: context.workspaceDir,
|
|
221
|
+
port: context.opencodePort,
|
|
222
|
+
env: buildOpenCodeSpawnEnv(context),
|
|
223
|
+
spawn: nodeChildSpawner,
|
|
224
|
+
logPath,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* ORI-2512 cut 3: start the egress canary and then OpenCode in the
|
|
229
|
+
* background, for the boot to call before it clones. The order is the
|
|
230
|
+
* loop's: the canary first, fail-closed, before the models.dev refresh or
|
|
231
|
+
* OpenCode. Nothing here records events; the first turn does. Only for the
|
|
232
|
+
* pre-baked OpenCode runtime under an enforced egress policy; otherwise null
|
|
233
|
+
* and the turn starts everything in order.
|
|
234
|
+
*/
|
|
235
|
+
export function prestartHostedOpenCode(context, opts) {
|
|
236
|
+
if ((context.harness ?? 'opencode') !== 'opencode' || !context.egressCanaryHost || context.prebaked !== true)
|
|
237
|
+
return null;
|
|
238
|
+
const targets = {
|
|
239
|
+
allowedHost: egressCanaryAllowedHost(context.apiBaseUrl),
|
|
240
|
+
deniedHost: context.egressCanaryHost,
|
|
241
|
+
};
|
|
242
|
+
const results = new Map();
|
|
243
|
+
let stopped = false;
|
|
244
|
+
const canary = (async () => {
|
|
245
|
+
let checkedAt = Date.now();
|
|
246
|
+
// The loop's own decision, with nothing recorded yet.
|
|
247
|
+
const decision = await runEgressCanary(targets, { append: async () => { } }, async (host) => {
|
|
248
|
+
const result = await defaultProbeEgress(host);
|
|
249
|
+
results.set(host, result);
|
|
250
|
+
return result;
|
|
251
|
+
}, () => (checkedAt = Date.now()));
|
|
252
|
+
return { results, checkedAt, proceed: decision.proceed };
|
|
253
|
+
})().catch(() => null);
|
|
254
|
+
const opencode = canary.then(async (stored) => {
|
|
255
|
+
if (!stored?.proceed || stopped)
|
|
256
|
+
return null;
|
|
257
|
+
const started = await startOpenCodeProcess(openCodeSpawnOptions(context, opts.logPath));
|
|
258
|
+
if (stopped) {
|
|
259
|
+
started.stop();
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
return started;
|
|
263
|
+
});
|
|
264
|
+
// The turn reads a failure; until then it must not count as unhandled.
|
|
265
|
+
opencode.catch(() => { });
|
|
266
|
+
return {
|
|
267
|
+
canary,
|
|
268
|
+
opencode,
|
|
269
|
+
stop: () => {
|
|
270
|
+
stopped = true;
|
|
271
|
+
void opencode.then(started => started?.stop(), () => { });
|
|
272
|
+
},
|
|
273
|
+
};
|
|
203
274
|
}
|
|
204
275
|
/** ORI-2512: the longest the end-of-turn save waits for the boot's
|
|
205
276
|
* background fill of the session copy before saving anyway. */
|
|
@@ -260,15 +331,22 @@ export async function runHostedLoop(opts) {
|
|
|
260
331
|
// unreachable → network broken / indistinguishable from a block) emits
|
|
261
332
|
// `egress_allowed` and finishes the run FAILED rather than touch real customer
|
|
262
333
|
// data. A canary whose own event append fails is likewise fail-closed.
|
|
334
|
+
// ORI-2512: on the first turn, the boot may already have probed in the
|
|
335
|
+
// background; the same decision is then made from its stored answers.
|
|
336
|
+
const prestart = opts.sharedRuntime && !opts.sharedRuntime.startupComplete ? opts.sharedRuntime.prestart : null;
|
|
263
337
|
if (context.egressCanaryHost && !opts.sharedRuntime?.startupComplete) {
|
|
264
|
-
const
|
|
338
|
+
const liveProbe = opts.probeEgress ?? defaultProbeEgress;
|
|
339
|
+
const stored = prestart ? await prestart.canary : null;
|
|
340
|
+
const probe = stored
|
|
341
|
+
? async (host) => stored.results.get(host) ?? liveProbe(host)
|
|
342
|
+
: liveProbe;
|
|
265
343
|
const targets = {
|
|
266
344
|
allowedHost: egressCanaryAllowedHost(context.apiBaseUrl),
|
|
267
345
|
deniedHost: context.egressCanaryHost,
|
|
268
346
|
};
|
|
269
347
|
let canary;
|
|
270
348
|
try {
|
|
271
|
-
canary = await runEgressCanary(targets, sink, probe, opts.now);
|
|
349
|
+
canary = await runEgressCanary(targets, sink, probe, stored ? () => stored.checkedAt : opts.now);
|
|
272
350
|
}
|
|
273
351
|
catch (error) {
|
|
274
352
|
// The canary's own event append failed — treat as fail-closed: we cannot
|
|
@@ -490,26 +568,52 @@ export async function runHostedLoop(opts) {
|
|
|
490
568
|
payload: { step: 'opencode_install', ok: install.ok, detail: install.detail },
|
|
491
569
|
});
|
|
492
570
|
}
|
|
571
|
+
const logPath = opts.sharedRuntime?.spawnLogPath ?? join(tmpdir(), `opencode-serve-${context.runId}.log`);
|
|
572
|
+
// ORI-2512: the first turn takes the server the boot started during the
|
|
573
|
+
// clone and asks it something only now, after the clone. A background
|
|
574
|
+
// start that failed, or a process that already exited, is started again
|
|
575
|
+
// here in order.
|
|
576
|
+
const waitStartedAt = Date.now();
|
|
577
|
+
let prestarted = null;
|
|
578
|
+
if (prestart && opts.sharedRuntime) {
|
|
579
|
+
opts.sharedRuntime.prestart = null;
|
|
580
|
+
let started = null;
|
|
581
|
+
try {
|
|
582
|
+
started = await prestart.opencode;
|
|
583
|
+
}
|
|
584
|
+
catch {
|
|
585
|
+
diagnose('hosted OpenCode background start failed; starting it in order');
|
|
586
|
+
}
|
|
587
|
+
if (started) {
|
|
588
|
+
try {
|
|
589
|
+
prestarted = await waitOpenCodeReady(started, { logPath, signal });
|
|
590
|
+
}
|
|
591
|
+
catch (error) {
|
|
592
|
+
if (!(error instanceof OpenCodeExitedError))
|
|
593
|
+
throw error;
|
|
594
|
+
diagnose('hosted OpenCode background start exited; starting it in order');
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
493
598
|
const spawnImpl = opts.spawnOpenCode ?? spawnOpenCode;
|
|
494
599
|
// The default spawnOpenCode WAITS for the server to answer HTTP before
|
|
495
600
|
// returning — OpenCode's first boot runs a one-time sqlite migration, and
|
|
496
601
|
// starting the harness before the server listens raced straight into a
|
|
497
602
|
// connection-refused "fetch failed" (ALI-1034).
|
|
498
|
-
spawned = await spawnImpl({
|
|
499
|
-
model: context.model,
|
|
500
|
-
permission: permissionForOrigin(context.sessionOrigin),
|
|
501
|
-
projectId: context.projectId,
|
|
502
|
-
cwd: context.workspaceDir,
|
|
503
|
-
port: context.opencodePort,
|
|
504
|
-
env: buildOpenCodeSpawnEnv(context),
|
|
505
|
-
spawn: nodeChildSpawner,
|
|
506
|
-
logPath: opts.sharedRuntime?.spawnLogPath ?? join(tmpdir(), `opencode-serve-${context.runId}.log`),
|
|
507
|
-
signal,
|
|
508
|
-
});
|
|
603
|
+
spawned = prestarted ?? await spawnImpl({ ...openCodeSpawnOptions(context, logPath), signal });
|
|
509
604
|
if (typeof spawned.readyAfterMs === 'number') {
|
|
510
605
|
await sink.append({
|
|
511
606
|
kind: 'artifact',
|
|
512
|
-
payload: {
|
|
607
|
+
payload: {
|
|
608
|
+
step: 'opencode_ready',
|
|
609
|
+
ok: true,
|
|
610
|
+
// How long this turn waited for OpenCode. When the boot started it
|
|
611
|
+
// during the clone, that is the wait after the clone; the time
|
|
612
|
+
// since it was started (clone included) is kept apart.
|
|
613
|
+
...(prestarted
|
|
614
|
+
? { waitedMs: Date.now() - waitStartedAt, prestarted: true, sinceStartMs: spawned.readyAfterMs }
|
|
615
|
+
: { waitedMs: spawned.readyAfterMs }),
|
|
616
|
+
},
|
|
513
617
|
});
|
|
514
618
|
}
|
|
515
619
|
// Fail-fast model validation (ALI-1086): ask the RUNNING opencode whether
|
|
@@ -804,7 +908,7 @@ export async function runHostedLoop(opts) {
|
|
|
804
908
|
}
|
|
805
909
|
}
|
|
806
910
|
}
|
|
807
|
-
export async function startHostedLoopSession(context) {
|
|
911
|
+
export async function startHostedLoopSession(context, options = {}) {
|
|
808
912
|
return {
|
|
809
913
|
context,
|
|
810
914
|
runtime: {
|
|
@@ -813,11 +917,16 @@ export async function startHostedLoopSession(context) {
|
|
|
813
917
|
agentSessionId: null,
|
|
814
918
|
installOk: false,
|
|
815
919
|
startupComplete: false,
|
|
816
|
-
spawnLogPath:
|
|
920
|
+
spawnLogPath: hostedSessionOpenCodeLogPath(context),
|
|
817
921
|
closed: false,
|
|
922
|
+
prestart: options.prestart ?? null,
|
|
818
923
|
},
|
|
819
924
|
};
|
|
820
925
|
}
|
|
926
|
+
/** Where a hosted session's `opencode serve` writes its output. */
|
|
927
|
+
export function hostedSessionOpenCodeLogPath(context) {
|
|
928
|
+
return join(context.sessionDir, `opencode-serve-${context.sessionId}.log`);
|
|
929
|
+
}
|
|
821
930
|
export async function runHostedLoopTurn(session, turn, options) {
|
|
822
931
|
if (session.runtime.closed)
|
|
823
932
|
throw new Error('hosted loop session is closed');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hosted-optimization.d.ts","sourceRoot":"","sources":["../src/hosted-optimization.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hosted-optimization.d.ts","sourceRoot":"","sources":["../src/hosted-optimization.ts"],"names":[],"mappings":"AAcA,UAAU,oBAAoB;IAAG,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE;AAgZrF,wBAAsB,yBAAyB,CAAC,EAAE,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoHzF"}
|