@liberseek/boft-cli-win32-arm64 0.6.5 → 0.6.7

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.
@@ -3709,6 +3709,93 @@ var require_websocket_server = __commonJS({
3709
3709
  }
3710
3710
  });
3711
3711
 
3712
+ // packages/host-runtime/src/delegation-cli-help.ts
3713
+ var COMMAND_HELP = {
3714
+ "harness list": `boft harness list [--format json|compact]
3715
+ List Harnesses available in the active Runtime.`,
3716
+ "harness inspect": `boft harness inspect <harness> [--cwd <path>] [--refresh true|false] [--format json|compact]
3717
+ Read available Models, native defaults, Thinking options, and configuration capabilities.
3718
+ Use the returned Model and Thinking IDs for explicit selections.`,
3719
+ "delegate start": `boft delegate start --harness <id> --task <text> [--cwd <path>] [--model <opaque-ref>] [--thinking <option-id>] [--parent-thread <thread>] [--request-id <id>] [--format json|compact]
3720
+ Create an independent child Thread, submit the task, and return immediately.
3721
+ Omit --model and --thinking to use the Harness native defaults.
3722
+ --cwd overrides the child workspace. Otherwise use the resolved parent Thread workspace, then the Host Runtime process cwd.
3723
+ --parent-thread overrides caller inference. PARENT_THREAD_AMBIGUOUS requires an explicit parent.
3724
+ Reuse --request-id for an idempotent retry. Identical recent parent/target/task/configuration requests are also deduplicated briefly.
3725
+ The response confirms cwd and parent. Use its Thread reference with thread read, wait, send, or cancel.`,
3726
+ "thread send": `boft thread send <thread> --message <text> [--format json|compact]
3727
+ Start a new Turn in an idle writable Thread and return immediately.
3728
+ THREAD_BUSY means the current Turn is still active: wait or cancel before sending. Messages are not queued.`,
3729
+ "thread cancel": `boft thread cancel <thread> [--format json|compact]
3730
+ Request cancellation of the active Turn while preserving the Thread and history.
3731
+ cancelled=true (compact: cancelRequested=true) means the cancellation request was accepted. Read or wait to confirm the terminal state. An idle Thread returns false.`,
3732
+ "thread read": `boft thread read <thread> [--view result|messages] [--cursor <cursor>] [--limit <n>] [--format json|compact]
3733
+ Read immediately without starting a Turn. The default result view reports the latest Turn's status and result.
3734
+ The messages view pages visible user/Agent messages, oldest first. Default limit 25, maximum 100; --cursor and --limit require --view messages.
3735
+ hasMore describes remaining messages now. Save nextCursor for later incremental reads even when hasMore=false.
3736
+ Compact messages output contains only the message page and status; compact result output includes the latest nonempty progress while running.
3737
+ Full JSON retains the complete snapshot. Tool calls/output, file activity, and reasoning are not included in either format.`,
3738
+ "thread wait": `boft thread wait <thread> [--timeout-ms <n>] [--view result|messages] [--cursor <cursor>] [--limit <n>] [--format json|compact]
3739
+ Wait until the Thread is terminal or the timeout expires (default 30000 ms), then return the same snapshot as thread read plus timedOut.
3740
+ timedOut=true is a running checkpoint: the child keeps running. The response already includes the result when available; another read is unnecessary unless more information is needed.
3741
+ Message pagination uses --view messages, default limit 25, maximum 100. hasMore is for current pages; nextCursor also supports future incremental reads.`,
3742
+ "thread list": `boft thread list [--cwd <path>] [--parent <thread>] [--limit <n>] [--cursor <cursor>] [--sort created-asc|created-desc|updated-asc|updated-desc|recency-asc|recency-desc] [--format json|compact]
3743
+ Find existing Threads by workspace, or use --parent to list a Thread's delegated children.
3744
+ Workspace listing defaults to the caller process cwd. Default limit 25 (maximum 100), sorted created-desc.
3745
+ --parent uses Delegation relationships. A null nextCursor ends the list.
3746
+ Compact output keeps task links, Harness, status, title, and workspace.`
3747
+ };
3748
+ var COMMON_HELP = `Thread references accept a bare ID or codex://threads/<id>.
3749
+ --format json is the compatible full JSON output (default); --format compact returns concise JSON using task links instead of internal IDs.
3750
+ Success is written to stdout; errors {"error":{"code":"...","message":"...","details":{...}}} go to stderr with exit code 1. Exit code 0 means the command succeeded, not that the delegated task succeeded.
3751
+ read/wait are non-consuming. Native Codex callers need local Runtime access; RUNTIME_UNREACHABLE requires the Host-provided environment and a sandbox that permits that connection.
3752
+ Native Codex shell commands also need the Host-provided CODEXHOST_* environment variables. If shell_environment_policy filters them, prefer inherit = "all" with ignore_default_excludes = true and a narrow include_only containing "CODEXHOST_RUNTIME_ENDPOINT" and "CODEXHOST_RUNTIME_TOKEN" plus the variables required by the platform and invoked tools. Avoid unconstrained inherit = "all", which forwards unrelated ambient variables.`;
3753
+ var DELEGATION_HELP = `usage:
3754
+ boft harness list
3755
+ boft harness inspect <harness>
3756
+ boft delegate start --harness <id> --task <text>
3757
+ boft thread send <thread> --message <text>
3758
+ boft thread cancel <thread>
3759
+ boft thread read <thread>
3760
+ boft thread wait <thread>
3761
+ boft thread list
3762
+
3763
+ Use <command> --help for its options. Use harness list to discover targets.
3764
+ ${COMMON_HELP}
3765
+ `;
3766
+ function hasHelpOption(arguments_2) {
3767
+ for (let index = 0; index < arguments_2.length; index += 1) {
3768
+ const argument = arguments_2[index];
3769
+ if (argument === "--help" || argument === "-h") return true;
3770
+ if (argument?.startsWith("--")) index += 1;
3771
+ }
3772
+ return false;
3773
+ }
3774
+ function delegationCliHelp(arguments_2) {
3775
+ const [group, command, ...rest] = arguments_2;
3776
+ if (!group || group === "--help" || group === "-h") return DELEGATION_HELP;
3777
+ if (!command || command === "--help" || command === "-h" || command === "help") {
3778
+ if (group === "delegate") return DELEGATION_HELP;
3779
+ if (group === "harness" || group === "thread") {
3780
+ const usages = Object.entries(COMMAND_HELP).filter(([name]) => name.startsWith(`${group} `)).map(([, help]) => help.split("\n")[0]);
3781
+ return `${usages.join("\n")}
3782
+
3783
+ ${COMMON_HELP}
3784
+ `;
3785
+ }
3786
+ }
3787
+ if (hasHelpOption(rest)) {
3788
+ const name = `${group} ${command}`;
3789
+ if (Object.hasOwn(COMMAND_HELP, name)) {
3790
+ return `${COMMAND_HELP[name]}
3791
+
3792
+ ${COMMON_HELP}
3793
+ `;
3794
+ }
3795
+ }
3796
+ return void 0;
3797
+ }
3798
+
3712
3799
  // packages/host-runtime/src/delegation-types.ts
