mirror of
https://github.com/mvschwarz/openrig.git
synced 2026-11-07 22:58:42 -10:00
fix(cli): honor external queue sources as declared body claims (#440)
Signed-off-by: Rudy Celekli <[email protected]>
This commit is contained in:
1 parent
5887d3b996
commit
264fade906
2 files changed
+44
-4
No files matched your search
@@ -414,7 +414,7 @@ export function queueCommand(depsOverride?: QueueDeps): Command {
|
||||
cmd
|
||||
.command("create")
|
||||
.description("Create a new qitem")
|
||||
.option("--source <session>", "(deprecated, ignored) the source is derived from the seat env (X-OpenRig-Session); P21 I3 made the create route derive it from the transport header")
|
||||
.option("--source <session>", "Declared source outside a managed seat (recorded as claimed:v1); the managed seat env takes precedence")
|
||||
.requiredOption("--destination <session>", "Destination session (the seat that owns the work)")
|
||||
.option("--body <text>", "Qitem body inline (use - to read from stdin; mutually exclusive with --body-file)")
|
||||
.option("--body-file <path>", "Read qitem body from a file path (use - for stdin; mutually exclusive with --body). Kills the backtick-shell-corruption class for multiline bodies.")
|
||||
@@ -529,9 +529,11 @@ export function queueCommand(depsOverride?: QueueDeps): Command {
|
||||
"warning: rig queue create called without --summary. Pass --summary <text> to set the new qitem's short human-readable summary; without it, the Story node falls back to a bounded body preview. A good summary is 1-2 plain sentences a human skims in the needs-you view — what the work is and why it needs this seat, not the agent-speak --body. Proceeding (pre-18 callers exempt).\n"
|
||||
);
|
||||
}
|
||||
// P21 I3 reconcile: the source is DERIVED from the seat env (X-OpenRig-Session) — --source
|
||||
// deprecated + ignored, no body sourceSession. Verify the env or the daemon returns 400 actor_required (no seat identity to record; P18 retired the 401 refusal).
|
||||
if (!resolveCurrentSession(undefined, "source")) return;
|
||||
// A managed seat keeps transport-derived identity; an external caller can
|
||||
// name the existing claimed:v1 body actor without forging a transport header.
|
||||
const managedSource = readOpenRigEnv("OPENRIG_SESSION_NAME", "RIGGED_SESSION_NAME");
|
||||
const source = resolveCurrentSession(managedSource ?? opts.source, "source");
|
||||
if (!source) return;
|
||||
const deps = getDeps();
|
||||
// OPR.0.3.2.21.FR-4(b) — first-class --mission / --slice flags
|
||||
// translate to canonical mission:<id> / slice:<id> tags. Composes
|
||||
@@ -568,6 +570,7 @@ export function queueCommand(depsOverride?: QueueDeps): Command {
|
||||
}
|
||||
}
|
||||
const res = await client.post<Record<string, unknown>>("/api/queue/create", {
|
||||
...(managedSource === undefined ? { sourceSession: source } : {}),
|
||||
qitemId: opts.id,
|
||||
destinationSession: hostResolved.destination,
|
||||
body: resolvedBody,
|
||||
|
||||
@@ -141,6 +141,43 @@ describe("rig queue CLI", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("create accepts an explicit source outside a managed seat as a body claim", async () => {
|
||||
vi.stubEnv("OPENRIG_SESSION_NAME", "");
|
||||
vi.stubEnv("RIGGED_SESSION_NAME", "");
|
||||
const { deps, calls } = makeDeps();
|
||||
const program = createProgram({ queueDeps: deps });
|
||||
await program.parseAsync(["node", "rig", "queue", "create", "--source", "external@rig",
|
||||
"--destination", "bob@rig", "--body", "external work", "--summary", "External work", "--json"]);
|
||||
expect(process.exitCode).toBeUndefined();
|
||||
const body = calls.find(c => c.path === "/api/queue/create")?.body as Record<string, unknown>;
|
||||
expect(body.sourceSession).toBe("external@rig");
|
||||
expect(body.destinationSession).toBe("bob@rig");
|
||||
});
|
||||
|
||||
it("create still requires a source when neither the managed env nor explicit claim is supplied", async () => {
|
||||
vi.stubEnv("OPENRIG_SESSION_NAME", "");
|
||||
vi.stubEnv("RIGGED_SESSION_NAME", "");
|
||||
const { deps, calls } = makeDeps();
|
||||
const program = createProgram({ queueDeps: deps });
|
||||
await program.parseAsync(["node", "rig", "queue", "create", "--destination", "bob@rig",
|
||||
"--body", "external work", "--summary", "External work", "--json"]);
|
||||
expect(process.exitCode).toBe(1);
|
||||
expect(calls).toEqual([]);
|
||||
expect(errors.join("\n")).toContain("--source is required");
|
||||
});
|
||||
|
||||
it("create preserves the legacy managed source env without forwarding an explicit body claim", async () => {
|
||||
vi.stubEnv("OPENRIG_SESSION_NAME", "");
|
||||
vi.stubEnv("RIGGED_SESSION_NAME", "legacy@rig");
|
||||
const { deps, calls } = makeDeps();
|
||||
const program = createProgram({ queueDeps: deps });
|
||||
await program.parseAsync(["node", "rig", "queue", "create", "--source", "ignored@rig",
|
||||
"--destination", "bob@rig", "--body", "legacy work", "--summary", "Legacy work", "--json"]);
|
||||
expect(process.exitCode).toBeUndefined();
|
||||
const body = calls.find(c => c.path === "/api/queue/create")?.body as Record<string, unknown>;
|
||||
expect(body.sourceSession).toBeUndefined();
|
||||
});
|
||||
|
||||
it("create --human-questions-file sends the parsed questions; unreadable JSON is refused before any request", async () => {
|
||||
const directory = fs.mkdtempSync(path.join(os.tmpdir(), "queue-human-questions-"));
|
||||
const file = path.join(directory, "questions.json");
|
||||
|
||||
Reference in new issue
Block a user