@llblab/pi-actors 0.45.0 → 0.46.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/AGENTS.md +10 -6
- package/CHANGELOG.md +14 -1
- package/README.md +28 -12
- package/dist/fixtures/protocol/recipe-summary.json +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +10 -110
- package/dist/lib/async-runs.d.ts +4 -1
- package/dist/lib/async-runs.js +22 -23
- package/dist/lib/automatic-review-runtime.d.ts +2 -0
- package/dist/lib/automatic-review-runtime.js +12 -5
- package/dist/lib/draft-sleep.js +0 -1
- package/dist/lib/extension-runtime.d.ts +21 -0
- package/dist/lib/extension-runtime.js +122 -0
- package/dist/lib/inspector.js +45 -7
- package/dist/lib/paths.d.ts +0 -1
- package/dist/lib/paths.js +0 -7
- package/dist/lib/prompts.d.ts +1 -1
- package/dist/lib/prompts.js +2 -2
- package/dist/lib/recipes-context.js +2 -2
- package/dist/lib/recipes-references.d.ts +24 -9
- package/dist/lib/recipes-references.js +152 -126
- package/dist/lib/runtime.d.ts +0 -1
- package/dist/lib/runtime.js +1 -3
- package/dist/lib/tools-inspect.d.ts +0 -1
- package/dist/lib/tools-inspect.js +35 -8
- package/dist/lib/tools-local.d.ts +2 -0
- package/dist/lib/tools-local.js +1 -1
- package/dist/lib/tools-spawn.d.ts +2 -0
- package/dist/lib/tools-spawn.js +24 -52
- package/dist/scripts/async-runner.mjs +0 -16
- package/dist/scripts/build-dist.mjs +13 -4
- package/dist/skills/actors/SKILL.md +6 -6
- package/dist/skills/actors/recipes/recipe-validate.json +11 -0
- package/{recipes/utility-coordinator-lock-snapshot.json → dist/skills/actors/recipes/resource-locker-snapshot.json} +1 -3
- package/dist/{recipes → skills/actors/recipes}/resource-locker.json +1 -3
- package/dist/{recipes/utility-run-ops-snapshot.json → skills/actors/recipes/run-ops-snapshot.json} +1 -3
- package/dist/skills/actors/recipes/run-summary.json +9 -0
- package/dist/{scripts/locker.mjs → skills/actors/scripts/resource-locker.mjs} +2 -23
- package/dist/skills/actors/scripts/run-utils.mjs +164 -0
- package/{scripts → dist/skills/actors/scripts}/validate-recipe.mjs +134 -18
- package/dist/skills/artifacts/SKILL.md +16 -0
- package/{recipes/pipeline-artifact-bundle.json → dist/skills/artifacts/recipes/bundle.json} +4 -4
- package/dist/{recipes/utility-artifact-write.json → skills/artifacts/recipes/file-write.json} +1 -3
- package/dist/{recipes/utility-artifact-manifest.json → skills/artifacts/recipes/manifest.json} +1 -3
- package/{recipes/pipeline-artifact-report.json → dist/skills/artifacts/recipes/report.json} +2 -2
- package/dist/{recipes/pipeline-artifact-write.json → skills/artifacts/recipes/write.json} +3 -3
- package/dist/skills/artifacts/scripts/artifact-utils.mjs +63 -0
- package/dist/skills/media/SKILL.md +16 -0
- package/dist/{recipes/pipeline-media-library.json → skills/media/recipes/library.json} +2 -2
- package/{recipes/music-player.json → dist/skills/media/recipes/player.json} +1 -3
- package/dist/{recipes/utility-playlist-build.json → skills/media/recipes/playlist-build.json} +1 -3
- package/dist/skills/media/scripts/media-utils.mjs +47 -0
- package/dist/{scripts → skills/media/scripts}/music-player.mjs +9 -3
- package/dist/skills/project-work/SKILL.md +16 -0
- package/dist/skills/project-work/recipes/changelog-section.json +11 -0
- package/{recipes/pipeline-docs-maintenance.json → dist/skills/project-work/recipes/docs-maintenance.json} +4 -4
- package/dist/skills/project-work/recipes/package-summary.json +9 -0
- package/{recipes/pipeline-release-readiness.json → dist/skills/project-work/recipes/release-readiness.json} +6 -6
- package/dist/{recipes/pipeline-release-summary.json → skills/project-work/recipes/release-summary.json} +5 -5
- package/{recipes/pipeline-repo-health.json → dist/skills/project-work/recipes/repo-health.json} +6 -6
- package/{recipes/pipeline-async-run-ops.json → dist/skills/project-work/recipes/run-ops.json} +3 -3
- package/dist/skills/project-work/recipes/skill-summary.json +11 -0
- package/dist/skills/project-work/scripts/project-utils.mjs +89 -0
- package/dist/skills/recipe-memory/SKILL.md +16 -0
- package/dist/skills/swarm/SKILL.md +4 -4
- package/{recipes/pipeline-architect-coordinator.json → dist/skills/swarm/recipes/architect.json} +5 -5
- package/{recipes/pipeline-checkpoint-continuation.json → dist/skills/swarm/recipes/checkpoint-continuation.json} +3 -3
- package/dist/{recipes/pipeline-development-tasking.json → skills/swarm/recipes/development-tasking.json} +4 -4
- package/dist/{recipes/lens-swarm.json → skills/swarm/recipes/lens-review.json} +1 -1
- package/dist/{recipes/pipeline-quorum-review.json → skills/swarm/recipes/quorum-review.json} +4 -4
- package/{recipes/pipeline-research-synthesis.json → dist/skills/swarm/recipes/research-synthesis.json} +6 -6
- package/{recipes/pipeline-review-readiness.json → dist/skills/swarm/recipes/review-readiness.json} +1 -1
- package/{recipes/subagents-prompts.json → dist/skills/swarm/recipes/subagent-prompts.json} +1 -1
- package/{recipes → dist/skills/swarm/recipes}/subagent-quorum.json +1 -1
- package/dist/{recipes → skills/swarm/recipes}/subagent-review-coordinator.json +6 -6
- package/docs/actor-inspector.md +4 -3
- package/docs/async-runs.md +2 -2
- package/docs/recipe-library.md +23 -23
- package/docs/releasing.md +2 -2
- package/docs/template-recipes.md +30 -14
- package/docs/tool-registry.md +2 -2
- package/fixtures/protocol/recipe-summary.json +1 -1
- package/index.ts +18 -112
- package/lib/async-runs.ts +47 -24
- package/lib/automatic-review-runtime.ts +16 -3
- package/lib/draft-sleep.ts +0 -1
- package/lib/extension-runtime.ts +158 -0
- package/lib/inspector.ts +56 -11
- package/lib/paths.ts +0 -7
- package/lib/prompts.ts +2 -2
- package/lib/recipes-context.ts +2 -2
- package/lib/recipes-references.ts +223 -134
- package/lib/runtime.ts +1 -5
- package/lib/tools-inspect.ts +42 -9
- package/lib/tools-local.ts +2 -0
- package/lib/tools-spawn.ts +37 -74
- package/package.json +3 -5
- package/scripts/async-runner.mjs +0 -16
- package/scripts/build-dist.mjs +13 -4
- package/skills/actors/SKILL.md +6 -6
- package/skills/actors/recipes/recipe-validate.json +11 -0
- package/{dist/recipes/utility-coordinator-lock-snapshot.json → skills/actors/recipes/resource-locker-snapshot.json} +1 -3
- package/{recipes → skills/actors/recipes}/resource-locker.json +1 -3
- package/{recipes/utility-run-ops-snapshot.json → skills/actors/recipes/run-ops-snapshot.json} +1 -3
- package/skills/actors/recipes/run-summary.json +9 -0
- package/{scripts/locker.mjs → skills/actors/scripts/resource-locker.mjs} +2 -23
- package/skills/actors/scripts/run-utils.mjs +164 -0
- package/{dist → skills/actors}/scripts/validate-recipe.mjs +134 -18
- package/skills/artifacts/SKILL.md +16 -0
- package/{dist/recipes/pipeline-artifact-bundle.json → skills/artifacts/recipes/bundle.json} +4 -4
- package/{recipes/utility-artifact-write.json → skills/artifacts/recipes/file-write.json} +1 -3
- package/{recipes/utility-artifact-manifest.json → skills/artifacts/recipes/manifest.json} +1 -3
- package/{dist/recipes/pipeline-artifact-report.json → skills/artifacts/recipes/report.json} +2 -2
- package/{recipes/pipeline-artifact-write.json → skills/artifacts/recipes/write.json} +3 -3
- package/skills/artifacts/scripts/artifact-utils.mjs +63 -0
- package/skills/media/SKILL.md +16 -0
- package/{recipes/pipeline-media-library.json → skills/media/recipes/library.json} +2 -2
- package/{dist/recipes/music-player.json → skills/media/recipes/player.json} +1 -3
- package/{recipes/utility-playlist-build.json → skills/media/recipes/playlist-build.json} +1 -3
- package/skills/media/scripts/media-utils.mjs +47 -0
- package/{scripts → skills/media/scripts}/music-player.mjs +9 -3
- package/skills/project-work/SKILL.md +16 -0
- package/skills/project-work/recipes/changelog-section.json +11 -0
- package/{dist/recipes/pipeline-docs-maintenance.json → skills/project-work/recipes/docs-maintenance.json} +4 -4
- package/skills/project-work/recipes/package-summary.json +9 -0
- package/{dist/recipes/pipeline-release-readiness.json → skills/project-work/recipes/release-readiness.json} +6 -6
- package/{recipes/pipeline-release-summary.json → skills/project-work/recipes/release-summary.json} +5 -5
- package/{dist/recipes/pipeline-repo-health.json → skills/project-work/recipes/repo-health.json} +6 -6
- package/{dist/recipes/pipeline-async-run-ops.json → skills/project-work/recipes/run-ops.json} +3 -3
- package/skills/project-work/recipes/skill-summary.json +11 -0
- package/skills/project-work/scripts/project-utils.mjs +89 -0
- package/skills/recipe-memory/SKILL.md +16 -0
- package/skills/swarm/SKILL.md +4 -4
- package/{dist/recipes/pipeline-architect-coordinator.json → skills/swarm/recipes/architect.json} +5 -5
- package/{dist/recipes/pipeline-checkpoint-continuation.json → skills/swarm/recipes/checkpoint-continuation.json} +3 -3
- package/{recipes/pipeline-development-tasking.json → skills/swarm/recipes/development-tasking.json} +4 -4
- package/{recipes/lens-swarm.json → skills/swarm/recipes/lens-review.json} +1 -1
- package/{recipes/pipeline-quorum-review.json → skills/swarm/recipes/quorum-review.json} +4 -4
- package/{dist/recipes/pipeline-research-synthesis.json → skills/swarm/recipes/research-synthesis.json} +6 -6
- package/{dist/recipes/pipeline-review-readiness.json → skills/swarm/recipes/review-readiness.json} +1 -1
- package/{dist/recipes/subagents-prompts.json → skills/swarm/recipes/subagent-prompts.json} +1 -1
- package/{dist → skills/swarm}/recipes/subagent-quorum.json +1 -1
- package/{recipes → skills/swarm/recipes}/subagent-review-coordinator.json +6 -6
- package/dist/recipes/utility-changelog-section.json +0 -13
- package/dist/recipes/utility-package-summary.json +0 -11
- package/dist/recipes/utility-run-summary.json +0 -11
- package/dist/recipes/utility-skill-summary.json +0 -13
- package/dist/recipes/utility-validate-recipe.json +0 -13
- package/dist/scripts/recipe-utils.mjs +0 -405
- package/dist/scripts/release-gates.mjs +0 -278
- package/recipes/utility-changelog-section.json +0 -13
- package/recipes/utility-package-summary.json +0 -11
- package/recipes/utility-run-summary.json +0 -11
- package/recipes/utility-skill-summary.json +0 -13
- package/recipes/utility-validate-recipe.json +0 -13
- package/scripts/recipe-utils.mjs +0 -405
- package/scripts/release-gates.mjs +0 -278
- /package/dist/{recipes/utility-validation-wrapper.json → skills/actors/recipes/command-validate.json} +0 -0
- /package/dist/{recipes/utility-jsonl-tail.json → skills/actors/recipes/jsonl-tail.json} +0 -0
- /package/dist/{recipes/utility-run-state-files.json → skills/actors/recipes/run-state-files.json} +0 -0
- /package/dist/{recipes/utility-playlist-scan.json → skills/media/recipes/playlist-scan.json} +0 -0
- /package/dist/{recipes/utility-changelog-head.json → skills/project-work/recipes/changelog-head.json} +0 -0
- /package/dist/{recipes/utility-git-log.json → skills/project-work/recipes/git-log.json} +0 -0
- /package/dist/{recipes/utility-git-status.json → skills/project-work/recipes/git-status.json} +0 -0
- /package/dist/{recipes/utility-markdown-index.json → skills/project-work/recipes/markdown-index.json} +0 -0
- /package/dist/{recipes → skills/recipe-memory/recipes}/draft-review.json +0 -0
- /package/dist/{recipes → skills/recipe-memory/recipes}/tool-review.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-artifact.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-checkpoint.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-conflict-report.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-contradiction-map.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-critic.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-evidence-map.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-followup.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-judge.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-merge.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-normalize.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-plan.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-preflight.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-prompt.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-review.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-task-card.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-tools.json +0 -0
- /package/dist/{recipes → skills/swarm/recipes}/subagent-verify.json +0 -0
- /package/{recipes/utility-validation-wrapper.json → skills/actors/recipes/command-validate.json} +0 -0
- /package/{recipes/utility-jsonl-tail.json → skills/actors/recipes/jsonl-tail.json} +0 -0
- /package/{recipes/utility-run-state-files.json → skills/actors/recipes/run-state-files.json} +0 -0
- /package/{recipes/utility-playlist-scan.json → skills/media/recipes/playlist-scan.json} +0 -0
- /package/{recipes/utility-changelog-head.json → skills/project-work/recipes/changelog-head.json} +0 -0
- /package/{recipes/utility-git-log.json → skills/project-work/recipes/git-log.json} +0 -0
- /package/{recipes/utility-git-status.json → skills/project-work/recipes/git-status.json} +0 -0
- /package/{recipes/utility-markdown-index.json → skills/project-work/recipes/markdown-index.json} +0 -0
- /package/{recipes → skills/recipe-memory/recipes}/draft-review.json +0 -0
- /package/{recipes → skills/recipe-memory/recipes}/tool-review.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-artifact.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-checkpoint.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-conflict-report.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-contradiction-map.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-critic.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-evidence-map.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-followup.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-judge.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-merge.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-normalize.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-plan.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-preflight.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-prompt.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-review.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-task-card.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-tools.json +0 -0
- /package/{recipes → skills/swarm/recipes}/subagent-verify.json +0 -0
|
@@ -157,7 +157,7 @@ function inspectRuntime(view, input, ctx, deps) {
|
|
|
157
157
|
return runtimeTriage(ctx, deps);
|
|
158
158
|
throw new Error("inspect runtime supports view=status, view=runs, or view=triage.");
|
|
159
159
|
}
|
|
160
|
-
function inspectRecipes(view, deps) {
|
|
160
|
+
function inspectRecipes(view, deps, context) {
|
|
161
161
|
if (view !== "status" &&
|
|
162
162
|
view !== "summary" &&
|
|
163
163
|
view !== "doctor" &&
|
|
@@ -171,17 +171,44 @@ function inspectRecipes(view, deps) {
|
|
|
171
171
|
}
|
|
172
172
|
const discovered = RecipesDiscovery.discoverRecipeSources([
|
|
173
173
|
{ root: recipeRoot, defaultTool: true, mutableUsage: true },
|
|
174
|
-
{ root: deps.packagedRecipeRoot ?? Paths.getPackagedRecipeRoot() },
|
|
175
174
|
]);
|
|
176
|
-
const
|
|
175
|
+
const skillContext = context && typeof context === "object" && "activeSkillRecipeContext" in context
|
|
176
|
+
? context.activeSkillRecipeContext
|
|
177
|
+
: undefined;
|
|
178
|
+
const activeSkillContext = skillContext ?? RecipesReferences.EMPTY_ACTIVE_SKILL_RECIPE_CONTEXT;
|
|
179
|
+
const skillRecipeNamespaces = RecipesReferences.getActiveSkillRecipeNamespaces(activeSkillContext);
|
|
180
|
+
let skillRecipeComponents = [];
|
|
181
|
+
const skillRecipeComponentDiagnostics = [];
|
|
182
|
+
try {
|
|
183
|
+
skillRecipeComponents = RecipesReferences.listActiveSkillRecipeComponents(activeSkillContext).map((component) => ({
|
|
184
|
+
identity: component.identity,
|
|
185
|
+
source_kind: "active_skill_component",
|
|
186
|
+
skill: component.skill,
|
|
187
|
+
stem: component.stem,
|
|
188
|
+
imports: component.imports,
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
skillRecipeComponentDiagnostics.push({
|
|
193
|
+
error: error instanceof Error ? error.message : String(error),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
const discoverySummary = RecipesDiscovery.summarizeDiscovery(discovered);
|
|
177
197
|
const summary = {
|
|
178
|
-
...
|
|
179
|
-
|
|
198
|
+
...discoverySummary,
|
|
199
|
+
active: Array.isArray(discoverySummary.active)
|
|
200
|
+
? discoverySummary.active.map((entry) => ({
|
|
201
|
+
...entry,
|
|
202
|
+
source_kind: "user_registry_capability",
|
|
203
|
+
}))
|
|
204
|
+
: discoverySummary.active,
|
|
205
|
+
skill_recipe_components: skillRecipeComponents,
|
|
206
|
+
skill_recipe_component_diagnostics: skillRecipeComponentDiagnostics,
|
|
207
|
+
active_skill_recipe_identities: Object.keys(skillRecipeNamespaces).sort(),
|
|
180
208
|
skill_recipe_namespace_diagnostics: Object.entries(skillRecipeNamespaces)
|
|
181
209
|
.filter(([, roots]) => roots.length > 1)
|
|
182
|
-
.map(([name
|
|
210
|
+
.map(([name]) => ({
|
|
183
211
|
name,
|
|
184
|
-
roots,
|
|
185
212
|
error: `Ambiguous active Skill Recipe namespace ${name}`,
|
|
186
213
|
})),
|
|
187
214
|
drafts: RecipesDiscovery.listDraftRecipes(join(recipeRoot, "drafts")),
|
|
@@ -316,7 +343,7 @@ export function createInspectToolDefinition(deps = {}) {
|
|
|
316
343
|
details = inspectRuntime(view, input, ctx, deps);
|
|
317
344
|
}
|
|
318
345
|
else if (target === "recipes") {
|
|
319
|
-
details = inspectRecipes(view, deps);
|
|
346
|
+
details = inspectRecipes(view, deps, ctx);
|
|
320
347
|
}
|
|
321
348
|
else {
|
|
322
349
|
const run = parseRunTarget(target);
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
import * as ModelContext from "./model-context.ts";
|
|
7
7
|
import type { RegisteredTool } from "./config.ts";
|
|
8
8
|
import * as Execution from "./execution.ts";
|
|
9
|
+
import * as RecipesReferences from "./recipes-references.ts";
|
|
9
10
|
export interface RuntimeToolContext extends ModelContext.CurrentModelContext {
|
|
11
|
+
activeSkillRecipeContext?: RecipesReferences.ActiveSkillRecipeContext;
|
|
10
12
|
cwd: string;
|
|
11
13
|
sessionManager?: {
|
|
12
14
|
getSessionId?: () => string;
|
package/dist/lib/tools-local.js
CHANGED
|
@@ -160,7 +160,7 @@ export function createRuntimeToolDefinition(cfg, exec) {
|
|
|
160
160
|
tool: cfg.name,
|
|
161
161
|
policy_values: ModelContext.withCurrentModelValues({ ...(cfg.recipe?.values ?? {}), ...values }, ctx),
|
|
162
162
|
values: resolveRecipeToolValues(cfg, values, ctx),
|
|
163
|
-
}, ctx.cwd);
|
|
163
|
+
}, ctx.cwd, { skillContext: ctx.activeSkillRecipeContext });
|
|
164
164
|
return {
|
|
165
165
|
content: [
|
|
166
166
|
{
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* Owns the public spawn execution path for run-backed actors
|
|
5
5
|
*/
|
|
6
6
|
import * as ModelContext from "./model-context.ts";
|
|
7
|
+
import * as RecipesReferences from "./recipes-references.ts";
|
|
7
8
|
export interface SpawnToolContext extends ModelContext.CurrentModelContext {
|
|
9
|
+
activeSkillRecipeContext?: RecipesReferences.ActiveSkillRecipeContext;
|
|
8
10
|
cwd: string;
|
|
9
11
|
sessionManager?: {
|
|
10
12
|
getSessionId?: () => string;
|
package/dist/lib/tools-spawn.js
CHANGED
|
@@ -9,7 +9,6 @@ import * as AsyncRuns from "./async-runs.js";
|
|
|
9
9
|
import { withFileMutationLock } from "./file-state.js";
|
|
10
10
|
import * as ModelContext from "./model-context.js";
|
|
11
11
|
import * as Paths from "./paths.js";
|
|
12
|
-
import * as RecipesDiscovery from "./recipes-discovery.js";
|
|
13
12
|
import * as RecipesUsage from "./recipes-usage.js";
|
|
14
13
|
import * as Schema from "./schema.js";
|
|
15
14
|
import * as ToolsResponse from "./tools-response.js";
|
|
@@ -18,17 +17,6 @@ const maybeJsonText = ToolsResponse.maybeJsonText;
|
|
|
18
17
|
function getRunOwnerId(ctx) {
|
|
19
18
|
return ctx.sessionManager?.getSessionId?.();
|
|
20
19
|
}
|
|
21
|
-
function shadowedRecipeLaunchDiagnostic(recipe) {
|
|
22
|
-
if (typeof recipe !== "string" ||
|
|
23
|
-
recipe.includes("/") ||
|
|
24
|
-
recipe.includes("~"))
|
|
25
|
-
return undefined;
|
|
26
|
-
const discovery = RecipesDiscovery.discoverRecipeSources([
|
|
27
|
-
{ root: Paths.getRecipeRoot(), defaultTool: true, mutableUsage: true },
|
|
28
|
-
{ root: Paths.getPackagedRecipeRoot(), defaultTool: false },
|
|
29
|
-
]);
|
|
30
|
-
return RecipesDiscovery.getShadowedLaunchDiagnostic(discovery, recipe);
|
|
31
|
-
}
|
|
32
20
|
function draftRecipeName(run) {
|
|
33
21
|
return `${run.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "spawn"}.json`;
|
|
34
22
|
}
|
|
@@ -60,16 +48,6 @@ function writeSpawnDraftRecipe(input, meta) {
|
|
|
60
48
|
RecipesUsage.recordRecipeLaunch(path, new Date(), "spawn", Paths.getRecipeRoot());
|
|
61
49
|
return path;
|
|
62
50
|
}
|
|
63
|
-
function enhanceSpawnRecipeError(error, recipe) {
|
|
64
|
-
const diagnostic = shadowedRecipeLaunchDiagnostic(recipe);
|
|
65
|
-
if (!diagnostic)
|
|
66
|
-
return error instanceof Error ? error : new Error(String(error));
|
|
67
|
-
const original = error instanceof Error ? error.message : String(error);
|
|
68
|
-
return Object.assign(new Error(`${original} reason=${diagnostic.reason} active_path=${diagnostic.active_path} blocked_fallback=${diagnostic.blocked_fallback} hint=${diagnostic.hint}`), {
|
|
69
|
-
...diagnostic,
|
|
70
|
-
original_error: original,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
51
|
function runIdFromTarget(target) {
|
|
74
52
|
if (!target)
|
|
75
53
|
return undefined;
|
|
@@ -90,8 +68,8 @@ export function createSpawnToolDefinition() {
|
|
|
90
68
|
parameters: Schema.objectSchema({
|
|
91
69
|
artifacts: Schema.looseObjectSchema("Optional named artifact paths for the spawned Run."),
|
|
92
70
|
as: Schema.stringSchema("Optional Run identity in exact run:<id> form."),
|
|
93
|
-
file: Schema.stringSchema("Optional
|
|
94
|
-
recipe: Schema.stringSchema("Alias for file
|
|
71
|
+
file: Schema.stringSchema("Optional Recipe reference as <skill>/<recipe> or an explicit .json/.md file path."),
|
|
72
|
+
recipe: Schema.stringSchema("Alias for file."),
|
|
95
73
|
template: Schema.unionSchema([
|
|
96
74
|
Schema.stringSchema("Inline command template string"),
|
|
97
75
|
Schema.arraySchema("Inline command-template sequence or parallel tree"),
|
|
@@ -112,34 +90,28 @@ export function createSpawnToolDefinition() {
|
|
|
112
90
|
: typeof input.recipe === "string"
|
|
113
91
|
? input.recipe
|
|
114
92
|
: undefined;
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
: {}),
|
|
138
|
-
}, ctx.cwd);
|
|
139
|
-
}
|
|
140
|
-
catch (error) {
|
|
141
|
-
throw enhanceSpawnRecipeError(error, recipe);
|
|
142
|
-
}
|
|
93
|
+
const meta = AsyncRuns.startRun({
|
|
94
|
+
file: recipe,
|
|
95
|
+
launch_source: "spawn",
|
|
96
|
+
launch_correlation: { tool_call_id: toolCallId },
|
|
97
|
+
ownerId: getRunOwnerId(ctx),
|
|
98
|
+
...(input.transport_context
|
|
99
|
+
? { transport_context: asRecord(input.transport_context) } : {}),
|
|
100
|
+
run_id: runId,
|
|
101
|
+
...(input.template !== undefined
|
|
102
|
+
? {
|
|
103
|
+
template: input.template,
|
|
104
|
+
}
|
|
105
|
+
: {}),
|
|
106
|
+
values: ModelContext.withCurrentModelValues(asRecord(input.values), ctx),
|
|
107
|
+
...(input.artifacts &&
|
|
108
|
+
typeof input.artifacts === "object" &&
|
|
109
|
+
!Array.isArray(input.artifacts)
|
|
110
|
+
? {
|
|
111
|
+
artifacts: input.artifacts,
|
|
112
|
+
}
|
|
113
|
+
: {}),
|
|
114
|
+
}, ctx.cwd, { skillContext: ctx.activeSkillRecipeContext });
|
|
143
115
|
const draftRecipe = writeSpawnDraftRecipe(input, meta);
|
|
144
116
|
const nextActions = ToolsResponse.runNextActions(meta.run);
|
|
145
117
|
const details = {
|
|
@@ -74,7 +74,6 @@ function summarizeCommandDetail(commandDetail) {
|
|
|
74
74
|
|
|
75
75
|
export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
76
76
|
if (!stateDir) throw new Error("missing state dir");
|
|
77
|
-
|
|
78
77
|
const runPath = join(stateDir, "run.json");
|
|
79
78
|
const progressPath = join(stateDir, "progress.json");
|
|
80
79
|
const resultPath = join(stateDir, "result.json");
|
|
@@ -83,11 +82,9 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
83
82
|
const stderrPath = join(stateDir, "stderr.log");
|
|
84
83
|
const executionPath = join(stateDir, "execution.json");
|
|
85
84
|
const meta = JSON.parse(readFileSync(runPath, "utf8"));
|
|
86
|
-
|
|
87
85
|
function event(kind, data = {}) {
|
|
88
86
|
appendRunTraceEvent(stateDir, { kind, data });
|
|
89
87
|
}
|
|
90
|
-
|
|
91
88
|
function observation(kind, summary, data = {}, delivery = "log", level = "info") {
|
|
92
89
|
appendRunTraceEvent(stateDir, {
|
|
93
90
|
kind,
|
|
@@ -97,7 +94,6 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
97
94
|
...(level === "error" ? { level: "error" } : {}),
|
|
98
95
|
});
|
|
99
96
|
}
|
|
100
|
-
|
|
101
97
|
function progress(phase, extra = {}) {
|
|
102
98
|
writeJsonAtomic(progressPath, {
|
|
103
99
|
...(meta.model_policy ? { model_policy: meta.model_policy } : {}),
|
|
@@ -106,7 +102,6 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
106
102
|
...extra,
|
|
107
103
|
});
|
|
108
104
|
}
|
|
109
|
-
|
|
110
105
|
let activeSubagents = 0;
|
|
111
106
|
let completedSubagents = 0;
|
|
112
107
|
let promptCounter = 0;
|
|
@@ -115,7 +110,6 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
115
110
|
const evidenceRecords = [];
|
|
116
111
|
const stageOccurrences = new Map();
|
|
117
112
|
let reportEvidence;
|
|
118
|
-
|
|
119
113
|
function writeExecutionManifest(status) {
|
|
120
114
|
writeJsonAtomic(executionPath, {
|
|
121
115
|
version: 1,
|
|
@@ -129,7 +123,6 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
129
123
|
updated_at: new Date().toISOString(),
|
|
130
124
|
});
|
|
131
125
|
}
|
|
132
|
-
|
|
133
126
|
function commandSessionFiles(sessionDir) {
|
|
134
127
|
if (!sessionDir) return [];
|
|
135
128
|
try {
|
|
@@ -141,7 +134,6 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
141
134
|
return [];
|
|
142
135
|
}
|
|
143
136
|
}
|
|
144
|
-
|
|
145
137
|
function commandEvidenceStartRecord({
|
|
146
138
|
commandDetail,
|
|
147
139
|
commandId,
|
|
@@ -181,7 +173,6 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
181
173
|
: "not_required",
|
|
182
174
|
};
|
|
183
175
|
}
|
|
184
|
-
|
|
185
176
|
function commandEvidenceRecord({
|
|
186
177
|
captureDir,
|
|
187
178
|
commandDetail,
|
|
@@ -273,7 +264,6 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
273
264
|
: "rejected",
|
|
274
265
|
};
|
|
275
266
|
}
|
|
276
|
-
|
|
277
267
|
function auditReviewReport(text) {
|
|
278
268
|
const required = evidenceRecords
|
|
279
269
|
.filter((record) =>
|
|
@@ -294,11 +284,9 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
294
284
|
complete_allowed: missing.length === 0,
|
|
295
285
|
};
|
|
296
286
|
}
|
|
297
|
-
|
|
298
287
|
function getCommandDoneDelivery(result) {
|
|
299
288
|
return result.code !== 0 || activeSubagents > 0 ? "followup" : "log";
|
|
300
289
|
}
|
|
301
|
-
|
|
302
290
|
function progressRunning() {
|
|
303
291
|
progress("running", {
|
|
304
292
|
activeSubagents,
|
|
@@ -306,14 +294,12 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
306
294
|
failures: subagentFailures,
|
|
307
295
|
});
|
|
308
296
|
}
|
|
309
|
-
|
|
310
297
|
function promptFilePath() {
|
|
311
298
|
promptCounter += 1;
|
|
312
299
|
const dir = join(stateDir, "prompts");
|
|
313
300
|
mkdirSync(dir, { recursive: true });
|
|
314
301
|
return join(dir, `command-${String(promptCounter).padStart(3, "0")}.md`);
|
|
315
302
|
}
|
|
316
|
-
|
|
317
303
|
function readPromptText(promptFile) {
|
|
318
304
|
if (!promptFile) return undefined;
|
|
319
305
|
try {
|
|
@@ -322,7 +308,6 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
322
308
|
return undefined;
|
|
323
309
|
}
|
|
324
310
|
}
|
|
325
|
-
|
|
326
311
|
async function observedExec(command, args, options) {
|
|
327
312
|
captureCounter += 1;
|
|
328
313
|
const commandId = `command-${String(captureCounter).padStart(3, "0")}`;
|
|
@@ -485,7 +470,6 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
485
470
|
progressRunning();
|
|
486
471
|
return result;
|
|
487
472
|
}
|
|
488
|
-
|
|
489
473
|
try {
|
|
490
474
|
event("run.runner.start", { pid: process.pid });
|
|
491
475
|
progressRunning();
|
|
@@ -40,12 +40,21 @@ writeFileSync(
|
|
|
40
40
|
"utf8",
|
|
41
41
|
);
|
|
42
42
|
|
|
43
|
-
for (const dir of ["scripts", "
|
|
43
|
+
for (const dir of ["scripts", "fixtures", "skills"]) {
|
|
44
44
|
cpSync(dir, join("dist", dir), { recursive: true });
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
.
|
|
49
|
-
|
|
47
|
+
function listModuleScripts(root) {
|
|
48
|
+
return readdirSync(root, { withFileTypes: true }).flatMap((entry) => {
|
|
49
|
+
const path = join(root, entry.name);
|
|
50
|
+
if (entry.isDirectory()) return listModuleScripts(path);
|
|
51
|
+
return entry.isFile() && entry.name.endsWith(".mjs") ? [path] : [];
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const builtScripts = [
|
|
56
|
+
...listModuleScripts(join("dist", "scripts")),
|
|
57
|
+
...listModuleScripts(join("dist", "skills")),
|
|
58
|
+
];
|
|
50
59
|
|
|
51
60
|
run(process.execPath, ["--check", ...builtScripts]);
|
|
@@ -29,7 +29,7 @@ A Recipe defines execution. It may declare named typed args, inline fallbacks, c
|
|
|
29
29
|
|
|
30
30
|
Do not declare Control for ordinary one-shot work. Runtime lifecycle actions such as `kill` stay runtime-owned and must not appear in Recipe Control declarations. Imported Recipes act as local definitions inside one Run; they do not create nested Runs unless execution explicitly spawns them.
|
|
31
31
|
|
|
32
|
-
Prefer maintained
|
|
32
|
+
Prefer maintained Skill-owned Recipes over ad hoc wrappers. Skill Recipe identity is `<active Skill name>/<Recipe filename stem>`; Recipe files have no top-level `name`. `SKILL.md` `name` is Pi host metadata matching its directory, not an additional pi-actors identity field. Use `<skill>/<recipe>` for an exact direct component or an explicit `.json` / `.md` path. Entry paths resolve from invocation `cwd`; relative imports resolve from the importing Recipe directory. File-backed Recipes own `{recipe_dir}` and Skill Recipes own `{skill_dir}`; callers never pass or override these origins. Skill Recipes are components, not automatic tools. Keep model, thinking, mission, concurrency, quorum, and timeout choices caller-owned unless a Recipe documents a stable policy.
|
|
33
33
|
|
|
34
34
|
## Trace
|
|
35
35
|
|
|
@@ -90,11 +90,11 @@ If work may outlive the current turn, needs steering, produces artifacts, fans o
|
|
|
90
90
|
|
|
91
91
|
## Top Recipes
|
|
92
92
|
|
|
93
|
-
- [Repository health](
|
|
94
|
-
- [Quorum review](
|
|
95
|
-
- [Artifact bundle](
|
|
96
|
-
- [Music player service](
|
|
97
|
-
- [Resource locker service](
|
|
93
|
+
- [Repository health](../project-work/recipes/repo-health.json)
|
|
94
|
+
- [Quorum review](../swarm/recipes/quorum-review.json)
|
|
95
|
+
- [Artifact bundle](../artifacts/recipes/bundle.json)
|
|
96
|
+
- [Music player service](../media/recipes/player.json)
|
|
97
|
+
- [Resource locker service](./recipes/resource-locker.json)
|
|
98
98
|
|
|
99
99
|
## Deep References
|
|
100
100
|
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"args": [
|
|
3
|
-
"repo:path",
|
|
4
3
|
"state_dir:path",
|
|
5
4
|
"lines:int"
|
|
6
5
|
],
|
|
7
6
|
"defaults": {
|
|
8
|
-
"repo": "~/.pi/agent/extensions/pi-actors",
|
|
9
7
|
"state_dir": "~/.pi/agent/tmp/pi-actors/runs/coordinator-locker",
|
|
10
8
|
"lines": "20"
|
|
11
9
|
},
|
|
12
|
-
"template": "{
|
|
10
|
+
"template": "{skill_dir}/scripts/resource-locker.mjs snapshot --state-dir {state_dir} --lines {lines}"
|
|
13
11
|
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"async": true,
|
|
3
3
|
"args": [
|
|
4
|
-
"repo:path",
|
|
5
4
|
"lease_ms:int"
|
|
6
5
|
],
|
|
7
6
|
"defaults": {
|
|
8
|
-
"repo": "~/.pi/agent/extensions/pi-actors",
|
|
9
7
|
"lease_ms": "600000"
|
|
10
8
|
},
|
|
11
9
|
"control": [
|
|
@@ -23,5 +21,5 @@
|
|
|
23
21
|
"locks": "{state_dir}/locks.json",
|
|
24
22
|
"journal": "{state_dir}/journal.jsonl"
|
|
25
23
|
},
|
|
26
|
-
"template": "{
|
|
24
|
+
"template": "{skill_dir}/scripts/resource-locker.mjs serve --state-dir {state_dir} --lease-ms {lease_ms}"
|
|
27
25
|
}
|
package/dist/{recipes/utility-run-ops-snapshot.json → skills/actors/recipes/run-ops-snapshot.json}
RENAMED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"args": [
|
|
3
|
-
"repo:path",
|
|
4
3
|
"state_root:path",
|
|
5
4
|
"run_id:string",
|
|
6
5
|
"lines:int",
|
|
7
6
|
"stale_minutes:int"
|
|
8
7
|
],
|
|
9
8
|
"defaults": {
|
|
10
|
-
"repo": "~/.pi/agent/extensions/pi-actors",
|
|
11
9
|
"state_root": "~/.pi/agent/tmp/pi-actors/runs",
|
|
12
10
|
"run_id": "music",
|
|
13
11
|
"lines": "80",
|
|
14
12
|
"stale_minutes": "60"
|
|
15
13
|
},
|
|
16
|
-
"template": "{
|
|
14
|
+
"template": "{skill_dir}/scripts/run-utils.mjs run-ops-snapshot {state_root} {run_id} {lines} {stale_minutes}"
|
|
17
15
|
}
|
|
@@ -21,12 +21,12 @@ import readline from "node:readline";
|
|
|
21
21
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
22
22
|
|
|
23
23
|
function packageRoot() {
|
|
24
|
-
return dirname(dirname(fileURLToPath(import.meta.url)));
|
|
24
|
+
return dirname(dirname(dirname(dirname(fileURLToPath(import.meta.url)))));
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
async function importRuntimeModule(name) {
|
|
28
28
|
const root = packageRoot();
|
|
29
|
-
const compiled = join(root, "
|
|
29
|
+
const compiled = join(root, "lib", `${name}.js`);
|
|
30
30
|
const source = join(root, "lib", `${name}.ts`);
|
|
31
31
|
return await import(pathToFileURL(existsSync(compiled) ? compiled : source).href);
|
|
32
32
|
}
|
|
@@ -65,7 +65,6 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
65
65
|
const controlPath = join(stateDir, "control.fifo");
|
|
66
66
|
let runInstanceId;
|
|
67
67
|
mkdirSync(stateDir, { recursive: true });
|
|
68
|
-
|
|
69
68
|
function readJson(path, fallback) {
|
|
70
69
|
if (!existsSync(path)) return fallback;
|
|
71
70
|
try {
|
|
@@ -74,11 +73,9 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
74
73
|
return fallback;
|
|
75
74
|
}
|
|
76
75
|
}
|
|
77
|
-
|
|
78
76
|
function writeJson(path, value) {
|
|
79
77
|
writeJsonAtomic(path, value);
|
|
80
78
|
}
|
|
81
|
-
|
|
82
79
|
function getControlEndpoint() {
|
|
83
80
|
if (process.platform !== "win32") return { path: controlPath, type: "fifo" };
|
|
84
81
|
const hash = createHash("sha256")
|
|
@@ -87,7 +84,6 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
87
84
|
.slice(0, 20);
|
|
88
85
|
return { path: `\\\\.\\pipe\\pi-actors-locker-${hash}`, type: "named-pipe" };
|
|
89
86
|
}
|
|
90
|
-
|
|
91
87
|
function writeControlEndpoint(endpoint) {
|
|
92
88
|
if (!runInstanceId) throw new Error("Run generation unavailable for Control endpoint");
|
|
93
89
|
writeJson(join(stateDir, "control-endpoint.json"), {
|
|
@@ -96,7 +92,6 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
96
92
|
run_instance_id: runInstanceId,
|
|
97
93
|
});
|
|
98
94
|
}
|
|
99
|
-
|
|
100
95
|
function journal(event, data = {}) {
|
|
101
96
|
const release = acquireFileMutationLock(journalPath);
|
|
102
97
|
try {
|
|
@@ -111,11 +106,9 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
111
106
|
writeTextAtomic(journalPath, content);
|
|
112
107
|
} finally { release(); }
|
|
113
108
|
}
|
|
114
|
-
|
|
115
109
|
function encodeJournal(records) {
|
|
116
110
|
return records.length ? `${records.map((record) => JSON.stringify(record)).join("\n")}\n` : "";
|
|
117
111
|
}
|
|
118
|
-
|
|
119
112
|
function emitTrace(kind, summary, data = {}, level = "info") {
|
|
120
113
|
appendRunTraceEvent(stateDir, {
|
|
121
114
|
attention: "followup",
|
|
@@ -125,11 +118,9 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
125
118
|
summary,
|
|
126
119
|
});
|
|
127
120
|
}
|
|
128
|
-
|
|
129
121
|
function now() {
|
|
130
122
|
return Date.now();
|
|
131
123
|
}
|
|
132
|
-
|
|
133
124
|
function cleanExpiredLocks(locks) {
|
|
134
125
|
const current = now();
|
|
135
126
|
const kept = {};
|
|
@@ -139,7 +130,6 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
139
130
|
}
|
|
140
131
|
return kept;
|
|
141
132
|
}
|
|
142
|
-
|
|
143
133
|
function normalizeControl(line) {
|
|
144
134
|
const trimmed = line.trim();
|
|
145
135
|
if (!trimmed) return undefined;
|
|
@@ -160,8 +150,6 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
160
150
|
);
|
|
161
151
|
}
|
|
162
152
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
153
|
function tailJournal(count) {
|
|
166
154
|
if (!existsSync(journalPath)) return [];
|
|
167
155
|
return readFileSync(journalPath, "utf8")
|
|
@@ -177,7 +165,6 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
177
165
|
}
|
|
178
166
|
});
|
|
179
167
|
}
|
|
180
|
-
|
|
181
168
|
function printSnapshot() {
|
|
182
169
|
const locks = cleanExpiredLocks(readJson(locksPath, {}));
|
|
183
170
|
writeJson(locksPath, locks);
|
|
@@ -195,7 +182,6 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
195
182
|
),
|
|
196
183
|
);
|
|
197
184
|
}
|
|
198
|
-
|
|
199
185
|
function nextTask(queue, locks) {
|
|
200
186
|
const items = Array.isArray(queue.items) ? queue.items : [];
|
|
201
187
|
const index = items.findIndex((item) => {
|
|
@@ -205,7 +191,6 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
205
191
|
if (index < 0) return undefined;
|
|
206
192
|
return items.splice(index, 1)[0];
|
|
207
193
|
}
|
|
208
|
-
|
|
209
194
|
function handle(control) {
|
|
210
195
|
const action = control.action;
|
|
211
196
|
const body =
|
|
@@ -333,18 +318,15 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
333
318
|
journal("lock.unknown", { action, input: body });
|
|
334
319
|
emitTrace("lock.unknown", `Unknown Control ${action}`, { action, input: body }, "warning");
|
|
335
320
|
}
|
|
336
|
-
|
|
337
321
|
if (mode === "snapshot") {
|
|
338
322
|
printSnapshot();
|
|
339
323
|
process.exit(0);
|
|
340
324
|
}
|
|
341
|
-
|
|
342
325
|
const startupRun = readJson(join(stateDir, "run.json"), undefined);
|
|
343
326
|
if (!startupRun || typeof startupRun.run_instance_id !== "string") {
|
|
344
327
|
throw new Error("Run generation unavailable for Control service");
|
|
345
328
|
}
|
|
346
329
|
runInstanceId = startupRun.run_instance_id;
|
|
347
|
-
|
|
348
330
|
function handleLine(line) {
|
|
349
331
|
const control = normalizeControl(line);
|
|
350
332
|
if (!control) return false;
|
|
@@ -376,7 +358,6 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
376
358
|
return false;
|
|
377
359
|
}
|
|
378
360
|
}
|
|
379
|
-
|
|
380
361
|
async function serveFifo(endpoint) {
|
|
381
362
|
if (!existsSync(endpoint.path)) {
|
|
382
363
|
const result = spawnSync("mkfifo", [endpoint.path]);
|
|
@@ -403,7 +384,6 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
403
384
|
fs.closeSync(fd);
|
|
404
385
|
}
|
|
405
386
|
}
|
|
406
|
-
|
|
407
387
|
async function serveNamedPipe(endpoint) {
|
|
408
388
|
let resolveStopped;
|
|
409
389
|
const stopped = new Promise((resolve) => {
|
|
@@ -428,7 +408,6 @@ async function runLocker(argv = process.argv.slice(2)) {
|
|
|
428
408
|
});
|
|
429
409
|
await stopped;
|
|
430
410
|
}
|
|
431
|
-
|
|
432
411
|
const endpoint = getControlEndpoint();
|
|
433
412
|
writeJson(queuePath, readJson(queuePath, { items: [] }));
|
|
434
413
|
writeJson(locksPath, cleanExpiredLocks(readJson(locksPath, {})));
|