@triflux/remote 10.53.0 → 10.55.0

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 (47) hide show
  1. package/hub/team/backend.mjs +10 -3
  2. package/hub/team/cli/commands/start/index.mjs +0 -2
  3. package/hub/team/handoff.mjs +1 -1
  4. package/hub/team/headless.mjs +41 -57
  5. package/hub/team/intervention.mjs +6 -4
  6. package/hub/team/nativeProxy.mjs +2 -48
  7. package/hub/team/pane.mjs +31 -18
  8. package/hub/team/psmux.mjs +36 -20
  9. package/hub/team/remote-session.mjs +66 -56
  10. package/hub/team/retry-state-machine.mjs +1 -1
  11. package/hub/team/session.mjs +80 -59
  12. package/hub/team/terminal-opener.mjs +5 -19
  13. package/hub/team/tui-viewer.mjs +2 -2
  14. package/hub/team/tui.mjs +0 -6
  15. package/hub/workers/factory.mjs +1 -10
  16. package/hub/workers/interface.mjs +0 -7
  17. package/package.json +2 -6
  18. package/scripts/lib/backup-rotation.mjs +60 -0
  19. package/scripts/lib/codex-profile-config.mjs +20 -7
  20. package/scripts/lib/codex-recovery.sh +2 -3
  21. package/scripts/lib/install-blob-history.json +3196 -0
  22. package/scripts/lib/install-retire.mjs +203 -0
  23. package/scripts/lib/legacy-hook-cleanup.mjs +148 -13
  24. package/scripts/lib/legacy-mcp-cleanup.mjs +405 -104
  25. package/scripts/lib/machine-profile.mjs +2 -2
  26. package/scripts/lib/mcp-filter.mjs +1 -42
  27. package/scripts/lib/mcp-guard-engine.mjs +198 -19
  28. package/scripts/lib/mcp-manifest.mjs +0 -40
  29. package/scripts/lib/process-utils.mjs +19 -0
  30. package/scripts/lib/stable-node.mjs +35 -0
  31. package/scripts/lib/test-env.mjs +20 -0
  32. package/cto/brief.mjs +0 -73
  33. package/cto/collect.mjs +0 -490
  34. package/cto/current.schema.json +0 -148
  35. package/cto/events.mjs +0 -208
  36. package/cto/hygiene.mjs +0 -320
  37. package/cto/lake-root.mjs +0 -127
  38. package/cto/status.mjs +0 -124
  39. package/hub/lib/cto-env.mjs +0 -1
  40. package/hub/team/notify.mjs +0 -385
  41. package/hub/team/process-cleanup.mjs +0 -386
  42. package/hub/team/routing.mjs +0 -249
  43. package/hub/team/staleState.mjs +0 -403
  44. package/hub/team/worker-signal.mjs +0 -263
  45. package/hub/team/worker-signal.types.d.ts +0 -52
  46. package/hub/workers/codex-mcp.mjs +0 -853
  47. package/scripts/lib/remote-spawn-transfer.mjs +0 -226
