@zq-silk/yui 0.14.0 → 0.14.1

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 CHANGED
@@ -781,7 +781,10 @@ TaskRole itself stores identity and desired launch configuration, not runtime
781
781
  status; Role status shown by CLI/Web is derived from the active Turn plus
782
782
  Session/Driver lifecycle facts.
783
783
 
784
- Global Operator and global Role sessions remain native interactive CLIs:
784
+ Global Operator and global Role sessions remain native interactive CLIs. Codex
785
+ connects that TUI to the default shared App Server, so the same thread can move
786
+ between Yui and Desktop without transferring a rollout writer or losing its
787
+ Global Context entry:
785
788
 
786
789
  ```sh
787
790
  yui session enter <global-role>
@@ -1,7 +1,8 @@
1
1
  const OWNED_ARGUMENTS_BY_ADAPTER = {
2
2
  codex: [
3
3
  "resume", "fork", "exec", "e", "review",
4
- "--model", "-m", "--config", "-c", "--sandbox", "-s",
4
+ "--model", "-m", "--config", "-c", "--remote", "--remote-auth-token-env",
5
+ "--sandbox", "-s",
5
6
  "--ask-for-approval", "-a", "--search", "--profile", "-p",
6
7
  "--add-dir", "--cd", "-C", "--full-auto",
7
8
  "--dangerously-bypass-approvals-and-sandbox",
@@ -130,7 +130,10 @@ export function materializeSessionBootstrap(input) {
130
130
  roleProfileRef: { digest: profileDigest, path: roleProfilePath },
131
131
  contextProtocol: input.owner.scope === "global"
132
132
  ? {
133
- loadCommand: "\"$YUI_SESSION_CLI\" session context \"$YUI_ROLE\" --json"
133
+ // A Global Session may move between Yui's remote TUI and Desktop.
134
+ // Carry its read entry in the Thread-visible Manifest instead of
135
+ // depending on the client process that happened to create it.
136
+ loadCommand: renderGlobalContextCommand(input.controlPlane, home, input.role.name)
134
137
  }
135
138
  : {
136
139
  loadCommand: "\"$YUI_SESSION_CLI\" task turn context \"$YUI_TASK_ID/<turn-id>\" --json",
@@ -148,6 +151,20 @@ export function materializeSessionBootstrap(input) {
148
151
  descriptorPath
149
152
  });
150
153
  }
154
+ function renderGlobalContextCommand(controlPlane, home, roleName) {
155
+ return [
156
+ `YUI_HOME=${quoteShellWord(home)}`,
157
+ quoteShellWord(controlPlane.executable),
158
+ quoteShellWord(controlPlane.cliEntry),
159
+ "session",
160
+ "context",
161
+ quoteShellWord(roleName),
162
+ "--json"
163
+ ].join(" ");
164
+ }
165
+ function quoteShellWord(value) {
166
+ return `'${value.replaceAll("'", "'\"'\"'")}'`;
167
+ }
151
168
  /**
152
169
  * Retargets known managed wrappers to the current resolved control plane after
153
170
  * a compatible update. Only a valid Session Manifest may nominate a wrapper,
@@ -567,7 +567,13 @@ export class FileRoleLaunchPlanner {
567
567
  const scopedLaunch = owner.scope === "task"
568
568
  ? this.#applyWorkspaceScope(owner.taskId, role, launch, workspaceOverride)
569
569
  : launch;
570
- const ordinaryConversationLaunch = withCodexThreadEnvironment(scopedLaunch);
570
+ const sharedDaemonLaunch = owner.scope === "global" && configured.adapterId === "codex"
571
+ ? {
572
+ ...scopedLaunch,
573
+ args: addCodexSharedDaemonRemote(scopedLaunch.args, launchMode, scopedLaunch.env)
574
+ }
575
+ : scopedLaunch;
576
+ const ordinaryConversationLaunch = withCodexThreadEnvironment(sharedDaemonLaunch);
571
577
  return {
572
578
  role: {
573
579
  name: role.name,
@@ -830,6 +836,34 @@ function addCodexSessionNotify(args, mode, cliPath) {
830
836
  }
831
837
  return [...args.slice(0, -2), ...managed, ...args.slice(-2)];
832
838
  }
839
+ /**
840
+ * Global Codex keeps its native TUI, but the TUI is only a client attachment
841
+ * to the user's shared App Server. The daemon owns the Thread and its writer,
842
+ * so Desktop can open the same Yui-created Thread without a second rollout
843
+ * writer or a Yui-specific takeover.
844
+ */
845
+ export function addCodexSharedDaemonRemote(args, mode, environment = {}) {
846
+ const sessionEnvironment = Object.fromEntries(Object.entries(environment).filter(([name]) => name.startsWith("YUI_")));
847
+ const remote = [
848
+ "--remote",
849
+ "unix://",
850
+ ...(Object.keys(sessionEnvironment).length === 0
851
+ ? []
852
+ : ["--config", codexShellEnvironmentConfig(sessionEnvironment)])
853
+ ];
854
+ if (mode === "new")
855
+ return [...args, ...remote];
856
+ if (args.length < 2 || args.at(-2) !== "resume") {
857
+ throw new Error("Codex resume launch shape is invalid.");
858
+ }
859
+ return [...args.slice(0, -2), ...remote, ...args.slice(-2)];
860
+ }
861
+ function codexShellEnvironmentConfig(environment) {
862
+ const entries = Object.entries(environment)
863
+ .sort(([left], [right]) => left.localeCompare(right))
864
+ .map(([name, value]) => `${JSON.stringify(name)}=${JSON.stringify(value)}`);
865
+ return `shell_environment_policy.set={${entries.join(",")}}`;
866
+ }
833
867
  /**
834
868
  * Codex 0.145 discovers lifecycle hooks from its effective config. Keep Yui's
835
869
  * two handlers invocation-local: this avoids mutating CODEX_HOME or the Task
@@ -519,7 +519,7 @@ yui task role takeover <task-id> <role>
519
519
  yui task role release <task-id> <role>
520
520
  ```
521
521
 
522
- Codex Role thread 可在 Desktop 中直接查看和操作;Desktop 已有 active Turn 时,Yui 只保留待投递工作并等待,不会失败或重复投递。`view`、`takeover`、`release` 继续作为 Claude 等独立进程 Provider 的人工控制入口。Yui 不写入全局 Hook/config,也不启动、重启或停止共享 daemon;Codex CLI/daemon 故障由 Task 生命周期之外修复。Global Operator 与 global Role 继续使用原生交互式 CLI,不属于受管理 Task Provider 协议。
522
+ Codex Role thread 可在 Desktop 中直接查看和操作;Desktop 已有 active Turn 时,Yui 只保留待投递工作并等待,不会失败或重复投递。`view`、`takeover`、`release` 继续作为 Claude 等独立进程 Provider 的人工控制入口。Yui 不写入全局 Hook/config,也不启动、重启或停止共享 daemon;Codex CLI/daemon 故障由 Task 生命周期之外修复。Global Operator 与 global Role 继续使用原生交互式 CLI,不属于受管理 Task Provider 协议;Yui 在内部将 Codex 的 Global TUI 连接到同一个默认 App Server,用户不能通过 Agent 或 Role 参数覆盖该连接,Session Manifest 自带不依赖启动进程环境的 Global Context 命令,因此同一 thread 可直接切换到 Desktop 继续对话。
523
523
 
524
524
  当新版本需要离线迁移 Home 时,应等待当前 Turn 完成,然后从普通 shell
525
525
  执行 `yui session stop --all`,再重新执行 `yui update`。停止命令会先整体预检:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zq-silk/yui",
3
- "version": "0.14.0",
3
+ "version": "0.14.1",
4
4
  "description": "Local control plane for long-running native agent CLI sessions backed by tmux.",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -43,12 +43,11 @@ The pack's authority view and writable Project IDs are hard boundaries. A
43
43
  native subagent inherits the parent Turn's refs and authority; it does not gain a
44
44
  new Yui actor, Turn, Session, or cross-Task read permission.
45
45
 
46
- For a global Operator or custom GlobalRole Session, load the stable authorized view
47
- before routing or acting:
48
-
49
- ```sh
50
- "$YUI_SESSION_CLI" session context "$YUI_ROLE" --json
51
- ```
46
+ For a global Operator or custom GlobalRole Session, execute the exact
47
+ `contextProtocol.loadCommand` carried by the current Session Manifest before
48
+ routing or acting. That command is self-contained because a Global Codex Thread
49
+ may move between Yui's remote TUI and Desktop; never reconstruct it from
50
+ `YUI_SESSION_*` process variables.
52
51
 
53
52
  Global context grants no Task implementation workspace. Read a Task only after
54
53
  the Operator has routed to its public/task-authorized context command; never