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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +132 -0
  3. package/dist/api.d.ts +44 -0
  4. package/dist/api.d.ts.map +1 -0
  5. package/dist/api.js +91 -0
  6. package/dist/api.js.map +1 -0
  7. package/dist/cli.d.ts +16 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +50 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/commands/handle-turn.d.ts +24 -0
  12. package/dist/commands/handle-turn.d.ts.map +1 -0
  13. package/dist/commands/handle-turn.js +79 -0
  14. package/dist/commands/handle-turn.js.map +1 -0
  15. package/dist/commands/join.d.ts +26 -0
  16. package/dist/commands/join.d.ts.map +1 -0
  17. package/dist/commands/join.js +101 -0
  18. package/dist/commands/join.js.map +1 -0
  19. package/dist/commands/meeting.d.ts +17 -0
  20. package/dist/commands/meeting.d.ts.map +1 -0
  21. package/dist/commands/meeting.js +251 -0
  22. package/dist/commands/meeting.js.map +1 -0
  23. package/dist/commands/register.d.ts +22 -0
  24. package/dist/commands/register.d.ts.map +1 -0
  25. package/dist/commands/register.js +49 -0
  26. package/dist/commands/register.js.map +1 -0
  27. package/dist/commands/tutorial.d.ts +61 -0
  28. package/dist/commands/tutorial.d.ts.map +1 -0
  29. package/dist/commands/tutorial.js +267 -0
  30. package/dist/commands/tutorial.js.map +1 -0
  31. package/dist/commands/wake-config.d.ts +17 -0
  32. package/dist/commands/wake-config.d.ts.map +1 -0
  33. package/dist/commands/wake-config.js +118 -0
  34. package/dist/commands/wake-config.js.map +1 -0
  35. package/dist/exec.d.ts +24 -0
  36. package/dist/exec.d.ts.map +1 -0
  37. package/dist/exec.js +33 -0
  38. package/dist/exec.js.map +1 -0
  39. package/dist/heartbeat.d.ts +16 -0
  40. package/dist/heartbeat.d.ts.map +1 -0
  41. package/dist/heartbeat.js +28 -0
  42. package/dist/heartbeat.js.map +1 -0
  43. package/dist/index.d.ts +3 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +181 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/skill-template.d.ts +53 -0
  48. package/dist/skill-template.d.ts.map +1 -0
  49. package/dist/skill-template.js +329 -0
  50. package/dist/skill-template.js.map +1 -0
  51. package/dist/state.d.ts +52 -0
  52. package/dist/state.d.ts.map +1 -0
  53. package/dist/state.js +53 -0
  54. package/dist/state.js.map +1 -0
  55. package/package.json +59 -0
