spawnfile 0.1.34 → 0.1.35
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/audit/readAudit.d.ts +3 -3
- package/dist/auth/profileStore.d.ts +3 -1
- package/dist/auth/profileStore.js +31 -30
- package/dist/auth/types.d.ts +16 -0
- package/dist/cli/authCommands.d.ts +1 -1
- package/dist/cli/authCommands.js +21 -1
- package/dist/cli/runCli.d.ts +2 -0
- package/dist/cli/runCli.js +2 -1
- package/dist/cli/trainingBooted.d.ts +2 -0
- package/dist/cli/trainingBooted.js +5 -1
- package/dist/compiler/containerDaimonBrokerRender.js +12 -2
- package/dist/compiler/containerDaimonGatewayRender.js +4 -0
- package/dist/compiler/containerDaimonUidEntrypointRender.js +3 -1
- package/dist/compiler/runProject.d.ts +2 -0
- package/dist/compiler/runProject.js +6 -5
- package/dist/compiler/runProjectAuth.js +4 -1
- package/dist/compiler/training/rewind/contract.d.ts +6 -6
- package/dist/compiler/training/trial/boot.d.ts +20 -1
- package/dist/compiler/training/trial/boot.js +102 -24
- package/dist/compiler/training/trial/docker.d.ts +2 -0
- package/dist/compiler/training/trial/docker.js +1 -1
- package/dist/compiler/training/trial/gateway.d.ts +5 -0
- package/dist/compiler/training/trial/gateway.js +18 -3
- package/dist/compiler/training/trial/homeLogin.d.ts +31 -0
- package/dist/compiler/training/trial/homeLogin.js +69 -0
- package/dist/compiler/training/trial/index.d.ts +5 -1
- package/dist/compiler/training/trial/index.js +5 -1
- package/dist/compiler/training/trial/judge.d.ts +15 -0
- package/dist/compiler/training/trial/judge.js +42 -0
- package/dist/compiler/training/trial/launcher.d.ts +28 -13
- package/dist/compiler/training/trial/launcher.js +168 -24
- package/dist/compiler/training/trial/login.d.ts +35 -0
- package/dist/compiler/training/trial/login.js +85 -0
- package/dist/compiler/training/trial/realmTurns.d.ts +20 -0
- package/dist/compiler/training/trial/realmTurns.js +69 -0
- package/dist/manifest/renderSpawnfile.js +2 -1
- package/dist/runtime/daimon/config.js +3 -3
- package/dist/runtime/daimon/engineDescriptors.generated.d.ts +1 -1
- package/dist/runtime/daimon/engineDescriptors.generated.js +1 -1
- package/dist/runtime/daimon/index.d.ts +1 -1
- package/dist/runtime/daimon/index.js +1 -1
- package/dist/runtime/daimon/runAuth.js +8 -0
- package/dist/runtime/daimon/subscriptionRealms.d.ts +18 -0
- package/dist/runtime/daimon/subscriptionRealms.js +14 -1
- package/dist/runtime/daimon/training/booted/adapter.d.ts +5 -1
- package/dist/runtime/daimon/training/booted/adapter.js +3 -2
- package/dist/runtime/daimon/training/booted/adapter.js.map +1 -1
- package/dist/runtime/daimon/training/booted/index.d.ts +3 -1
- package/dist/runtime/daimon/training/booted/index.js +2 -1
- package/dist/runtime/daimon/training/booted/index.js.map +1 -1
- package/dist/runtime/daimon/training/booted/judge.d.ts +39 -0
- package/dist/runtime/daimon/training/booted/judge.js +122 -0
- package/dist/runtime/daimon/training/booted/judge.js.map +1 -0
- package/dist/runtime/trainingGraderProviders.js +10 -4
- package/dist/runtime/trainingProviders.d.ts +4 -1
- package/dist/runtime/trainingProviders.js +13 -6
- package/dist/runtime/usageRequestLedger.d.ts +2 -0
- package/dist/runtime/usageRequestLedger.js +3 -1
- package/dist/shared/trainingLegacy/trainingLegacyHashDomains.d.ts +1 -0
- package/dist/shared/trainingLegacy/trainingLegacyHashDomains.js +1 -0
- package/dist/shared/trainingLegacy/trainingLegacyHashDomains.js.map +1 -1
- package/package.json +1 -1
- package/runtimes.yaml +5 -5
- package/dist/runtime/daimon/training/providers/codex-subscription/index.d.ts +0 -1
- package/dist/runtime/daimon/training/providers/codex-subscription/index.js +0 -2
- package/dist/runtime/daimon/training/providers/codex-subscription/index.js.map +0 -1
- package/dist/runtime/daimon/training/providers/codex-subscription/protocol.d.ts +0 -17
- package/dist/runtime/daimon/training/providers/codex-subscription/protocol.js +0 -80
- package/dist/runtime/daimon/training/providers/codex-subscription/protocol.js.map +0 -1
- package/dist/runtime/daimon/training/providers/codex-subscription/provider.d.ts +0 -12
- package/dist/runtime/daimon/training/providers/codex-subscription/provider.js +0 -125
- package/dist/runtime/daimon/training/providers/codex-subscription/provider.js.map +0 -1
- package/dist/runtime/daimon/training/providers/codex-subscription/strict-schema.d.ts +0 -6
- package/dist/runtime/daimon/training/providers/codex-subscription/strict-schema.js +0 -219
- package/dist/runtime/daimon/training/providers/codex-subscription/strict-schema.js.map +0 -1
- package/dist/runtime/daimon/training/providers/grok-subscription/cli.d.ts +0 -19
- package/dist/runtime/daimon/training/providers/grok-subscription/cli.js +0 -81
- package/dist/runtime/daimon/training/providers/grok-subscription/cli.js.map +0 -1
- package/dist/runtime/daimon/training/providers/grok-subscription/index.d.ts +0 -3
- package/dist/runtime/daimon/training/providers/grok-subscription/index.js +0 -4
- package/dist/runtime/daimon/training/providers/grok-subscription/index.js.map +0 -1
- package/dist/runtime/daimon/training/providers/grok-subscription/protocol.d.ts +0 -14
- package/dist/runtime/daimon/training/providers/grok-subscription/protocol.js +0 -89
- package/dist/runtime/daimon/training/providers/grok-subscription/protocol.js.map +0 -1
- package/dist/runtime/daimon/training/providers/grok-subscription/provider.d.ts +0 -9
- package/dist/runtime/daimon/training/providers/grok-subscription/provider.js +0 -37
- package/dist/runtime/daimon/training/providers/grok-subscription/provider.js.map +0 -1
|
@@ -3,12 +3,12 @@ import type { AuditReport } from "./types.js";
|
|
|
3
3
|
export declare const auditReportSchema: z.ZodObject<{
|
|
4
4
|
checks: z.ZodArray<z.ZodObject<{
|
|
5
5
|
category: z.ZodEnum<{
|
|
6
|
-
provenance: "provenance";
|
|
7
|
-
causal: "causal";
|
|
8
6
|
container: "container";
|
|
9
|
-
control: "control";
|
|
10
7
|
memory: "memory";
|
|
11
8
|
network: "network";
|
|
9
|
+
provenance: "provenance";
|
|
10
|
+
causal: "causal";
|
|
11
|
+
control: "control";
|
|
12
12
|
}>;
|
|
13
13
|
evidence: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
14
14
|
id: z.ZodString;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import type { AuthProfile, ImportedAuthKind, ResolvedAuthProfile } from "./types.js";
|
|
1
|
+
import type { AuthProfile, ImportedAuthKind, ResolvedAuthProfile, SubscriptionRealmBinding } from "./types.js";
|
|
2
2
|
export declare const createResolvedAuthProfile: (profileName: string, profile: AuthProfile) => ResolvedAuthProfile;
|
|
3
3
|
export declare const loadAuthProfile: (profileName: string) => Promise<ResolvedAuthProfile | null>;
|
|
4
4
|
export declare const requireAuthProfile: (profileName: string) => Promise<ResolvedAuthProfile>;
|
|
5
5
|
export declare const ensureAuthProfile: (profileName: string) => Promise<ResolvedAuthProfile>;
|
|
6
6
|
export declare const setAuthProfileEnv: (profileName: string, env: Record<string, string>) => Promise<ResolvedAuthProfile>;
|
|
7
|
+
/** Records an engine's volume-held login on the profile (names only, never login bytes). */
|
|
8
|
+
export declare const registerSubscriptionRealm: (profileName: string, engine: string, binding: SubscriptionRealmBinding) => Promise<ResolvedAuthProfile>;
|
|
7
9
|
export declare const registerImportedAuth: (profileName: string, kind: ImportedAuthKind) => Promise<{
|
|
8
10
|
directory: string;
|
|
9
11
|
profile: ResolvedAuthProfile;
|
|
@@ -4,7 +4,7 @@ import { ensurePrivateDirectory, fileExists, readUtf8File, removeDirectory, writ
|
|
|
4
4
|
import { SpawnfileError } from "../shared/index.js";
|
|
5
5
|
import { resolveAuthHome, resolveImportedAuthDirectory, resolveProfileDirectory, resolveProfilePath, resolveProfilesRoot } from "./paths.js";
|
|
6
6
|
const importedAuthEntrySchema = z.object({
|
|
7
|
-
kind: z.enum(["claude-code", "codex"]),
|
|
7
|
+
kind: z.enum(["claude-code", "codex", "grok"]),
|
|
8
8
|
relativePath: z.string().min(1)
|
|
9
9
|
});
|
|
10
10
|
const authProfileSchema = z.object({
|
|
@@ -12,9 +12,15 @@ const authProfileSchema = z.object({
|
|
|
12
12
|
imports: z
|
|
13
13
|
.object({
|
|
14
14
|
"claude-code": importedAuthEntrySchema.optional(),
|
|
15
|
-
codex: importedAuthEntrySchema.optional()
|
|
15
|
+
codex: importedAuthEntrySchema.optional(),
|
|
16
|
+
grok: importedAuthEntrySchema.optional()
|
|
16
17
|
})
|
|
17
18
|
.default({}),
|
|
19
|
+
realms: z.record(z.string().regex(/^[a-z][a-z0-9-]*$/u), z.object({
|
|
20
|
+
realmVolume: z.string().min(1),
|
|
21
|
+
unlockVolume: z.string().min(1),
|
|
22
|
+
homeVolume: z.string().min(1).optional()
|
|
23
|
+
}).strict()).optional(),
|
|
18
24
|
version: z.literal(1)
|
|
19
25
|
});
|
|
20
26
|
const createEmptyProfile = () => ({
|
|
@@ -35,6 +41,17 @@ export const createResolvedAuthProfile = (profileName, profile) => ({
|
|
|
35
41
|
name: profileName,
|
|
36
42
|
profileDirectory: resolveProfileDirectory(profileName),
|
|
37
43
|
profilePath: resolveProfilePath(profileName),
|
|
44
|
+
...(profile.realms && Object.keys(profile.realms).length > 0 ? { realms: structuredClone(profile.realms) } : {}),
|
|
45
|
+
version: 1
|
|
46
|
+
});
|
|
47
|
+
/** The stored form of a resolved profile: import paths relative to its directory again. */
|
|
48
|
+
const storedProfile = (current) => ({
|
|
49
|
+
env: { ...current.env },
|
|
50
|
+
imports: Object.fromEntries(Object.entries(current.imports).map(([kind, entry]) => [
|
|
51
|
+
kind,
|
|
52
|
+
{ kind: entry.kind, relativePath: path.relative(current.profileDirectory, entry.path) }
|
|
53
|
+
])),
|
|
54
|
+
...(current.realms ? { realms: structuredClone(current.realms) } : {}),
|
|
38
55
|
version: 1
|
|
39
56
|
});
|
|
40
57
|
export const loadAuthProfile = async (profileName) => {
|
|
@@ -80,20 +97,13 @@ const writeProfile = async (profileName, profile) => {
|
|
|
80
97
|
};
|
|
81
98
|
export const setAuthProfileEnv = async (profileName, env) => {
|
|
82
99
|
const current = (await loadAuthProfile(profileName)) ?? (await ensureAuthProfile(profileName));
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
{
|
|
91
|
-
kind: entry.kind,
|
|
92
|
-
relativePath: path.relative(current.profileDirectory, entry.path)
|
|
93
|
-
}
|
|
94
|
-
])),
|
|
95
|
-
version: 1
|
|
96
|
-
});
|
|
100
|
+
const stored = storedProfile(current);
|
|
101
|
+
return writeProfile(profileName, { ...stored, env: { ...stored.env, ...env } });
|
|
102
|
+
};
|
|
103
|
+
/** Records an engine's volume-held login on the profile (names only, never login bytes). */
|
|
104
|
+
export const registerSubscriptionRealm = async (profileName, engine, binding) => {
|
|
105
|
+
const stored = storedProfile((await loadAuthProfile(profileName)) ?? (await ensureAuthProfile(profileName)));
|
|
106
|
+
return writeProfile(profileName, { ...stored, realms: { ...stored.realms, [engine]: { ...binding } } });
|
|
97
107
|
};
|
|
98
108
|
export const registerImportedAuth = async (profileName, kind) => {
|
|
99
109
|
const current = (await loadAuthProfile(profileName)) ?? (await ensureAuthProfile(profileName));
|
|
@@ -104,22 +114,13 @@ export const registerImportedAuth = async (profileName, kind) => {
|
|
|
104
114
|
if (kind !== "grok")
|
|
105
115
|
await removeDirectory(importDirectory);
|
|
106
116
|
await ensurePrivateDirectory(importDirectory);
|
|
117
|
+
const stored = storedProfile(current);
|
|
107
118
|
const nextProfile = {
|
|
108
|
-
|
|
119
|
+
...stored,
|
|
109
120
|
imports: {
|
|
110
|
-
...
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
kind: entry.kind,
|
|
114
|
-
relativePath: path.relative(current.profileDirectory, entry.path)
|
|
115
|
-
}
|
|
116
|
-
])),
|
|
117
|
-
[kind]: {
|
|
118
|
-
kind,
|
|
119
|
-
relativePath: path.relative(current.profileDirectory, importDirectory)
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
version: 1
|
|
121
|
+
...stored.imports,
|
|
122
|
+
[kind]: { kind, relativePath: path.relative(current.profileDirectory, importDirectory) }
|
|
123
|
+
}
|
|
123
124
|
};
|
|
124
125
|
return {
|
|
125
126
|
directory: importDirectory,
|
package/dist/auth/types.d.ts
CHANGED
|
@@ -3,9 +3,23 @@ export interface ImportedAuthEntry {
|
|
|
3
3
|
kind: ImportedAuthKind;
|
|
4
4
|
relativePath: string;
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* A login that lives in Docker volumes rather than an importable file: the
|
|
8
|
+
* engine's durable realm volume, the volume holding its unlock secret, and the
|
|
9
|
+
* volume holding the engine's login files from its runtime home (seeded into
|
|
10
|
+
* each fresh home at boot, written back after the container stops).
|
|
11
|
+
* Created once by `spawnfile auth login <engine>`; the profile records names only.
|
|
12
|
+
*/
|
|
13
|
+
export interface SubscriptionRealmBinding {
|
|
14
|
+
realmVolume: string;
|
|
15
|
+
unlockVolume: string;
|
|
16
|
+
/** Absent on a login recorded before home login files were kept: log in again. */
|
|
17
|
+
homeVolume?: string;
|
|
18
|
+
}
|
|
6
19
|
export interface AuthProfile {
|
|
7
20
|
env: Record<string, string>;
|
|
8
21
|
imports: Partial<Record<ImportedAuthKind, ImportedAuthEntry>>;
|
|
22
|
+
realms?: Record<string, SubscriptionRealmBinding>;
|
|
9
23
|
version: 1;
|
|
10
24
|
}
|
|
11
25
|
export interface ResolvedAuthProfile {
|
|
@@ -18,5 +32,7 @@ export interface ResolvedAuthProfile {
|
|
|
18
32
|
name: string;
|
|
19
33
|
profileDirectory: string;
|
|
20
34
|
profilePath: string;
|
|
35
|
+
/** Volume-held logins by engine id; absent means none. */
|
|
36
|
+
realms?: Record<string, SubscriptionRealmBinding>;
|
|
21
37
|
version: 1;
|
|
22
38
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
import type { CliHandlers, CliStreams } from "./runCli.js";
|
|
3
|
-
type AuthCommandHandlers = Pick<CliHandlers, "importClaudeCodeAuth" | "importCodexAuth" | "importGrokAuth" | "importEnvFile" | "initializeTargetSecretSourceLifecycle" | "provisionCredentials" | "requireAuthProfile" | "syncProjectAuth">;
|
|
3
|
+
type AuthCommandHandlers = Pick<CliHandlers, "importClaudeCodeAuth" | "importCodexAuth" | "importGrokAuth" | "importEnvFile" | "initializeTargetSecretSourceLifecycle" | "loginSubscriptionRealm" | "provisionCredentials" | "requireAuthProfile" | "syncProjectAuth">;
|
|
4
4
|
export declare const registerAuthCommands: (program: Command, handlers: AuthCommandHandlers, streams: CliStreams, stdin: AsyncIterable<unknown>) => void;
|
|
5
5
|
export {};
|
package/dist/cli/authCommands.js
CHANGED
|
@@ -9,10 +9,12 @@ import { envFileAliasOption, resolveEnvFileOption, runtimeEnvFileOption } from "
|
|
|
9
9
|
const formatAuthProfileSummary = (profile) => {
|
|
10
10
|
const envKeys = Object.keys(profile.env).sort();
|
|
11
11
|
const importedKinds = Object.keys(profile.imports).sort();
|
|
12
|
+
const realms = Object.keys(profile.realms ?? {}).sort();
|
|
12
13
|
return [
|
|
13
14
|
`profile: ${profile.name}`,
|
|
14
15
|
`env: ${envKeys.length > 0 ? envKeys.join(", ") : "none"}`,
|
|
15
|
-
`imports: ${importedKinds.length > 0 ? importedKinds.join(", ") : "none"}
|
|
16
|
+
`imports: ${importedKinds.length > 0 ? importedKinds.join(", ") : "none"}`,
|
|
17
|
+
...(realms.length > 0 ? [`logins: ${realms.join(", ")}`] : [])
|
|
16
18
|
];
|
|
17
19
|
};
|
|
18
20
|
const emitLines = (streams, lines) => lines.forEach((line) => streams.stdout(line));
|
|
@@ -108,6 +110,24 @@ export const registerAuthCommands = (program, handlers, streams, stdin) => {
|
|
|
108
110
|
const profile = await handlers.importCodexAuth(options.profile, options.from);
|
|
109
111
|
emitLines(streams, formatAuthProfileSummary(profile));
|
|
110
112
|
});
|
|
113
|
+
authCommand
|
|
114
|
+
.command("login")
|
|
115
|
+
.description("Sign an auth profile into its own volume-held login (AGY) from this terminal")
|
|
116
|
+
.argument("<engine>", "Daimon engine whose login lives in a keyring realm, e.g. agy")
|
|
117
|
+
.option("-p, --profile <name>", "Auth profile name", "default")
|
|
118
|
+
.option("--dry-run", "Prepare the login volumes and print the login command without running it")
|
|
119
|
+
.action(async (engine, options) => {
|
|
120
|
+
if (!options.dryRun && process.stdin.isTTY !== true) {
|
|
121
|
+
throw new Error("spawnfile auth login is interactive; run it from a terminal");
|
|
122
|
+
}
|
|
123
|
+
const result = await handlers.loginSubscriptionRealm({ engine, profileName: options.profile, dryRun: options.dryRun === true });
|
|
124
|
+
emitLines(streams, [
|
|
125
|
+
...formatAuthProfileSummary(result.profile),
|
|
126
|
+
`realm volume: ${result.binding.realmVolume}`,
|
|
127
|
+
`unlock volume: ${result.binding.unlockVolume}`,
|
|
128
|
+
...(options.dryRun ? [`login command: ${result.command.join(" ")}`] : [])
|
|
129
|
+
]);
|
|
130
|
+
});
|
|
111
131
|
authCommand
|
|
112
132
|
.command("sync")
|
|
113
133
|
.description("Provision auth material a project requires into a profile")
|
package/dist/cli/runCli.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { loginSubscriptionRealm } from "../compiler/training/trial/index.js";
|
|
1
2
|
import { importClaudeCodeAuth, importCodexAuth, importGrokAuth, importEnvFile, initializeTargetSecretSourceLifecycle, provisionCredentials, requireAuthProfile } from "../auth/index.js";
|
|
2
3
|
import { addAgentProject, addProjectSurface, addProjectModelFallback, addSubagentProject, addTeamProject, buildOrganizationView, buildCompilePlan, buildProject, buildUpReceipt, clearProjectModelFallbacks, compileProject, createTrainingContext, createTrainingPlan, loadTrainingProject, resolveTrainingPlan, materializeTrainingMoment, lowerTrainingExecution, allocateTrainingOutputParent, initProject, listInitTemplates, publishProject, upProject, removeProjectSurface, runProject, setProjectPrimaryModel, setProjectRuntime, setProjectSurfaceAccess, showProjectSurfaces, syncProjectAuth } from "../compiler/index.js";
|
|
3
4
|
import { devStopProject, devUpProject } from "../dev/index.js";
|
|
@@ -37,6 +38,7 @@ export interface CliHandlers {
|
|
|
37
38
|
importClaudeCodeAuth: typeof importClaudeCodeAuth;
|
|
38
39
|
importCodexAuth: typeof importCodexAuth;
|
|
39
40
|
importGrokAuth: typeof importGrokAuth;
|
|
41
|
+
loginSubscriptionRealm: typeof loginSubscriptionRealm;
|
|
40
42
|
importEnvFile: typeof importEnvFile;
|
|
41
43
|
initProject: typeof initProject;
|
|
42
44
|
listInitTemplates: typeof listInitTemplates;
|
package/dist/cli/runCli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
+
import { loginSubscriptionRealm } from "../compiler/training/trial/index.js";
|
|
2
3
|
import { Command } from "commander";
|
|
3
4
|
import { importClaudeCodeAuth, importCodexAuth, importGrokAuth, importEnvFile, initializeTargetSecretSourceLifecycle, provisionCredentials, requireAuthProfile } from "../auth/index.js";
|
|
4
5
|
import { addAgentProject, addProjectSurface, addProjectModelFallback, addSubagentProject, addTeamProject, buildOrganizationView, buildCompilePlan, buildProject, buildUpReceipt, clearProjectModelFallbacks, compileProject, createTrainingContext, createTrainingPlan, loadTrainingProject, resolveTrainingPlan, materializeTrainingMoment, lowerTrainingExecution, allocateTrainingOutputParent, initProject, listInitTemplates, preflightCompilePlan, publishProject, upProject, removeProjectSurface, runProject, setProjectPrimaryModel, setProjectRuntime, setProjectSurfaceAccess, showProjectSurfaces, syncProjectAuth } from "../compiler/index.js";
|
|
@@ -44,7 +45,7 @@ const createDefaultHandlers = () => ({
|
|
|
44
45
|
addAgentProject, addProjectModelFallback, addProjectSurface,
|
|
45
46
|
addSubagentProject, addTeamProject, clearProjectModelFallbacks,
|
|
46
47
|
importClaudeCodeAuth, importCodexAuth, importGrokAuth, importEnvFile, initializeTargetSecretSourceLifecycle,
|
|
47
|
-
provisionCredentials,
|
|
48
|
+
loginSubscriptionRealm, provisionCredentials,
|
|
48
49
|
createDockerProbeGateway, exportRunArtifacts, downDeployment, inspectDockerDeployment,
|
|
49
50
|
listDeploymentRecords, listHomeDeploymentRecords,
|
|
50
51
|
initProject, listInitTemplates, listRuntimeAdapters, removeProjectSurface, requireAuthProfile,
|
|
@@ -3,5 +3,7 @@ import type { RunTrainingOptions } from "./trainingExecution.js";
|
|
|
3
3
|
* Production-booted training for a Daimon subject: the training core and the
|
|
4
4
|
* grader run here, and every trial is the subject's own compiled organization
|
|
5
5
|
* in its own container, sharing the run's one auth gateway (and so one login).
|
|
6
|
+
* Every subscription judgment of the run wakes one of the run's warm, tool-free
|
|
7
|
+
* judge containers on that same gateway; none reads a personal login.
|
|
6
8
|
*/
|
|
7
9
|
export declare const runBootedTraining: (options: RunTrainingOptions) => Promise<number>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { requireAuthProfile } from "../auth/index.js";
|
|
3
3
|
import { createBootedTrialRun } from "../compiler/training/trial/index.js";
|
|
4
|
-
import { createDaimonBootedAdapter } from "../runtime/daimon/training/booted/index.js";
|
|
4
|
+
import { bindBootedJudges, createDaimonBootedAdapter } from "../runtime/daimon/training/booted/index.js";
|
|
5
5
|
import { SpawnfileError } from "../shared/index.js";
|
|
6
6
|
const failure = (message) => new SpawnfileError("runtime_error", message);
|
|
7
7
|
const flag = (args, name) => {
|
|
@@ -12,6 +12,8 @@ const flag = (args, name) => {
|
|
|
12
12
|
* Production-booted training for a Daimon subject: the training core and the
|
|
13
13
|
* grader run here, and every trial is the subject's own compiled organization
|
|
14
14
|
* in its own container, sharing the run's one auth gateway (and so one login).
|
|
15
|
+
* Every subscription judgment of the run wakes one of the run's warm, tool-free
|
|
16
|
+
* judge containers on that same gateway; none reads a personal login.
|
|
15
17
|
*/
|
|
16
18
|
export const runBootedTraining = async (options) => {
|
|
17
19
|
if (!options.authProfile)
|
|
@@ -29,6 +31,7 @@ export const runBootedTraining = async (options) => {
|
|
|
29
31
|
authProfile: await requireAuthProfile(options.authProfile),
|
|
30
32
|
scratchRoot: path.join(path.resolve(out), "booted-trials")
|
|
31
33
|
});
|
|
34
|
+
bindBootedJudges(run);
|
|
32
35
|
try {
|
|
33
36
|
const { main } = await import("../runtime/trainingCli.js");
|
|
34
37
|
return await main(["train", ...options.args, ...(flag(options.args, "runtime") ? [] : ["--runtime", "daimon"]), ...instructions], {
|
|
@@ -36,6 +39,7 @@ export const runBootedTraining = async (options) => {
|
|
|
36
39
|
}, { adapter: (_runtime, adapter) => createDaimonBootedAdapter({ launcher: run, timeoutMs: adapter.timeoutMs }) });
|
|
37
40
|
}
|
|
38
41
|
finally {
|
|
42
|
+
bindBootedJudges(undefined);
|
|
39
43
|
await run.close();
|
|
40
44
|
}
|
|
41
45
|
};
|
|
@@ -51,9 +51,19 @@ export const renderDaimonWorkspaceResourceSecurity = (resources, owners = { link
|
|
|
51
51
|
* `EPERM` the moment root no longer owns the path.
|
|
52
52
|
*/
|
|
53
53
|
export const renderDaimonUsageLedgerProvisioning = () => {
|
|
54
|
-
const { directoryPath } = DAIMON_GROK_TURN_USAGE_LEDGER;
|
|
54
|
+
const { directoryPath, filePath } = DAIMON_GROK_TURN_USAGE_LEDGER;
|
|
55
|
+
// The ledger file itself is shared too: the broker uid appends Grok rows and
|
|
56
|
+
// the organization uid appends Codex/AGY rows, and Daimon's wake fuse creates
|
|
57
|
+
// it empty as the organization uid at 0640 when absent, which leaves the
|
|
58
|
+
// broker unable to append and every Grok usage row silently lost. Root owns
|
|
59
|
+
// it first (it holds no CAP_DAC_OVERRIDE or CAP_FOWNER), then hands it to
|
|
60
|
+
// broker:organization at 0660, on every start so a reattached volume heals.
|
|
61
|
+
const owner = `${DAIMON_BROKER_UID}:${DAIMON_ORGANIZATION_UID}`;
|
|
55
62
|
return [
|
|
56
|
-
`chown 0:0 ${directoryPath} && chmod 0770 ${directoryPath}
|
|
63
|
+
`chown 0:0 ${directoryPath} && chmod 0770 ${directoryPath}`,
|
|
64
|
+
`if [ -L ${filePath} ] || { [ -e ${filePath} ] && [ ! -f ${filePath} ]; }; then echo "usage ledger ${filePath} is not a regular file" >&2; exit 1; fi`,
|
|
65
|
+
`if [ -e ${filePath} ]; then chown 0:0 ${filePath}; else (umask 077 && : > ${filePath}); fi && chmod 0660 ${filePath} && chown ${owner} ${filePath}`,
|
|
66
|
+
`chown ${owner} ${directoryPath}`,
|
|
57
67
|
`setpriv --clear-groups --reuid ${DAIMON_ORGANIZATION_UID} --regid ${DAIMON_ORGANIZATION_UID} --inh-caps=-all --ambient-caps=-all --bounding-set=-all -- bash -ceu 'probe=${directoryPath}/.daimon-usage-probe; umask 007; : > "$probe"; rm "$probe"'`
|
|
58
68
|
];
|
|
59
69
|
};
|
|
@@ -88,6 +88,10 @@ export const renderDaimonGatewayProvisioning = (plans) => {
|
|
|
88
88
|
` ${KEY_VARIABLE}=\${${DAIMON_GATEWAY_KEY_ENV}:?${DAIMON_GATEWAY_KEY_ENV} must accompany ${DAIMON_GATEWAY_URL_ENV}}`,
|
|
89
89
|
// Only the runtime and broker launches below get them, as with the in-container gateway.
|
|
90
90
|
` export -n ${DAIMON_GATEWAY_URL_ENV} ${DAIMON_GATEWAY_KEY_ENV}`,
|
|
91
|
+
// Empty root-only placeholders: a brokered worker's sandbox masks these paths and refuses one that is missing.
|
|
92
|
+
...(descriptors.some((descriptor) => descriptor.broker !== null)
|
|
93
|
+
? [DAIMON_GATEWAY_ETC, DAIMON_GATEWAY_RUN, DAIMON_GATEWAY_BOOTSTRAP_ROOT, ...descriptors.map(daimonGatewayRealmPath)] : [])
|
|
94
|
+
.map((target) => ` if [ ! -e ${target} ]; then install -d -o root -g root -m 0700 ${target}; fi`),
|
|
91
95
|
"else",
|
|
92
96
|
` ${EXTERNAL_VARIABLE}=0 ${URL_VARIABLE}=${DAIMON_GATEWAY_URL}`,
|
|
93
97
|
// Rotated every start: 32 random bytes as lowercase hex, held only in this root shell.
|
|
@@ -253,7 +253,9 @@ export const renderDaimonUidEntrypoint = (runtimePlans, persistentMountPaths = [
|
|
|
253
253
|
" if [ \"$EUID\" -eq 0 ]; then exit 1; fi",
|
|
254
254
|
" test \"$(sed -n \"s/^CapEff:[[:space:]]*//p\" /proc/self/status)\" = 0000000000000000",
|
|
255
255
|
" exec \"$@\"",
|
|
256
|
-
|
|
256
|
+
// Explicit stdin: a non-interactive shell gives `&` jobs /dev/null, which would
|
|
257
|
+
// starve the interactive `auth <engine> login` of the operator's terminal.
|
|
258
|
+
`' bash "\${runtime_command[@]}" <&0 &`,
|
|
257
259
|
"runtime_pid=$!",
|
|
258
260
|
"trap - EXIT TERM INT HUP",
|
|
259
261
|
"stopping=0",
|
|
@@ -29,6 +29,7 @@ export declare const createDockerRunInvocation: (compileResult: CompileProjectRe
|
|
|
29
29
|
name: string;
|
|
30
30
|
value: string;
|
|
31
31
|
};
|
|
32
|
+
command?: readonly string[];
|
|
32
33
|
/** See `RuntimeAuthPreparationInput.containerCredentialUid`. */
|
|
33
34
|
containerCredentialUid?: number;
|
|
34
35
|
containerName?: string;
|
|
@@ -38,6 +39,7 @@ export declare const createDockerRunInvocation: (compileResult: CompileProjectRe
|
|
|
38
39
|
dockerContext?: string;
|
|
39
40
|
dockerHost?: string;
|
|
40
41
|
envFilePath?: string;
|
|
42
|
+
interactive?: boolean;
|
|
41
43
|
network?: string;
|
|
42
44
|
}) => Promise<DockerRunInvocation>;
|
|
43
45
|
interface ResolvedRunDeploymentOptions {
|
|
@@ -6,7 +6,7 @@ import { ensureDirectory, fileExists, removeDirectory, writeUtf8File } from "../
|
|
|
6
6
|
import { appendDockerLabelArgs, createDockerDeploymentLabels, createDockerDeploymentUnitId, createDockerProjectLabel, dockerContextNameForTarget, dockerHostValueForTarget, normalizeDeploymentName, readDeploymentRecordFromOutput, resolveDeploymentRecordPath, verifyDockerDeploymentTarget, writeDockerDeploymentRecordForRun } from "../deployment/index.js";
|
|
7
7
|
import { DAIMON_DOCKER_RUNTIME_SECURITY_ARGS, DEFAULT_OUTPUT_DIRECTORY, SpawnfileError } from "../shared/index.js";
|
|
8
8
|
import { ensureNoopolisRunId, resolveNoopolisRunId } from "../runtime/index.js";
|
|
9
|
-
import { DAIMON_GATEWAY_URL_ENV, isDaimonGatewayRealmMountId } from "../runtime/daimon/index.js";
|
|
9
|
+
import { DAIMON_GATEWAY_URL_ENV, daimonProfileRealmVolume, isDaimonGatewayRealmMountId } from "../runtime/daimon/index.js";
|
|
10
10
|
import { compileProject } from "./compileProject.js";
|
|
11
11
|
import { createDefaultImageTag, resolveDockerBuildArchitecture } from "./buildProject.js";
|
|
12
12
|
import { slugify } from "./helpers.js";
|
|
@@ -60,7 +60,7 @@ export const createDockerRunInvocation = async (compileResult, imageTag, options
|
|
|
60
60
|
args.push("-d", "--restart", "unless-stopped");
|
|
61
61
|
}
|
|
62
62
|
else {
|
|
63
|
-
args.push("--rm");
|
|
63
|
+
args.push("--rm", ...(options.interactive ? ["-it"] : []));
|
|
64
64
|
}
|
|
65
65
|
args.push("--name", containerName);
|
|
66
66
|
if (options.network)
|
|
@@ -83,9 +83,10 @@ export const createDockerRunInvocation = async (compileResult, imageTag, options
|
|
|
83
83
|
// reattached volume that already holds state is untouched by dropping it.
|
|
84
84
|
// (Target/secrets volumes under src/target/* keep `volume-nocopy`: no
|
|
85
85
|
// image content backs those paths and they must stay opaque.)
|
|
86
|
-
// An external auth gateway
|
|
86
|
+
// An external auth gateway holds every gatewayed realm (the org mounts none); a profile-held login reattaches its volume.
|
|
87
87
|
const persistentMounts = (containerReport.persistent_mounts ?? [])
|
|
88
|
-
.filter((mount) => !env[DAIMON_GATEWAY_URL_ENV] || !isDaimonGatewayRealmMountId(mount.id))
|
|
88
|
+
.filter((mount) => !env[DAIMON_GATEWAY_URL_ENV] || !isDaimonGatewayRealmMountId(mount.id))
|
|
89
|
+
.map((mount) => ({ ...mount, volume_name: daimonProfileRealmVolume(mount.id, options.authProfile) ?? mount.volume_name }));
|
|
89
90
|
for (const mount of persistentMounts) {
|
|
90
91
|
args.push("--mount", `type=volume,source=${mount.volume_name},target=${mount.mount_path}`);
|
|
91
92
|
}
|
|
@@ -103,7 +104,7 @@ export const createDockerRunInvocation = async (compileResult, imageTag, options
|
|
|
103
104
|
args.push("--env-file", envFilePath);
|
|
104
105
|
args.push(...(await resolveAuthMountArgs(containerReport, options.authProfile ?? null)));
|
|
105
106
|
args.push(...preparedRuntimeAuth.mountArgs);
|
|
106
|
-
args.push(imageTag);
|
|
107
|
+
args.push(imageTag, ...(options.command ?? []));
|
|
107
108
|
return {
|
|
108
109
|
args,
|
|
109
110
|
command: options.dockerCommand ?? "docker",
|
|
@@ -107,6 +107,7 @@ export const assertDeclaredModelAuthSatisfied = (containerReport, authProfile, c
|
|
|
107
107
|
throw new SpawnfileError("validation_error", `Auth profile ${authProfile.name} is missing required auth imports: ${missingImportKinds.join(", ")}`);
|
|
108
108
|
}
|
|
109
109
|
};
|
|
110
|
+
const RUNTIME_HOME_IMPORT_KINDS = ["claude-code", "codex"];
|
|
110
111
|
const getImportMountTargetName = (kind) => kind === "claude-code" ? ".claude" : ".codex";
|
|
111
112
|
const createGeneratedRuntimeSecret = (secretName, generatedMoltnetSecrets) => {
|
|
112
113
|
if (secretName === "OPENCLAW_GATEWAY_TOKEN" || secretName === "OPENCLAW_HOOKS_TOKEN") {
|
|
@@ -221,7 +222,9 @@ export const resolveAuthMountArgs = async (containerReport, authProfile) => {
|
|
|
221
222
|
return [];
|
|
222
223
|
}
|
|
223
224
|
const args = [];
|
|
224
|
-
|
|
225
|
+
// Only runtime-home logins are bind-mounted; a Grok import belongs to the auth gateway alone.
|
|
226
|
+
for (const kind of RUNTIME_HOME_IMPORT_KINDS) {
|
|
227
|
+
const entry = authProfile.imports[kind];
|
|
225
228
|
if (!entry) {
|
|
226
229
|
continue;
|
|
227
230
|
}
|
|
@@ -17,9 +17,9 @@ export declare const materializedInputSchema: z.ZodObject<{
|
|
|
17
17
|
id: z.ZodString;
|
|
18
18
|
declaredBy: z.ZodString;
|
|
19
19
|
kind: z.ZodEnum<{
|
|
20
|
-
moltnet: "moltnet";
|
|
21
|
-
memory: "memory";
|
|
22
20
|
volume: "volume";
|
|
21
|
+
memory: "memory";
|
|
22
|
+
moltnet: "moltnet";
|
|
23
23
|
git: "git";
|
|
24
24
|
feed: "feed";
|
|
25
25
|
bundle: "bundle";
|
|
@@ -81,9 +81,9 @@ export declare const materializedMomentSchema: z.ZodObject<{
|
|
|
81
81
|
id: z.ZodString;
|
|
82
82
|
declaredBy: z.ZodString;
|
|
83
83
|
kind: z.ZodEnum<{
|
|
84
|
-
moltnet: "moltnet";
|
|
85
|
-
memory: "memory";
|
|
86
84
|
volume: "volume";
|
|
85
|
+
memory: "memory";
|
|
86
|
+
moltnet: "moltnet";
|
|
87
87
|
git: "git";
|
|
88
88
|
feed: "feed";
|
|
89
89
|
bundle: "bundle";
|
|
@@ -228,9 +228,9 @@ export declare const materializedMomentJsonSchema: z.core.ZodStandardJSONSchemaP
|
|
|
228
228
|
id: z.ZodString;
|
|
229
229
|
declaredBy: z.ZodString;
|
|
230
230
|
kind: z.ZodEnum<{
|
|
231
|
-
moltnet: "moltnet";
|
|
232
|
-
memory: "memory";
|
|
233
231
|
volume: "volume";
|
|
232
|
+
memory: "memory";
|
|
233
|
+
moltnet: "moltnet";
|
|
234
234
|
git: "git";
|
|
235
235
|
feed: "feed";
|
|
236
236
|
bundle: "bundle";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ResolvedAuthProfile } from "../../../auth/index.js";
|
|
1
2
|
import { type DaimonControlCall } from "../../../runtime/daimon/control.js";
|
|
2
3
|
import { type UsageRecord } from "../../../runtime/usageLedger.js";
|
|
3
4
|
import { type TrialDocker } from "./docker.js";
|
|
@@ -27,6 +28,8 @@ export interface TrialWake {
|
|
|
27
28
|
usage: UsageRecord[];
|
|
28
29
|
/** The engine's own newest session record, bounded; null when none exists. */
|
|
29
30
|
transcript: string | null;
|
|
31
|
+
/** Per model request of this wake, the tool-call names its response carried; null where the runtime could not say. */
|
|
32
|
+
requestToolCalls: (readonly string[] | null)[];
|
|
30
33
|
}
|
|
31
34
|
export interface BootedTrial {
|
|
32
35
|
container: string;
|
|
@@ -44,10 +47,26 @@ export interface PreparedTrial {
|
|
|
44
47
|
runtimeRoot: string;
|
|
45
48
|
engines: string[];
|
|
46
49
|
agentId: string;
|
|
47
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Boots the organization. `gateway` is null for an organization on no
|
|
52
|
+
* gatewayed engine; `realms` is a profile view holding only the
|
|
53
|
+
* volume-held logins (`spawnfile auth login`) this organization mounts.
|
|
54
|
+
*/
|
|
55
|
+
boot(gateway: TrainingGatewayAccess | null, options?: {
|
|
48
56
|
readyTimeoutMs?: number;
|
|
57
|
+
realms?: ResolvedAuthProfile;
|
|
49
58
|
}): Promise<BootedTrial>;
|
|
59
|
+
/** Runs the organization's own `auth <engine> login` attached to the operator's terminal, or returns its argv on `dryRun`. */
|
|
60
|
+
login(realms: ResolvedAuthProfile, options?: {
|
|
61
|
+
dryRun?: boolean;
|
|
62
|
+
}): Promise<readonly string[]>;
|
|
50
63
|
dispose(): Promise<void>;
|
|
51
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Readable and collision-free: trial ids may share long prefixes. The cut can
|
|
67
|
+
* land just after a hyphen, so it is trimmed: the slug names a kebab-case
|
|
68
|
+
* deployment, which refuses a doubled hyphen.
|
|
69
|
+
*/
|
|
70
|
+
export declare const trialSlug: (trialId: string) => string;
|
|
52
71
|
/** Compiles and builds the trial's one-agent organization under its own lineage, as production does. */
|
|
53
72
|
export declare const prepareTrial: (options: TrialOptions) => Promise<PreparedTrial>;
|