Jelajahi Sumber

fix(v0.6.4): 10s fallback force-load if renderer stuck + elapsed counter

KirinCode 1 bulan lalu
induk
melakukan
e32cae28ea
38 mengubah file dengan 99 tambahan dan 37 penghapusan
  1. 2 1
      KIRINCODE.md
  2. 2 0
      NOTICE.md
  3. 21 0
      README.md
  4. 1 1
      packages/app/package.json
  5. 1 1
      packages/cli/package.json
  6. 1 1
      packages/codemode/package.json
  7. 1 1
      packages/console/app/package.json
  8. 1 1
      packages/console/core/package.json
  9. 1 1
      packages/console/function/package.json
  10. 1 1
      packages/console/mail/package.json
  11. 1 1
      packages/console/support/package.json
  12. 1 1
      packages/core/package.json
  13. 1 1
      packages/desktop/package.json
  14. 16 2
      packages/desktop/src/renderer/index.tsx
  15. 1 1
      packages/effect-drizzle-sqlite/package.json
  16. 1 1
      packages/effect-sqlite-node/package.json
  17. 1 1
      packages/enterprise/package.json
  18. 1 1
      packages/function/package.json
  19. 1 1
      packages/http-recorder/package.json
  20. 1 1
      packages/kirincode-cloud/package.json
  21. 24 0
      packages/kirincode-core/src/commands.ts
  22. 1 1
      packages/kirincode-core/src/index.ts
  23. 2 2
      packages/kirincode-core/src/subagent.ts
  24. 1 1
      packages/kirincode-workflow/package.json
  25. 1 1
      packages/kirincode/package.json
  26. 1 1
      packages/llm/package.json
  27. 1 1
      packages/mobile/package.json
  28. 1 1
      packages/plugin/package.json
  29. 1 1
      packages/sdk/js/package.json
  30. 1 1
      packages/server/package.json
  31. 1 1
      packages/session-ui/package.json
  32. 1 1
      packages/slack/package.json
  33. 1 1
      packages/stats/app/package.json
  34. 1 1
      packages/stats/core/package.json
  35. 1 1
      packages/stats/server/package.json
  36. 1 1
      packages/tui/package.json
  37. 1 1
      packages/ui/package.json
  38. 1 1
      packages/web/package.json

+ 2 - 1
KIRINCODE.md

@@ -39,7 +39,8 @@ KIRINCODE_CHANNEL=prod bun x electron-builder --win --x64 --config electron-buil
 ## 项目结构
 
 - `packages/kirincode/` — 核心 CLI + TUI 引擎
-- `packages/kirincode-core/` — 自动记忆 + 技能系统插件
+- `packages/kirincode-core/` — 自动记忆 + 技能系统 + 多子智能体插件
+- `packages/kirincode-workflow/` — 工作流引擎(定时任务、文件触发、后台智能体)
 - `packages/desktop/` — Electron 桌面应用
 - `packages/tui/` — 终端 UI 框架
 - `packages/core/` — 核心共享库

+ 2 - 0
NOTICE.md

@@ -13,6 +13,8 @@ Modifications include but are not limited to:
 - Brand identity: product name "KirinCode", command "kirincode"
 - Auto-memory plugin: @kirincode-ai/kirincode-core (packages/kirincode-core/)
 - Skills system: SKILL.md support, skill registry, self-learning engine
+- Multi-sub-agent: parallel sub-agent spawning, status tracking, result collection
+- Workflow engine: scheduled tasks, file-change triggers, background agents
 - Custom theme: "kirincode" theme (麒麟 red + gold palette)
 - Default configuration: kirincode.json with sharing disabled
 - Desktop app branding: KirinCode icon, title, tray menu

+ 21 - 0
README.md

@@ -10,6 +10,7 @@
 
 - **自动记忆** — AI 自主记录项目经验,跨会话学习
 - **技能系统** — 可复用工作流,手动/自动调用
+- **多子智能体** — 并行派生子智能体,分治复杂任务
 - **75+ LLM 提供商** — 兼容所有主流模型
 - **5 个内置 Agent** — Build / Plan / General / Explore / Scout
 - **MCP 协议** — 连接外部工具和数据源
