ticlawk 0.1.15 → 0.1.16-dev.10

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 (34) hide show
  1. package/README.md +96 -212
  2. package/bin/ticlawk.mjs +223 -46
  3. package/package.json +2 -5
  4. package/src/adapters/ticlawk/api.mjs +308 -43
  5. package/src/adapters/ticlawk/credentials.mjs +1 -2
  6. package/src/adapters/ticlawk/index.mjs +310 -119
  7. package/src/cli/agent-commands.mjs +876 -0
  8. package/src/core/adapter-registry.mjs +12 -28
  9. package/src/core/agent-cli-handlers.mjs +731 -0
  10. package/src/core/agent-home.mjs +85 -0
  11. package/src/core/config.mjs +0 -15
  12. package/src/core/http.mjs +211 -18
  13. package/src/core/reminder-ticker.mjs +70 -0
  14. package/src/core/runtime-contract.mjs +1 -1
  15. package/src/core/runtime-env.mjs +41 -5
  16. package/src/core/runtime-support.mjs +31 -44
  17. package/src/core/ticlawk-control.mjs +7 -6
  18. package/src/migrate/write-initial-memory.mjs +101 -0
  19. package/src/runtimes/_shared/standing-prompt.mjs +308 -0
  20. package/src/runtimes/claude-code/index.mjs +49 -133
  21. package/src/runtimes/claude-code/session.mjs +15 -7
  22. package/src/runtimes/codex/index.mjs +29 -41
  23. package/src/runtimes/codex/session.mjs +9 -5
  24. package/src/runtimes/openclaw/index.mjs +59 -31
  25. package/src/runtimes/openclaw/target.mjs +0 -30
  26. package/src/runtimes/opencode/index.mjs +34 -56
  27. package/src/runtimes/opencode/session.mjs +11 -2
  28. package/src/runtimes/pi/index.mjs +31 -51
  29. package/src/runtimes/pi/session.mjs +8 -2
  30. package/ticlawk.mjs +37 -10
  31. package/assets/ticlawk-concept.svg +0 -137
  32. package/src/adapters/telegram/index.mjs +0 -359
  33. package/src/adapters/ticlawk/cards.mjs +0 -149
  34. package/src/core/media/outbound.mjs +0 -163
package/bin/ticlawk.mjs CHANGED
@@ -3,8 +3,6 @@
3
3
  import { request } from 'node:http';
4
4
  import { installProcessDiagnostics } from '../src/core/diagnostics.mjs';
