teamshift 0.1.1 → 0.1.2
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 +10 -6
- package/dist/api.js +3 -0
- package/dist/cli.js +17 -10
- package/dist/run.js +30 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,9 +11,11 @@ npx teamshift add code-audit-swarm # adds it to your workspace
|
|
|
11
11
|
npx teamshift run <team-id> "review services/api for auth mistakes"
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
`teamshift teams` lists
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
`teamshift teams` lists callable teams, including teams you built yourself in the
|
|
15
|
+
portal; `teamshift agents` lists callable individual agents. Keeping the two
|
|
16
|
+
inventories separate prevents a large internal agent library from burying the
|
|
17
|
+
teams a customer actually runs. `add` is idempotent — running it twice will not
|
|
18
|
+
duplicate a team or overwrite edits you have made to it.
|
|
17
19
|
|
|
18
20
|
## Parallel fan-out
|
|
19
21
|
|
|
@@ -36,7 +38,9 @@ completed $1.20 4.0s find dead code
|
|
|
36
38
|
```
|
|
37
39
|
|
|
38
40
|
`--file prompts.txt` reads one prompt per line. Concurrency is bounded (default
|
|
39
|
-
5) so a large batch does not trip the API's write rate limit.
|
|
41
|
+
5) so a large batch does not trip the API's write rate limit. Completed runs
|
|
42
|
+
print their scrubbed deliverable after the status table; `--json` includes it as
|
|
43
|
+
the outcome's `output` field.
|
|
40
44
|
|
|
41
45
|
## Already using Claude Code or Codex?
|
|
42
46
|
|
|
@@ -54,8 +58,8 @@ agent, with no second CLI to learn. Both install commands are in the portal unde
|
|
|
54
58
|
|
|
55
59
|
| Code | Meaning |
|
|
56
60
|
| --- | --- |
|
|
57
|
-
| `0` | every run
|
|
58
|
-
| `1` | usage error,
|
|
61
|
+
| `0` | every run completed and returned its deliverable |
|
|
62
|
+
| `1` | usage/auth error, timeout, failed run, or missing deliverable |
|
|
59
63
|
| `2` | out of credit — add credits and rerun |
|
|
60
64
|
|
|
61
65
|
## Releasing
|
package/dist/api.js
CHANGED
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,8 @@ const USAGE = `teamshift — run agent teams from your terminal
|
|
|
10
10
|
teamshift whoami Show the active key and endpoint
|
|
11
11
|
teamshift catalog Browse prebuilt teams you can add
|
|
12
12
|
teamshift add <catalog-id> Add a prebuilt team to your workspace
|
|
13
|
-
teamshift teams List callable teams
|
|
13
|
+
teamshift teams List callable teams
|
|
14
|
+
teamshift agents List callable agents
|
|
14
15
|
teamshift run <id> "<prompt>" Run one team, wait, print status and charge
|
|
15
16
|
teamshift run <id> -p "a" -p "b" Fan out prompts in parallel
|
|
16
17
|
teamshift run <id> --file prompts.txt One prompt per line, run in parallel
|
|
@@ -71,18 +72,16 @@ async function login() {
|
|
|
71
72
|
rl.close();
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
|
-
async function listCallable(json) {
|
|
75
|
+
async function listCallable(kind, json) {
|
|
75
76
|
const payload = await requireClient().interop();
|
|
77
|
+
const items = kind === 'team' ? payload.teams : payload.agents;
|
|
76
78
|
if (json) {
|
|
77
|
-
console.log(JSON.stringify(
|
|
79
|
+
console.log(JSON.stringify(items, null, 2));
|
|
78
80
|
return;
|
|
79
81
|
}
|
|
80
|
-
const rows = [
|
|
81
|
-
...payload.teams.map((item) => ['team', item.id, item.name]),
|
|
82
|
-
...payload.agents.map((item) => ['agent', item.id, item.name]),
|
|
83
|
-
];
|
|
82
|
+
const rows = items.map((item) => [kind, item.id, item.name]);
|
|
84
83
|
if (rows.length === 0) {
|
|
85
|
-
console.log(
|
|
84
|
+
console.log(`No callable ${kind}s yet${kind === 'team' ? ' — add one with `teamshift add <id>`.' : '.'}`);
|
|
86
85
|
return;
|
|
87
86
|
}
|
|
88
87
|
console.log(table(['KIND', 'ID', 'NAME'], rows));
|
|
@@ -152,9 +151,15 @@ async function run(args) {
|
|
|
152
151
|
const serial = outcomes.reduce((sum, outcome) => sum + outcome.elapsedMs, 0);
|
|
153
152
|
console.log(`\n${outcomes.length} run(s) · ${money(total)} total · ${duration(Date.now() - startedAt)} wall clock ` +
|
|
154
153
|
`(${duration(serial)} if run one at a time)`);
|
|
154
|
+
for (const outcome of outcomes) {
|
|
155
|
+
if (outcome.output === null || outcome.output === undefined)
|
|
156
|
+
continue;
|
|
157
|
+
const output = typeof outcome.output === 'string' ? outcome.output : JSON.stringify(outcome.output, null, 2);
|
|
158
|
+
console.log(`\n${outcomes.length > 1 ? `[${outcome.prompt}]\n` : ''}${output}`);
|
|
159
|
+
}
|
|
155
160
|
const failed = outcomes.filter((outcome) => outcome.error).length;
|
|
156
161
|
if (failed > 0) {
|
|
157
|
-
console.log(`${failed} run(s)
|
|
162
|
+
console.log(`${failed} run(s) need attention — inspect the status above before retrying.`);
|
|
158
163
|
process.exitCode = 1;
|
|
159
164
|
}
|
|
160
165
|
}
|
|
@@ -186,7 +191,9 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
186
191
|
case 'add':
|
|
187
192
|
return await addFromCatalog(args);
|
|
188
193
|
case 'teams':
|
|
189
|
-
return await listCallable(args.json);
|
|
194
|
+
return await listCallable('team', args.json);
|
|
195
|
+
case 'agents':
|
|
196
|
+
return await listCallable('agent', args.json);
|
|
190
197
|
case 'run':
|
|
191
198
|
return await run(args);
|
|
192
199
|
default:
|
package/dist/run.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { isTerminal } from './format.js';
|
|
2
2
|
const defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
3
|
+
export class RunPollingTimeoutError extends Error {
|
|
4
|
+
runId;
|
|
5
|
+
latest;
|
|
6
|
+
constructor(runId, latest) {
|
|
7
|
+
super(`run ${runId} did not finish before the polling timeout (last status: ${latest.status ?? 'unknown'})`);
|
|
8
|
+
this.runId = runId;
|
|
9
|
+
this.latest = latest;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
3
12
|
/** Poll one run to a terminal status, or give up at the timeout. */
|
|
4
13
|
export async function waitForRun(client, runId, options = {}) {
|
|
5
14
|
const { intervalMs = 2000, timeoutMs = 900_000, now = Date.now, sleep = defaultSleep } = options;
|
|
@@ -7,7 +16,7 @@ export async function waitForRun(client, runId, options = {}) {
|
|
|
7
16
|
let latest = await client.getRun(runId);
|
|
8
17
|
while (!isTerminal(latest.status)) {
|
|
9
18
|
if (now() - startedAt >= timeoutMs)
|
|
10
|
-
|
|
19
|
+
throw new RunPollingTimeoutError(runId, latest);
|
|
11
20
|
await sleep(intervalMs);
|
|
12
21
|
latest = await client.getRun(runId);
|
|
13
22
|
}
|
|
@@ -34,22 +43,39 @@ export async function runBatch(client, kind, id, prompts, options = {}) {
|
|
|
34
43
|
if (prompt === undefined)
|
|
35
44
|
return;
|
|
36
45
|
const startedAt = now();
|
|
46
|
+
let runId = null;
|
|
37
47
|
try {
|
|
38
|
-
|
|
48
|
+
runId = await client.startRun(kind, id, prompt);
|
|
39
49
|
const summary = await waitForRun(client, runId, { ...pollOptions, now });
|
|
50
|
+
let output = null;
|
|
51
|
+
let resultError;
|
|
52
|
+
if (summary.status === 'completed') {
|
|
53
|
+
try {
|
|
54
|
+
const result = await client.getRunResult(runId);
|
|
55
|
+
output = result.text ?? result.document;
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
resultError = `result unavailable: ${error instanceof Error ? error.message : String(error)}`;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
resultError = `run ended with status ${summary.status ?? 'unknown'}`;
|
|
63
|
+
}
|
|
40
64
|
results[index] = {
|
|
41
65
|
prompt,
|
|
42
66
|
runId,
|
|
43
67
|
status: String(summary.status ?? 'unknown'),
|
|
44
68
|
costUsd: summary.cost_estimate_usd ?? null,
|
|
45
69
|
elapsedMs: now() - startedAt,
|
|
70
|
+
output,
|
|
71
|
+
...(resultError ? { error: resultError } : {}),
|
|
46
72
|
};
|
|
47
73
|
}
|
|
48
74
|
catch (error) {
|
|
49
75
|
results[index] = {
|
|
50
76
|
prompt,
|
|
51
|
-
runId
|
|
52
|
-
status: 'dispatch_failed',
|
|
77
|
+
runId,
|
|
78
|
+
status: error instanceof RunPollingTimeoutError ? 'poll_timeout' : 'dispatch_failed',
|
|
53
79
|
costUsd: null,
|
|
54
80
|
elapsedMs: now() - startedAt,
|
|
55
81
|
error: error instanceof Error ? error.message : String(error),
|
package/package.json
CHANGED