@team-agent/installer 0.3.23 → 0.3.25

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.
@@ -157,6 +157,13 @@ pub enum Key {
157
157
  Char(char),
158
158
  /// `\x03`。
159
159
  CtrlC,
160
+ /// E46 (0.3.24 bug#5): pre-submit Escape to exit bracketed-paste mode on
161
+ /// fresh provider TUIs (claude). When a bracketed paste lands on a TUI
162
+ /// whose composer is still initialising, the framework's plain `Enter`
163
+ /// gets interpreted as paste content, not submit. Sending `Escape` first
164
+ /// closes the paste bracket so the subsequent `Enter` submits.
165
+ /// Real-machine truth source: macmini demo-director repro.
166
+ Escape,
160
167
  /// tmux `-X cancel` / `q` / `d`;非 tmux 后端无 copy-mode 概念 → no-op。
161
168
  CancelMode,
162
169
  }
@@ -287,7 +294,10 @@ pub enum InjectVerification {
287
294
  /// `{key}_sent_after_visible_token` 是模板 → 用携带 Key 的 variant 表达。
288
295
  #[derive(Debug, Clone, Copy, PartialEq, Eq)]
289
296
  pub enum SubmitVerification {
290
- /// `enter_sent_without_placeholder_check`。
297
+ /// `enter_sent_without_placeholder_check`。MUST-10:此 variant 代表 paste+Enter
298
+ /// 完成且无需 placeholder probe(纯 peer 消息路径)。**保留** ⇒ delivered 语义;
299
+ /// E46 后只有 post-Enter consumption 确认通过(input 清空 / Working 信号)才返回
300
+ /// 此 variant — fresh TUI 未消费走 [`Self::SubmitConsumptionUnverified`]。
291
301
  EnterSentWithoutPlaceholderCheck,
292
302
  /// `pasted_content_prompt_absent_after_submit`。
293
303
  PastedContentPromptAbsentAfterSubmit,
@@ -297,6 +307,14 @@ pub enum SubmitVerification {
297
307
  KeySentAfterVisibleToken { key: Key },
298
308
  /// `send_keys_failed`。
299
309
  SendKeysFailed,
310
+ /// E46 (0.3.24 bug#5, demo-director 卡 bracketed paste): Enter 已发但
311
+ /// post-Enter 接收侧消费信号(input 行清空 / provider 进 Working)在 bounded
312
+ /// resend 上限内未观察到。**delivery 不当作 delivered**;走 submitted_unverified /
313
+ /// failed 路径。区别于
314
+ /// [`Self::PastedContentPromptStillPresentAfterSubmit`](claude paste-prompt
315
+ /// 折叠场景)— 本 variant 是结构化 input-empty 检测,适配 demo-director
316
+ /// 直接渲染文本路径。
317
+ SubmitConsumptionUnverified,
300
318
  }
301
319
 
302
320
  /// turn-boundary 观测(tmux_io.py:224-260,09-transport.md 表 §40)。
@@ -621,6 +639,10 @@ pub fn tmux_key_name(key: Key) -> &'static str {
621
639
  Key::Char('8') => "8",
622
640
  Key::Char('9') => "9",
623
641
  Key::CtrlC => "C-c",
642
+ // E46 (0.3.24 bug#5): tmux supports `Escape` as a key name; sending
643
+ // it as a send-keys arg emits `\x1b` to the pane (closes bracketed
644
+ // paste mode on a stuck TUI composer).
645
+ Key::Escape => "Escape",
624
646
  Key::CancelMode | Key::Char(_) => "",
625
647
  }
626
648
  }
@@ -850,6 +872,9 @@ pub fn submit_verification_wire(v: SubmitVerification) -> String {
850
872
  format!("{}_sent_after_visible_token", tmux_key_name(key))
851
873
  }
852
874
  SubmitVerification::SendKeysFailed => "send_keys_failed".to_string(),
875
+ SubmitVerification::SubmitConsumptionUnverified => {
876
+ "submit_consumption_unverified".to_string()
877
+ }
853
878
  }
854
879
  }
855
880
 
package/npm/install.mjs CHANGED
@@ -6,36 +6,104 @@ import os from "node:os";
6
6
  import path from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
8
 
9
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const modulePath = fileURLToPath(import.meta.url);
10
+ const __dirname = path.dirname(modulePath);
10
11
  const packageRoot = path.resolve(__dirname, "..");
11
12
  const require = createRequire(import.meta.url);
12
13
  const packageJson = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.json"), "utf8"));
13
14
  const DOCTOR_TIMEOUT_MS = 5000;
14
15
  const VERSION_SMOKE_TIMEOUT_MS = 5000;
15
16
 