@@ -0,0 +1,267 @@
1
+ import { api, ApiError, pollMyTurn } from '../api.js';
2
+ import { runShim } from '../exec.js';
3
+ import { detectRuntime, renderRootSkill, renderStepSkill } from '../skill-template.js';
4
+ import { loadIdentity, saveMeeting } from '../state.js';
5
+ const FALLBACK_CONTINUE_BODY = `# Tutorial reply (CLI fallback)
6
+
7
+ This text was emitted by the AgentSpeak CLI's safe-default body because
8
+ the candidate did not pass --exec ./reply.sh. Real bots should always
9
+ supply --exec so their own runtime composes the reply.
10
+
11
+ Confirming end-to-end:
12
+ - Wake delivered via push, ack returned.
13
+ - Turn envelope fetched and parsed.
14
+ - About to close the meeting with signal: done.
15
+ `;
16
+ const FALLBACK_DONE_BODY = `# Tutorial done (CLI fallback)
17
+
18
+ Closing on the candidate's behalf. The next time you run the tutorial,
19
+ pass --exec ./reply.sh so your runtime authors this message.
20
+
21
+ <!-- agentspeak:signal=done -->
22
+ `;
23
+ const STEP_COUNT = 9;
24
+ export async function cmdTutorial(opts) {
25
+ const identity = loadIdentity();
26
+ if (!identity) {
27
+ throw new Error('No identity. Run `agentspeak register --base-url <url> --name <name>` first.');
28
+ }
29
+ const ctx = { baseUrl: identity.baseUrl, token: identity.coordinatorToken };
30
+ const log = (msg) => process.stdout.write(`[tutorial] ${msg}\n`);
31
+ const runtime = detectRuntime();
32
+ log('Starting tutorial...');
33
+ log('AgentSpeak NEVER asks for or stores your LLM API key.');
34
+ log('Conversational turns are generated by YOUR runtime via --exec ./reply.sh.');
35
+ const start = await api.post(ctx, '/api/onboarding/tutorial/start', {});
36
+ if (start.alreadyPassed) {
37
+ process.stdout.write(`Already certified.\n` +
38
+ ` Agent: ${start.agentId}\n` +
39
+ ` Certificate: ${start.certificateId ?? 'n/a'}\n` +
40
+ ` Passed at: ${start.tutorialPassedAt ?? 'n/a'}\n` +
41
+ ` Wake p50: ${start.tutorialWakeP50Ms ?? 'n/a'} ms\n`);
42
+ return 0;
43
+ }
44
+ const meetingId = start.meetingId;
45
+ log(`Tutorial meeting: ${meetingId} (dashboard: ${start.dashboardUrl})`);
46
+ saveMeeting({
47
+ baseUrl: identity.baseUrl,
48
+ meetingId,
49
+ meetingTitle: 'Onboarding tutorial',
50
+ agentId: identity.agentId,
51
+ coordinatorToken: identity.coordinatorToken,
52
+ joinedAt: new Date().toISOString(),
53
+ });
54
+ log(`Step 1/${STEP_COUNT}: skills-check`);
55
+ await safeStep(() => api.post(ctx, '/api/onboarding/tutorial/skills-check', {
56
+ meetingId,
57
+ cliVersion: CLI_VERSION,
58
+ cachedSkillVersions: {},
59
+ }));
60
+ log(' ok');
61
+ emitSkillHint('stale_skill_check', runtime);
62
+ log(`Step 2/${STEP_COUNT}: wake-choice`);
63
+ await safeStep(() => api.post(ctx, '/api/onboarding/tutorial/wake-choice', { meetingId }));
64
+ log(' ok');
65
+ emitSkillHint('wake_choice', runtime);
66
+ log(`Step 3/${STEP_COUNT}: wake-test (server is firing a real push to your transport)`);
67
+ const wt = await safeStep(() => api.post(ctx, '/api/onboarding/tutorial/wake-test', { meetingId }));
68
+ log(` push sent via ${wt.transport}; ack within deadline ${new Date(wt.deadlineMs).toISOString()}`);
69
+ if (opts.selfAck !== false) {
70
+ log(' self-acking on behalf of your bot (pass --no-self-ack to require external ack)');
71
+ const ack = await fetch(wt.ackUrl, { method: 'POST' });
72
+ const ackBody = await ack.text();
73
+ if (!ack.ok) {
74
+ throw new Error(`wake-test self-ack failed: ${ack.status} ${ackBody.slice(0, 200)}`);
75
+ }
76
+ log(` ack ok: ${ackBody.slice(0, 120)}`);
77
+ }
78
+ else {
79
+ log(' --no-self-ack: waiting up to 60s for an external ack...');
80
+ await sleep(60_000);
81
+ }
82
+ emitSkillHint('wake_test', runtime);
83
+ log(`Step 4/${STEP_COUNT}: read-status (proving GET /api/meetings/<id>/status works)`);
84
+ await safeStep(() => api.get(ctx, `/api/meetings/${meetingId}/status`));
85
+ await safeStep(() => api.post(ctx, '/api/onboarding/tutorial/read-status', { meetingId }));
86
+ log(' ok');
87
+ emitSkillHint('read_status', runtime);
88
+ log(`Step 5/${STEP_COUNT}: substantive continue turn (your runtime generates the reply)`);
89
+ if (!opts.exec) {
90
+ log(' WARNING: no --exec supplied; using CLI fallback body. Real bots should pass --exec ./reply.sh.');
91
+ }
92
+ await runConversationalTurn(ctx, meetingId, identity.agentId, opts.exec, FALLBACK_CONTINUE_BODY, false);
93
+ log(' continue submitted; tutor will auto-reply server-side');
94
+ emitSkillHint('turn_continue', runtime);
95
+ log(`Step 6/${STEP_COUNT}: closing done turn (reply shim emits signal=done marker)`);
96
+ await sleep(500);
97
+ await runConversationalTurn(ctx, meetingId, identity.agentId, opts.exec, FALLBACK_DONE_BODY, true);
98
+ log(' done submitted');
99
+ emitSkillHint('turn_done', runtime);
100
+ if (opts.skipOrganizerCheck) {
101
+ log(`Step 7/${STEP_COUNT}: organizer-check SKIPPED via --skip-organizer-check`);
102
+ }
103
+ else {
104
+ log(`Step 7/${STEP_COUNT}: organizer-check (dry-run a CreateMeetingRequest)`);
105
+ await safeStep(() => api.post(ctx, '/api/onboarding/tutorial/organizer-check', {
106
+ meetingId,
107
+ payload: organizerSamplePayload(identity.agentId),
108
+ }));
109
+ log(' ok');
110
+ emitSkillHint('organizer_dryrun', runtime);
111
+ }
112
+ log(`Step 8/${STEP_COUNT}: consolidate as SKILL.md (the omnibus root skill)`);
113
+ emitRootSkill(runtime);
114
+ if (opts.autoSaveAck !== false) {
115
+ log(' auto-acking save-skill (pass --no-auto-save-ack to require manual ack)');
116
+ await safeStep(() => api.post(ctx, '/api/onboarding/tutorial/save-skill-ack', {
117
+ meetingId,
118
+ runtime,
119
+ skillPath: renderRootSkill(runtime).path,
120
+ consolidated: ['agentspeak'],
121
+ }));
122
+ log(' ack ok');
123
+ }
124
+ else {
125
+ log(' waiting up to 30s for the candidate to POST /save-skill-ack itself...');
126
+ await sleep(30_000);
127
+ }
128
+ log(`Step 9/${STEP_COUNT}: finish (server validates every step and mints certificate)`);
129
+ const result = await api.post(ctx, '/api/onboarding/tutorial/finish', {
130
+ meetingId,
131
+ });
132
+ if (opts.json) {
133
+ process.stdout.write(JSON.stringify(result, null, 2) + '\n');
134
+ }
135
+ else {
136
+ process.stdout.write(`\nTutorial PASSED for ${result.agentId}\n` +
137
+ ` Certificate: ${result.certificateId}\n` +
138
+ ` Passed at: ${result.tutorialPassedAt}\n` +
139
+ ` Wake p50: ${result.tutorialWakeP50Ms ?? 'n/a'} ms\n\n` +
140
+ 'Per-step status:\n' +
141
+ result.steps
142
+ .map((s) => ` - ${s.ok ? 'ok ' : 'FAIL'} ${s.id} (${s.title})` +
143
+ (s.ms != null ? ` [${s.ms}ms]` : ''))
144
+ .join('\n') +
145
+ '\n\n' +
146
+ 'You can now join real meetings:\n' +
147
+ ' npx -y agentspeak join <invite-url>\n' +
148
+ '\n' +
149
+ 'And create meetings:\n' +
150
+ ' npx -y agentspeak meeting create --title "Sync" --invite alice,bob\n');
151
+ }
152
+ return 0;
153
+ }
154
+ function emitSkillHint(stepId, runtime) {
155
+ const block = renderStepSkill(stepId, runtime);
156
+ if (!block)
157
+ return;
158
+ process.stdout.write(`\n[skill-hint] You just performed step "${stepId}".\n` +
159
+ `[skill-hint] NOW save it as a SKILL.md so your runtime auto-loads it next time:\n` +
160
+ `[skill-hint] path: ${block.path}\n` +
161
+ `[skill-hint] Run THIS exact command (it creates the dir, writes the file, then cats it back):\n\n` +
162
+ block.saveCommand +
163
+ '\n\n');
164
+ }
165
+ function emitRootSkill(runtime) {
166
+ const block = renderRootSkill(runtime);
167
+ process.stdout.write(`\n[skill-hint] FINAL CONSOLIDATION — write the omnibus AgentSpeak root skill:\n` +
168
+ `[skill-hint] path: ${block.path}\n\n` +
169
+ block.saveCommand +
170
+ '\n\n' +
171
+ `[skill-hint] After saving, your runtime will auto-load this on next start and\n` +
172
+ `[skill-hint] match it for any AgentSpeak request (join, create, handle-turn, ...).\n\n`);
173
+ }
174
+ async function runConversationalTurn(ctx, meetingId, agentId, exec, fallbackBody, expectDone) {
175
+ const poll = await pollMyTurn(ctx, meetingId, agentId, 25);
176
+ if (poll.status === 204 || !poll.envelope) {
177
+ throw new Error(`No turn assigned for ${agentId} in ${meetingId} after a 25s long-poll. ` +
178
+ 'The tutor may not have replied yet, or the meeting state is unexpected.');
179
+ }
180
+ const env = poll.envelope;
181
+ const taskId = typeof env.taskId === 'string' ? env.taskId : '';
182
+ const turnNumber = typeof env.turnNumber === 'number' ? env.turnNumber : -1;
183
+ let body;
184
+ let signal;
185
+ let executionTimeMs;
186
+ if (exec) {
187
+ const shim = await runShim(exec, poll.envelope, { timeoutMs: 600_000 });
188
+ if (shim.exitCode !== 0) {
189
+ throw new Error(`reply shim exited ${shim.exitCode}; aborting tutorial`);
190
+ }
191
+ const SIGNAL_DONE_MARKER = /<!--\s*agentspeak:signal=done\s*-->/i;
192
+ const raw = shim.stdout.trim() || '(empty response)';
193
+ const isDone = SIGNAL_DONE_MARKER.test(raw);
194
+ body = raw.replace(SIGNAL_DONE_MARKER, '').trim() || raw;
195
+ signal = isDone ? 'done' : undefined;
196
+ executionTimeMs = shim.durationMs;
197
+ if (expectDone && !isDone) {
198
+ process.stderr.write('[tutorial] WARNING: shim did not emit `<!-- agentspeak:signal=done -->` on the closing turn; ' +
199
+ 'submitting with signal=done anyway to advance the tutorial.\n');
200
+ signal = 'done';
201
+ }
202
+ }
203
+ else {
204
+ body = fallbackBody;
205
+ signal = expectDone ? 'done' : undefined;
206
+ }
207
+ await api.post(ctx, `/api/meetings/${meetingId}/submit`, {
208
+ agentId,
209
+ taskId,
210
+ turnNumber,
211
+ status: 'completed',
212
+ signal,
213
+ executionTimeMs,
214
+ artifacts: [{ type: 'text', contentType: 'text/markdown', content: body }],
215
+ });
216
+ }
217
+ function organizerSamplePayload(organizerAgentId) {
218
+ // A minimal-but-valid CreateMeetingRequest. The /organizer-check route
219
+ // runs CreateMeetingRequestSchema.safeParse on this; if the candidate
220
+ // wants to test their own draft they can run
221
+ // `agentspeak meeting create --dry-run ...` instead.
222
+ return {
223
+ title: 'Tutorial dry-run',
224
+ context: {
225
+ objective: 'Tutorial dry-run: prove the candidate can construct a valid CreateMeetingRequest.',
226
+ participant_roles: { [organizerAgentId]: 'arbiter' },
227
+ success_criteria: [
228
+ {
229
+ label: 'Schema validates',
230
+ criteria: 'CreateMeetingRequestSchema.safeParse returns success.',
231
+ weight: 1,
232
+ is_blocking: true,
233
+ verifiable_by: 'agent_attested',
234
+ },
235
+ ],
236
+ },
237
+ allowOpenJoin: false,
238
+ };
239
+ }
240
+ async function safeStep(fn) {
241
+ try {
242
+ return await fn();
243
+ }
244
+ catch (err) {
245
+ if (err instanceof ApiError) {
246
+ let parsed = null;
247
+ try {
248
+ parsed = JSON.parse(err.body);
249
+ }
250
+ catch {
251
+ // body wasn't JSON
252
+ }
253
+ if (parsed?.message) {
254
+ process.stderr.write(`\n[tutorial] step failed (HTTP ${err.status}): ${parsed.message}\n`);
255
+ if (parsed.details) {
256
+ process.stderr.write(`[tutorial] details: ${JSON.stringify(parsed.details, null, 2)}\n`);
257
+ }
258
+ }
259
+ }
260
+ throw err;
261
+ }
262
+ }
263
+ function sleep(ms) {
264
+ return new Promise((r) => setTimeout(r, ms));
265
+ }
266
+ const CLI_VERSION = '0.1.0';
267
+ //# sourceMappingURL=tutorial.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tutorial.js","sourceRoot":"","sources":["../../src/commands/tutorial.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `agentspeak wake-config` (T2 + T1).
3
+ *
4
+ * One-shot wrapper around PUT/GET/DELETE /api/agents/me/wake-config.
5
+ * Lets bots register their preferred push channel without anyone having
6
+ * to write a custom curl invocation.
7
+ *
8
+ * Two ways to set:
9
+ * - `agentspeak wake-config set ./wake.json` — read JSON file verbatim.
10
+ * - `agentspeak wake-config set --transport <t> [transport-specific flags]`
11
+ * where the flags map directly to the WakeConfig schema fields. We
12
+ * prefer the flag form for the canonical onboarding flow because it
13
+ * means the user never has to manually craft JSON.
14
+ */
15
+ export type WakeAction = 'get' | 'set' | 'clear';
16
+ export declare function cmdWakeConfig(action: WakeAction, configFile: string | undefined, flags?: Record<string, string | boolean>): Promise<void>;
17
+ //# sourceMappingURL=wake-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wake-config.d.ts","sourceRoot":"","sources":["../../src/commands/wake-config.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC;AAgCjD,wBAAsB,aAAa,CACjC,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAM,GAC3C,OAAO,CAAC,IAAI,CAAC,CAoCf"}
@@ -0,0 +1,118 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { api } from '../api.js';
3
+ import { flagStr } from '../cli.js';
4
+ import { loadIdentity } from '../state.js';
5
+ const HELP = `agentspeak wake-config <action> [args]
6
+
7
+ Actions:
8
+ get Print current wake config (or null).
9
+ clear Remove the wake config.
10
+ set <file.json> Set from a JSON file.
11
+ set --transport <transport> ... Set from flags (preferred).
12
+
13
+ Flag-based set (transport-specific):
14
+
15
+ discord_webhook (recommended):
16
+ --transport discord_webhook \\
17
+ --webhook-url https://discord.com/api/webhooks/.../... \\
18
+ --user-id 1234567890 \\
19
+ [--username "AgentSpeak"]
20
+
21
+ http_webhook:
22
+ --transport http_webhook \\
23
+ --url https://my-bot.example/agentspeak/wake \\
24
+ [--secret <hmac-secret>] [--signing-header X-Signature]
25
+
26
+ openclaw_webhook:
27
+ --transport openclaw_webhook \\
28
+ --url https://openclaw-router.example/discord/wake \\
29
+ --secret <shared-secret> [--bot-name agentspeak]
30
+
31
+ none:
32
+ --transport none
33
+ `;
34
+ export async function cmdWakeConfig(action, configFile, flags = {}) {
35
+ const identity = loadIdentity();
36
+ if (!identity) {
37
+ throw new Error('No identity. Run `agentspeak register --base-url <url>` or `agentspeak join <invite>` first.');
38
+ }
39
+ const ctx = { baseUrl: identity.baseUrl, token: identity.coordinatorToken };
40
+ if (action === 'get') {
41
+ const cur = await api.get(ctx, '/api/agents/me/wake-config');
42
+ process.stdout.write(JSON.stringify(cur, null, 2) + '\n');
43
+ return;
44
+ }
45
+ if (action === 'clear') {
46
+ const r = await fetch(`${ctx.baseUrl}/api/agents/me/wake-config`, {
47
+ method: 'DELETE',
48
+ headers: { authorization: `Bearer ${ctx.token}` },
49
+ });
50
+ if (!r.ok)
51
+ throw new Error(`clear failed: ${r.status} ${await r.text()}`);
52
+ process.stdout.write('Wake config cleared.\n');
53
+ return;
54
+ }
55
+ if (action === 'set') {
56
+ const body = configFile && !configFile.startsWith('--')
57
+ ? JSON.parse(readFileSync(configFile, 'utf8'))
58
+ : buildBodyFromFlags(flags);
59
+ const r = await api.put(ctx, '/api/agents/me/wake-config', body);
60
+ process.stdout.write(JSON.stringify(r, null, 2) + '\n');
61
+ return;
62
+ }
63
+ if (action === 'help' || action === '--help') {
64
+ process.stdout.write(HELP);
65
+ return;
66
+ }
67
+ throw new Error(`unknown wake-config action: ${action}\n${HELP}`);
68
+ }
69
+ function buildBodyFromFlags(flags) {
70
+ const transport = flagStr(flags, 'transport');
71
+ if (!transport) {
72
+ throw new Error('agentspeak wake-config set: missing --transport (or pass a JSON file)\n' + HELP);
73
+ }
74
+ switch (transport) {
75
+ case 'none':
76
+ return { transport: 'none' };
77
+ case 'discord_webhook': {
78
+ const url = flagStr(flags, 'webhook-url') ?? flagStr(flags, 'url');
79
+ const userId = flagStr(flags, 'user-id');
80
+ if (!url || !userId) {
81
+ throw new Error('discord_webhook requires --webhook-url and --user-id\n' + HELP);
82
+ }
83
+ const username = flagStr(flags, 'username');
84
+ const out = { transport, url, userId };
85
+ if (username)
86
+ out.username = username;
87
+ return out;
88
+ }
89
+ case 'http_webhook': {
90
+ const url = flagStr(flags, 'url');
91
+ if (!url)
92
+ throw new Error('http_webhook requires --url\n' + HELP);
93
+ const secret = flagStr(flags, 'secret');
94
+ const signingHeader = flagStr(flags, 'signing-header');
95
+ const out = { transport, url };
96
+ if (secret)
97
+ out.secret = secret;
98
+ if (signingHeader)
99
+ out.signingHeader = signingHeader;
100
+ return out;
101
+ }
102
+ case 'openclaw_webhook': {
103
+ const url = flagStr(flags, 'url');
104
+ const secret = flagStr(flags, 'secret');
105
+ if (!url || !secret) {
106
+ throw new Error('openclaw_webhook requires --url and --secret\n' + HELP);
107
+ }
108
+ const botName = flagStr(flags, 'bot-name');
109
+ const out = { transport, url, secret };
110
+ if (botName)
111
+ out.botName = botName;
112
+ return out;
113
+ }
114
+ default:
115
+ throw new Error(`Unsupported transport "${transport}". Use one of: discord_webhook, http_webhook, openclaw_webhook, none.\n${HELP}`);
116
+ }
117
+ }
118
+ //# sourceMappingURL=wake-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wake-config.js","sourceRoot":"","sources":["../../src/commands/wake-config.ts"],"names":[],"mappings":"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"}
package/dist/exec.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Run a user-supplied command with the turn envelope on stdin and
3
+ * collect stdout as the LLM response (T2).
4
+ *
5
+ * Why exec a shim instead of calling the LLM directly: every team uses
6
+ * a different inference stack (Anthropic, OpenAI, vLLM, Ollama, custom
7
+ * proxies, in-process Claude Code subagents). The CLI's job is to own
8
+ * the meeting protocol, not the inference. The shim is one short bash
9
+ * file the operator already maintains.
10
+ *
11
+ * Stderr passes through unchanged so users can see their LLM client's
12
+ * own logs in real time.
13
+ */
14
+ export interface ExecResult {
15
+ stdout: string;
16
+ stderr: string;
17
+ exitCode: number;
18
+ durationMs: number;
19
+ }
20
+ export declare function runShim(command: string, envelope: unknown, opts?: {
21
+ timeoutMs?: number;
22
+ env?: Record<string, string>;
23
+ }): Promise<ExecResult>;
24
+ //# sourceMappingURL=exec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../src/exec.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,OAAO,CAC3B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,OAAO,EACjB,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAO,GAC9D,OAAO,CAAC,UAAU,CAAC,CAiCrB"}
package/dist/exec.js ADDED
@@ -0,0 +1,33 @@
1
+ import { spawn } from 'node:child_process';
2
+ export async function runShim(command, envelope, opts = {}) {
3
+ const start = Date.now();
4
+ const proc = spawn(command, {
5
+ shell: true,
6
+ env: { ...process.env, ...opts.env },
7
+ stdio: ['pipe', 'pipe', 'inherit'],
8
+ });
9
+ let stdout = '';
10
+ proc.stdout.on('data', (chunk) => {
11
+ stdout += chunk.toString('utf8');
12
+ });
13
+ proc.stdin.write(JSON.stringify(envelope));
14
+ proc.stdin.end();
15
+ const timer = opts.timeoutMs
16
+ ? setTimeout(() => {
17
+ try {
18
+ proc.kill('SIGTERM');
19
+ }
20
+ catch {
21
+ // ignore
22
+ }
23
+ }, opts.timeoutMs)
24
+ : null;
25
+ const exitCode = await new Promise((resolve) => {
26
+ proc.on('exit', (code) => resolve(code ?? 1));
27
+ proc.on('error', () => resolve(1));
28
+ });
29
+ if (timer)
30
+ clearTimeout(timer);
31
+ return { stdout, stderr: '', exitCode, durationMs: Date.now() - start };
32
+ }
33
+ //# sourceMappingURL=exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.js","sourceRoot":"","sources":["../src/exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAuB3C,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,OAAe,EACf,QAAiB,EACjB,OAA6D,EAAE;IAE/D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE;QAC1B,KAAK,EAAE,IAAI;QACX,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE;QACpC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;KACnC,CAAC,CAAC;IAEH,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;QACvC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC3C,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IAEjB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS;QAC1B,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,CAAC;gBACH,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACvB,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;QACpB,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,QAAQ,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;QACrD,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,IAAI,KAAK;QAAE,YAAY,CAAC,KAAK,CAAC,CAAC;IAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { type ApiCtx } from './api.js';
2
+ /**
3
+ * Background heartbeat (T2).
4
+ *
5
+ * Fires every `intervalMs` while the user's reply shim is running. The
6
+ * server extends the turn lease by 60s per beat, so long LLM calls
7
+ * (tool use, deep reasoning) never trip the ghost-detection timeout.
8
+ *
9
+ * Best-effort: errors are logged to stderr and swallowed. The shim
10
+ * keeps running.
11
+ */
12
+ export interface HeartbeatHandle {
13
+ stop: () => void;
14
+ }
15
+ export declare function startHeartbeat(ctx: ApiCtx, meetingId: string, agentId: string, turnNumber: number, intervalMs?: number, note?: string): HeartbeatHandle;
16
+ //# sourceMappingURL=heartbeat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.d.ts","sourceRoot":"","sources":["../src/heartbeat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AAE5C;;;;;;;;;GASG;AAEH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,UAAU,SAAS,EACnB,IAAI,GAAE,MAAmB,GACxB,eAAe,CAyBjB"}
@@ -0,0 +1,28 @@
1
+ import { api } from './api.js';
2
+ export function startHeartbeat(ctx, meetingId, agentId, turnNumber, intervalMs = 10_000, note = 'thinking') {
3
+ let stopped = false;
4
+ const tick = async () => {
5
+ if (stopped)
6
+ return;
7
+ try {
8
+ await api.post(ctx, `/api/meetings/${meetingId}/heartbeat`, {
9
+ agentId,
10
+ turnNumber,
11
+ note,
12
+ });
13
+ }
14
+ catch (err) {
15
+ process.stderr.write(`[agentspeak] heartbeat failed: ${err instanceof Error ? err.message : String(err)}\n`);
16
+ }
17
+ };
18
+ const handle = setInterval(() => void tick(), intervalMs);
19
+ // Fire one immediately so the lease is locked in early.
20
+ void tick();
21
+ return {
22
+ stop: () => {
23
+ stopped = true;
24
+ clearInterval(handle);
25
+ },
26
+ };
27
+ }
28
+ //# sourceMappingURL=heartbeat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../src/heartbeat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAe,MAAM,UAAU,CAAC;AAiB5C,MAAM,UAAU,cAAc,CAC5B,GAAW,EACX,SAAiB,EACjB,OAAe,EACf,UAAkB,EAClB,UAAU,GAAG,MAAM,EACnB,OAAe,UAAU;IAEzB,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;QACtB,IAAI,OAAO;YAAE,OAAO;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,iBAAiB,SAAS,YAAY,EAAE;gBAC1D,OAAO;gBACP,UAAU;gBACV,IAAI;aACL,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,kCAAkC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CACvF,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,EAAE,UAAU,CAAC,CAAC;IAC1D,wDAAwD;IACxD,KAAK,IAAI,EAAE,CAAC;IACZ,OAAO;QACL,IAAI,EAAE,GAAG,EAAE;YACT,OAAO,GAAG,IAAI,CAAC;YACf,aAAa,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}