@tangle-network/agent-profile-materialize 0.25.3 → 0.26.0
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/index.d.ts +4 -5
- package/dist/index.js +3 -2
- package/dist/managed-workspace-bind.d.ts +1 -1
- package/dist/managed-workspace-bind.js +5 -5
- package/dist/prime-agent-dir.d.ts +18 -1
- package/dist/prime-agent-dir.js +20 -11
- package/dist/profile-start-check.d.ts +32 -0
- package/dist/profile-start-check.js +39 -0
- package/dist/secret-concurrent-revision.js +29 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -5,10 +5,9 @@ export type { HarnessId } from "./harness.js";
|
|
|
5
5
|
export { HARNESS_SKILL_DIRS, harnessAutoLoadsAgentContextFile, harnessAutoLoadsContextFile, harnessContextFile, isMaterializerHarness, MATERIALIZER_CONTEXT_PATHS, MATERIALIZER_HARNESSES, markMaterializerContextFile, skillDirForHarness, } from "./harness.js";
|
|
6
6
|
export * from "./harness-prompt.js";
|
|
7
7
|
export { type ConcurrentProfileRevision, ensurePublicConcurrentProfileRoots, type ManagedWorkspaceFileDigest, type ManagedWorkspaceManifest, preparePublicConcurrentProfileRevision, } from "./managed-workspace.js";
|
|
8
|
-
export type
|
|
9
|
-
export { openCodeMcpConfig } from "./mcp.js";
|
|
8
|
+
export { type OpenCodeMcpConfig, openCodeMcpConfig } from "./mcp.js";
|
|
10
9
|
export { isMaterializerMcpConfig } from "./mcp-config-ownership.js";
|
|
11
|
-
export
|
|
10
|
+
export * from "./model-id.js";
|
|
12
11
|
export { buildPiModelsConfig, buildPiModelsConfigFile, PI_MODELS_CONFIG_PATH, type PiModelsConfigFile, type PiModelsConfigInput, type PiRuntimePaths, resolvePiRuntimePaths, } from "./pi-models-config.js";
|
|
13
12
|
export { applyWorkspacePlan, applyWorkspacePlanWithSecretProvider, } from "./plan-application.js";
|
|
14
13
|
export { agentCandidateProfilePlanMaterial, canonicalizeAgentCandidateProfilePlan, captureAgentCandidateProfilePlan, hashWorkspacePlan, } from "./plan-digest.js";
|
|
@@ -16,14 +15,14 @@ export { takeSystemPromptBinding } from "./plan-prompt.js";
|
|
|
16
15
|
export { assertWorkspacePlanSupported, enforceWorkspacePlanSupport, } from "./plan-support.js";
|
|
17
16
|
export type { ApplyWorkspacePlanOptions, BindableLaunchControl, ExecutorSystemPromptBinding, PlanFile, PlanFileRoot, PlanFileSecretSlot, PlanRequirement, SkippableDimension, Unsupported, WorkspacePlan, WorkspacePlanApplication, WorkspacePlanArgument, WorkspacePlanArgumentTemplate, WorkspacePlanConfigValue, WorkspacePlanReceipt, WorkspacePlanSecretSegment, WorkspacePlanSpawnInputs, WorkspacePlanSystemPromptBinding, WorkspacePlanWrittenFile, } from "./plan-types.js";
|
|
18
17
|
export { BINDABLE_LAUNCH_CONTROLS, EXECUTOR_SYSTEM_PROMPT_BINDINGS, isExecutorSystemPromptBinding, isSkippableDimension, SKIPPABLE_DIMENSIONS, WorkspacePlanCleanupError, } from "./plan-types.js";
|
|
19
|
-
export type
|
|
20
|
-
export { materializePrimeProfileControls, prunePrimeProfileMaterial, seedPrimeProfileSubagents, writePrimeAgentFile, } from "./prime-agent-dir.js";
|
|
18
|
+
export { materializePrimeProfileControls, type PrimeMaterializeOptions, primeHarnessStatePath, prunePrimeProfileMaterial, seedPrimeProfileSubagents, writePrimeAgentFile, } from "./prime-agent-dir.js";
|
|
21
19
|
export type { PrimeProfileErrorKind, PrimeThinkingLevel, } from "./prime-fork.js";
|
|
22
20
|
export { matchPrimeKernelDeadMarker, PRIME_AGENT_DIR_ENV_VAR, PRIME_AGENT_DIR_ENV_VARS, PRIME_FORK_INSTALL, PRIME_FORK_PIN, PRIME_HARNESS_STATE_ENV_DENYLIST, PRIME_KERNEL_DEAD_MARKERS, PRIME_KERNEL_ENV_PASSTHROUGH, PRIME_MCP_UNSUPPORTED_REASON, PRIME_THINKING_LEVELS, PrimeHarnessStateError, PrimeProfileError, parsePrimeModelsJson, primeAgentDirEnv, primeApiKeyEnvNames, primeThinkingLevel, stripPrimeJsonComments, } from "./prime-fork.js";
|
|
23
21
|
export type { PrimeProfileControls, PrimeProfileSkill, PrimeProfileSubagent, } from "./prime-profile.js";
|
|
24
22
|
export { assertPrimeModelAgreement, hasPrimeProfileMaterial, primeProfileNeedsAgentDir, primeSubagentEntryId, readPrimeProfileControls, } from "./prime-profile.js";
|
|
25
23
|
export * from "./profile-bundle-cache.js";
|
|
26
24
|
export { executionControlConflict, materializeProfile, UNAVAILABLE_AGENT_PROFILE_SECRET_PROVIDER, } from "./profile-materializer.js";
|
|
25
|
+
export * from "./profile-start-check.js";
|
|
27
26
|
export type { ResolveAgentProfileResourcesOptions } from "./resource-resolution.js";
|
|
28
27
|
export { normalizeSkillMd, resolveAgentProfileResources, } from "./resource-resolution.js";
|
|
29
28
|
export { prepareSecretConcurrentProfileRevision } from "./secret-concurrent-revision.js";
|
package/dist/index.js
CHANGED
|
@@ -5,17 +5,18 @@ export * from "./harness-prompt.js";
|
|
|
5
5
|
export { ensurePublicConcurrentProfileRoots, preparePublicConcurrentProfileRevision, } from "./managed-workspace.js";
|
|
6
6
|
export { openCodeMcpConfig } from "./mcp.js";
|
|
7
7
|
export { isMaterializerMcpConfig } from "./mcp-config-ownership.js";
|
|
8
|
-
export
|
|
8
|
+
export * from "./model-id.js";
|
|
9
9
|
export { buildPiModelsConfig, buildPiModelsConfigFile, PI_MODELS_CONFIG_PATH, resolvePiRuntimePaths, } from "./pi-models-config.js";
|
|
10
10
|
export { applyWorkspacePlan, applyWorkspacePlanWithSecretProvider, } from "./plan-application.js";
|
|
11
11
|
export { agentCandidateProfilePlanMaterial, canonicalizeAgentCandidateProfilePlan, captureAgentCandidateProfilePlan, hashWorkspacePlan, } from "./plan-digest.js";
|
|
12
12
|
export { takeSystemPromptBinding } from "./plan-prompt.js";
|
|
13
13
|
export { assertWorkspacePlanSupported, enforceWorkspacePlanSupport, } from "./plan-support.js";
|
|
14
14
|
export { BINDABLE_LAUNCH_CONTROLS, EXECUTOR_SYSTEM_PROMPT_BINDINGS, isExecutorSystemPromptBinding, isSkippableDimension, SKIPPABLE_DIMENSIONS, WorkspacePlanCleanupError, } from "./plan-types.js";
|
|
15
|
-
export { materializePrimeProfileControls, prunePrimeProfileMaterial, seedPrimeProfileSubagents, writePrimeAgentFile, } from "./prime-agent-dir.js";
|
|
15
|
+
export { materializePrimeProfileControls, primeHarnessStatePath, prunePrimeProfileMaterial, seedPrimeProfileSubagents, writePrimeAgentFile, } from "./prime-agent-dir.js";
|
|
16
16
|
export { matchPrimeKernelDeadMarker, PRIME_AGENT_DIR_ENV_VAR, PRIME_AGENT_DIR_ENV_VARS, PRIME_FORK_INSTALL, PRIME_FORK_PIN, PRIME_HARNESS_STATE_ENV_DENYLIST, PRIME_KERNEL_DEAD_MARKERS, PRIME_KERNEL_ENV_PASSTHROUGH, PRIME_MCP_UNSUPPORTED_REASON, PRIME_THINKING_LEVELS, PrimeHarnessStateError, PrimeProfileError, parsePrimeModelsJson, primeAgentDirEnv, primeApiKeyEnvNames, primeThinkingLevel, stripPrimeJsonComments, } from "./prime-fork.js";
|
|
17
17
|
export { assertPrimeModelAgreement, hasPrimeProfileMaterial, primeProfileNeedsAgentDir, primeSubagentEntryId, readPrimeProfileControls, } from "./prime-profile.js";
|
|
18
18
|
export * from "./profile-bundle-cache.js";
|
|
19
19
|
export { executionControlConflict, materializeProfile, UNAVAILABLE_AGENT_PROFILE_SECRET_PROVIDER, } from "./profile-materializer.js";
|
|
20
|
+
export * from "./profile-start-check.js";
|
|
20
21
|
export { normalizeSkillMd, resolveAgentProfileResources, } from "./resource-resolution.js";
|
|
21
22
|
export { prepareSecretConcurrentProfileRevision } from "./secret-concurrent-revision.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { WorkspacePlan, WorkspacePlanApplication } from "./plan-types.js";
|
|
2
2
|
export declare function bindConcurrentLaunch(plan: WorkspacePlan, application: WorkspacePlanApplication, revisionWorkspaceDir: string, options?: {
|
|
3
|
-
readonly
|
|
3
|
+
readonly secretOpenCodeConfigDirectory?: boolean;
|
|
4
4
|
}): WorkspacePlanApplication["spawn"];
|
|
@@ -4,15 +4,15 @@ import { join } from "node:path";
|
|
|
4
4
|
* skills, and its standard agent and command definitions (OpenCode reads
|
|
5
5
|
* `.opencode/{agent,agents}/**\/*.md` and `.opencode/{command,commands}/**\/*.md`).
|
|
6
6
|
*/
|
|
7
|
-
const SECRET_REVISION_NATIVE_PATH = /^(
|
|
7
|
+
const SECRET_REVISION_NATIVE_PATH = /^(?:\.opencode\/skills\/|\.opencode\/(?:agents?|commands?)\/(?:[^./][^/]*\/)*[^./][^/]*\.md$)/u;
|
|
8
8
|
/**
|
|
9
|
-
* A secret OpenCode revision
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* A secret OpenCode revision binds its immutable, digest-attested .opencode
|
|
10
|
+
* directory explicitly, so native agent, command and skill resources remain
|
|
11
|
+
* visible without discovering mutable shared-workspace configuration. The binding stays limited to
|
|
12
12
|
* OpenCode's standard paths, never an app's own directory.
|
|
13
13
|
*/
|
|
14
14
|
function ridesSecretRevision(plan, file, options) {
|
|
15
|
-
return (options.
|
|
15
|
+
return (options.secretOpenCodeConfigDirectory === true &&
|
|
16
16
|
plan.harness === "opencode" &&
|
|
17
17
|
(file.root ?? "workspace") === "workspace" &&
|
|
18
18
|
SECRET_REVISION_NATIVE_PATH.test(file.relPath));
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
export declare function writePrimeAgentFile(path: string, data: string, mode?: number): void;
|
|
2
|
+
/**
|
|
3
|
+
* File access on a prime agent dir. The default reads and writes the local
|
|
4
|
+
* filesystem as the calling process. An executor whose agent dir belongs to
|
|
5
|
+
* another user (a root sidecar that demotes prime-agent) passes reads it took
|
|
6
|
+
* as that user and replays the writes as that user, so it never touches the
|
|
7
|
+
* agent's files with its own rights.
|
|
8
|
+
*/
|
|
9
|
+
export interface PrimeAgentDirIo {
|
|
10
|
+
/** The file's text, or undefined when it does not exist. */
|
|
11
|
+
read(path: string): string | undefined;
|
|
12
|
+
/** Replace the whole file: atomic and owner-only. */
|
|
13
|
+
write(path: string, data: string): void;
|
|
14
|
+
}
|
|
15
|
+
/** The fork's continual-harness store, the only agent-dir file a materialization reads. */
|
|
16
|
+
export declare function primeHarnessStatePath(agentDir: string): string;
|
|
2
17
|
export interface PrimeMaterializeOptions {
|
|
3
18
|
/**
|
|
4
19
|
* Where the FLAG-NAMED files go — the prompt files and the skills root.
|
|
@@ -14,6 +29,8 @@ export interface PrimeMaterializeOptions {
|
|
|
14
29
|
* (currently: adopting entries a pre-shared executor left behind).
|
|
15
30
|
*/
|
|
16
31
|
warn?: (msg: string, meta?: Record<string, unknown>) => void;
|
|
32
|
+
/** Agent-dir file access; the local filesystem when omitted. */
|
|
33
|
+
io?: PrimeAgentDirIo;
|
|
17
34
|
}
|
|
18
35
|
/**
|
|
19
36
|
* Materialize the validated controls and return the extra spawn args that bind
|
|
@@ -43,5 +60,5 @@ export declare function prunePrimeProfileMaterial(agentDir: string, options?: Pi
|
|
|
43
60
|
* {@link PrimeHarnessStateError}: the file is the agent's own self-modification
|
|
44
61
|
* state, and overwriting it destroys what the run was supposed to observe.
|
|
45
62
|
*/
|
|
46
|
-
export declare function seedPrimeProfileSubagents(agentDir: string, subagents: PrimeProfileSubagent[], warn?: (msg: string, meta?: Record<string, unknown>) => void): void;
|
|
63
|
+
export declare function seedPrimeProfileSubagents(agentDir: string, subagents: PrimeProfileSubagent[], warn?: (msg: string, meta?: Record<string, unknown>) => void, io?: PrimeAgentDirIo): void;
|
|
47
64
|
import type { PrimeProfileControls, PrimeProfileSubagent } from "./prime-profile.js";
|
package/dist/prime-agent-dir.js
CHANGED
|
@@ -4,6 +4,14 @@ export function writePrimeAgentFile(path, data, mode = 0o600) {
|
|
|
4
4
|
writeFileSync(temp, data, { mode });
|
|
5
5
|
renameSync(temp, path);
|
|
6
6
|
}
|
|
7
|
+
const localPrimeAgentDirIo = {
|
|
8
|
+
read: (path) => (existsSync(path) ? readFileSync(path, "utf8") : undefined),
|
|
9
|
+
write: (path, data) => writePrimeAgentFile(path, data),
|
|
10
|
+
};
|
|
11
|
+
/** The fork's continual-harness store, the only agent-dir file a materialization reads. */
|
|
12
|
+
export function primeHarnessStatePath(agentDir) {
|
|
13
|
+
return join(agentDir, PRIME_HARNESS_DIR_NAME, PRIME_HARNESS_STATE_FILE);
|
|
14
|
+
}
|
|
7
15
|
/**
|
|
8
16
|
* Materialize the validated controls and return the extra spawn args that bind
|
|
9
17
|
* them. Runs before every spawn (same place models.json is materialized), so a
|
|
@@ -11,30 +19,30 @@ export function writePrimeAgentFile(path, data, mode = 0o600) {
|
|
|
11
19
|
* process.
|
|
12
20
|
*/
|
|
13
21
|
export function materializePrimeProfileControls(agentDir, controls, options = {}) {
|
|
14
|
-
const { flagFileRoot = agentDir, warn } = options;
|
|
22
|
+
const { flagFileRoot = agentDir, warn, io = localPrimeAgentDirIo } = options;
|
|
15
23
|
const args = [];
|
|
16
24
|
const profileDir = join(flagFileRoot, PRIME_PROFILE_DIR_NAME);
|
|
17
25
|
if (controls.systemPrompt !== undefined) {
|
|
18
26
|
const promptPath = join(profileDir, PRIME_SYSTEM_PROMPT_FILE);
|
|
19
|
-
|
|
27
|
+
io.write(promptPath, controls.systemPrompt);
|
|
20
28
|
args.push("--system-prompt", promptPath);
|
|
21
29
|
}
|
|
22
30
|
if (controls.appendSystemPrompt !== undefined) {
|
|
23
31
|
const appendPath = join(profileDir, PRIME_APPEND_SYSTEM_PROMPT_FILE);
|
|
24
|
-
|
|
32
|
+
io.write(appendPath, controls.appendSystemPrompt);
|
|
25
33
|
args.push("--append-system-prompt", appendPath);
|
|
26
34
|
}
|
|
27
35
|
if (controls.instructions !== undefined) {
|
|
28
|
-
|
|
36
|
+
io.write(join(agentDir, PRIME_CONTEXT_FILE), `${controls.instructions}\n`);
|
|
29
37
|
}
|
|
30
38
|
if (controls.skills.length > 0) {
|
|
31
39
|
const skillsRoot = join(profileDir, PRIME_SKILLS_DIR_NAME);
|
|
32
40
|
for (const skill of controls.skills) {
|
|
33
|
-
|
|
41
|
+
io.write(join(skillsRoot, skill.name, "SKILL.md"), normalizeSkillMd(skill.name, skill.content));
|
|
34
42
|
}
|
|
35
43
|
args.push("--skill", skillsRoot);
|
|
36
44
|
}
|
|
37
|
-
seedPrimeProfileSubagents(agentDir, controls.subagents, warn);
|
|
45
|
+
seedPrimeProfileSubagents(agentDir, controls.subagents, warn, io);
|
|
38
46
|
return args;
|
|
39
47
|
}
|
|
40
48
|
/**
|
|
@@ -65,13 +73,14 @@ export function prunePrimeProfileMaterial(agentDir, options = {}) {
|
|
|
65
73
|
* {@link PrimeHarnessStateError}: the file is the agent's own self-modification
|
|
66
74
|
* state, and overwriting it destroys what the run was supposed to observe.
|
|
67
75
|
*/
|
|
68
|
-
export function seedPrimeProfileSubagents(agentDir, subagents, warn) {
|
|
69
|
-
const statePath =
|
|
76
|
+
export function seedPrimeProfileSubagents(agentDir, subagents, warn, io = localPrimeAgentDirIo) {
|
|
77
|
+
const statePath = primeHarnessStatePath(agentDir);
|
|
70
78
|
let state = {};
|
|
71
|
-
|
|
79
|
+
const stored = io.read(statePath);
|
|
80
|
+
if (stored !== undefined) {
|
|
72
81
|
let parsed;
|
|
73
82
|
try {
|
|
74
|
-
parsed = JSON.parse(
|
|
83
|
+
parsed = JSON.parse(stored);
|
|
75
84
|
}
|
|
76
85
|
catch (err) {
|
|
77
86
|
throw new PrimeHarnessStateError(statePath, err instanceof Error ? err.message : String(err));
|
|
@@ -149,7 +158,7 @@ export function seedPrimeProfileSubagents(agentDir, subagents, warn) {
|
|
|
149
158
|
}
|
|
150
159
|
if (!changed)
|
|
151
160
|
return;
|
|
152
|
-
|
|
161
|
+
io.write(statePath, `${JSON.stringify({
|
|
153
162
|
...state,
|
|
154
163
|
schema: typeof state.schema === "number" ? state.schema : 1,
|
|
155
164
|
entries,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { BindableLaunchControl } from "./plan-types.js";
|
|
2
|
+
import { type ResolveAgentProfileResourcesOptions } from "./resource-resolution.js";
|
|
3
|
+
/** Whether a profile starts on a harness, answered before any spawn. */
|
|
4
|
+
export interface ProfileStartCheck {
|
|
5
|
+
readonly ok: boolean;
|
|
6
|
+
/** Each error a spawn would raise, in the materializer's own words. */
|
|
7
|
+
readonly refusals: readonly string[];
|
|
8
|
+
/** Controls `resources.failOnError: false` lets the run skip, as a spawn logs them. */
|
|
9
|
+
readonly warnings: readonly string[];
|
|
10
|
+
}
|
|
11
|
+
export interface CheckProfileStartsOptions extends ResolveAgentProfileResourcesOptions {
|
|
12
|
+
/** Harness to check; defaults to the profile's own `harness`. */
|
|
13
|
+
harness?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Launch controls the launcher binds. Defaults to what the maintained
|
|
16
|
+
* launchers bind: `systemPrompt` on opencode (the sidecar and the opencode
|
|
17
|
+
* provider both pass it), nothing elsewhere, where binds change no refusal.
|
|
18
|
+
*/
|
|
19
|
+
binds?: readonly BindableLaunchControl[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Run the spawn path's profile steps without spawning: resolve resources,
|
|
23
|
+
* materialize for the harness, then enforce `resources.failOnError`.
|
|
24
|
+
*
|
|
25
|
+
* A refusal here is the error a spawn gives, word for word, because it is the
|
|
26
|
+
* same code. Profile builders and validators call this instead of copying the
|
|
27
|
+
* native tool maps, which change whenever a harness does. Inline resources
|
|
28
|
+
* need no network; GitHub refs are fetched exactly as a spawn fetches them.
|
|
29
|
+
* Model and harness compatibility is not decided here: its owner is
|
|
30
|
+
* `harnessModelSupportFor` in `@tangle-network/cli-agent-registry`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function checkProfileStarts(input: unknown, options?: CheckProfileStartsOptions): Promise<ProfileStartCheck>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { agentProfileSchema } from "@tangle-network/agent-interface";
|
|
2
|
+
import { assertMaterializerHarness } from "./harness.js";
|
|
3
|
+
import { enforceWorkspacePlanSupport } from "./plan-support.js";
|
|
4
|
+
import { materializeProfile } from "./profile-materializer.js";
|
|
5
|
+
import { resolveAgentProfileResources, } from "./resource-resolution.js";
|
|
6
|
+
/**
|
|
7
|
+
* Run the spawn path's profile steps without spawning: resolve resources,
|
|
8
|
+
* materialize for the harness, then enforce `resources.failOnError`.
|
|
9
|
+
*
|
|
10
|
+
* A refusal here is the error a spawn gives, word for word, because it is the
|
|
11
|
+
* same code. Profile builders and validators call this instead of copying the
|
|
12
|
+
* native tool maps, which change whenever a harness does. Inline resources
|
|
13
|
+
* need no network; GitHub refs are fetched exactly as a spawn fetches them.
|
|
14
|
+
* Model and harness compatibility is not decided here: its owner is
|
|
15
|
+
* `harnessModelSupportFor` in `@tangle-network/cli-agent-registry`.
|
|
16
|
+
*/
|
|
17
|
+
export async function checkProfileStarts(input, options = {}) {
|
|
18
|
+
const { harness: harnessOption, binds, ...resolveOptions } = options;
|
|
19
|
+
try {
|
|
20
|
+
const parsed = agentProfileSchema.parse(input);
|
|
21
|
+
const harness = harnessOption ?? parsed.harness;
|
|
22
|
+
if (harness === undefined) {
|
|
23
|
+
return refused(["harness: the profile names no harness to start on"]);
|
|
24
|
+
}
|
|
25
|
+
assertMaterializerHarness(harness);
|
|
26
|
+
const profile = await resolveAgentProfileResources(parsed, resolveOptions);
|
|
27
|
+
const plan = materializeProfile(profile, harness, {
|
|
28
|
+
binds: binds ?? (harness === "opencode" ? ["systemPrompt"] : []),
|
|
29
|
+
});
|
|
30
|
+
const warnings = enforceWorkspacePlanSupport(plan, profile.resources?.failOnError);
|
|
31
|
+
return { ok: true, refusals: [], warnings };
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return refused([error instanceof Error ? error.message : String(error)]);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function refused(refusals) {
|
|
38
|
+
return { ok: false, refusals, warnings: [] };
|
|
39
|
+
}
|
|
@@ -20,7 +20,20 @@ export async function prepareSecretConcurrentProfileRevision(input) {
|
|
|
20
20
|
!input.ownerId) {
|
|
21
21
|
throw new Error("Secret concurrent profile needs a root executor and reserved identity");
|
|
22
22
|
}
|
|
23
|
+
for (const name of [
|
|
24
|
+
"OPENCODE_DISABLE_PROJECT_CONFIG",
|
|
25
|
+
"OPENCODE_CONFIG_DIR",
|
|
26
|
+
"TANGLE_SHARED_WORKSPACE",
|
|
27
|
+
]) {
|
|
28
|
+
if (Object.hasOwn(input.plan.env, name)) {
|
|
29
|
+
throw new Error(`Secret OpenCode reserves ${name} for its launch binding`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
23
32
|
let plan = prepareExplicitOpenCodePlan(input.plan);
|
|
33
|
+
if (plan.files.some((file) => (file.root ?? "workspace") === "workspace" &&
|
|
34
|
+
file.relPath.startsWith("reference/"))) {
|
|
35
|
+
throw new Error("Secret OpenCode cannot bind cwd-relative reference resources to a shared data workspace");
|
|
36
|
+
}
|
|
24
37
|
if (input.providerConfig) {
|
|
25
38
|
plan = {
|
|
26
39
|
...plan,
|
|
@@ -53,7 +66,13 @@ export async function prepareSecretConcurrentProfileRevision(input) {
|
|
|
53
66
|
recursive: true,
|
|
54
67
|
mode: 0o700,
|
|
55
68
|
});
|
|
69
|
+
mkdirSync(join(prepared.root, "workspace", ".opencode"), {
|
|
70
|
+
recursive: true,
|
|
71
|
+
mode: 0o700,
|
|
72
|
+
});
|
|
56
73
|
const identity = createHmac("sha256", input.namingKey)
|
|
74
|
+
.update(input.sharedWorkspaceDir)
|
|
75
|
+
.update("\0")
|
|
57
76
|
.update(input.ownerId)
|
|
58
77
|
.update("\0")
|
|
59
78
|
.update(String(input.subprocessUid))
|
|
@@ -61,7 +80,16 @@ export async function prepareSecretConcurrentProfileRevision(input) {
|
|
|
61
80
|
.update(prepared.manifest.materializedDigest)
|
|
62
81
|
.digest("hex");
|
|
63
82
|
const directory = join(input.launchRoot, `revision-${identity}`);
|
|
64
|
-
const
|
|
83
|
+
const bound = bindConcurrentLaunch(plan, prepared.application, join(directory, "workspace"), { secretOpenCodeConfigDirectory: true });
|
|
84
|
+
const spawn = {
|
|
85
|
+
...bound,
|
|
86
|
+
env: {
|
|
87
|
+
...bound.env,
|
|
88
|
+
OPENCODE_DISABLE_PROJECT_CONFIG: "1",
|
|
89
|
+
OPENCODE_CONFIG_DIR: join(directory, "workspace", ".opencode"),
|
|
90
|
+
TANGLE_SHARED_WORKSPACE: input.sharedWorkspaceDir,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
65
93
|
prepared.manifest.launchDigest = createHash("sha256")
|
|
66
94
|
.update(JSON.stringify(spawn))
|
|
67
95
|
.digest("hex");
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-profile-materialize",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Materialize an AgentProfile into the native per-harness workspace files (the one shared materializer for cli-bridge, agent-
|
|
3
|
+
"version": "0.26.0",
|
|
4
|
+
"description": "Materialize an AgentProfile into the native per-harness workspace files (the one shared materializer for cli-bridge, agent-container, and VB).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/tangle-network/agent-
|
|
8
|
+
"url": "git+https://github.com/tangle-network/agent-container.git",
|
|
9
9
|
"directory": "packages/agent-profile-materialize"
|
|
10
10
|
},
|
|
11
11
|
"main": "./dist/index.js",
|