@teammates/cli 0.2.5 → 0.2.6

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.
@@ -111,11 +111,12 @@ export class CliProxyAdapter {
111
111
  }
112
112
  async startSession(teammate) {
113
113
  const id = `${this.name}-${teammate.name}-${nextId++}`;
114
- // Create session file inside .teammates/.tmp so sandboxed agents can access it
114
+ // Always ensure sessions directory exists before writing startupMaintenance
115
+ // runs concurrently and may delete empty dirs between calls.
116
+ const tmpBase = join(teammate.cwd ?? process.cwd(), ".teammates", ".tmp");
117
+ const dir = join(tmpBase, "sessions");
118
+ await mkdir(dir, { recursive: true });
115
119
  if (!this.sessionsDir) {
116
- const tmpBase = join(teammate.cwd ?? process.cwd(), ".teammates", ".tmp");
117
- const dir = join(tmpBase, "sessions");
118
- await mkdir(dir, { recursive: true });
119
120
  this.sessionsDir = dir;
120
121
  // Ensure .tmp is gitignored
121
122
  const gitignorePath = join(tmpBase, "..", ".gitignore");
@@ -36,11 +36,12 @@ export class CopilotAdapter {
36
36
  const id = `copilot-${teammate.name}-${nextId++}`;
37
37
  // Ensure the client is running
38
38
  await this.ensureClient(teammate.cwd);
39
- // Create session file inside .teammates/.tmp so the agent can access it
39
+ // Always ensure sessions directory exists before writing startupMaintenance
40
+ // runs concurrently and may delete empty dirs between calls.
41
+ const tmpBase = join(teammate.cwd ?? process.cwd(), ".teammates", ".tmp");
42
+ const dir = join(tmpBase, "sessions");
43
+ await mkdir(dir, { recursive: true });
40
44
  if (!this.sessionsDir) {
41
- const tmpBase = join(teammate.cwd ?? process.cwd(), ".teammates", ".tmp");
42
- const dir = join(tmpBase, "sessions");
43
- await mkdir(dir, { recursive: true });
44
45
  this.sessionsDir = dir;
45
46
  const gitignorePath = join(tmpBase, "..", ".gitignore");
46
47
  const existing = await readFile(gitignorePath, "utf-8").catch(() => "");
package/dist/cli.js CHANGED
@@ -1361,6 +1361,7 @@ Do NOT modify any other teammate's files. Only edit your own SOUL.md and daily l
1361
1361
  weeklyLogs: [],
1362
1362
  ownership: { primary: [], secondary: [] },
1363
1363
  routingKeywords: [],
1364
+ cwd: projectDir,
1364
1365
  };
1365
1366
  const sessionId = await adapter.startSession(tempConfig);
1366
1367
  const spinner = ora({
@@ -1491,6 +1492,7 @@ Do NOT modify any other teammate's files. Only edit your own SOUL.md and daily l
1491
1492
  weeklyLogs: [],
1492
1493
  ownership: { primary: [], secondary: [] },
1493
1494
  routingKeywords: [],
1495
+ cwd: projectDir,
1494
1496
  };
1495
1497
  const sessionId = await adapter.startSession(tempConfig);
1496
1498
  const spinner = ora({
@@ -2274,12 +2276,13 @@ Do NOT modify any other teammate's files. Only edit your own SOUL.md and daily l
2274
2276
  }
2275
2277
  });
2276
2278
  this.chatView.on("link", (url) => {
2279
+ const quoted = JSON.stringify(url);
2277
2280
  const cmd = process.platform === "darwin"
2278
- ? "open"
2281
+ ? `open ${quoted}`
2279
2282
  : process.platform === "win32"
2280
- ? "start"
2281
- : "xdg-open";
2282
- execCb(`${cmd} ${JSON.stringify(url)}`);
2283
+ ? `start "" ${quoted}`
2284
+ : `xdg-open ${quoted}`;
2285
+ execCb(cmd, () => { });
2283
2286
  });
2284
2287
  this.app = new App({
2285
2288
  root: this.chatView,
@@ -3459,10 +3462,13 @@ Issues that can't be resolved unilaterally — they need input from other teamma
3459
3462
  const fullPath = join(dir, entry.name);
3460
3463
  if (entry.isDirectory()) {
3461
3464
  await this.cleanOldTempFiles(fullPath, maxAgeMs);
3462
- // Remove dir if now empty
3463
- const remaining = await readdir(fullPath).catch(() => [""]);
3464
- if (remaining.length === 0)
3465
- await rm(fullPath, { recursive: true }).catch(() => { });
3465
+ // Remove dir if now empty — but skip "sessions" which is structural
3466
+ // and may be recreated concurrently by startSession().
3467
+ if (entry.name !== "sessions") {
3468
+ const remaining = await readdir(fullPath).catch(() => [""]);
3469
+ if (remaining.length === 0)
3470
+ await rm(fullPath, { recursive: true }).catch(() => { });
3471
+ }
3466
3472
  }
3467
3473
  else {
3468
3474
  const info = await stat(fullPath).catch(() => null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teammates/cli",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "Agent-agnostic CLI for teammates. Routes tasks, manages handoffs, and plugs into any coding agent backend.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",