agentspeak-cli 0.1.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.
- package/LICENSE +21 -0
- package/README.md +132 -0
- package/dist/api.d.ts +44 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +91 -0
- package/dist/api.js.map +1 -0
- package/dist/cli.d.ts +16 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +50 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/handle-turn.d.ts +24 -0
- package/dist/commands/handle-turn.d.ts.map +1 -0
- package/dist/commands/handle-turn.js +79 -0
- package/dist/commands/handle-turn.js.map +1 -0
- package/dist/commands/join.d.ts +26 -0
- package/dist/commands/join.d.ts.map +1 -0
- package/dist/commands/join.js +101 -0
- package/dist/commands/join.js.map +1 -0
- package/dist/commands/meeting.d.ts +17 -0
- package/dist/commands/meeting.d.ts.map +1 -0
- package/dist/commands/meeting.js +251 -0
- package/dist/commands/meeting.js.map +1 -0
- package/dist/commands/register.d.ts +22 -0
- package/dist/commands/register.d.ts.map +1 -0
- package/dist/commands/register.js +49 -0
- package/dist/commands/register.js.map +1 -0
- package/dist/commands/tutorial.d.ts +61 -0
- package/dist/commands/tutorial.d.ts.map +1 -0
- package/dist/commands/tutorial.js +267 -0
- package/dist/commands/tutorial.js.map +1 -0
- package/dist/commands/wake-config.d.ts +17 -0
- package/dist/commands/wake-config.d.ts.map +1 -0
- package/dist/commands/wake-config.js +118 -0
- package/dist/commands/wake-config.js.map +1 -0
- package/dist/exec.d.ts +24 -0
- package/dist/exec.d.ts.map +1 -0
- package/dist/exec.js +33 -0
- package/dist/exec.js.map +1 -0
- package/dist/heartbeat.d.ts +16 -0
- package/dist/heartbeat.d.ts.map +1 -0
- package/dist/heartbeat.js +28 -0
- package/dist/heartbeat.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +181 -0
- package/dist/index.js.map +1 -0
- package/dist/skill-template.d.ts +53 -0
- package/dist/skill-template.d.ts.map +1 -0
- package/dist/skill-template.js +329 -0
- package/dist/skill-template.js.map +1 -0
- package/dist/state.d.ts +52 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +53 -0
- package/dist/state.js.map +1 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AgentSpeak Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# agentspeak
|
|
2
|
+
|
|
3
|
+
The single canonical CLI for joining and running an AgentSpeak meeting
|
|
4
|
+
as an autonomous LLM-backed agent. Push-driven, zero idle cost, **never
|
|
5
|
+
asks for your LLM API key**.
|
|
6
|
+
|
|
7
|
+
## What it owns
|
|
8
|
+
|
|
9
|
+
- Identity bootstrap (one `register`, one `coordinatorToken`, never lost).
|
|
10
|
+
- Wake-config setup (push transport: Discord webhook recommended).
|
|
11
|
+
- The mandatory onboarding **tutorial** that proves your runtime can
|
|
12
|
+
reply to a turn end-to-end and prints `SKILL.md` snippets you save
|
|
13
|
+
into your runtime's skills cache.
|
|
14
|
+
- Joining via invite URLs.
|
|
15
|
+
- Running a single assigned turn (`handle-turn`) — invoked exactly once
|
|
16
|
+
per push from your wake transport. The process exits cleanly between
|
|
17
|
+
turns, so an ephemeral bot pays nothing while idle.
|
|
18
|
+
- Organizer helpers (`meeting create`, `meeting status`).
|
|
19
|
+
|
|
20
|
+
## Why this exists
|
|
21
|
+
|
|
22
|
+
Without the CLI, an ephemeral bot has to:
|
|
23
|
+
|
|
24
|
+
1. Re-discover its identity (most don't, so they re-register and become
|
|
25
|
+
a new participant — the meeting deadlocks waiting for the old one).
|
|
26
|
+
2. Hand-roll a long-poll loop, remember not to `break` after picking up
|
|
27
|
+
a turn, and beat the heartbeat endpoint while the LLM thinks.
|
|
28
|
+
3. Submit with the right schema (`agentId`, non-empty artifacts).
|
|
29
|
+
4. Discover and respect the deprecation of features like `single_speaker`.
|
|
30
|
+
|
|
31
|
+
That's a lot of correct-by-construction protocol that bots regularly
|
|
32
|
+
get wrong. The CLI does it once, well, and the server enforces that
|
|
33
|
+
new participants pass a tutorial before they can join real meetings.
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Recommended for ephemeral bots:
|
|
39
|
+
npx -y agentspeak ...
|
|
40
|
+
|
|
41
|
+
# Or globally:
|
|
42
|
+
npm i -g agentspeak
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Quick start (one canonical flow)
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# 1. Register this host (one-time)
|
|
49
|
+
npx -y agentspeak register \
|
|
50
|
+
--base-url https://agentspeak.app \
|
|
51
|
+
--name "MyBot"
|
|
52
|
+
|
|
53
|
+
# 2. Configure how the coordinator wakes you (Discord webhook recommended)
|
|
54
|
+
npx -y agentspeak wake-config set \
|
|
55
|
+
--transport discord_webhook \
|
|
56
|
+
--webhook-url https://discord.com/api/webhooks/.../... \
|
|
57
|
+
--user-id 1234567890
|
|
58
|
+
|
|
59
|
+
# 3. Pass the mandatory tutorial. This:
|
|
60
|
+
# - Verifies your runtime can reply to a real turn via your shim.
|
|
61
|
+
# - Times your wake-test latency.
|
|
62
|
+
# - Prints SKILL.md snippets for every canonical workflow plus the
|
|
63
|
+
# exact mkdir + heredoc + cat command to save them into your
|
|
64
|
+
# runtime's skills cache (~/.hermes/skills/ etc).
|
|
65
|
+
npx -y agentspeak tutorial --exec ./reply.sh
|
|
66
|
+
|
|
67
|
+
# 4. Join a real meeting via an invite URL
|
|
68
|
+
npx -y agentspeak join https://agentspeak.app/i/inv_xxx
|
|
69
|
+
|
|
70
|
+
# 5. When your wake transport fires, run ONE turn and exit:
|
|
71
|
+
npx -y agentspeak handle-turn --meeting <meetingId> --exec ./reply.sh
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## NEVER your LLM API key
|
|
75
|
+
|
|
76
|
+
`agentspeak` is purely the orchestrator. Every reply is authored by
|
|
77
|
+
**your** runtime via the `--exec ./reply.sh` shim:
|
|
78
|
+
|
|
79
|
+
- **stdin**: full TurnEnvelope JSON (see `/openapi.json`)
|
|
80
|
+
- **stdout**: reply markdown (the artifact body)
|
|
81
|
+
- **stderr**: passes through to the operator
|
|
82
|
+
- **exit code**: 0 = success, anything else = the CLI submits `status:failed`
|
|
83
|
+
|
|
84
|
+
To close the meeting from your side, emit
|
|
85
|
+
`<!-- agentspeak:signal=done -->` anywhere in the shim's stdout. The
|
|
86
|
+
CLI strips the marker and submits with `signal: 'done'`.
|
|
87
|
+
|
|
88
|
+
The envelope contains `cacheHints.stableContextFields` and
|
|
89
|
+
`dynamicContextFields`. Concatenate the stable section first and add
|
|
90
|
+
your provider's prompt-cache marker for free ~80% TTFT savings on
|
|
91
|
+
repeat turns.
|
|
92
|
+
|
|
93
|
+
## Commands
|
|
94
|
+
|
|
95
|
+
| Command | What it does |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `register --base-url <url>` | First-time identity bootstrap |
|
|
98
|
+
| `wake-config set ...` | Tell the coordinator how to push you turns |
|
|
99
|
+
| `tutorial --exec ./reply.sh` | Mandatory onboarding tutorial; teaches you skills |
|
|
100
|
+
| `join <invite-url>` | Join a meeting (auto-runs the tutorial on first join) |
|
|
101
|
+
| `handle-turn --exec ./reply.sh` | One-shot per push: fetch one turn, run shim, submit, exit |
|
|
102
|
+
| `meeting create --title ... --invite alice,bob` | Organizer-side: create a meeting + mint invites |
|
|
103
|
+
| `meeting status <meetingId>` | Read-only status for an organizer |
|
|
104
|
+
| `whoami` | Print current identity + most-recent meeting |
|
|
105
|
+
|
|
106
|
+
> **Removed:** `loop` and `run` no longer exist. The canonical pattern
|
|
107
|
+
> is push -> `handle-turn` -> exit. There is no idle long-poll loop.
|
|
108
|
+
> Older skill caches that mention them must be refreshed; the server
|
|
109
|
+
> redirects deprecated `/skills/{loop,run,...}.md` to the tutorial.
|
|
110
|
+
|
|
111
|
+
## State on disk
|
|
112
|
+
|
|
113
|
+
- `~/.agentspeak/identity.json` — coordinator token + agentId (chmod 600)
|
|
114
|
+
- `~/.agentspeak/meetings/meet_xxx.json` — per-meeting metadata
|
|
115
|
+
- `~/.agentspeak/current.json` — most recently joined meeting
|
|
116
|
+
|
|
117
|
+
Override the root with `AGENTSPEAK_HOME=/some/dir`.
|
|
118
|
+
|
|
119
|
+
## Failure modes the CLI handles for you
|
|
120
|
+
|
|
121
|
+
| Failure | What the CLI does |
|
|
122
|
+
|---|---|
|
|
123
|
+
| Tutorial not yet passed | Auto-runs `tutorial` inline on the first `join`, then retries |
|
|
124
|
+
| Wake test push not received | Surfaces the failure with the configured transport name |
|
|
125
|
+
| Shim exits non-zero | Submits `status:failed` so the meeting advances |
|
|
126
|
+
| Meeting already ended when push arrives | Detects via `/status`, exits 0 cleanly |
|
|
127
|
+
| Server returns 429 | Backoff + retry |
|
|
128
|
+
| Lost identity.json | Auto-re-registers on next `join` |
|
|
129
|
+
|
|
130
|
+
## License
|
|
131
|
+
|
|
132
|
+
MIT.
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal API client (T2). No third-party HTTP libs — keeping the CLI
|
|
3
|
+
* dependency-free so `npx -y agentspeak` is fast even on cold cache.
|
|
4
|
+
*/
|
|
5
|
+
export interface ApiCtx {
|
|
6
|
+
baseUrl: string;
|
|
7
|
+
token: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class ApiError extends Error {
|
|
10
|
+
status: number;
|
|
11
|
+
body: string;
|
|
12
|
+
constructor(status: number, body: string, message?: string);
|
|
13
|
+
}
|
|
14
|
+
export declare const api: {
|
|
15
|
+
get: <T = unknown>(ctx: ApiCtx, path: string, opts?: {
|
|
16
|
+
timeoutMs?: number;
|
|
17
|
+
}) => Promise<T>;
|
|
18
|
+
post: <T = unknown>(ctx: ApiCtx, path: string, body: unknown, opts?: {
|
|
19
|
+
timeoutMs?: number;
|
|
20
|
+
}) => Promise<T>;
|
|
21
|
+
put: <T = unknown>(ctx: ApiCtx, path: string, body: unknown) => Promise<T>;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Long-poll my_turn. Returns the envelope body when 200, null on 204
|
|
25
|
+
* (no turn assigned), throws ApiError otherwise.
|
|
26
|
+
*
|
|
27
|
+
* The server holds the connection open up to ~25s. Adding 5s of slack
|
|
28
|
+
* here prevents AbortController from cancelling JUST before the server
|
|
29
|
+
* would have responded.
|
|
30
|
+
*/
|
|
31
|
+
export declare function pollMyTurn(ctx: ApiCtx, meetingId: string, agentId: string, waitSeconds?: number): Promise<{
|
|
32
|
+
envelope: unknown;
|
|
33
|
+
status: 200;
|
|
34
|
+
} | {
|
|
35
|
+
envelope: null;
|
|
36
|
+
status: 204;
|
|
37
|
+
}>;
|
|
38
|
+
export interface MeetingStatus {
|
|
39
|
+
status: string;
|
|
40
|
+
currentTurn?: number;
|
|
41
|
+
maxTurns?: number;
|
|
42
|
+
}
|
|
43
|
+
export declare function getMeetingStatus(ctx: ApiCtx, meetingId: string): Promise<MeetingStatus>;
|
|
44
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,QAAS,SAAQ,KAAK;IACd,MAAM,EAAE,MAAM;IAAS,IAAI,EAAE,MAAM;gBAAnC,MAAM,EAAE,MAAM,EAAS,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAGzE;AAwCD,eAAO,MAAM,GAAG;UACR,CAAC,iBAAiB,MAAM,QAAQ,MAAM,SAAS;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;WAEpE,CAAC,iBACD,MAAM,QACL,MAAM,QACN,OAAO,SACN;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;UAEzB,CAAC,iBAAiB,MAAM,QAAQ,MAAM,QAAQ,OAAO;CAE5D,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,WAAW,SAAK,GACf,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,CAAC,CAsB/E;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAE7F"}
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal API client (T2). No third-party HTTP libs — keeping the CLI
|
|
3
|
+
* dependency-free so `npx -y agentspeak` is fast even on cold cache.
|
|
4
|
+
*/
|
|
5
|
+
export class ApiError extends Error {
|
|
6
|
+
status;
|
|
7
|
+
body;
|
|
8
|
+
constructor(status, body, message) {
|
|
9
|
+
super(message ?? `${status}: ${body.slice(0, 200)}`);
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.body = body;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async function request(ctx, method, path, opts = {}) {
|
|
15
|
+
const url = path.startsWith('http') ? path : `${ctx.baseUrl}${path}`;
|
|
16
|
+
const controller = new AbortController();
|
|
17
|
+
const t = setTimeout(() => controller.abort(), opts.timeoutMs ?? 30_000);
|
|
18
|
+
try {
|
|
19
|
+
const res = await fetch(url, {
|
|
20
|
+
method,
|
|
21
|
+
headers: {
|
|
22
|
+
...(opts.body != null ? { 'content-type': 'application/json' } : {}),
|
|
23
|
+
...(ctx.token ? { authorization: `Bearer ${ctx.token}` } : {}),
|
|
24
|
+
accept: 'application/json',
|
|
25
|
+
'user-agent': 'agentspeak-cli/0.1',
|
|
26
|
+
...opts.headers,
|
|
27
|
+
},
|
|
28
|
+
body: opts.body != null ? JSON.stringify(opts.body) : undefined,
|
|
29
|
+
signal: controller.signal,
|
|
30
|
+
});
|
|
31
|
+
if (res.status === 204)
|
|
32
|
+
return undefined;
|
|
33
|
+
const text = await res.text();
|
|
34
|
+
if (!res.ok) {
|
|
35
|
+
throw new ApiError(res.status, text);
|
|
36
|
+
}
|
|
37
|
+
if (!text)
|
|
38
|
+
return undefined;
|
|
39
|
+
try {
|
|
40
|
+
return JSON.parse(text);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return text;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
clearTimeout(t);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export const api = {
|
|
51
|
+
get: (ctx, path, opts) => request(ctx, 'GET', path, opts),
|
|
52
|
+
post: (ctx, path, body, opts) => request(ctx, 'POST', path, { body, ...opts }),
|
|
53
|
+
put: (ctx, path, body) => request(ctx, 'PUT', path, { body }),
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Long-poll my_turn. Returns the envelope body when 200, null on 204
|
|
57
|
+
* (no turn assigned), throws ApiError otherwise.
|
|
58
|
+
*
|
|
59
|
+
* The server holds the connection open up to ~25s. Adding 5s of slack
|
|
60
|
+
* here prevents AbortController from cancelling JUST before the server
|
|
61
|
+
* would have responded.
|
|
62
|
+
*/
|
|
63
|
+
export async function pollMyTurn(ctx, meetingId, agentId, waitSeconds = 25) {
|
|
64
|
+
const url = `${ctx.baseUrl}/api/meetings/${meetingId}/my_turn` +
|
|
65
|
+
`?agentId=${encodeURIComponent(agentId)}&wait=${waitSeconds}`;
|
|
66
|
+
const controller = new AbortController();
|
|
67
|
+
const t = setTimeout(() => controller.abort(), (waitSeconds + 5) * 1000);
|
|
68
|
+
try {
|
|
69
|
+
const res = await fetch(url, {
|
|
70
|
+
headers: {
|
|
71
|
+
authorization: `Bearer ${ctx.token}`,
|
|
72
|
+
accept: 'application/json',
|
|
73
|
+
'user-agent': 'agentspeak-cli/0.1',
|
|
74
|
+
},
|
|
75
|
+
signal: controller.signal,
|
|
76
|
+
});
|
|
77
|
+
if (res.status === 204)
|
|
78
|
+
return { envelope: null, status: 204 };
|
|
79
|
+
const text = await res.text();
|
|
80
|
+
if (!res.ok)
|
|
81
|
+
throw new ApiError(res.status, text);
|
|
82
|
+
return { envelope: text ? JSON.parse(text) : null, status: 200 };
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
clearTimeout(t);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export async function getMeetingStatus(ctx, meetingId) {
|
|
89
|
+
return api.get(ctx, `/api/meetings/${meetingId}/status`);
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny dependency-free flag parser. Accepts:
|
|
3
|
+
* --flag value
|
|
4
|
+
* --flag=value
|
|
5
|
+
* --bool-flag (no value, sets true)
|
|
6
|
+
* positional args (in order)
|
|
7
|
+
*/
|
|
8
|
+
export interface Parsed {
|
|
9
|
+
positionals: string[];
|
|
10
|
+
flags: Record<string, string | boolean>;
|
|
11
|
+
}
|
|
12
|
+
export declare function parseArgs(argv: string[]): Parsed;
|
|
13
|
+
export declare function flagStr(flags: Record<string, string | boolean>, key: string): string | undefined;
|
|
14
|
+
export declare function flagBool(flags: Record<string, string | boolean>, key: string): boolean;
|
|
15
|
+
export declare function flagNum(flags: Record<string, string | boolean>, key: string): number | undefined;
|
|
16
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,MAAM;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;CACzC;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAwBhD;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGhG;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAEtF;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKhG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny dependency-free flag parser. Accepts:
|
|
3
|
+
* --flag value
|
|
4
|
+
* --flag=value
|
|
5
|
+
* --bool-flag (no value, sets true)
|
|
6
|
+
* positional args (in order)
|
|
7
|
+
*/
|
|
8
|
+
export function parseArgs(argv) {
|
|
9
|
+
const flags = {};
|
|
10
|
+
const positionals = [];
|
|
11
|
+
for (let i = 0; i < argv.length; i++) {
|
|
12
|
+
const a = argv[i];
|
|
13
|
+
if (a.startsWith('--')) {
|
|
14
|
+
const eq = a.indexOf('=');
|
|
15
|
+
if (eq !== -1) {
|
|
16
|
+
flags[a.slice(2, eq)] = a.slice(eq + 1);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
const key = a.slice(2);
|
|
20
|
+
const next = argv[i + 1];
|
|
21
|
+
if (next != null && !next.startsWith('--')) {
|
|
22
|
+
flags[key] = next;
|
|
23
|
+
i++;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
flags[key] = true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
positionals.push(a);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return { positionals, flags };
|
|
35
|
+
}
|
|
36
|
+
export function flagStr(flags, key) {
|
|
37
|
+
const v = flags[key];
|
|
38
|
+
return typeof v === 'string' ? v : undefined;
|
|
39
|
+
}
|
|
40
|
+
export function flagBool(flags, key) {
|
|
41
|
+
return flags[key] === true || flags[key] === 'true' || flags[key] === '1';
|
|
42
|
+
}
|
|
43
|
+
export function flagNum(flags, key) {
|
|
44
|
+
const s = flagStr(flags, key);
|
|
45
|
+
if (s == null)
|
|
46
|
+
return undefined;
|
|
47
|
+
const n = Number(s);
|
|
48
|
+
return Number.isFinite(n) ? n : undefined;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,KAAK,GAAqC,EAAE,CAAC;IACnD,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACnB,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC1B,IAAI,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;gBACd,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBACvB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACzB,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC3C,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;oBAClB,CAAC,EAAE,CAAC;gBACN,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;gBACpB,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAuC,EAAE,GAAW;IAC1E,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IACrB,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAuC,EAAE,GAAW;IAC3E,OAAO,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAuC,EAAE,GAAW;IAC1E,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC;IAChC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agentspeak handle-turn` — one-shot, push-driven (T2.handle_turn).
|
|
3
|
+
*
|
|
4
|
+
* The push transport (Discord @mention, OpenClaw webhook, generic HTTP
|
|
5
|
+
* webhook) wakes the bot with a message that says "run this command".
|
|
6
|
+
* The command is exactly:
|
|
7
|
+
*
|
|
8
|
+
* agentspeak handle-turn --meeting <id> --exec ./reply.sh
|
|
9
|
+
*
|
|
10
|
+
* We do ONE my_turn fetch (wait=0 — must already have a turn assigned
|
|
11
|
+
* since the push fired), run the shim, submit, exit.
|
|
12
|
+
*
|
|
13
|
+
* If no turn is actually assigned (race with concurrent pushes), exit 0
|
|
14
|
+
* with a warning rather than blocking — the next push will retry.
|
|
15
|
+
*/
|
|
16
|
+
export interface HandleTurnOpts {
|
|
17
|
+
meetingId?: string;
|
|
18
|
+
exec: string;
|
|
19
|
+
shimTimeoutMs?: number;
|
|
20
|
+
/** Wait this many seconds for the turn (default 5 — push race tolerance). */
|
|
21
|
+
waitSeconds?: number;
|
|
22
|
+
}
|
|
23
|
+
export declare function cmdHandleTurn(opts: HandleTurnOpts): Promise<number>;
|
|
24
|
+
//# sourceMappingURL=handle-turn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle-turn.d.ts","sourceRoot":"","sources":["../../src/commands/handle-turn.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAuFzE"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { api, pollMyTurn } from '../api.js';
|
|
2
|
+
import { runShim } from '../exec.js';
|
|
3
|
+
import { startHeartbeat } from '../heartbeat.js';
|
|
4
|
+
import { loadCurrentMeetingId, loadMeeting } from '../state.js';
|
|
5
|
+
export async function cmdHandleTurn(opts) {
|
|
6
|
+
const meetingId = opts.meetingId ?? loadCurrentMeetingId();
|
|
7
|
+
if (!meetingId) {
|
|
8
|
+
throw new Error('No meeting id supplied (--meeting) and no current meeting saved.');
|
|
9
|
+
}
|
|
10
|
+
const state = loadMeeting(meetingId);
|
|
11
|
+
if (!state) {
|
|
12
|
+
throw new Error(`No saved state for ${meetingId}. Run \`agentspeak join <invite>\` first.`);
|
|
13
|
+
}
|
|
14
|
+
const ctx = { baseUrl: state.baseUrl, token: state.coordinatorToken };
|
|
15
|
+
const wait = opts.waitSeconds ?? 5;
|
|
16
|
+
const poll = await pollMyTurn(ctx, meetingId, state.agentId, wait);
|
|
17
|
+
if (poll.status === 204 || !poll.envelope) {
|
|
18
|
+
process.stderr.write(`[agentspeak] handle-turn: no turn currently assigned (waited ${wait}s); exiting cleanly\n`);
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
const envelope = poll.envelope;
|
|
22
|
+
const turnNumber = typeof envelope.turnNumber === 'number' ? envelope.turnNumber : -1;
|
|
23
|
+
const taskId = typeof envelope.taskId === 'string' ? envelope.taskId : '';
|
|
24
|
+
process.stdout.write(`[agentspeak] handle-turn: ${meetingId} turn ${turnNumber} — running shim\n`);
|
|
25
|
+
const hb = startHeartbeat(ctx, meetingId, state.agentId, turnNumber);
|
|
26
|
+
let shim;
|
|
27
|
+
try {
|
|
28
|
+
shim = await runShim(opts.exec, envelope, {
|
|
29
|
+
timeoutMs: opts.shimTimeoutMs ?? 600_000,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
hb.stop();
|
|
34
|
+
}
|
|
35
|
+
if (shim.exitCode !== 0) {
|
|
36
|
+
await api.post(ctx, `/api/meetings/${meetingId}/submit`, {
|
|
37
|
+
agentId: state.agentId,
|
|
38
|
+
taskId,
|
|
39
|
+
turnNumber,
|
|
40
|
+
status: 'failed',
|
|
41
|
+
artifacts: [
|
|
42
|
+
{
|
|
43
|
+
type: 'text',
|
|
44
|
+
contentType: 'text/plain',
|
|
45
|
+
content: `shim exited ${shim.exitCode}`,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
});
|
|
49
|
+
return shim.exitCode;
|
|
50
|
+
}
|
|
51
|
+
const rawContent = shim.stdout.trim() || '(empty response)';
|
|
52
|
+
// Allow the shim to declaratively mark the turn as the closing one
|
|
53
|
+
// by emitting an HTML comment marker anywhere in its output. This
|
|
54
|
+
// keeps the shim contract pure stdout (no extra channels) while
|
|
55
|
+
// making it trivial to express "this is the done turn" from a one-
|
|
56
|
+
// line bash echo. We strip the marker before submitting so the
|
|
57
|
+
// transcript artifact stays clean.
|
|
58
|
+
const SIGNAL_DONE_MARKER = /<!--\s*agentspeak:signal=done\s*-->/i;
|
|
59
|
+
const isDone = SIGNAL_DONE_MARKER.test(rawContent);
|
|
60
|
+
const content = rawContent.replace(SIGNAL_DONE_MARKER, '').trim() || rawContent;
|
|
61
|
+
await api.post(ctx, `/api/meetings/${meetingId}/submit`, {
|
|
62
|
+
agentId: state.agentId,
|
|
63
|
+
taskId,
|
|
64
|
+
turnNumber,
|
|
65
|
+
status: 'completed',
|
|
66
|
+
executionTimeMs: shim.durationMs,
|
|
67
|
+
signal: isDone ? 'done' : undefined,
|
|
68
|
+
artifacts: [
|
|
69
|
+
{
|
|
70
|
+
type: 'text',
|
|
71
|
+
contentType: 'text/markdown',
|
|
72
|
+
content,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
});
|
|
76
|
+
process.stdout.write(`[agentspeak] handle-turn: submitted turn ${turnNumber} (${shim.durationMs}ms)\n`);
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=handle-turn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle-turn.js","sourceRoot":"","sources":["../../src/commands/handle-turn.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agentspeak join INVITE_URL` (T2).
|
|
3
|
+
*
|
|
4
|
+
* Resolves the base URL + invite token from any of:
|
|
5
|
+
* - https://<host>/i/<token>
|
|
6
|
+
* - https://<host>/s/<token>.md
|
|
7
|
+
* - bare <token> (requires --base-url or AGENTSPEAK_BASE_URL)
|
|
8
|
+
*
|
|
9
|
+
* Calls POST /api/meetings/<meetingId>/join with X-Invite-Token. To
|
|
10
|
+
* discover meetingId from a token we first GET /s/<token>.md and parse
|
|
11
|
+
* the contextualized skill (cheap; one HTTP call).
|
|
12
|
+
*
|
|
13
|
+
* Persists per-meeting state so subsequent `agentspeak handle-turn`
|
|
14
|
+
* runs need only the meeting id (or default to the most recent join).
|
|
15
|
+
*/
|
|
16
|
+
export interface JoinOpts {
|
|
17
|
+
invite: string;
|
|
18
|
+
baseUrl?: string;
|
|
19
|
+
role?: string;
|
|
20
|
+
json?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare function cmdJoin(opts: JoinOpts): Promise<{
|
|
23
|
+
meetingId: string;
|
|
24
|
+
agentId: string;
|
|
25
|
+
}>;
|
|
26
|
+
//# sourceMappingURL=join.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"join.d.ts","sourceRoot":"","sources":["../../src/commands/join.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAiED,wBAAsB,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAgE7F"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { loadIdentity, saveIdentity, saveMeeting } from '../state.js';
|
|
2
|
+
import { cmdRegister } from './register.js';
|
|
3
|
+
import { cmdTutorial } from './tutorial.js';
|
|
4
|
+
function parseInvite(input, fallbackBase) {
|
|
5
|
+
if (/^https?:\/\//.test(input)) {
|
|
6
|
+
const u = new URL(input);
|
|
7
|
+
const m = u.pathname.match(/^\/(?:i|s)\/([^/]+?)(?:\.md)?\/?$/);
|
|
8
|
+
if (!m)
|
|
9
|
+
throw new Error(`URL does not look like an AgentSpeak invite: ${input}`);
|
|
10
|
+
return { baseUrl: `${u.protocol}//${u.host}`, token: m[1] };
|
|
11
|
+
}
|
|
12
|
+
if (!fallbackBase) {
|
|
13
|
+
throw new Error('Bare invite token requires --base-url or AGENTSPEAK_BASE_URL.');
|
|
14
|
+
}
|
|
15
|
+
return { baseUrl: fallbackBase.replace(/\/+$/, ''), token: input };
|
|
16
|
+
}
|
|
17
|
+
async function tryJoin(baseUrl, meetingId, inviteToken, identity, role) {
|
|
18
|
+
return fetch(`${baseUrl}/api/meetings/${meetingId}/join`, {
|
|
19
|
+
method: 'POST',
|
|
20
|
+
headers: {
|
|
21
|
+
'content-type': 'application/json',
|
|
22
|
+
authorization: `Bearer ${identity.coordinatorToken}`,
|
|
23
|
+
'x-invite-token': inviteToken,
|
|
24
|
+
},
|
|
25
|
+
body: JSON.stringify({ agentId: identity.agentId, role }),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async function discoverMeetingFromInvite(baseUrl, token) {
|
|
29
|
+
// /s/{token}.md returns markdown with meeting metadata in the header.
|
|
30
|
+
const res = await fetch(`${baseUrl}/s/${token}.md`, {
|
|
31
|
+
headers: { accept: 'text/markdown' },
|
|
32
|
+
});
|
|
33
|
+
const body = await res.text();
|
|
34
|
+
if (!res.ok) {
|
|
35
|
+
throw new Error(`Failed to resolve invite ${token}: ${res.status} ${body.slice(0, 200)}`);
|
|
36
|
+
}
|
|
37
|
+
// Look for `meetingId: meet_xxx` in the markdown body. The
|
|
38
|
+
// contextualized skill template renders this verbatim.
|
|
39
|
+
const idMatch = body.match(/meet[_\-A-Za-z0-9]+/);
|
|
40
|
+
const titleMatch = body.match(/^title:\s*(.+)$/m) ?? body.match(/^#\s*Join.*?["“]([^"”]+)["”]/m);
|
|
41
|
+
if (!idMatch) {
|
|
42
|
+
throw new Error('Could not find a meeting id in the invite skill. Are you sure this is a join invite (not a create invite)?');
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
meetingId: idMatch[0],
|
|
46
|
+
meetingTitle: titleMatch?.[1]?.trim(),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export async function cmdJoin(opts) {
|
|
50
|
+
let identity = loadIdentity();
|
|
51
|
+
const fallbackBase = opts.baseUrl ?? identity?.baseUrl ?? process.env.AGENTSPEAK_BASE_URL;
|
|
52
|
+
const parsed = parseInvite(opts.invite, fallbackBase);
|
|
53
|
+
// Auto-register if we don't have an identity for this base URL.
|
|
54
|
+
if (!identity || identity.baseUrl !== parsed.baseUrl) {
|
|
55
|
+
process.stderr.write(`[agentspeak] no identity for ${parsed.baseUrl}; auto-registering...\n`);
|
|
56
|
+
identity = await cmdRegister({ baseUrl: parsed.baseUrl, json: false });
|
|
57
|
+
}
|
|
58
|
+
const meeting = await discoverMeetingFromInvite(parsed.baseUrl, parsed.token);
|
|
59
|
+
let r = await tryJoin(parsed.baseUrl, meeting.meetingId, parsed.token, identity, opts.role);
|
|
60
|
+
// Server returns 403 tutorial_required when this agent has never
|
|
61
|
+
// passed the onboarding tutorial. Run it inline and retry once so
|
|
62
|
+
// the human only ever has to invoke `agentspeak join`.
|
|
63
|
+
if (r.status === 403) {
|
|
64
|
+
const text = await r.clone().text();
|
|
65
|
+
if (text.includes('tutorial_required')) {
|
|
66
|
+
process.stderr.write('[agentspeak] join blocked: tutorial required.\n' +
|
|
67
|
+
'[agentspeak] running `agentspeak tutorial` inline; this is a one-time setup.\n');
|
|
68
|
+
const code = await cmdTutorial({ selfAck: true, json: false });
|
|
69
|
+
if (code !== 0) {
|
|
70
|
+
throw new Error(`tutorial failed (exit ${code}); join aborted`);
|
|
71
|
+
}
|
|
72
|
+
r = await tryJoin(parsed.baseUrl, meeting.meetingId, parsed.token, identity, opts.role);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const text = await r.text();
|
|
76
|
+
if (!r.ok) {
|
|
77
|
+
throw new Error(`Join failed: ${r.status} ${text}`);
|
|
78
|
+
}
|
|
79
|
+
const joinRes = JSON.parse(text);
|
|
80
|
+
saveMeeting({
|
|
81
|
+
baseUrl: parsed.baseUrl,
|
|
82
|
+
meetingId: meeting.meetingId,
|
|
83
|
+
meetingTitle: meeting.meetingTitle,
|
|
84
|
+
agentId: identity.agentId,
|
|
85
|
+
coordinatorToken: identity.coordinatorToken,
|
|
86
|
+
joinedAt: new Date().toISOString(),
|
|
87
|
+
});
|
|
88
|
+
// Update identity in case base URL was just learned.
|
|
89
|
+
saveIdentity(identity);
|
|
90
|
+
if (opts.json) {
|
|
91
|
+
process.stdout.write(JSON.stringify({ ok: true, ...joinRes }, null, 2) + '\n');
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
process.stdout.write(`Joined ${meeting.meetingTitle ?? meeting.meetingId} as ${identity.agentId} (role=${joinRes.role}).\n` +
|
|
95
|
+
`Dashboard: ${parsed.baseUrl}/meetings/${meeting.meetingId}\n` +
|
|
96
|
+
'\nWhen the coordinator wakes you (push transport), run:\n' +
|
|
97
|
+
` agentspeak handle-turn --meeting ${meeting.meetingId} --exec ./reply.sh\n`);
|
|
98
|
+
}
|
|
99
|
+
return { meetingId: meeting.meetingId, agentId: identity.agentId };
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=join.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"join.js","sourceRoot":"","sources":["../../src/commands/join.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Parsed } from '../cli.js';
|
|
2
|
+
/**
|
|
3
|
+
* `agentspeak meeting <subcommand>` — organizer surface.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the curl-heavy "construct CreateMeetingRequest by hand" flow
|
|
6
|
+
* with a small CLI on top of POST /api/meetings, POST /invites, and
|
|
7
|
+
* GET /status. Defaults are deliberately opinionated (consensus, 20 turns,
|
|
8
|
+
* 30min timeout) so the common case is a one-liner:
|
|
9
|
+
*
|
|
10
|
+
* agentspeak meeting create --title "Sync" --invite hermes,openclaw
|
|
11
|
+
*
|
|
12
|
+
* Each --invite name becomes a freshly-minted invite with that persona;
|
|
13
|
+
* the CLI prints the join URLs you can paste straight into Discord / a
|
|
14
|
+
* shell.
|
|
15
|
+
*/
|
|
16
|
+
export declare function cmdMeeting(parsed: Parsed): Promise<number>;
|
|
17
|
+
//# sourceMappingURL=meeting.d.ts.map
|