typeclaw 0.3.0 → 0.4.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 (101) hide show
  1. package/README.md +20 -15
  2. package/auth.schema.json +113 -0
  3. package/package.json +2 -1
  4. package/scripts/dump-system-prompt.ts +401 -0
  5. package/secrets.schema.json +113 -0
  6. package/src/agent/index.ts +149 -30
  7. package/src/agent/provider-error.ts +44 -0
  8. package/src/agent/session-meta.ts +43 -0
  9. package/src/agent/session-origin.ts +3 -2
  10. package/src/agent/subagents.ts +8 -0
  11. package/src/agent/system-prompt.ts +70 -35
  12. package/src/bundled-plugins/security/index.ts +3 -2
  13. package/src/channels/adapters/github/auth-app.ts +120 -0
  14. package/src/channels/adapters/github/auth-pat.ts +50 -0
  15. package/src/channels/adapters/github/auth.ts +33 -0
  16. package/src/channels/adapters/github/channel-resolver.ts +30 -0
  17. package/src/channels/adapters/github/dedup.ts +26 -0
  18. package/src/channels/adapters/github/event-allowlist.ts +8 -0
  19. package/src/channels/adapters/github/fetch-attachment.ts +5 -0
  20. package/src/channels/adapters/github/history.ts +63 -0
  21. package/src/channels/adapters/github/inbound.ts +286 -0
  22. package/src/channels/adapters/github/index.ts +286 -0
  23. package/src/channels/adapters/github/managed-path.ts +54 -0
  24. package/src/channels/adapters/github/membership.ts +35 -0
  25. package/src/channels/adapters/github/outbound.ts +145 -0
  26. package/src/channels/adapters/github/webhook-register.ts +349 -0
  27. package/src/channels/manager.ts +94 -9
  28. package/src/channels/router.ts +28 -2
  29. package/src/channels/schema.ts +31 -1
  30. package/src/channels/tunnel-bridge.ts +51 -0
  31. package/src/cli/builtins.ts +28 -0
  32. package/src/cli/channel.ts +511 -25
  33. package/src/cli/container-command-client.ts +244 -0
  34. package/src/cli/cron.ts +173 -0
  35. package/src/cli/host-command-runner.ts +150 -0
  36. package/src/cli/index.ts +42 -1
  37. package/src/cli/init.ts +256 -27
  38. package/src/cli/model.ts +4 -2
  39. package/src/cli/plugin-command-help.ts +49 -0
  40. package/src/cli/plugin-commands-dispatch.ts +112 -0
  41. package/src/cli/plugin-commands.ts +118 -0
  42. package/src/cli/tui.ts +10 -2
  43. package/src/cli/tunnel.ts +533 -0
  44. package/src/cli/ui.ts +8 -3
  45. package/src/cli/usage.ts +30 -2
  46. package/src/config/config.ts +90 -4
  47. package/src/config/reloadable.ts +22 -4
  48. package/src/container/start.ts +30 -3
  49. package/src/cron/bridge.ts +136 -0
  50. package/src/cron/consumer.ts +62 -6
  51. package/src/cron/index.ts +19 -2
  52. package/src/cron/list.ts +105 -0
  53. package/src/cron/scheduler.ts +12 -3
  54. package/src/cron/schema.ts +11 -3
  55. package/src/doctor/checks.ts +0 -50
  56. package/src/init/dockerfile.ts +59 -13
  57. package/src/init/ensure-deps.ts +15 -4
  58. package/src/init/github-webhook-install.ts +109 -0
  59. package/src/init/index.ts +505 -9
  60. package/src/init/run-bun-install.ts +17 -3
  61. package/src/init/run-owner-claim.ts +11 -2
  62. package/src/permissions/builtins.ts +6 -1
  63. package/src/permissions/match-rule.ts +24 -2
  64. package/src/permissions/resolve.ts +1 -0
  65. package/src/plugin/define.ts +42 -1
  66. package/src/plugin/index.ts +18 -3
  67. package/src/plugin/manager.ts +2 -0
  68. package/src/plugin/registry.ts +85 -3
  69. package/src/plugin/types.ts +138 -1
  70. package/src/plugin/zod-introspect.ts +100 -0
  71. package/src/role-claim/match-rule.ts +2 -1
  72. package/src/run/index.ts +119 -4
  73. package/src/secrets/index.ts +1 -1
  74. package/src/secrets/schema.ts +21 -0
  75. package/src/server/command-runner.ts +476 -0
  76. package/src/server/index.ts +393 -15
  77. package/src/shared/index.ts +8 -0
  78. package/src/shared/protocol.ts +80 -1
  79. package/src/skills/typeclaw-channel-github/SKILL.md +24 -0
  80. package/src/skills/typeclaw-config/SKILL.md +27 -26
  81. package/src/skills/typeclaw-cron/SKILL.md +234 -3
  82. package/src/skills/typeclaw-monorepo/SKILL.md +2 -2
  83. package/src/skills/typeclaw-permissions/SKILL.md +5 -4
  84. package/src/skills/typeclaw-plugins/SKILL.md +251 -5
  85. package/src/skills/typeclaw-tunnels/SKILL.md +111 -0
  86. package/src/test-helpers/wait-for.ts +50 -0
  87. package/src/tui/index.ts +35 -4
  88. package/src/tunnels/__fixtures__/cloudflared-quick-stderr.txt +11 -0
  89. package/src/tunnels/events.ts +14 -0
  90. package/src/tunnels/index.ts +12 -0
  91. package/src/tunnels/log-ring.ts +54 -0
  92. package/src/tunnels/manager.ts +139 -0
  93. package/src/tunnels/providers/cloudflare-quick.ts +189 -0
  94. package/src/tunnels/providers/external.ts +53 -0
  95. package/src/tunnels/quick-url-parser.ts +5 -0
  96. package/src/tunnels/types.ts +43 -0
  97. package/src/usage/aggregate.ts +30 -1
  98. package/src/usage/index.ts +3 -2
  99. package/src/usage/report.ts +103 -3
  100. package/src/usage/scan.ts +59 -4
  101. package/typeclaw.schema.json +254 -1
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod'
2
2
 