5
5
  import {
6
- AF_ADAPTER_KEY,
7
- getConfiguredAdapter,
8
6
  loadPersistentConfig,
9
7
  getStreamingConfigView,
10
8
  normalizeAdapterConfigTarget,
@@ -20,7 +18,7 @@ import {
20
18
  getActiveProfile,
21
19
  listProfiles,
22
20
  } from '../src/core/profiles.mjs';
23
- import { getAdapterAuthHelp, runAdapterAuth } from '../src/core/adapter-registry.mjs';
21
+ import { runAdapterAuth } from '../src/core/adapter-registry.mjs';
24
22
  import { runTiclawkConnect } from '../src/core/ticlawk-control.mjs';
25
23
  import {
26
24
  RUNTIME_DEFINITIONS,
@@ -30,12 +28,39 @@ import { runSelfUpdate, readPkgVersion } from '../src/core/update.mjs';
30
28
  import { getUninstallHelp, runSelfUninstall } from '../src/core/uninstall.mjs';
31
29
  import { getInstallDaemonHelp, runInstallDaemon } from '../src/core/daemon-install.mjs';
32
30
  import { runSetupReadiness } from '../src/core/setup-readiness.mjs';
31
+ import {
32
+ AGENT_COMMAND_HELP,
33
+ runAttachmentViewCommand,
34
+ runGroupCreateCommand,
35
+ runGroupMembersAddCommand,
36
+ runGroupMembersCommand,
37
+ runGroupMembersRemoveCommand,
38
+ runMessageCheckCommand,
39
+ runMessageReactCommand,
40
+ runMessageReadCommand,
41
+ runMessageSearchCommand,
42
+ runMessageSendCommand,
43
+ runProfileShowCommand,
44
+ runProfileUpdateCommand,
45
+ runReminderCancelCommand,
46
+ runReminderListCommand,
47
+ runReminderLogCommand,
48
+ runReminderScheduleCommand,
49
+ runReminderSnoozeCommand,
50
+ runReminderUpdateCommand,
51
+ runServerInfoCommand,
52
+ runTaskClaimCommand,
53
+ runTaskCreateCommand,
54
+ runTaskListCommand,
55
+ runTaskUnclaimCommand,
56
+ runTaskUpdateCommand,
57
+ } from '../src/cli/agent-commands.mjs';
33
58
 
34
59
  const TICLAWK_PORT = Number(process.env.FEED_RELAY_PORT || 8741);
35
60
 
36
61
  function getConfigKeyUsage() {
37
62
  const runtimeKeys = getRuntimeExecutableDefinitions().map((runtime) => runtime.executableCliKey);
38
- return ['adapter', 'streaming...', ...runtimeKeys, 'telegram.bot-token', 'ticlawk.connector-api-key', 'ticlawk.api-url', 'ticlawk.connector-ws-url'].join('|');
63
+ return ['streaming...', ...runtimeKeys, 'ticlawk.connector-api-key', 'ticlawk.api-url', 'ticlawk.connector-ws-url'].join('|');
39
64
  }
40
65
 
41
66
  function getRuntimeConfigExamples() {
@@ -56,7 +81,7 @@ Usage:
56
81
  ticlawk config
57
82
  ticlawk config get <${configKeys}>
58
83
  ticlawk config set <${configKeys}> <value>
59
- ticlawk auth <adapter> [adapter-auth-args...]
84
+ ticlawk auth --code <6-digit-code> [--api-url <url>]
60
85
  ticlawk connect
61
86
  ticlawk profile list
62
87
  ticlawk profile current
@@ -66,44 +91,50 @@ Usage:
66
91
  ticlawk uninstall [-y]
67
92
  ticlawk version
68
93
 
94
+ Agent CLI (run inside an agent runtime; requires TICLAWK_RUNTIME_AGENT_ID):
95
+ ticlawk message send --target <t> # body on stdin
96
+ ticlawk message read --target <t> [opts]
97
+ ticlawk task claim --message-id <id>
98
+ ticlawk task update --task-id <id> --status <s>
99
+ ticlawk task list [--target <t>]
100
+ ticlawk group members --target <t>
101
+ ticlawk server info [--refresh]
102
+
69
103
  Commands:
70
- auth store adapter-specific auth/setup input locally
71
- connect connect the selected adapter to a local runtime
104
+ auth store the ticlawk app pairing code locally
105
+ connect connect ticlawk to a local runtime
72
106
  profile list or switch saved local identities
107
+ message send/read chat messages (agent CLI surface)
108
+ task claim/update/list tasks (agent CLI surface)
109
+ group list members of a group conversation (agent CLI surface)
110
+ server server-info introspection (agent CLI surface)
73
111
  install-daemon install or refresh the background daemon
74
112
  update update the npm package and refresh the daemon
75
113
  uninstall remove service and managed install files, preserving ~/.ticlawk
76
114
 
77
115
  Config examples:
78
- ticlawk config get adapter
79
- ticlawk config set adapter telegram
80
- ticlawk config set adapter ticlawk
81
116
  ticlawk config set streaming off # turn streaming off for all runtimes
82
117
  ticlawk config set streaming.codex default # clear the codex-specific override and inherit the global streaming setting
83
118
  ${getRuntimeConfigExamples()}
84
- ticlawk config set telegram.bot-token <bot-token> # advanced/manual
85
119
  ticlawk config set ticlawk.connector-api-key <key> # advanced/manual
86
120
  ticlawk config set ticlawk.api-url <api-url> # advanced/manual
87
121
  ticlawk config set ticlawk.connector-ws-url <url> # advanced/manual
88
122
 
89
123
  Examples:
90
124
  ticlawk connect
91
- ticlawk auth telegram --bot-token <bot-token>
125
+ ticlawk auth --code <6-digit-code>
92
126
  `;
93
127
  }
94
128
 
95
129
  function getAuthHelp() {
96
- return `ticlawk auth
130
+ return `ticlawk auth --code <6-digit-code> [--api-url <url>]
97
131
 
98
- Use \`auth\` to store adapter-specific auth/setup input locally.
99
- Adapter-specific args live after \`--\` so new adapters can define their own flags
100
- without changing the top-level CLI.
101
-
102
- Examples:
103
- ticlawk auth telegram --bot-token <bot-token>
132
+ Store the ticlawk app pairing code locally. The daemon picks it up on the
133
+ next start and exchanges it for an API key.
104
134
 
105
- Per-adapter help:
106
- ticlawk auth telegram --help
135
+ Options:
136
+ --code <code> 6-digit setup code from the ticlawk app
137
+ --api-url <url> optional ticlawk API base URL override
107
138
  `;
108
139
  }
109
140
 
@@ -132,11 +163,6 @@ function printHelp(helpPath, args = {}) {
132
163
  return;
133
164
  }
134
165
  if (head === 'auth') {
135
- const adapterValue = helpPath[1] || args._?.[1];
136
- if (adapterValue) {
137
- console.log(getAdapterAuthHelp(requireAdapter(adapterValue)));
138
- return;
139
- }
140
166
  console.log(getAuthHelp());
141
167
  return;
142
168
  }
@@ -169,7 +195,6 @@ function parseConfigBoolean(value) {
169
195
  }
170
196
 
171
197
  function printConfigView(config = loadPersistentConfig()) {
172
- console.log(`adapter=${getConfiguredAdapter(config)}`);
173
198
  const view = getStreamingConfigView(config);
174
199
  console.log(`streaming=${formatStreamingValue(view.streaming.value, view.streaming.inherited)}`);
175
200
  for (const runtime of RUNTIME_DEFINITIONS) {
@@ -180,7 +205,6 @@ function printConfigView(config = loadPersistentConfig()) {
180
205
  for (const runtime of getRuntimeExecutableDefinitions()) {
181
206
  console.log(`${runtime.executableCliKey}=${config[runtime.executableConfigKey] || ''}`);
182
207
  }
183
- console.log(`telegram.bot-token=${config.TELEGRAM_BOT_TOKEN ? 'set' : 'unset'}`);
184
208
  console.log(`ticlawk.connector-api-key=${config[TICLAWK_CONNECTOR_API_KEY] ? 'set' : 'unset'}`);
185
209
  console.log(`ticlawk.api-url=${config.TICLAWK_API_URL || ''}`);
186
210
  console.log(`ticlawk.connector-ws-url=${config[TICLAWK_CONNECTOR_WS_URL] || ''}`);
@@ -211,7 +235,7 @@ function getLocal(path) {
211
235
  }
212
236
 
213
237
  function formatSecretConfigValue(configKey, value) {
214
- if (configKey === 'TELEGRAM_BOT_TOKEN' || configKey === TICLAWK_CONNECTOR_API_KEY) {
238
+ if (configKey === TICLAWK_CONNECTOR_API_KEY) {
215
239
  return value ? 'set' : 'unset';
216
240
  }
217
241
  return value || '';
@@ -302,6 +326,174 @@ async function main() {
302
326
  return;
303
327
  }
304
328
 
329
+ // ── Agent-facing subcommands (run inside a runtime; talk to local daemon) ──
330
+ if (command === 'message') {
331
+ const sub = args._[1];
332
+ if (args.help || args.h || !sub) {
333
+ console.log(AGENT_COMMAND_HELP.message);
334
+ return;
335
+ }
336
+ if (sub === 'send') {
337
+ process.exitCode = await runMessageSendCommand(args);
338
+ return;
339
+ }
340
+ if (sub === 'read') {
341
+ process.exitCode = await runMessageReadCommand(args);
342
+ return;
343
+ }
344
+ if (sub === 'react') {
345
+ process.exitCode = await runMessageReactCommand(args);
346
+ return;
347
+ }
348
+ if (sub === 'check') {
349
+ process.exitCode = await runMessageCheckCommand(args);
350
+ return;
351
+ }
352
+ if (sub === 'search') {
353
+ process.exitCode = await runMessageSearchCommand(args);
354
+ return;
355
+ }
356
+ console.error(`unknown message subcommand: ${sub}`);
357
+ process.exit(1);
358
+ }
359
+
360
+ if (command === 'profile') {
361
+ const sub = args._[1];
362
+ if (args.help || args.h || !sub) {
363
+ console.log(AGENT_COMMAND_HELP.profile);
364
+ return;
365
+ }
366
+ if (sub === 'show') {
367
+ process.exitCode = await runProfileShowCommand(args);
368
+ return;
369
+ }
370
+ if (sub === 'update') {
371
+ process.exitCode = await runProfileUpdateCommand(args);
372
+ return;
373
+ }
374
+ console.error(`unknown profile subcommand: ${sub}`);
375
+ process.exit(1);
376
+ }
377
+
378
+ if (command === 'reminder') {
379
+ const sub = args._[1];
380
+ if (args.help || args.h || !sub) {
381
+ console.log(AGENT_COMMAND_HELP.reminder);
382
+ return;
383
+ }
384
+ if (sub === 'schedule') {
385
+ process.exitCode = await runReminderScheduleCommand(args);
386
+ return;
387
+ }
388
+ if (sub === 'list') {
389
+ process.exitCode = await runReminderListCommand(args);
390
+ return;
391
+ }
392
+ if (sub === 'snooze') {
393
+ process.exitCode = await runReminderSnoozeCommand(args);
394
+ return;
395
+ }
396
+ if (sub === 'update') {
397
+ process.exitCode = await runReminderUpdateCommand(args);
398
+ return;
399
+ }
400
+ if (sub === 'cancel') {
401
+ process.exitCode = await runReminderCancelCommand(args);
402
+ return;
403
+ }
404
+ if (sub === 'log') {
405
+ process.exitCode = await runReminderLogCommand(args);
406
+ return;
407
+ }
408
+ console.error(`unknown reminder subcommand: ${sub}`);
409
+ process.exit(1);
410
+ }
411
+
412
+ if (command === 'attachment') {
413
+ const sub = args._[1];
414
+ if (args.help || args.h || !sub) {
415
+ console.log(AGENT_COMMAND_HELP.attachment);
416
+ return;
417
+ }
418
+ if (sub === 'view') {
419
+ process.exitCode = await runAttachmentViewCommand(args);
420
+ return;
421
+ }
422
+ console.error(`unknown attachment subcommand: ${sub}`);
423
+ process.exit(1);
424
+ }
425
+
426
+ if (command === 'task') {
427
+ const sub = args._[1];
428
+ if (args.help || args.h || !sub) {
429
+ console.log(AGENT_COMMAND_HELP.task);
430
+ return;
431
+ }
432
+ if (sub === 'create') {
433
+ process.exitCode = await runTaskCreateCommand(args);
434
+ return;
435
+ }
436
+ if (sub === 'claim') {
437
+ process.exitCode = await runTaskClaimCommand(args);
438
+ return;
439
+ }
440
+ if (sub === 'unclaim') {
441
+ process.exitCode = await runTaskUnclaimCommand(args);
442
+ return;
443
+ }
444
+ if (sub === 'update') {
445
+ process.exitCode = await runTaskUpdateCommand(args);
446
+ return;
447
+ }
448
+ if (sub === 'list') {
449
+ process.exitCode = await runTaskListCommand(args);
450
+ return;
451
+ }
452
+ console.error(`unknown task subcommand: ${sub}`);
453
+ process.exit(1);
454
+ }
455
+
456
+ if (command === 'group') {
457
+ const sub = args._[1];
458
+ if (args.help || args.h || !sub) {
459
+ console.log(AGENT_COMMAND_HELP.group);
460
+ return;
461
+ }
462
+ if (sub === 'create') {
463
+ process.exitCode = await runGroupCreateCommand(args);
464
+ return;
465
+ }
466
+ if (sub === 'members') {
467
+ // Same subcommand handles list / add / remove based on flags.
468
+ if (args.add) {
469
+ process.exitCode = await runGroupMembersAddCommand(args);
470
+ return;
471
+ }
472
+ if (args.remove) {
473
+ process.exitCode = await runGroupMembersRemoveCommand(args);
474
+ return;
475
+ }
476
+ process.exitCode = await runGroupMembersCommand(args);
477
+ return;
478
+ }
479
+ console.error(`unknown group subcommand: ${sub}`);
480
+ process.exit(1);
481
+ }
482
+
483
+ if (command === 'server') {
484
+ const sub = args._[1];
485
+ if (args.help || args.h || !sub) {
486
+ console.log(AGENT_COMMAND_HELP.server);
487
+ return;
488
+ }
489
+ if (sub === 'info') {
490
+ process.exitCode = await runServerInfoCommand(args);
491
+ return;
492
+ }
493
+ console.error(`unknown server subcommand: ${sub}`);
494
+ process.exit(1);
495
+ }
496
+
305
497
  if (command === 'config') {
306
498
  const subcommand = args._[1];
307
499
  const config = loadPersistentConfig();
@@ -312,10 +504,6 @@ async function main() {
312
504
 
313
505
  if (subcommand === 'get') {
314
506
  const key = args._[2];
315
- if (key === 'adapter') {
316
- console.log(getConfiguredAdapter(config));
317
- return;
318
- }
319
507
  const adapterTarget = normalizeAdapterConfigTarget(key);
320
508
  if (adapterTarget) {
321
509
  console.log(formatSecretConfigValue(adapterTarget.configKey, config[adapterTarget.configKey]));
@@ -340,16 +528,6 @@ async function main() {
340
528
  if (subcommand === 'set') {
341
529
  const key = args._[2];
342
530
  const rawValue = args._[3];
343
- if (key === 'adapter') {
344
- if (!rawValue) {
345
- console.error('config set adapter requires a value');
346
- process.exit(1);
347
- }
348
- const adapterId = requireAdapter(rawValue);
349
- persistConfig({ [AF_ADAPTER_KEY]: adapterId });
350
- console.log(`adapter=${adapterId}`);
351
- return;
352
- }
353
531
  const adapterTarget = normalizeAdapterConfigTarget(key);
354
532
  if (adapterTarget) {
355
533
  if (!rawValue) {
@@ -464,9 +642,8 @@ async function main() {
464
642
  printHelp(['auth'], args);
465
643
  return;
466
644
  }
467
- const adapterId = requireAdapter(args._[1]);
468
- const adapterArgv = rawArgv.slice(2);
469
- const res = await runAdapterAuth(adapterId, adapterArgv);
645
+ const adapterArgv = rawArgv.slice(1);
646
+ const res = await runAdapterAuth('ticlawk', adapterArgv);
470
647
  printCommandResult(res);
471
648
  process.exitCode = res.statusCode >= 400 ? 1 : 0;
472
649
  return;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ticlawk",
3
- "version": "0.1.15",
4
- "description": "Connect local agent harnesses to Ticlawk, Telegram, and other mobile clients.",
3
+ "version": "0.1.16-dev.10",
4
+ "description": "Local connector that links agent harnesses (Claude Code, Codex, OpenClaw, opencode, Pi) to the Ticlawk mobile app.",
5
5
  "type": "module",
6
6
  "main": "ticlawk.mjs",
7
7
  "exports": {
@@ -48,9 +48,6 @@
48
48
  "codex",
49
49
  "agent",
50
50
  "ai-agent",
51
- "telegram",
52
- "telegram-bot",
53
- "chatops",
54
51
  "remote-agent",
55
52
  "mobile",
56
53
  "bridge",