@retasc/cli 1.6.1 → 1.6.3
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 +7 -2
- package/dist/commands/bind.js +34 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Issues live in a persistent, multi-tenant store; agents reach them through one M
|
|
|
8
8
|
The `retasc` CLI signs you in, creates projects, mints agent API keys, and wires the MCP
|
|
9
9
|
server into your agent in a single command.
|
|
10
10
|
|
|
11
|
-
→ [retasc.com](https://retasc.com)
|
|
11
|
+
→ [retasc.com](https://retasc.com) · [Set up your agent](https://retasc.com/connect) · [Quickstart](https://docs.retasc.com/quickstart)
|
|
12
12
|
|
|
13
13
|
## Install
|
|
14
14
|
|
|
@@ -37,7 +37,9 @@ is stored in your home keystore (`~/.retasc/bindings.json`); the folder's `.mcp.
|
|
|
37
37
|
**secret-free marker** (safe to commit). Each workspace is bound to exactly one org/project, so
|
|
38
38
|
an agent can never file issues into the wrong one — the server enforces it by the key. From then
|
|
39
39
|
on your agent calls `next_issue` / `next_batch` to atomically claim the top unblocked,
|
|
40
|
-
prioritized work, and several agents run at once without ever claiming the same issue
|
|
40
|
+
prioritized work, and several agents run at once without ever claiming the same issue — see
|
|
41
|
+
[Running Claude Code agents in parallel](https://retasc.com/guides/claude-code-parallel-agents)
|
|
42
|
+
for that workflow end to end.
|
|
41
43
|
|
|
42
44
|
Run `retasc whoami` (shows this folder's binding) or `retasc doctor` (checks it) any time.
|
|
43
45
|
|
|
@@ -71,6 +73,9 @@ Run `retasc --help` or `retasc <command> --help` for the full set.
|
|
|
71
73
|
## Links
|
|
72
74
|
|
|
73
75
|
- Website — [retasc.com](https://retasc.com)
|
|
76
|
+
- Set up your agent — [retasc.com/connect](https://retasc.com/connect)
|
|
77
|
+
- Docs + quickstart — [docs.retasc.com/quickstart](https://docs.retasc.com/quickstart)
|
|
78
|
+
- Parallel agents guide — [retasc.com/guides/claude-code-parallel-agents](https://retasc.com/guides/claude-code-parallel-agents)
|
|
74
79
|
- Issues — [github.com/Retasc/retasc/issues](https://github.com/Retasc/retasc/issues)
|
|
75
80
|
|
|
76
81
|
## License
|
package/dist/commands/bind.js
CHANGED
|
@@ -11,7 +11,13 @@ function isInteractive() {
|
|
|
11
11
|
async function ask(question) {
|
|
12
12
|
const rl = createInterface({ input: stdin, output: stdout });
|
|
13
13
|
try {
|
|
14
|
-
|
|
14
|
+
// readline's question() NEVER settles when stdin hits EOF (Ctrl-D, or a
|
|
15
|
+
// closed pipe) — it silently drops the callback rather than resolving ""
|
|
16
|
+
// or throwing, so a bare `await` here wedges the CLI with no output and no
|
|
17
|
+
// exit. Race the close event so callers fail fast instead (RTSC-269).
|
|
18
|
+
const closed = new Promise((_, reject) => rl.once("close", () => reject(new Error("input closed"))));
|
|
19
|
+
closed.catch(() => { }); // the normal path closes rl too; that loser rejection is expected
|
|
20
|
+
return (await Promise.race([rl.question(question), closed])).trim();
|
|
15
21
|
}
|
|
16
22
|
finally {
|
|
17
23
|
rl.close();
|
|
@@ -25,18 +31,37 @@ async function confirm(question, assumeYes) {
|
|
|
25
31
|
const a = (await ask(`${question} [y/N] `)).toLowerCase();
|
|
26
32
|
return a === "y" || a === "yes";
|
|
27
33
|
}
|
|
28
|
-
/**
|
|
29
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Pick from a list interactively. Returns the chosen item, or undefined when the
|
|
36
|
+
* user explicitly picks the trailing "create new" option.
|
|
37
|
+
*
|
|
38
|
+
* Invalid input re-prompts rather than falling through: undefined used to mean
|
|
39
|
+
* BOTH "chose create-new" and "typed garbage", so a typo like `1)` silently
|
|
40
|
+
* created a new org/project instead of selecting option 1 (RTSC-269).
|
|
41
|
+
*
|
|
42
|
+
* The answer must be plain digits. Number() alone accepts "0x4"/"4e0"/"+4"/
|
|
43
|
+
* "4.0", which would route those straight to create-new — the same
|
|
44
|
+
* non-canonical-input-hits-the-destructive-branch bug in a new coat.
|
|
45
|
+
*/
|
|
46
|
+
export async function pick(label, items, render, askFn = ask) {
|
|
30
47
|
if (!items.length)
|
|
31
48
|
return undefined;
|
|
32
49
|
console.log(`\n${label}:`);
|
|
33
50
|
items.forEach((it, i) => console.log(` ${i + 1}) ${render(it)}`));
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
const createNew = items.length + 1;
|
|
52
|
+
console.log(` ${createNew}) + create new`);
|
|
53
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
54
|
+
const a = await askFn("Choose a number: ");
|
|
55
|
+
if (/^\d+$/.test(a)) {
|
|
56
|
+
const n = Number(a);
|
|
57
|
+
if (n >= 1 && n <= items.length)
|
|
58
|
+
return items[n - 1];
|
|
59
|
+
if (n === createNew)
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
console.log(`Please enter a number between 1 and ${createNew}.`);
|
|
63
|
+
}
|
|
64
|
+
throw new Error("no valid choice — aborting");
|
|
40
65
|
}
|
|
41
66
|
export async function bindAction(opts) {
|
|
42
67
|
const cfg = loadConfig();
|
package/package.json
CHANGED