@interactive-inc/claude-funnel 0.2.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.
- package/README.md +82 -26
- package/lib/funnel.ts +49 -5
- package/lib/index.ts +8 -2
- package/lib/modules/channels/channel-connector-ref-updater.ts +4 -0
- package/lib/modules/channels/funnel-channels.ts +50 -8
- package/lib/modules/claude/funnel-claude.ts +79 -1
- package/lib/modules/connectors/connector-config-schema.ts +16 -0
- package/lib/modules/connectors/connector-existence-checker.ts +3 -0
- package/lib/modules/connectors/discord-connector-schema.ts +9 -0
- package/lib/modules/connectors/funnel-callable-connector-store.ts +9 -0
- package/lib/modules/connectors/funnel-connector-stores.ts +24 -0
- package/lib/modules/connectors/funnel-connector-type-store.ts +24 -0
- package/lib/modules/connectors/funnel-connectors.ts +98 -77
- package/lib/modules/connectors/funnel-discord-adapter.ts +1 -1
- package/lib/modules/connectors/funnel-discord-listener.ts +1 -1
- package/lib/modules/connectors/funnel-discord-store.ts +84 -0
- package/lib/modules/connectors/funnel-gh-listener.ts +1 -1
- package/lib/modules/connectors/funnel-gh-store.ts +84 -0
- package/lib/modules/connectors/funnel-json-connector-store.ts +100 -0
- package/lib/modules/connectors/funnel-schedule-listener.ts +124 -0
- package/lib/modules/connectors/funnel-schedule-store.ts +178 -0
- package/lib/modules/connectors/funnel-slack-adapter.ts +1 -1
- package/lib/modules/connectors/funnel-slack-listener.ts +1 -1
- package/lib/modules/connectors/funnel-slack-store.ts +86 -0
- package/lib/modules/connectors/gh-connector-schema.ts +9 -0
- package/lib/modules/connectors/match-cron.ts +72 -0
- package/lib/modules/connectors/migrate-legacy-connectors.ts +77 -0
- package/lib/modules/connectors/schedule-connector-schema.ts +18 -0
- package/lib/modules/connectors/schedule-last-fired-store.ts +48 -0
- package/lib/modules/connectors/slack-connector-schema.ts +10 -0
- package/lib/modules/gateway/daemon.ts +30 -13
- package/lib/modules/mcp/channel-server.ts +1 -2
- package/lib/modules/profiles/funnel-profiles.ts +123 -0
- package/lib/modules/profiles/profile-channel-checker.ts +3 -0
- package/lib/modules/profiles/profile-channel-ref-updater.ts +3 -0
- package/lib/modules/repos/funnel-repositories.ts +4 -4
- package/lib/modules/router/to-request.ts +2 -5
- package/lib/modules/schedule/funnel-schedule.ts +34 -0
- package/lib/modules/settings/funnel-settings-store.ts +1 -2
- package/lib/modules/settings/mock-funnel-settings-reader.ts +1 -2
- package/lib/modules/settings/settings-schema.ts +3 -37
- package/lib/routes/claude/claude.help.ts +9 -4
- package/lib/routes/claude/claude.ts +44 -7
- package/lib/routes/connectors/add.help.ts +10 -4
- package/lib/routes/connectors/add.ts +10 -1
- package/lib/routes/connectors/routes.ts +6 -2
- package/lib/routes/connectors/schedules-add.help.ts +11 -0
- package/lib/routes/connectors/schedules-add.ts +33 -0
- package/lib/routes/connectors/schedules-group.help.ts +1 -0
- package/lib/routes/connectors/schedules-group.ts +38 -0
- package/lib/routes/connectors/schedules-remove.help.ts +3 -0
- package/lib/routes/connectors/schedules-remove.ts +17 -0
- package/lib/routes/connectors/set.ts +47 -5
- package/lib/routes/connectors/show.ts +9 -0
- package/lib/routes/profiles/add.help.ts +3 -0
- package/lib/routes/{agents → profiles}/add.ts +4 -4
- package/lib/routes/profiles/group.help.ts +16 -0
- package/lib/routes/profiles/group.ts +25 -0
- package/lib/routes/profiles/launch.help.ts +4 -0
- package/lib/routes/{agents → profiles}/launch.ts +9 -8
- package/lib/routes/profiles/remove.help.ts +3 -0
- package/lib/routes/{agents → profiles}/remove.ts +4 -4
- package/lib/routes/profiles/rename.help.ts +5 -0
- package/lib/routes/{agents → profiles}/rename.ts +4 -4
- package/lib/routes/profiles/routes.ts +18 -0
- package/lib/routes/profiles/set.help.ts +5 -0
- package/lib/routes/{agents → profiles}/set.ts +4 -4
- package/lib/routes/repos/add.help.ts +3 -2
- package/lib/routes/repos/add.ts +3 -2
- package/lib/routes/repos/group.help.ts +1 -1
- package/lib/routes/request/discord-help.ts +9 -0
- package/lib/routes/request/discord.help.ts +19 -0
- package/lib/routes/request/discord.ts +65 -0
- package/lib/routes/request/group.help.ts +15 -0
- package/lib/routes/request/group.ts +9 -0
- package/lib/routes/request/routes.ts +14 -0
- package/lib/routes/request/slack-help.ts +9 -0
- package/lib/routes/request/slack.help.ts +19 -0
- package/lib/routes/{connectors/call.ts → request/slack.ts} +24 -6
- package/lib/routes/status/status.help.ts +1 -1
- package/lib/routes/status/status.ts +7 -7
- package/lib/routes/update/routes.ts +4 -0
- package/lib/routes/update/update.help.ts +5 -0
- package/lib/routes/update/update.ts +21 -0
- package/lib/routes.ts +6 -2
- package/package.json +1 -1
- package/lib/modules/agents/funnel-agents.ts +0 -105
- package/lib/modules/connectors/resolve-listener.ts +0 -13
- package/lib/routes/agents/add.help.ts +0 -3
- package/lib/routes/agents/group.help.ts +0 -13
- package/lib/routes/agents/group.ts +0 -25
- package/lib/routes/agents/launch.help.ts +0 -3
- package/lib/routes/agents/remove.help.ts +0 -3
- package/lib/routes/agents/rename.help.ts +0 -5
- package/lib/routes/agents/routes.ts +0 -17
- package/lib/routes/agents/set.help.ts +0 -5
- package/lib/routes/connectors/call.help.ts +0 -17
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { FunnelSettingsReader } from "@/modules/settings/funnel-settings-reader"
|
|
2
|
-
import type { AgentConfig } from "@/modules/settings/settings-schema"
|
|
3
|
-
|
|
4
|
-
type Deps = {
|
|
5
|
-
store: FunnelSettingsReader
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export class FunnelAgents {
|
|
9
|
-
private readonly store: FunnelSettingsReader
|
|
10
|
-
|
|
11
|
-
constructor(deps: Deps) {
|
|
12
|
-
this.store = deps.store
|
|
13
|
-
Object.freeze(this)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
list(): AgentConfig[] {
|
|
17
|
-
return this.store.read().agents
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get(name: string): AgentConfig | null {
|
|
21
|
-
return this.list().find((a) => a.name === name) ?? null
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
add(config: AgentConfig): void {
|
|
25
|
-
const settings = this.store.read()
|
|
26
|
-
|
|
27
|
-
if (settings.agents.some((a) => a.name === config.name)) {
|
|
28
|
-
throw new Error(`agent "${config.name}" already exists`)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (!settings.channels.some((c) => c.name === config.channel)) {
|
|
32
|
-
throw new Error(`channel "${config.channel}" not found`)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (config.repo && !settings.repositories.some((r) => r.name === config.repo)) {
|
|
36
|
-
throw new Error(`repo "${config.repo}" not found`)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
settings.agents.push(config)
|
|
40
|
-
|
|
41
|
-
this.store.write(settings)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
remove(name: string): void {
|
|
45
|
-
const settings = this.store.read()
|
|
46
|
-
|
|
47
|
-
const index = settings.agents.findIndex((a) => a.name === name)
|
|
48
|
-
|
|
49
|
-
if (index < 0) throw new Error(`agent "${name}" not found`)
|
|
50
|
-
|
|
51
|
-
settings.agents.splice(index, 1)
|
|
52
|
-
|
|
53
|
-
this.store.write(settings)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
rename(oldName: string, newName: string): void {
|
|
57
|
-
const settings = this.store.read()
|
|
58
|
-
|
|
59
|
-
const agent = settings.agents.find((a) => a.name === oldName)
|
|
60
|
-
|
|
61
|
-
if (!agent) throw new Error(`agent "${oldName}" not found`)
|
|
62
|
-
|
|
63
|
-
if (settings.agents.some((a) => a.name === newName)) {
|
|
64
|
-
throw new Error(`agent "${newName}" already exists`)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
agent.name = newName
|
|
68
|
-
|
|
69
|
-
this.store.write(settings)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
update(name: string, fields: Partial<Omit<AgentConfig, "name">>): void {
|
|
73
|
-
const settings = this.store.read()
|
|
74
|
-
|
|
75
|
-
const agent = settings.agents.find((a) => a.name === name)
|
|
76
|
-
|
|
77
|
-
if (!agent) throw new Error(`agent "${name}" not found`)
|
|
78
|
-
|
|
79
|
-
if (fields.channel !== undefined) {
|
|
80
|
-
if (!settings.channels.some((c) => c.name === fields.channel)) {
|
|
81
|
-
throw new Error(`channel "${fields.channel}" not found`)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
agent.channel = fields.channel
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (fields.repo !== undefined) {
|
|
88
|
-
if (fields.repo && !settings.repositories.some((r) => r.name === fields.repo)) {
|
|
89
|
-
throw new Error(`repo "${fields.repo}" not found`)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
agent.repo = fields.repo || undefined
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (fields.subAgent !== undefined) {
|
|
96
|
-
agent.subAgent = fields.subAgent || undefined
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (fields.envFiles !== undefined) {
|
|
100
|
-
agent.envFiles = fields.envFiles
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
this.store.write(settings)
|
|
104
|
-
}
|
|
105
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { FunnelConnectorListener } from "@/modules/connectors/funnel-connector-listener"
|
|
2
|
-
import { FunnelDiscordListener } from "@/modules/connectors/funnel-discord-listener"
|
|
3
|
-
import { FunnelGhListener } from "@/modules/connectors/funnel-gh-listener"
|
|
4
|
-
import { FunnelSlackListener } from "@/modules/connectors/funnel-slack-listener"
|
|
5
|
-
import type { ConnectorConfig } from "@/modules/settings/settings-schema"
|
|
6
|
-
|
|
7
|
-
export const resolveListener = (config: ConnectorConfig): FunnelConnectorListener => {
|
|
8
|
-
if (config.type === "slack") return new FunnelSlackListener({ config })
|
|
9
|
-
if (config.type === "gh") return new FunnelGhListener({ config })
|
|
10
|
-
if (config.type === "discord") return new FunnelDiscordListener({ config })
|
|
11
|
-
|
|
12
|
-
throw new Error(`unsupported connector type: ${(config as { type: string }).type}`)
|
|
13
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export const help = `funnel agents — agent presets (extra)
|
|
2
|
-
|
|
3
|
-
usage: funnel agents [subcommand]
|
|
4
|
-
|
|
5
|
-
subcommands:
|
|
6
|
-
(none) list
|
|
7
|
-
add <name> --channel <ch> [--repo <r>] [--sub-agent <s>] [--env-file <f>]
|
|
8
|
-
remove <name> remove
|
|
9
|
-
<name> launch (sugar for fnl claude)
|
|
10
|
-
|
|
11
|
-
examples:
|
|
12
|
-
funnel agents add cto --channel prod-inbox --repo myapp --sub-agent cto
|
|
13
|
-
funnel agents cto`
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { z } from "zod"
|
|
2
|
-
import { factory } from "@/factory"
|
|
3
|
-
import { zValidator } from "@/modules/router/validator"
|
|
4
|
-
import { help } from "@/routes/agents/group.help"
|
|
5
|
-
|
|
6
|
-
export const agentsGroupHandler = factory.createHandlers(
|
|
7
|
-
zValidator("query", z.object({}), help),
|
|
8
|
-
(c) => {
|
|
9
|
-
const funnel = c.var.funnel
|
|
10
|
-
const agents = funnel.agents.list()
|
|
11
|
-
|
|
12
|
-
if (agents.length === 0) return c.text("no agents")
|
|
13
|
-
|
|
14
|
-
const lines = agents.map((agent) => {
|
|
15
|
-
const parts = [`channel=${agent.channel}`]
|
|
16
|
-
|
|
17
|
-
if (agent.repo) parts.push(`repo=${agent.repo}`)
|
|
18
|
-
if (agent.subAgent) parts.push(`subAgent=${agent.subAgent}`)
|
|
19
|
-
|
|
20
|
-
return `${agent.name} [${parts.join(", ")}]`
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
return c.text(lines.join("\n"))
|
|
24
|
-
},
|
|
25
|
-
)
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { factory } from "@/factory"
|
|
2
|
-
import { agentsAddHandler } from "@/routes/agents/add"
|
|
3
|
-
import { agentsGroupHandler } from "@/routes/agents/group"
|
|
4
|
-
import { agentsLaunchHandler } from "@/routes/agents/launch"
|
|
5
|
-
import { agentsRemoveHandler } from "@/routes/agents/remove"
|
|
6
|
-
import { agentsRenameHandler } from "@/routes/agents/rename"
|
|
7
|
-
import { agentsSetHandler } from "@/routes/agents/set"
|
|
8
|
-
|
|
9
|
-
export const agentsRoutes = factory
|
|
10
|
-
.createApp()
|
|
11
|
-
.get("/", ...agentsGroupHandler)
|
|
12
|
-
.put("/:name/rename/:newName", ...agentsRenameHandler)
|
|
13
|
-
.put("/rename/:name/:newName", ...agentsRenameHandler)
|
|
14
|
-
.post("/:name", ...agentsAddHandler)
|
|
15
|
-
.put("/:name", ...agentsSetHandler)
|
|
16
|
-
.delete("/:name", ...agentsRemoveHandler)
|
|
17
|
-
.get("/:name", ...agentsLaunchHandler)
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export const help = `funnel connectors <name> <method> <path> [body] — call a connector API
|
|
2
|
-
|
|
3
|
-
usage:
|
|
4
|
-
funnel connectors <name> <method> <path> [<json-body>]
|
|
5
|
-
|
|
6
|
-
<method>:
|
|
7
|
-
get / post / put / patch / delete / head / options
|
|
8
|
-
|
|
9
|
-
Slack examples (every API is posted via POST internally):
|
|
10
|
-
funnel connectors my-slack post chat.postMessage '{"channel":"D...","text":"hi"}'
|
|
11
|
-
funnel connectors my-slack post chat.update '{"channel":"D...","ts":"...","text":"edit"}'
|
|
12
|
-
funnel connectors my-slack post chat.delete '{"channel":"D...","ts":"..."}'
|
|
13
|
-
funnel connectors my-slack post users.info '{"user":"U..."}'
|
|
14
|
-
|
|
15
|
-
Discord examples (per HTTP method):
|
|
16
|
-
funnel connectors my-discord post channels/C/messages '{"content":"hi"}'
|
|
17
|
-
funnel connectors my-discord delete channels/C/messages/M`
|