16
- const command = process.argv[2] || "install";
17
- const args = process.argv.slice(3);
18
-
19
- if (["-h", "--help", "help"].includes(command)) {
20
- printHelp();
21
- process.exit(0);
17
+ if (isCliEntrypoint()) {
18
+ main();
22
19
  }
23
20
 
24
- try {
25
- if (command === "install" || command === "update") {
26
- install(args);
27
- } else if (command === "doctor") {
28
- runDoctor(args);
29
- } else if (command === "uninstall") {
30
- uninstall(args);
31
- } else {
32
- console.error(`unknown command: ${command}`);
21
+ function main() {
22
+ const command = process.argv[2] || "install";
23
+ const args = process.argv.slice(3);
24
+
25
+ if (["-h", "--help", "help"].includes(command)) {
33
26
  printHelp();
34
- process.exit(2);
27
+ process.exit(0);
28
+ }
29
+
30
+ try {
31
+ if (command === "install" || command === "update") {
32
+ install(args);
33
+ } else if (command === "doctor") {
34
+ runDoctor(args);
35
+ } else if (command === "uninstall") {
36
+ uninstall(args);
37
+ } else {
38
+ console.error(`unknown command: ${command}`);
39
+ printHelp();
40
+ process.exit(2);
41
+ }
42
+ } catch (error) {
43
+ console.error(error instanceof Error ? error.message : String(error));
44
+ process.exit(1);
45
+ }
46
+ }
47
+
48
+ function isCliEntrypoint() {
49
+ if (!process.argv[1]) {
50
+ return false;
51
+ }
52
+ try {
53
+ return fs.realpathSync(process.argv[1]) === fs.realpathSync(modulePath);
54
+ } catch {
55
+ return path.resolve(process.argv[1]) === modulePath;
56
+ }
57
+ }
58
+
59
+ export function doctorSelfCheckVerdict(doctorBody, spawnMeta = {}) {
60
+ if (spawnMeta.error || spawnMeta.signal) {
61
+ return { kind: "advisory", blockers: [] };
35
62
  }
36
- } catch (error) {
37
- console.error(error instanceof Error ? error.message : String(error));
38
- process.exit(1);
63
+
64
+ let body;
65
+ try {
66
+ body = JSON.parse(doctorBody || "");
67
+ } catch {
68
+ return { kind: "advisory", blockers: [] };
69
+ }
70
+
71
+ const blockers = [];
72
+ // Doctor JSON source: crates/team-agent/src/cli/mod.rs:2739-2764.
73
+ if (body?.tmux?.installed === false) {
74
+ blockers.push("tmux not installed");
75
+ }
76
+ if (!body?.mcp?.server_command) {
77
+ blockers.push("MCP server command missing");
78
+ }
79
+ const profileSmokeStatus = body?.profile_smoke?.status;
80
+ const profileSmokeNonBlocking =
81
+ profileSmokeStatus === "legacy_team_invalid" || profileSmokeStatus === "not_required";
82
+ if (
83
+ body?.error === "profile_smoke_failed" ||
84
+ (body?.profile_smoke?.ok === false && !profileSmokeNonBlocking)
85
+ ) {
86
+ blockers.push("profile smoke failed");
87
+ }
88
+
89
+ if (blockers.length > 0) {
90
+ return { kind: "blockers", blockers };
91
+ }
92
+
93
+ const noContext =
94
+ body?.ok === false && body?.error === "workspace has no Team Agent spec or runtime context";
95
+ if (body?.ok === true || noContext) {
96
+ return { kind: "ok", blockers: [] };
97
+ }
98
+
99
+ return { kind: "advisory", blockers: [] };
100
+ }
101
+
102
+ export function doctorSelfCheckLine(verdict) {
103
+ if (verdict.kind === "blockers") {
104
+ return `doctor: found blockers (${verdict.blockers.join("; ")}); run team-agent doctor in your project for details`;
105
+ }
106
+ return "doctor: ok (run team-agent doctor inside a team workspace for a full report)";
39
107
  }
40
108
 
41
109
  function printHelp() {
@@ -116,11 +184,8 @@ function install(argv) {
116
184
  encoding: "utf8",
117
185
  timeout: DOCTOR_TIMEOUT_MS,
118
186
  });
119
- if (doctor.status === 0) {
120
- console.log("doctor: ok");
121
- } else {
122
- console.log("doctor: has blockers; run `team-agent doctor` after updating PATH");
123
- }
187
+ const verdict = doctorSelfCheckVerdict(doctor.stdout, doctor);
188
+ console.log(doctorSelfCheckLine(verdict));
124
189
  } finally {
125
190
  fs.rmSync(doctorWorkspace, { recursive: true, force: true });
126
191
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-agent/installer",
3
- "version": "0.3.23",
3
+ "version": "0.3.25",
4
4
  "description": "npx installer for Team Agent",
5
5
  "keywords": [
6
6
  "codex",
@@ -20,9 +20,9 @@
20
20
  "team-agent-installer": "npm/install.mjs"
21
21
  },
22
22
  "optionalDependencies": {
23
- "@team-agent/cli-darwin-arm64": "0.3.23",
24
- "@team-agent/cli-darwin-x64": "0.3.23",
25
- "@team-agent/cli-linux-x64": "0.3.23"
23
+ "@team-agent/cli-darwin-arm64": "0.3.25",
24
+ "@team-agent/cli-darwin-x64": "0.3.25",
25
+ "@team-agent/cli-linux-x64": "0.3.25"
26
26
  },
27
27
  "scripts": {
28
28
  "postinstall": "node npm/bincheck.mjs",