@linzumi/cli 0.0.88-beta → 0.0.90-beta
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/README.md +1 -1
- package/dist/index.js +511 -282
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -1936,6 +1936,228 @@ var init_codexRuntimeOptions = __esm({
|
|
|
1936
1936
|
}
|
|
1937
1937
|
});
|
|
1938
1938
|
|
|
1939
|
+
// src/linzumiContext.ts
|
|
1940
|
+
function parseLinzumiConversationContext(value, warn = console.warn) {
|
|
1941
|
+
if (value === void 0) {
|
|
1942
|
+
return void 0;
|
|
1943
|
+
}
|
|
1944
|
+
const context = objectValue(value);
|
|
1945
|
+
if (context === void 0) {
|
|
1946
|
+
return invalidLinzumiContext("linzumiContext must be an object", warn);
|
|
1947
|
+
}
|
|
1948
|
+
const threadId = stringValue(context.threadId);
|
|
1949
|
+
const creatorUserId = stringValue(context.creatorUserId) ?? integerValue(context.creatorUserId)?.toString();
|
|
1950
|
+
const creatorUsername = stringValue(context.creatorUsername);
|
|
1951
|
+
const conversationUrl = stringValue(context.conversationUrl);
|
|
1952
|
+
if (threadId === void 0 || creatorUserId === void 0 || creatorUsername === void 0 || conversationUrl === void 0) {
|
|
1953
|
+
return invalidLinzumiContext(
|
|
1954
|
+
"linzumiContext must include threadId, creatorUserId, creatorUsername, and conversationUrl",
|
|
1955
|
+
warn
|
|
1956
|
+
);
|
|
1957
|
+
}
|
|
1958
|
+
return { threadId, creatorUserId, creatorUsername, conversationUrl };
|
|
1959
|
+
}
|
|
1960
|
+
function formatLinzumiConversationContextForPrompt(context) {
|
|
1961
|
+
return `<linzumi_context>
|
|
1962
|
+
<linzumi_thread_id>${escapeXmlText(context.threadId)}</linzumi_thread_id>
|
|
1963
|
+
<linzumi_creator_user_id>${escapeXmlText(context.creatorUserId)}</linzumi_creator_user_id>
|
|
1964
|
+
<linzumi_creator_username>${escapeXmlText(context.creatorUsername)}</linzumi_creator_username>
|
|
1965
|
+
<linzumi_conversation_url>${escapeXmlText(context.conversationUrl)}</linzumi_conversation_url>
|
|
1966
|
+
</linzumi_context>
|
|
1967
|
+
|
|
1968
|
+
<linzumi_pr_footer_instruction>
|
|
1969
|
+
For any GitHub pull request you open from this session, include this Markdown footer link in the PR description: [Continue this on Linzumi](${context.conversationUrl})
|
|
1970
|
+
</linzumi_pr_footer_instruction>`;
|
|
1971
|
+
}
|
|
1972
|
+
function invalidLinzumiContext(reason, warn) {
|
|
1973
|
+
warn(`Ignoring invalid linzumiContext: ${reason}`);
|
|
1974
|
+
return void 0;
|
|
1975
|
+
}
|
|
1976
|
+
function escapeXmlText(value) {
|
|
1977
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
1978
|
+
}
|
|
1979
|
+
var init_linzumiContext = __esm({
|
|
1980
|
+
"src/linzumiContext.ts"() {
|
|
1981
|
+
"use strict";
|
|
1982
|
+
init_json();
|
|
1983
|
+
}
|
|
1984
|
+
});
|
|
1985
|
+
|
|
1986
|
+
// src/commanderDeveloperInstructions.ts
|
|
1987
|
+
function commanderDeveloperInstructions(args) {
|
|
1988
|
+
const agentLabel = args.agentLabel ?? "Codex";
|
|
1989
|
+
const planOpener = `Before you begin ANY work - and again whenever the job
|
|
1990
|
+
changes - call linzumi_upsert_coding_job_plan to set or refresh the current
|
|
1991
|
+
goal and the high-level plan. Always record the plan up front, before starting
|
|
1992
|
+
work, so the user can see a high-level view of what you are doing at all times
|
|
1993
|
+
and trust your work. Keep it accurate as you go: whenever you discover steps to
|
|
1994
|
+
add, steps that are no longer needed, or the nature of the job changes, update
|
|
1995
|
+
it with linzumi_upsert_coding_job_plan.`;
|
|
1996
|
+
const planStepsInstruction = args.planTool === "todo-write" ? `${planOpener}
|
|
1997
|
+
Record and maintain the plan STEPS with the TodoWrite tool. Linzumi mirrors
|
|
1998
|
+
your TodoWrite list into the coding-job plan steps automatically, one TodoWrite
|
|
1999
|
+
item per plan step.` : `${planOpener}
|
|
2000
|
+
Replace the plan STEPS with linzumi_replace_coding_job_plan_steps.`;
|
|
2001
|
+
const planUpdateInstruction = args.planTool === "todo-write" ? `As work proceeds, update each step's status with TodoWrite. Do not call
|
|
2002
|
+
linzumi_replace_coding_job_plan_steps or linzumi_update_coding_job_plan_step
|
|
2003
|
+
directly; TodoWrite is the source of truth for the plan steps.` : `As work proceeds, update each step with linzumi_update_coding_job_plan_step.`;
|
|
2004
|
+
const customPrompt = args.developerPrompt === void 0 ? "" : `
|
|
2005
|
+
<invoker_developer_prompt>
|
|
2006
|
+
${args.developerPrompt}
|
|
2007
|
+
</invoker_developer_prompt>
|
|
2008
|
+
`;
|
|
2009
|
+
const linzumiContext = args.linzumiContext === void 0 ? "" : `
|
|
2010
|
+
${formatLinzumiConversationContextForPrompt(args.linzumiContext)}
|
|
2011
|
+
`;
|
|
2012
|
+
return `<context>
|
|
2013
|
+
You are a Linzumi ${agentLabel} session launched by the Linzumi Commander.
|
|
2014
|
+
The Commander is the local bridge process that connects this computer to the
|
|
2015
|
+
user's Linzumi workspace, secure preview tunnel, browser VS Code editor, and
|
|
2016
|
+
thread transcript. Your work and progress are relayed into that Linzumi thread.
|
|
2017
|
+
</context>
|
|
2018
|
+
|
|
2019
|
+
<term_definitions>
|
|
2020
|
+
Bootstrapper ${agentLabel}: The outer setup agent that claimed/signup, generated the
|
|
2021
|
+
demo folder when applicable, and asked Linzumi to start this session. It does
|
|
2022
|
+
not own implementation work.
|
|
2023
|
+
Linzumi Commander: The local long-running process that launched this ${agentLabel}
|
|
2024
|
+
session, enforces the trusted folder, and forwards descendant preview ports to
|
|
2025
|
+
Linzumi.
|
|
2026
|
+
Linzumi ${agentLabel} session: You, the inner ${agentLabel} process that performs the actual
|
|
2027
|
+
work in the approved project folder.
|
|
2028
|
+
Approved project folder: ${args.cwd}
|
|
2029
|
+
Coding-job metadata: User-visible goal, plan steps, step statuses, completion
|
|
2030
|
+
notes, primary pull request link, and worktree state shown in Linzumi's coding
|
|
2031
|
+
job overview.
|
|
2032
|
+
Plan step: A discrete chunk of work with a short title, one-line description,
|
|
2033
|
+
status, and completion note. It should describe an actual goal, not just a
|
|
2034
|
+
process verb.
|
|
2035
|
+
Primary pull request: The GitHub PR the job is currently driving or reviewing;
|
|
2036
|
+
Linzumi uses this link to hydrate PR comments, files, commits, checks, and
|
|
2037
|
+
deployments in the metadata overview.
|
|
2038
|
+
</term_definitions>
|
|
2039
|
+
|
|
2040
|
+
<linzumi_mcp>
|
|
2041
|
+
The Codex process is preconfigured with a Linzumi MCP server named "linzumi".
|
|
2042
|
+
Use it when you need authenticated context from the current Linzumi workspace:
|
|
2043
|
+
read a message by ID/URL, read a thread by ID, read the scoped channel, or send
|
|
2044
|
+
a concise DM to the Commander owner when the task genuinely requires it.
|
|
2045
|
+
</linzumi_mcp>
|
|
2046
|
+
|
|
2047
|
+
<task_instructions>
|
|
2048
|
+
Work only in the approved project folder unless the human explicitly asks for
|
|
2049
|
+
something else in the Linzumi thread. Start, inspect, and modify the local app
|
|
2050
|
+
from that folder. Report concise progress and exact blockers in the thread.
|
|
2051
|
+
Use the Linzumi MCP server named "linzumi" when you need authenticated
|
|
2052
|
+
workspace context or coding-job metadata tools.
|
|
2053
|
+
${planStepsInstruction}
|
|
2054
|
+
When the coding-job scope changes materially, call linzumi_rename_coding_job
|
|
2055
|
+
with a concise title so the Linzumi thread title and workflow-facing title
|
|
2056
|
+
match the work.
|
|
2057
|
+
${planUpdateInstruction}
|
|
2058
|
+
When you open, discover, or choose the primary pull request, link it with
|
|
2059
|
+
linzumi_link_coding_job_pull_request.
|
|
2060
|
+
Before stopping, confirm the metadata overview tells the truth for a user who
|
|
2061
|
+
only sees that overview: completed work is completed, active work is really
|
|
2062
|
+
active, blocked work says why, and no stale in-progress step is left behind.
|
|
2063
|
+
For frontend or other user-visible changes, ask whether the user wants
|
|
2064
|
+
screenshot or screen-recording proof, ideally before/after when that helps
|
|
2065
|
+
review the change. Screen recordings should be WebM or MP4.
|
|
2066
|
+
When the user asks you to open or update a PR, attach or link feasible proof in
|
|
2067
|
+
the PR and state the exact blocker when proof is not feasible.
|
|
2068
|
+
</task_instructions>
|
|
2069
|
+
|
|
2070
|
+
<rules>
|
|
2071
|
+
You MUST treat the Linzumi thread as the source of truth for user-facing
|
|
2072
|
+
progress.
|
|
2073
|
+
For coding-job threads, you MUST keep coding-job metadata current throughout
|
|
2074
|
+
the job.
|
|
2075
|
+
Plan steps MUST be fairly granular, discrete chunks of real work that a human
|
|
2076
|
+
can track.
|
|
2077
|
+
Plan step descriptions MUST stay short, usually one line and less than one full
|
|
2078
|
+
sentence.
|
|
2079
|
+
Plan steps MUST NOT be vague process-only labels such as "sync PR",
|
|
2080
|
+
"update PR", "verify PR", or "commit and merge" when those labels hide the
|
|
2081
|
+
concrete goal.
|
|
2082
|
+
You MUST update steps in sequence as work is completed. Do not mark a later
|
|
2083
|
+
step active while earlier applicable steps are still pending.
|
|
2084
|
+
Before you stop work, you MUST reconcile the plan so the job is not left with a
|
|
2085
|
+
stale active step. You may delegate metadata upkeep to a sub-agent when useful,
|
|
2086
|
+
but the visible job state must remain truthful.
|
|
2087
|
+
If the coding-job thread title is missing, undefined, or "Untitled", you MUST
|
|
2088
|
+
choose a concise, specific title for the job.
|
|
2089
|
+
User-visible UI, status, error, and PR-review copy MUST keep it short, direct,
|
|
2090
|
+
and focused on the user's outcome unless the user explicitly asks for
|
|
2091
|
+
implementation detail.
|
|
2092
|
+
You MUST keep user-visible preview servers bound to 0.0.0.0, not 127.0.0.1 or
|
|
2093
|
+
localhost, so the Linzumi secure tunnel can reach them.
|
|
2094
|
+
You MUST keep any preview or dev server as your descendant process so the
|
|
2095
|
+
Commander can discover and forward it.
|
|
2096
|
+
You MUST NOT ask the Bootstrapper ${agentLabel} to do implementation work.
|
|
2097
|
+
You MUST NOT inspect unrelated repositories or folders.
|
|
2098
|
+
You MUST report the exact blocker if a command, preview, editor, or tunnel step
|
|
2099
|
+
fails.
|
|
2100
|
+
When several Linzumi Codex sessions work in the same repository, create or use
|
|
2101
|
+
a separate checkout or git worktree for this task before making changes, unless
|
|
2102
|
+
the human explicitly asks you to share the current checkout. Do not overwrite or
|
|
2103
|
+
revert another session's work.
|
|
2104
|
+
</rules>
|
|
2105
|
+
|
|
2106
|
+
<examples>
|
|
2107
|
+
GOOD preview command: npm run dev -- --host 0.0.0.0 --port 8787
|
|
2108
|
+
Why good: The preview is reachable through the Linzumi secure tunnel.
|
|
2109
|
+
|
|
2110
|
+
BAD preview command: npm run dev -- --host 127.0.0.1
|
|
2111
|
+
Why bad: Binding to localhost prevents the Linzumi secure tunnel from reaching
|
|
2112
|
+
the preview.
|
|
2113
|
+
|
|
2114
|
+
GOOD coding-job plan:
|
|
2115
|
+
- Inspect prompt sources: Locate the prompt builder, prompt guide, and tests.
|
|
2116
|
+
- Add metadata guidance: Patch the prompt with plan, title, and stop-state rules.
|
|
2117
|
+
- Verify compiled prompt: Run focused tests and inspect the generated text.
|
|
2118
|
+
- Push PR update: Commit owned files, push the branch, and refresh PR metadata.
|
|
2119
|
+
Why good: Each step is a concrete chunk of work, the list is short enough to
|
|
2120
|
+
scan, and the titles explain what is actually happening.
|
|
2121
|
+
|
|
2122
|
+
BAD coding-job plan:
|
|
2123
|
+
- Sync PR
|
|
2124
|
+
- Update PR
|
|
2125
|
+
- Verify PR
|
|
2126
|
+
- Commit and merge
|
|
2127
|
+
Why bad: These labels describe process mechanics, not the concrete work or
|
|
2128
|
+
product goal. A user cannot tell what the agent has learned, changed, or still
|
|
2129
|
+
needs to do.
|
|
2130
|
+
|
|
2131
|
+
BAD coding-job metadata state:
|
|
2132
|
+
- Step 1 complete, Step 2 complete, Step 3 active, Step 4 pending.
|
|
2133
|
+
- The agent has stopped working and sent its final response.
|
|
2134
|
+
Why bad: The overview still says work is active even though the agent is idle.
|
|
2135
|
+
Before stopping, the agent should mark Step 3 completed, blocked, or canceled
|
|
2136
|
+
with a truthful note.
|
|
2137
|
+
</examples>
|
|
2138
|
+
${linzumiContext}
|
|
2139
|
+
${customPrompt}
|
|
2140
|
+
<task_reminder>
|
|
2141
|
+
You are the Commander-launched Linzumi ${agentLabel} session. Do the implementation
|
|
2142
|
+
work in the approved project folder, keep preview servers reachable through the
|
|
2143
|
+
secure tunnel, and keep the Linzumi thread and coding-job metadata truthful.
|
|
2144
|
+
</task_reminder>
|
|
2145
|
+
|
|
2146
|
+
<output_format>
|
|
2147
|
+
Use normal concise Linzumi thread messages for user-facing progress and final
|
|
2148
|
+
answers. When the task requires files, code, commits, pull requests, previews,
|
|
2149
|
+
or verification output, report the concrete artifact, command, result, and any
|
|
2150
|
+
exact blocker. Do not emit machine-only JSON unless the user or tool explicitly
|
|
2151
|
+
requests it.
|
|
2152
|
+
</output_format>`;
|
|
2153
|
+
}
|
|
2154
|
+
var init_commanderDeveloperInstructions = __esm({
|
|
2155
|
+
"src/commanderDeveloperInstructions.ts"() {
|
|
2156
|
+
"use strict";
|
|
2157
|
+
init_linzumiContext();
|
|
2158
|
+
}
|
|
2159
|
+
});
|
|
2160
|
+
|
|
1939
2161
|
// src/codexOutput.ts
|
|
1940
2162
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
1941
2163
|
import { fileURLToPath } from "node:url";
|
|
@@ -5116,6 +5338,43 @@ var init_itemProjection = __esm({
|
|
|
5116
5338
|
function rowStreamStateIsTerminal(state) {
|
|
5117
5339
|
return state !== void 0 && terminalRowStreamStates.has(state);
|
|
5118
5340
|
}
|
|
5341
|
+
function codexProtocolFailureReasonFromItems(items) {
|
|
5342
|
+
for (const value of items) {
|
|
5343
|
+
const reason = codexProtocolFailureReasonFromItem(objectValue(value));
|
|
5344
|
+
if (reason !== void 0) {
|
|
5345
|
+
return reason;
|
|
5346
|
+
}
|
|
5347
|
+
}
|
|
5348
|
+
return void 0;
|
|
5349
|
+
}
|
|
5350
|
+
function codexProtocolFailureReasonFromItem(item) {
|
|
5351
|
+
if (item === void 0) {
|
|
5352
|
+
return void 0;
|
|
5353
|
+
}
|
|
5354
|
+
const explicitReason = stringValue(item.codex_protocol_failure_reason) ?? stringValue(item.protocolFailureReason);
|
|
5355
|
+
if (explicitReason !== void 0) {
|
|
5356
|
+
return explicitReason;
|
|
5357
|
+
}
|
|
5358
|
+
const itemType = stringValue(item.type);
|
|
5359
|
+
if (itemType !== "function_call_output" && itemType !== "custom_tool_call_output") {
|
|
5360
|
+
return void 0;
|
|
5361
|
+
}
|
|
5362
|
+
const output = stringValue(item.output) ?? stringValue(item.result) ?? stringValue(item.text) ?? stringValue(item.content);
|
|
5363
|
+
const unsupportedCall = unsupportedCodexCallName(output);
|
|
5364
|
+
return unsupportedCall === void 0 ? void 0 : `${unsupportedCodexToolCallReasonPrefix}: ${unsupportedCall}`;
|
|
5365
|
+
}
|
|
5366
|
+
function unsupportedCodexCallName(output) {
|
|
5367
|
+
const prefix = "unsupported call:";
|
|
5368
|
+
if (output === void 0) {
|
|
5369
|
+
return void 0;
|
|
5370
|
+
}
|
|
5371
|
+
const normalized = output.trim();
|
|
5372
|
+
if (!normalized.toLowerCase().startsWith(prefix)) {
|
|
5373
|
+
return void 0;
|
|
5374
|
+
}
|
|
5375
|
+
const callName = normalized.slice(prefix.length).trim();
|
|
5376
|
+
return callName === "" ? "unknown" : callName;
|
|
5377
|
+
}
|
|
5119
5378
|
function createInitialLoopState() {
|
|
5120
5379
|
return {
|
|
5121
5380
|
phase: "running",
|
|
@@ -5260,6 +5519,7 @@ function createTurn(state, turnId, sourceSeq) {
|
|
|
5260
5519
|
turnId,
|
|
5261
5520
|
sourceSeq,
|
|
5262
5521
|
phase: "active",
|
|
5522
|
+
protocolFailureReason: void 0,
|
|
5263
5523
|
items: []
|
|
5264
5524
|
};
|
|
5265
5525
|
state.turns.set(turnId, turn);
|
|
@@ -5366,6 +5626,10 @@ function handleDelta(turn, signal, deps, effects) {
|
|
|
5366
5626
|
emitRowUpdate(turn, item, deltaIndex, streamState, deps, effects);
|
|
5367
5627
|
}
|
|
5368
5628
|
function handleItemCompleted(turn, params, deps, effects) {
|
|
5629
|
+
const completedItem = objectValue(params.item);
|
|
5630
|
+
if (completedItem !== void 0) {
|
|
5631
|
+
turn.protocolFailureReason ??= codexProtocolFailureReasonFromItem(completedItem);
|
|
5632
|
+
}
|
|
5369
5633
|
const completed = completedItemForNotification(params);
|
|
5370
5634
|
if (completed === void 0) {
|
|
5371
5635
|
return;
|
|
@@ -5535,6 +5799,7 @@ function handleSnapshot(state, turnId, snapshot, deps, effects) {
|
|
|
5535
5799
|
return;
|
|
5536
5800
|
}
|
|
5537
5801
|
const rawItems = Array.isArray(snapshot.items) ? snapshot.items : [];
|
|
5802
|
+
turn.protocolFailureReason ??= codexProtocolFailureReasonFromItems(rawItems);
|
|
5538
5803
|
const projected = projectSnapshotItems(rawItems);
|
|
5539
5804
|
const consumedItemKeys = /* @__PURE__ */ new Set();
|
|
5540
5805
|
const matches = /* @__PURE__ */ new Map();
|
|
@@ -5640,6 +5905,17 @@ function handleSnapshot(state, turnId, snapshot, deps, effects) {
|
|
|
5640
5905
|
const assistantResponseSeen = turn.items.some(
|
|
5641
5906
|
(item) => item.identity.streamKind === "assistant" && item.posted
|
|
5642
5907
|
) || projected.some((proj) => proj.streamKind === "assistant");
|
|
5908
|
+
const terminalFailureReason = turn.protocolFailureReason ?? (assistantResponseSeen ? void 0 : completedWithoutAssistantOutputReason);
|
|
5909
|
+
if (turn.protocolFailureReason !== void 0) {
|
|
5910
|
+
effects.push(
|
|
5911
|
+
log("codex.turn_completed_with_protocol_failure", {
|
|
5912
|
+
thread_key: deps.threadKey,
|
|
5913
|
+
turn_id: turn.turnId,
|
|
5914
|
+
source_seq: turn.sourceSeq,
|
|
5915
|
+
reason: turn.protocolFailureReason
|
|
5916
|
+
})
|
|
5917
|
+
);
|
|
5918
|
+
}
|
|
5643
5919
|
if (!assistantResponseSeen) {
|
|
5644
5920
|
effects.push(
|
|
5645
5921
|
log("codex.turn_completed_without_assistant_output", {
|
|
@@ -5658,19 +5934,19 @@ function handleSnapshot(state, turnId, snapshot, deps, effects) {
|
|
|
5658
5934
|
thread_key: deps.threadKey,
|
|
5659
5935
|
turn_id: turn.turnId,
|
|
5660
5936
|
seq: turn.sourceSeq,
|
|
5661
|
-
...
|
|
5937
|
+
...terminalFailureReason === void 0 ? { status: "processed" } : {
|
|
5662
5938
|
status: "failed",
|
|
5663
|
-
reason:
|
|
5939
|
+
reason: terminalFailureReason
|
|
5664
5940
|
}
|
|
5665
5941
|
},
|
|
5666
5942
|
resolution: "must_ack"
|
|
5667
5943
|
});
|
|
5668
5944
|
effects.push(
|
|
5669
|
-
|
|
5945
|
+
terminalFailureReason === void 0 ? { type: "turnTerminal", turnId: turn.turnId, outcome: "completed" } : {
|
|
5670
5946
|
type: "turnTerminal",
|
|
5671
5947
|
turnId: turn.turnId,
|
|
5672
5948
|
outcome: "failed",
|
|
5673
|
-
reason:
|
|
5949
|
+
reason: terminalFailureReason
|
|
5674
5950
|
}
|
|
5675
5951
|
);
|
|
5676
5952
|
state.turns.delete(turn.turnId);
|
|
@@ -5751,7 +6027,7 @@ function failureReason(params) {
|
|
|
5751
6027
|
function log(event, fields) {
|
|
5752
6028
|
return { type: "log", event, fields };
|
|
5753
6029
|
}
|
|
5754
|
-
var terminalRowStreamStates, turnMappingReadyMethod, turnMappingFailedMethod, maxTerminalTurnIds, completedWithoutAssistantOutputReason, turnTerminalFailureMethods, handledNotificationMethods;
|
|
6030
|
+
var terminalRowStreamStates, turnMappingReadyMethod, turnMappingFailedMethod, maxTerminalTurnIds, completedWithoutAssistantOutputReason, unsupportedCodexToolCallReasonPrefix, turnTerminalFailureMethods, handledNotificationMethods;
|
|
5755
6031
|
var init_transition = __esm({
|
|
5756
6032
|
"src/pipeline/transition.ts"() {
|
|
5757
6033
|
"use strict";
|
|
@@ -5767,6 +6043,7 @@ var init_transition = __esm({
|
|
|
5767
6043
|
turnMappingFailedMethod = "pipeline/turnMappingFailed";
|
|
5768
6044
|
maxTerminalTurnIds = 512;
|
|
5769
6045
|
completedWithoutAssistantOutputReason = "Codex completed without producing a response.";
|
|
6046
|
+
unsupportedCodexToolCallReasonPrefix = "Codex emitted unsupported tool call";
|
|
5770
6047
|
turnTerminalFailureMethods = /* @__PURE__ */ new Map([
|
|
5771
6048
|
["turn/failed", "failed"],
|
|
5772
6049
|
["turn/aborted", "interrupted"],
|
|
@@ -6321,17 +6598,22 @@ function rawItemFromToolCallMessage(message) {
|
|
|
6321
6598
|
const structured = message.structured;
|
|
6322
6599
|
const itemId = /^item-\d+$/.test(message.itemKey) ? void 0 : message.itemKey;
|
|
6323
6600
|
const idField = itemId === void 0 ? {} : { id: itemId };
|
|
6601
|
+
const output = typeof structured.output === "string" ? structured.output : "";
|
|
6324
6602
|
switch (stringValue(structured.kind)) {
|
|
6325
|
-
case "codex_command_execution":
|
|
6603
|
+
case "codex_command_execution": {
|
|
6604
|
+
const protocolFailureReason = unsupportedToolCallReason(output);
|
|
6605
|
+
const protocolFailureField = protocolFailureReason === void 0 ? {} : { codex_protocol_failure_reason: protocolFailureReason };
|
|
6326
6606
|
return {
|
|
6327
6607
|
type: "commandExecution",
|
|
6328
6608
|
...idField,
|
|
6609
|
+
...protocolFailureField,
|
|
6329
6610
|
command: stringValue(structured.command) ?? "command",
|
|
6330
6611
|
cwd: stringValue(structured.cwd) ?? "",
|
|
6331
6612
|
status: stringValue(structured.status) ?? "",
|
|
6332
6613
|
...stringValue(structured.process_id) === void 0 || stringValue(structured.process_id) === "" ? {} : { processId: stringValue(structured.process_id) },
|
|
6333
|
-
aggregatedOutput:
|
|
6614
|
+
aggregatedOutput: output
|
|
6334
6615
|
};
|
|
6616
|
+
}
|
|
6335
6617
|
case "codex_file_change":
|
|
6336
6618
|
return {
|
|
6337
6619
|
type: "fileChange",
|
|
@@ -6344,6 +6626,15 @@ function rawItemFromToolCallMessage(message) {
|
|
|
6344
6626
|
return void 0;
|
|
6345
6627
|
}
|
|
6346
6628
|
}
|
|
6629
|
+
function unsupportedToolCallReason(output) {
|
|
6630
|
+
const prefix = "unsupported call:";
|
|
6631
|
+
const normalized = output.trim();
|
|
6632
|
+
if (!normalized.toLowerCase().startsWith(prefix)) {
|
|
6633
|
+
return void 0;
|
|
6634
|
+
}
|
|
6635
|
+
const callName = normalized.slice(prefix.length).trim();
|
|
6636
|
+
return `Codex emitted unsupported tool call: ${callName === "" ? "unknown" : callName}`;
|
|
6637
|
+
}
|
|
6347
6638
|
function mergeSnapshotItems(readItems, sessionItems) {
|
|
6348
6639
|
if (sessionItems.length === 0) {
|
|
6349
6640
|
return [...readItems];
|
|
@@ -6552,53 +6843,6 @@ var init_kandanQueue = __esm({
|
|
|
6552
6843
|
}
|
|
6553
6844
|
});
|
|
6554
6845
|
|
|
6555
|
-
// src/linzumiContext.ts
|
|
6556
|
-
function parseLinzumiConversationContext(value, warn = console.warn) {
|
|
6557
|
-
if (value === void 0) {
|
|
6558
|
-
return void 0;
|
|
6559
|
-
}
|
|
6560
|
-
const context = objectValue(value);
|
|
6561
|
-
if (context === void 0) {
|
|
6562
|
-
return invalidLinzumiContext("linzumiContext must be an object", warn);
|
|
6563
|
-
}
|
|
6564
|
-
const threadId = stringValue(context.threadId);
|
|
6565
|
-
const creatorUserId = stringValue(context.creatorUserId) ?? integerValue(context.creatorUserId)?.toString();
|
|
6566
|
-
const creatorUsername = stringValue(context.creatorUsername);
|
|
6567
|
-
const conversationUrl = stringValue(context.conversationUrl);
|
|
6568
|
-
if (threadId === void 0 || creatorUserId === void 0 || creatorUsername === void 0 || conversationUrl === void 0) {
|
|
6569
|
-
return invalidLinzumiContext(
|
|
6570
|
-
"linzumiContext must include threadId, creatorUserId, creatorUsername, and conversationUrl",
|
|
6571
|
-
warn
|
|
6572
|
-
);
|
|
6573
|
-
}
|
|
6574
|
-
return { threadId, creatorUserId, creatorUsername, conversationUrl };
|
|
6575
|
-
}
|
|
6576
|
-
function formatLinzumiConversationContextForPrompt(context) {
|
|
6577
|
-
return `<linzumi_context>
|
|
6578
|
-
<linzumi_thread_id>${escapeXmlText(context.threadId)}</linzumi_thread_id>
|
|
6579
|
-
<linzumi_creator_user_id>${escapeXmlText(context.creatorUserId)}</linzumi_creator_user_id>
|
|
6580
|
-
<linzumi_creator_username>${escapeXmlText(context.creatorUsername)}</linzumi_creator_username>
|
|
6581
|
-
<linzumi_conversation_url>${escapeXmlText(context.conversationUrl)}</linzumi_conversation_url>
|
|
6582
|
-
</linzumi_context>
|
|
6583
|
-
|
|
6584
|
-
<linzumi_pr_footer_instruction>
|
|
6585
|
-
For any GitHub pull request you open from this session, include this Markdown footer link in the PR description: [Continue this on Linzumi](${context.conversationUrl})
|
|
6586
|
-
</linzumi_pr_footer_instruction>`;
|
|
6587
|
-
}
|
|
6588
|
-
function invalidLinzumiContext(reason, warn) {
|
|
6589
|
-
warn(`Ignoring invalid linzumiContext: ${reason}`);
|
|
6590
|
-
return void 0;
|
|
6591
|
-
}
|
|
6592
|
-
function escapeXmlText(value) {
|
|
6593
|
-
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
6594
|
-
}
|
|
6595
|
-
var init_linzumiContext = __esm({
|
|
6596
|
-
"src/linzumiContext.ts"() {
|
|
6597
|
-
"use strict";
|
|
6598
|
-
init_json();
|
|
6599
|
-
}
|
|
6600
|
-
});
|
|
6601
|
-
|
|
6602
6846
|
// src/reconnectContext.ts
|
|
6603
6847
|
function parseReconnectContextMessages(value) {
|
|
6604
6848
|
if (!Array.isArray(value)) {
|
|
@@ -11336,10 +11580,27 @@ async function startCodexThread(codex, options) {
|
|
|
11336
11580
|
cwd: options.cwd,
|
|
11337
11581
|
serviceName: "kandan-local-runner",
|
|
11338
11582
|
personality: "pragmatic",
|
|
11583
|
+
...developerInstructionsForThreadStart(options),
|
|
11339
11584
|
...codexThreadRuntimeOverrides(options)
|
|
11340
11585
|
});
|
|
11341
11586
|
return extractThreadIdFromResponse(start);
|
|
11342
11587
|
}
|
|
11588
|
+
function developerInstructionsForThreadStart(options) {
|
|
11589
|
+
const developerPrompt = options.channelSession.developerPrompt;
|
|
11590
|
+
if (developerPrompt === void 0) {
|
|
11591
|
+
return {};
|
|
11592
|
+
}
|
|
11593
|
+
return {
|
|
11594
|
+
developerInstructions: commanderDeveloperInstructions({
|
|
11595
|
+
cwd: options.cwd,
|
|
11596
|
+
planTool: "linzumi-mcp",
|
|
11597
|
+
developerPrompt,
|
|
11598
|
+
linzumiContext: parseLinzumiConversationContext(
|
|
11599
|
+
options.channelSession.linzumiContext
|
|
11600
|
+
)
|
|
11601
|
+
})
|
|
11602
|
+
};
|
|
11603
|
+
}
|
|
11343
11604
|
async function pushOk2(kandan, topic, event, payload) {
|
|
11344
11605
|
const reply = await kandan.push(topic, event, payload);
|
|
11345
11606
|
if (isJsonObject(reply) && reply.status === "ok" && isJsonObject(reply.response)) {
|
|
@@ -11366,6 +11627,7 @@ var init_channelSession = __esm({
|
|
|
11366
11627
|
init_channelSessionSupport();
|
|
11367
11628
|
init_commanderAttachments();
|
|
11368
11629
|
init_codexRuntimeOptions();
|
|
11630
|
+
init_commanderDeveloperInstructions();
|
|
11369
11631
|
init_codexOutput();
|
|
11370
11632
|
init_codexSessionLog();
|
|
11371
11633
|
init_integration();
|
|
@@ -11406,6 +11668,23 @@ var init_channelSession = __esm({
|
|
|
11406
11668
|
// src/claudeCodePipeline.ts
|
|
11407
11669
|
import { existsSync as existsSync3 } from "node:fs";
|
|
11408
11670
|
import { isAbsolute as isAbsolute2, resolve as resolve2 } from "node:path";
|
|
11671
|
+
function claudeIncompleteProgressCompletionReason(body, bodySource) {
|
|
11672
|
+
if (bodySource !== "assistant_aggregate") {
|
|
11673
|
+
return void 0;
|
|
11674
|
+
}
|
|
11675
|
+
const normalized = body.trim().replace(/\s+/g, " ").toLowerCase();
|
|
11676
|
+
if (normalized === "") {
|
|
11677
|
+
return void 0;
|
|
11678
|
+
}
|
|
11679
|
+
const continuationPatterns = [
|
|
11680
|
+
/\blet me\b.*\bbefore\b.*\b(writing|implementing|editing|patching|making|changing|coding|updating)\b/u,
|
|
11681
|
+
/\blet me\b.*\b(check|inspect|confirm|look|verify|investigate|find|review)\b/u,
|
|
11682
|
+
/\bi(?:'|\u2019)ll\b.*\b(check|inspect|confirm|look|verify|investigate|find|review|write|implement|update|edit|patch|run)\b/u,
|
|
11683
|
+
/\bi will\b.*\b(check|inspect|confirm|look|verify|investigate|find|review|write|implement|update|edit|patch|run)\b/u,
|
|
11684
|
+
/\bnext\b.*\b(i(?:'|\u2019)ll|i will|let me)\b/u
|
|
11685
|
+
];
|
|
11686
|
+
return continuationPatterns.some((pattern) => pattern.test(normalized)) ? incompleteProgressCompletionReason : void 0;
|
|
11687
|
+
}
|
|
11409
11688
|
function createClaudeCodeSessionPipeline(host) {
|
|
11410
11689
|
const sourceSeqByTurn = /* @__PURE__ */ new Map();
|
|
11411
11690
|
const snapshotsByTurn = /* @__PURE__ */ new Map();
|
|
@@ -11535,6 +11814,10 @@ function createClaudeCodeSessionPipeline(host) {
|
|
|
11535
11814
|
submit("turn/completed", { turnId: turn.turnId });
|
|
11536
11815
|
activeTurn = void 0;
|
|
11537
11816
|
};
|
|
11817
|
+
const failTurn2 = (turn, reason) => {
|
|
11818
|
+
submit("turn/failed", { turnId: turn.turnId, reason });
|
|
11819
|
+
activeTurn = void 0;
|
|
11820
|
+
};
|
|
11538
11821
|
const handleToolResult = (turn, event) => {
|
|
11539
11822
|
const pending = turn.pendingTools.get(event.itemKey);
|
|
11540
11823
|
turn.pendingTools.delete(event.itemKey);
|
|
@@ -11752,6 +12035,19 @@ function createClaudeCodeSessionPipeline(host) {
|
|
|
11752
12035
|
}
|
|
11753
12036
|
const turn = ensureTurn();
|
|
11754
12037
|
lastUsage = event.usage ?? lastUsage;
|
|
12038
|
+
const incompleteProgressReason = claudeIncompleteProgressCompletionReason(
|
|
12039
|
+
event.body,
|
|
12040
|
+
event.bodySource
|
|
12041
|
+
);
|
|
12042
|
+
if (incompleteProgressReason !== void 0) {
|
|
12043
|
+
host.log("claude_pipeline.incomplete_progress_completion", {
|
|
12044
|
+
thread_key: host.threadKey,
|
|
12045
|
+
turn_id: turn.turnId,
|
|
12046
|
+
body_source: event.bodySource ?? "unspecified"
|
|
12047
|
+
});
|
|
12048
|
+
failTurn2(turn, incompleteProgressReason);
|
|
12049
|
+
return;
|
|
12050
|
+
}
|
|
11755
12051
|
finishTurn(turn, event.body);
|
|
11756
12052
|
return;
|
|
11757
12053
|
}
|
|
@@ -11761,6 +12057,19 @@ function createClaudeCodeSessionPipeline(host) {
|
|
|
11761
12057
|
return;
|
|
11762
12058
|
}
|
|
11763
12059
|
lastUsage = event.usage ?? lastUsage;
|
|
12060
|
+
const incompleteProgressReason = claudeIncompleteProgressCompletionReason(
|
|
12061
|
+
event.body,
|
|
12062
|
+
event.bodySource
|
|
12063
|
+
);
|
|
12064
|
+
if (incompleteProgressReason !== void 0) {
|
|
12065
|
+
host.log("claude_pipeline.incomplete_progress_completion", {
|
|
12066
|
+
thread_key: host.threadKey,
|
|
12067
|
+
turn_id: activeTurn.turnId,
|
|
12068
|
+
body_source: event.bodySource ?? "unspecified"
|
|
12069
|
+
});
|
|
12070
|
+
failTurn2(activeTurn, incompleteProgressReason);
|
|
12071
|
+
return;
|
|
12072
|
+
}
|
|
11764
12073
|
finishTurn(activeTurn, event.body);
|
|
11765
12074
|
return;
|
|
11766
12075
|
}
|
|
@@ -11773,11 +12082,7 @@ function createClaudeCodeSessionPipeline(host) {
|
|
|
11773
12082
|
});
|
|
11774
12083
|
return;
|
|
11775
12084
|
}
|
|
11776
|
-
|
|
11777
|
-
turnId: activeTurn.turnId,
|
|
11778
|
-
reason: event.reason
|
|
11779
|
-
});
|
|
11780
|
-
activeTurn = void 0;
|
|
12085
|
+
failTurn2(activeTurn, event.reason);
|
|
11781
12086
|
return;
|
|
11782
12087
|
}
|
|
11783
12088
|
}
|
|
@@ -11989,12 +12294,13 @@ function claudeToolInputSummary(input) {
|
|
|
11989
12294
|
return void 0;
|
|
11990
12295
|
}
|
|
11991
12296
|
}
|
|
11992
|
-
var maxRetainedSnapshots, todoStatusGlyphs;
|
|
12297
|
+
var incompleteProgressCompletionReason, maxRetainedSnapshots, todoStatusGlyphs;
|
|
11993
12298
|
var init_claudeCodePipeline = __esm({
|
|
11994
12299
|
"src/claudeCodePipeline.ts"() {
|
|
11995
12300
|
"use strict";
|
|
11996
12301
|
init_json();
|
|
11997
12302
|
init_integration();
|
|
12303
|
+
incompleteProgressCompletionReason = "Claude Code ended after an incomplete progress response instead of a final answer";
|
|
11998
12304
|
maxRetainedSnapshots = 8;
|
|
11999
12305
|
todoStatusGlyphs = {
|
|
12000
12306
|
completed: "[x]",
|
|
@@ -13129,7 +13435,9 @@ async function startClaudeCodeSession(options) {
|
|
|
13129
13435
|
return completeClaudeCodeSession(options, state);
|
|
13130
13436
|
}
|
|
13131
13437
|
async function emitClaudeCodeTurnCompleted(options, state) {
|
|
13132
|
-
const
|
|
13438
|
+
const aggregateText = nonEmptyText(claudeAssistantAggregateText(state));
|
|
13439
|
+
const body = state.resultText ?? aggregateText ?? "";
|
|
13440
|
+
const bodySource = state.resultText !== void 0 ? "result" : aggregateText !== void 0 ? "assistant_aggregate" : "empty";
|
|
13133
13441
|
if (state.sessionId === void 0) {
|
|
13134
13442
|
return;
|
|
13135
13443
|
}
|
|
@@ -13137,12 +13445,17 @@ async function emitClaudeCodeTurnCompleted(options, state) {
|
|
|
13137
13445
|
type: "turn_completed",
|
|
13138
13446
|
sessionId: state.sessionId,
|
|
13139
13447
|
body,
|
|
13448
|
+
bodySource,
|
|
13140
13449
|
usage: state.usage
|
|
13141
13450
|
});
|
|
13142
13451
|
}
|
|
13143
13452
|
async function completeClaudeCodeSession(options, state) {
|
|
13144
|
-
const
|
|
13145
|
-
|
|
13453
|
+
const aggregateText = nonEmptyText(claudeAssistantAggregateText(state));
|
|
13454
|
+
const completion = state.resultText !== void 0 ? { body: state.resultText, bodySource: "result" } : aggregateText !== void 0 ? { body: aggregateText, bodySource: "assistant_aggregate" } : state.lastCompletedTurnBody !== void 0 ? {
|
|
13455
|
+
body: state.lastCompletedTurnBody,
|
|
13456
|
+
bodySource: "last_completed_turn"
|
|
13457
|
+
} : void 0;
|
|
13458
|
+
if (completion === void 0) {
|
|
13146
13459
|
return await failClaudeCodeSession(
|
|
13147
13460
|
options,
|
|
13148
13461
|
state.sessionId,
|
|
@@ -13158,13 +13471,14 @@ async function completeClaudeCodeSession(options, state) {
|
|
|
13158
13471
|
}
|
|
13159
13472
|
const result = {
|
|
13160
13473
|
sessionId: state.sessionId,
|
|
13161
|
-
body,
|
|
13474
|
+
body: completion.body,
|
|
13162
13475
|
usage: state.usage
|
|
13163
13476
|
};
|
|
13164
13477
|
await options.onTranscriptEvent?.({
|
|
13165
13478
|
type: "session_completed",
|
|
13166
13479
|
sessionId: result.sessionId,
|
|
13167
13480
|
body: result.body,
|
|
13481
|
+
bodySource: completion.bodySource,
|
|
13168
13482
|
usage: result.usage
|
|
13169
13483
|
});
|
|
13170
13484
|
return result;
|
|
@@ -14961,11 +15275,34 @@ var init_defaultUrls = __esm({
|
|
|
14961
15275
|
import { spawn as spawn3 } from "node:child_process";
|
|
14962
15276
|
import { randomBytes } from "node:crypto";
|
|
14963
15277
|
import { createServer as createServer2 } from "node:http";
|
|
15278
|
+
function oauthCallbackTimeoutMs(override, env = process.env) {
|
|
15279
|
+
if (typeof override === "number" && Number.isFinite(override) && override > 0) {
|
|
15280
|
+
return override;
|
|
15281
|
+
}
|
|
15282
|
+
const raw = env.LINZUMI_OAUTH_CALLBACK_TIMEOUT_MS?.trim();
|
|
15283
|
+
if (raw !== void 0 && raw !== "") {
|
|
15284
|
+
const parsed = Number.parseInt(raw, 10);
|
|
15285
|
+
if (Number.isFinite(parsed) && parsed > 0) {
|
|
15286
|
+
return parsed;
|
|
15287
|
+
}
|
|
15288
|
+
}
|
|
15289
|
+
return DEFAULT_OAUTH_CALLBACK_TIMEOUT_MS;
|
|
15290
|
+
}
|
|
14964
15291
|
async function acquireLocalRunnerTokenDetails(options) {
|
|
14965
15292
|
const httpBaseUrl = kandanHttpBaseUrl(options.kandanUrl);
|
|
14966
15293
|
const state = randomBytes(18).toString("base64url");
|
|
14967
15294
|
const callback = await startCallbackServer({
|
|
14968
|
-
host: oauthCallbackHost(options.kandanUrl, options.callbackHost)
|
|
15295
|
+
host: oauthCallbackHost(options.kandanUrl, options.callbackHost),
|
|
15296
|
+
exchange: async (result) => {
|
|
15297
|
+
if (result.state !== state) {
|
|
15298
|
+
throw new Error("local runner OAuth state mismatch");
|
|
15299
|
+
}
|
|
15300
|
+
return await exchangeCodeForToken({
|
|
15301
|
+
httpBaseUrl,
|
|
15302
|
+
code: result.code,
|
|
15303
|
+
redirectUri: result.redirectUri
|
|
15304
|
+
});
|
|
15305
|
+
}
|
|
14969
15306
|
});
|
|
14970
15307
|
const authorizeUrl = authorizationUrl({
|
|
14971
15308
|
httpBaseUrl,
|
|
@@ -14981,15 +15318,9 @@ ${authorizeUrl}
|
|
|
14981
15318
|
`);
|
|
14982
15319
|
try {
|
|
14983
15320
|
await (options.openAuthorizationUrl ?? openBrowser)(authorizeUrl);
|
|
14984
|
-
|
|
14985
|
-
|
|
14986
|
-
|
|
14987
|
-
}
|
|
14988
|
-
return await exchangeCodeForToken({
|
|
14989
|
-
httpBaseUrl,
|
|
14990
|
-
code: result.code,
|
|
14991
|
-
redirectUri: callback.redirectUri
|
|
14992
|
-
});
|
|
15321
|
+
return await callback.waitForToken(
|
|
15322
|
+
oauthCallbackTimeoutMs(options.waitForTokenTimeoutMs)
|
|
15323
|
+
);
|
|
14993
15324
|
} finally {
|
|
14994
15325
|
callback.close();
|
|
14995
15326
|
}
|
|
@@ -15169,49 +15500,83 @@ function stringBodyField(body, key) {
|
|
|
15169
15500
|
}
|
|
15170
15501
|
function startCallbackServer(args) {
|
|
15171
15502
|
return new Promise((resolve12, reject) => {
|
|
15172
|
-
let
|
|
15173
|
-
let
|
|
15174
|
-
|
|
15175
|
-
|
|
15176
|
-
|
|
15503
|
+
let resolveToken;
|
|
15504
|
+
let rejectToken;
|
|
15505
|
+
let settled = false;
|
|
15506
|
+
const tokenPromise = new Promise(
|
|
15507
|
+
(tokenResolve, tokenReject) => {
|
|
15508
|
+
resolveToken = tokenResolve;
|
|
15509
|
+
rejectToken = tokenReject;
|
|
15510
|
+
}
|
|
15511
|
+
);
|
|
15512
|
+
tokenPromise.catch(() => {
|
|
15177
15513
|
});
|
|
15514
|
+
const settle = (apply) => {
|
|
15515
|
+
if (settled) {
|
|
15516
|
+
return false;
|
|
15517
|
+
}
|
|
15518
|
+
settled = true;
|
|
15519
|
+
apply();
|
|
15520
|
+
return true;
|
|
15521
|
+
};
|
|
15522
|
+
let boundRedirectUri = `http://${args.host}/callback`;
|
|
15178
15523
|
const server = createServer2((request, response) => {
|
|
15179
|
-
|
|
15180
|
-
|
|
15181
|
-
|
|
15182
|
-
|
|
15183
|
-
|
|
15184
|
-
|
|
15185
|
-
|
|
15524
|
+
void (async () => {
|
|
15525
|
+
try {
|
|
15526
|
+
const url = new URL(request.url ?? "/", `http://${args.host}`);
|
|
15527
|
+
const code = url.searchParams.get("code");
|
|
15528
|
+
const state = url.searchParams.get("state");
|
|
15529
|
+
const error = url.searchParams.get("error");
|
|
15530
|
+
if (error !== null && error.trim() !== "") {
|
|
15531
|
+
settle(
|
|
15532
|
+
() => rejectToken?.(new Error(`local runner OAuth failed: ${error}`))
|
|
15533
|
+
);
|
|
15534
|
+
writeOauthResult(response, {
|
|
15535
|
+
title: "Not authorized",
|
|
15536
|
+
body: "You denied the request. Close this tab and rerun the bootstrap command when you're ready.",
|
|
15537
|
+
status: 403
|
|
15538
|
+
});
|
|
15539
|
+
return;
|
|
15540
|
+
}
|
|
15541
|
+
if (code === null || state === null || code.trim() === "" || state.trim() === "") {
|
|
15542
|
+
writeOauthResult(response, {
|
|
15543
|
+
title: "Authorization callback was incomplete",
|
|
15544
|
+
body: "We didn't receive the authorization code. Return to your terminal and try again.",
|
|
15545
|
+
status: 400
|
|
15546
|
+
});
|
|
15547
|
+
return;
|
|
15548
|
+
}
|
|
15549
|
+
let token;
|
|
15550
|
+
try {
|
|
15551
|
+
token = await args.exchange({
|
|
15552
|
+
code,
|
|
15553
|
+
state,
|
|
15554
|
+
redirectUri: boundRedirectUri
|
|
15555
|
+
});
|
|
15556
|
+
} catch (exchangeError) {
|
|
15557
|
+
settle(() => rejectToken?.(exchangeError));
|
|
15558
|
+
writeOauthResult(response, {
|
|
15559
|
+
title: "Authorization could not be completed",
|
|
15560
|
+
body: "We received the authorization but could not finish setup. Return to your terminal for details and rerun the bootstrap command.",
|
|
15561
|
+
status: 400
|
|
15562
|
+
});
|
|
15563
|
+
return;
|
|
15564
|
+
}
|
|
15565
|
+
const accepted = settle(() => resolveToken?.(token));
|
|
15186
15566
|
writeOauthResult(response, {
|
|
15187
|
-
title: "
|
|
15188
|
-
body: "
|
|
15189
|
-
status:
|
|
15567
|
+
title: accepted ? "Computer authorized" : "Already authorized",
|
|
15568
|
+
body: "This computer has been authorized for agentic use in Linzumi. Feel free to close this tab and let the terminal finish setup.",
|
|
15569
|
+
status: 200
|
|
15190
15570
|
});
|
|
15191
|
-
|
|
15192
|
-
|
|
15193
|
-
if (code === null || state === null || code.trim() === "" || state.trim() === "") {
|
|
15571
|
+
} catch (handlerError) {
|
|
15572
|
+
settle(() => rejectToken?.(handlerError));
|
|
15194
15573
|
writeOauthResult(response, {
|
|
15195
|
-
title: "Authorization callback
|
|
15196
|
-
body: "
|
|
15197
|
-
status:
|
|
15574
|
+
title: "Authorization callback failed",
|
|
15575
|
+
body: "Return to your terminal and rerun the bootstrap command.",
|
|
15576
|
+
status: 500
|
|
15198
15577
|
});
|
|
15199
|
-
return;
|
|
15200
15578
|
}
|
|
15201
|
-
|
|
15202
|
-
writeOauthResult(response, {
|
|
15203
|
-
title: "Computer authorized",
|
|
15204
|
-
body: "This computer has been authorized for agentic use in Linzumi. Feel free to close this tab and let the terminal finish setup.",
|
|
15205
|
-
status: 200
|
|
15206
|
-
});
|
|
15207
|
-
} catch (error) {
|
|
15208
|
-
rejectCallback?.(error);
|
|
15209
|
-
writeOauthResult(response, {
|
|
15210
|
-
title: "Authorization callback failed",
|
|
15211
|
-
body: "Return to your terminal and rerun the bootstrap command.",
|
|
15212
|
-
status: 500
|
|
15213
|
-
});
|
|
15214
|
-
}
|
|
15579
|
+
})();
|
|
15215
15580
|
});
|
|
15216
15581
|
server.once("error", reject);
|
|
15217
15582
|
server.listen(0, args.host, () => {
|
|
@@ -15224,9 +15589,34 @@ function startCallbackServer(args) {
|
|
|
15224
15589
|
);
|
|
15225
15590
|
return;
|
|
15226
15591
|
}
|
|
15592
|
+
boundRedirectUri = `http://${args.host}:${address.port}/callback`;
|
|
15227
15593
|
resolve12({
|
|
15228
|
-
redirectUri:
|
|
15229
|
-
|
|
15594
|
+
redirectUri: boundRedirectUri,
|
|
15595
|
+
// Bound the wait so that "only spurious/incomplete requests, no real
|
|
15596
|
+
// callback" can't hang forever. Incomplete requests deliberately never
|
|
15597
|
+
// settle the token promise (they only render the incomplete page), so
|
|
15598
|
+
// the overall timeout is what guarantees forward progress. The timer is
|
|
15599
|
+
// unref'd so it can't keep the process alive on its own, and it's
|
|
15600
|
+
// cleared once the token promise settles for any reason.
|
|
15601
|
+
waitForToken: (timeoutMs) => {
|
|
15602
|
+
const effectiveTimeoutMs = oauthCallbackTimeoutMs(timeoutMs);
|
|
15603
|
+
const timer = setTimeout(() => {
|
|
15604
|
+
settle(
|
|
15605
|
+
() => rejectToken?.(
|
|
15606
|
+
new Error(
|
|
15607
|
+
"Authorization timed out before the browser callback completed. Rerun the connect command and finish authorizing in the browser."
|
|
15608
|
+
)
|
|
15609
|
+
)
|
|
15610
|
+
);
|
|
15611
|
+
server.close();
|
|
15612
|
+
}, effectiveTimeoutMs);
|
|
15613
|
+
timer.unref?.();
|
|
15614
|
+
tokenPromise.finally(() => {
|
|
15615
|
+
clearTimeout(timer);
|
|
15616
|
+
}).catch(() => {
|
|
15617
|
+
});
|
|
15618
|
+
return tokenPromise;
|
|
15619
|
+
},
|
|
15230
15620
|
close: () => {
|
|
15231
15621
|
server.close();
|
|
15232
15622
|
}
|
|
@@ -15291,7 +15681,7 @@ function oauthResultHtml(args) {
|
|
|
15291
15681
|
place-items: center;
|
|
15292
15682
|
padding: 24px;
|
|
15293
15683
|
background:
|
|
15294
|
-
radial-gradient(1200px 600px at 50% -10%, var(--notice-soft), transparent 60%),
|
|
15684
|
+
radial-gradient(1200px 600px at 50% -10%, var(${success ? "--success-soft" : "--notice-soft"}), transparent 60%),
|
|
15295
15685
|
var(--page-bg);
|
|
15296
15686
|
color: var(--foreground);
|
|
15297
15687
|
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
@@ -15376,11 +15766,12 @@ function openBrowser(url) {
|
|
|
15376
15766
|
});
|
|
15377
15767
|
});
|
|
15378
15768
|
}
|
|
15379
|
-
var LINZUMI_LOGO_SVG;
|
|
15769
|
+
var DEFAULT_OAUTH_CALLBACK_TIMEOUT_MS, LINZUMI_LOGO_SVG;
|
|
15380
15770
|
var init_oauth = __esm({
|
|
15381
15771
|
"src/oauth.ts"() {
|
|
15382
15772
|
"use strict";
|
|
15383
15773
|
init_runnerLogger();
|
|
15774
|
+
DEFAULT_OAUTH_CALLBACK_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
15384
15775
|
LINZUMI_LOGO_SVG = '<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path fill="currentColor" d="M206.7,82.37l2.55-6.45,2.01-3.63c.67-1.21,1.07-1.88,2.55-3.63,1.34-1.61,3.36-4.43,5.64-6.58,2.42-2.24,5.06-4.3,7.93-6.18,3.92-2.53,8.17-4.52,12.63-5.91,1.79-.63,4.03-1.16,6.72-1.61,6.1-.88,12.29-.92,18.4-.13,2.69.45,5.06,1.03,7.12,1.75,2.15.67,3.49,1.07,5.64,2.15,4.55,2.16,8.87,4.77,12.9,7.79,1.61,1.34,2.42,2.15,4.16,4.16l5.91,7.66c1.34,2.01,1.34,2.28,2.15,4.03l2.55,6.58c.67,1.34-.13,1.34,1.07.94,1.21-.27,4.3-2.01,6.45-2.82,4.7-1.83,9.62-3,14.64-3.49,2.42-.27,3.76-.54,7.12-.27s9.27,1.21,12.76,2.15c3.63.94,6.58,2.55,8.73,3.49,2.15,1.07,2.55,1.48,4.16,2.55,3.49,2.51,6.77,5.29,9.81,8.33,1.52,1.7,3.04,3.58,4.57,5.64,2.74,4.49,4.86,9.32,6.31,14.37.67,2.28,1.07,3.49,1.34,6.72.27,3.22,0,10.48.4,12.76.27,2.28.27.67,1.61.94,1.48.27,4.3,0,6.72.4,2.42.27,4.97.85,7.66,1.75,6.76,2.32,13.01,5.92,18.4,10.61,2.28,1.75,2.96,2.69,4.3,4.3,3.51,3.93,6.32,8.43,8.33,13.3,1.07,2.15,1.21,2.28,1.88,5.1.54,2.96,1.61,8.19,1.61,12.36s-.81,9.67-1.34,12.76c-.67,3.22-1.07,4.03-2.15,6.18-2.16,4.54-4.81,8.82-7.93,12.76-1.25,1.61-2.6,3-4.03,4.16-1.48,1.34-2.69,2.42-4.7,3.76-3.79,2.34-7.74,4.4-11.82,6.18l-6.58,2.15c-2.06.45-4.12.72-6.18.81l-7.25.13c-2.28,0-2.82.27-6.58-.4-3.76-.81-11.69-2.82-15.99-4.3-4.16-1.34-6.31-2.69-9.67-4.43-3.49-1.75-10.48-6.18-12.9-7.39-8.26-4.54-16.78-8.58-25.52-12.09-4.3-1.75-9.27-3.22-11.82-4.03-2.55-.81-5.24-1.61-7.66-2.15-8.39-2.25-16.99-3.6-25.66-4.03-3.9-.27-4.84-.27-8.19-.13-3.67-.09-7.79.04-12.36.4-7.9.79-15.75,2.04-23.51,3.76-8.37,2.26-16.62,4.95-24.72,8.06-3.22,1.34-2.82.81-9.13,4.16-6.31,3.36-22.03,12.22-28.75,15.58-6.72,3.36-8.73,3.49-11.82,4.43-3.09,1.07-4.3,1.21-6.58,1.61-7.3,1.09-14.71,1.18-22.03.27-2.55-.54-5.78-1.61-7.79-2.28-2.01-.54-2.15-.67-4.03-1.75-2.02-1.07-5.64-3.22-7.79-4.7-3.24-2.15-6.14-4.77-8.6-7.79-1.34-1.52-2.69-3.36-4.03-5.51-1.52-2.51-2.96-5.24-4.3-8.19-2.03-5.46-3.03-11.24-2.96-17.06,0-2.96.13-6.72.67-9.67.54-2.87,1.34-5.6,2.42-8.19,4.24-10.52,12.04-19.22,22.03-24.58,5.19-2.98,10.88-4.98,16.79-5.91,2.55-.4,5.37-.13,6.72-.4,1.34-.27,1.34,1.34,1.61-.94.4-2.28,0-9.4.4-12.76.27-3.36.81-4.97,1.48-7.25,1.87-6.19,4.88-11.97,8.87-17.06,3.47-3.98,7.39-7.54,11.69-10.61,4.43-2.61,9.11-4.77,13.97-6.45,2.55-.67,6.99-1.34,9.13-1.75,2.15-.27,1.88-.13,3.63-.13,1.79-.09,4.03,0,6.72.27,2.69.18,5.73.72,9.13,1.61,3.49,1.07,9.27,4.03,11.28,4.7s.4.27,1.07-.94ZM512.27,255.7c0,141.39-114.62,256-256,256S.27,397.09.27,255.7,114.89-.3,256.27-.3s256,114.62,256,256ZM449.33,352.66c14.67-29.16,22.94-62.09,22.94-96.95,0-119.29-96.71-216-216-216S40.27,136.41,40.27,255.7c0,41.89,11.94,80.98,32.57,114.09,1.7,1.79,2.94.65,3.05-.57.27-1.61,2.75-20.85,4.43-27.27,1.87-7.6,4.52-14.98,7.93-22.03,1.75-3.49,3.76-7.93,6.18-11.82,8.77-13.95,19.75-26.38,32.51-36.81,7.24-5.32,14.87-10.08,22.84-14.24,9.74-4.78,20.09-8.22,30.76-10.21,4.03-.99,7.61-1.66,10.75-2.02,3.36-.54,5.78-.54,9.27-.94,3.49-.54,9.32-1.16,11.82-2.01,6.65-2.27,5.64-6.72,3.09-7.52-2.55-.81-9.67-1.88-13.84-2.96-4.16-1.21-8.73-2.82-11.28-3.76-2.55-.94-2.28-.94-3.9-2.02l-5.91-4.03c-.94-.94-1.34-.94.54-2.02l10.21-5.51c2.01-1.07,1.75-.67,3.09-.13,1.34.67,4.3,2.42,6.72,3.36,7.2,2.69,14.96,3.52,22.57,2.42,1.34-.27,1.34-.54,1.61-1.21.27-.67.81-.94-.13-2.69-.94-1.88-4.43-6.58-5.64-8.46l-1.21-2.28c-.27-.45-1.07-1.07,1.21-1.75,2.42-.54,10.48-2.58,12.9-2.82.86-.09.67,0,1.75,1.07,1.07,1.07,3.09,3.63,4.84,5.24,1.88,1.61,4.43,3.22,6.18,4.3,2.8,1.71,5.99,2.68,9.27,2.82,1.88,0,4.97-.13,7.12-.67,2.15-.4,3.63-.94,5.64-2.02,2.01-1.07,4.7-2.69,6.72-4.43,2.01-1.75,3.49-5.1,5.64-6.04,2.15-.81,4.97.54,7.12.94,2.28.4,4.97,1.21,6.18,1.61,1.21.4,2.01.4.67,2.28l-8.06,10.34c-1.34,1.88.13,5.51,1.21,5.64l5.64.27c2.28-.13,4.43.13,7.66-.67,3.36-.81,9.27-2.96,11.82-3.9,2.69-.94,3.22-1.34,4.16-2.01.81-.54,1.39-1.03,1.75-1.48.45-.27.67-1.07,2.82,0s9.4,4.97,11.28,6.18c2.01,1.21,1.07.94,0,1.75l-5.51,3.9c-1.48.94-1.07.94-3.22,1.88-2.15,1.07-6.58,2.96-9.67,4.03s-4.03,1.75-8.73,2.69c-4.7.81-14.51,1.75-19.48,2.55-4.97.81-7.93,1.34-10.34,2.01-2.28.67-2.15.94-3.49,1.88-1.48,1.07-2.69,1.61-4.97,3.9-2.28,2.28-5.91,6.85-8.73,9.81-2.82,2.96-6.45,6.04-8.33,7.79-2.02,1.61-1.61,1.34-3.36,2.42l-6.99,4.03-4.03,2.02-6.72,2.15c-2.42.67-3.9,1.21-7.66,2.01l-14.91,2.82c-3.63.81-4.3,1.07-7.12,2.01-2.96,1.07-6.22,2.46-9.81,4.16-3.22,1.43-6.81,3.45-10.75,6.04-13.6,9.14-24.61,21.63-31.97,36.27-2.01,3.76-2.96,6.58-3.9,9.27-1.07,2.69-1.61,4.03-2.28,6.58-.67,2.69-1.48,5.24-2.15,9.27-.54,4.16-1.48,11.15-1.75,15.45-.27,4.16-.27,6.04,0,10.21l1.88,14.91c.67,3.76,1.48,5.91,2.15,8.19l1.88,5.64c.99,2.6,2.42,5.78,4.3,9.54,2.15,3.76,5.37,9.13,8.06,13.03,10.08,14.51,23.81,26.36,40.17,33.05,22.55,9.22,43.32,10.46,61.89,10.46,3.25,0,6.49-.09,9.71-.23,3.07-.42,2.74-6.09,10.48-9.42,5.26-2.26,13.7-2.42,14.91-2.55,1.07-.13-5.24-4.57-7.79-6.45-2.55-1.88-4.97-4.3-6.72-5.91-1.75-1.75-2.42-2.28-3.9-4.16-1.61-1.88-3.9-5.51-5.24-7.12-1.34-1.61-1.48-2.28-2.55-2.55-.98-.27-2.37-.09-4.16.54-1.88.4-5.37,1.21-7.12,1.88-1.75.67-2.02.81-3.09,2.01-1.07,1.07-2.69,3.76-3.63,4.7-.81.94-.67.67-1.48.94-.81.27-2.42.67-3.63.54-1.34-.18-2.55-.58-3.63-1.21-.81-.81-1.48-2.42-1.88-3.22-.4-.94-.54-1.21-.54-2.15l.4-3.49c.18-1.52.72-3.27,1.61-5.24.94-1.75,1.88-3.49,4.16-5.64,2.15-2.02,7.52-5.51,9.13-6.85,1.61-1.34,1.21-2.15.54-3.63-2.69-5.16-6.33-9.77-10.75-13.57-2.42-1.88-5.51-3.22-7.79-4.3-2.15-1.21-2.01-1.21-5.78-2.42-3.76-1.07-13.16-3.63-16.79-4.84-3.63-1.07-2.82-.94-5.1-2.01l-8.19-4.3c-1.75-.94-1.34-.54-2.69-1.61l-5.51-4.57c-2.18-1.93-3.77-4.45-4.57-7.25-.45-1.52-.45-2.87,0-4.03.4-1.34,0-1.21,2.01-3.63,2.15-2.42,7.25-7.93,10.21-10.75,3.09-2.82,4.97-4.03,7.79-6.04,5.43-3.82,11.09-7.32,16.93-10.48,2.42-1.21,5.37-2.02,7.12-2.69,1.61-.81,2.64-1.43,3.09-1.88.54-.4.67.54.4-.94-.4-1.48-1.88-4.97-2.28-7.66-.4-2.82-.4-6.18,0-8.73.36-2.42,1.03-4.66,2.01-6.72,1.16-2.24,2.46-4.3,3.9-6.18,1.34-1.7,2.91-3.04,4.7-4.03,1.75-1.07,4.3-2.01,6.18-2.42,1.61-.45,3.13-.58,4.57-.4l4.57.27c1.34.18,2.55.49,3.63.94,1.07.54,2.55,1.48,3.09,2.01.4.67.67.13-.27,1.61-1.07,1.48-4.16,4.57-5.78,7.12-1.61,2.69-2.96,5.6-4.03,8.73-.94,3.22-1.88,8.73-2.01,10.75-.27,2.15,4.7,1.75,5.1.54.54-1.07.27-2.55,1.07-5.1.81-2.42,2.42-7.25,3.9-9.81,1.34-2.55,2.82-3.76,4.57-5.51,1.79-1.88,3.67-3.45,5.64-4.7,1.88-1.21,3.22-1.75,5.64-2.28,2.42-.4,6.18-.67,8.73-.67,2.42,0,3.9.13,6.18.94,2.15.81,5.24,2.69,7.12,4.03,1.79,1.52,3.22,3.09,4.3,4.7,1.21,1.61,1.88,2.96,2.55,5.1.67,2.15,1.34,5.1,1.34,7.66,0,2.69-.54,6.04-1.21,8.19-.63,2.24-1.43,4.03-2.42,5.37-.67,1.34-.94,1.61-2.15,2.82-1.21,1.34-3.22,3.22-4.97,4.57-1.75,1.21-4.43,2.28-5.51,3.22-.94.81-.4,2.51.4,2.42.94.13,1.75.4,4.57-.13,2.82-.4,8.33-2.15,12.22-2.82,11.99-2.63,24.41-2.63,36.4,0,3.22.54,4.16,1.07,6.31,1.75l6.04,2.28c2.42,1.07,5.51,2.42,8.19,4.16,8.15,5.36,15.14,12.3,20.55,20.42,1.61,2.42,2.87,4.66,3.76,6.72,1.85,4.51,3.42,9.13,4.7,13.84.67,2.82,1.21,4.43,1.61,8.19.4,3.76.4,11.82.54,14.37.27,2.55-.13,2.28,1.75,1.34,1.75-.94,20.09-7.74,30.63-31.57,9.16-20.71,1.9-47.26-2.28-55.34-1.75-3.22-4.16-6.99-6.31-9.81-4.44-5.14-9.6-9.62-15.31-13.3-2.96-1.7-5.55-3.09-7.79-4.16-4.33-1.6-8.77-2.86-13.3-3.76l-6.18-.4h-14.37c-2.69-.27-3.1-3.18-.54-4.3,3.64-1.58,9.88-2.63,18.54-2.42,8.78.21,14.91,1.88,17.33,2.55,13.98,3.94,30.19,16.65,38.55,30.76,6.61,11.16,9.81,29.96,9.81,29.96.37,1.75,2.18,1.66,3.08.35ZM232.78,345.3c-3.91,0-7.08,3.17-7.08,7.08s3.17,7.08,7.08,7.08,7.08-3.17,7.08-7.08-3.17-7.08-7.08-7.08Z"/></svg>';
|
|
15385
15776
|
}
|
|
15386
15777
|
});
|
|
@@ -18719,7 +19110,7 @@ var linzumiCliVersion, linzumiCliVersionText;
|
|
|
18719
19110
|
var init_version = __esm({
|
|
18720
19111
|
"src/version.ts"() {
|
|
18721
19112
|
"use strict";
|
|
18722
|
-
linzumiCliVersion = "0.0.
|
|
19113
|
+
linzumiCliVersion = "0.0.90-beta";
|
|
18723
19114
|
linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
|
|
18724
19115
|
}
|
|
18725
19116
|
});
|
|
@@ -26082,173 +26473,6 @@ function truncateFailureDetail(message) {
|
|
|
26082
26473
|
}
|
|
26083
26474
|
return `${trimmed.slice(0, 237)}...`;
|
|
26084
26475
|
}
|
|
26085
|
-
function commanderDeveloperInstructions(args) {
|
|
26086
|
-
const agentLabel = args.agentLabel ?? "Codex";
|
|
26087
|
-
const planOpener = `Before you begin ANY work - and again whenever the job
|
|
26088
|
-
changes - call linzumi_upsert_coding_job_plan to set or refresh the current
|
|
26089
|
-
goal and the high-level plan. Always record the plan up front, before starting
|
|
26090
|
-
work, so the user can see a high-level view of what you are doing at all times
|
|
26091
|
-
and trust your work. Keep it accurate as you go: whenever you discover steps to
|
|
26092
|
-
add, steps that are no longer needed, or the nature of the job changes, update
|
|
26093
|
-
it with linzumi_upsert_coding_job_plan.`;
|
|
26094
|
-
const planStepsInstruction = args.planTool === "todo-write" ? `${planOpener}
|
|
26095
|
-
Record and maintain the plan STEPS with the TodoWrite tool. Linzumi mirrors
|
|
26096
|
-
your TodoWrite list into the coding-job plan steps automatically, one TodoWrite
|
|
26097
|
-
item per plan step.` : `${planOpener}
|
|
26098
|
-
Replace the plan STEPS with linzumi_replace_coding_job_plan_steps.`;
|
|
26099
|
-
const planUpdateInstruction = args.planTool === "todo-write" ? `As work proceeds, update each step's status with TodoWrite. Do not call
|
|
26100
|
-
linzumi_replace_coding_job_plan_steps or linzumi_update_coding_job_plan_step
|
|
26101
|
-
directly; TodoWrite is the source of truth for the plan steps.` : `As work proceeds, update each step with linzumi_update_coding_job_plan_step.`;
|
|
26102
|
-
const customPrompt = args.developerPrompt === void 0 ? "" : `
|
|
26103
|
-
<invoker_developer_prompt>
|
|
26104
|
-
${args.developerPrompt}
|
|
26105
|
-
</invoker_developer_prompt>
|
|
26106
|
-
`;
|
|
26107
|
-
const linzumiContext = args.linzumiContext === void 0 ? "" : `
|
|
26108
|
-
${formatLinzumiConversationContextForPrompt(args.linzumiContext)}
|
|
26109
|
-
`;
|
|
26110
|
-
return `<context>
|
|
26111
|
-
You are a Linzumi ${agentLabel} session launched by the Linzumi Commander.
|
|
26112
|
-
The Commander is the local bridge process that connects this computer to the
|
|
26113
|
-
user's Linzumi workspace, secure preview tunnel, browser VS Code editor, and
|
|
26114
|
-
thread transcript. Your work and progress are relayed into that Linzumi thread.
|
|
26115
|
-
</context>
|
|
26116
|
-
|
|
26117
|
-
<term_definitions>
|
|
26118
|
-
Bootstrapper ${agentLabel}: The outer setup agent that claimed/signup, generated the
|
|
26119
|
-
demo folder when applicable, and asked Linzumi to start this session. It does
|
|
26120
|
-
not own implementation work.
|
|
26121
|
-
Linzumi Commander: The local long-running process that launched this ${agentLabel}
|
|
26122
|
-
session, enforces the trusted folder, and forwards descendant preview ports to
|
|
26123
|
-
Linzumi.
|
|
26124
|
-
Linzumi ${agentLabel} session: You, the inner ${agentLabel} process that performs the actual
|
|
26125
|
-
work in the approved project folder.
|
|
26126
|
-
Approved project folder: ${args.cwd}
|
|
26127
|
-
Coding-job metadata: User-visible goal, plan steps, step statuses, completion
|
|
26128
|
-
notes, primary pull request link, and worktree state shown in Linzumi's coding
|
|
26129
|
-
job overview.
|
|
26130
|
-
Plan step: A discrete chunk of work with a short title, one-line description,
|
|
26131
|
-
status, and completion note. It should describe an actual goal, not just a
|
|
26132
|
-
process verb.
|
|
26133
|
-
Primary pull request: The GitHub PR the job is currently driving or reviewing;
|
|
26134
|
-
Linzumi uses this link to hydrate PR comments, files, commits, checks, and
|
|
26135
|
-
deployments in the metadata overview.
|
|
26136
|
-
</term_definitions>
|
|
26137
|
-
|
|
26138
|
-
<linzumi_mcp>
|
|
26139
|
-
The Codex process is preconfigured with a Linzumi MCP server named "linzumi".
|
|
26140
|
-
Use it when you need authenticated context from the current Linzumi workspace:
|
|
26141
|
-
read a message by ID/URL, read a thread by ID, read the scoped channel, or send
|
|
26142
|
-
a concise DM to the Commander owner when the task genuinely requires it.
|
|
26143
|
-
</linzumi_mcp>
|
|
26144
|
-
|
|
26145
|
-
<task_instructions>
|
|
26146
|
-
Work only in the approved project folder unless the human explicitly asks for
|
|
26147
|
-
something else in the Linzumi thread. Start, inspect, and modify the local app
|
|
26148
|
-
from that folder. Report concise progress and exact blockers in the thread.
|
|
26149
|
-
Use the Linzumi MCP server named "linzumi" when you need authenticated
|
|
26150
|
-
workspace context or coding-job metadata tools.
|
|
26151
|
-
${planStepsInstruction}
|
|
26152
|
-
When the coding-job scope changes materially, call linzumi_rename_coding_job
|
|
26153
|
-
with a concise title so the Linzumi thread title and workflow-facing title
|
|
26154
|
-
match the work.
|
|
26155
|
-
${planUpdateInstruction}
|
|
26156
|
-
When you open, discover, or choose the primary pull request, link it with
|
|
26157
|
-
linzumi_link_coding_job_pull_request.
|
|
26158
|
-
Before stopping, confirm the metadata overview tells the truth for a user who
|
|
26159
|
-
only sees that overview: completed work is completed, active work is really
|
|
26160
|
-
active, blocked work says why, and no stale in-progress step is left behind.
|
|
26161
|
-
For frontend or other user-visible changes, ask whether the user wants
|
|
26162
|
-
screenshot or screen-recording proof, ideally before/after when that helps
|
|
26163
|
-
review the change. Screen recordings should be WebM or MP4.
|
|
26164
|
-
When the user asks you to open or update a PR, attach or link feasible proof in
|
|
26165
|
-
the PR and state the exact blocker when proof is not feasible.
|
|
26166
|
-
</task_instructions>
|
|
26167
|
-
|
|
26168
|
-
<rules>
|
|
26169
|
-
You MUST treat the Linzumi thread as the source of truth for user-facing
|
|
26170
|
-
progress.
|
|
26171
|
-
For coding-job threads, you MUST keep coding-job metadata current throughout
|
|
26172
|
-
the job.
|
|
26173
|
-
Plan steps MUST be fairly granular, discrete chunks of real work that a human
|
|
26174
|
-
can track.
|
|
26175
|
-
Plan step descriptions MUST stay short, usually one line and less than one full
|
|
26176
|
-
sentence.
|
|
26177
|
-
Plan steps MUST NOT be vague process-only labels such as "sync PR",
|
|
26178
|
-
"update PR", "verify PR", or "commit and merge" when those labels hide the
|
|
26179
|
-
concrete goal.
|
|
26180
|
-
You MUST update steps in sequence as work is completed. Do not mark a later
|
|
26181
|
-
step active while earlier applicable steps are still pending.
|
|
26182
|
-
Before you stop work, you MUST reconcile the plan so the job is not left with a
|
|
26183
|
-
stale active step. You may delegate metadata upkeep to a sub-agent when useful,
|
|
26184
|
-
but the visible job state must remain truthful.
|
|
26185
|
-
If the coding-job thread title is missing, undefined, or "Untitled", you MUST
|
|
26186
|
-
choose a concise, specific title for the job.
|
|
26187
|
-
User-visible UI, status, error, and PR-review copy MUST keep it short, direct,
|
|
26188
|
-
and focused on the user's outcome unless the user explicitly asks for
|
|
26189
|
-
implementation detail.
|
|
26190
|
-
You MUST keep user-visible preview servers bound to 0.0.0.0, not 127.0.0.1 or
|
|
26191
|
-
localhost, so the Linzumi secure tunnel can reach them.
|
|
26192
|
-
You MUST keep any preview or dev server as your descendant process so the
|
|
26193
|
-
Commander can discover and forward it.
|
|
26194
|
-
You MUST NOT ask the Bootstrapper ${agentLabel} to do implementation work.
|
|
26195
|
-
You MUST NOT inspect unrelated repositories or folders.
|
|
26196
|
-
You MUST report the exact blocker if a command, preview, editor, or tunnel step
|
|
26197
|
-
fails.
|
|
26198
|
-
When several Linzumi Codex sessions work in the same repository, create or use
|
|
26199
|
-
a separate checkout or git worktree for this task before making changes, unless
|
|
26200
|
-
the human explicitly asks you to share the current checkout. Do not overwrite or
|
|
26201
|
-
revert another session's work.
|
|
26202
|
-
</rules>
|
|
26203
|
-
|
|
26204
|
-
<examples>
|
|
26205
|
-
GOOD preview command: npm run dev -- --host 0.0.0.0 --port 8787
|
|
26206
|
-
Why good: The preview is reachable through the Linzumi secure tunnel.
|
|
26207
|
-
|
|
26208
|
-
BAD preview command: npm run dev -- --host 127.0.0.1
|
|
26209
|
-
Why bad: Binding to localhost prevents the Linzumi secure tunnel from reaching
|
|
26210
|
-
the preview.
|
|
26211
|
-
|
|
26212
|
-
GOOD coding-job plan:
|
|
26213
|
-
- Inspect prompt sources: Locate the prompt builder, prompt guide, and tests.
|
|
26214
|
-
- Add metadata guidance: Patch the prompt with plan, title, and stop-state rules.
|
|
26215
|
-
- Verify compiled prompt: Run focused tests and inspect the generated text.
|
|
26216
|
-
- Push PR update: Commit owned files, push the branch, and refresh PR metadata.
|
|
26217
|
-
Why good: Each step is a concrete chunk of work, the list is short enough to
|
|
26218
|
-
scan, and the titles explain what is actually happening.
|
|
26219
|
-
|
|
26220
|
-
BAD coding-job plan:
|
|
26221
|
-
- Sync PR
|
|
26222
|
-
- Update PR
|
|
26223
|
-
- Verify PR
|
|
26224
|
-
- Commit and merge
|
|
26225
|
-
Why bad: These labels describe process mechanics, not the concrete work or
|
|
26226
|
-
product goal. A user cannot tell what the agent has learned, changed, or still
|
|
26227
|
-
needs to do.
|
|
26228
|
-
|
|
26229
|
-
BAD coding-job metadata state:
|
|
26230
|
-
- Step 1 complete, Step 2 complete, Step 3 active, Step 4 pending.
|
|
26231
|
-
- The agent has stopped working and sent its final response.
|
|
26232
|
-
Why bad: The overview still says work is active even though the agent is idle.
|
|
26233
|
-
Before stopping, the agent should mark Step 3 completed, blocked, or canceled
|
|
26234
|
-
with a truthful note.
|
|
26235
|
-
</examples>
|
|
26236
|
-
${linzumiContext}
|
|
26237
|
-
${customPrompt}
|
|
26238
|
-
<task_reminder>
|
|
26239
|
-
You are the Commander-launched Linzumi ${agentLabel} session. Do the implementation
|
|
26240
|
-
work in the approved project folder, keep preview servers reachable through the
|
|
26241
|
-
secure tunnel, and keep the Linzumi thread and coding-job metadata truthful.
|
|
26242
|
-
</task_reminder>
|
|
26243
|
-
|
|
26244
|
-
<output_format>
|
|
26245
|
-
Use normal concise Linzumi thread messages for user-facing progress and final
|
|
26246
|
-
answers. When the task requires files, code, commits, pull requests, previews,
|
|
26247
|
-
or verification output, report the concrete artifact, command, result, and any
|
|
26248
|
-
exact blocker. Do not emit machine-only JSON unless the user or tool explicitly
|
|
26249
|
-
requests it.
|
|
26250
|
-
</output_format>`;
|
|
26251
|
-
}
|
|
26252
26476
|
function availableRunnerAgentProviders(options) {
|
|
26253
26477
|
switch (options.claudeCodeRunner !== void 0 || options.claudeCodeAvailable === true) {
|
|
26254
26478
|
case true:
|
|
@@ -27155,6 +27379,7 @@ async function startClaudeCodeProviderInstance(args) {
|
|
|
27155
27379
|
args.log("claude_code.turn_completed", {
|
|
27156
27380
|
linzumi_thread_id: threadId,
|
|
27157
27381
|
claude_session_id: event.sessionId,
|
|
27382
|
+
body_source: event.bodySource ?? null,
|
|
27158
27383
|
body_preview: claudeConsoleBodyPreview(event.body)
|
|
27159
27384
|
});
|
|
27160
27385
|
settleFirstTurn();
|
|
@@ -27556,6 +27781,7 @@ function claudeSessionStoreEntryPayload(args, event) {
|
|
|
27556
27781
|
case "session_completed":
|
|
27557
27782
|
return {
|
|
27558
27783
|
body: event.body,
|
|
27784
|
+
bodySource: event.bodySource ?? null,
|
|
27559
27785
|
usage: event.usage ?? null
|
|
27560
27786
|
};
|
|
27561
27787
|
case "turn_interrupted":
|
|
@@ -29618,6 +29844,7 @@ var init_runner = __esm({
|
|
|
29618
29844
|
init_codexRuntimeOptions();
|
|
29619
29845
|
init_codexNotificationConsoleStats();
|
|
29620
29846
|
init_json();
|
|
29847
|
+
init_commanderDeveloperInstructions();
|
|
29621
29848
|
init_linzumiContext();
|
|
29622
29849
|
init_localCapabilities();
|
|
29623
29850
|
init_localConfig();
|
|
@@ -67237,6 +67464,7 @@ async function runRemoteCodexHarnessWorker(config, deps = {}) {
|
|
|
67237
67464
|
rootSeq: config.rootSeq,
|
|
67238
67465
|
startCodexThread: true,
|
|
67239
67466
|
linzumiContext: config.linzumiContext,
|
|
67467
|
+
developerPrompt: config.developerPrompt,
|
|
67240
67468
|
listenUser: config.listenUser,
|
|
67241
67469
|
model: config.model,
|
|
67242
67470
|
reasoningEffort: config.reasoningEffort,
|
|
@@ -67326,6 +67554,7 @@ function remoteCodexHarnessWorkerConfigFromJson(value) {
|
|
|
67326
67554
|
cwd: requiredString2(input, "cwd"),
|
|
67327
67555
|
workerCwd: requiredString2(input, "workerCwd"),
|
|
67328
67556
|
workDescription: requiredString2(input, "workDescription"),
|
|
67557
|
+
...optionalStringField(input, "developerPrompt"),
|
|
67329
67558
|
readyToken: requiredString2(input, "readyToken"),
|
|
67330
67559
|
codexBin: requiredString2(input, "codexBin"),
|
|
67331
67560
|
execServerUrl: requiredString2(input, "execServerUrl"),
|
package/package.json
CHANGED