3713
3800
  var DELEGATION_RUNTIME_ENDPOINT_ENV = "CODEXHOST_RUNTIME_ENDPOINT";
3714
3801
  var DELEGATION_RUNTIME_TOKEN_ENV = "CODEXHOST_RUNTIME_TOKEN";
@@ -3725,6 +3812,114 @@ var DelegationControlError = class extends Error {
3725
3812
  details;
3726
3813
  };
3727
3814
 
3815
+ // packages/host-runtime/src/delegation-cli-output.ts
3816
+ function threadLink(threadId3) {
3817
+ return `codex://threads/${threadId3}`;
3818
+ }
3819
+ function inspectOutput({ harnessId, inspection }) {
3820
+ if (inspection.status !== "ready") return { harnessId, ...inspection };
3821
+ const { catalog } = inspection;
3822
+ return {
3823
+ harnessId,
3824
+ status: inspection.status,
3825
+ models: catalog.models.map(({ ref, label, supportedThinkingOptionIds }) => ({
3826
+ id: ref.id,
3827
+ label,
3828
+ ...supportedThinkingOptionIds ? { thinking: supportedThinkingOptionIds } : {}
3829
+ })),
3830
+ ...catalog.defaultModel ? { defaultModel: catalog.defaultModel.id } : {},
3831
+ thinkingOptions: catalog.thinkingOptions,
3832
+ ...catalog.defaultThinkingOptionId ? { defaultThinkingOptionId: catalog.defaultThinkingOptionId } : {},
3833
+ capabilities: inspection.capabilities
3834
+ };
3835
+ }
3836
+ function snapshotOutput(snapshot, view) {
3837
+ const common = {
3838
+ thread: threadLink(snapshot.threadId),
3839
+ harnessId: snapshot.harnessId,
3840
+ status: snapshot.status,
3841
+ ...snapshot.timedOut !== void 0 ? { timedOut: snapshot.timedOut } : {}
3842
+ };
3843
+ if (view === "messages") {
3844
+ if (typeof snapshot.hasMore !== "boolean") {
3845
+ throw new DelegationControlError(
3846
+ "INTERNAL_ERROR",
3847
+ "Compact message pagination requires an updated Host Runtime; use --format json with this Runtime."
3848
+ );
3849
+ }
3850
+ return {
3851
+ ...common,
3852
+ messages: (snapshot.messages ?? []).map(({ role, phase, text: text2 }) => ({
3853
+ role,
3854
+ ...phase ? { phase } : {},
3855
+ text: text2
3856
+ })),
3857
+ hasMore: snapshot.hasMore,
3858
+ nextCursor: snapshot.nextCursor,
3859
+ ...snapshot.result.message ? { error: snapshot.result.message } : {}
3860
+ };
3861
+ }
3862
+ const progress = snapshot.progress.filter(({ text: text2 }) => text2.trim()).at(-1)?.text;
3863
+ return {
3864
+ ...common,
3865
+ result: snapshot.result,
3866
+ ...snapshot.status === "running" && progress ? { progress } : {}
3867
+ };
3868
+ }
3869
+ function compactDelegationOutput(command, body, view = "result") {
3870
+ switch (command) {
3871
+ case "harness list":
3872
+ return body;
3873
+ case "harness inspect":
3874
+ return inspectOutput(body);
3875
+ case "delegate start": {
3876
+ const result = body;
3877
+ const effective = result.configuration?.effective;
3878
+ return {
3879
+ thread: result.deepLink,
3880
+ harnessId: result.harnessId,
3881
+ status: result.status,
3882
+ ...result.cwd ? { cwd: result.cwd } : {},
3883
+ ...result.parentThreadId ? { parent: threadLink(result.parentThreadId) } : {},
3884
+ ...effective?.resolvedModelLabel ? { model: effective.resolvedModelLabel } : {},
3885
+ ...effective?.effectiveThinkingOptionId ? { thinking: effective.effectiveThinkingOptionId } : {}
3886
+ };
3887
+ }
3888
+ case "thread send": {
3889
+ const result = body;
3890
+ return {
3891
+ thread: threadLink(result.threadId),
3892
+ harnessId: result.harnessId,
3893
+ status: result.status
3894
+ };
3895
+ }
3896
+ case "thread cancel": {
3897
+ const result = body;
3898
+ return {
3899
+ thread: threadLink(result.threadId),
3900
+ harnessId: result.harnessId,
3901
+ cancelRequested: result.cancelled
3902
+ };
3903
+ }
3904
+ case "thread read":
3905
+ case "thread wait":
3906
+ return snapshotOutput(body, view);
3907
+ case "thread list": {
3908
+ const result = body;
3909
+ return {
3910
+ threads: result.threads.map(({ deepLink, harnessId, status, title, cwd }) => ({
3911
+ thread: deepLink,
3912
+ harnessId,
3913
+ status,
3914
+ ...title ? { title } : {},
3915
+ ...cwd ? { cwd } : {}
3916
+ })),
3917
+ nextCursor: result.nextCursor
3918
+ };
3919
+ }
3920
+ }
3921
+ }
3922
+
3728
3923
  // packages/host-runtime/src/delegation-cli.ts