@@ -42,6 +43,8 @@ kirincode              # 启动 TUI
 /memory                # 查看自动记忆
 /skill list            # 列出可用技能
 /skill create my-skill "描述"  # 创建新技能
+/subagent list         # 列出子智能体
+/subagent collect <name>  # 收集子智能体结果
 ```
 
 ### 配置
@@ -84,6 +87,23 @@ tools: Read, Grep, Glob
 4. 边界条件处理
 ```
 
+## 多子智能体
+
+KirinCode 支持通过 `subagent_spawn` 工具并行派生多个子智能体,每个子智能体在独立的 Session 中运行:
+
+```
+subagent_spawn(name: "review", task: "审查 src/ 下的代码安全漏洞", agent: "explore")
+subagent_spawn(name: "test", task: "为核心模块补充单元测试", agent: "build")
+subagent_list()                    # 查看所有子智能体状态
+subagent_collect("review")        # 等待并收集结果
+subagent_collect("test")
+```
+
+也可通过 `/subagent` 命令管理:
+- `/subagent list` — 列出所有子智能体
+- `/subagent status <name>` — 查看详情
+- `/subagent collect <name>` — 收集结果
+
 ## 与 OpenCode 的关系
 
 KirinCode 是 OpenCode 的分叉项目,主要差异:
@@ -92,6 +112,7 @@ KirinCode 是 OpenCode 的分叉项目,主要差异:
 |------|----------|-----------|
 | 自动记忆 | ❌ | ✅ 内置 |
 | 技能系统 | 基础 | ✅ 增强 |
+| 多子智能体 | ❌ | ✅ 内置 |
 | 品牌主题 | opencode theme | kirincode (麒麟) theme |
 | Zen/Go 服务 | ✅ 官方付费 | ❌ 已移除 |
 | 数据共享 | 可选 | 默认关闭 |