@@ -1,226 +0,0 @@
1
- import { existsSync, readFileSync, statSync } from "fs";
2
- import { basename, dirname, isAbsolute, resolve } from "path";
3
-
4
- const URL_LIKE_RE = /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//u;
5
- const WINDOWS_ABS_RE = /^[a-zA-Z]:[\\/]/u;
6
-
7
- function normalizeMarkdownTarget(raw) {
8
- const trimmed = String(raw || "").trim();
9
- const match = /^<?([^>\s]+)>?(?:\s+["'][^"']*["'])?$/u.exec(trimmed);
10
- return match ? match[1] : trimmed;
11
- }
12
-
13
- function sanitizeToken(raw) {
14
- let token = String(raw || "").trim();
15
- if (!token) return "";
16
- token = token
17
- .replace(/^[<(]+/u, "")
18
- .replace(/[)>.,;:!?]+$/u, "")
19
- .trim();
20
- return token;
21
- }
22
-
23
- function isLikelyPathToken(token) {
24
- if (!token || URL_LIKE_RE.test(token)) return false;
25
- if (
26
- token.startsWith("app://") ||
27
- token.startsWith("plugin://") ||
28
- token.startsWith("mention://")
29
- )
30
- return false;
31
- if (token === "~") return false;
32
-
33
- const hasPathSeparator = token.includes("/") || token.includes("\\");
34
- const hasDotPrefix =
35
- token.startsWith("./") || token.startsWith("../") || token.startsWith(".");
36
- const isHomeRelative = token.startsWith("~/") || token.startsWith("~\\");
37
- const isWindowsAbs = WINDOWS_ABS_RE.test(token);
38
- const hasFileLikeSuffix = /\.[a-zA-Z0-9]{1,16}$/u.test(token);
39
-
40
- return (
41
- hasPathSeparator ||
42
- hasDotPrefix ||
43
- isHomeRelative ||
44
- isWindowsAbs ||
45
- hasFileLikeSuffix
46
- );
47
- }
48
-
49
- export function extractExplicitFileTokens(text) {
50
- const content = String(text || "");
51
- const candidates = [];
52
-
53
- for (const match of content.matchAll(/\[[^\]]+\]\(([^)\n]+)\)/gu)) {
54
- candidates.push(normalizeMarkdownTarget(match[1]));
55
- }
56
- for (const match of content.matchAll(/`([^`\n]+)`/gu)) {
57
- candidates.push(match[1]);
58
- }
59
- for (const match of content.matchAll(/"([^"\n]+)"/gu)) {
60
- candidates.push(match[1]);
61
- }
62
- for (const match of content.matchAll(/'([^'\n]+)'/gu)) {
63
- candidates.push(match[1]);
64
- }
65
-
66
- const unique = new Set();
67
- for (const raw of candidates) {
68
- const token = sanitizeToken(raw);
69
- if (!isLikelyPathToken(token)) continue;
70
- unique.add(token);
71
- }
72
-
73
- return Array.from(unique);
74
- }
75
-
76
- function validateTransferFile(filePath, maxBytes) {
77
- if (!existsSync(filePath)) {
78
- throw new Error(`referenced file not found: ${filePath}`);
79
- }
80
- const stats = statSync(filePath);
81
- if (!stats.isFile()) {
82
- throw new Error(`referenced path is not a file: ${filePath}`);
83
- }
84
- if (stats.size > maxBytes) {
85
- throw new Error(
86
- `referenced file too large: ${stats.size} bytes (max ${maxBytes}) for ${filePath}`,
87
- );
88
- }
89
- return stats.size;
90
- }
91
-
92
- function resolveReferencePath(token, handoffAbsPath, cwd) {
93
- if (WINDOWS_ABS_RE.test(token) || isAbsolute(token)) {
94
- return resolve(token);
95
- }
96
-
97
- if (token.startsWith("~/") || token.startsWith("~\\")) {
98
- if (!process.env.HOME && !process.env.USERPROFILE) {
99
- return null;
100
- }
101
- const homeDir = process.env.HOME || process.env.USERPROFILE;
102
- return resolve(homeDir, token.slice(2));
103
- }
104
-
105
- const handoffDir = dirname(handoffAbsPath);
106
- const primary = resolve(handoffDir, token);
107
- if (existsSync(primary)) {
108
- return primary;
109
- }
110
-
111
- const fallback = resolve(cwd, token);
112
- return existsSync(fallback) ? fallback : primary;
113
- }
114
-
115
- function toRemotePath(stageRoot, relativePath) {
116
- const root = String(stageRoot).replace(/\\/gu, "/").replace(/\/+$/u, "");
117
- const rel = String(relativePath).replace(/\\/gu, "/").replace(/^\/+/, "");
118
- return `${root}/${rel}`;
119
- }
120
-
121
- export function buildRemoteTransferPlan(options = {}) {
122
- const {
123
- cwd = process.cwd(),
124
- handoffPath = null,
125
- maxBytes,
126
- remoteStageRoot,
127
- userPrompt = null,
128
- maxReferenceFiles = 32,
129
- } = options;
130
-
131
- if (!handoffPath) {
132
- return {
133
- prompt: userPrompt || "",
134
- replacements: [],
135
- stagedHandoffPath: null,
136
- transfers: [],
137
- };
138
- }
139
-
140
- if (!remoteStageRoot) {
141
- throw new Error("remoteStageRoot is required when handoffPath is provided");
142
- }
143
-
144
- if (!Number.isFinite(maxBytes) || maxBytes <= 0) {
145
- throw new Error("maxBytes must be a positive number");
146
- }
147
-
148
- const absoluteHandoffPath = resolve(cwd, handoffPath);
149
- validateTransferFile(absoluteHandoffPath, maxBytes);
150
- const handoffContent = readFileSync(absoluteHandoffPath, "utf8").trim();
151
-
152
- const stagedHandoffPath = toRemotePath(
153
- remoteStageRoot,
154
- `handoff/${basename(absoluteHandoffPath)}`,
155
- );
156
- const transfers = [
157
- {
158
- localPath: absoluteHandoffPath,
159
- remotePath: stagedHandoffPath,
160
- type: "handoff",
161
- },
162
- ];
163
-
164
- const tokens = extractExplicitFileTokens(handoffContent);
165
- if (tokens.length > maxReferenceFiles) {
166
- throw new Error(
167
- `too many referenced files: ${tokens.length} (max ${maxReferenceFiles})`,
168
- );
169
- }
170
-
171
- const stagedByLocalPath = new Map();
172
- const replacements = [];
173
- let fileIndex = 0;
174
-
175
- for (const token of tokens) {
176
- const resolvedPath = resolveReferencePath(token, absoluteHandoffPath, cwd);
177
- validateTransferFile(resolvedPath, maxBytes);
178
-
179
- if (!stagedByLocalPath.has(resolvedPath)) {
180
- fileIndex += 1;
181
- const stagedPath = toRemotePath(
182
- remoteStageRoot,
183
- `refs/${String(fileIndex).padStart(2, "0")}-${basename(resolvedPath)}`,
184
- );
185
- stagedByLocalPath.set(resolvedPath, stagedPath);
186
- transfers.push({
187
- localPath: resolvedPath,
188
- remotePath: stagedPath,
189
- type: "reference",
190
- });
191
- }
192
-
193
- replacements.push({
194
- token,
195
- stagedPath: stagedByLocalPath.get(resolvedPath),
196
- });
197
- }
198
-
199
- const replacementEntries = Array.from(
200
- replacements
201
- .reduce((map, entry) => map.set(entry.token, entry.stagedPath), new Map())
202
- .entries(),
203
- ).sort((a, b) => b[0].length - a[0].length);
204
-
205
- let rewrittenHandoff = handoffContent;
206
- for (const [token, stagedPath] of replacementEntries) {
207
- rewrittenHandoff = rewrittenHandoff.split(token).join(stagedPath);
208
- }
209
-
210
- const prefix = `Staged handoff file: ${stagedHandoffPath}`;
211
- let prompt = rewrittenHandoff ? `${prefix}\n\n${rewrittenHandoff}` : prefix;
212
-
213
- if (userPrompt) {
214
- prompt = `${prompt}\n\n---\n\n${userPrompt}`;
215
- }
216
-
217
- return {
218
- prompt,
219
- replacements: replacementEntries.map(([token, stagedPath]) => ({
220
- stagedPath,
221
- token,
222
- })),
223
- stagedHandoffPath,
224
- transfers,
225
- };
226
- }