3
- export const ADAPTER_IDS = ['discord-bot', 'kakaotalk', 'slack-bot', 'telegram-bot'] as const
3
+ export const ADAPTER_IDS = ['discord-bot', 'github', 'kakaotalk', 'slack-bot', 'telegram-bot'] as const
4
4
 
5
5
  export type AdapterId = (typeof ADAPTER_IDS)[number]
6
6
 
@@ -99,6 +99,33 @@ const adapterSchema = z.object({
99
99
  enabled: z.boolean().default(true),
100
100
  })
101
101
 
102
+ export const DEFAULT_GITHUB_EVENT_ALLOWLIST = [
103
+ 'issue_comment.created',
104
+ 'pull_request_review_comment.created',
105
+ 'discussion_comment.created',
106
+ 'issues.opened',
107
+ 'pull_request.opened',
108
+ 'discussion.created',
109
+ 'pull_request_review.submitted',
110
+ ] as const
111
+
112
+ const githubChannelSchema = adapterSchema.extend({
113
+ // Optional now (PR 2): when omitted and a `tunnels[]` entry with
114
+ // `for: { kind: 'channel', name: 'github' }` exists, the runtime resolves
115
+ // the URL from the tunnel manager via the adapter's `tunnelUrl` callback.
116
+ // The github adapter skips webhook registration when no effective URL is available.
117
+ webhookUrl: z.string().url().optional(),
118
+ webhookPort: z.number().int().positive().default(8975),
119
+ eventAllowlist: z.array(z.string()).default([...DEFAULT_GITHUB_EVENT_ALLOWLIST]),
120
+ // Repositories whose webhooks the adapter manages. Each entry is an
121
+ // `owner/name` slug. On adapter start(), TypeClaw registers a webhook
122
+ // pointing at webhookUrl for every repo here (idempotent: existing hooks
123
+ // at the same URL are updated). On stop(), every hook TypeClaw created
124
+ // this session is deleted so a restart with a different webhookUrl (e.g.
125
+ // a tunnel reassigning a URL) doesn't leave orphaned hooks on GitHub.
126
+ repos: z.array(z.string()).default([]),
127
+ })
128
+
102
129
  // KakaoTalk uses the same shape as every other adapter. There used to be an
103
130
  // `autoMarkRead` opt-in here; the adapter now fires a LOCO NOTIREAD ack on
104
131
  // every inbound MSG event unconditionally (see kakaotalk.ts) so the sender's
