@linzumi/cli 0.0.75-beta → 0.0.77-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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +205 -27
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -58,7 +58,7 @@ Install the CLI or run it with `npx`:
58
58
  ```bash
59
59
  npm install -g @linzumi/cli@latest
60
60
  npx -y @linzumi/cli@latest signup
61
- npx -y @linzumi/cli@0.0.75-beta --version
61
+ npx -y @linzumi/cli@0.0.77-beta --version
62
62
  linzumi --version
63
63
  ```
64
64
 
package/dist/index.js CHANGED
@@ -376,12 +376,7 @@ function appendDownloadedAttachmentContext(input, attachments, options = {}) {
376
376
  "Do not mention that you are using the upload tool. Do not print an upload manifest or upload footer in the message.",
377
377
  "The MCP upload tool is the only supported path for attaching generated files to Linzumi messages."
378
378
  ];
379
- return [
380
- input,
381
- ...attachmentContext,
382
- "",
383
- ...uploadInstructions
384
- ].join("\n");
379
+ return [input, ...attachmentContext, "", ...uploadInstructions].join("\n");
385
380
  }
386
381
  function codexImageInputItemsForDownloadedAttachments(attachments) {
387
382
  return attachments.flatMap(
@@ -659,7 +654,11 @@ async function commanderAttachmentUploadRoots(cwdRealPath) {
659
654
  const roots = [
660
655
  { path: cwdRealPath, label: "runner cwd" }
661
656
  ];
662
- const downloadsPath = resolve(homedir(), "Downloads");
657
+ const configuredHome = process.env.HOME?.trim();
658
+ const downloadsPath = resolve(
659
+ configuredHome === void 0 || configuredHome === "" ? homedir() : configuredHome,
660
+ "Downloads"
661
+ );
663
662
  try {
664
663
  const downloadsRealPath = await realpath(downloadsPath);
665
664
  if (!roots.some((root) => root.path === downloadsRealPath)) {
@@ -9603,7 +9602,7 @@ function defaultCliAuditLogFile() {
9603
9602
  return override === void 0 || override === "" ? join4(homedir4(), ".linzumi", "logs", "command-events.jsonl") : override;
9604
9603
  }
9605
9604
  function defaultRunnerLogFile() {
9606
- return join4(homedir4(), ".linzumi", "logs", "runner-events.jsonl");
9605
+ return join4(homedir4(), ".linzumi", "logs", "linzumi-runner.log");
9607
9606
  }
9608
9607
  function redactForCliLog(value) {
9609
9608
  return redactObject(value);
@@ -14633,7 +14632,7 @@ var linzumiCliVersion, linzumiCliVersionText;
14633
14632
  var init_version = __esm({
14634
14633
  "src/version.ts"() {
14635
14634
  "use strict";
14636
- linzumiCliVersion = "0.0.75-beta";
14635
+ linzumiCliVersion = "0.0.77-beta";
14637
14636
  linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
14638
14637
  }
14639
14638
  });
@@ -15937,8 +15936,7 @@ import { existsSync as existsSync8, mkdirSync as mkdirSync8, readFileSync as rea
15937
15936
  import { homedir as homedir9 } from "node:os";
15938
15937
  import { dirname as dirname8, join as join12 } from "node:path";
15939
15938
  function defaultAuthFilePath() {
15940
- const base = process.env.KANDAN_HOME ?? join12(homedir9(), ".kandan");
15941
- return join12(base, "auth.json");
15939
+ return join12(homedir9(), ".linzumi", "auth.json");
15942
15940
  }
15943
15941
  function readCachedLocalRunnerToken(kandanUrl, authFilePath = defaultAuthFilePath()) {
15944
15942
  if (!existsSync8(authFilePath)) {
@@ -16628,7 +16626,7 @@ var init_signupTaskSuggestions = __esm({
16628
16626
 
16629
16627
  // src/remoteCodexSandboxRunner.ts
16630
16628
  import { spawn as spawn7 } from "node:child_process";
16631
- import { existsSync as existsSync9 } from "node:fs";
16629
+ import { existsSync as existsSync9, realpathSync as realpathSync5 } from "node:fs";
16632
16630
  import { dirname as dirname9, isAbsolute as isAbsolute3 } from "node:path";
16633
16631
  function createConfiguredRemoteCodexSandboxRunner(args) {
16634
16632
  const kind = normalizedSandboxKind(args.env.LINZUMI_REMOTE_CODEX_SANDBOX);
@@ -16785,6 +16783,10 @@ function macosSeatbeltProfile(request, exists) {
16785
16783
  `(allow file-read* (subpath ${sandboxString(path2)}))`,
16786
16784
  `(allow file-write* (subpath ${sandboxString(path2)}))`
16787
16785
  ]).join("\n");
16786
+ const cwdRules = existingPathAliases(request.cwd).flatMap((path2) => [
16787
+ `(allow file-read* (subpath ${sandboxString(path2)}))`,
16788
+ `(allow file-write* (subpath ${sandboxString(path2)}))`
16789
+ ]).join("\n");
16788
16790
  return [
16789
16791
  "(version 1)",
16790
16792
  "(deny default)",
@@ -16792,13 +16794,13 @@ function macosSeatbeltProfile(request, exists) {
16792
16794
  "(allow signal (target self))",
16793
16795
  "(allow sysctl-read)",
16794
16796
  "(allow file-read-metadata)",
16797
+ '(allow file-read-data (literal "/"))',
16795
16798
  '(allow file-read* (literal "/dev/null"))',
16796
16799
  '(allow file-read* (literal "/dev/random"))',
16797
16800
  '(allow file-read* (literal "/dev/urandom"))',
16798
16801
  readableRules,
16799
16802
  writableTempRules,
16800
- `(allow file-read* (subpath ${sandboxString(request.cwd)}))`,
16801
- `(allow file-write* (subpath ${sandboxString(request.cwd)}))`
16803
+ cwdRules
16802
16804
  ].join("\n");
16803
16805
  }
16804
16806
  function createBoundedOutputBuffer() {
@@ -16859,6 +16861,9 @@ function parentDirs(path2) {
16859
16861
  function uniqueStrings2(values) {
16860
16862
  return Array.from(new Set(values));
16861
16863
  }
16864
+ function existingPathAliases(path2) {
16865
+ return uniqueStrings2([path2, realpathSync5(path2)]);
16866
+ }
16862
16867
  function sandboxString(value) {
16863
16868
  return JSON.stringify(value);
16864
16869
  }
@@ -16880,6 +16885,8 @@ var init_remoteCodexSandboxRunner = __esm({
16880
16885
  macosReadOnlyRoots = [
16881
16886
  "/System",
16882
16887
  "/Library",
16888
+ "/etc",
16889
+ "/private/etc",
16883
16890
  "/usr",
16884
16891
  "/bin",
16885
16892
  "/sbin",
@@ -16899,7 +16906,7 @@ import {
16899
16906
  mkdirSync as mkdirSync9,
16900
16907
  mkdtempSync as mkdtempSync4,
16901
16908
  readdirSync as readdirSync2,
16902
- realpathSync as realpathSync5,
16909
+ realpathSync as realpathSync6,
16903
16910
  rmSync as rmSync4,
16904
16911
  statSync
16905
16912
  } from "node:fs";
@@ -19733,6 +19740,15 @@ read a message by ID/URL, read a thread by ID, read the scoped channel, or send
19733
19740
  a concise DM to the Commander owner when the task genuinely requires it.
19734
19741
  </linzumi_mcp>
19735
19742
 
19743
+ <coding_job_metadata>
19744
+ When you are working inside a coding-job thread, keep the job metadata current through the Linzumi MCP tools.
19745
+ At the beginning of a job, call linzumi_upsert_coding_job_plan with your current understanding of the goal, then call linzumi_replace_coding_job_plan_steps with an ordered list of steps to accomplish that goal.
19746
+ The plan is allowed to change. Rework it when the old plan is no longer a useful description of the work, but do not churn it for minor tactical adjustments.
19747
+ As you make progress, call linzumi_update_coding_job_plan_step to mark the active step and completed steps. Read the metadata first when you need current step ids or lock versions.
19748
+ When you open, discover, or choose the primary GitHub pull request for the job, call linzumi_link_coding_job_pull_request with the PR URL, repo owner/name, PR number, title, head/base branches, head/base SHAs, local worktree path, remote URL, and current dirty status. This link is what lets GitHub PR comments, files, commits, checks, deployments, and reviews appear automatically in the metadata overview.
19749
+ The plan and goal are user-visible, so keep titles short, descriptions concrete, and completion notes focused on what was verified.
19750
+ </coding_job_metadata>
19751
+
19736
19752
  <task_instructions>
19737
19753
  Work only in the approved project folder unless the human explicitly asks for
19738
19754
  something else in the Linzumi thread. Start, inspect, and modify the local app
@@ -21700,7 +21716,7 @@ function configuredAllowedCwds(values, options = {}) {
21700
21716
  if (options.createMissing === true) {
21701
21717
  mkdirSync9(absolutePath, { recursive: true });
21702
21718
  }
21703
- const realPath = realpathSync5(absolutePath);
21719
+ const realPath = realpathSync6(absolutePath);
21704
21720
  allowedCwds.push(
21705
21721
  ...realPath === absolutePath ? [realPath] : [realPath, absolutePath]
21706
21722
  );
@@ -21747,7 +21763,7 @@ function browseRunnerDirectory(control, options) {
21747
21763
  const requestId = stringValue(control.requestId) ?? null;
21748
21764
  const requestedPath = stringValue(control.path) ?? currentHomeDirectory();
21749
21765
  try {
21750
- const currentPath = realpathSync5(resolve7(expandUserPath(requestedPath)));
21766
+ const currentPath = realpathSync6(resolve7(expandUserPath(requestedPath)));
21751
21767
  const stats = statSync(currentPath);
21752
21768
  if (!stats.isDirectory()) {
21753
21769
  return {
@@ -21870,7 +21886,7 @@ function createRunnerProject(control, options, allowedCwds) {
21870
21886
  error: cleanupError === void 0 ? `git_init_failed:${gitFailure}` : `git_init_cleanup_failed:${cleanupError}`
21871
21887
  };
21872
21888
  }
21873
- const projectRealPath = realpathSync5(projectPath);
21889
+ const projectRealPath = realpathSync6(projectPath);
21874
21890
  const persistedAllowedCwds = addAllowedCwdForLinzumiUrl(
21875
21891
  projectRealPath,
21876
21892
  options.kandanUrl
@@ -42325,6 +42341,7 @@ function signupHelpText() {
42325
42341
  "",
42326
42342
  "Options:",
42327
42343
  " --api-url <url> Linzumi HTTP origin, default https://serve.linzumi.com",
42344
+ " --code-server-bin <path> Custom development code-server executable",
42328
42345
  " --force-signup Ignore existing local signup auth and create a fresh login",
42329
42346
  " --no-open Print the launch URL without opening the browser",
42330
42347
  " --debug-signup Print the collected launch payload JSON after signup",
@@ -42343,6 +42360,7 @@ function signupPromptCancelMessage(error) {
42343
42360
  function parseSignupTuiOptions(args) {
42344
42361
  let serviceUrl = defaultLinzumiHttpUrl;
42345
42362
  let forceSignup = false;
42363
+ let codeServerBin;
42346
42364
  let openBrowser2 = true;
42347
42365
  let debugLaunchPayload = false;
42348
42366
  for (let index = 0; index < args.length; index += 1) {
@@ -42368,11 +42386,26 @@ function parseSignupTuiOptions(args) {
42368
42386
  index += 1;
42369
42387
  break;
42370
42388
  }
42389
+ case "--code-server-bin": {
42390
+ const value = args[index + 1];
42391
+ if (value === void 0 || value.startsWith("--")) {
42392
+ throw new Error("missing value for --code-server-bin");
42393
+ }
42394
+ codeServerBin = value;
42395
+ index += 1;
42396
+ break;
42397
+ }
42371
42398
  default:
42372
42399
  throw new Error(`invalid signup flag: ${arg ?? ""}`);
42373
42400
  }
42374
42401
  }
42375
- return { serviceUrl, forceSignup, openBrowser: openBrowser2, debugLaunchPayload };
42402
+ return {
42403
+ serviceUrl,
42404
+ forceSignup,
42405
+ ...codeServerBin === void 0 ? {} : { codeServerBin },
42406
+ openBrowser: openBrowser2,
42407
+ debugLaunchPayload
42408
+ };
42376
42409
  }
42377
42410
  function signupAuthMatchesServiceUrl(auth, serviceUrl) {
42378
42411
  return comparableServiceUrl(auth.serviceUrl) === comparableServiceUrl(serviceUrl);
@@ -42628,6 +42661,7 @@ async function runSignupFlow(deps = {}) {
42628
42661
  const preflight = deps.preflight ?? defaultPreflightRuntime();
42629
42662
  const forceSignup = deps.forceSignup === true;
42630
42663
  const serviceUrl = deps.serviceUrl ?? defaultLinzumiHttpUrl;
42664
+ const codeServerBin = deps.codeServerBin;
42631
42665
  const openBrowser2 = deps.openBrowser !== false;
42632
42666
  const debugLaunchPayload = deps.debugLaunchPayload === true;
42633
42667
  const openUrl = deps.openUrl ?? openUrlInBrowser;
@@ -42916,7 +42950,8 @@ async function runSignupFlow(deps = {}) {
42916
42950
  workspaceSlug: missionControl.workspace.slug,
42917
42951
  projectPath: starterProjectPath,
42918
42952
  selectedProjectPaths: missionControl.config.allowedCwds,
42919
- codexBin: verifiedCodexBin
42953
+ codexBin: verifiedCodexBin,
42954
+ ...codeServerBin === void 0 ? {} : { codeServerBin }
42920
42955
  });
42921
42956
  const starterTaskLaunches = await startSignupTasksForCommander(
42922
42957
  signupServerClient,
@@ -43650,6 +43685,7 @@ async function signupCommanderRunnerOptions(args, runnerId) {
43650
43685
  const editorRuntime = await resolveEditorRuntime({
43651
43686
  kandanUrl: args.serviceUrl,
43652
43687
  token: args.localRunnerAccessToken,
43688
+ customCodeServerBin: args.codeServerBin,
43653
43689
  fetchImpl: trustedFetch(trust)
43654
43690
  });
43655
43691
  const dependencyStatus = await buildRunnerDependencyStatus({
@@ -43704,6 +43740,7 @@ function signupConnectRestartCommand(args) {
43704
43740
  "--workspace",
43705
43741
  args.workspaceSlug,
43706
43742
  ...args.codexBin === void 0 ? [] : ["--codex-bin", args.codexBin],
43743
+ ...args.codeServerBin === void 0 ? [] : ["--code-server-bin", args.codeServerBin],
43707
43744
  "--cwd",
43708
43745
  args.projectPath,
43709
43746
  ...args.serviceUrl === defaultLinzumiHttpUrl ? [] : ["--api-url", args.serviceUrl]
@@ -45562,7 +45599,7 @@ secure mission control for all your agents on your computers
45562
45599
  init_runner();
45563
45600
  init_claudeCodeSession();
45564
45601
  init_authCache();
45565
- import { existsSync as existsSync14, readFileSync as readFileSync16, realpathSync as realpathSync6 } from "node:fs";
45602
+ import { existsSync as existsSync14, readFileSync as readFileSync16, realpathSync as realpathSync7 } from "node:fs";
45566
45603
  import { homedir as homedir13 } from "node:os";
45567
45604
  import { resolve as resolve10 } from "node:path";
45568
45605
  import { fileURLToPath as fileURLToPath4 } from "node:url";
@@ -46453,8 +46490,8 @@ function commanderStatusDir() {
46453
46490
  function commanderStatusFile(runnerId, statusDir = commanderStatusDir()) {
46454
46491
  return join16(statusDir, `${safeRunnerId(runnerId)}.json`);
46455
46492
  }
46456
- function defaultCommanderLogFile(runnerId, statusDir = commanderStatusDir()) {
46457
- return join16(statusDir, `${safeRunnerId(runnerId)}.log`);
46493
+ function defaultCommanderLogFile(runnerId) {
46494
+ return join16(homedir11(), ".linzumi", "logs", `${safeRunnerId(runnerId)}.log`);
46458
46495
  }
46459
46496
  function commanderLogIsConnected(log) {
46460
46497
  return connectedMarkers.some((marker) => log.includes(marker));
@@ -46463,7 +46500,7 @@ function startCommanderDaemon(options) {
46463
46500
  const statusDir = options.statusDir ?? commanderStatusDir();
46464
46501
  const statusFile = commanderStatusFile(options.runnerId, statusDir);
46465
46502
  const logFile = resolve8(
46466
- options.logFile ?? defaultCommanderLogFile(options.runnerId, statusDir)
46503
+ options.logFile ?? defaultCommanderLogFile(options.runnerId)
46467
46504
  );
46468
46505
  const entrypoint = options.entrypoint ?? currentEntrypoint();
46469
46506
  const nodeBin = options.nodeBin ?? process.execPath;
@@ -58496,6 +58533,11 @@ function createLinzumiMcpApiClient(options) {
58496
58533
  getMessage: (params) => request("GET", `${apiPrefix}/message`, params),
58497
58534
  getThread: (params) => request("GET", `${apiPrefix}/thread`, params),
58498
58535
  getChannel: (params) => request("GET", `${apiPrefix}/channel`, params),
58536
+ getCodingJobMetadata: (params) => request("GET", `${apiPrefix}/coding-job-metadata`, params),
58537
+ upsertCodingJobPlan: (params) => request("POST", `${apiPrefix}/coding-job-plan`, params),
58538
+ replaceCodingJobPlanSteps: (params) => request("POST", `${apiPrefix}/coding-job-plan/steps`, params),
58539
+ updateCodingJobPlanStep: (params) => request("POST", `${apiPrefix}/coding-job-plan/step`, params),
58540
+ linkCodingJobPullRequest: (params) => request("POST", `${apiPrefix}/coding-job-primary-pr`, params),
58499
58541
  listVaultSecrets: (params) => request("GET", `${apiPrefix}/vault-secrets`, params),
58500
58542
  sendChannelMessage: (params) => request("POST", `${apiPrefix}/channel-message`, params),
58501
58543
  prepareMessageUploads: (params) => request("POST", `${apiPrefix}/message-uploads/prepare`, params),
@@ -58573,6 +58615,16 @@ Tools:
58573
58615
  linzumi_get_message Read one message by scoped seq or Linzumi message URL.
58574
58616
  linzumi_get_thread Read one bounded thread by ID.
58575
58617
  linzumi_get_channel Read bounded recent messages and channel metadata.
58618
+ linzumi_get_coding_job_metadata
58619
+ Read the current coding job goal, plan, and workflow metadata.
58620
+ linzumi_upsert_coding_job_plan
58621
+ Set or update the coding job goal.
58622
+ linzumi_replace_coding_job_plan_steps
58623
+ Replace the ordered coding job plan steps.
58624
+ linzumi_update_coding_job_plan_step
58625
+ Update one coding job plan step status or note.
58626
+ linzumi_link_coding_job_pull_request
58627
+ Link the coding job to its primary GitHub pull request.
58576
58628
  linzumi_list_vault_secrets
58577
58629
  List vault secret names, descriptions, and owner scope.
58578
58630
  linzumi_send_channel_message
@@ -58660,6 +58712,123 @@ async function runMcpServer(args) {
58660
58712
  },
58661
58713
  async (params) => mcpJsonResult(await client.getChannel(params))
58662
58714
  );
58715
+ server.tool(
58716
+ "linzumi_get_coding_job_metadata",
58717
+ "Read the active coding job workflow metadata for a thread, including the agent-owned goal, ordered plan steps, step lock versions, and workflow status.",
58718
+ {
58719
+ thread_id: external_exports2.string().uuid().optional().describe(
58720
+ "Linzumi thread UUID. Defaults to the active coding job thread."
58721
+ )
58722
+ },
58723
+ async (params) => mcpJsonResult(
58724
+ await client.getCodingJobMetadata(
58725
+ paramsWithDefaultThread(params, defaultThreadId)
58726
+ )
58727
+ )
58728
+ );
58729
+ server.tool(
58730
+ "linzumi_upsert_coding_job_plan",
58731
+ "Set or update the current coding job goal. Use this at job start and whenever the goal changes materially.",
58732
+ {
58733
+ thread_id: external_exports2.string().uuid().optional().describe(
58734
+ "Linzumi thread UUID. Defaults to the active coding job thread."
58735
+ ),
58736
+ goal: external_exports2.string().min(1).max(1e4).describe("Concrete user-visible goal for this coding job.")
58737
+ },
58738
+ async (params) => mcpJsonResult(
58739
+ await client.upsertCodingJobPlan(
58740
+ paramsWithDefaultThread(params, defaultThreadId)
58741
+ )
58742
+ )
58743
+ );
58744
+ server.tool(
58745
+ "linzumi_replace_coding_job_plan_steps",
58746
+ "Replace the ordered coding job plan steps. Use this for the initial plan and for substantial rewrites when the old plan no longer fits the work.",
58747
+ {
58748
+ thread_id: external_exports2.string().uuid().optional().describe(
58749
+ "Linzumi thread UUID. Defaults to the active coding job thread."
58750
+ ),
58751
+ goal: external_exports2.string().min(1).max(1e4).optional().describe(
58752
+ "Required when no plan exists yet; updates the current coding job goal."
58753
+ ),
58754
+ steps: external_exports2.array(
58755
+ external_exports2.object({
58756
+ title: external_exports2.string().min(1).max(255),
58757
+ description: external_exports2.string().min(1).max(1e4),
58758
+ status: external_exports2.enum([
58759
+ "pending",
58760
+ "active",
58761
+ "completed",
58762
+ "blocked",
58763
+ "canceled"
58764
+ ]),
58765
+ status_note: external_exports2.string().min(1).max(4e3).optional(),
58766
+ completed_debrief: external_exports2.string().min(1).max(2e4).optional()
58767
+ })
58768
+ ).min(1).max(50).describe(
58769
+ "Ordered user-visible plan steps. Completed steps must include completed_debrief."
58770
+ )
58771
+ },
58772
+ async (params) => mcpJsonResult(
58773
+ await client.replaceCodingJobPlanSteps(
58774
+ paramsWithDefaultThread(params, defaultThreadId)
58775
+ )
58776
+ )
58777
+ );
58778
+ server.tool(
58779
+ "linzumi_update_coding_job_plan_step",
58780
+ "Update one coding job plan step status or note. Read metadata first and pass the current step lock_version.",
58781
+ {
58782
+ thread_id: external_exports2.string().uuid().optional().describe(
58783
+ "Linzumi thread UUID. Defaults to the active coding job thread."
58784
+ ),
58785
+ step_id: external_exports2.string().uuid().describe("Step id returned by linzumi_get_coding_job_metadata."),
58786
+ lock_version: external_exports2.number().int().positive().describe("Current step lock_version from metadata."),
58787
+ status: external_exports2.enum(["pending", "active", "completed", "blocked", "canceled"]),
58788
+ status_note: external_exports2.string().min(1).max(4e3).optional(),
58789
+ completed_debrief: external_exports2.string().min(1).max(2e4).optional().describe("Required when marking a step completed.")
58790
+ },
58791
+ async (params) => mcpJsonResult(
58792
+ await client.updateCodingJobPlanStep(
58793
+ paramsWithDefaultThread(params, defaultThreadId)
58794
+ )
58795
+ )
58796
+ );
58797
+ server.tool(
58798
+ "linzumi_link_coding_job_pull_request",
58799
+ "Link the active coding job to its primary GitHub pull request so PR comments, files, commits, checks, deployments, and reviews can flow into the metadata view.",
58800
+ {
58801
+ thread_id: external_exports2.string().uuid().optional().describe(
58802
+ "Linzumi thread UUID. Defaults to the active coding job thread."
58803
+ ),
58804
+ github_repo_owner: external_exports2.string().min(1).max(255),
58805
+ github_repo_name: external_exports2.string().min(1).max(255),
58806
+ github_pr_number: external_exports2.number().int().positive(),
58807
+ github_pr_url: external_exports2.string().url(),
58808
+ title: external_exports2.string().min(1).max(255),
58809
+ body: external_exports2.string().min(1).max(1e5).optional(),
58810
+ head_branch: external_exports2.string().min(1).max(255),
58811
+ head_sha: external_exports2.string().min(7).max(64),
58812
+ base_branch: external_exports2.string().min(1).max(255),
58813
+ base_sha: external_exports2.string().min(7).max(64),
58814
+ state: external_exports2.enum(["draft", "open", "closed", "merged"]).optional(),
58815
+ is_draft: external_exports2.boolean().optional(),
58816
+ review_status: external_exports2.enum(["unknown", "review_required", "approved", "changes_requested"]).optional(),
58817
+ source_remote_url: external_exports2.string().min(1).max(1e3).describe(
58818
+ "Git remote URL for the local job worktree; required when this job has no repo workspace yet."
58819
+ ),
58820
+ runtime_worktree_root: external_exports2.string().min(1).max(1e3).describe(
58821
+ "Absolute local worktree path for the coding job; required when this job has no repo workspace yet."
58822
+ ),
58823
+ dirty_status: external_exports2.enum(["unknown", "clean", "dirty"]).optional(),
58824
+ dirty_summary: external_exports2.string().min(1).max(2e3).optional()
58825
+ },
58826
+ async (params) => mcpJsonResult(
58827
+ await client.linkCodingJobPullRequest(
58828
+ paramsWithDefaultThread(params, defaultThreadId)
58829
+ )
58830
+ )
58831
+ );
58663
58832
  server.tool(
58664
58833
  "linzumi_upload_files",
58665
58834
  "Upload local files to Linzumi and attach them to a new, exact, or latest assistant message. Use silently; do not mention this tool in the visible reply.",
@@ -58957,6 +59126,13 @@ function targetWithDefaultThread(target, defaultThreadId) {
58957
59126
  return target;
58958
59127
  }
58959
59128
  }
59129
+ function paramsWithDefaultThread(params, defaultThreadId) {
59130
+ const existingThreadId = stringValue(params.thread_id);
59131
+ if (existingThreadId !== void 0 || defaultThreadId === void 0) {
59132
+ return params;
59133
+ }
59134
+ return { ...params, thread_id: defaultThreadId };
59135
+ }
58960
59136
  function resolveLinzumiUploadUrl(kandanUrl, uploadUrl) {
58961
59137
  try {
58962
59138
  return new URL(uploadUrl).toString();
@@ -59557,6 +59733,7 @@ async function main(args) {
59557
59733
  await runSignupFlow2({
59558
59734
  forceSignup: options.forceSignup,
59559
59735
  serviceUrl: options.serviceUrl,
59736
+ codeServerBin: options.codeServerBin,
59560
59737
  openBrowser: false,
59561
59738
  debugLaunchPayload: options.debugLaunchPayload,
59562
59739
  signupServerClient: false
@@ -59575,6 +59752,7 @@ async function main(args) {
59575
59752
  await runSignupFlow2({
59576
59753
  forceSignup: options.forceSignup,
59577
59754
  serviceUrl: options.serviceUrl,
59755
+ codeServerBin: options.codeServerBin,
59578
59756
  openBrowser: options.openBrowser,
59579
59757
  debugLaunchPayload: options.debugLaunchPayload
59580
59758
  });
@@ -59741,7 +59919,7 @@ function runPathsCommand(args) {
59741
59919
  if (pathValue === void 0 || pathValue.trim() === "") {
59742
59920
  throw new Error("missing path for linzumi paths add");
59743
59921
  }
59744
- const trustedPath = realpathSync6(resolve10(expandUserPath(pathValue)));
59922
+ const trustedPath = realpathSync7(resolve10(expandUserPath(pathValue)));
59745
59923
  if (linzumiUrl === void 0) {
59746
59924
  addAllowedCwd(pathValue);
59747
59925
  } else {
@@ -60628,7 +60806,7 @@ Codex:
60628
60806
  --approval-policy <value> Approval-policy metadata shown in Linzumi
60629
60807
  --stream-flush-ms <ms> Batch live Codex deltas before Linzumi persistence, default 150
60630
60808
  --fast Mark this runner as low-latency/fast in the availability message
60631
- --log-file <path> JSONL event log path, default ~/.linzumi/logs/runner-events.jsonl
60809
+ --log-file <path> JSONL event log path, default ~/.linzumi/logs/linzumi-runner.log
60632
60810
  --allowed-cwd <paths> Extra comma-separated roots where Linzumi may start local Codex sessions
60633
60811
  --forward-port <ports> Comma-separated local TCP ports Linzumi may expose as authenticated previews
60634
60812
  --code-server-bin <path> Custom development code-server executable. The default editor runtime is downloaded from Linzumi.
@@ -60710,7 +60888,7 @@ What it does:
60710
60888
  Options:
60711
60889
  --api-url <url> Linzumi API URL used to select the stored scoped runner id
60712
60890
  --status-dir <path> Status directory, default ~/.linzumi/commanders
60713
- --log-file <path> Commander log path, default in the status dir
60891
+ --log-file <path> Commander log path, default ~/.linzumi/logs/<runner-id>.log
60714
60892
  --timeout-ms <ms> Wait timeout, default 30000
60715
60893
 
60716
60894
  All normal Commander options such as --agent-token-file, --allowed-cwd,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linzumi/cli",
3
- "version": "0.0.75-beta",
3
+ "version": "0.0.77-beta",
4
4
  "description": "Linzumi CLI — point a Codex agent at the real code on your laptop, with your team watching and steering from shared threads.",
5
5
  "type": "module",
6
6
  "bin": {