typeclaw 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 +134 -0
- package/auth.schema.json +63 -0
- package/cron.schema.json +96 -0
- package/package.json +72 -0
- package/scripts/emit-base-dockerfile.ts +5 -0
- package/scripts/generate-schema.ts +34 -0
- package/secrets.schema.json +63 -0
- package/src/agent/auth.ts +119 -0
- package/src/agent/compaction.ts +35 -0
- package/src/agent/git-nudge.ts +95 -0
- package/src/agent/index.ts +451 -0
- package/src/agent/plugin-tools.ts +269 -0
- package/src/agent/reload-tool.ts +71 -0
- package/src/agent/self.ts +45 -0
- package/src/agent/session-origin.ts +288 -0
- package/src/agent/subagents.ts +253 -0
- package/src/agent/system-prompt.ts +68 -0
- package/src/agent/tools/channel-fetch-attachment.ts +118 -0
- package/src/agent/tools/channel-history.ts +119 -0
- package/src/agent/tools/channel-reply.ts +182 -0
- package/src/agent/tools/channel-send.ts +212 -0
- package/src/agent/tools/ddg.ts +218 -0
- package/src/agent/tools/restart.ts +122 -0
- package/src/agent/tools/stream-snapshot.ts +181 -0
- package/src/agent/tools/webfetch/fetch.ts +102 -0
- package/src/agent/tools/webfetch/index.ts +1 -0
- package/src/agent/tools/webfetch/strategies/grep.ts +70 -0
- package/src/agent/tools/webfetch/strategies/jq.ts +31 -0
- package/src/agent/tools/webfetch/strategies/raw.ts +3 -0
- package/src/agent/tools/webfetch/strategies/readability.ts +30 -0
- package/src/agent/tools/webfetch/strategies/selector.ts +41 -0
- package/src/agent/tools/webfetch/strategies/snapshot.ts +135 -0
- package/src/agent/tools/webfetch/tool.ts +281 -0
- package/src/agent/tools/webfetch/types.ts +33 -0
- package/src/agent/tools/websearch.ts +96 -0
- package/src/agent/tools/wikipedia.ts +52 -0
- package/src/bundled-plugins/agent-browser/dashboard-discovery.ts +170 -0
- package/src/bundled-plugins/agent-browser/dashboard-proxy.ts +421 -0
- package/src/bundled-plugins/agent-browser/index.ts +179 -0
- package/src/bundled-plugins/agent-browser/shim-install.ts +158 -0
- package/src/bundled-plugins/agent-browser/shim.ts +152 -0
- package/src/bundled-plugins/agent-browser/skills/agent-browser/SKILL.md +113 -0
- package/src/bundled-plugins/guard/index.ts +26 -0
- package/src/bundled-plugins/guard/policies/non-workspace-write.ts +98 -0
- package/src/bundled-plugins/guard/policies/skill-authoring.ts +185 -0
- package/src/bundled-plugins/guard/policies/uncommitted-changes.ts +85 -0
- package/src/bundled-plugins/guard/policy.ts +18 -0
- package/src/bundled-plugins/memory/README.md +71 -0
- package/src/bundled-plugins/memory/append-tool.ts +84 -0
- package/src/bundled-plugins/memory/dreaming-state.ts +86 -0
- package/src/bundled-plugins/memory/dreaming.ts +470 -0
- package/src/bundled-plugins/memory/fragment-parser.ts +67 -0
- package/src/bundled-plugins/memory/index.ts +238 -0
- package/src/bundled-plugins/memory/load-memory.ts +122 -0
- package/src/bundled-plugins/memory/memory-logger.ts +257 -0
- package/src/bundled-plugins/memory/secret-detector.ts +49 -0
- package/src/bundled-plugins/memory/watermark.ts +15 -0
- package/src/bundled-plugins/security/index.ts +35 -0
- package/src/bundled-plugins/security/policies/git-exfil.ts +120 -0
- package/src/bundled-plugins/security/policies/outbound-secret-scan.ts +167 -0
- package/src/bundled-plugins/security/policies/prompt-injection.ts +488 -0
- package/src/bundled-plugins/security/policies/secret-exfil-bash.ts +99 -0
- package/src/bundled-plugins/security/policies/secret-exfil-read.ts +127 -0
- package/src/bundled-plugins/security/policies/session-search-secrets.ts +86 -0
- package/src/bundled-plugins/security/policies/ssrf.ts +196 -0
- package/src/bundled-plugins/security/policies/system-prompt-leak.ts +81 -0
- package/src/bundled-plugins/security/policy.ts +9 -0
- package/src/channels/adapters/discord-bot-channel-resolver.ts +77 -0
- package/src/channels/adapters/discord-bot-classify.ts +148 -0
- package/src/channels/adapters/discord-bot.ts +640 -0
- package/src/channels/adapters/kakaotalk-author-resolver.ts +78 -0
- package/src/channels/adapters/kakaotalk-channel-resolver.ts +105 -0
- package/src/channels/adapters/kakaotalk-classify.ts +77 -0
- package/src/channels/adapters/kakaotalk.ts +622 -0
- package/src/channels/adapters/slack-bot-author-resolver.ts +80 -0
- package/src/channels/adapters/slack-bot-channel-resolver.ts +84 -0
- package/src/channels/adapters/slack-bot-classify.ts +213 -0
- package/src/channels/adapters/slack-bot-dedupe.ts +51 -0
- package/src/channels/adapters/slack-bot-time.ts +10 -0
- package/src/channels/adapters/slack-bot.ts +881 -0
- package/src/channels/adapters/telegram-bot-classify.ts +155 -0
- package/src/channels/adapters/telegram-bot-format.ts +309 -0
- package/src/channels/adapters/telegram-bot.ts +604 -0
- package/src/channels/engagement.ts +227 -0
- package/src/channels/index.ts +21 -0
- package/src/channels/manager.ts +292 -0
- package/src/channels/membership-cache.ts +116 -0
- package/src/channels/membership-from-history.ts +53 -0
- package/src/channels/membership.ts +30 -0
- package/src/channels/participants.ts +47 -0
- package/src/channels/persistence.ts +209 -0
- package/src/channels/reloadable.ts +28 -0
- package/src/channels/router.ts +1570 -0
- package/src/channels/schema.ts +273 -0
- package/src/channels/types.ts +160 -0
- package/src/cli/channel.ts +403 -0
- package/src/cli/compose-status.ts +95 -0
- package/src/cli/compose.ts +240 -0
- package/src/cli/hostd.ts +163 -0
- package/src/cli/index.ts +27 -0
- package/src/cli/init.ts +592 -0
- package/src/cli/logs.ts +38 -0
- package/src/cli/reload.ts +68 -0
- package/src/cli/restart.ts +66 -0
- package/src/cli/run.ts +77 -0
- package/src/cli/shell.ts +33 -0
- package/src/cli/start.ts +57 -0
- package/src/cli/status.ts +178 -0
- package/src/cli/stop.ts +31 -0
- package/src/cli/tui.ts +35 -0
- package/src/cli/ui.ts +110 -0
- package/src/commands/index.ts +74 -0
- package/src/compose/discover.ts +43 -0
- package/src/compose/index.ts +25 -0
- package/src/compose/logs.ts +162 -0
- package/src/compose/restart.ts +69 -0
- package/src/compose/start.ts +62 -0
- package/src/compose/status.ts +28 -0
- package/src/compose/stop.ts +43 -0
- package/src/config/config.ts +424 -0
- package/src/config/index.ts +25 -0
- package/src/config/providers.ts +234 -0
- package/src/config/reloadable.ts +47 -0
- package/src/container/index.ts +27 -0
- package/src/container/logs.ts +37 -0
- package/src/container/port.ts +137 -0
- package/src/container/shared.ts +290 -0
- package/src/container/shell.ts +58 -0
- package/src/container/start.ts +670 -0
- package/src/container/status.ts +76 -0
- package/src/container/stop.ts +120 -0
- package/src/container/verify-running.ts +149 -0
- package/src/cron/consumer.ts +138 -0
- package/src/cron/index.ts +54 -0
- package/src/cron/reloadable.ts +64 -0
- package/src/cron/scheduler.ts +200 -0
- package/src/cron/schema.ts +96 -0
- package/src/hostd/client.ts +113 -0
- package/src/hostd/daemon.ts +587 -0
- package/src/hostd/index.ts +25 -0
- package/src/hostd/paths.ts +82 -0
- package/src/hostd/portbroker-manager.ts +101 -0
- package/src/hostd/protocol.ts +48 -0
- package/src/hostd/spawn.ts +224 -0
- package/src/hostd/supervisor.ts +60 -0
- package/src/hostd/tailscale.ts +172 -0
- package/src/hostd/version.ts +115 -0
- package/src/init/dockerfile.ts +327 -0
- package/src/init/ensure-deps.ts +152 -0
- package/src/init/gitignore.ts +46 -0
- package/src/init/hatching.ts +60 -0
- package/src/init/index.ts +786 -0
- package/src/init/kakaotalk-auth.ts +114 -0
- package/src/init/models-dev.ts +130 -0
- package/src/init/oauth-login.ts +74 -0
- package/src/init/packagejson.ts +94 -0
- package/src/init/paths.ts +2 -0
- package/src/init/run-bun-install.ts +20 -0
- package/src/markdown/chunk.ts +299 -0
- package/src/markdown/index.ts +1 -0
- package/src/plugin/context.ts +40 -0
- package/src/plugin/define.ts +35 -0
- package/src/plugin/hooks.ts +204 -0
- package/src/plugin/index.ts +63 -0
- package/src/plugin/loader.ts +111 -0
- package/src/plugin/manager.ts +136 -0
- package/src/plugin/registry.ts +145 -0
- package/src/plugin/skills.ts +62 -0
- package/src/plugin/types.ts +172 -0
- package/src/portbroker/bind-with-forward.ts +102 -0
- package/src/portbroker/container-server.ts +305 -0
- package/src/portbroker/forward-result-bus.ts +36 -0
- package/src/portbroker/hostd-client.ts +443 -0
- package/src/portbroker/index.ts +33 -0
- package/src/portbroker/policy.ts +24 -0
- package/src/portbroker/proc-net-tcp.ts +72 -0
- package/src/portbroker/protocol.ts +39 -0
- package/src/reload/client.ts +59 -0
- package/src/reload/index.ts +3 -0
- package/src/reload/registry.ts +60 -0
- package/src/reload/types.ts +13 -0
- package/src/run/bundled-plugins.ts +24 -0
- package/src/run/channel-session-factory.ts +105 -0
- package/src/run/index.ts +432 -0
- package/src/run/plugin-runtime.ts +43 -0
- package/src/run/schema-with-plugins.ts +14 -0
- package/src/secrets/index.ts +13 -0
- package/src/secrets/migrate.ts +95 -0
- package/src/secrets/schema.ts +75 -0
- package/src/secrets/storage.ts +231 -0
- package/src/server/index.ts +436 -0
- package/src/sessions/index.ts +23 -0
- package/src/shared/index.ts +9 -0
- package/src/shared/local-time.ts +21 -0
- package/src/shared/protocol.ts +25 -0
- package/src/skills/typeclaw-channel-kakaotalk/SKILL.md +87 -0
- package/src/skills/typeclaw-channel-telegram-bot/SKILL.md +64 -0
- package/src/skills/typeclaw-config/SKILL.md +643 -0
- package/src/skills/typeclaw-cron/SKILL.md +159 -0
- package/src/skills/typeclaw-git/SKILL.md +89 -0
- package/src/skills/typeclaw-memory/SKILL.md +174 -0
- package/src/skills/typeclaw-monorepo/SKILL.md +175 -0
- package/src/skills/typeclaw-plugins/SKILL.md +594 -0
- package/src/skills/typeclaw-skills/SKILL.md +246 -0
- package/src/stream/broker.ts +161 -0
- package/src/stream/index.ts +16 -0
- package/src/stream/types.ts +69 -0
- package/src/tui/client.ts +45 -0
- package/src/tui/format.ts +317 -0
- package/src/tui/index.ts +225 -0
- package/src/tui/theme.ts +41 -0
- package/typeclaw.schema.json +826 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DiscordFile,
|
|
3
|
+
DiscordGatewayEmbed,
|
|
4
|
+
DiscordGatewayMessageCreateEvent,
|
|
5
|
+
DiscordGatewayStickerItem,
|
|
6
|
+
} from 'agent-messenger/discordbot'
|
|
7
|
+
|
|
8
|
+
import { isAllowed, type ChannelAdapterConfig } from '@/channels/schema'
|
|
9
|
+
import type { InboundMessage } from '@/channels/types'
|
|
10
|
+
|
|
11
|
+
export type InboundDropReason =
|
|
12
|
+
| 'self_author' // event.author.id === botUserId; we never route our own messages back to ourselves
|
|
13
|
+
| 'empty_content' // SDK delivered content: '' — usually missing MessageContent intent
|
|
14
|
+
| 'not_in_allow_list' // workspace/channel not admitted by typeclaw.json `channels.discord-bot.allow`
|
|
15
|
+
| 'pre_connect' // bot identity is not known yet, so mention/self/reply classification cannot be trusted
|
|
16
|
+
|
|
17
|
+
export type InboundClassification =
|
|
18
|
+
| { kind: 'drop'; reason: InboundDropReason }
|
|
19
|
+
| { kind: 'route'; payload: InboundMessage }
|
|
20
|
+
|
|
21
|
+
// All decision logic for "should this gateway event be routed to the agent?"
|
|
22
|
+
// lives here so it can be unit-tested in isolation. The adapter is left as a
|
|
23
|
+
// thin shell that handles SDK lifecycle and translates this verdict into
|
|
24
|
+
// log lines + router calls. Adding a new drop reason MUST extend
|
|
25
|
+
// InboundDropReason — there is no `default` log path, so the type system
|
|
26
|
+
// forces logging to stay exhaustive.
|
|
27
|
+
export function classifyInbound(
|
|
28
|
+
event: DiscordGatewayMessageCreateEvent,
|
|
29
|
+
config: ChannelAdapterConfig,
|
|
30
|
+
botUserId: string | null,
|
|
31
|
+
): InboundClassification {
|
|
32
|
+
// Self-drop is the hard floor: we must never route our own messages back to
|
|
33
|
+
// ourselves under any circumstance. We can only do this once botUserId is
|
|
34
|
+
// known (post-connect); before that, fail closed below because mention,
|
|
35
|
+
// reply, and self classification all depend on the bot identity.
|
|
36
|
+
if (botUserId !== null && event.author.id === botUserId) {
|
|
37
|
+
return { kind: 'drop', reason: 'self_author' }
|
|
38
|
+
}
|
|
39
|
+
const text = inboundText(event)
|
|
40
|
+
if (text === '') return { kind: 'drop', reason: 'empty_content' }
|
|
41
|
+
|
|
42
|
+
const isDm = event.guild_id === undefined
|
|
43
|
+
const workspace = isDm ? '@dm' : event.guild_id!
|
|
44
|
+
if (!isAllowed(config.allow, workspace, event.channel_id)) {
|
|
45
|
+
return { kind: 'drop', reason: 'not_in_allow_list' }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (botUserId === null) {
|
|
49
|
+
return { kind: 'drop', reason: 'pre_connect' }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Group mentions (`@everyone`, `@here`, role mentions) are coerced to
|
|
53
|
+
// direct mentions: the broadcast explicitly includes the bot, and the
|
|
54
|
+
// engagement layer doesn't meaningfully distinguish "@bot" from "@channel"
|
|
55
|
+
// — both invite participation. Reusing isBotMention also means the
|
|
56
|
+
// existing 'mention' trigger in typeclaw.json catches both with no new
|
|
57
|
+
// config surface. Discord's gateway already provides structured fields
|
|
58
|
+
// for these, so we don't need to parse content.
|
|
59
|
+
const hasGroupMention = event.mention_everyone === true || (event.mention_roles ?? []).length > 0
|
|
60
|
+
const isBotMention =
|
|
61
|
+
hasGroupMention || event.content.includes(`<@${botUserId}>`) || event.content.includes(`<@!${botUserId}>`)
|
|
62
|
+
|
|
63
|
+
// Discord sends a structured `mentions` array on every message, so we can
|
|
64
|
+
// tell "tagged someone other than us" apart from "no mentions at all"
|
|
65
|
+
// without parsing the content.
|
|
66
|
+
const mentionsOthers = (event.mentions ?? []).length > 0 && !(event.mentions ?? []).some((m) => m.id === botUserId)
|
|
67
|
+
|
|
68
|
+
const replyToParentId = event.message_reference?.message_id
|
|
69
|
+
const replyToBotMessageId = replyToParentId !== undefined && isReplyToBot(event, botUserId) ? replyToParentId : null
|
|
70
|
+
// Discord does not echo the parent message's author on `message_reference`,
|
|
71
|
+
// but in practice the replied-to user is auto-mentioned in the reply's
|
|
72
|
+
// `mentions` array (this is how the Discord client renders the "Replying
|
|
73
|
+
// to @user" header). So when the parent reference exists and our id is NOT
|
|
74
|
+
// among the mentions, the reply is targeted at someone else.
|
|
75
|
+
const replyToOtherMessageId = replyToParentId !== undefined && replyToBotMessageId === null ? replyToParentId : null
|
|
76
|
+
|
|
77
|
+
const ts = Date.parse(event.timestamp)
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
kind: 'route',
|
|
81
|
+
payload: {
|
|
82
|
+
adapter: 'discord-bot',
|
|
83
|
+
workspace,
|
|
84
|
+
chat: event.channel_id,
|
|
85
|
+
thread: null,
|
|
86
|
+
text,
|
|
87
|
+
externalMessageId: event.id,
|
|
88
|
+
authorId: event.author.id,
|
|
89
|
+
// Discord's post-2023 username system allows pure-numeric handles (e.g.
|
|
90
|
+
// "1411531"); the human-facing display name lives on `global_name`. The
|
|
91
|
+
// history mapper in discord-bot.ts uses the same fallback chain — keep
|
|
92
|
+
// them aligned so the agent sees a stable identity for a given user
|
|
93
|
+
// regardless of whether the message arrived live or via history.
|
|
94
|
+
authorName: event.author.global_name ?? event.author.username,
|
|
95
|
+
authorIsBot: event.author.bot === true,
|
|
96
|
+
isBotMention,
|
|
97
|
+
replyToBotMessageId,
|
|
98
|
+
mentionsOthers,
|
|
99
|
+
replyToOtherMessageId,
|
|
100
|
+
isDm,
|
|
101
|
+
ts: Number.isFinite(ts) ? ts : 0,
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Discord's `message_reference.message_id` only carries the parent id, not
|
|
107
|
+
// the parent author. We infer "this reply targets the bot" from the auto-
|
|
108
|
+
// mention Discord injects into the reply's `mentions` array (the same
|
|
109
|
+
// mechanism that drives the "Replying to @user" header in the client).
|
|
110
|
+
function isReplyToBot(event: DiscordGatewayMessageCreateEvent, botUserId: string): boolean {
|
|
111
|
+
return (event.mentions ?? []).some((m) => m.id === botUserId)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function inboundText(event: DiscordGatewayMessageCreateEvent): string {
|
|
115
|
+
const mediaSummary = summarizeDiscordMedia(event)
|
|
116
|
+
if (mediaSummary.length === 0) return event.content
|
|
117
|
+
const summary = `[Discord message with ${mediaSummary.join('; ')}]`
|
|
118
|
+
return event.content === '' ? summary : `${event.content}\n${summary}`
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function summarizeDiscordMedia(event: DiscordGatewayMessageCreateEvent): string[] {
|
|
122
|
+
return [
|
|
123
|
+
...(event.attachments ?? []).map(summarizeAttachment),
|
|
124
|
+
...(event.embeds ?? []).map(summarizeEmbed),
|
|
125
|
+
...(event.sticker_items ?? []).map(summarizeSticker),
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function summarizeAttachment(attachment: DiscordFile): string {
|
|
130
|
+
return compactJoin(' ', [
|
|
131
|
+
`attachment: ${attachment.filename}`,
|
|
132
|
+
attachment.content_type === undefined ? undefined : `(${attachment.content_type})`,
|
|
133
|
+
attachment.url,
|
|
134
|
+
])
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function summarizeEmbed(embed: DiscordGatewayEmbed): string {
|
|
138
|
+
const label = embed.title ?? embed.description ?? embed.url ?? embed.type ?? 'embed'
|
|
139
|
+
return compactJoin(' ', ['embed:', label, embed.url !== undefined && embed.url !== label ? embed.url : undefined])
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function summarizeSticker(sticker: DiscordGatewayStickerItem): string {
|
|
143
|
+
return `sticker: ${sticker.name}`
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function compactJoin(separator: string, parts: Array<string | undefined>): string {
|
|
147
|
+
return parts.filter((part) => part !== undefined && part !== '').join(separator)
|
|
148
|
+
}
|