@meowlynxsea/koi 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 (109) hide show
  1. package/LICENSE +34 -0
  2. package/NOTICE +35 -0
  3. package/README.md +15 -0
  4. package/bin/koi +12 -0
  5. package/dist/highlights-eq9cgrbb.scm +604 -0
  6. package/dist/highlights-ghv9g403.scm +205 -0
  7. package/dist/highlights-hk7bwhj4.scm +284 -0
  8. package/dist/highlights-r812a2qc.scm +150 -0
  9. package/dist/highlights-x6tmsnaa.scm +115 -0
  10. package/dist/injections-73j83es3.scm +27 -0
  11. package/dist/main.js +489918 -0
  12. package/dist/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
  13. package/dist/tree-sitter-markdown-411r6y9b.wasm +0 -0
  14. package/dist/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
  15. package/dist/tree-sitter-typescript-zxjzwt75.wasm +0 -0
  16. package/dist/tree-sitter-zig-e78zbjpm.wasm +0 -0
  17. package/package.json +51 -0
  18. package/src/agent/check-permissions.ts +239 -0
  19. package/src/agent/hooks/message-utils.ts +305 -0
  20. package/src/agent/hooks/types.ts +32 -0
  21. package/src/agent/hooks.ts +1560 -0
  22. package/src/agent/mode.ts +163 -0
  23. package/src/agent/monitor-registry.ts +308 -0
  24. package/src/agent/permission-ui.ts +71 -0
  25. package/src/agent/plan-ui.ts +74 -0
  26. package/src/agent/question-ui.ts +58 -0
  27. package/src/agent/session-fork.ts +299 -0
  28. package/src/agent/session-snapshots.ts +216 -0
  29. package/src/agent/session-store.ts +649 -0
  30. package/src/agent/session-tasks.ts +305 -0
  31. package/src/agent/session.ts +27 -0
  32. package/src/agent/subagent-registry.ts +176 -0
  33. package/src/agent/subagent.ts +194 -0
  34. package/src/agent/tool-orchestration.ts +55 -0
  35. package/src/agent/tools.ts +8 -0
  36. package/src/cli/args.ts +6 -0
  37. package/src/cli/commands.ts +5 -0
  38. package/src/commands/skills/index.ts +23 -0
  39. package/src/config/models.ts +6 -0
  40. package/src/config/settings.ts +392 -0
  41. package/src/main.tsx +64 -0
  42. package/src/services/mcp/client.ts +194 -0
  43. package/src/services/mcp/config.ts +232 -0
  44. package/src/services/mcp/connection-manager.ts +258 -0
  45. package/src/services/mcp/index.ts +80 -0
  46. package/src/services/mcp/mcp-commands.ts +114 -0
  47. package/src/services/mcp/stdio-transport.ts +246 -0
  48. package/src/services/mcp/types.ts +155 -0
  49. package/src/skills/SkillsMenu.tsx +370 -0
  50. package/src/skills/bundled/batch.ts +106 -0
  51. package/src/skills/bundled/debug.ts +86 -0
  52. package/src/skills/bundled/loremIpsum.ts +101 -0
  53. package/src/skills/bundled/remember.ts +97 -0
  54. package/src/skills/bundled/simplify.ts +100 -0
  55. package/src/skills/bundled/skillify.ts +123 -0
  56. package/src/skills/bundled/stuck.ts +101 -0
  57. package/src/skills/bundled/updateConfig.ts +228 -0
  58. package/src/skills/bundled.ts +46 -0
  59. package/src/skills/frontmatter.ts +179 -0
  60. package/src/skills/index.ts +87 -0
  61. package/src/skills/invoke.ts +231 -0
  62. package/src/skills/loader.ts +710 -0
  63. package/src/skills/substitution.ts +169 -0
  64. package/src/skills/types.ts +201 -0
  65. package/src/tools/agent.ts +143 -0
  66. package/src/tools/ask-user-question.ts +46 -0
  67. package/src/tools/bash.ts +148 -0
  68. package/src/tools/edit.ts +164 -0
  69. package/src/tools/glob.ts +102 -0
  70. package/src/tools/grep.ts +248 -0
  71. package/src/tools/index.ts +73 -0
  72. package/src/tools/list-mcp-resources.ts +74 -0
  73. package/src/tools/ls.ts +85 -0
  74. package/src/tools/mcp.ts +76 -0
  75. package/src/tools/monitor.ts +159 -0
  76. package/src/tools/plan-mode.ts +134 -0
  77. package/src/tools/read-mcp-resource.ts +79 -0
  78. package/src/tools/read.ts +137 -0
  79. package/src/tools/skill.ts +176 -0
  80. package/src/tools/task.ts +349 -0
  81. package/src/tools/types.ts +52 -0
  82. package/src/tools/webfetch-domains.ts +239 -0
  83. package/src/tools/webfetch.ts +533 -0
  84. package/src/tools/write.ts +101 -0
  85. package/src/tui/app.tsx +1178 -0
  86. package/src/tui/components/chat-panel.tsx +1071 -0
  87. package/src/tui/components/command-panel.tsx +261 -0
  88. package/src/tui/components/confirm-modal.tsx +135 -0
  89. package/src/tui/components/connect-modal.tsx +435 -0
  90. package/src/tui/components/connecting-modal.tsx +167 -0
  91. package/src/tui/components/edit-pending-modal.tsx +103 -0
  92. package/src/tui/components/exit-modal.tsx +131 -0
  93. package/src/tui/components/fork-modal.tsx +377 -0
  94. package/src/tui/components/image-preview-modal.tsx +141 -0
  95. package/src/tui/components/image-utils.ts +128 -0
  96. package/src/tui/components/info-bar.tsx +103 -0
  97. package/src/tui/components/input-box.tsx +352 -0
  98. package/src/tui/components/mcp/MCPSettings.tsx +386 -0
  99. package/src/tui/components/mcp/index.ts +7 -0
  100. package/src/tui/components/model-modal.tsx +310 -0
  101. package/src/tui/components/pending-area.tsx +88 -0
  102. package/src/tui/components/rename-modal.tsx +119 -0
  103. package/src/tui/components/session-modal.tsx +233 -0
  104. package/src/tui/components/side-bar.tsx +349 -0
  105. package/src/tui/components/tool-output.ts +6 -0
  106. package/src/tui/hooks/user-prompt-history.ts +114 -0
  107. package/src/tui/theme.ts +63 -0
  108. package/src/types/commands.ts +80 -0
  109. package/src/types/cross-spawn.d.ts +24 -0
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Tool metadata and shared types for Koi's custom tool system.
3
+ */
4
+
5
+ import type { ToolDefinition } from "@mariozechner/pi-coding-agent";
6
+ import type { AgentToolResult } from "@mariozechner/pi-coding-agent";
7
+
8
+ export interface ToolMetadata {
9
+ name: string;
10
+ isReadOnly: boolean;
11
+ isDestructive: boolean;
12
+ riskLevel: "low" | "medium" | "high";
13
+ }
14
+
15
+ export const TOOL_METADATA: Record<string, ToolMetadata> = {
16
+ read: { name: "read", isReadOnly: true, isDestructive: false, riskLevel: "low" },
17
+ grep: { name: "grep", isReadOnly: true, isDestructive: false, riskLevel: "low" },
18
+ glob: { name: "glob", isReadOnly: true, isDestructive: false, riskLevel: "low" },
19
+ ls: { name: "ls", isReadOnly: true, isDestructive: false, riskLevel: "low" },
20
+ bash: { name: "bash", isReadOnly: false, isDestructive: true, riskLevel: "high" },
21
+ edit: { name: "edit", isReadOnly: false, isDestructive: false, riskLevel: "medium" },
22
+ write: { name: "write", isReadOnly: false, isDestructive: true, riskLevel: "medium" },
23
+ webfetch: { name: "webfetch", isReadOnly: true, isDestructive: false, riskLevel: "low" },
24
+ taskCreate: { name: "taskCreate", isReadOnly: false, isDestructive: false, riskLevel: "low" },
25
+ taskGet: { name: "taskGet", isReadOnly: true, isDestructive: false, riskLevel: "low" },
26
+ taskList: { name: "taskList", isReadOnly: true, isDestructive: false, riskLevel: "low" },
27
+ taskUpdate: { name: "taskUpdate", isReadOnly: false, isDestructive: false, riskLevel: "low" },
28
+ askUserQuestion: { name: "askUserQuestion", isReadOnly: true, isDestructive: false, riskLevel: "low" },
29
+ enterPlanMode: { name: "enterPlanMode", isReadOnly: true, isDestructive: false, riskLevel: "low" },
30
+ exitPlanMode: { name: "exitPlanMode", isReadOnly: true, isDestructive: false, riskLevel: "low" },
31
+ agent: { name: "agent", isReadOnly: false, isDestructive: false, riskLevel: "medium" },
32
+ };
33
+
34
+ export type KoiToolName = keyof typeof TOOL_METADATA;
35
+
36
+ export function isReadOnlyTool(name: string): boolean {
37
+ return TOOL_METADATA[name]?.isReadOnly ?? false;
38
+ }
39
+
40
+ export function isDestructiveTool(name: string): boolean {
41
+ return TOOL_METADATA[name]?.isDestructive ?? false;
42
+ }
43
+
44
+ export type AnyToolDefinition = ToolDefinition;
45
+
46
+ /** AgentToolResult with optional isError flag for permission denials. */
47
+ export type ToolResultWithError<T> = AgentToolResult<T> & { isError?: boolean };
48
+
49
+ /** Extract a readable message from an unknown error value. */
50
+ export function getErrorMessage(err: unknown): string {
51
+ return err instanceof Error ? err.message : String(err);
52
+ }
@@ -0,0 +1,239 @@
1
+ /**
2
+ * WebFetchTool — 预批准域名列表与域名检查
3
+ *
4
+ * 抽离为独立模块,避免 check-permissions.ts 与 webfetch.ts 之间的循环依赖。
5
+ */
6
+
7
+ /** 危险/本地域名黑名单 */
8
+ export const DANGEROUS_DOMAINS: string[] = [
9
+ "localhost",
10
+ "127.0.0.1",
11
+ "0.0.0.0",
12
+ "[::1]",
13
+ "[::]",
14
+ ];
15
+
16
+ /** 预批准技术文档域名(127+ 条) */
17
+ export const PREAPPROVED_DOMAINS: string[] = [
18
+ /* Python */
19
+ "docs.python.org",
20
+ "python.org",
21
+ /* MDN / Web 标准 */
22
+ "developer.mozilla.org",
23
+ "mdn.dev",
24
+ /* TypeScript / JavaScript 运行时 */
25
+ "typescriptlang.org",
26
+ "nodejs.org",
27
+ "npmjs.com",
28
+ "deno.land",
29
+ "bun.sh",
30
+ /* React 生态 */
31
+ "react.dev",
32
+ "reactjs.org",
33
+ "nextjs.org",
34
+ "remix.run",
35
+ /* Vue / Angular / Svelte */
36
+ "vuejs.org",
37
+ "nuxt.com",
38
+ "angular.io",
39
+ "angular.cn",
40
+ "svelte.dev",
41
+ "solidjs.com",
42
+ /* Go */
43
+ "go.dev",
44
+ "golang.org",
45
+ "golang.google.cn",
46
+ "pkg.go.dev",
47
+ /* Rust */
48
+ "doc.rust-lang.org",
49
+ "rust-lang.org",
50
+ "docs.rs",
51
+ "crates.io",
52
+ /* Java / JVM */
53
+ "docs.oracle.com",
54
+ "spring.io",
55
+ "docs.spring.io",
56
+ "kotlinlang.org",
57
+ "docs.kotlinlang.org",
58
+ /* .NET */
59
+ "learn.microsoft.com",
60
+ "dotnet.microsoft.com",
61
+ "asp.net",
62
+ /* Swift / Apple */
63
+ "developer.apple.com",
64
+ "swift.org",
65
+ /* 云平台 */
66
+ "docs.aws.amazon.com",
67
+ "aws.amazon.com",
68
+ "cloud.google.com",
69
+ "developers.google.com",
70
+ "firebase.google.com",
71
+ "azure.microsoft.com",
72
+ "docs.digitalocean.com",
73
+ /* 数据库 */
74
+ "postgresql.org",
75
+ "docs.postgresql.org",
76
+ "mysql.com",
77
+ "dev.mysql.com",
78
+ "mongodb.com",
79
+ "docs.mongodb.com",
80
+ "redis.io",
81
+ "redis.com",
82
+ "sqlite.org",
83
+ "www.sqlite.org",
84
+ "neo4j.com",
85
+ "prisma.io",
86
+ "orm.drizzle.team",
87
+ "cassandra.apache.org",
88
+ "influxdata.com",
89
+ /* ML / AI / Data Science */
90
+ "pytorch.org",
91
+ "tensorflow.org",
92
+ "keras.io",
93
+ "huggingface.co",
94
+ "scikit-learn.org",
95
+ "scipy.org",
96
+ "numpy.org",
97
+ "pandas.pydata.org",
98
+ "matplotlib.org",
99
+ "jupyter.org",
100
+ "openai.com",
101
+ "platform.openai.com",
102
+ "docs.anthropic.com",
103
+ "langchain.com",
104
+ "python.langchain.com",
105
+ "docs.llamaindex.ai",
106
+ "mlflow.org",
107
+ /* 容器 / DevOps */
108
+ "docker.com",
109
+ "docs.docker.com",
110
+ "kubernetes.io",
111
+ "helm.sh",
112
+ "terraform.io",
113
+ "ansible.com",
114
+ "prometheus.io",
115
+ "grafana.com",
116
+ "grafana.org",
117
+ "nginx.org",
118
+ "nginx.com",
119
+ "traefik.io",
120
+ /* Git 托管 / CI */
121
+ "github.com",
122
+ "docs.github.com",
123
+ "gitlab.com",
124
+ "about.gitlab.com",
125
+ "bitbucket.org",
126
+ /* 包管理 / Registry */
127
+ "pypi.org",
128
+ "packagist.org",
129
+ "rubygems.org",
130
+ "nuget.org",
131
+ "mvnrepository.com",
132
+ /* 前端 / UI */
133
+ "tailwindcss.com",
134
+ "ui.shadcn.com",
135
+ "radix-ui.com",
136
+ "mui.com",
137
+ "vuetifyjs.com",
138
+ "ant.design",
139
+ "element-plus.org",
140
+ "storybook.js.org",
141
+ "figma.com",
142
+ "developers.figma.com",
143
+ /* 构建工具 */
144
+ "vitejs.dev",
145
+ "webpack.js.org",
146
+ "rollupjs.org",
147
+ "esbuild.github.io",
148
+ "swc.rs",
149
+ /* 测试 */
150
+ "jestjs.io",
151
+ "vitest.dev",
152
+ "cypress.io",
153
+ "playwright.dev",
154
+ /* Lint / Format */
155
+ "eslint.org",
156
+ "prettier.io",
157
+ /* 后端框架 */
158
+ "expressjs.com",
159
+ "fastify.dev",
160
+ "nestjs.com",
161
+ "docs.djangoproject.com",
162
+ "flask.palletsprojects.com",
163
+ "fastapi.tiangolo.com",
164
+ "pydantic.dev",
165
+ "sqlalchemy.org",
166
+ "laravel.com",
167
+ "rubyonrails.org",
168
+ "guides.rubyonrails.org",
169
+ /* 通信 / 消息队列 */
170
+ "kafka.apache.org",
171
+ "rabbitmq.com",
172
+ "docs.confluent.io",
173
+ "nats.io",
174
+ /* 搜索 / 大数据 */
175
+ "elastic.co",
176
+ "opensearch.org",
177
+ "spark.apache.org",
178
+ /* 文档 / 社区 */
179
+ "stackoverflow.com",
180
+ "stackexchange.com",
181
+ "wikipedia.org",
182
+ "dev.to",
183
+ "medium.com",
184
+ "github.io",
185
+ "gitlab.io",
186
+ /* API / 协议 */
187
+ "graphql.org",
188
+ "json-schema.org",
189
+ "openapi.org",
190
+ "swagger.io",
191
+ "postman.com",
192
+ /* 部署 / Serverless */
193
+ "vercel.com",
194
+ "netlify.com",
195
+ "cloudflare.com",
196
+ "workers.cloudflare.com",
197
+ "supabase.com",
198
+ "docs.supabase.com",
199
+ /* 移动开发 */
200
+ "reactnative.dev",
201
+ "expo.dev",
202
+ /* 游戏引擎 */
203
+ "unity.com",
204
+ "docs.unity3d.com",
205
+ "unrealengine.com",
206
+ "godotengine.org",
207
+ /* 安全 / 加密 */
208
+ "owasp.org",
209
+ "letsencrypt.org",
210
+ /* 版本控制 */
211
+ "git-scm.com",
212
+ /* 操作系统 / 内核 */
213
+ "kernel.org",
214
+ "man7.org",
215
+ "freebsd.org",
216
+ ];
217
+
218
+ /** 检查主机名是否为本地/IP/危险地址 */
219
+ export function isDangerousHost(hostname: string): boolean {
220
+ const h = hostname.toLowerCase();
221
+ if (DANGEROUS_DOMAINS.some((d) => h === d || h.endsWith(`.${d}`))) return true;
222
+ if (/^\d+\.\d+\.\d+\.\d+$/.test(h)) return true;
223
+ if (h.startsWith("[") && h.endsWith("]")) return true;
224
+ return false;
225
+ }
226
+
227
+ /** 判断 URL 是否属于预批准域名 */
228
+ export function isPreapprovedDomain(url: string): boolean {
229
+ try {
230
+ const parsed = new URL(url);
231
+ const hostname = parsed.hostname.toLowerCase();
232
+ if (isDangerousHost(hostname)) return false;
233
+ return PREAPPROVED_DOMAINS.some(
234
+ (d) => hostname === d || hostname.endsWith(`.${d}`)
235
+ );
236
+ } catch {
237
+ return false;
238
+ }
239
+ }