@teammates/cli 0.2.4 → 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.
- package/dist/adapters/cli-proxy.js +5 -4
- package/dist/adapters/copilot.js +5 -4
- package/dist/cli.js +38 -19
- package/dist/onboard.d.ts +1 -0
- package/dist/onboard.js +3 -1
- package/package.json +1 -1
|
@@ -111,11 +111,12 @@ export class CliProxyAdapter {
|
|
|
111
111
|
}
|
|
112
112
|
async startSession(teammate) {
|
|
113
113
|
const id = `${this.name}-${teammate.name}-${nextId++}`;
|
|
114
|
-
//
|
|
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");
|
package/dist/adapters/copilot.js
CHANGED
|
@@ -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
|
-
//
|
|
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({
|
|
@@ -1431,16 +1432,22 @@ Do NOT modify any other teammate's files. Only edit your own SOUL.md and daily l
|
|
|
1431
1432
|
const teammatesDir = join(projectDir, ".teammates");
|
|
1432
1433
|
console.log();
|
|
1433
1434
|
try {
|
|
1434
|
-
const { teammates, files } = await importTeammates(sourceDir, teammatesDir);
|
|
1435
|
-
|
|
1435
|
+
const { teammates, skipped, files } = await importTeammates(sourceDir, teammatesDir);
|
|
1436
|
+
const allTeammates = [...teammates, ...skipped];
|
|
1437
|
+
if (allTeammates.length === 0) {
|
|
1436
1438
|
console.log(chalk.yellow(" No teammates found at ") + chalk.white(sourceDir));
|
|
1437
1439
|
console.log(chalk.gray(" The directory should contain teammate folders (each with a SOUL.md)."));
|
|
1438
1440
|
return;
|
|
1439
1441
|
}
|
|
1440
|
-
|
|
1441
|
-
chalk.
|
|
1442
|
-
|
|
1443
|
-
|
|
1442
|
+
if (teammates.length > 0) {
|
|
1443
|
+
console.log(chalk.green(" ✔") +
|
|
1444
|
+
chalk.white(` Imported ${teammates.length} teammate${teammates.length > 1 ? "s" : ""}: `) +
|
|
1445
|
+
chalk.cyan(teammates.join(", ")));
|
|
1446
|
+
console.log(chalk.gray(` (${files.length} files copied)`));
|
|
1447
|
+
}
|
|
1448
|
+
if (skipped.length > 0) {
|
|
1449
|
+
console.log(chalk.gray(` ${skipped.length} already present: ${skipped.join(", ")} (will re-adapt)`));
|
|
1450
|
+
}
|
|
1444
1451
|
console.log();
|
|
1445
1452
|
// Copy framework files so the agent has TEMPLATE.md etc. available
|
|
1446
1453
|
await copyTemplateFiles(teammatesDir);
|
|
@@ -1452,7 +1459,7 @@ Do NOT modify any other teammate's files. Only edit your own SOUL.md and daily l
|
|
|
1452
1459
|
console.log();
|
|
1453
1460
|
const adapt = await this.askChoice("Adapt now? (y/n): ", ["y", "n"]);
|
|
1454
1461
|
if (adapt === "y") {
|
|
1455
|
-
await this.runAdaptationAgent(this.adapter, projectDir,
|
|
1462
|
+
await this.runAdaptationAgent(this.adapter, projectDir, allTeammates, sourceDir);
|
|
1456
1463
|
}
|
|
1457
1464
|
else {
|
|
1458
1465
|
console.log(chalk.gray(" Skipped adaptation. Run /init to adapt later."));
|
|
@@ -1485,6 +1492,7 @@ Do NOT modify any other teammate's files. Only edit your own SOUL.md and daily l
|
|
|
1485
1492
|
weeklyLogs: [],
|
|
1486
1493
|
ownership: { primary: [], secondary: [] },
|
|
1487
1494
|
routingKeywords: [],
|
|
1495
|
+
cwd: projectDir,
|
|
1488
1496
|
};
|
|
1489
1497
|
const sessionId = await adapter.startSession(tempConfig);
|
|
1490
1498
|
const spinner = ora({
|
|
@@ -2268,12 +2276,13 @@ Do NOT modify any other teammate's files. Only edit your own SOUL.md and daily l
|
|
|
2268
2276
|
}
|
|
2269
2277
|
});
|
|
2270
2278
|
this.chatView.on("link", (url) => {
|
|
2279
|
+
const quoted = JSON.stringify(url);
|
|
2271
2280
|
const cmd = process.platform === "darwin"
|
|
2272
|
-
?
|
|
2281
|
+
? `open ${quoted}`
|
|
2273
2282
|
: process.platform === "win32"
|
|
2274
|
-
?
|
|
2275
|
-
:
|
|
2276
|
-
execCb(
|
|
2283
|
+
? `start "" ${quoted}`
|
|
2284
|
+
: `xdg-open ${quoted}`;
|
|
2285
|
+
execCb(cmd, () => { });
|
|
2277
2286
|
});
|
|
2278
2287
|
this.app = new App({
|
|
2279
2288
|
root: this.chatView,
|
|
@@ -3011,18 +3020,25 @@ Do NOT modify any other teammate's files. Only edit your own SOUL.md and daily l
|
|
|
3011
3020
|
sourceDir = resolved;
|
|
3012
3021
|
}
|
|
3013
3022
|
try {
|
|
3014
|
-
const { teammates, files } = await importTeammates(sourceDir, teammatesDir);
|
|
3015
|
-
|
|
3023
|
+
const { teammates, skipped, files } = await importTeammates(sourceDir, teammatesDir);
|
|
3024
|
+
// Combine newly imported + already existing for adaptation
|
|
3025
|
+
const allTeammates = [...teammates, ...skipped];
|
|
3026
|
+
if (allTeammates.length === 0) {
|
|
3016
3027
|
this.feedLine(tp.warning(` No teammates found at ${sourceDir}`));
|
|
3017
3028
|
this.refreshView();
|
|
3018
3029
|
return;
|
|
3019
3030
|
}
|
|
3020
|
-
|
|
3031
|
+
if (teammates.length > 0) {
|
|
3032
|
+
this.feedLine(tp.success(` Imported ${teammates.length} teammate${teammates.length > 1 ? "s" : ""}: ${teammates.join(", ")} (${files.length} files)`));
|
|
3033
|
+
}
|
|
3034
|
+
if (skipped.length > 0) {
|
|
3035
|
+
this.feedLine(tp.muted(` ${skipped.length} already present: ${skipped.join(", ")} (will re-adapt)`));
|
|
3036
|
+
}
|
|
3021
3037
|
// Copy framework files so the agent has TEMPLATE.md etc. available
|
|
3022
3038
|
await copyTemplateFiles(teammatesDir);
|
|
3023
3039
|
// Queue a single adaptation task that handles all teammates
|
|
3024
3040
|
this.feedLine(tp.muted(` Queuing ${this.adapterName} to scan this project and adapt the team...`));
|
|
3025
|
-
const prompt = await buildImportAdaptationPrompt(teammatesDir,
|
|
3041
|
+
const prompt = await buildImportAdaptationPrompt(teammatesDir, allTeammates, sourceDir);
|
|
3026
3042
|
this.taskQueue.push({
|
|
3027
3043
|
type: "agent",
|
|
3028
3044
|
teammate: this.adapterName,
|
|
@@ -3446,10 +3462,13 @@ Issues that can't be resolved unilaterally — they need input from other teamma
|
|
|
3446
3462
|
const fullPath = join(dir, entry.name);
|
|
3447
3463
|
if (entry.isDirectory()) {
|
|
3448
3464
|
await this.cleanOldTempFiles(fullPath, maxAgeMs);
|
|
3449
|
-
// Remove dir if now empty
|
|
3450
|
-
|
|
3451
|
-
if (
|
|
3452
|
-
await
|
|
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
|
+
}
|
|
3453
3472
|
}
|
|
3454
3473
|
else {
|
|
3455
3474
|
const info = await stat(fullPath).catch(() => null);
|
package/dist/onboard.d.ts
CHANGED
package/dist/onboard.js
CHANGED
|
@@ -129,6 +129,7 @@ export async function importTeammates(sourceDir, targetDir) {
|
|
|
129
129
|
}
|
|
130
130
|
await mkdir(targetDir, { recursive: true });
|
|
131
131
|
const teammates = [];
|
|
132
|
+
const skipped = [];
|
|
132
133
|
const files = [];
|
|
133
134
|
const entries = await readdir(sourceDir, { withFileTypes: true });
|
|
134
135
|
for (const entry of entries) {
|
|
@@ -140,6 +141,7 @@ export async function importTeammates(sourceDir, targetDir) {
|
|
|
140
141
|
// Skip if teammate already exists in target
|
|
141
142
|
try {
|
|
142
143
|
await stat(destPath);
|
|
144
|
+
skipped.push(entry.name);
|
|
143
145
|
continue;
|
|
144
146
|
}
|
|
145
147
|
catch {
|
|
@@ -185,7 +187,7 @@ export async function importTeammates(sourceDir, targetDir) {
|
|
|
185
187
|
await writeFile(gitignoreDest, "USER.md\n.*/\n", "utf-8");
|
|
186
188
|
files.push(".gitignore");
|
|
187
189
|
}
|
|
188
|
-
return { teammates, files };
|
|
190
|
+
return { teammates, skipped, files };
|
|
189
191
|
}
|
|
190
192
|
/**
|
|
191
193
|
* Build an import-adaptation prompt that runs as a single non-interactive agent session.
|
package/package.json
CHANGED