@@ -112,6 +139,7 @@ const adapterSchema = z.object({
112
139
  export const channelsSchema = z
113
140
  .object({
114
141
  'discord-bot': adapterSchema.optional(),
142
+ github: githubChannelSchema.optional(),
115
143
  kakaotalk: adapterSchema.optional(),
116
144
  'slack-bot': adapterSchema.optional(),
117
145
  'telegram-bot': adapterSchema.optional(),
@@ -120,4 +148,6 @@ export const channelsSchema = z
120
148
 
121
149
  export type EngagementConfig = z.infer<typeof engagementSchema>
122
150
  export type ChannelAdapterConfig = z.infer<typeof adapterSchema>
151
+ type ParsedGithubAdapterConfig = z.infer<typeof githubChannelSchema>
152
+ export type GithubAdapterConfig = ParsedGithubAdapterConfig
123
153
  export type ChannelsConfig = z.infer<typeof channelsSchema>
@@ -0,0 +1,51 @@
1
+ import type { Stream } from '@/stream'
2
+ import { isTunnelUrlChangedPayload } from '@/tunnels'
3
+
4
+ import type { AdapterId } from './schema'
5
+
6
+ export type TunnelBridgeLogger = {
7
+ info: (msg: string) => void
8
+ warn: (msg: string) => void
9
+ error: (msg: string) => void
10
+ }
11
+
12
+ export type TunnelBridgeChannelManager = {
13
+ restartAdapter: (name: AdapterId) => Promise<void>
14
+ }
15
+
16
+ export type TunnelBridgeOptions = {
17
+ stream: Stream
18
+ channelManager: TunnelBridgeChannelManager
19
+ logger?: TunnelBridgeLogger
20
+ }
21
+
22
+ export type TunnelBridge = {
23
+ stop: () => void
24
+ }
25
+
26
+ const consoleLogger: TunnelBridgeLogger = {
27
+ info: (msg) => console.log(msg),
28
+ warn: (msg) => console.warn(msg),
29
+ error: (msg) => console.error(msg),
30
+ }
31
+
32
+ export function createTunnelBridge(options: TunnelBridgeOptions): TunnelBridge {
33
+ const logger = options.logger ?? consoleLogger
34
+ // Subscribe synchronously; run/index.ts must create this bridge before
35
+ // tunnelManager.start() so an initial provider URL broadcast cannot be missed.
36
+ const unsubscribe = options.stream.subscribe({ target: { kind: 'broadcast' } }, (msg) => {
37
+ const payload = msg.payload
38
+ if (!isTunnelUrlChangedPayload(payload)) return
39
+ if (payload.for.kind !== 'channel') return
40
+ const name = (payload.for as { name?: unknown }).name
41
+ if (typeof name !== 'string') return
42
+ logger.info(`[tunnels] ${name} URL → restarting adapter`)
43
+ void options.channelManager.restartAdapter(name as AdapterId).catch((err: unknown) => {
44
+ logger.error(`[tunnels] failed to restart ${name} adapter: ${err instanceof Error ? err.message : String(err)}`)
45
+ })
46
+ })
47
+
48
+ return {
49
+ stop: unsubscribe,
50
+ }
51
+ }
@@ -0,0 +1,28 @@
1
+ // Single source of truth for the top-level `typeclaw` subcommands that the
2
+ // CLI dispatches via citty. Plugin commands MUST NOT shadow these names.
3
+ // `src/cli/index.ts` consumes this for argv interception; `src/plugin/registry.ts`
4
+ // consumes it to reject plugin commands that collide.
5
+ export const BUILTIN_COMMAND_NAMES = [
6
+ 'init',
7
+ 'run',
8
+ 'tui',
9
+ 'start',
10
+ 'stop',
11
+ 'restart',
12
+ 'status',
13
+ 'reload',
14
+ 'logs',
15
+ 'shell',
16
+ 'compose',
17
+ 'channel',
18
+ 'cron',
19
+ 'tunnel',
20
+ 'role',
21
+ 'provider',
22
+ 'model',
23
+ 'doctor',
24
+ 'usage',
25
+ '_hostd',
26
+ ] as const
27
+
28
+ export type BuiltinCommandName = (typeof BUILTIN_COMMAND_NAMES)[number]