@linzumi/cli 0.0.88-beta → 0.0.89-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 +371 -265
- 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";
|
|
@@ -6552,53 +6774,6 @@ var init_kandanQueue = __esm({
|
|
|
6552
6774
|
}
|
|
6553
6775
|
});
|
|
6554
6776
|
|
|
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
6777
|
// src/reconnectContext.ts
|
|
6603
6778
|
function parseReconnectContextMessages(value) {
|
|
6604
6779
|
if (!Array.isArray(value)) {
|
|
@@ -11336,10 +11511,27 @@ async function startCodexThread(codex, options) {
|
|
|
11336
11511
|
cwd: options.cwd,
|
|
11337
11512
|
serviceName: "kandan-local-runner",
|
|
11338
11513
|
personality: "pragmatic",
|
|
11514
|
+
...developerInstructionsForThreadStart(options),
|
|
11339
11515
|
...codexThreadRuntimeOverrides(options)
|
|
11340
11516
|
});
|
|
11341
11517
|
return extractThreadIdFromResponse(start);
|
|
11342
11518
|
}
|
|
11519
|
+
function developerInstructionsForThreadStart(options) {
|
|
11520
|
+
const developerPrompt = options.channelSession.developerPrompt;
|
|
11521
|
+
if (developerPrompt === void 0) {
|
|
11522
|
+
return {};
|
|
11523
|
+
}
|
|
11524
|
+
return {
|
|
11525
|
+
developerInstructions: commanderDeveloperInstructions({
|
|
11526
|
+
cwd: options.cwd,
|
|
11527
|
+
planTool: "linzumi-mcp",
|
|
11528
|
+
developerPrompt,
|
|
11529
|
+
linzumiContext: parseLinzumiConversationContext(
|
|
11530
|
+
options.channelSession.linzumiContext
|
|
11531
|
+
)
|
|
11532
|
+
})
|
|
11533
|
+
};
|
|
11534
|
+
}
|
|
11343
11535
|
async function pushOk2(kandan, topic, event, payload) {
|
|
11344
11536
|
const reply = await kandan.push(topic, event, payload);
|
|
11345
11537
|
if (isJsonObject(reply) && reply.status === "ok" && isJsonObject(reply.response)) {
|
|
@@ -11366,6 +11558,7 @@ var init_channelSession = __esm({
|
|
|
11366
11558
|
init_channelSessionSupport();
|
|
11367
11559
|
init_commanderAttachments();
|
|
11368
11560
|
init_codexRuntimeOptions();
|
|
11561
|
+
init_commanderDeveloperInstructions();
|
|
11369
11562
|
init_codexOutput();
|
|
11370
11563
|
init_codexSessionLog();
|
|
11371
11564
|
init_integration();
|
|
@@ -14961,11 +15154,34 @@ var init_defaultUrls = __esm({
|
|
|
14961
15154
|
import { spawn as spawn3 } from "node:child_process";
|
|
14962
15155
|
import { randomBytes } from "node:crypto";
|
|
14963
15156
|
import { createServer as createServer2 } from "node:http";
|
|
15157
|
+
function oauthCallbackTimeoutMs(override, env = process.env) {
|
|
15158
|
+
if (typeof override === "number" && Number.isFinite(override) && override > 0) {
|
|
15159
|
+
return override;
|
|
15160
|
+
}
|
|
15161
|
+
const raw = env.LINZUMI_OAUTH_CALLBACK_TIMEOUT_MS?.trim();
|
|
15162
|
+
if (raw !== void 0 && raw !== "") {
|
|
15163
|
+
const parsed = Number.parseInt(raw, 10);
|
|
15164
|
+
if (Number.isFinite(parsed) && parsed > 0) {
|
|
15165
|
+
return parsed;
|
|
15166
|
+
}
|
|
15167
|
+
}
|
|
15168
|
+
return DEFAULT_OAUTH_CALLBACK_TIMEOUT_MS;
|
|
15169
|
+
}
|
|
14964
15170
|
async function acquireLocalRunnerTokenDetails(options) {
|
|
14965
15171
|
const httpBaseUrl = kandanHttpBaseUrl(options.kandanUrl);
|
|
14966
15172
|
const state = randomBytes(18).toString("base64url");
|
|
14967
15173
|
const callback = await startCallbackServer({
|
|
14968
|
-
host: oauthCallbackHost(options.kandanUrl, options.callbackHost)
|
|
15174
|
+
host: oauthCallbackHost(options.kandanUrl, options.callbackHost),
|
|
15175
|
+
exchange: async (result) => {
|
|
15176
|
+
if (result.state !== state) {
|
|
15177
|
+
throw new Error("local runner OAuth state mismatch");
|
|
15178
|
+
}
|
|
15179
|
+
return await exchangeCodeForToken({
|
|
15180
|
+
httpBaseUrl,
|
|
15181
|
+
code: result.code,
|
|
15182
|
+
redirectUri: result.redirectUri
|
|
15183
|
+
});
|
|
15184
|
+
}
|
|
14969
15185
|
});
|
|
14970
15186
|
const authorizeUrl = authorizationUrl({
|
|
14971
15187
|
httpBaseUrl,
|
|
@@ -14981,15 +15197,9 @@ ${authorizeUrl}
|
|
|
14981
15197
|
`);
|
|
14982
15198
|
try {
|
|
14983
15199
|
await (options.openAuthorizationUrl ?? openBrowser)(authorizeUrl);
|
|
14984
|
-
|
|
14985
|
-
|
|
14986
|
-
|
|
14987
|
-
}
|
|
14988
|
-
return await exchangeCodeForToken({
|
|
14989
|
-
httpBaseUrl,
|
|
14990
|
-
code: result.code,
|
|
14991
|
-
redirectUri: callback.redirectUri
|
|
14992
|
-
});
|
|
15200
|
+
return await callback.waitForToken(
|
|
15201
|
+
oauthCallbackTimeoutMs(options.waitForTokenTimeoutMs)
|
|
15202
|
+
);
|
|
14993
15203
|
} finally {
|
|
14994
15204
|
callback.close();
|
|
14995
15205
|
}
|
|
@@ -15169,49 +15379,83 @@ function stringBodyField(body, key) {
|
|
|
15169
15379
|
}
|
|
15170
15380
|
function startCallbackServer(args) {
|
|
15171
15381
|
return new Promise((resolve12, reject) => {
|
|
15172
|
-
let
|
|
15173
|
-
let
|
|
15174
|
-
|
|
15175
|
-
|
|
15176
|
-
|
|
15382
|
+
let resolveToken;
|
|
15383
|
+
let rejectToken;
|
|
15384
|
+
let settled = false;
|
|
15385
|
+
const tokenPromise = new Promise(
|
|
15386
|
+
(tokenResolve, tokenReject) => {
|
|
15387
|
+
resolveToken = tokenResolve;
|
|
15388
|
+
rejectToken = tokenReject;
|
|
15389
|
+
}
|
|
15390
|
+
);
|
|
15391
|
+
tokenPromise.catch(() => {
|
|
15177
15392
|
});
|
|
15393
|
+
const settle = (apply) => {
|
|
15394
|
+
if (settled) {
|
|
15395
|
+
return false;
|
|
15396
|
+
}
|
|
15397
|
+
settled = true;
|
|
15398
|
+
apply();
|
|
15399
|
+
return true;
|
|
15400
|
+
};
|
|
15401
|
+
let boundRedirectUri = `http://${args.host}/callback`;
|
|
15178
15402
|
const server = createServer2((request, response) => {
|
|
15179
|
-
|
|
15180
|
-
|
|
15181
|
-
|
|
15182
|
-
|
|
15183
|
-
|
|
15184
|
-
|
|
15185
|
-
|
|
15403
|
+
void (async () => {
|
|
15404
|
+
try {
|
|
15405
|
+
const url = new URL(request.url ?? "/", `http://${args.host}`);
|
|
15406
|
+
const code = url.searchParams.get("code");
|
|
15407
|
+
const state = url.searchParams.get("state");
|
|
15408
|
+
const error = url.searchParams.get("error");
|
|
15409
|
+
if (error !== null && error.trim() !== "") {
|
|
15410
|
+
settle(
|
|
15411
|
+
() => rejectToken?.(new Error(`local runner OAuth failed: ${error}`))
|
|
15412
|
+
);
|
|
15413
|
+
writeOauthResult(response, {
|
|
15414
|
+
title: "Not authorized",
|
|
15415
|
+
body: "You denied the request. Close this tab and rerun the bootstrap command when you're ready.",
|
|
15416
|
+
status: 403
|
|
15417
|
+
});
|
|
15418
|
+
return;
|
|
15419
|
+
}
|
|
15420
|
+
if (code === null || state === null || code.trim() === "" || state.trim() === "") {
|
|
15421
|
+
writeOauthResult(response, {
|
|
15422
|
+
title: "Authorization callback was incomplete",
|
|
15423
|
+
body: "We didn't receive the authorization code. Return to your terminal and try again.",
|
|
15424
|
+
status: 400
|
|
15425
|
+
});
|
|
15426
|
+
return;
|
|
15427
|
+
}
|
|
15428
|
+
let token;
|
|
15429
|
+
try {
|
|
15430
|
+
token = await args.exchange({
|
|
15431
|
+
code,
|
|
15432
|
+
state,
|
|
15433
|
+
redirectUri: boundRedirectUri
|
|
15434
|
+
});
|
|
15435
|
+
} catch (exchangeError) {
|
|
15436
|
+
settle(() => rejectToken?.(exchangeError));
|
|
15437
|
+
writeOauthResult(response, {
|
|
15438
|
+
title: "Authorization could not be completed",
|
|
15439
|
+
body: "We received the authorization but could not finish setup. Return to your terminal for details and rerun the bootstrap command.",
|
|
15440
|
+
status: 400
|
|
15441
|
+
});
|
|
15442
|
+
return;
|
|
15443
|
+
}
|
|
15444
|
+
const accepted = settle(() => resolveToken?.(token));
|
|
15186
15445
|
writeOauthResult(response, {
|
|
15187
|
-
title: "
|
|
15188
|
-
body: "
|
|
15189
|
-
status:
|
|
15446
|
+
title: accepted ? "Computer authorized" : "Already authorized",
|
|
15447
|
+
body: "This computer has been authorized for agentic use in Linzumi. Feel free to close this tab and let the terminal finish setup.",
|
|
15448
|
+
status: 200
|
|
15190
15449
|
});
|
|
15191
|
-
|
|
15192
|
-
|
|
15193
|
-
if (code === null || state === null || code.trim() === "" || state.trim() === "") {
|
|
15450
|
+
} catch (handlerError) {
|
|
15451
|
+
settle(() => rejectToken?.(handlerError));
|
|
15194
15452
|
writeOauthResult(response, {
|
|
15195
|
-
title: "Authorization callback
|
|
15196
|
-
body: "
|
|
15197
|
-
status:
|
|
15453
|
+
title: "Authorization callback failed",
|
|
15454
|
+
body: "Return to your terminal and rerun the bootstrap command.",
|
|
15455
|
+
status: 500
|
|
15198
15456
|
});
|
|
15199
|
-
return;
|
|
15200
15457
|
}
|
|
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
|
-
}
|
|
15458
|
+
})();
|
|
15215
15459
|
});
|
|
15216
15460
|
server.once("error", reject);
|
|
15217
15461
|
server.listen(0, args.host, () => {
|
|
@@ -15224,9 +15468,34 @@ function startCallbackServer(args) {
|
|
|
15224
15468
|
);
|
|
15225
15469
|
return;
|
|
15226
15470
|
}
|
|
15471
|
+
boundRedirectUri = `http://${args.host}:${address.port}/callback`;
|
|
15227
15472
|
resolve12({
|
|
15228
|
-
redirectUri:
|
|
15229
|
-
|
|
15473
|
+
redirectUri: boundRedirectUri,
|
|
15474
|
+
// Bound the wait so that "only spurious/incomplete requests, no real
|
|
15475
|
+
// callback" can't hang forever. Incomplete requests deliberately never
|
|
15476
|
+
// settle the token promise (they only render the incomplete page), so
|
|
15477
|
+
// the overall timeout is what guarantees forward progress. The timer is
|
|
15478
|
+
// unref'd so it can't keep the process alive on its own, and it's
|
|
15479
|
+
// cleared once the token promise settles for any reason.
|
|
15480
|
+
waitForToken: (timeoutMs) => {
|
|
15481
|
+
const effectiveTimeoutMs = oauthCallbackTimeoutMs(timeoutMs);
|
|
15482
|
+
const timer = setTimeout(() => {
|
|
15483
|
+
settle(
|
|
15484
|
+
() => rejectToken?.(
|
|
15485
|
+
new Error(
|
|
15486
|
+
"Authorization timed out before the browser callback completed. Rerun the connect command and finish authorizing in the browser."
|
|
15487
|
+
)
|
|
15488
|
+
)
|
|
15489
|
+
);
|
|
15490
|
+
server.close();
|
|
15491
|
+
}, effectiveTimeoutMs);
|
|
15492
|
+
timer.unref?.();
|
|
15493
|
+
tokenPromise.finally(() => {
|
|
15494
|
+
clearTimeout(timer);
|
|
15495
|
+
}).catch(() => {
|
|
15496
|
+
});
|
|
15497
|
+
return tokenPromise;
|
|
15498
|
+
},
|
|
15230
15499
|
close: () => {
|
|
15231
15500
|
server.close();
|
|
15232
15501
|
}
|
|
@@ -15291,7 +15560,7 @@ function oauthResultHtml(args) {
|
|
|
15291
15560
|
place-items: center;
|
|
15292
15561
|
padding: 24px;
|
|
15293
15562
|
background:
|
|
15294
|
-
radial-gradient(1200px 600px at 50% -10%, var(--notice-soft), transparent 60%),
|
|
15563
|
+
radial-gradient(1200px 600px at 50% -10%, var(${success ? "--success-soft" : "--notice-soft"}), transparent 60%),
|
|
15295
15564
|
var(--page-bg);
|
|
15296
15565
|
color: var(--foreground);
|
|
15297
15566
|
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
@@ -15376,11 +15645,12 @@ function openBrowser(url) {
|
|
|
15376
15645
|
});
|
|
15377
15646
|
});
|
|
15378
15647
|
}
|
|
15379
|
-
var LINZUMI_LOGO_SVG;
|
|
15648
|
+
var DEFAULT_OAUTH_CALLBACK_TIMEOUT_MS, LINZUMI_LOGO_SVG;
|
|
15380
15649
|
var init_oauth = __esm({
|
|
15381
15650
|
"src/oauth.ts"() {
|
|
15382
15651
|
"use strict";
|
|
15383
15652
|
init_runnerLogger();
|
|
15653
|
+
DEFAULT_OAUTH_CALLBACK_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
15384
15654
|
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
15655
|
}
|
|
15386
15656
|
});
|
|
@@ -18719,7 +18989,7 @@ var linzumiCliVersion, linzumiCliVersionText;
|
|
|
18719
18989
|
var init_version = __esm({
|
|
18720
18990
|
"src/version.ts"() {
|
|
18721
18991
|
"use strict";
|
|
18722
|
-
linzumiCliVersion = "0.0.
|
|
18992
|
+
linzumiCliVersion = "0.0.89-beta";
|
|
18723
18993
|
linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
|
|
18724
18994
|
}
|
|
18725
18995
|
});
|
|
@@ -26082,173 +26352,6 @@ function truncateFailureDetail(message) {
|
|
|
26082
26352
|
}
|
|
26083
26353
|
return `${trimmed.slice(0, 237)}...`;
|
|
26084
26354
|
}
|
|
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
26355
|
function availableRunnerAgentProviders(options) {
|
|
26253
26356
|
switch (options.claudeCodeRunner !== void 0 || options.claudeCodeAvailable === true) {
|
|
26254
26357
|
case true:
|
|
@@ -29618,6 +29721,7 @@ var init_runner = __esm({
|
|
|
29618
29721
|
init_codexRuntimeOptions();
|
|
29619
29722
|
init_codexNotificationConsoleStats();
|
|
29620
29723
|
init_json();
|
|
29724
|
+
init_commanderDeveloperInstructions();
|
|
29621
29725
|
init_linzumiContext();
|
|
29622
29726
|
init_localCapabilities();
|
|
29623
29727
|
init_localConfig();
|
|
@@ -67237,6 +67341,7 @@ async function runRemoteCodexHarnessWorker(config, deps = {}) {
|
|
|
67237
67341
|
rootSeq: config.rootSeq,
|
|
67238
67342
|
startCodexThread: true,
|
|
67239
67343
|
linzumiContext: config.linzumiContext,
|
|
67344
|
+
developerPrompt: config.developerPrompt,
|
|
67240
67345
|
listenUser: config.listenUser,
|
|
67241
67346
|
model: config.model,
|
|
67242
67347
|
reasoningEffort: config.reasoningEffort,
|
|
@@ -67326,6 +67431,7 @@ function remoteCodexHarnessWorkerConfigFromJson(value) {
|
|
|
67326
67431
|
cwd: requiredString2(input, "cwd"),
|
|
67327
67432
|
workerCwd: requiredString2(input, "workerCwd"),
|
|
67328
67433
|
workDescription: requiredString2(input, "workDescription"),
|
|
67434
|
+
...optionalStringField(input, "developerPrompt"),
|
|
67329
67435
|
readyToken: requiredString2(input, "readyToken"),
|
|
67330
67436
|
codexBin: requiredString2(input, "codexBin"),
|
|
67331
67437
|
execServerUrl: requiredString2(input, "execServerUrl"),
|
package/package.json
CHANGED