+ 1 - 1
packages/app/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@kirincode-ai/app",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "description": "",
   "type": "module",
   "exports": {

+ 1 - 1
packages/cli/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@kirincode-ai/cli",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "type": "module",
   "license": "MIT",
   "bin": {

+ 1 - 1
packages/codemode/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@kirincode-ai/codemode",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "description": "Effect-native confined code execution over schema-described tools",
   "private": true,
   "type": "module",

+ 1 - 1
packages/console/app/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@kirincode-ai/console-app",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "type": "module",
   "license": "MIT",
   "scripts": {

+ 1 - 1
packages/console/core/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@kirincode-ai/console-core",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "private": true,
   "type": "module",
   "license": "MIT",

+ 1 - 1
packages/console/function/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@kirincode-ai/console-function",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "$schema": "https://json.schemastore.org/package.json",
   "private": true,
   "type": "module",

+ 1 - 1
packages/console/mail/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@kirincode-ai/console-mail",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "dependencies": {
     "@jsx-email/all": "2.2.3",
     "@jsx-email/cli": "1.4.3",

+ 1 - 1
packages/console/support/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@kirincode-ai/console-support",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "type": "module",
   "license": "MIT",
   "scripts": {

+ 1 - 1
packages/core/package.json

@@ -1,6 +1,6 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "name": "@kirincode-ai/core",
   "type": "module",
   "license": "MIT",

+ 1 - 1
packages/desktop/package.json

@@ -1,7 +1,7 @@
 {
   "name": "@kirincode-ai/desktop",
   "private": true,
-  "version": "0.6.3",
+  "version": "0.6.4",
   "type": "module",
   "license": "MIT",
   "homepage": "https://kirincode.ai",

+ 16 - 2
packages/desktop/src/renderer/index.tsx

@@ -317,10 +317,15 @@ window.api.onMenuCommand((id) => {
 listenForDeepLinks()
 
 function LoadingSplash() {
+  const [elapsed, setElapsed] = createSignal(0)
+  onMount(() => {
+    const i = setInterval(() => setElapsed(e => e + 1), 1000)
+    return () => clearInterval(i)
+  })
   return (
     <div class="h-dvh w-screen flex flex-col items-center justify-center bg-background-base">
       <Splash class="w-16 h-20 opacity-50 animate-pulse" />
-      <span class="text-14-medium text-text-muted mt-4">正在启动 KirinCode</span>
+      <span class="text-13-medium text-text-muted mt-4">正在启动 KirinCode ({elapsed()}s)</span>
     </div>
   )
 }
@@ -382,6 +387,15 @@ function DesktopRoot(props: { windowState: DesktopWindowState }) {
     const ready = createMemo(
       () => !defaultServer.loading && !sidecar.loading && !windowCount.loading && !locale.loading,
     )
+    // Fallback: force loading complete after sidecar is ready + 10 seconds
+    const [forceReady, setForceReady] = createSignal(false)
+    createEffect(() => {
+      if (!sidecar.loading && sidecar.latest && !forceReady()) {
+        const t = setTimeout(() => setForceReady(true), 10000)
+        onCleanup(() => clearTimeout(t))
+      }
+    })
+    const effectiveReady = createMemo(() => ready() || forceReady())
     const servers = createMemo(() => {
       const data = initializationData(sidecar)
       const list: ServerConnection.Any[] = []
@@ -404,7 +418,7 @@ function DesktopRoot(props: { windowState: DesktopWindowState }) {
       ServerConnection.Key.make(availableStartupServer(defaultServer.latest, wslServers.data)),
     )
     return (
-      <Show when={ready()} fallback={<LoadingSplash />}>
+      <Show when={effectiveReady()} fallback={<LoadingSplash />}>
         <Show when={effectiveDefaultServer()} keyed>
           {(key) => (
             <AppInterface

+ 1 - 1
packages/effect-drizzle-sqlite/package.json

@@ -1,6 +1,6 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "name": "@kirincode-ai/effect-drizzle-sqlite",
   "type": "module",
   "license": "MIT",

+ 1 - 1
packages/effect-sqlite-node/package.json

@@ -1,6 +1,6 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "name": "@kirincode-ai/effect-sqlite-node",
   "type": "module",
   "license": "MIT",

+ 1 - 1
packages/enterprise/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@kirincode-ai/enterprise",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "private": true,
   "type": "module",
   "license": "MIT",

+ 1 - 1
packages/function/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@kirincode-ai/function",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "$schema": "https://json.schemastore.org/package.json",
   "private": true,
   "type": "module",

+ 1 - 1
packages/http-recorder/package.json

@@ -1,6 +1,6 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "name": "@kirincode-ai/http-recorder",
   "description": "Record and replay Effect HTTP client traffic with deterministic cassettes",
   "type": "module",

+ 1 - 1
packages/kirincode-cloud/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@kirincode-ai/kirincode-cloud",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "type": "module",
   "description": "KirinCode Cloud Sync Server — multi-user backend with session sync, memory, skills, workflows",
   "license": "MIT",

+ 24 - 0
packages/kirincode-core/src/commands.ts

@@ -1,6 +1,7 @@
 import type { Part } from "@kirincode-ai/sdk"
 import type { MemoryStore } from "./memory"
 import type { SkillRegistry } from "./skills"
+import type { SubAgentRegistry } from "./subagent"
 
 let partSeq = 0
 
@@ -67,3 +68,26 @@ export async function handleSkillCommand(args: string, registry: SkillRegistry,
   const content = registry.injectSkill(sub)
   return [textPart(content, sessionID)]
 }
+
+export async function handleSubAgentCommand(args: string, subagents: SubAgentRegistry, sessionID: string): Promise<Part[]> {
+  const sub = args.trim()
+  if (!sub || sub === "list") {
+    const list = subagents.list()
+    if (list.length === 0) return [textPart("No sub-agents spawned. Use the subagent_spawn tool to create one.", sessionID)]
+    const lines = list.map((a) => {
+      const icon = a.status === "completed" ? "✅" : a.status === "failed" ? "❌" : a.status === "spawning" ? "⏳" : "🔄"
+      return `- ${icon} **${a.name}** — ${a.status} — ${a.task.slice(0, 60)}${a.task.length > 60 ? "..." : ""}`
+    })
+    return [textPart(["## Sub-Agents", "", ...lines].join("\n"), sessionID)]
+  }
+  if (sub.startsWith("status ")) {
+    const name = sub.slice(7).trim()
+    return [textPart(subagents.status(name), sessionID)]
+  }
+  if (sub.startsWith("collect ")) {
+    const name = sub.slice(8).trim()
+    const result = await subagents.collect(name)
+    return [textPart(result, sessionID)]
+  }
+  return [textPart("Usage: /subagent [list|status <name>|collect <name>]", sessionID)]
+}

+ 1 - 1
packages/kirincode-core/src/index.ts

@@ -49,7 +49,7 @@ export const KirinCodePlugin: Plugin = async ({ client, project, directory, work
         output.parts = await handleSkillCommand(input.arguments, registry, worktree, input.sessionID)
       }
       if (input.command === "subagent") {
-        output.parts = await handleSubAgentCommand(input.arguments, subagents)
+        output.parts = await handleSubAgentCommand(input.arguments, subagents, input.sessionID)
       }
     },
 

+ 2 - 2
packages/kirincode-core/src/subagent.ts

@@ -53,7 +53,7 @@ export class SubAgentRegistry {
     }
 
     this.agents.set(opts.name, def)
-    const promise = this.executeSubAgent(client, parentSessionID, def, opts)
+    const promise = this.executeSubAgent(client, parentSessionID, def, { task: opts.task, agent: opts.agent })
     this.promises.set(opts.name, promise)
     return def
   }
@@ -62,7 +62,7 @@ export class SubAgentRegistry {
     client: Client,
     parentSessionID: string,
     def: SubAgentDef,
-    opts: { task: string; agent?: string; model?: { providerID: string; modelID: string } },
+    opts: { task: string; agent?: string },
   ): Promise<void> {
     try {
       const createResult = await client.session.create({

+ 1 - 1
packages/kirincode-workflow/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@kirincode-ai/kirincode-workflow",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "type": "module",
   "description": "KirinCode workflow engine — scheduled tasks, event triggers, background agents",
   "license": "MIT",

+ 1 - 1
packages/kirincode/package.json

@@ -1,6 +1,6 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "name": "kirincode",
   "type": "module",
   "license": "MIT",

+ 1 - 1
packages/llm/package.json

@@ -1,6 +1,6 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "name": "@kirincode-ai/llm",
   "type": "module",
   "license": "MIT",

+ 1 - 1
packages/mobile/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@kirincode-ai/mobile",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "private": true,
   "scripts": {
     "start": "expo start",

+ 1 - 1
packages/plugin/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@kirincode-ai/plugin",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "type": "module",
   "license": "MIT",
   "scripts": {

+ 1 - 1
packages/sdk/js/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@kirincode-ai/sdk",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "type": "module",
   "license": "MIT",
   "scripts": {

+ 1 - 1
packages/server/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@kirincode-ai/server",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "private": true,
   "type": "module",
   "license": "MIT",

+ 1 - 1
packages/session-ui/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@kirincode-ai/session-ui",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "private": true,
   "type": "module",
   "license": "MIT",

+ 1 - 1
packages/slack/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@kirincode-ai/slack",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "type": "module",
   "license": "MIT",
   "scripts": {

+ 1 - 1
packages/stats/app/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@kirincode-ai/stats-app",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "private": true,
   "type": "module",
   "license": "MIT",

+ 1 - 1
packages/stats/core/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@kirincode-ai/stats-core",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "private": true,
   "type": "module",
   "license": "MIT",

+ 1 - 1
packages/stats/server/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@kirincode-ai/stats-server",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "private": true,
   "type": "module",
   "license": "MIT",

+ 1 - 1
packages/tui/package.json

@@ -1,7 +1,7 @@
 {
   "$schema": "https://json.schemastore.org/package.json",
   "name": "@kirincode-ai/tui",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "private": true,
   "type": "module",
   "license": "MIT",

+ 1 - 1
packages/ui/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@kirincode-ai/ui",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "type": "module",
   "license": "MIT",
   "repository": {

+ 1 - 1
packages/web/package.json

@@ -2,7 +2,7 @@
   "name": "@kirincode-ai/web",
   "type": "module",
   "license": "MIT",
-  "version": "0.6.3",
+  "version": "0.6.4",
   "scripts": {
     "dev": "astro dev",
     "dev:remote": "VITE_API_URL=https://api.kirincode.ai astro dev",