3729
3924
  var DEFAULT_WAIT_TIMEOUT_MS = 3e4;
3730
3925
  var DEFAULT_LIMIT = 25;
@@ -3771,45 +3966,12 @@ function value(parsed, name) {
3771
3966
  return parsed.options.get(name);
3772
3967
  }
3773
3968
  function rejectUnknown(parsed, allowed) {
3774
- const known = new Set(allowed);
3969
+ const known = /* @__PURE__ */ new Set([...allowed, "--format"]);
3775
3970
  for (const name of parsed.options.keys()) {
3776
3971
  if (!known.has(name))
3777
3972
  throw new DelegationControlError("INVALID_ARGUMENT", `Unknown option '${name}'`);
3778
3973
  }
3779
3974
  }
3780
- var DELEGATION_HELP = `usage:
3781
- boft harness inspect <harness> [--cwd <path>] [--refresh true|false]
3782
- boft delegate start --harness <id> --task <text> [--cwd <path>] [--model <opaque-ref>] [--thinking <option-id>] [--parent-thread <thread>] [--request-id <id>]
3783
- boft thread send <thread> --message <text>
3784
- boft thread cancel <thread>
3785
- boft thread read <thread> [--view result|messages] [--cursor <cursor>] [--limit <n>]
3786
- boft thread wait <thread> [--timeout-ms <n>] [--view result|messages] [--cursor <cursor>] [--limit <n>]
3787
- boft thread list [--cwd <path>] [--parent <thread>] [--limit <n>] [--cursor <cursor>] [--sort created-asc|created-desc|updated-asc|updated-desc|recency-asc|recency-desc]
3788
-
3789
- Thread identifiers accept a bare ID or codex://threads/<id>. Output is JSON by default.
3790
- harness inspect returns the target Model catalog, default Model, Thinking options, and configuration capabilities without creating a Thread. Use opaque IDs exactly as returned.
3791
- delegate start requires --harness and --task, creates and submits the child Thread, then returns immediately. --cwd selects the child workspace and defaults to the resolved parent Thread workspace, with the caller process cwd as a fallback. --model and --thinking select values returned by harness inspect. Omit either option to preserve that target's current default behavior. --parent-thread overrides caller inference. Reuse --request-id for idempotent retries; without it, identical recent parent/target/task/configuration requests are deduplicated briefly.
3792
- Successful start fields: delegationId, threadId, turnId, harnessId, deepLink, status, next.read, next.wait.
3793
- thread send starts a new Turn in an idle writable Thread and returns immediately. It fails with THREAD_BUSY instead of queueing or starting a concurrent Turn.
3794
- thread cancel requests cancellation of the current Turn while preserving the Thread. An idle Thread returns cancelled=false.
3795
- thread read is non-blocking. Its default result view returns threadId, harnessId, status, latest turn, visible progress, result.availability/result.text, and nextCursor.
3796
- thread read --view messages additionally returns paginated user/Agent-visible messages. The default page is 25 and --limit is capped at 100; --cursor and --limit require the messages view. Tool calls, tool output, file activity, reasoning summaries, hidden reasoning, and private Harness transcripts are never returned.
3797
- thread wait defaults to 30000 ms and waits only until the Thread reaches a terminal state or the bounded timeout expires. A timeout is a successful running checkpoint with timedOut=true; the child keeps running.
3798
- thread list defaults to the caller cwd, limit 25, created-desc; limit is capped at 100. --parent uses Delegation lineage, not Codex Subagent relationships.
3799
- read and wait are non-consuming: they do not start a Turn, send input, wake an Agent, mark messages read, or inject a result into the parent Session.
3800
- Native Codex as caller requires a session sandbox that permits local Runtime connections; otherwise RUNTIME_UNREACHABLE is returned. Native Codex as a target uses brokered official requests and is unaffected.
3801
- Native Codex shell commands also need the Host-provided CODEXHOST_* environment variables. If shell_environment_policy filters them, prefer inherit = "all" with ignore_default_excludes = true and a narrow include_only containing "CODEXHOST_RUNTIME_ENDPOINT" and "CODEXHOST_RUNTIME_TOKEN" plus the variables required by the platform and invoked tools. Avoid unconstrained inherit = "all", which forwards unrelated ambient variables.
3802
-
3803
- Errors are JSON: {"error":{"code":"...","message":"...","details":{...}}}.
3804
- INVALID_ARGUMENT: fix the named argument or incompatible option combination.
3805
- HARNESS_NOT_FOUND: choose a Harness ID listed in error.details.validHarnessIds.
3806
- THREAD_NOT_FOUND: verify the bare ID or codex:// deep link.
3807
- THREAD_BUSY: wait for or cancel the active Turn before sending another message.
3808
- PARENT_THREAD_AMBIGUOUS: pass --parent-thread explicitly.
3809
- RUNTIME_UNREACHABLE: run inside the Host-provided environment and, for native Codex, allow local Runtime connections; boft never falls back to PATH or another Runtime.
3810
- DELEGATION_FAILED: the target Session or initial task delivery failed and no successful child was published.
3811
- INTERNAL_ERROR: retry after checking the Host Runtime diagnostics.
3812
- `;
3813
3975
  async function requestRuntime(input) {
3814
3976
  const endpoint = input.environment[DELEGATION_RUNTIME_ENDPOINT_ENV];
3815
3977
  const token = input.environment[DELEGATION_RUNTIME_TOKEN_ENV];
@@ -3870,12 +4032,37 @@ async function runDelegationCli(input) {
3870
4032
  const environment = input.environment ?? process.env;
3871
4033
  try {
3872
4034
  const [group, command, ...rest] = input.arguments;
3873
- if (group === "delegate" && (!command || command === "--help" || command === "help") || group === "--help" || group === "-h") {
3874
- output.write(DELEGATION_HELP);
4035
+ const help = delegationCliHelp(input.arguments);
4036
+ if (help !== void 0) {
4037
+ output.write(help);
4038
+ return 0;
4039
+ }
4040
+ const parsed = options(rest);
4041
+ const format = value(parsed, "--format") ?? "json";
4042
+ if (format !== "json" && format !== "compact") {
4043
+ throw new DelegationControlError("INVALID_ARGUMENT", "--format must be json or compact");
4044
+ }
4045
+ const writeResult = (name, body, view = "result") => writeJson(output, format === "json" ? body : compactDelegationOutput(name, body, view));
4046
+ if (group === "harness" && command === "list") {
4047
+ rejectUnknown(parsed, []);
4048
+ if (parsed.positionals.length > 0) {
4049
+ throw new DelegationControlError(
4050
+ "INVALID_ARGUMENT",
4051
+ "harness list accepts no positional arguments"
4052
+ );
4053
+ }
4054
+ writeResult(
4055
+ "harness list",
4056
+ await requestRuntime({
4057
+ environment,
4058
+ path: "/v1/harness/list",
4059
+ body: {},
4060
+ ...input.fetchImpl ? { fetchImpl: input.fetchImpl } : {}
4061
+ })
4062
+ );
3875
4063
  return 0;
3876
4064
  }
3877
4065
  if (group === "harness" && command === "inspect") {
3878
- const parsed = options(rest);
3879
4066
  rejectUnknown(parsed, ["--cwd", "--refresh"]);
3880
4067
  if (parsed.positionals.length !== 1) {
3881
4068
  throw new DelegationControlError(
@@ -3891,8 +4078,8 @@ async function runDelegationCli(input) {
3891
4078
  if (refresh !== void 0 && refresh !== "true" && refresh !== "false") {
3892
4079
  throw new DelegationControlError("INVALID_ARGUMENT", "--refresh must be true or false");
3893
4080
  }
3894
- writeJson(
3895
- output,
4081
+ writeResult(
4082
+ "harness inspect",
3896
4083
  await requestRuntime({
3897
4084
  environment,
3898
4085
  path: "/v1/harness/inspect",
@@ -3907,7 +4094,6 @@ async function runDelegationCli(input) {
3907
4094
  return 0;
3908
4095
  }
3909
4096
  if (group === "delegate" && command === "start") {
3910
- const parsed = options(rest);
3911
4097
  rejectUnknown(parsed, [
3912
4098
  "--harness",
3913
4099
  "--task",
@@ -3927,8 +4113,8 @@ async function runDelegationCli(input) {
3927
4113
  if (!harnessId || !task)
3928
4114
  throw new DelegationControlError("INVALID_ARGUMENT", "--harness and --task are required");
3929
4115
  const parentThread = value(parsed, "--parent-thread") ?? environment[DELEGATION_THREAD_ID_ENV];
3930
- writeJson(
3931
- output,
4116
+ writeResult(
4117
+ "delegate start",
3932
4118
  await requestRuntime({
3933
4119
  environment,
3934
4120
  path: "/v1/delegate/start",
@@ -3947,7 +4133,6 @@ async function runDelegationCli(input) {
3947
4133
  return 0;
3948
4134
  }
3949
4135
  if (group === "thread" && command === "send") {
3950
- const parsed = options(rest);
3951
4136
  rejectUnknown(parsed, ["--message"]);
3952
4137
  if (parsed.positionals.length !== 1) {
3953
4138
  throw new DelegationControlError(
@@ -3963,8 +4148,8 @@ async function runDelegationCli(input) {
3963
4148
  "Thread identifier and --message are required"
3964
4149
  );
3965
4150
  }
3966
- writeJson(
3967
- output,
4151
+ writeResult(
4152
+ "thread send",
3968
4153
  await requestRuntime({
3969
4154
  environment,
3970
4155
  path: "/v1/thread/send",
@@ -3975,7 +4160,6 @@ async function runDelegationCli(input) {
3975
4160
  return 0;
3976
4161
  }
3977
4162
  if (group === "thread" && command === "cancel") {
3978
- const parsed = options(rest);
3979
4163
  rejectUnknown(parsed, []);
3980
4164
  if (parsed.positionals.length !== 1) {
3981
4165
  throw new DelegationControlError(
@@ -3987,8 +4171,8 @@ async function runDelegationCli(input) {
3987
4171
  if (!threadId3) {
3988
4172
  throw new DelegationControlError("INVALID_ARGUMENT", "Thread identifier is required");
3989
4173
  }
3990
- writeJson(
3991
- output,
4174
+ writeResult(
4175
+ "thread cancel",
3992
4176
  await requestRuntime({
3993
4177
  environment,
3994
4178
  path: "/v1/thread/cancel",
@@ -3999,7 +4183,6 @@ async function runDelegationCli(input) {
3999
4183
  return 0;
4000
4184
  }
4001
4185
  if (group === "thread" && (command === "read" || command === "wait")) {
4002
- const parsed = options(rest);
4003
4186
  rejectUnknown(parsed, ["--view", "--cursor", "--limit", "--timeout-ms"]);
4004
4187
  if (parsed.positionals.length !== 1)
4005
4188
  throw new DelegationControlError(
@@ -4031,19 +4214,19 @@ async function runDelegationCli(input) {
4031
4214
  timeoutMs: value(parsed, "--timeout-ms") ? positiveInteger(value(parsed, "--timeout-ms"), "--timeout-ms") : DEFAULT_WAIT_TIMEOUT_MS
4032
4215
  } : {}
4033
4216
  };
4034
- writeJson(
4035
- output,
4217
+ writeResult(
4218
+ command === "read" ? "thread read" : "thread wait",
4036
4219
  await requestRuntime({
4037
4220
  environment,
4038
4221
  path: command === "read" ? "/v1/thread/read" : "/v1/thread/wait",
4039
4222
  body,
4040
4223
  ...input.fetchImpl ? { fetchImpl: input.fetchImpl } : {}
4041
- })
4224
+ }),
4225
+ view
4042
4226
  );
4043
4227
  return 0;
4044
4228
  }
4045
4229
  if (group === "thread" && command === "list") {
4046
- const parsed = options(rest);
4047
4230
  rejectUnknown(parsed, ["--cwd", "--parent", "--limit", "--cursor", "--sort"]);
4048
4231
  if (parsed.positionals.length > 0)
4049
4232
  throw new DelegationControlError(
@@ -4061,8 +4244,8 @@ async function runDelegationCli(input) {
4061
4244
  ])).has(sort))
4062
4245
  throw new DelegationControlError("INVALID_ARGUMENT", "--sort is invalid");
4063
4246
  const parentThread = value(parsed, "--parent");
4064
- writeJson(
4065
- output,
4247
+ writeResult(
4248
+ "thread list",
4066
4249
  await requestRuntime({
4067
4250
  environment,
4068
4251
  path: "/v1/thread/list",
@@ -4261,7 +4444,7 @@ async function resolveInstalledUpdateContext(options2) {
4261
4444
  const stateDirectory = path.normalize(options2.stateDirectory ?? defaultUpdateStateDirectory(platform, environment));
4262
4445
  const resourcesRoot = path.dirname(appDirectory);
4263
4446
  const installationRoot = platform === "darwin" ? path.dirname(path.dirname(resourcesRoot)) : resourcesRoot;
4264
- const updaterExecutable = path.join(resourcesRoot, "libexec", platform === "win32" ? "codexhost-updater.exe" : "codexhost-updater");
4447
+ const updaterExecutable = path.join(resourcesRoot, "libexec", platform === "win32" ? "boft-updater.exe" : "boft-updater");
4265
4448
  const common = {
4266
4449
  version: metadata.version,
4267
4450
  launcherPid,
@@ -4824,7 +5007,7 @@ function createBackgroundUpdateManager(dependencies2 = {}) {
4824
5007
  const workDirectory = path3.join(stateDirectory, `update-${version2}-${randomId()}`);
4825
5008
  await mkdir2(workDirectory, { recursive: false, mode: 448 });
4826
5009
  const executableSuffix = platform === "win32" ? ".exe" : "";
4827
- const helperPath = path3.join(workDirectory, `codexhost-updater${executableSuffix}`);
5010
+ const helperPath = path3.join(workDirectory, `boft-updater${executableSuffix}`);
4828
5011
  await copyFile(updaterExecutable, helperPath);
4829
5012
  if (platform !== "win32")
4830
5013
  await chmod(helperPath, 448);
@@ -22568,6 +22751,7 @@ function projectItem(item, outcome, defaultCwd, includeCommandOutput = true, sen
22568
22751
  };
22569
22752
  case "subagentDelegation": {
22570
22753
  const primary = item.subagents[0];
22754
+ const sameConfiguration = item.subagents.every((subagent) => subagent.model === primary?.model && subagent.reasoningEffort === primary?.reasoningEffort);
22571
22755
  return {
22572
22756
  id: item.itemId,
22573
22757
  type: "collabAgentToolCall",
@@ -22576,8 +22760,8 @@ function projectItem(item, outcome, defaultCwd, includeCommandOutput = true, sen
22576
22760
  senderThreadId: senderThreadId ?? "",
22577
22761
  receiverThreadIds: item.subagents.map(({ subagentId }) => subagentId),
22578
22762
  prompt: item.prompt ?? null,
22579
- model: primary?.model ?? null,
22580
- reasoningEffort: primary?.reasoningEffort ?? null,
22763
+ model: sameConfiguration ? primary?.model ?? null : null,
22764
+ reasoningEffort: sameConfiguration ? primary?.reasoningEffort ?? null : null,
22581
22765
  agentsStates: Object.fromEntries(item.subagents.map(({ subagentId, status, resultSummary }) => [
22582
22766
  subagentId,
22583
22767
  { status: collabAgentStatus(status), message: resultSummary ?? null }
@@ -26252,15 +26436,21 @@ function projectDelegationThreadSnapshot(input) {
26252
26436
  const latestTurnStatus = latestTurn ? turnStatus2(latestTurn.status) : null;
26253
26437
  const status = input.running ? "running" : latestTurnStatus === "failed" || latestTurnStatus === "interrupted" ? latestTurnStatus : threadStatus(input.thread.status, input.running);
26254
26438
  const latestTurnMessages = latestTurnId ? visible.filter((message) => message.turnId === latestTurnId && message.role === "agent") : [];
26255
- const final = latestTurnMessages.filter((message) => message.phase === "final").at(-1);
26256
- const progress = latestTurnMessages.filter((message) => message.phase !== "final").map(({ id: id2, turnId, text: text2 }) => ({ id: id2, turnId, text: text2 }));
26439
+ const final = latestTurnMessages.filter((message) => message.phase === "final" && message.text.trim()).at(-1);
26440
+ const progress = latestTurnMessages.filter((message) => message.phase !== "final" && message.text.trim()).map(({ id: id2, turnId, text: text2 }) => ({ id: id2, turnId, text: text2 }));
26257
26441
  const result = input.running ? { availability: "pending" } : final ? { availability: "available", text: final.text } : {
26258
26442
  availability: "unavailable",
26259
26443
  ...isRecord9(latestTurn?.error) && typeof latestTurn.error.message === "string" ? { message: latestTurn.error.message } : {}
26260
26444
  };
26261
26445
  const offset = options2.view === "messages" ? decodeCursor(input.threadId, options2.cursor) : visible.length;
26262
- const page = options2.view === "messages" ? visible.slice(offset, offset + options2.limit) : void 0;
26263
- const nextOffset = options2.view === "messages" ? offset + (page?.length ?? 0) : visible.length;
26446
+ const page = options2.view === "messages" ? [] : void 0;
26447
+ let nextOffset = offset;
26448
+ if (page) {
26449
+ while (nextOffset < visible.length && page.length < options2.limit) {
26450
+ const message = visible[nextOffset++];
26451
+ if (message?.text.trim()) page.push(message);
26452
+ }
26453
+ }
26264
26454
  return {
26265
26455
  threadId: input.threadId,
26266
26456
  harnessId: input.harnessId,
@@ -26268,7 +26458,10 @@ function projectDelegationThreadSnapshot(input) {
26268
26458
  turn: latestTurnId && latestTurnStatus ? { turnId: latestTurnId, status: latestTurnStatus } : null,
26269
26459
  progress,
26270
26460
  result,
26271
- ...page ? { messages: page } : {},
26461
+ ...page ? {
26462
+ messages: page,
26463
+ hasMore: visible.slice(nextOffset).some((message) => message.text.trim())
26464
+ } : {},
26272
26465
  nextCursor: encodeCursor(input.threadId, nextOffset)
26273
26466
  };
26274
26467
  }
@@ -26316,11 +26509,11 @@ function statusFromThread(thread) {
26316
26509
  return last ? "completed" : "creating";
26317
26510
  }
26318
26511
  function validateStart(input) {
26319
- if (!input.task?.trim())
26512
+ if (typeof input.task !== "string" || !input.task.trim())
26320
26513
  throw new DelegationControlError("INVALID_ARGUMENT", "Task must not be empty");
26321
- if (input.cwd !== void 0 && !input.cwd.trim())
26514
+ if (input.cwd !== void 0 && (typeof input.cwd !== "string" || !input.cwd.trim()))
26322
26515
  throw new DelegationControlError("INVALID_ARGUMENT", "cwd must not be empty");
26323
- if (input.requestId !== void 0 && !input.requestId.trim()) {
26516
+ if (input.requestId !== void 0 && (typeof input.requestId !== "string" || !input.requestId.trim())) {
26324
26517
  throw new DelegationControlError("INVALID_ARGUMENT", "Request ID must not be empty");
26325
26518
  }
26326
26519
  }
@@ -26338,6 +26531,7 @@ var HarnessDelegationCoordinator = class {
26338
26531
  #cancelOfficial;
26339
26532
  #startOfficial;
26340
26533
  #listOfficial;
26534
+ #officialThreadCwd;
26341
26535
  #activeOfficialParents;
26342
26536
  constructor(input) {
26343
26537
  this.#adapters = input.adapters;
@@ -26353,8 +26547,12 @@ var HarnessDelegationCoordinator = class {
26353
26547
  this.#cancelOfficial = input.cancelOfficial;
26354
26548
  this.#startOfficial = input.startOfficial;
26355
26549
  this.#listOfficial = input.listOfficial;
26550
+ this.#officialThreadCwd = input.officialThreadCwd;
26356
26551
  this.#activeOfficialParents = input.activeOfficialParents;
26357
26552
  }
26553
+ async listHarnesses() {
26554
+ return { harnesses: ["codex", ...this.#adapters.keys()] };
26555
+ }
26358
26556
  async inspect(input) {
26359
26557
  if (input.harnessId === "codex") return this.#inspectOfficial(input);
26360
26558
  const adapter = this.#adapters.get(input.harnessId);
@@ -26379,7 +26577,8 @@ var HarnessDelegationCoordinator = class {
26379
26577
  const parent = await this.#parentMetadata(parentThreadId);
26380
26578
  const selectedCwd = input.cwd ?? parent.cwd ?? process.cwd();
26381
26579
  if (input.harnessId === "codex") {
26382
- return this.#startOfficial({ ...input, parentThreadId, cwd: selectedCwd });
26580
+ const result = await this.#startOfficial({ ...input, parentThreadId, cwd: selectedCwd });
26581
+ return { ...result, parentThreadId, cwd: result.cwd ?? selectedCwd };
26383
26582
  }
26384
26583
  const startInput = { ...input, parentThreadId, cwd: path7.resolve(selectedCwd) };
26385
26584
  if (!this.#adapters.has(input.harnessId)) {
@@ -26501,17 +26700,21 @@ var HarnessDelegationCoordinator = class {
26501
26700
  }
26502
26701
  await this.#repository.setDelegationStatus(delegationId, "running");
26503
26702
  await this.#notifyThreadStarted(thread.thread);
26504
- return this.#result(delegationId, childThreadId, turnId, targetHarnessId, "running", {
26505
- requested: {
26506
- ...input.model ? { model: input.model } : {},
26507
- ...input.thinkingOptionId ? { thinkingOptionId: input.thinkingOptionId } : {}
26508
- },
26509
- effective: {
26510
- ...thread.stateObserver.state.effectiveModel ? { effectiveModel: thread.stateObserver.state.effectiveModel } : {},
26511
- ...thread.stateObserver.state.resolvedModelLabel ? { resolvedModelLabel: thread.stateObserver.state.resolvedModelLabel } : {},
26512
- ...thread.stateObserver.state.effectiveThinkingOptionId ? { effectiveThinkingOptionId: thread.stateObserver.state.effectiveThinkingOptionId } : {}
26513
- }
26514
- });
26703
+ return {
26704
+ ...this.#result(delegationId, childThreadId, turnId, targetHarnessId, "running", {
26705
+ requested: {
26706
+ ...input.model ? { model: input.model } : {},
26707
+ ...input.thinkingOptionId ? { thinkingOptionId: input.thinkingOptionId } : {}
26708
+ },
26709
+ effective: {
26710
+ ...thread.stateObserver.state.effectiveModel ? { effectiveModel: thread.stateObserver.state.effectiveModel } : {},
26711
+ ...thread.stateObserver.state.resolvedModelLabel ? { resolvedModelLabel: thread.stateObserver.state.resolvedModelLabel } : {},
26712
+ ...thread.stateObserver.state.effectiveThinkingOptionId ? { effectiveThinkingOptionId: thread.stateObserver.state.effectiveThinkingOptionId } : {}
26713
+ }
26714
+ }),
26715
+ cwd: record3.cwd,
26716
+ parentThreadId
26717
+ };
26515
26718
  } catch (error51) {
26516
26719
  if (session) await session.close().catch(() => void 0);
26517
26720
  this.#externalRuntime.remove(childThreadId);
@@ -26740,19 +26943,24 @@ var HarnessDelegationCoordinator = class {
26740
26943
  }
26741
26944
  async #parentMetadata(parentThreadId) {
26742
26945
  const record3 = await this.#repository.find(parentThreadId);
26743
- if (!record3) return { harnessId: "codex" };
26744
- return { harnessId: record3.harnessId, cwd: record3.cwd };
26946
+ if (record3) return { harnessId: record3.harnessId, cwd: record3.cwd };
26947
+ const cwd = await this.#officialThreadCwd(parentThreadId).catch(() => void 0);
26948
+ return { harnessId: "codex", ...cwd ? { cwd } : {} };
26745
26949
  }
26746
26950
  async #existingResult(delegation) {
26747
26951
  const record3 = await this.#repository.find(delegation.childHostThreadId);
26748
26952
  const turnId = record3?.turnMappings.at(-1)?.hostTurnId ?? "pending";
26749
- return this.#result(
26750
- delegation.delegationId,
26751
- delegation.childHostThreadId,
26752
- turnId,
26753
- delegation.targetHarnessId,
26754
- delegation.status
26755
- );
26953
+ return {
26954
+ ...this.#result(
26955
+ delegation.delegationId,
26956
+ delegation.childHostThreadId,
26957
+ turnId,
26958
+ delegation.targetHarnessId,
26959
+ delegation.status
26960
+ ),
26961
+ ...record3 ? { cwd: record3.cwd } : {},
26962
+ parentThreadId: delegation.parentHostThreadId
26963
+ };
26756
26964
  }
26757
26965
  #turnResult(threadId3, turnId, harnessId) {
26758
26966
  return {
@@ -28578,9 +28786,11 @@ var AppServerHost = class {
28578
28786
  cancelOfficial: (input) => this.#cancelOfficialDelegationThread(input),
28579
28787
  startOfficial: (input) => this.#startOfficialDelegation(input),
28580
28788
  listOfficial: (input) => this.#listDelegationThreads(input),
28789
+ officialThreadCwd: (threadId3) => this.#readOfficialThreadCwd(threadId3),
28581
28790
  activeOfficialParents: () => [...this.#activeOfficialTurns.keys()]
28582
28791
  });
28583
28792
  const unregisterDelegationApi = options2.onDelegationApi?.({
28793
+ listHarnesses: () => this.#delegationCoordinator.listHarnesses(),
28584
28794
  inspect: (input) => this.#delegationCoordinator.inspect(input),
28585
28795
  start: (input) => this.#delegationCoordinator.start(input),
28586
28796
  send: (input) => this.#delegationCoordinator.send(input),
@@ -29615,6 +29825,13 @@ var AppServerHost = class {
29615
29825
  ]);
29616
29826
  return thread !== null || childDelegation !== null || delegation !== null;
29617
29827
  }
29828
+ async #readOfficialThreadCwd(threadId3) {
29829
+ const response = await this.#requestOfficial("thread/read", { threadId: threadId3 });
29830
+ if (isRecord13(response.error)) return void 0;
29831
+ const result = isRecord13(response.result) ? response.result : null;
29832
+ const thread = result && isRecord13(result.thread) ? result.thread : null;
29833
+ return thread && typeof thread.cwd === "string" && thread.cwd.trim() ? thread.cwd : void 0;
29834
+ }
29618
29835
  async #inspectOfficialDelegationTarget(input) {
29619
29836
  const response = await this.#requestOfficial("model/list", {});
29620
29837
  if (isRecord13(response.error)) {
@@ -29807,6 +30024,7 @@ var AppServerHost = class {
29807
30024
  harnessId: "codex",
29808
30025
  deepLink: `codex://threads/${threadId3}`,
29809
30026
  status: pendingTerminal ?? "running",
30027
+ cwd: thread && typeof thread.cwd === "string" ? thread.cwd : input.cwd,
29810
30028
  ...requestedModel || input.thinkingOptionId ? {
29811
30029
  configuration: {
29812
30030
  requested: {
@@ -32183,6 +32401,12 @@ var DelegationControlRegistry = class {
32183
32401
  "Harness inspection requires exactly one active Host Runtime session"
32184
32402
  ).inspect(input);
32185
32403
  }
32404
+ async listHarnesses() {
32405
+ return only(
32406
+ [...this.#registrations],
32407
+ "Harness discovery requires exactly one active Host Runtime session"
32408
+ ).listHarnesses();
32409
+ }
32186
32410
  async start(input) {
32187
32411
  return (await this.#registrationForStart(input)).start(input);
32188
32412
  }
@@ -32414,6 +32638,9 @@ async function startDelegationControlServer(input) {
32414
32638
  }
32415
32639
  const body = await jsonBody(request);
32416
32640
  switch (request.url) {
32641
+ case "/v1/harness/list":
32642
+ writeJson2(response, 200, await input.api.listHarnesses());
32643
+ return;
32417
32644
  case "/v1/harness/inspect":
32418
32645
  writeJson2(response, 200, await input.api.inspect(body));
32419
32646
  return;
@@ -32461,9 +32688,11 @@ import { createHash as createHash6, randomUUID as randomUUID9 } from "node:crypt
32461
32688
  import { mkdir as mkdir7, open as open5, readFile as readFile8, rename as rename5, rm as rm5, stat as stat3 } from "node:fs/promises";
32462
32689
  import os4 from "node:os";
32463
32690
  import path16 from "node:path";
32464
- var SKILL_VERSION = 5;
32691
+ var SKILL_VERSION = 7;
32465
32692
  var SKILL_RELATIVE_PATH = path16.join("skills", "codexhost-delegation", "SKILL.md");
32466
32693
  var PREVIOUS_MANAGED_DIGESTS = [
32694
+ "9d2f491850fb0b4084a31ba9b5e4a550b5e833747af322090d8ed0ff80b88c30",
32695
+ "2bb0aebb9b06febbc6c0c0bcdb0b32506c7cdbf8dc3b734cc6b2a86621270e4e",
32467
32696
  "aff258622dc8ff321f32b15620d081e578cb9c9ed1134d6a57f35ca8e7762c0a",
32468
32697
  "ba509f57e5448e796b3dfdd5031dcb08672eded50b61c0a54de84cfa02c49dd3",
32469
32698
  "d3ddf6db9bc5c5df825479c885bbbf0ca08da66f7057a12e02e1fdf57525149e",
@@ -32488,21 +32717,13 @@ Before acting, run:
32488
32717
 
32489
32718
  \`boft delegate --help\`
32490
32719
 
32491
- Treat its output as the sole authoritative source for:
32492
-
32493
- - available commands;
32494
- - command parameters;
32495
- - available target Harness IDs;
32496
- - Thread identifier formats;
32497
- - waiting and reading behavior;
32498
- - response fields;
32499
- - errors and recovery guidance.
32720
+ Use CLI help as the authoritative source for commands and behavior. Consult
32721
+ command-specific help for options and the Harness listing command when the
32722
+ target is unknown. Prefer compact output when supported, and use its task links
32723
+ directly for subsequent commands.
32500
32724
 
32501
- Do not construct commands, parameters, or Harness IDs from memory.
32502
-
32503
- When the user asks for a specific Model or Thinking level, inspect the target
32504
- Harness first and use the exact opaque IDs returned by the authoritative CLI.
32505
- When they do not specify either setting, omit it so the target keeps its default.
32725
+ Use the Harness native defaults. Inspect the target when a Model or Thinking
32726
+ selection is needed or the default is unavailable.
32506
32727
 
32507
32728
  For a new delegation, create an independent child session and submit the
32508
32729
  requested task. For an existing external session, resolve the target from the
@@ -32521,18 +32742,8 @@ user’s request and the task:
32521
32742
  - check it again later;
32522
32743
  - leave it running in the background.
32523
32744
 
32524
- When the result is needed, explicitly read the target Thread. Report only the
32525
- visible result returned by that Thread.
32526
-
32527
- Provide the user with the necessary tracking information available from the
32528
- CLI; omit unavailable fields rather than inventing them:
32529
-
32530
- - target agent;
32531
- - \`delegationId\`;
32532
- - \`threadId\`;
32533
- - \`turnId\`;
32534
- - \`deepLink\`;
32535
- - current or final status.
32745
+ Report the result returned by read or a completed wait, together with the target
32746
+ agent, status, and a labeled task link. Keep internal tracking IDs in tool calls.
32536
32747
  `;
32537
32748
  var CURRENT_DIGEST = createHash6("sha256").update(CODEXHOST_DELEGATION_SKILL).digest("hex");
32538
32749
  function digest(value2) {