agim-cli 1.4.9 → 1.5.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/CHANGELOG.md +415 -402
- package/README.md +4 -4
- package/bin/agim_rpc.py +12 -12
- package/dist/cli-ui/cmd-handlers.d.ts +3 -3
- package/dist/cli-ui/cmd-handlers.d.ts.map +1 -1
- package/dist/cli-ui/cmd-handlers.js +11 -19
- package/dist/cli-ui/cmd-handlers.js.map +1 -1
- package/dist/cli-ui/config-wizard.js +27 -27
- package/dist/cli-ui/config-wizard.js.map +1 -1
- package/dist/cli-ui/env-file.d.ts +4 -4
- package/dist/cli-ui/env-file.js +13 -13
- package/dist/cli-ui/env-file.js.map +1 -1
- package/dist/cli-ui/i18n.d.ts +2 -2
- package/dist/cli-ui/i18n.js +9 -9
- package/dist/cli-ui/i18n.js.map +1 -1
- package/dist/cli-ui/lang-picker.js +1 -1
- package/dist/cli-ui/lang-picker.js.map +1 -1
- package/dist/cli-ui/paths.d.ts.map +1 -1
- package/dist/cli-ui/paths.js +2 -4
- package/dist/cli-ui/paths.js.map +1 -1
- package/dist/cli-ui/service.d.ts +7 -7
- package/dist/cli-ui/service.d.ts.map +1 -1
- package/dist/cli-ui/service.js +57 -72
- package/dist/cli-ui/service.js.map +1 -1
- package/dist/cli-ui/tui/app.js +2 -2
- package/dist/cli-ui/tui/app.js.map +1 -1
- package/dist/cli-ui/tui/index.js +6 -6
- package/dist/cli-ui/tui/index.js.map +1 -1
- package/dist/cli-ui/tui/mouse-stdin.js +1 -1
- package/dist/cli-ui/tui/mouse-stdin.js.map +1 -1
- package/dist/cli-ui/tui/stream-reveal.d.ts +2 -2
- package/dist/cli-ui/tui/stream-reveal.d.ts.map +1 -1
- package/dist/cli-ui/tui/stream-reveal.js +4 -4
- package/dist/cli-ui/tui/stream-reveal.js.map +1 -1
- package/dist/cli.js +24 -45
- package/dist/cli.js.map +1 -1
- package/dist/core/a2a-notify.js +5 -5
- package/dist/core/a2a-notify.js.map +1 -1
- package/dist/core/a2a.d.ts +2 -2
- package/dist/core/a2a.d.ts.map +1 -1
- package/dist/core/a2a.js +12 -12
- package/dist/core/a2a.js.map +1 -1
- package/dist/core/access-token.d.ts +1 -1
- package/dist/core/access-token.js +7 -7
- package/dist/core/access-token.js.map +1 -1
- package/dist/core/acp-server.js +5 -5
- package/dist/core/acp-server.js.map +1 -1
- package/dist/core/admin-allowlist.js +5 -5
- package/dist/core/admin-allowlist.js.map +1 -1
- package/dist/core/agent-base.d.ts +1 -1
- package/dist/core/agent-base.js +3 -3
- package/dist/core/agent-base.js.map +1 -1
- package/dist/core/agent-cwd.d.ts +5 -6
- package/dist/core/agent-cwd.d.ts.map +1 -1
- package/dist/core/agent-cwd.js +15 -16
- package/dist/core/agent-cwd.js.map +1 -1
- package/dist/core/agim-paths.d.ts +1 -4
- package/dist/core/agim-paths.d.ts.map +1 -1
- package/dist/core/agim-paths.js +18 -35
- package/dist/core/agim-paths.js.map +1 -1
- package/dist/core/approval-bus.d.ts +4 -4
- package/dist/core/approval-bus.d.ts.map +1 -1
- package/dist/core/approval-bus.js +14 -14
- package/dist/core/approval-bus.js.map +1 -1
- package/dist/core/approval-router.js +2 -2
- package/dist/core/artifacts.js +3 -3
- package/dist/core/artifacts.js.map +1 -1
- package/dist/core/ask-user-rpc.js +1 -1
- package/dist/core/ask-user-rpc.js.map +1 -1
- package/dist/core/audit-log.js +2 -2
- package/dist/core/audit-log.js.map +1 -1
- package/dist/core/bgjob-reader.d.ts +1 -1
- package/dist/core/bgjob-reader.js +4 -4
- package/dist/core/bgjob-reader.js.map +1 -1
- package/dist/core/commands/approval.js +2 -2
- package/dist/core/commands/approval.js.map +1 -1
- package/dist/core/commands/heartbeat.js +2 -2
- package/dist/core/commands/heartbeat.js.map +1 -1
- package/dist/core/commands/memo.js +1 -1
- package/dist/core/commands/memo.js.map +1 -1
- package/dist/core/commands/model.js +1 -1
- package/dist/core/commands/model.js.map +1 -1
- package/dist/core/commands/plan.js +3 -3
- package/dist/core/commands/plan.js.map +1 -1
- package/dist/core/commands/router-compare.js +3 -3
- package/dist/core/commands/router-compare.js.map +1 -1
- package/dist/core/commands/service.d.ts.map +1 -1
- package/dist/core/commands/service.js +1 -3
- package/dist/core/commands/service.js.map +1 -1
- package/dist/core/commands/sessions.js +4 -4
- package/dist/core/commands/sessions.js.map +1 -1
- package/dist/core/commands/skill.js +1 -1
- package/dist/core/commands/skill.js.map +1 -1
- package/dist/core/commands/stats.js +1 -1
- package/dist/core/commands/stats.js.map +1 -1
- package/dist/core/commands/web.js +5 -5
- package/dist/core/commands/web.js.map +1 -1
- package/dist/core/config-schema.js +1 -1
- package/dist/core/coord-systems.d.ts +1 -1
- package/dist/core/coord-systems.js +4 -4
- package/dist/core/coord-systems.js.map +1 -1
- package/dist/core/event-bus.d.ts +5 -5
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js +3 -3
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/feature-flags.d.ts +2 -2
- package/dist/core/feature-flags.js +4 -4
- package/dist/core/feature-flags.js.map +1 -1
- package/dist/core/goal-rpc.js +2 -2
- package/dist/core/goal-rpc.js.map +1 -1
- package/dist/core/goals.d.ts +1 -1
- package/dist/core/goals.js +3 -3
- package/dist/core/goals.js.map +1 -1
- package/dist/core/heartbeat-store.d.ts +1 -1
- package/dist/core/heartbeat-store.d.ts.map +1 -1
- package/dist/core/heartbeat-store.js +3 -3
- package/dist/core/heartbeat-store.js.map +1 -1
- package/dist/core/heartbeat.js +4 -4
- package/dist/core/heartbeat.js.map +1 -1
- package/dist/core/intent-llm.d.ts +2 -2
- package/dist/core/intent-llm.js +5 -5
- package/dist/core/intent-llm.js.map +1 -1
- package/dist/core/job-board.d.ts +5 -5
- package/dist/core/job-board.d.ts.map +1 -1
- package/dist/core/job-board.js +17 -17
- package/dist/core/job-board.js.map +1 -1
- package/dist/core/llm/agent-loop.d.ts +3 -3
- package/dist/core/llm/agent-loop.js +14 -14
- package/dist/core/llm/agent-loop.js.map +1 -1
- package/dist/core/llm/{imhub-dispatcher.d.ts → agim-dispatcher.d.ts} +4 -4
- package/dist/core/llm/agim-dispatcher.d.ts.map +1 -0
- package/dist/core/llm/{imhub-dispatcher.js → agim-dispatcher.js} +43 -43
- package/dist/core/llm/agim-dispatcher.js.map +1 -0
- package/dist/core/llm/agim-rpc-server.js +17 -17
- package/dist/core/llm/agim-rpc-server.js.map +1 -1
- package/dist/core/llm/auto-compact.d.ts +3 -3
- package/dist/core/llm/auto-compact.d.ts.map +1 -1
- package/dist/core/llm/auto-compact.js +5 -5
- package/dist/core/llm/auto-compact.js.map +1 -1
- package/dist/core/llm/builtin-dispatcher.js +3 -3
- package/dist/core/llm/builtin-dispatcher.js.map +1 -1
- package/dist/core/llm/exec-dispatcher.d.ts +2 -2
- package/dist/core/llm/exec-dispatcher.d.ts.map +1 -1
- package/dist/core/llm/exec-dispatcher.js +20 -22
- package/dist/core/llm/exec-dispatcher.js.map +1 -1
- package/dist/core/llm/fs-dispatcher.js +8 -8
- package/dist/core/llm/fs-dispatcher.js.map +1 -1
- package/dist/core/llm/goal-critic.js +4 -4
- package/dist/core/llm/goal-critic.js.map +1 -1
- package/dist/core/llm/hallucination-detector.js +2 -2
- package/dist/core/llm/hallucination-detector.js.map +1 -1
- package/dist/core/llm/mcp-client.d.ts +1 -1
- package/dist/core/llm/mcp-client.js +3 -3
- package/dist/core/llm/mcp-client.js.map +1 -1
- package/dist/core/llm/mcp-registry.js +3 -3
- package/dist/core/llm/mcp-registry.js.map +1 -1
- package/dist/core/llm/openai-compat-provider.d.ts +1 -1
- package/dist/core/llm/openai-compat-provider.js +2 -2
- package/dist/core/llm/openai-compat-provider.js.map +1 -1
- package/dist/core/llm/provider-base.d.ts +1 -1
- package/dist/core/llm/secrets.d.ts +2 -2
- package/dist/core/llm/secrets.d.ts.map +1 -1
- package/dist/core/llm/tool-dispatcher.d.ts +1 -1
- package/dist/core/llm/web-dispatcher.d.ts +1 -1
- package/dist/core/llm/web-dispatcher.js +15 -15
- package/dist/core/llm/web-dispatcher.js.map +1 -1
- package/dist/core/logger.d.ts +1 -1
- package/dist/core/logger.js +3 -3
- package/dist/core/logger.js.map +1 -1
- package/dist/core/memo-rpc.js +3 -3
- package/dist/core/memo-rpc.js.map +1 -1
- package/dist/core/memory-consolidate.js +4 -4
- package/dist/core/memory-consolidate.js.map +1 -1
- package/dist/core/memory-distill.js +4 -4
- package/dist/core/memory-distill.js.map +1 -1
- package/dist/core/memory-distiller.js +9 -9
- package/dist/core/memory-distiller.js.map +1 -1
- package/dist/core/memory-vector.js +9 -9
- package/dist/core/memory-vector.js.map +1 -1
- package/dist/core/memory.js +2 -2
- package/dist/core/memory.js.map +1 -1
- package/dist/core/memos.js +6 -6
- package/dist/core/memos.js.map +1 -1
- package/dist/core/message-sink.js +13 -13
- package/dist/core/message-sink.js.map +1 -1
- package/dist/core/notification-evaluator.d.ts +2 -2
- package/dist/core/notification-evaluator.js +4 -4
- package/dist/core/notification-evaluator.js.map +1 -1
- package/dist/core/onboarding.js +3 -3
- package/dist/core/onboarding.js.map +1 -1
- package/dist/core/outbox.js +2 -2
- package/dist/core/outbox.js.map +1 -1
- package/dist/core/persona.d.ts +1 -1
- package/dist/core/persona.d.ts.map +1 -1
- package/dist/core/persona.js +2 -2
- package/dist/core/persona.js.map +1 -1
- package/dist/core/plan-history.js +1 -1
- package/dist/core/plan-history.js.map +1 -1
- package/dist/core/plan-intent.js +5 -5
- package/dist/core/plan-intent.js.map +1 -1
- package/dist/core/plan-mode-state.d.ts +1 -1
- package/dist/core/plan-mode-state.js +4 -4
- package/dist/core/plan-mode-state.js.map +1 -1
- package/dist/core/push-rpc.d.ts +1 -1
- package/dist/core/push-rpc.js +6 -6
- package/dist/core/push-rpc.js.map +1 -1
- package/dist/core/registry.d.ts +4 -4
- package/dist/core/registry.js +10 -10
- package/dist/core/registry.js.map +1 -1
- package/dist/core/reminders.js +1 -1
- package/dist/core/reminders.js.map +1 -1
- package/dist/core/restart-flow.d.ts.map +1 -1
- package/dist/core/restart-flow.js +5 -7
- package/dist/core/restart-flow.js.map +1 -1
- package/dist/core/router.d.ts +1 -1
- package/dist/core/router.js +5 -5
- package/dist/core/router.js.map +1 -1
- package/dist/core/schedule.d.ts +2 -2
- package/dist/core/schedule.js +4 -4
- package/dist/core/schedule.js.map +1 -1
- package/dist/core/self-protect.js +3 -3
- package/dist/core/self-protect.js.map +1 -1
- package/dist/core/sender-allowlist.js +7 -7
- package/dist/core/sender-allowlist.js.map +1 -1
- package/dist/core/sensitive-paths.d.ts.map +1 -1
- package/dist/core/sensitive-paths.js +1 -2
- package/dist/core/sensitive-paths.js.map +1 -1
- package/dist/core/session.js +2 -2
- package/dist/core/session.js.map +1 -1
- package/dist/core/skills/builtin/ECC_NOTICE.md +1 -1
- package/dist/core/skills/builtin/agim-memory/SKILL.md +1 -1
- package/dist/core/skills/builtin/agim-reminders/SKILL.md +2 -2
- package/dist/core/skills/builtin/agim-self/SKILL.md +9 -9
- package/dist/core/skills/builtin/agim-skill-discovery/SKILL.md +5 -5
- package/dist/core/skills/builtin/image-generation/SKILL.md +2 -2
- package/dist/core/skills/builtin/long-goal/SKILL.md +7 -7
- package/dist/core/skills/builtin/my/SKILL.md +2 -2
- package/dist/core/skills/builtin/skill-creator/SKILL.md +2 -2
- package/dist/core/skills/loader.d.ts +4 -4
- package/dist/core/skills/loader.js +22 -22
- package/dist/core/skills/loader.js.map +1 -1
- package/dist/core/skills-rpc.js +1 -1
- package/dist/core/skills-rpc.js.map +1 -1
- package/dist/core/transcribe.js +13 -13
- package/dist/core/transcribe.js.map +1 -1
- package/dist/core/tunnel.js +1 -1
- package/dist/core/tunnel.js.map +1 -1
- package/dist/core/types.d.ts +2 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/user-coord-prefs.js +1 -1
- package/dist/core/user-coord-prefs.js.map +1 -1
- package/dist/core/viewer-config.d.ts +8 -8
- package/dist/core/viewer-config.js +17 -17
- package/dist/core/viewer-config.js.map +1 -1
- package/dist/core/viewer-local.js +4 -4
- package/dist/core/viewer-local.js.map +1 -1
- package/dist/core/viewer-remote.js +1 -1
- package/dist/core/viewer-remote.js.map +1 -1
- package/dist/plugins/agents/acp/url-guard.d.ts +1 -1
- package/dist/plugins/agents/acp/url-guard.js +2 -2
- package/dist/plugins/agents/acp/url-guard.js.map +1 -1
- package/dist/plugins/agents/antigravity/ensure-mcp-config.d.ts +6 -6
- package/dist/plugins/agents/antigravity/ensure-mcp-config.d.ts.map +1 -1
- package/dist/plugins/agents/antigravity/ensure-mcp-config.js +12 -12
- package/dist/plugins/agents/antigravity/ensure-mcp-config.js.map +1 -1
- package/dist/plugins/agents/antigravity/index.js +10 -10
- package/dist/plugins/agents/antigravity/index.js.map +1 -1
- package/dist/plugins/agents/claude-code/index.d.ts +2 -2
- package/dist/plugins/agents/claude-code/index.js +16 -16
- package/dist/plugins/agents/claude-code/index.js.map +1 -1
- package/dist/plugins/agents/claude-code/mcp-approval-server.js +13 -13
- package/dist/plugins/agents/claude-code/mcp-approval-server.js.map +1 -1
- package/dist/plugins/agents/codex/build-mcp-cli-args.d.ts +4 -4
- package/dist/plugins/agents/codex/build-mcp-cli-args.js +14 -14
- package/dist/plugins/agents/codex/build-mcp-cli-args.js.map +1 -1
- package/dist/plugins/agents/codex/index.d.ts +3 -3
- package/dist/plugins/agents/codex/index.js +14 -14
- package/dist/plugins/agents/codex/index.js.map +1 -1
- package/dist/plugins/agents/cursor/ensure-mcp-config.d.ts +5 -5
- package/dist/plugins/agents/cursor/ensure-mcp-config.d.ts.map +1 -1
- package/dist/plugins/agents/cursor/ensure-mcp-config.js +11 -11
- package/dist/plugins/agents/cursor/ensure-mcp-config.js.map +1 -1
- package/dist/plugins/agents/cursor/index.d.ts +1 -1
- package/dist/plugins/agents/cursor/index.js +12 -12
- package/dist/plugins/agents/cursor/index.js.map +1 -1
- package/dist/plugins/agents/native/index.js +14 -14
- package/dist/plugins/agents/native/index.js.map +1 -1
- package/dist/plugins/agents/native/tool-registry.d.ts +3 -3
- package/dist/plugins/agents/native/tool-registry.d.ts.map +1 -1
- package/dist/plugins/agents/native/tool-registry.js +5 -5
- package/dist/plugins/agents/native/tool-registry.js.map +1 -1
- package/dist/plugins/agents/opencode/ensure-mcp-config.d.ts +1 -1
- package/dist/plugins/agents/opencode/ensure-mcp-config.js +9 -9
- package/dist/plugins/agents/opencode/ensure-mcp-config.js.map +1 -1
- package/dist/plugins/agents/opencode/index.js +3 -3
- package/dist/plugins/agents/opencode/index.js.map +1 -1
- package/dist/plugins/agents/opencode/opencode-http-adapter.d.ts +4 -0
- package/dist/plugins/agents/opencode/opencode-http-adapter.d.ts.map +1 -1
- package/dist/plugins/agents/opencode/opencode-http-adapter.js +16 -12
- package/dist/plugins/agents/opencode/opencode-http-adapter.js.map +1 -1
- package/dist/plugins/agents/opencode/opencode-stdio-adapter.d.ts +2 -2
- package/dist/plugins/agents/opencode/opencode-stdio-adapter.d.ts.map +1 -1
- package/dist/plugins/agents/opencode/opencode-stdio-adapter.js +7 -5
- package/dist/plugins/agents/opencode/opencode-stdio-adapter.js.map +1 -1
- package/dist/plugins/agents/opencode/serve-manager.d.ts +1 -1
- package/dist/plugins/agents/opencode/serve-manager.d.ts.map +1 -1
- package/dist/plugins/agents/opencode/serve-manager.js +10 -10
- package/dist/plugins/agents/opencode/serve-manager.js.map +1 -1
- package/dist/plugins/agents/pi-native/factory.js +10 -10
- package/dist/plugins/agents/pi-native/factory.js.map +1 -1
- package/dist/plugins/agents/pi-native/index.d.ts +3 -3
- package/dist/plugins/agents/pi-native/index.d.ts.map +1 -1
- package/dist/plugins/agents/pi-native/index.js +2 -2
- package/dist/plugins/agents/pi-native/index.js.map +1 -1
- package/dist/plugins/agents/pi-native/tool-bridge.js +1 -1
- package/dist/plugins/agents/pi-native/tool-bridge.js.map +1 -1
- package/dist/plugins/agents/pi-native/tools.js +4 -4
- package/dist/plugins/agents/pi-native/tools.js.map +1 -1
- package/dist/plugins/messengers/dingtalk/dingtalk-adapter.d.ts +1 -1
- package/dist/plugins/messengers/dingtalk/dingtalk-adapter.js +2 -2
- package/dist/plugins/messengers/dingtalk/dingtalk-adapter.js.map +1 -1
- package/dist/plugins/messengers/email/email-adapter.js +15 -15
- package/dist/plugins/messengers/email/email-adapter.js.map +1 -1
- package/dist/plugins/messengers/telegram/media-download.d.ts +1 -1
- package/dist/plugins/messengers/telegram/media-download.js +4 -4
- package/dist/plugins/messengers/telegram/media-download.js.map +1 -1
- package/dist/plugins/messengers/telegram/telegram-adapter.d.ts +1 -1
- package/dist/plugins/messengers/telegram/telegram-adapter.js +3 -3
- package/dist/plugins/messengers/telegram/telegram-adapter.js.map +1 -1
- package/dist/plugins/messengers/wechat/context-store.js +1 -1
- package/dist/plugins/messengers/wechat/context-store.js.map +1 -1
- package/dist/plugins/messengers/wechat/ilink-adapter.js +1 -1
- package/dist/plugins/messengers/wechat/ilink-adapter.js.map +1 -1
- package/dist/plugins/messengers/wechat/ilink-client.js +1 -1
- package/dist/plugins/messengers/wechat/ilink-client.js.map +1 -1
- package/dist/plugins/messengers/wechat/media-download.js +1 -1
- package/dist/plugins/messengers/wechat/media-download.js.map +1 -1
- package/dist/scripts/migrate-gcj02-to-wgs84.js +1 -1
- package/dist/scripts/migrate-gcj02-to-wgs84.js.map +1 -1
- package/dist/web/public/assets/{a2a-CZxwvgvh.js → a2a-D7MoJ1iT.js} +2 -2
- package/dist/web/public/assets/{a2a-CZxwvgvh.js.map → a2a-D7MoJ1iT.js.map} +1 -1
- package/dist/web/public/assets/{activity-BnlFGipw.js → activity-BAgb2WZC.js} +2 -2
- package/dist/web/public/assets/{activity-BnlFGipw.js.map → activity-BAgb2WZC.js.map} +1 -1
- package/dist/web/public/assets/{admins-CH84Rw1d.js → admins-CZYANmhn.js} +2 -2
- package/dist/web/public/assets/{admins-CH84Rw1d.js.map → admins-CZYANmhn.js.map} +1 -1
- package/dist/web/public/assets/{agents-CFB4Uj6b.js → agents-BXThDW6f.js} +2 -2
- package/dist/web/public/assets/agents-BXThDW6f.js.map +1 -0
- package/dist/web/public/assets/{approvals-DnzjbDR6.js → approvals-ByPXIYVl.js} +2 -2
- package/dist/web/public/assets/{approvals-DnzjbDR6.js.map → approvals-ByPXIYVl.js.map} +1 -1
- package/dist/web/public/assets/{arrow-down-DxlRHrs8.js → arrow-down-B8DkdbEY.js} +2 -2
- package/dist/web/public/assets/{arrow-down-DxlRHrs8.js.map → arrow-down-B8DkdbEY.js.map} +1 -1
- package/dist/web/public/assets/{arrow-up-CAiQ2jy-.js → arrow-up-i_dEdXkz.js} +2 -2
- package/dist/web/public/assets/{arrow-up-CAiQ2jy-.js.map → arrow-up-i_dEdXkz.js.map} +1 -1
- package/dist/web/public/assets/{asks-DyUQopay.js → asks-yD_inOnM.js} +2 -2
- package/dist/web/public/assets/{asks-DyUQopay.js.map → asks-yD_inOnM.js.map} +1 -1
- package/dist/web/public/assets/{audit-BVHTMS82.js → audit-teCIRtgN.js} +2 -2
- package/dist/web/public/assets/{audit-BVHTMS82.js.map → audit-teCIRtgN.js.map} +1 -1
- package/dist/web/public/assets/{bell-D7iS7ctN.js → bell-CeWDMs8_.js} +2 -2
- package/dist/web/public/assets/{bell-D7iS7ctN.js.map → bell-CeWDMs8_.js.map} +1 -1
- package/dist/web/public/assets/{bgjobs-BYCQhd_1.js → bgjobs-Rc05aEy9.js} +2 -2
- package/dist/web/public/assets/bgjobs-Rc05aEy9.js.map +1 -0
- package/dist/web/public/assets/{brain-CCF25Egu.js → brain-BQqv0Zhc.js} +2 -2
- package/dist/web/public/assets/{brain-CCF25Egu.js.map → brain-BQqv0Zhc.js.map} +1 -1
- package/dist/web/public/assets/{briefcase-BMLMD8nM.js → briefcase-DUXbR4xs.js} +2 -2
- package/dist/web/public/assets/{briefcase-BMLMD8nM.js.map → briefcase-DUXbR4xs.js.map} +1 -1
- package/dist/web/public/assets/{chat-DPkKy5y_.js → chat-DQpQLW9j.js} +2 -2
- package/dist/web/public/assets/{chat-DPkKy5y_.js.map → chat-DQpQLW9j.js.map} +1 -1
- package/dist/web/public/assets/{chevron-left-BDO3vw8G.js → chevron-left-RC6mMSiX.js} +2 -2
- package/dist/web/public/assets/{chevron-left-BDO3vw8G.js.map → chevron-left-RC6mMSiX.js.map} +1 -1
- package/dist/web/public/assets/{chevron-right-5ZUC2opg.js → chevron-right-DrkYVi19.js} +2 -2
- package/dist/web/public/assets/{chevron-right-5ZUC2opg.js.map → chevron-right-DrkYVi19.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-COhM5JsK.js → circle-check-DZnkaUdk.js} +2 -2
- package/dist/web/public/assets/{circle-check-COhM5JsK.js.map → circle-check-DZnkaUdk.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-big-DHAHqUlS.js → circle-check-big-BC8ntMsz.js} +2 -2
- package/dist/web/public/assets/{circle-check-big-DHAHqUlS.js.map → circle-check-big-BC8ntMsz.js.map} +1 -1
- package/dist/web/public/assets/{circle-x-7VaoZ7dY.js → circle-x-DHK7ypFY.js} +2 -2
- package/dist/web/public/assets/{circle-x-7VaoZ7dY.js.map → circle-x-DHK7ypFY.js.map} +1 -1
- package/dist/web/public/assets/{clock-ZPVXnd6V.js → clock-DXHhWqJH.js} +2 -2
- package/dist/web/public/assets/{clock-ZPVXnd6V.js.map → clock-DXHhWqJH.js.map} +1 -1
- package/dist/web/public/assets/{confirm-dialog-CgpJL9oN.js → confirm-dialog-gPKJnvEW.js} +2 -2
- package/dist/web/public/assets/{confirm-dialog-CgpJL9oN.js.map → confirm-dialog-gPKJnvEW.js.map} +1 -1
- package/dist/web/public/assets/{copy-BaZl52tH.js → copy-DtQxgcR0.js} +2 -2
- package/dist/web/public/assets/{copy-BaZl52tH.js.map → copy-DtQxgcR0.js.map} +1 -1
- package/dist/web/public/assets/{data-table-BLYG79TX.js → data-table-DOKUic1J.js} +2 -2
- package/dist/web/public/assets/{data-table-BLYG79TX.js.map → data-table-DOKUic1J.js.map} +1 -1
- package/dist/web/public/assets/distill-p6P7-1UR.js +7 -0
- package/dist/web/public/assets/distill-p6P7-1UR.js.map +1 -0
- package/dist/web/public/assets/{download-bzCepctg.js → download-CqNiIHa8.js} +2 -2
- package/dist/web/public/assets/{download-bzCepctg.js.map → download-CqNiIHa8.js.map} +1 -1
- package/dist/web/public/assets/email-DwbfTUlV.js +7 -0
- package/dist/web/public/assets/email-DwbfTUlV.js.map +1 -0
- package/dist/web/public/assets/{empty-state-96qpPTNg.js → empty-state-CTwOQemt.js} +2 -2
- package/dist/web/public/assets/{empty-state-96qpPTNg.js.map → empty-state-CTwOQemt.js.map} +1 -1
- package/dist/web/public/assets/{external-link-J4nIlCem.js → external-link-BY7Ye8yi.js} +2 -2
- package/dist/web/public/assets/{external-link-J4nIlCem.js.map → external-link-BY7Ye8yi.js.map} +1 -1
- package/dist/web/public/assets/{eye-BvsBLK42.js → eye-6RUADoDS.js} +2 -2
- package/dist/web/public/assets/{eye-BvsBLK42.js.map → eye-6RUADoDS.js.map} +1 -1
- package/dist/web/public/assets/{facts-DMucDXYd.js → facts-DXE0aJmb.js} +2 -2
- package/dist/web/public/assets/{facts-DMucDXYd.js.map → facts-DXE0aJmb.js.map} +1 -1
- package/dist/web/public/assets/{goals-B9ETHgL0.js → goals-C1LCm3qL.js} +2 -2
- package/dist/web/public/assets/{goals-B9ETHgL0.js.map → goals-C1LCm3qL.js.map} +1 -1
- package/dist/web/public/assets/{health-DLzZ7KHc.js → health-wqCp-K_o.js} +2 -2
- package/dist/web/public/assets/{health-DLzZ7KHc.js.map → health-wqCp-K_o.js.map} +1 -1
- package/dist/web/public/assets/{heart-pulse-CVEeD2sz.js → heart-pulse-DfqI4GF7.js} +2 -2
- package/dist/web/public/assets/{heart-pulse-CVEeD2sz.js.map → heart-pulse-DfqI4GF7.js.map} +1 -1
- package/dist/web/public/assets/{heartbeat-B1BEBHge.js → heartbeat-Bumv4XtQ.js} +2 -2
- package/dist/web/public/assets/{heartbeat-B1BEBHge.js.map → heartbeat-Bumv4XtQ.js.map} +1 -1
- package/dist/web/public/assets/{hot-Yc7iad0D.js → hot-B-CMjQIr.js} +2 -2
- package/dist/web/public/assets/{hot-Yc7iad0D.js.map → hot-B-CMjQIr.js.map} +1 -1
- package/dist/web/public/assets/{index-DY2Zglku.js → index-DHh1LYlA.js} +29 -29
- package/dist/web/public/assets/{index-DY2Zglku.js.map → index-DHh1LYlA.js.map} +1 -1
- package/dist/web/public/assets/{injection-Ca-9gbo0.js → injection-Dn_XqgLG.js} +2 -2
- package/dist/web/public/assets/{injection-Ca-9gbo0.js.map → injection-Dn_XqgLG.js.map} +1 -1
- package/dist/web/public/assets/{installed-Zz34apdi.js → installed-Cet-1M2Q.js} +2 -2
- package/dist/web/public/assets/{installed-Zz34apdi.js.map → installed-Cet-1M2Q.js.map} +1 -1
- package/dist/web/public/assets/{jobs-CtVRpl0r.js → jobs-CfEzOOAC.js} +2 -2
- package/dist/web/public/assets/{jobs-CtVRpl0r.js.map → jobs-CfEzOOAC.js.map} +1 -1
- package/dist/web/public/assets/{layout-DnANw2Q2.js → layout-BX43KyXM.js} +2 -2
- package/dist/web/public/assets/{layout-DnANw2Q2.js.map → layout-BX43KyXM.js.map} +1 -1
- package/dist/web/public/assets/{layout-Cxch59sI.js → layout-BcYZlaqf.js} +2 -2
- package/dist/web/public/assets/{layout-Cxch59sI.js.map → layout-BcYZlaqf.js.map} +1 -1
- package/dist/web/public/assets/{layout-BTCLgkgN.js → layout-Cb7looUv.js} +2 -2
- package/dist/web/public/assets/{layout-BTCLgkgN.js.map → layout-Cb7looUv.js.map} +1 -1
- package/dist/web/public/assets/{layout-yIZG87fq.js → layout-D7xH78OU.js} +2 -2
- package/dist/web/public/assets/{layout-yIZG87fq.js.map → layout-D7xH78OU.js.map} +1 -1
- package/dist/web/public/assets/{layout-CtDc2i7w.js → layout-D_3ZcVG7.js} +2 -2
- package/dist/web/public/assets/{layout-CtDc2i7w.js.map → layout-D_3ZcVG7.js.map} +1 -1
- package/dist/web/public/assets/llm-BZ9qqp-D.js +27 -0
- package/dist/web/public/assets/llm-BZ9qqp-D.js.map +1 -0
- package/dist/web/public/assets/{loader-circle-D8L1w9c1.js → loader-circle-DgdBWYl0.js} +2 -2
- package/dist/web/public/assets/{loader-circle-D8L1w9c1.js.map → loader-circle-DgdBWYl0.js.map} +1 -1
- package/dist/web/public/assets/{map-pin--GMunU9n.js → map-pin-3QS1A0-I.js} +2 -2
- package/dist/web/public/assets/{map-pin--GMunU9n.js.map → map-pin-3QS1A0-I.js.map} +1 -1
- package/dist/web/public/assets/{mcp-DhnXhO9B.js → mcp-DwKZULET.js} +2 -2
- package/dist/web/public/assets/{mcp-DhnXhO9B.js.map → mcp-DwKZULET.js.map} +1 -1
- package/dist/web/public/assets/{memos-DQZc7llR.js → memos-BBtqFcoH.js} +2 -2
- package/dist/web/public/assets/{memos-DQZc7llR.js.map → memos-BBtqFcoH.js.map} +1 -1
- package/dist/web/public/assets/{messengers-DwSmauLs.js → messengers-i7WvNT3o.js} +2 -2
- package/dist/web/public/assets/messengers-i7WvNT3o.js.map +1 -0
- package/dist/web/public/assets/{mobile-CUZ359rQ.js → mobile-Bq0FH9JV.js} +2 -2
- package/dist/web/public/assets/{mobile-CUZ359rQ.js.map → mobile-Bq0FH9JV.js.map} +1 -1
- package/dist/web/public/assets/{network-BBdRdrH_.js → network--s113Jkm.js} +2 -2
- package/dist/web/public/assets/{network-BBdRdrH_.js.map → network--s113Jkm.js.map} +1 -1
- package/dist/web/public/assets/{outbox-CmN0U35l.js → outbox-BbfC5kuG.js} +2 -2
- package/dist/web/public/assets/{outbox-CmN0U35l.js.map → outbox-BbfC5kuG.js.map} +1 -1
- package/dist/web/public/assets/{pagination-DcsgDXXM.js → pagination-DkdCTctJ.js} +2 -2
- package/dist/web/public/assets/{pagination-DcsgDXXM.js.map → pagination-DkdCTctJ.js.map} +1 -1
- package/dist/web/public/assets/{persona-ig2ac4mY.js → persona-BvtcZh6G.js} +2 -2
- package/dist/web/public/assets/{persona-ig2ac4mY.js.map → persona-BvtcZh6G.js.map} +1 -1
- package/dist/web/public/assets/{plans-Bzbk8eUr.js → plans-i3a6lrqF.js} +2 -2
- package/dist/web/public/assets/{plans-Bzbk8eUr.js.map → plans-i3a6lrqF.js.map} +1 -1
- package/dist/web/public/assets/{play-Di1jqulh.js → play-CPoE_JnS.js} +2 -2
- package/dist/web/public/assets/{play-Di1jqulh.js.map → play-CPoE_JnS.js.map} +1 -1
- package/dist/web/public/assets/{plus-C2zyJ1mF.js → plus-CfzKV_0u.js} +2 -2
- package/dist/web/public/assets/{plus-C2zyJ1mF.js.map → plus-CfzKV_0u.js.map} +1 -1
- package/dist/web/public/assets/policy-Cm88P8LO.js +2 -0
- package/dist/web/public/assets/policy-Cm88P8LO.js.map +1 -0
- package/dist/web/public/assets/{qr-code-C-ACsKv_.js → qr-code-DMkV8nv2.js} +2 -2
- package/dist/web/public/assets/{qr-code-C-ACsKv_.js.map → qr-code-DMkV8nv2.js.map} +1 -1
- package/dist/web/public/assets/{refresh-ccw-7HdadG5V.js → refresh-ccw-nBMm5Xal.js} +2 -2
- package/dist/web/public/assets/{refresh-ccw-7HdadG5V.js.map → refresh-ccw-nBMm5Xal.js.map} +1 -1
- package/dist/web/public/assets/{reminders-BDeiVYTC.js → reminders-DjEujanC.js} +2 -2
- package/dist/web/public/assets/{reminders-BDeiVYTC.js.map → reminders-DjEujanC.js.map} +1 -1
- package/dist/web/public/assets/{save-BYFmz9gD.js → save-DbrrCFDM.js} +2 -2
- package/dist/web/public/assets/{save-BYFmz9gD.js.map → save-DbrrCFDM.js.map} +1 -1
- package/dist/web/public/assets/{schedules-BddzBrxI.js → schedules-DzwDWykc.js} +2 -2
- package/dist/web/public/assets/{schedules-BddzBrxI.js.map → schedules-DzwDWykc.js.map} +1 -1
- package/dist/web/public/assets/search-5q3dkINm.js +17 -0
- package/dist/web/public/assets/search-5q3dkINm.js.map +1 -0
- package/dist/web/public/assets/{search-DxkvV-8p.js → search-DbE4VEm9.js} +2 -2
- package/dist/web/public/assets/{search-DxkvV-8p.js.map → search-DbE4VEm9.js.map} +1 -1
- package/dist/web/public/assets/security-BIcnUrAs.js +2 -0
- package/dist/web/public/assets/security-BIcnUrAs.js.map +1 -0
- package/dist/web/public/assets/{service-BsY8CaNG.js → service-CnorFHzZ.js} +2 -2
- package/dist/web/public/assets/{service-BsY8CaNG.js.map → service-CnorFHzZ.js.map} +1 -1
- package/dist/web/public/assets/{shield-alert-DXGk9Rak.js → shield-alert-WOa69jy3.js} +2 -2
- package/dist/web/public/assets/{shield-alert-DXGk9Rak.js.map → shield-alert-WOa69jy3.js.map} +1 -1
- package/dist/web/public/assets/{status-badge-D0nbFSom.js → status-badge-D5xhwquL.js} +2 -2
- package/dist/web/public/assets/{status-badge-D0nbFSom.js.map → status-badge-D5xhwquL.js.map} +1 -1
- package/dist/web/public/assets/{subtasks-DFiAXvDp.js → subtasks-DMRyk6YS.js} +2 -2
- package/dist/web/public/assets/{subtasks-DFiAXvDp.js.map → subtasks-DMRyk6YS.js.map} +1 -1
- package/dist/web/public/assets/{table-_WsrnZ_T.js → table-Dx65w6V0.js} +2 -2
- package/dist/web/public/assets/{table-_WsrnZ_T.js.map → table-Dx65w6V0.js.map} +1 -1
- package/dist/web/public/assets/{topn-C2PHE4tX.js → topn-L7Juczp3.js} +2 -2
- package/dist/web/public/assets/{topn-C2PHE4tX.js.map → topn-L7Juczp3.js.map} +1 -1
- package/dist/web/public/assets/{trash-2-1Km439fW.js → trash-2-7xrfqd-v.js} +2 -2
- package/dist/web/public/assets/{trash-2-1Km439fW.js.map → trash-2-7xrfqd-v.js.map} +1 -1
- package/dist/web/public/assets/{use-agim-skills-COSqZrdH.js → use-agim-skills-pFjfgqMF.js} +2 -2
- package/dist/web/public/assets/{use-agim-skills-COSqZrdH.js.map → use-agim-skills-pFjfgqMF.js.map} +1 -1
- package/dist/web/public/assets/{use-background-tasks-wCL7jn68.js → use-background-tasks-D1--hHjp.js} +2 -2
- package/dist/web/public/assets/{use-background-tasks-wCL7jn68.js.map → use-background-tasks-D1--hHjp.js.map} +1 -1
- package/dist/web/public/assets/{use-memory-B9oRyQC8.js → use-memory-Bz1Zao7g.js} +2 -2
- package/dist/web/public/assets/{use-memory-B9oRyQC8.js.map → use-memory-Bz1Zao7g.js.map} +1 -1
- package/dist/web/public/assets/{use-observability-DGkN80qa.js → use-observability-DtqSWVjM.js} +2 -2
- package/dist/web/public/assets/{use-observability-DGkN80qa.js.map → use-observability-DtqSWVjM.js.map} +1 -1
- package/dist/web/public/assets/{use-settings-Co-iafXD.js → use-settings-DKbDqCEJ.js} +2 -2
- package/dist/web/public/assets/{use-settings-Co-iafXD.js.map → use-settings-DKbDqCEJ.js.map} +1 -1
- package/dist/web/public/assets/{use-workspace-BDXP5XO1.js → use-workspace-CConjEx0.js} +2 -2
- package/dist/web/public/assets/{use-workspace-BDXP5XO1.js.map → use-workspace-CConjEx0.js.map} +1 -1
- package/dist/web/public/assets/vector-D8sEa2W-.js +2 -0
- package/dist/web/public/assets/vector-D8sEa2W-.js.map +1 -0
- package/dist/web/public/assets/viewer-aSIjAKVA.js +12 -0
- package/dist/web/public/assets/viewer-aSIjAKVA.js.map +1 -0
- package/dist/web/public/assets/{workspace-BbCchiHE.js → workspace-BqwWoinI.js} +2 -2
- package/dist/web/public/assets/{workspace-BbCchiHE.js.map → workspace-BqwWoinI.js.map} +1 -1
- package/dist/web/public/assets/{workspaces-5HE7pjdA.js → workspaces-ChsJcrav.js} +2 -2
- package/dist/web/public/assets/{workspaces-5HE7pjdA.js.map → workspaces-ChsJcrav.js.map} +1 -1
- package/dist/web/public/index.html +1 -1
- package/dist/web/public/loc.html +1 -1
- package/dist/web/public/login.html +2 -2
- package/dist/web/server.d.ts +2 -2
- package/dist/web/server.js +118 -119
- package/dist/web/server.js.map +1 -1
- package/package.json +2 -3
- package/dist/core/llm/imhub-dispatcher.d.ts.map +0 -1
- package/dist/core/llm/imhub-dispatcher.js.map +0 -1
- package/dist/web/public/assets/agents-CFB4Uj6b.js.map +0 -1
- package/dist/web/public/assets/bgjobs-BYCQhd_1.js.map +0 -1
- package/dist/web/public/assets/distill-D9p8O8Jf.js +0 -7
- package/dist/web/public/assets/distill-D9p8O8Jf.js.map +0 -1
- package/dist/web/public/assets/email-Douv-rZ5.js +0 -7
- package/dist/web/public/assets/email-Douv-rZ5.js.map +0 -1
- package/dist/web/public/assets/llm-CMMa85Ig.js +0 -27
- package/dist/web/public/assets/llm-CMMa85Ig.js.map +0 -1
- package/dist/web/public/assets/messengers-DwSmauLs.js.map +0 -1
- package/dist/web/public/assets/policy-yD1c2Pcn.js +0 -2
- package/dist/web/public/assets/policy-yD1c2Pcn.js.map +0 -1
- package/dist/web/public/assets/search-B8PlbtLg.js +0 -17
- package/dist/web/public/assets/search-B8PlbtLg.js.map +0 -1
- package/dist/web/public/assets/security-DpOGp3nS.js +0 -2
- package/dist/web/public/assets/security-DpOGp3nS.js.map +0 -1
- package/dist/web/public/assets/vector-BfIEx8xX.js +0 -2
- package/dist/web/public/assets/vector-BfIEx8xX.js.map +0 -1
- package/dist/web/public/assets/viewer-BPMZkT05.js +0 -12
- package/dist/web/public/assets/viewer-BPMZkT05.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.5.0] - 2026-06-29
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Public runtime surfaces now consistently use Agim naming: `agim`, `AGIM_*`, `mcp__agim__*`, `X-Agim-Token`, `~/.agim`, `~/.agim-workspaces`, and `agim.service`.
|
|
12
|
+
- Removed retired command, env, path, MCP, HTTP header, and systemd aliases from code, docs, tests, and release notes.
|
|
13
|
+
- Decoupled opencode from normal startup: Agim now registers the opencode MCP sidecar lazily only when an opencode adapter is actually used.
|
|
14
|
+
- Headless production startup now defaults to `claude-code` when no default agent is configured.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Non-Linux Agim process detection now validates argv shape via `ps` instead of substring matching, avoiding false positives from shell commands that merely contain `agim start`.
|
|
19
|
+
|
|
7
20
|
## [1.3.10] - 2026-06-23
|
|
8
21
|
|
|
9
22
|
### Added
|
|
@@ -49,7 +62,7 @@ All notable changes to this project will be documented in this file.
|
|
|
49
62
|
|
|
50
63
|
### Added(自 1.3.0 累积)
|
|
51
64
|
|
|
52
|
-
- `
|
|
65
|
+
- `mcp__agim__ask_user` 扩展为结构化决策模式:单选/多选/自定义输入(`selectionMode`、`minSelections`、`maxSelections`、`allowCustomInput`、`customInputLabel`;结果含 `selectionMode`、`indexes`、`labels`、`customText`,旧字段兼容)。
|
|
53
66
|
- TUI 统一决策交互面板(审批 + `ask_user`:键盘单选 / 多选 Space 勾选 / 自定义输入);会话管理 `/new` `/sessions`;`/agent` 名称补全;token/cost 状态栏;工具调用审批桥。
|
|
54
67
|
|
|
55
68
|
### Documentation
|
|
@@ -65,17 +78,17 @@ All notable changes to this project will be documented in this file.
|
|
|
65
78
|
|
|
66
79
|
- **pi-native 成为默认 native 引擎**(1.2.155):in-process 循环换成 pi 的
|
|
67
80
|
`AgentHarness` + durable JSONL session(崩溃可恢复);legacy 降级为逃生通道
|
|
68
|
-
(`
|
|
81
|
+
(`AGIM_NATIVE_ENGINE=legacy`)。含 approval 门 / plan-mode / max-iter /
|
|
69
82
|
stuck-loop 护栏 / 真实身份 system prompt。
|
|
70
83
|
- **上下文压缩 + provider 韧性**(1.2.156):每轮按 token 阈值 `harness.compact()`;
|
|
71
|
-
provider 重试/退避/超时 + prompt 缓存,全 `
|
|
72
|
-
- **A2A 子输出压缩**(1.2.157):子代理回传超 `
|
|
84
|
+
provider 重试/退避/超时 + prompt 缓存,全 `AGIM_NATIVE_*` 可覆盖。
|
|
85
|
+
- **A2A 子输出压缩**(1.2.157):子代理回传超 `AGIM_A2A_MAX_RESULT_CHARS`(默认
|
|
73
86
|
8000)即截断,全文溢出到 `_agim-output/`,父按需 read。
|
|
74
87
|
- **TUI 体验**(1.2.158):`/agent` 名称补全 + 底部 token/cost 实时状态栏。
|
|
75
88
|
- **模型成本/窗口元数据**(1.2.159):复用 pi-ai MODELS 目录,`LlmProvider`
|
|
76
89
|
在 API 不回成本时按目录回填真实 $(覆盖所有 legacy provider)。
|
|
77
90
|
- **auth 重构 + 手机端**(1.2.160):web-token-only admin 注册表(IM admin 在
|
|
78
|
-
Settings → Admins 管理,取消 bootstrap token / `
|
|
91
|
+
Settings → Admins 管理,取消 bootstrap token / `AGIM_ADMIN_USERS` 运行时依赖);
|
|
79
92
|
手机版聊天 UX + run 活动时间线;native 配置弹窗 + role-optional 后端兜底。
|
|
80
93
|
|
|
81
94
|
详见各 1.2.15x 段。
|
|
@@ -83,13 +96,13 @@ All notable changes to this project will be documented in this file.
|
|
|
83
96
|
## Native engine (pi-native) overview
|
|
84
97
|
|
|
85
98
|
> Consolidated from historical pi-native migration notes.
|
|
86
|
-
> Default native engine since `1.2.155`; legacy escape hatch: `
|
|
99
|
+
> Default native engine since `1.2.155`; legacy escape hatch: `AGIM_NATIVE_ENGINE=legacy`.
|
|
87
100
|
|
|
88
101
|
### Shipped (1.2.155 → 1.2.159)
|
|
89
102
|
|
|
90
103
|
- **1.2.155**: switched native engine to pi-native (`AgentHarness` + durable JSONL session), added tool bridge, resolver, approval integration, runaway/stuck-loop guards.
|
|
91
|
-
- **1.2.156**: added pre-turn compaction (`
|
|
92
|
-
- **1.2.157**: added A2A result compression (`
|
|
104
|
+
- **1.2.156**: added pre-turn compaction (`AGIM_NATIVE_COMPACTION`), provider retry/cache tuning (`AGIM_NATIVE_*`).
|
|
105
|
+
- **1.2.157**: added A2A result compression (`AGIM_A2A_MAX_RESULT_CHARS`) with overflow to artifact files.
|
|
93
106
|
- **1.2.158**: improved TUI interaction (`/agent` completion + token/cost status visibility).
|
|
94
107
|
- **1.2.159**: added model catalog-based usage enrichment for cost/window metadata backfill.
|
|
95
108
|
|
|
@@ -254,7 +267,7 @@ workspace 排在 ECC picks 之前。运营者亲装 > 框架预选 > ECC remaind
|
|
|
254
267
|
运营者可以覆盖自动生成的 skill 块。文件存在且非空时,**全文替换** auto block
|
|
255
268
|
(路由头 + always-on body 保留)。三个 helper:
|
|
256
269
|
`readInjectionOverride / writeInjectionOverride / deleteInjectionOverride`。
|
|
257
|
-
环境变量 `
|
|
270
|
+
环境变量 `AGIM_SKILLS_INJECTION_OVERRIDE_PATH` 可改路径(测试用)。
|
|
258
271
|
|
|
259
272
|
#### Admin API + SPA 页
|
|
260
273
|
|
|
@@ -268,8 +281,8 @@ workspace 排在 ECC picks 之前。运营者亲装 > 框架预选 > ECC remaind
|
|
|
268
281
|
|
|
269
282
|
#### 新增 env knob
|
|
270
283
|
|
|
271
|
-
- `
|
|
272
|
-
- `
|
|
284
|
+
- `AGIM_SKILLS_ECC_PICKS=name1,name2,...` 覆盖默认 20 picks(推荐池)
|
|
285
|
+
- `AGIM_SKILLS_INJECT_ECC_REMAINDER=on|off|name-list`:
|
|
273
286
|
- `on`(默认):cluster 模式
|
|
274
287
|
- `off`:完全抑制 ECC remainder 块(省 token)
|
|
275
288
|
- 逗号分隔白名单:只保留指定 skill
|
|
@@ -343,7 +356,7 @@ LLM 看不到 description → 无法 route。
|
|
|
343
356
|
/ code-tour / coding-standards / content-engine / context-budget / continuous-learning-v2
|
|
344
357
|
/ cost-aware-llm-pipeline / prompt-optimizer / security-review / tdd-workflow / verification-loop
|
|
345
358
|
|
|
346
|
-
## ECC remainder (read full description via
|
|
359
|
+
## ECC remainder (read full description via mcp__agim__read_skill) (210)
|
|
347
360
|
- django-* (5): django-celery · django-patterns · django-security · django-tdd · django-verification
|
|
348
361
|
- kotlin-* (5): kotlin-coroutines-flows · kotlin-exposed-patterns · kotlin-ktor-patterns
|
|
349
362
|
· kotlin-patterns · kotlin-testing
|
|
@@ -414,7 +427,7 @@ v1.2.148 的 bulk-import 脚本对 YAML 折叠语法(`description: >-\n text.
|
|
|
414
427
|
| 3 | 工作区运营者 skill(业务域)+ ECC 余下 210 |
|
|
415
428
|
|
|
416
429
|
4 + 8 + 20 = 32 正好填满;bucket 3 全部靠 description match + 显式
|
|
417
|
-
`
|
|
430
|
+
`mcp__agim__read_skill('name')` 触发,不强占系统提示门面。
|
|
418
431
|
|
|
419
432
|
#### ECC 精选清单(20 个)
|
|
420
433
|
|
|
@@ -493,7 +506,7 @@ verification 循环、cost-aware LLM 流水线等。MIT 许可,license 文件
|
|
|
493
506
|
|
|
494
507
|
#### env switch
|
|
495
508
|
|
|
496
|
-
- `
|
|
509
|
+
- `AGIM_INCLUDE_ECC_SKILLS=off` (或 `0`/`false`/`no`/`disable`)→ loader 跳过
|
|
497
510
|
所有 `origin: ECC` 的 skill。默认 ON,保留新装 agim 用户的开箱即用体验。
|
|
498
511
|
- 仅过滤 ECC pack;用户自己写 SKILL.md 时若复用 `origin: ECC` 字段是允许的
|
|
499
512
|
(但显式标记 ECC pack 的 description `[ECC]` 前缀已写死,不影响 user skill)。
|
|
@@ -517,7 +530,7 @@ verification 循环、cost-aware LLM 流水线等。MIT 许可,license 文件
|
|
|
517
530
|
(部分含 scripts/references/templates 子目录),description 行加 `[ECC]` 前缀
|
|
518
531
|
- 新增 `src/core/skills/builtin/ECC_LICENSE` —— MIT, © Affaan Mustafa
|
|
519
532
|
- 新增 `src/core/skills/builtin/ECC_NOTICE.md` —— 归属说明 + 排除清单
|
|
520
|
-
- `src/core/skills/loader.ts` —— `parseSkill` 加
|
|
533
|
+
- `src/core/skills/loader.ts` —— `parseSkill` 加 AGIM_INCLUDE_ECC_SKILLS 过滤
|
|
521
534
|
- `src/core/skills/loader.test.ts` —— 新增 1 case 覆盖 env switch(默认 ON / off /
|
|
522
535
|
unrecognized 三态)
|
|
523
536
|
|
|
@@ -530,7 +543,7 @@ verification 循环、cost-aware LLM 流水线等。MIT 许可,license 文件
|
|
|
530
543
|
#### 注意事项(agim user 视角)
|
|
531
544
|
|
|
532
545
|
- system prompt 仍只列前 32 个 skill(`MAX_INJECTED_SKILLS=32`),不会爆 context
|
|
533
|
-
- 其余 200+ 个仍可通过 `
|
|
546
|
+
- 其余 200+ 个仍可通过 `mcp__agim__read_skill('name')` 主动调
|
|
534
547
|
- 同名 workspace skill 会 shadow builtin(用户自定义优先)
|
|
535
548
|
|
|
536
549
|
## [1.2.147] - 2026-06-12
|
|
@@ -548,7 +561,7 @@ prompt,命中模式就走复盘卡)。
|
|
|
548
561
|
push 一段 `[agim framework rule — tool-call discipline]` 块。**默认所有 agim 安装
|
|
549
562
|
生效**,不依赖用户写 AGENTS.md。
|
|
550
563
|
- 段内 5 条硬规则(禁演练、必须真调、不确定走 todo、追问时坦白、副作用工具一次发完整)。
|
|
551
|
-
- env `
|
|
564
|
+
- env `AGIM_NATIVE_TOOL_DISCIPLINE`,默认 `on`;`off`/`0`/`false`/`no`/`disable`
|
|
552
565
|
关掉(escape hatch,给 prompt 调优实验用)。
|
|
553
566
|
|
|
554
567
|
### Added (native harness — hallucinated tool-call detector)
|
|
@@ -574,7 +587,7 @@ prompt,命中模式就走复盘卡)。
|
|
|
574
587
|
|
|
575
588
|
#### Env
|
|
576
589
|
|
|
577
|
-
- `
|
|
590
|
+
- `AGIM_NATIVE_HALLUCINATION_DETECT` 默认 `on`;`off`/`0`/`false`/`no`/`disable` 关掉
|
|
578
591
|
(误判 cost 仅是多一张复盘卡,关掉 cost 是放过 silent lies,所以默认开)。
|
|
579
592
|
|
|
580
593
|
#### Tests
|
|
@@ -588,11 +601,11 @@ prompt,命中模式就走复盘卡)。
|
|
|
588
601
|
|
|
589
602
|
#### 未做(留续作)
|
|
590
603
|
|
|
591
|
-
- 自动 retry(`
|
|
604
|
+
- 自动 retry(`AGIM_NATIVE_HALLUCINATION_AUTO_RETRY=1` 强制注入纠正 prompt 再跑一轮)
|
|
592
605
|
- web outbox crash-safe delivery(web reply 在 client 重连时丢失)
|
|
593
606
|
- viewer DELETE 加 audit_event
|
|
594
|
-
- `docs/security-hardening.md` §1 env 速查表补 `
|
|
595
|
-
与 `
|
|
607
|
+
- `docs/security-hardening.md` §1 env 速查表补 `AGIM_NATIVE_WEB_ALLOW_PRIVATE`
|
|
608
|
+
与 `AGIM_NATIVE_WEB_SSRF_WHITELIST` 两项
|
|
596
609
|
|
|
597
610
|
## [1.2.145] - 2026-06-12
|
|
598
611
|
|
|
@@ -601,9 +614,9 @@ prompt,命中模式就走复盘卡)。
|
|
|
601
614
|
### Security (CR 修复)
|
|
602
615
|
|
|
603
616
|
- **viewer 越权删除(H1, #90)**:`DELETE /api/viewer/:id` 之前漏了 `requireAdmin` 且 handler 忽略请求上下文,任意已认证 token(含 `role=user` 移动 QR token)可凭 paste id(经 IM `/v/<uuid>` 链接外泄)删除任意 paste。已补 `requireAdmin`。
|
|
604
|
-
- **notify_url SSRF(H2, #92)**:定时任务 webhook 之前只做词法校验(只看 host 串)。新增 `assertWebhookHostPublic()`,在 fetch 前 DNS 解析 + 拒私网/回环/link-local,堵住"主机名解析进内网 / DNS-rebinding"。新 env `
|
|
617
|
+
- **notify_url SSRF(H2, #92)**:定时任务 webhook 之前只做词法校验(只看 host 串)。新增 `assertWebhookHostPublic()`,在 fetch 前 DNS 解析 + 拒私网/回环/link-local,堵住"主机名解析进内网 / DNS-rebinding"。新 env `AGIM_ALLOW_PRIVATE_WEBHOOKS=1` 放行内网调试。
|
|
605
618
|
- **sensitive-paths 绕过(#83)**:denylist 可被 `/proc/<pid>/{root,cwd}/...`(root 是指向进程 `/` 的 symlink)与工作区 symlink 绕过。`canonical()` 现做 best-effort `realpath`,对字面 + 解析后路径双重匹配,并直拒 `/proc` 间接寻址。
|
|
606
|
-
- **工作区信任门(T6, #89)**:新 env `
|
|
619
|
+
- **工作区信任门(T6, #89)**:新 env `AGIM_NATIVE_TRUST_WORKSPACE=off` → native 一次性跳过工作区发现的 `AGENTS.md`/`AGENTS.local.md` 注入(多租户 / A2A 防 prompt 投毒)。显式 `AGIM_NATIVE_AGENT_ROLE_FILE` 不受门控。
|
|
607
620
|
|
|
608
621
|
### Fixed (运行时可靠性,CR + #83)
|
|
609
622
|
|
|
@@ -619,7 +632,7 @@ prompt,命中模式就走复盘卡)。
|
|
|
619
632
|
- **IM 入站非阻塞(M3, #93)**:Feishu / DingTalk 之前在 SDK 回调内 `await` 整轮 agent,阻塞接收循环(一个慢会话拖死其他线程入站)。改 fire-and-forget;钉钉 **先 ack 再派发**(避免超 60s 重投 + handler 挂起时消息被 dedup 丢弃)。
|
|
620
633
|
- **native 上下文预算(T1/T3, #85)**:`readOperatorRole` 按 mtime/size memoize(每轮省一次磁盘读 + 注入扫描);system-prompt skills 列表封顶 `MAX_INJECTED_SKILLS`(之前未封顶且与 router 注入重复)。
|
|
621
634
|
- **native 单一工具注册表(T2, #86)**:`tools[]` / `combineDispatchers` / 静态 `parallelSafeTools` 三份并行清单合一为 `tool-registry.ts` 的 `assembleNativeTools()`;并发判定改 **逐调用** classifier(`agent-loop` 新增 `parallelSafeClassifier`,fail-closed);外部 MCP 分区按名排序保证 prompt-cache 稳定。
|
|
622
|
-
- **native 指令分层(T4, #88, local-wins)**:操作员角色从单 `AGENTS.md` → `<cwd>/AGENTS.md`(project)+ `<cwd>/AGENTS.local.md`(local,最后拼接=胜出)。`
|
|
635
|
+
- **native 指令分层(T4, #88, local-wins)**:操作员角色从单 `AGENTS.md` → `<cwd>/AGENTS.md`(project)+ `<cwd>/AGENTS.local.md`(local,最后拼接=胜出)。`AGIM_NATIVE_AGENT_ROLE_FILE` 仍可 pin 单文件。
|
|
623
636
|
- **验证子代理 SOP(T5, #89)**:native system prompt 增加"产出实质结果后用全新子代理独立校验 + 自包含 brief + 先综合再委派"指导(纯 prompt,无运行时分支)。
|
|
624
637
|
- **native 审计 traceId 关联(M5, #94)**:native 之前自造 `native-<sid>-<ts>` traceId,审计行无法关联入站消息。`AgentSendOpts.traceId` 由 router 透传、native 优先采用;进程内 A2A 子调用链接 `${parent}/a2a-${id}`(ADR-0002 修复)。
|
|
625
638
|
|
|
@@ -632,7 +645,7 @@ prompt,命中模式就走复盘卡)。
|
|
|
632
645
|
|
|
633
646
|
- A2A `call_agent('native')` 进程内快路径绕过 `callAgentByName`,不写 inline job / `intent:'a2a'` 审计行(本轮仅补 trace 链接)。
|
|
634
647
|
- `isAgentEnabled('native')` 恒 true,无视 `config.agents` 禁用开关。
|
|
635
|
-
- ACP 侧 SSRF 仅覆盖 Web test/discover API(该面默认被 `
|
|
648
|
+
- ACP 侧 SSRF 仅覆盖 Web test/discover API(该面默认被 `AGIM_ENABLE_REMOTE_AGENT` 关闭)。
|
|
636
649
|
|
|
637
650
|
## [1.2.144] - 2026-06-05
|
|
638
651
|
|
|
@@ -649,7 +662,7 @@ prompt,命中模式就走复盘卡)。
|
|
|
649
662
|
|
|
650
663
|
**修复**:新增 `isTrustedLoopbackPeer()` 三层检查:
|
|
651
664
|
1. `isLoopbackPeer(req)`(原有)
|
|
652
|
-
2. `
|
|
665
|
+
2. `AGIM_TRUST_LOOPBACK !== off`(新增 env kill switch)
|
|
653
666
|
3. **`!hasForwardedPeerHeaders(req)`** — 任一 `Forwarded` / `X-Forwarded-*`
|
|
654
667
|
/ `X-Real-IP` / `CF-Connecting-IP` header 出现 → 视为反代后流量,
|
|
655
668
|
走正常 token 路径
|
|
@@ -806,7 +819,7 @@ adapter.test.ts 已覆盖 commandName 通路。
|
|
|
806
819
|
正常收尾。请按三节给阶段性报告——已经做到/没做到/下一步建议。"
|
|
807
820
|
- **失败描述要求人话**:不能写 "`native_web_fetch` ×8 failed",要写
|
|
808
821
|
"新浪财经页面抓不到(疑似反爬)"。系统消息里 ban 掉 `native_xxx`
|
|
809
|
-
和 `
|
|
822
|
+
和 `mcp__agim__xxx` 字面字符串。
|
|
810
823
|
- **下一步软约束**:1-3 个具体可执行建议("继续 / 换数据源 / 缩小范
|
|
811
824
|
围 / 终止"),让模型自然挑词,不强制 a/b/c 选项格式。
|
|
812
825
|
- **off_track 模式**:critic 给的 reason / redirect 注入到 prompt 的
|
|
@@ -821,7 +834,7 @@ adapter.test.ts 已覆盖 commandName 通路。
|
|
|
821
834
|
- 把 `result.toolCalls.slice(-20)` 分成 success / failed 两组分别喂
|
|
822
835
|
——成功的截 300 字预览,失败的截 200 字(错误一般短)
|
|
823
836
|
- 返回的 `costUsd` 累加到 turn 总 cost,audit row 跟着算对
|
|
824
|
-
- env `
|
|
837
|
+
- env `AGIM_NATIVE_STAGE_REPORT=off` 全局禁用,回退到老的纯技术
|
|
825
838
|
recap,调试用
|
|
826
839
|
|
|
827
840
|
#### 兼容性
|
|
@@ -843,7 +856,7 @@ adapter.test.ts 已覆盖 commandName 通路。
|
|
|
843
856
|
- off_track reason 注入到 user prompt
|
|
844
857
|
- provider 返回空 → null(caller 走老 recap)
|
|
845
858
|
- provider 抛错 → null(不外抛)
|
|
846
|
-
- `
|
|
859
|
+
- `AGIM_NATIVE_STAGE_REPORT=off` → 不调 provider,直接 null
|
|
847
860
|
|
|
848
861
|
### 文件
|
|
849
862
|
|
|
@@ -1000,16 +1013,16 @@ delegate 就绕过了。
|
|
|
1000
1013
|
——所有 adapter 都已经认识 AgentSendOpts.planMode(claude-code 翻
|
|
1001
1014
|
`--permission-mode plan`,opencode 走 `--agent plan`,native 进
|
|
1002
1015
|
policy gate 拦写工具)
|
|
1003
|
-
- `
|
|
1016
|
+
- `AgimDispatcherCtx` 加 `callerPlanMode?: boolean`
|
|
1004
1017
|
- native/index.ts 通过 `effectivePlanModeOn(planThreadKey)` 求值后
|
|
1005
|
-
注入
|
|
1018
|
+
注入 agimCtx
|
|
1006
1019
|
- 派发 call_agent 时(in-process self-spawn 和正式 A2A 两条路)都
|
|
1007
1020
|
把这个标志透传出去
|
|
1008
1021
|
|
|
1009
1022
|
**P1a — 子代理返回值整段塞回父上下文**(context bloat)
|
|
1010
1023
|
|
|
1011
1024
|
call_agent 返回的文本默认整段进父对话历史,链 2-3 个就把 native 的
|
|
1012
|
-
context 撑爆了。新增 `
|
|
1025
|
+
context 撑爆了。新增 `AGIM_NATIVE_CALL_AGENT_OUTPUT_MAX_CHARS`
|
|
1013
1026
|
(默认 8000):
|
|
1014
1027
|
|
|
1015
1028
|
- 超过阈值 → 70/30 截首尾 + 中间放截断标记
|
|
@@ -1041,9 +1054,9 @@ claude-code 子代理调起来时偶发 5xx / socket reset,整次 call_agent
|
|
|
1041
1054
|
### 文件
|
|
1042
1055
|
|
|
1043
1056
|
- `src/core/a2a.ts` — `CallAgentOpts.planMode` + 透传到 sendPrompt
|
|
1044
|
-
- `src/core/llm/
|
|
1057
|
+
- `src/core/llm/agim-dispatcher.ts` — `callerPlanMode` + output cap +
|
|
1045
1058
|
retry + history-aware cap_exceeded
|
|
1046
|
-
- `src/plugins/agents/native/index.ts` —
|
|
1059
|
+
- `src/plugins/agents/native/index.ts` — agimCtx 注入 callerPlanMode +
|
|
1047
1060
|
system prompt 加 "when to delegate" 段落
|
|
1048
1061
|
|
|
1049
1062
|
### 不在范围
|
|
@@ -1066,8 +1079,8 @@ v1.2.123 的 graceful-degradation 只处理"有 partial 文本"的场景,零
|
|
|
1066
1079
|
#### 实现
|
|
1067
1080
|
在 `agent-loop.ts` streamThenBuffer 调用点加重试逻辑:
|
|
1068
1081
|
- **触发**:抛错 + isAbort(err)=false + isTransientStreamError(err)=true
|
|
1069
|
-
- **退避**:固定 1s(
|
|
1070
|
-
- **次数**:默认 1 次(
|
|
1082
|
+
- **退避**:固定 1s(AGIM_NATIVE_FIRSTTOKEN_RETRY_DELAY_MS 可调,cap 10s)
|
|
1083
|
+
- **次数**:默认 1 次(AGIM_NATIVE_FIRSTTOKEN_RETRY_MAX 可调,cap 3)
|
|
1071
1084
|
- **退出**:成功立刻退;超 cap 抛最后一次的错
|
|
1072
1085
|
|
|
1073
1086
|
#### 模式识别
|
|
@@ -1136,7 +1149,7 @@ v1.2.123 的 graceful-degradation 只处理"有 partial 文本"的场景,零
|
|
|
1136
1149
|
Before calling any generic tool (web_fetch / web_search / native_exec /
|
|
1137
1150
|
shell-style commands), you MUST scan the skill list below. If any entry's
|
|
1138
1151
|
description matches the user's intent — even loosely — you MUST call
|
|
1139
|
-
|
|
1152
|
+
mcp__agim__read_skill('<name>') first to load that skill's body. Skill
|
|
1140
1153
|
bodies contain dedicated tools, endpoints, or queries that produce
|
|
1141
1154
|
higher-quality, structured results than free-text web pages for the
|
|
1142
1155
|
same intent. Falling back to the generic tool is only valid when:
|
|
@@ -1168,7 +1181,7 @@ prompt 和 dispatcher 里写两次。Prompt 约束是软约束,硬约束应留
|
|
|
1168
1181
|
|
|
1169
1182
|
两项实战反馈一起打:
|
|
1170
1183
|
|
|
1171
|
-
#### 1. `
|
|
1184
|
+
#### 1. `AGIM_NATIVE_AGENT_MAX_ITER` 默认 20 → 50
|
|
1172
1185
|
真实使用观察:CR / 多步重构等任务常需 28-35 次迭代,20 把它们切掉。
|
|
1173
1186
|
50 给充足缓冲;30 分钟 IM 硬超时仍是更早的天花板(按 20-30s / iter
|
|
1174
1187
|
算,撞天花板大约 60-80 次),v1.2.122 语义死循环检测也会在 50 之前
|
|
@@ -1178,8 +1191,8 @@ agent` 调到 100。
|
|
|
1178
1191
|
#### 2. 移除 `先看看` 关键词
|
|
1179
1192
|
v1.2.135 P3 的默认 phrase 列表里有「先看看」,但 CR 指出这条过宽 ——
|
|
1180
1193
|
「先看看这个文件」明显是要读文件,不是 plan-only 意图。如果开启了
|
|
1181
|
-
`
|
|
1182
|
-
列表删除;操作员真需要可通过 `
|
|
1194
|
+
`AGIM_PLAN_INTENT_AUTO`,会把常规读操作误判进 plan 模式。从默认
|
|
1195
|
+
列表删除;操作员真需要可通过 `AGIM_PLAN_INTENT_PHRASES` 自行加
|
|
1183
1196
|
回(v1.2.135 的覆盖机制)。
|
|
1184
1197
|
|
|
1185
1198
|
### 文件
|
|
@@ -1200,7 +1213,7 @@ v1.2.135 P3 的默认 phrase 列表里有「先看看」,但 CR 指出这条
|
|
|
1200
1213
|
- `detectPlanIntent(text)` —— 子串匹配 + 大小写不敏感 + 中英文 26 个内置短语
|
|
1201
1214
|
- 中文:"先想想 / 先规划 / 先讨论 / 不要直接做 / 只规划 / 先别动手" 等
|
|
1202
1215
|
- 英文:"plan only / don't act yet / let's plan / research first / dry run only" 等
|
|
1203
|
-
- `
|
|
1216
|
+
- `AGIM_PLAN_INTENT_PHRASES` env 可整体覆盖(逗号分隔),不是合并;
|
|
1204
1217
|
让操作员能收紧或放宽匹配范围而不改代码
|
|
1205
1218
|
- `shouldAutoEnterPlanMode(prompt)` —— 综合判断:master switch on + 命中
|
|
1206
1219
|
→ 返回命中的短语;否则 null
|
|
@@ -1209,7 +1222,7 @@ v1.2.135 P3 的默认 phrase 列表里有「先看看」,但 CR 指出这条
|
|
|
1209
1222
|
`router.ts:callAgentWithHistory` 在确定 `effectivePlanMode` 后立刻做一次
|
|
1210
1223
|
启发式检查:
|
|
1211
1224
|
```
|
|
1212
|
-
if (planMode OFF +
|
|
1225
|
+
if (planMode OFF + AGIM_PLAN_INTENT_AUTO=on + intent matched) {
|
|
1213
1226
|
effectivePlanMode = true
|
|
1214
1227
|
log({ event: 'plan-intent.auto-enter', matchedPhrase })
|
|
1215
1228
|
}
|
|
@@ -1218,7 +1231,7 @@ if (planMode OFF + IMHUB_PLAN_INTENT_AUTO=on + intent matched) {
|
|
|
1218
1231
|
下一条消息不带这些关键词时自动回到 normal —— 这就是"临时"的语义。
|
|
1219
1232
|
|
|
1220
1233
|
#### 关键设计决策
|
|
1221
|
-
- **默认 OFF**:opt-in,env `
|
|
1234
|
+
- **默认 OFF**:opt-in,env `AGIM_PLAN_INTENT_AUTO=on` 才启用
|
|
1222
1235
|
- **绝不自动退出**:一旦进了 plan mode,要么用户 `/plan off`,要么模型
|
|
1223
1236
|
调 `native_exit_plan_mode`(v1.2.131 的握手)
|
|
1224
1237
|
- **错检 vs 漏检**:错检(用户想动手→被卡到 plan)代价远高于漏检(不
|
|
@@ -1228,8 +1241,8 @@ if (planMode OFF + IMHUB_PLAN_INTENT_AUTO=on + intent matched) {
|
|
|
1228
1241
|
|
|
1229
1242
|
#### 后台 UI
|
|
1230
1243
|
`/settings/native-agent` 早停+复盘卡内新增两项:
|
|
1231
|
-
- `Plan-intent auto-enter` bool toggle → `
|
|
1232
|
-
- `Plan-intent phrase list (optional override)` text → `
|
|
1244
|
+
- `Plan-intent auto-enter` bool toggle → `AGIM_PLAN_INTENT_AUTO`
|
|
1245
|
+
- `Plan-intent phrase list (optional override)` text → `AGIM_PLAN_INTENT_PHRASES`
|
|
1233
1246
|
(开关关闭时输入框 disabled)
|
|
1234
1247
|
|
|
1235
1248
|
env 白名单 (`ENV_EDITABLE_KEYS`) 同步扩展两个键。
|
|
@@ -1425,13 +1438,13 @@ P1 推到 v1.2.133。
|
|
|
1425
1438
|
- 拒绝场景下模型会自动迭代再次调用 `native_exit_plan_mode`
|
|
1426
1439
|
|
|
1427
1440
|
#### 新增 plan_history 审计表
|
|
1428
|
-
- `~/.agim/plan-history.db`(路径可由 `
|
|
1441
|
+
- `~/.agim/plan-history.db`(路径可由 `AGIM_PLAN_HISTORY_DB` 覆盖)
|
|
1429
1442
|
- 每次握手写一条不可变记录:thread_key / plan_md / outcome (approved|rejected|edited|expired)
|
|
1430
1443
|
/ detail / pending_ms / resolved_at
|
|
1431
1444
|
- 为后续 v1.2.133 的 `/tasks/plans` admin 列表查询打底(本版不做 UI)
|
|
1432
1445
|
|
|
1433
1446
|
#### system prompt 改造
|
|
1434
|
-
plan mode banner 之前结尾写"操作员清掉
|
|
1447
|
+
plan mode banner 之前结尾写"操作员清掉 AGIM_NATIVE_PLAN_MODE 你才能动手"。
|
|
1435
1448
|
现在改为:
|
|
1436
1449
|
|
|
1437
1450
|
> Exit handshake (v1.2.131): when the plan is ready, call
|
|
@@ -1601,26 +1614,26 @@ v1.2.126 把搜索 provider + 4 个运行上限接进 web admin,本版把 v1.2
|
|
|
1601
1614
|
#### 新增 4 张卡
|
|
1602
1615
|
|
|
1603
1616
|
**A. A2A 子 Agent 派生**
|
|
1604
|
-
- `
|
|
1605
|
-
- `
|
|
1606
|
-
- `
|
|
1607
|
-
- `
|
|
1617
|
+
- `AGIM_A2A_MAX_DEPTH` — 子 Agent 递归深度(默认 1,v1.2.119)
|
|
1618
|
+
- `AGIM_A2A_TIMEOUT_DEFAULT_MS` — 默认超时(默认 30 分钟)
|
|
1619
|
+
- `AGIM_NATIVE_CALL_AGENT_IN_PROCESS` — native→native 同进程 spawn 开关(默认开,v1.2.121)
|
|
1620
|
+
- `AGIM_NATIVE_CALL_AGENT_MAX_PER_TURN` — 单轮 call_agent 调用上限(默认 2)
|
|
1608
1621
|
|
|
1609
1622
|
**B. 早停 + 复盘**
|
|
1610
|
-
- `
|
|
1611
|
-
- `
|
|
1612
|
-
- `
|
|
1613
|
-
- `
|
|
1623
|
+
- `AGIM_NATIVE_SEMANTIC_STUCK_LOOP` — 语义死循环检测开关(默认开,v1.2.122)
|
|
1624
|
+
- `AGIM_NATIVE_CRITIC` — Goal Critic 复盘开关(默认关)
|
|
1625
|
+
- `AGIM_NATIVE_CRITIC_ROLE` — Critic LLM role override(可选)
|
|
1626
|
+
- `AGIM_NATIVE_PLAN_MODE` — PlanMode 默认状态(不影响 /plan per-thread)
|
|
1614
1627
|
|
|
1615
1628
|
**C. Auto-compact**(v1.2.125 完成的 4 滑块)
|
|
1616
|
-
- `
|
|
1617
|
-
- `
|
|
1618
|
-
- `
|
|
1619
|
-
- `
|
|
1629
|
+
- `AGIM_NATIVE_COMPACT_TRIGGER_CHARS` — 触发阈值(默认 60000)
|
|
1630
|
+
- `AGIM_NATIVE_COMPACT_KEEP_TURNS` — tail 保留 user/assistant 对数(默认 6)
|
|
1631
|
+
- `AGIM_NATIVE_COMPACT_KEEP_FIRST` — head 保留前 N 条 user 消息(默认 1)
|
|
1632
|
+
- `AGIM_NATIVE_COMPACT_SUMMARY_CHARS` — 摘要字符上限(默认 1500)
|
|
1620
1633
|
|
|
1621
1634
|
**D. 流式 + 迭代**
|
|
1622
|
-
- `
|
|
1623
|
-
- `
|
|
1635
|
+
- `AGIM_NATIVE_STREAM_PARTIAL` — 流式增量回写(默认开,v1.2.112/123)
|
|
1636
|
+
- `AGIM_NATIVE_AGENT_MAX_ITER` — 工具循环上限(默认 20,clamp [1,100])
|
|
1624
1637
|
|
|
1625
1638
|
#### 默认值对齐
|
|
1626
1639
|
所有 boolean 类型的默认开关都按 source 行为镜像(v1.2.119/121/122 的 enable-by-default
|
|
@@ -1644,7 +1657,7 @@ v1.2.126 把搜索 provider + 4 个运行上限接进 web admin,本版把 v1.2
|
|
|
1644
1657
|
#### 安全
|
|
1645
1658
|
- 全部走 `requireAdmin()` + `ENV_EDITABLE_KEYS` 白名单
|
|
1646
1659
|
- 不动 SSRF / FS / bwrap 沙箱键(这些已经在 `/settings/security` 与 `/settings/policy`)
|
|
1647
|
-
- 不动 `
|
|
1660
|
+
- 不动 `AGIM_NATIVE_AGENT_ROLE_FILE`(绝对路径敏感,留 env file 配置)
|
|
1648
1661
|
|
|
1649
1662
|
### 文件
|
|
1650
1663
|
- 新增 `test/unit/admin-env-allowed-keys.test.ts` (~95 lines)
|
|
@@ -1663,7 +1676,7 @@ v1.2.126 把搜索 provider + 4 个运行上限接进 web admin,本版把 v1.2
|
|
|
1663
1676
|
#### 新增 `/settings/search` 页面
|
|
1664
1677
|
- 列出 6 个已注册 web_search provider:tavily / brave / serper / exa / duckduckgo / metaso
|
|
1665
1678
|
- 每行包含:
|
|
1666
|
-
- **启用复选框** + **上移/下移按钮** → 编辑 `
|
|
1679
|
+
- **启用复选框** + **上移/下移按钮** → 编辑 `AGIM_WEB_SEARCH_PROVIDERS` CSV 链
|
|
1667
1680
|
- **API key 输入框**(密文输入;已配置时占位符为"已保存(隐藏)",可清空)
|
|
1668
1681
|
- **状态徽章**:configured / missing key / no key needed
|
|
1669
1682
|
- **测试按钮**:一次性发"agim ping"探针,返回 `{ ok, latencyMs, hits }`
|
|
@@ -1671,10 +1684,10 @@ v1.2.126 把搜索 provider + 4 个运行上限接进 web admin,本版把 v1.2
|
|
|
1671
1684
|
|
|
1672
1685
|
#### `/settings/native-agent` 页面新增 Runtime caps 卡片
|
|
1673
1686
|
覆盖 v1.2.118-119 的 4 个运行上限:
|
|
1674
|
-
- `
|
|
1675
|
-
- `
|
|
1676
|
-
- `
|
|
1677
|
-
- `
|
|
1687
|
+
- `AGIM_NATIVE_TOOL_RESULT_MAX_CHARS` — 单次工具返回字符上限
|
|
1688
|
+
- `AGIM_NATIVE_TOOL_TIMEOUT_MS` — 单次工具超时
|
|
1689
|
+
- `AGIM_NATIVE_BLANK_RETRY_MAX` — 空响应重试次数
|
|
1690
|
+
- `AGIM_NATIVE_LENGTH_RECOVERY_MAX` — finishReason=length 续写次数
|
|
1678
1691
|
|
|
1679
1692
|
留空则用默认值;编辑后 Save,下一次调用立即生效。
|
|
1680
1693
|
|
|
@@ -1684,7 +1697,7 @@ v1.2.126 把搜索 provider + 4 个运行上限接进 web admin,本版把 v1.2
|
|
|
1684
1697
|
- `server.ts` 新增两个端点:
|
|
1685
1698
|
- `GET /api/search/providers` — 列出 6 个 provider + 当前 chain
|
|
1686
1699
|
- `POST /api/search/test` — 单次探针,10 秒硬超时
|
|
1687
|
-
- `ENV_EDITABLE_KEYS` 扩展:新增 5 个 `*_API_KEY` + 4 个 `
|
|
1700
|
+
- `ENV_EDITABLE_KEYS` 扩展:新增 5 个 `*_API_KEY` + 4 个 `AGIM_NATIVE_*` 上限键
|
|
1688
1701
|
- `SECRET_KEYS` 扩展:5 个 search API key 全部加入掩码白名单
|
|
1689
1702
|
|
|
1690
1703
|
#### 热生效保证
|
|
@@ -1723,7 +1736,7 @@ v1.2.126 把搜索 provider + 4 个运行上限接进 web admin,本版把 v1.2
|
|
|
1723
1736
|
用户最初要做什么"
|
|
1724
1737
|
|
|
1725
1738
|
#### v1.2.125 修法
|
|
1726
|
-
- 新选项 `keepFirst`(env `
|
|
1739
|
+
- 新选项 `keepFirst`(env `AGIM_NATIVE_COMPACT_KEEP_FIRST`,默认 **1**):
|
|
1727
1740
|
保留前 N 个 user 消息**连同**它们的 assistant 回复 + tool 链 verbatim
|
|
1728
1741
|
- 新 helper `pickHeadEndIndex(messages, N)`:往前走到第 N 个 user,再吃完它之后
|
|
1729
1742
|
所有非-user 消息(assistant + tool),保证 head 是个完整的回合,不会留 orphan
|
|
@@ -1802,8 +1815,8 @@ native agent 现在有一把 in-process 的 plan-tracker 工具:
|
|
|
1802
1815
|
|
|
1803
1816
|
- `src/core/llm/todo-dispatcher.ts`(新 ~165 行)
|
|
1804
1817
|
- `src/plugins/agents/native/index.ts`:import + 加入 dispatcher chain
|
|
1805
|
-
(在
|
|
1806
|
-
加 Plan tracking 段落;planThreadKey 计算上移到
|
|
1818
|
+
(在 agim 之前);defaultBuiltins 加 `native_todo_write`;buildSystemPrompt
|
|
1819
|
+
加 Plan tracking 段落;planThreadKey 计算上移到 agimCtx 之前
|
|
1807
1820
|
- `test/unit/todo-dispatcher.test.ts`(新 / 12 case):write / 渲染 / per-thread
|
|
1808
1821
|
隔离 / 验证 / unknown 工具回退
|
|
1809
1822
|
|
|
@@ -1880,7 +1893,7 @@ tool name 不同所以不 fire,agent 会一直耗到 max_iter。
|
|
|
1880
1893
|
- ≥2 个不同 tool name 才触发,避免与 strict `isStuckLoop` 重叠
|
|
1881
1894
|
- 触发后走 `finishReason='stuck_loop'` 早停(与现有 stuck_loop 路径一致)
|
|
1882
1895
|
- 新 log event `agent-loop.semantic_stuck_loop_detected` 便于排查
|
|
1883
|
-
- `
|
|
1896
|
+
- `AGIM_NATIVE_SEMANTIC_STUCK_LOOP=off` 是 kill switch
|
|
1884
1897
|
|
|
1885
1898
|
### Affected paths
|
|
1886
1899
|
|
|
@@ -1914,8 +1927,8 @@ tool name 不同所以不 fire,agent 会一直耗到 max_iter。
|
|
|
1914
1927
|
本版加入 in-process fast path:
|
|
1915
1928
|
- 当 target=='native' → 跳过 subprocess,直接在同 JS 堆里 `nativeAgentAdapter.sendPrompt()`
|
|
1916
1929
|
- 共享 cwd / MCP fleet / 同一 LLM 后端,但开**全新 session id** 避免污染父对话
|
|
1917
|
-
- 仍按 `
|
|
1918
|
-
- `
|
|
1930
|
+
- 仍按 `AGIM_A2A_MAX_DEPTH`(默认 1)做深度检查 + 走 callerDepth+1 入子层
|
|
1931
|
+
- `AGIM_NATIVE_CALL_AGENT_IN_PROCESS=off` 是 kill switch(强制走 subprocess 老路)
|
|
1919
1932
|
- 子层若再 call_agent 会被 depth 拦下,避免无限递归
|
|
1920
1933
|
- 完整 trace 链:parent traceId → `a2a-{call.id}` → child native loop 内每个 tool
|
|
1921
1934
|
|
|
@@ -1925,18 +1938,18 @@ tool name 不同所以不 fire,agent 会一直耗到 max_iter。
|
|
|
1925
1938
|
- **Serper** (`SERPER_API_KEY`):Google SERP 中继,cheap
|
|
1926
1939
|
- **Exa** (`EXA_API_KEY`):语义/向量搜索,适合"找类似页"
|
|
1927
1940
|
- 新默认链:`tavily,brave,serper,exa,duckduckgo,metaso`
|
|
1928
|
-
- 缺 key 仍然静默跳过,env override `
|
|
1941
|
+
- 缺 key 仍然静默跳过,env override `AGIM_WEB_SEARCH_PROVIDERS` 不变
|
|
1929
1942
|
|
|
1930
1943
|
### Affected paths
|
|
1931
1944
|
|
|
1932
1945
|
- `src/core/llm/web-dispatcher.ts`:新增 `searchBrave/parseBraveResults` /
|
|
1933
1946
|
`searchSerper/parseSerperResults` / `searchExa/parseExaResults` + 注册到
|
|
1934
1947
|
`PROVIDERS`;默认 chain 更新;工具描述更新
|
|
1935
|
-
- `src/core/llm/
|
|
1948
|
+
- `src/core/llm/agim-dispatcher.ts`:`isInProcessSpawnDisabled` helper +
|
|
1936
1949
|
call_agent 分支检测 `agentName === 'native'` → in-process fast path
|
|
1937
1950
|
- `test/unit/web-search-providers.test.ts`:新增 3 个 parse 测试 + 1 个默认
|
|
1938
1951
|
chain 顺序测试 + 1 个三 provider 同时启用测试
|
|
1939
|
-
- `src/core/llm/
|
|
1952
|
+
- `src/core/llm/agim-dispatcher.test.ts`:新增 4 个 case(depth 拒绝 / A2A
|
|
1940
1953
|
disabled / 非 native 不走 in-process / kill switch 强制 subprocess)
|
|
1941
1954
|
|
|
1942
1955
|
### Test status
|
|
@@ -1960,11 +1973,11 @@ tool name 不同所以不 fire,agent 会一直耗到 max_iter。
|
|
|
1960
1973
|
|
|
1961
1974
|
- 新增 `src/core/plan-mode-state.ts`:sqlite 表 `native_plan_mode(thread_key PK,
|
|
1962
1975
|
enabled, updated_at)`,per-thread 持久化覆盖;DB 默认 `~/.agim/plan-mode.db`,
|
|
1963
|
-
env `
|
|
1976
|
+
env `AGIM_PLAN_MODE_DB` 可指定路径
|
|
1964
1977
|
- 三态优先级 `effectivePlanModeOn(threadKey)`:
|
|
1965
1978
|
1. per-thread = **true** → on(即使 env=off)
|
|
1966
1979
|
2. per-thread = **false** → off(即使 env=on——一个线程可单独 opt-out)
|
|
1967
|
-
3. per-thread = null(未设置)→ 回退到 env `
|
|
1980
|
+
3. per-thread = null(未设置)→ 回退到 env `AGIM_NATIVE_PLAN_MODE`
|
|
1968
1981
|
- `/plan on|off` 现在**同时**写 sessionManager.planMode(claude-code / codex /
|
|
1969
1982
|
opencode 用)和 plan-mode-state.db(native 用),native 加入 PLAN_CAPABLE_AGENTS
|
|
1970
1983
|
集合,提示文案里移除"native 不读 planMode"的警告
|
|
@@ -2008,16 +2021,16 @@ tool name 不同所以不 fire,agent 会一直耗到 max_iter。
|
|
|
2008
2021
|
- `src/core/a2a.ts:A2A_MAX_DEPTH_DEFAULT` 从 3 改为 1,对齐 OpenAI Codex CLI 的
|
|
2009
2022
|
`agents.max_depth=1` 默认。理由:链式委派(A 调 B 调 C …)几乎都是 LLM 失策,
|
|
2010
2023
|
外层应该用自己的工具收尾,而不是再委派。**Breaking-ish**:依赖 max_depth=3 的
|
|
2011
|
-
环境 `export
|
|
2012
|
-
- 配套:`callerDepth` 传播链路(
|
|
2024
|
+
环境 `export AGIM_A2A_MAX_DEPTH=3` 恢复。
|
|
2025
|
+
- 配套:`callerDepth` 传播链路(agim-dispatcher → callAgentByName → 检查 ceil)
|
|
2013
2026
|
本来就在,所以这一项**主要是默认值收紧**,逻辑没大动
|
|
2014
2027
|
|
|
2015
|
-
#### Item 5 — PlanMode(`
|
|
2028
|
+
#### Item 5 — PlanMode(`AGIM_NATIVE_PLAN_MODE=1`)
|
|
2016
2029
|
- 对齐 opencode plan-mode UX:env-toggled hard-deny `native_write_file` +
|
|
2017
2030
|
`native_exec`。读工具(Read/Grep/Glob/web_fetch/web_search)保持可用,agent
|
|
2018
2031
|
只能产出**只读规划**
|
|
2019
2032
|
- 实现:`resolvePolicy()` 在 PlanMode on 时把上述写工具追加到 denyList(与用户的
|
|
2020
|
-
`
|
|
2033
|
+
`AGIM_NATIVE_AGENT_DENYLIST` 合并去重)
|
|
2021
2034
|
- 加上系统 prompt 顶部的 `⚠ Plan mode is ACTIVE` 横幅,明确告诉模型现在不能落地,
|
|
2022
2035
|
让它产出 plan 后停手而不是反复试探被 deny
|
|
2023
2036
|
|
|
@@ -2028,7 +2041,7 @@ tool name 不同所以不 fire,agent 会一直耗到 max_iter。
|
|
|
2028
2041
|
final answer`",最多重试 2 次
|
|
2029
2042
|
- 与 length-recovery 互不冲突:`finishReason=length` 优先走截断续写,因为它有
|
|
2030
2043
|
partial text;blank-retry 处理的是真正"啥也没说"的失态
|
|
2031
|
-
- `
|
|
2044
|
+
- `AGIM_NATIVE_BLANK_RETRY_MAX` 控制,默认 2,最大 5,0=禁用
|
|
2032
2045
|
|
|
2033
2046
|
### Affected paths
|
|
2034
2047
|
|
|
@@ -2039,7 +2052,7 @@ tool name 不同所以不 fire,agent 会一直耗到 max_iter。
|
|
|
2039
2052
|
`resolvePolicy` 加 PlanMode 合并;`buildSystemPrompt` 加 PlanMode 横幅;export
|
|
2040
2053
|
这三个供测试
|
|
2041
2054
|
- `src/plugins/agents/native/native.test.ts`:在 clearAll 中显式
|
|
2042
|
-
`
|
|
2055
|
+
`AGIM_NATIVE_BLANK_RETRY_MAX=0` 让 legacy adapter 测试不受 blank-retry 影响
|
|
2043
2056
|
- `test/unit/agent-loop-blank-retry.test.ts`(新,5 case):one-shot recover /
|
|
2044
2057
|
cap=2 / cap=0 disable / tool_calls 不触发 / length 优先
|
|
2045
2058
|
- `src/plugins/agents/native/plan-mode.test.ts`(新,14 case):env 解析各形态 +
|
|
@@ -2071,20 +2084,20 @@ sst/opencode / Cursor / Continue.dev),按 ROI 排序产出 12 项改进路
|
|
|
2071
2084
|
- 新增 `SearchProvider` 接口(`name` / `available()` / `search()`)
|
|
2072
2085
|
- 内置 3 个 provider:**Tavily**(新增;行业默认 agent 搜索,`TAVILY_API_KEY`) /
|
|
2073
2086
|
DuckDuckGo(无 key) / Metaso(`METASO_API_KEY`)
|
|
2074
|
-
- 通过 `
|
|
2087
|
+
- 通过 `AGIM_WEB_SEARCH_PROVIDERS` 环境变量定义有序链
|
|
2075
2088
|
(默认 `tavily,duckduckgo,metaso`),首个返回 ≥1 结果的胜出
|
|
2076
2089
|
- 缺 key 的 provider **静默跳过**(不刷日志);未知 provider 名 warn 一次后跳过
|
|
2077
2090
|
- 添加 Tavily provider 后只需 `export TAVILY_API_KEY=tvly-...` 即可启用
|
|
2078
2091
|
|
|
2079
2092
|
#### Item 2 — per-tool-result 字节上限
|
|
2080
2093
|
- `src/core/llm/agent-loop.ts` 在 dispatch 包装层加 `truncateToolResult()`:
|
|
2081
|
-
- 默认 32 KB 上限(`
|
|
2094
|
+
- 默认 32 KB 上限(`AGIM_NATIVE_TOOL_RESULT_MAX_CHARS`),0 = 禁用
|
|
2082
2095
|
- 超限文本带明确截断标记返回模型:`…[native_grep output truncated: 5000000 of 5032768 chars omitted]`
|
|
2083
2096
|
- 防止一条 grep / curl 把 context 喂爆,比 auto-compact 触发更早更安全
|
|
2084
2097
|
|
|
2085
2098
|
#### Item 3 — per-tool 钟摆超时
|
|
2086
2099
|
- `ToolDef` 新增 `timeoutMs?: number` 字段;新 `dispatchWithTimeout()` helper:
|
|
2087
|
-
- 默认 60 秒(`
|
|
2100
|
+
- 默认 60 秒(`AGIM_NATIVE_TOOL_TIMEOUT_MS`),0 = 关闭该工具的超时(如 `long_task`)
|
|
2088
2101
|
- 超时后**返回结构化 timeout 工具结果**(不是抛异常),模型看到 tool-level 失败
|
|
2089
2102
|
- 同步 abort 子调用的 signal,防 wedge
|
|
2090
2103
|
|
|
@@ -2124,7 +2137,7 @@ sst/opencode / Cursor / Continue.dev),按 ROI 排序产出 12 项改进路
|
|
|
2124
2137
|
任何 partial tool_calls(避免 obot 文档化的"$0.91 烧在 6 次连续 length retry
|
|
2125
2138
|
执行截断 JSON 上"灾难),注入合成 user 消息:`Your previous response was cut
|
|
2126
2139
|
off … Continue from exactly where you left off — do not repeat any content`
|
|
2127
|
-
- **per-turn 计数器 cap=3**:与 HKUDS/nanobot 一致;env `
|
|
2140
|
+
- **per-turn 计数器 cap=3**:与 HKUDS/nanobot 一致;env `AGIM_NATIVE_LENGTH_
|
|
2128
2141
|
RECOVERY_MAX` 可调(0 = 完全关闭走老逻辑,最大 10)
|
|
2129
2142
|
- **partial text 累积返回**:新增 `lengthRecoveryPrefix` 串,所有终止路径
|
|
2130
2143
|
(aborted / error / stuck_loop / off_track / max_iterations / 早 terminate)
|
|
@@ -2315,8 +2328,8 @@ sst/opencode / Cursor / Continue.dev),按 ROI 排序产出 12 项改进路
|
|
|
2315
2328
|
- `AgentLoopInput` 新增两字段:`streamPartialText?: boolean`(caller 显式
|
|
2316
2329
|
opt-in;默认 false 保持 v1.2.111 行为不变)+ `onPartialText?: (delta,
|
|
2317
2330
|
totalSoFar) => void`(流式回调,将来可挂 IM 端 SSE 推送)。
|
|
2318
|
-
- **native 默认开启**:`
|
|
2319
|
-
全局 `
|
|
2331
|
+
- **native 默认开启**:`AGIM_NATIVE_STREAM_PARTIAL`(默认 'on';'off' 关闭)+
|
|
2332
|
+
全局 `AGIM_AGENT_LOOP_STREAM`(默认 'on';'off' 强制 buffer)双重 kill
|
|
2320
2333
|
switch,万一某 vendor 流式不稳可立即降级。
|
|
2321
2334
|
|
|
2322
2335
|
### Tests
|
|
@@ -2340,7 +2353,7 @@ v1.2.112(③)。下一步是真实使用观察 + 长尾红测试修复。
|
|
|
2340
2353
|
- **每个工具调用单独落 audit 行 + traceId 跨 A2A 贯通。** 之前 agent-loop 只在
|
|
2341
2354
|
iteration 层落一行 (`intent='native.agent.iter'`),单工具调用只在内存里;事后
|
|
2342
2355
|
无法在 audit 表按 traceId 拼出"一个 turn 里跑了哪些工具/sub-agent / 在哪一步
|
|
2343
|
-
失败"。同时
|
|
2356
|
+
失败"。同时 agim-dispatcher 调 A2A 时自造 `native-a2a-${Date.now()}`,把 turn
|
|
2344
2357
|
的 traceId 链断了。本版:
|
|
2345
2358
|
- agent-loop 在 slot 提交时调用新的 `writeToolCallAudit(audit, report)`,每个
|
|
2346
2359
|
tool call 一行 `intent='tool.<name>'`,traceId = 父 traceId,agent = 父
|
|
@@ -2348,7 +2361,7 @@ v1.2.112(③)。下一步是真实使用观察 + 长尾红测试修复。
|
|
|
2348
2361
|
`success = !isError`。deny / schema-validation 失败 / 真正派发都会落行。
|
|
2349
2362
|
- `ToolDispatcher` 类型新增可选第三参 `ctx?: ToolDispatcherContext { traceId? }`。
|
|
2350
2363
|
agent-loop 调 dispatch 时把 `input.audit?.traceId` 透传;`combineDispatchers`
|
|
2351
|
-
转发;
|
|
2364
|
+
转发;agim-dispatcher A2A 路径读 ctx.traceId 构造 `${parent}/a2a-${call.id}`
|
|
2352
2365
|
作为子 trace(无父则回退老格式,向后兼容)。其他 dispatcher 因为参数可选
|
|
2353
2366
|
完全不感知,0 改动。
|
|
2354
2367
|
- `queryInvocations` 新增 `traceId` / `tracePrefix` 过滤参数,按 trace 反查
|
|
@@ -2378,7 +2391,7 @@ v1.2.112(③)。下一步是真实使用观察 + 长尾红测试修复。
|
|
|
2378
2391
|
`required`/`enum`/`additionalProperties:false`/对象一层嵌套/数组 `items`。复杂
|
|
2379
2392
|
schema($ref/oneOf/format/数值约束)静默通过——失败开 footgun 比假阳性危险。
|
|
2380
2393
|
对 agim 现有 tool 的扁平 object schema 足够。
|
|
2381
|
-
- **Env 关阀**:`
|
|
2394
|
+
- **Env 关阀**:`AGIM_TOOL_SCHEMA_VALIDATE=off` 关闭校验,回退到 v1.2.109 行为,
|
|
2382
2395
|
万一某 vendor schema 触发误报有快速逃生路径。
|
|
2383
2396
|
|
|
2384
2397
|
### Tests
|
|
@@ -2407,7 +2420,7 @@ v1.2.112(③)。下一步是真实使用观察 + 长尾红测试修复。
|
|
|
2407
2420
|
- **native 内置声明的 parallel-safe 集合**(`NATIVE_PARALLEL_SAFE_TOOLS`):
|
|
2408
2421
|
`native_echo` / `native_now` / `native_random_uuid` / `native_read_file` /
|
|
2409
2422
|
`native_list_dir` / `native_glob` / `native_grep` / `native_web_fetch` /
|
|
2410
|
-
`native_web_search` / `
|
|
2423
|
+
`native_web_search` / `mcp__agim__{read_skill,list_skills,search_memos,
|
|
2411
2424
|
memory_list,memory_query}`。`native_exec` / `native_write_file` / 任何写类
|
|
2412
2425
|
memo / `push_message` / `ask_user` / `call_agent` / `long_task` /
|
|
2413
2426
|
`complete_goal` / 其他 MCP 均不在内(保持串行 + barrier)。
|
|
@@ -2427,7 +2440,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2427
2440
|
DeepSeek / Moonshot 等 OpenAI-compat 提供方返回 429 时把服务器要求的几秒等待
|
|
2428
2441
|
完全无视,250ms 后再撞墙、跳到 fallback provider,吃 cold-start + 模型语义切换。
|
|
2429
2442
|
现在默认 4 次尝试(base 250ms、cap 30s、jitter ±20%),`Retry-After` 作为硬下限
|
|
2430
|
-
(秒/HTTP-date 两种 RFC 7231 格式都支持)。`
|
|
2443
|
+
(秒/HTTP-date 两种 RFC 7231 格式都支持)。`AGIM_LLM_RETRY_MAX` 覆盖默认(clamp
|
|
2431
2444
|
[0,10])。导出 `parseRetryAfter` / `computeBackoffMs` 两个纯函数 + 13 个回归测试。
|
|
2432
2445
|
- **stuck-loop 早停升级为 `(name, argsKey, errorType)` 三元组。** v1.2.95 用的是
|
|
2433
2446
|
`(name, isError, preview[0..200])`:模型只要让结果文本带个时间戳/换行/计数器就
|
|
@@ -2439,7 +2452,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2439
2452
|
成功重置)。** v1.2.96 的 cachedTools 永不刷新——上游 MCP server 加新工具/改
|
|
2440
2453
|
schema 必须重启 agim 才看得见;重连冷却也是固定 5s,永远 broken 的 server 被
|
|
2441
2454
|
5s 一次永久敲。现在:`McpClient.cachedTools` 带 `fetchedAt`,
|
|
2442
|
-
`
|
|
2455
|
+
`AGIM_MCP_TOOLS_TTL_MS` 控制 TTL(0=不缓存),新增 `refresh()` 主动清缓存;
|
|
2443
2456
|
`mcp-registry.tryReconnect` 按 `state.reconnectFailures` 指数翻倍冷却,成功
|
|
2444
2457
|
立即 reset 为 0。导出 `computeReconnectCooldownMs` + 8 个回归测试。
|
|
2445
2458
|
|
|
@@ -2468,7 +2481,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2468
2481
|
`bunfig.toml` preload (stray `bun test <file>`, wrong cwd, a different
|
|
2469
2482
|
runner) leaves `AGIM_HOME` pointed at the real `~/.agim`, so
|
|
2470
2483
|
`admin-bootstrap.test.ts`'s `promoteAdmin('telegram','123')` →
|
|
2471
|
-
`updateEnvFile()` overwrites the operator's real `
|
|
2484
|
+
`updateEnvFile()` overwrites the operator's real `AGIM_ADMIN_USERS`,
|
|
2472
2485
|
locking them out of every admin command. The preload sandbox was the
|
|
2473
2486
|
only guard and is a single point of failure. Fix: a second,
|
|
2474
2487
|
preload-independent guard — `assertEnvWriteAllowed()` in
|
|
@@ -2550,7 +2563,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2550
2563
|
- **`/long_task` and `/complete_goal` slash commands.** Field observation
|
|
2551
2564
|
(the goal-critic recap card already hints at them, and users tried them
|
|
2552
2565
|
after off-track verdicts): both names existed only as MCP tools
|
|
2553
|
-
(`
|
|
2566
|
+
(`mcp__agim__long_task` / `mcp__agim__complete_goal`), so a human
|
|
2554
2567
|
typing `/long_task ship v1.2` in chat got back "Unknown command".
|
|
2555
2568
|
Added parser branches in `router.ts`:
|
|
2556
2569
|
- `/long_task <title>` → equivalent to `/goal set <title>`
|
|
@@ -2591,7 +2604,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2591
2604
|
### Fixed
|
|
2592
2605
|
|
|
2593
2606
|
- **bwrap sandbox: `/bin/sh` ENOENT, every `native_exec` failed.**
|
|
2594
|
-
Field report: with `
|
|
2607
|
+
Field report: with `AGIM_EXEC_SANDBOX=bwrap`, every command
|
|
2595
2608
|
the model tried to run came back as `ENOENT`. Root cause:
|
|
2596
2609
|
`buildBwrapInvocation` used `/bin/sh` as the shell, but on
|
|
2597
2610
|
usrmerge systems (modern Debian / Ubuntu / Fedora — most
|
|
@@ -2629,7 +2642,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2629
2642
|
story** (CR finding A2). v1.2.98 docs said the critic was off
|
|
2630
2643
|
by default for daily-driver turns; the code actually defaulted
|
|
2631
2644
|
on whenever the per-turn prompt was non-empty (which is
|
|
2632
|
-
always). `
|
|
2645
|
+
always). `AGIM_NATIVE_CRITIC` is now a three-valued knob:
|
|
2633
2646
|
- `off` (or `0` / `false`) — hard kill switch, never fire.
|
|
2634
2647
|
- `always` (or `on` / `1` / `true`) — fire whenever an
|
|
2635
2648
|
anchor exists; previous v1.2.98 default behaviour.
|
|
@@ -2668,7 +2681,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2668
2681
|
native renders a redirect recap citing the critic's reason
|
|
2669
2682
|
+ suggested new direction.
|
|
2670
2683
|
|
|
2671
|
-
Cost gate: disabled if `
|
|
2684
|
+
Cost gate: disabled if `AGIM_NATIVE_CRITIC=off`, if no
|
|
2672
2685
|
`cheap` role provider is configured, or if neither prompt nor
|
|
2673
2686
|
active goal is available as an anchor. Trigger only after 5+
|
|
2674
2687
|
tool calls so day-to-day short turns pay nothing. Diagnostic
|
|
@@ -2699,16 +2712,16 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2699
2712
|
- `core/llm/agim-rpc-server.ts` — Unix-socket HTTP server on
|
|
2700
2713
|
`AGIM_HOME/rpc.sock` (mode 0600, never bound to a TCP port).
|
|
2701
2714
|
Per-process token registry. Tool whitelist hard-coded to
|
|
2702
|
-
five read/write-safe
|
|
2715
|
+
five read/write-safe agim MCP tools: `search_memos`,
|
|
2703
2716
|
`save_memo`, `read_skill`, `list_skills`, `push_message`.
|
|
2704
|
-
Operators can extend via `
|
|
2705
|
-
Token TTL 24 h, configurable via `
|
|
2717
|
+
Operators can extend via `AGIM_RPC_ALLOWED_TOOLS`.
|
|
2718
|
+
Token TTL 24 h, configurable via `AGIM_RPC_TOKEN_TTL_MS`.
|
|
2706
2719
|
- `bin/agim_rpc.py` — stdlib-only Python sidecar shipped in
|
|
2707
2720
|
the npm package. `from agim_rpc import client; rpc =
|
|
2708
2721
|
client()` reads env + validates, then `rpc.search_memos(...)`
|
|
2709
2722
|
/ `rpc.push_message(...)` are typed wrappers.
|
|
2710
2723
|
- `exec-dispatcher`: every spawn under a known `rpcCtx` gets
|
|
2711
|
-
`
|
|
2724
|
+
`AGIM_RPC_SOCKET` + `AGIM_RPC_TOKEN` injected as env (not
|
|
2712
2725
|
argv — keeps the token out of `ps`). Token is bound to the
|
|
2713
2726
|
spawning thread; the worker can only drive its OWN IM
|
|
2714
2727
|
thread's tool surface, never anyone else's.
|
|
@@ -2746,7 +2759,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2746
2759
|
flagged `!isConnected()` before the call, or (b) `callTool`
|
|
2747
2760
|
itself throws — and runs `close() → connect() → retry once`.
|
|
2748
2761
|
Per-server cooldown (default 5 s, configurable via
|
|
2749
|
-
`
|
|
2762
|
+
`AGIM_MCP_RECONNECT_COOLDOWN_MS`) prevents hammering a
|
|
2750
2763
|
persistently-broken server. Diagnostic events:
|
|
2751
2764
|
`mcp-registry.reconnect_throttled / reconnected /
|
|
2752
2765
|
reconnect_failed / tool_call_threw`.
|
|
@@ -2757,7 +2770,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2757
2770
|
substantive turn for facts worth outliving the chat (personal
|
|
2758
2771
|
preferences, holdings / portfolio codes, recurring people /
|
|
2759
2772
|
places, stable identifiers, explicit "记一下" instructions) and
|
|
2760
|
-
call `
|
|
2773
|
+
call `mcp__agim__save_memo` itself without waiting for the
|
|
2761
2774
|
user to ask. Also tells it what NOT to save (one-off
|
|
2762
2775
|
questions, transient debug state) and to use small atomic
|
|
2763
2776
|
memos rather than one large one. Cost is just prompt bytes;
|
|
@@ -2840,7 +2853,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2840
2853
|
`bgjob status / tail` for follow-ups and explicitly forbids
|
|
2841
2854
|
`nohup … &` (those die with the parent shell).
|
|
2842
2855
|
- **bwrap sandbox carve-out for the bgjob wrapper.** When
|
|
2843
|
-
`
|
|
2856
|
+
`AGIM_EXEC_SANDBOX=bwrap`, bwrap's pid / cgroup namespace
|
|
2844
2857
|
used to tear down bgjob's `setsid`-detached worker the
|
|
2845
2858
|
moment `bgjob start` returned — so the model saw success
|
|
2846
2859
|
while the worker died a second later. `isBgjobInvocation`
|
|
@@ -2858,9 +2871,9 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2858
2871
|
|
|
2859
2872
|
### Fixed
|
|
2860
2873
|
|
|
2861
|
-
- **`
|
|
2874
|
+
- **`AGIM_NATIVE_AGENT_MAX_ITER` was dead documentation.** The
|
|
2862
2875
|
max-iterations banner had been telling operators to "raise
|
|
2863
|
-
|
|
2876
|
+
AGIM_NATIVE_AGENT_MAX_ITER" since v1.2.48, but no code path
|
|
2864
2877
|
ever read the env var — the agent loop quietly used the
|
|
2865
2878
|
hard-coded default of 20 regardless. `resolveMaxIterations()`
|
|
2866
2879
|
now reads the env (clamped to [1, 100]) and passes it to
|
|
@@ -2874,7 +2887,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2874
2887
|
last step's output, name the cause ("model wanted to keep going
|
|
2875
2888
|
but hit the safety cap at iteration N"), and offer three
|
|
2876
2889
|
continuation paths — reply 继续 to push forward, split the task
|
|
2877
|
-
into smaller pieces, or raise `
|
|
2890
|
+
into smaller pieces, or raise `AGIM_NATIVE_AGENT_MAX_ITER` to
|
|
2878
2891
|
2× current (capped at 100). Diagnostic
|
|
2879
2892
|
`native.turn.max_iterations` log added so the audit trail
|
|
2880
2893
|
records iterations / cap / last tool name.
|
|
@@ -2931,7 +2944,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
2931
2944
|
turn, and notes picture-count in the dispatched text so the
|
|
2932
2945
|
user knows to re-send images standalone for multimodal
|
|
2933
2946
|
parsing.
|
|
2934
|
-
- **`
|
|
2947
|
+
- **`mcp__agim__ask_user` typed replies were silently dropped.**
|
|
2935
2948
|
`ask-user-router.tryHandleAskReply` was defined and documented
|
|
2936
2949
|
to be called from `cli.ts` onMessage, but no caller existed —
|
|
2937
2950
|
the function was dead code. Result: when an agent invoked
|
|
@@ -3002,11 +3015,11 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
3002
3015
|
- **Long-task: active goal exempts the wall-clock timeout.** Inspired
|
|
3003
3016
|
by nanobot's "an objective in flight is not a turn", agent-loop +
|
|
3004
3017
|
A2A now consult `hasActiveGoal(platform, channelId, threadId)` and
|
|
3005
|
-
multiply the base timeout by `
|
|
3018
|
+
multiply the base timeout by `AGIM_GOAL_ACTIVE_TIMEOUT_MULTIPLIER`
|
|
3006
3019
|
(default `3`, hard-capped at 6 h). The native 30-minute SIGTERM no
|
|
3007
3020
|
longer kills a "research-an-entire-day" objective mid-flight; once
|
|
3008
3021
|
the goal is `complete_goal`'d, the next turn's timeout falls back
|
|
3009
|
-
to the normal base. Opt-out: `
|
|
3022
|
+
to the normal base. Opt-out: `AGIM_GOAL_ACTIVE_TIMEOUT_MULTIPLIER=1`.
|
|
3010
3023
|
- **Event-bus emission for goal state changes.** New `GoalEvent` type
|
|
3011
3024
|
in `event-bus.ts` (`phase: created | status | progress`). `goal-rpc`
|
|
3012
3025
|
publishes on `long_task` (created + auto-paused prior), on
|
|
@@ -3199,7 +3212,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
3199
3212
|
command; works regardless of input state. Up / Down + Enter to
|
|
3200
3213
|
pick, Esc to dismiss.
|
|
3201
3214
|
- **Completion bell**. After each agent reply ends successfully, write
|
|
3202
|
-
`\x07` to stdout. Disable with `
|
|
3215
|
+
`\x07` to stdout. Disable with `AGIM_TUI_NO_BELL=1`.
|
|
3203
3216
|
- **Markdown rendering** for assistant replies. New `Markdown` Ink
|
|
3204
3217
|
component walks `marked`'s lexer tokens to emit native Ink boxes:
|
|
3205
3218
|
headings (depth-coloured), paragraphs, bold / italic / strikethrough,
|
|
@@ -3264,7 +3277,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
3264
3277
|
- `tsconfig.json`: `"jsx": "react-jsx"` for tsx files.
|
|
3265
3278
|
- Root logger is set to `silent` for the TUI session (and restored
|
|
3266
3279
|
on exit) so pino-pretty doesn't write to fd 1 and scramble Ink's
|
|
3267
|
-
diff renderer. `
|
|
3280
|
+
diff renderer. `AGIM_TUI_VERBOSE=1` keeps logs flowing (helpful
|
|
3268
3281
|
when stuck — pair with `2>tui.log`).
|
|
3269
3282
|
|
|
3270
3283
|
## [1.2.75] - 2026-05-26
|
|
@@ -3329,7 +3342,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
3329
3342
|
|
|
3330
3343
|
### Removed
|
|
3331
3344
|
|
|
3332
|
-
- **Legacy v1 web admin: gone for good.** The `
|
|
3345
|
+
- **Legacy v1 web admin: gone for good.** The `AGIM_WEB_V2` env gate
|
|
3333
3346
|
is removed; v2 SPA is the only web admin path now. Multiple
|
|
3334
3347
|
operators kept hitting "white screen / wrong page" because the
|
|
3335
3348
|
default env (`unset`) was being misread on some installs, and the
|
|
@@ -3342,7 +3355,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
3342
3355
|
- `src/web/public/_app.js` (248 lines — shared v1 theme / i18n /
|
|
3343
3356
|
auth-aware fetch; replaced by the v2 SPA's bundle)
|
|
3344
3357
|
- **Removed routes** in `web/server.ts`:
|
|
3345
|
-
- The `process.env.
|
|
3358
|
+
- The `process.env.AGIM_WEB_V2 !== '0'` env gate is gone — SPA
|
|
3346
3359
|
fallback is now unconditional for GET requests.
|
|
3347
3360
|
- The legacy `/settings` / `/tasks` / `/reminders` / `/memos`
|
|
3348
3361
|
direct-HTML routing block deleted.
|
|
@@ -3351,13 +3364,13 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
3351
3364
|
- **No back-out hatch.** Operators who were on v1 (last shipped
|
|
3352
3365
|
default-ON 1.2.20 → flipped default-v2 1.2.21, knob preserved until
|
|
3353
3366
|
1.2.71) flipped over automatically when they upgraded. Anyone who
|
|
3354
|
-
still set `
|
|
3367
|
+
still set `AGIM_WEB_V2=0` in `~/.agim/env` can safely delete the
|
|
3355
3368
|
line — the value is ignored.
|
|
3356
3369
|
|
|
3357
3370
|
### Notes
|
|
3358
3371
|
|
|
3359
|
-
- `
|
|
3360
|
-
`
|
|
3372
|
+
- `AGIM_ENABLE_GLOBAL_IM` / `AGIM_ENABLE_REMOTE_AGENT` /
|
|
3373
|
+
`AGIM_PLATFORM_BLACKLIST` etc. are unaffected — those gate IM
|
|
3361
3374
|
platform visibility inside the SPA, not the SPA itself.
|
|
3362
3375
|
- `/loc` / `/loc.html` SSR pages and `/login.html` stay (they're not
|
|
3363
3376
|
part of the SPA).
|
|
@@ -3366,12 +3379,12 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
3366
3379
|
|
|
3367
3380
|
### Fixed
|
|
3368
3381
|
|
|
3369
|
-
- **
|
|
3382
|
+
- **AGIM_PLATFORM_BLACKLIST: SPA PlatformCards now hidden.**
|
|
3370
3383
|
v1.2.69 added 3-layer blacklist enforcement (registry refusal at
|
|
3371
3384
|
boot, CLI wizard filter, web GET `/api/config` field stripping)
|
|
3372
3385
|
but left the SPA `messengers.tsx` page hardcoding 5 `PlatformCard`
|
|
3373
3386
|
components that ignored the blacklist. Operators who set
|
|
3374
|
-
`
|
|
3387
|
+
`AGIM_PLATFORM_BLACKLIST=feishu,discord` still saw the Feishu /
|
|
3375
3388
|
Discord cards in /settings/messengers (with the fields blank,
|
|
3376
3389
|
since the backend correctly returned `null` for those slots).
|
|
3377
3390
|
- **Backend** (`web/server.ts:1574`): `/api/config` now returns
|
|
@@ -3444,14 +3457,14 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
3444
3457
|
### Notes
|
|
3445
3458
|
|
|
3446
3459
|
- CR-5 (exec-dispatcher dangerous-pattern regex bypass) and CR-6
|
|
3447
|
-
(`
|
|
3460
|
+
(`AGIM_NATIVE_EXEC_SANDBOX` defaults off) deferred to the next
|
|
3448
3461
|
batch alongside CR-2 (DNS-aware SSRF resolver).
|
|
3449
3462
|
|
|
3450
3463
|
## [1.2.69] - 2026-05-26
|
|
3451
3464
|
|
|
3452
3465
|
### Added
|
|
3453
3466
|
|
|
3454
|
-
- **`
|
|
3467
|
+
- **`AGIM_PLATFORM_BLACKLIST` env** — comma-separated list of IM
|
|
3455
3468
|
platform ids that the bot will REFUSE to enable. Default empty
|
|
3456
3469
|
(no blocks; backward compatible). Three-layer enforcement:
|
|
3457
3470
|
1. **Registry** (`core/registry.ts`): `registry.registerMessenger`
|
|
@@ -3462,7 +3475,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
3462
3475
|
2. **CLI wizard** (`core/onboarding.ts`): blacklisted platforms
|
|
3463
3476
|
vanish from `getAvailableMessengers()` so the wizard never
|
|
3464
3477
|
prompts for them. Layered on top of the existing
|
|
3465
|
-
`
|
|
3478
|
+
`AGIM_ENABLE_GLOBAL_IM` filter.
|
|
3466
3479
|
3. **Web admin** (`/api/messengers` GET): per-platform credential
|
|
3467
3480
|
blocks (`telegram` / `discord` / `feishu` / `dingtalk` /
|
|
3468
3481
|
`wechat`) are omitted from the response when their id (or
|
|
@@ -3484,7 +3497,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
3484
3497
|
- New section at the bottom: input field for the blacklist CSV
|
|
3485
3498
|
+ live preview of "currently in force" entries.
|
|
3486
3499
|
- `ENV_EDITABLE_KEYS` in `web/server.ts` extended with
|
|
3487
|
-
`
|
|
3500
|
+
`AGIM_PLATFORM_BLACKLIST`.
|
|
3488
3501
|
- `/api/security/diagnostics` returns `platformBlacklist: string[]`.
|
|
3489
3502
|
|
|
3490
3503
|
### Internal
|
|
@@ -3516,7 +3529,7 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
3516
3529
|
1. **Runtime diagnostics** (read-only badges): running-as-root,
|
|
3517
3530
|
env-file permissions (0600 / lax), bubblewrap availability,
|
|
3518
3531
|
sender allowlist configured, admin allowlist configured.
|
|
3519
|
-
2. **Sender allowlist** — `
|
|
3532
|
+
2. **Sender allowlist** — `AGIM_ALLOWED_USERS` editor.
|
|
3520
3533
|
3. **Native exec tool** — sandbox backend (none / bwrap, disabled
|
|
3521
3534
|
when bwrap missing), sandbox-net, timeout, max output.
|
|
3522
3535
|
4. **Native web tools** — allow-all-private toggle, SSRF CIDR
|
|
@@ -3531,12 +3544,12 @@ compat)、完成顺序 ≠ 原始顺序时 history 仍按原始顺序、serial
|
|
|
3531
3544
|
### Changed
|
|
3532
3545
|
|
|
3533
3546
|
- `ENV_EDITABLE_KEYS` in `web/server.ts` extended with the 11 new
|
|
3534
|
-
v1.2.58–v1.2.66 security knobs (`
|
|
3535
|
-
`
|
|
3536
|
-
`
|
|
3537
|
-
`
|
|
3538
|
-
`
|
|
3539
|
-
`
|
|
3547
|
+
v1.2.58–v1.2.66 security knobs (`AGIM_ALLOWED_USERS`,
|
|
3548
|
+
`AGIM_NATIVE_FS_RESTRICT`, `AGIM_NATIVE_FS_TIMEOUT_MS`,
|
|
3549
|
+
`AGIM_NATIVE_WEB_ALLOW_PRIVATE`, `AGIM_NATIVE_WEB_SSRF_WHITELIST`,
|
|
3550
|
+
`AGIM_NATIVE_WEB_TIMEOUT_MS`, `AGIM_EXEC_SANDBOX`,
|
|
3551
|
+
`AGIM_EXEC_SANDBOX_NET`, `AGIM_EXEC_TIMEOUT_MS`,
|
|
3552
|
+
`AGIM_EXEC_MAX_OUTPUT`, `AGIM_NATIVE_CALL_AGENT_MAX_PER_TURN`).
|
|
3540
3553
|
All editable + persistable via the existing `/api/env` PUT path.
|
|
3541
3554
|
- Settings sidebar: new "Security" tab between "Policy" and
|
|
3542
3555
|
"Workspaces". i18n keys `tabs.security` + `security.*` added to
|
|
@@ -3563,7 +3576,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3563
3576
|
- **Command-embedded SSRF scan** — `native_exec` now regex-extracts
|
|
3564
3577
|
every `http(s)://…` token in the command string and refuses if any
|
|
3565
3578
|
resolves through `checkUrlSafety` as private/internal. Honours
|
|
3566
|
-
the shared `
|
|
3579
|
+
the shared `AGIM_NATIVE_WEB_SSRF_WHITELIST`. Closes the
|
|
3567
3580
|
curl/wget-to-IMDS bypass.
|
|
3568
3581
|
- **SSRF redirect re-check** (`web-dispatcher.ts`) — `native_web_fetch`
|
|
3569
3582
|
no longer uses `redirect: 'follow'`. Now does `redirect: 'manual'`
|
|
@@ -3574,16 +3587,16 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3574
3587
|
- **100.64.0.0/10 carrier-grade NAT** added to default block list
|
|
3575
3588
|
(matches nanobot). Cloud providers + some ISPs use this for
|
|
3576
3589
|
internal hosts.
|
|
3577
|
-
- **CIDR whitelist** — new `
|
|
3590
|
+
- **CIDR whitelist** — new `AGIM_NATIVE_WEB_SSRF_WHITELIST=<csv>`
|
|
3578
3591
|
env (e.g. `100.64.0.0/10,10.20.0.0/16`) opens specific ranges for
|
|
3579
3592
|
legitimate Tailscale / VPN / internal-API use cases without
|
|
3580
|
-
binary-flipping `
|
|
3593
|
+
binary-flipping `AGIM_NATIVE_WEB_ALLOW_PRIVATE=1`. IPv4 only;
|
|
3581
3594
|
invalid entries dropped.
|
|
3582
3595
|
|
|
3583
3596
|
#### Sandbox
|
|
3584
3597
|
|
|
3585
|
-
- **bwrap tmpfs-mask** — when `
|
|
3586
|
-
now `--tmpfs $HOME/.agim` + `$HOME/.
|
|
3598
|
+
- **bwrap tmpfs-mask** — when `AGIM_EXEC_SANDBOX=bwrap`, the sandbox
|
|
3599
|
+
now `--tmpfs $HOME/.agim` + `$HOME/.agim` + the cwd's parent
|
|
3587
3600
|
directory, then bind-mounts the actual workspace back over the
|
|
3588
3601
|
masked parent. Even if the agent bypasses `sensitive-paths.ts` at
|
|
3589
3602
|
the tool-arg layer, an exec'd shell will see an empty
|
|
@@ -3595,8 +3608,8 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3595
3608
|
- **Sender allowlist** (new `core/sender-allowlist.ts`) — controls
|
|
3596
3609
|
WHO can talk to the bot (distinct from admin allowlist for
|
|
3597
3610
|
`/restart`).
|
|
3598
|
-
- `
|
|
3599
|
-
`
|
|
3611
|
+
- `AGIM_ALLOWED_USERS=platform:userId,…` — same syntax as
|
|
3612
|
+
`AGIM_ADMIN_USERS`. Set to `*` to explicitly mark "everyone
|
|
3600
3613
|
allowed" + suppress the boot warning.
|
|
3601
3614
|
- **Default is OPEN** when unset (no breaking change to existing
|
|
3602
3615
|
deployments). cli.ts emits a one-shot
|
|
@@ -3624,7 +3637,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3624
3637
|
### Changed
|
|
3625
3638
|
|
|
3626
3639
|
- **`long-goal` skill body** — replaced the stale "Future tools
|
|
3627
|
-
(deferred to v1.2.58)" section with the real `
|
|
3640
|
+
(deferred to v1.2.58)" section with the real `mcp__agim__long_task`
|
|
3628
3641
|
/ `complete_goal` usage instructions. Now matches v1.2.63 reality.
|
|
3629
3642
|
- **`agim-self` skill body** — added the 12 tools shipped in
|
|
3630
3643
|
v1.2.58–v1.2.63 that were missing: `long_task` / `complete_goal`
|
|
@@ -3644,7 +3657,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3644
3657
|
generator.
|
|
3645
3658
|
- **`agim-skill-discovery` skill** — teaches the agent how to answer
|
|
3646
3659
|
"what skills do I have / install X / search for Y" by referring to
|
|
3647
|
-
the system-prompt list, calling `
|
|
3660
|
+
the system-prompt list, calling `mcp__agim__read_skill` for
|
|
3648
3661
|
details, and pointing the operator at skillhub.cn + web admin's
|
|
3649
3662
|
Skills page. Documents the multi-root install layout +
|
|
3650
3663
|
restart-to-pick-up semantics.
|
|
@@ -3663,7 +3676,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3663
3676
|
- **`buildSkillsSummary` fallback** — if a skill somehow still ends
|
|
3664
3677
|
up with empty description after parsing, the summary line now
|
|
3665
3678
|
substitutes `(no description in SKILL.md — read body via
|
|
3666
|
-
|
|
3679
|
+
mcp__agim__read_skill)` instead of leaving the slot blank.
|
|
3667
3680
|
|
|
3668
3681
|
## [1.2.64] - 2026-05-26
|
|
3669
3682
|
|
|
@@ -3687,7 +3700,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3687
3700
|
|
|
3688
3701
|
### Added
|
|
3689
3702
|
|
|
3690
|
-
- **`
|
|
3703
|
+
- **`mcp__agim__long_task` / `mcp__agim__complete_goal` MCP tools** —
|
|
3691
3704
|
wraps `goals.ts` so every agim agent can self-register a sustained
|
|
3692
3705
|
multi-turn objective (previously only the `/goal set` slash command
|
|
3693
3706
|
let the user do this manually).
|
|
@@ -3699,7 +3712,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3699
3712
|
`completed` (default) or `cancelled`. `recap` becomes the final
|
|
3700
3713
|
progress note.
|
|
3701
3714
|
- **All agents** see these tools — registered in both
|
|
3702
|
-
`
|
|
3715
|
+
`agim-dispatcher.ts` (native side) and
|
|
3703
3716
|
`mcp-approval-server.ts` (claude-code / cursor / antigravity MCP
|
|
3704
3717
|
sidecar) with the new `goal` wire envelope handled by
|
|
3705
3718
|
`approval-bus.ts:handleGoal`. RunContext-resolved identity (no
|
|
@@ -3721,16 +3734,16 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3721
3734
|
|
|
3722
3735
|
- **`native_exec(command, timeout_ms?, cwd?)`** — shell execution
|
|
3723
3736
|
tool in `src/core/llm/exec-dispatcher.ts`. Default timeout 60s
|
|
3724
|
-
(hard cap 600s via `
|
|
3725
|
-
capped at 32KB (override via `
|
|
3737
|
+
(hard cap 600s via `AGIM_EXEC_TIMEOUT_MS`), per-stream output
|
|
3738
|
+
capped at 32KB (override via `AGIM_EXEC_MAX_OUTPUT`). Returns
|
|
3726
3739
|
JSON `{ exit_code, signal, timed_out, stdout, stderr,
|
|
3727
3740
|
stdout_truncated, stderr_truncated }`. SIGTERM at timeout with a
|
|
3728
3741
|
3s grace before SIGKILL.
|
|
3729
|
-
- **Optional bubblewrap sandbox** when `
|
|
3742
|
+
- **Optional bubblewrap sandbox** when `AGIM_EXEC_SANDBOX=bwrap`
|
|
3730
3743
|
(Linux + `/usr/bin/bwrap` required). Read-only binds the host's
|
|
3731
3744
|
`/usr`, `/lib`, `/lib64`, `/etc/ssl`, `/etc/resolv.conf`; rw-binds
|
|
3732
3745
|
the agent's cwd; tmpfs `/tmp`; isolated proc/dev. Net stays on by
|
|
3733
|
-
default; set `
|
|
3746
|
+
default; set `AGIM_EXEC_SANDBOX_NET=off` to add `--unshare-net`
|
|
3734
3747
|
for fully offline execution.
|
|
3735
3748
|
- `native_exec` is **NOT** in the default autoAllow — each invocation
|
|
3736
3749
|
routes through the v1.2.60 IM approval card. Same-fingerprint
|
|
@@ -3753,7 +3766,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3753
3766
|
protocols, RFC1918 (10/8, 172.16-31/12, 192.168/16), loopback
|
|
3754
3767
|
(127/8, ::1, localhost), link-local (169.254/16, fe80::/10), and
|
|
3755
3768
|
IPv6 ULA (fc00::/7). Operators who genuinely need private targets
|
|
3756
|
-
set `
|
|
3769
|
+
set `AGIM_NATIVE_WEB_ALLOW_PRIVATE=1`.
|
|
3757
3770
|
- Both tools added to native's default autoAllow — they're read-only
|
|
3758
3771
|
and the SSRF block stays in force regardless.
|
|
3759
3772
|
|
|
@@ -3781,7 +3794,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3781
3794
|
notifier (CI / smoke-test path), native silently falls back to the
|
|
3782
3795
|
legacy silent-deny so tests don't hang.
|
|
3783
3796
|
- **autoAllow lookup happens BEFORE mode resolution**, so adding a tool
|
|
3784
|
-
to `
|
|
3797
|
+
to `AGIM_NATIVE_AGENT_AUTOALLOW` always shortcuts the user-prompt
|
|
3785
3798
|
path regardless of mode.
|
|
3786
3799
|
|
|
3787
3800
|
## [1.2.59] - 2026-05-25
|
|
@@ -3789,14 +3802,14 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3789
3802
|
### Fixed
|
|
3790
3803
|
|
|
3791
3804
|
- **Native runaway delegation loop** — under deepseek-v4 the native agent
|
|
3792
|
-
would chain `
|
|
3805
|
+
would chain `mcp__agim__call_agent('claude-code', …)` repeatedly
|
|
3793
3806
|
inside a single turn (observed: 8 chained delegations across 11
|
|
3794
3807
|
minutes on one wechat thread before the user had to `/abort`). The
|
|
3795
3808
|
model picked call_agent over its own native fs tools even after
|
|
3796
3809
|
v1.2.58 added them. Three changes close it:
|
|
3797
|
-
- **Per-turn cap** in `
|
|
3810
|
+
- **Per-turn cap** in `agim-dispatcher.ts`: refuses further
|
|
3798
3811
|
`call_agent` after 2 delegations per turn (override with
|
|
3799
|
-
`
|
|
3812
|
+
`AGIM_NATIVE_CALL_AGENT_MAX_PER_TURN`, set 0 to disable). Refusal
|
|
3800
3813
|
message tells the model exactly which native tools to try instead,
|
|
3801
3814
|
so it self-corrects on the next iteration.
|
|
3802
3815
|
- **System-prompt HARD RULE** in `native/index.ts`: for read-file /
|
|
@@ -3818,7 +3831,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3818
3831
|
### Deferred
|
|
3819
3832
|
|
|
3820
3833
|
- `native_exec` (one-shot shell), `native_web_fetch`, `native_web_search`
|
|
3821
|
-
(duckduckgo → metaso fallback), `
|
|
3834
|
+
(duckduckgo → metaso fallback), `mcp__agim__long_task` /
|
|
3822
3835
|
`complete_goal`, and the bwrap sandbox path all move to v1.2.60.
|
|
3823
3836
|
Scope split: v1.2.59 is a focused hotfix for the user-visible
|
|
3824
3837
|
delegation loop; v1.2.60 returns to the bigger tool batch.
|
|
@@ -3839,20 +3852,20 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3839
3852
|
available; falls back to fs walk with a minimatch-style matcher
|
|
3840
3853
|
- `native_grep(pattern, path?, glob?, output_mode?, max_matches?,
|
|
3841
3854
|
case_insensitive?)` — ripgrep wrapper (rg required for now)
|
|
3842
|
-
- **Workspace restriction** — default-on via `
|
|
3855
|
+
- **Workspace restriction** — default-on via `AGIM_NATIVE_FS_RESTRICT`
|
|
3843
3856
|
(`'0'` disables). When on, every fs tool's path must resolve under
|
|
3844
3857
|
the per-thread native cwd subtree (typically
|
|
3845
3858
|
`~/.agim-workspaces/native/<thread>/`). Sensitive-path denylist
|
|
3846
3859
|
(`sensitive-paths.ts`) applies even when restriction is off.
|
|
3847
3860
|
- **Per-tool wall-clock** — every fs tool races against
|
|
3848
|
-
`
|
|
3861
|
+
`AGIM_NATIVE_FS_TIMEOUT_MS` (default 60_000). Prevents a slow
|
|
3849
3862
|
remote-mounted file from hanging the whole agent loop.
|
|
3850
3863
|
- **Default auto-allow** for the 4 read-only fs tools
|
|
3851
3864
|
(`native_read_file` / `native_list_dir` / `native_glob` /
|
|
3852
3865
|
`native_grep`) so native doesn't pop an IM card for every file
|
|
3853
3866
|
inspection. `native_write_file` stays approval-gated by default —
|
|
3854
3867
|
operators who trust native can add it via
|
|
3855
|
-
`
|
|
3868
|
+
`AGIM_NATIVE_AGENT_AUTOALLOW`.
|
|
3856
3869
|
|
|
3857
3870
|
### Deferred
|
|
3858
3871
|
|
|
@@ -3870,7 +3883,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3870
3883
|
packages — they teach the agent procedural knowledge and trigger
|
|
3871
3884
|
phrases without adding code. Available to every agim agent that
|
|
3872
3885
|
reads `agim skills available` (native injects into prompt; CLI
|
|
3873
|
-
agents load via `
|
|
3886
|
+
agents load via `mcp__agim__read_skill`):
|
|
3874
3887
|
- `weather` — wttr.in + Open-Meteo, no API key
|
|
3875
3888
|
- `summarize` — URL / article / YouTube / PDF summarisation flow
|
|
3876
3889
|
- `github` — `gh` CLI patterns (PR, issue, CI runs, gh api)
|
|
@@ -3881,7 +3894,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3881
3894
|
progress logging, and acceptance-criteria rules (adapted from
|
|
3882
3895
|
nanobot but mapped onto agim's existing goals.ts)
|
|
3883
3896
|
- `agim-reminders` — replaces nanobot's `cron`; teaches the
|
|
3884
|
-
`
|
|
3897
|
+
`mcp__agim__create_reminder` family with concrete examples
|
|
3885
3898
|
- `agim-memory` — replaces nanobot's `memory`; teaches the
|
|
3886
3899
|
`memory_*` + `*_memo` tools and the 5W1H taxonomy
|
|
3887
3900
|
|
|
@@ -3914,7 +3927,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3914
3927
|
v1.2.55 read the operator's real `~/.agim/env` on the dev/CI
|
|
3915
3928
|
host, breaking 7 tests that expected an empty allowlist after
|
|
3916
3929
|
`setEnv(undefined)`. Added a test opt-out: setting
|
|
3917
|
-
`
|
|
3930
|
+
`AGIM_ENV_FILE_PATH=''` disables the file read entirely (the
|
|
3918
3931
|
two admin test files now do this at module load).
|
|
3919
3932
|
|
|
3920
3933
|
## [1.2.55] - 2026-05-25
|
|
@@ -3927,7 +3940,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3927
3940
|
vanished from the web/IM admin list. Root cause: systemd's
|
|
3928
3941
|
`EnvironmentFile=` parser is stricter than agim's `readEnvFile` (it
|
|
3929
3942
|
silently drops lines containing certain characters), so the
|
|
3930
|
-
`
|
|
3943
|
+
`AGIM_ADMIN_USERS=…,…` line could land in `~/.agim/env` correctly
|
|
3931
3944
|
but be partially or fully ignored when systemd handed env to the new
|
|
3932
3945
|
process. `admin-allowlist.getEntries()` now ALSO reads
|
|
3933
3946
|
`~/.agim/env` directly with agim's own parser and merges entries
|
|
@@ -3946,10 +3959,10 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3946
3959
|
|
|
3947
3960
|
### Fixed
|
|
3948
3961
|
|
|
3949
|
-
- Web settings → Viewer: saving **「禁用社区默认」** (`
|
|
3962
|
+
- Web settings → Viewer: saving **「禁用社区默认」** (`AGIM_VIEWER_NO_DEFAULT_REMOTE`)
|
|
3950
3963
|
failed with「请求里的 key 均不可编辑」because the env whitelist omitted that
|
|
3951
3964
|
key. It is now editable via `PUT /api/env`.
|
|
3952
|
-
- Long-message viewer master switch (`
|
|
3965
|
+
- Long-message viewer master switch (`AGIM_VIEWER_ENABLED=0`) now hard-blocks
|
|
3953
3966
|
all viewer routing (truncate/link + remote paste + A2A artifact snapshots).
|
|
3954
3967
|
Previously only `decideRender` gated on enabled; A2A snapshots could still
|
|
3955
3968
|
upload when remote mode resolved.
|
|
@@ -3963,7 +3976,7 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
3963
3976
|
- `/models` under cursor returned "未能获取 cursor 的模型列表" on
|
|
3964
3977
|
systemd-launched agim because the spawned `cursor-agent` couldn't be
|
|
3965
3978
|
found on the stripped PATH. ModelDriver's listModels now uses the
|
|
3966
|
-
same bin-resolution as the cursor adapter (env `
|
|
3979
|
+
same bin-resolution as the cursor adapter (env `AGIM_CURSOR_BIN`
|
|
3967
3980
|
→ PATH → `~/.local/bin/cursor-agent` → `/usr/local/bin/...` →
|
|
3968
3981
|
`/opt/cursor/bin/...`), cached for the process lifetime.
|
|
3969
3982
|
- Tightened ANSI strip regex from `\[[0-9;]*m` (where the leading `\[`
|
|
@@ -4028,9 +4041,9 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
4028
4041
|
full `/cc cursor <prompt>` form).
|
|
4029
4042
|
- **Plan mode**: `/cs plan` or `--plan` flag yields cursor's plan mode
|
|
4030
4043
|
(read-only / clarifying questions). `--mode ask` similarly.
|
|
4031
|
-
- **MCP
|
|
4044
|
+
- **MCP agim bridge** — `~/.cursor/mcp.json` gets an `agim` entry on
|
|
4032
4045
|
first cursor turn, pointing at the same approval-bus sidecar
|
|
4033
|
-
claude-code uses. All `
|
|
4046
|
+
claude-code uses. All `mcp__agim__*` tool calls inside a cursor run
|
|
4034
4047
|
hop through agim's existing approval-bus + audit pipeline — no
|
|
4035
4048
|
bypass of agim policy.
|
|
4036
4049
|
- **Auth inheritance** — defaults to the machine's existing cursor
|
|
@@ -4050,11 +4063,11 @@ Nanobot-inspired defense-in-depth pass. 9 hardening items across
|
|
|
4050
4063
|
### Migration
|
|
4051
4064
|
|
|
4052
4065
|
- Existing cursor installs (with `cursor-agent login` already done) are
|
|
4053
|
-
picked up automatically. Set `
|
|
4066
|
+
picked up automatically. Set `AGIM_CURSOR_BIN=/path/to/cursor-agent`
|
|
4054
4067
|
to override binary resolution.
|
|
4055
4068
|
- `~/.cursor/mcp.json` is read-modify-written on first cursor turn;
|
|
4056
4069
|
pre-existing `mcpServers` entries are preserved.
|
|
4057
|
-
- The bin probe order is `
|
|
4070
|
+
- The bin probe order is `AGIM_CURSOR_BIN` env → PATH lookup →
|
|
4058
4071
|
`~/.local/bin/cursor-agent` → `/usr/local/bin/cursor-agent` →
|
|
4059
4072
|
`/opt/cursor/bin/cursor-agent`.
|
|
4060
4073
|
|
|
@@ -4076,19 +4089,19 @@ multi-hop research turn.
|
|
|
4076
4089
|
`[operator role definition]`. Edit the seed at
|
|
4077
4090
|
`~/.agim-workspaces/native/AGENTS.md` to change persona / tone /
|
|
4078
4091
|
house rules; no restart required. Env override
|
|
4079
|
-
`
|
|
4092
|
+
`AGIM_NATIVE_AGENT_ROLE_FILE=...` for non-default locations.
|
|
4080
4093
|
Prompt-injection guard runs over the content + audit-logs hits.
|
|
4081
|
-
- **Skills multi-root scan** — `
|
|
4094
|
+
- **Skills multi-root scan** — `AGIM_SKILLS_MODE=auto` (default)
|
|
4082
4095
|
merges `~/.agim/skills/` (write target) with `~/.claude/skills/`,
|
|
4083
4096
|
`~/.config/opencode/skills/`, and `~/.codex/skills/` so a fresh
|
|
4084
4097
|
install sees every skill the user already has from CLI agents.
|
|
4085
4098
|
Workspace skills shadow same-named entries from inherited roots.
|
|
4086
|
-
Modes: `auto | agim-only | custom` + `
|
|
4087
|
-
/ `
|
|
4099
|
+
Modes: `auto | agim-only | custom` + `AGIM_SKILLS_ROOTS=...`
|
|
4100
|
+
/ `AGIM_SKILLS_EXTRA_ROOTS=...`.
|
|
4088
4101
|
- **Auto-compact long histories** — when a native turn's accumulated
|
|
4089
|
-
history crosses `
|
|
4102
|
+
history crosses `AGIM_NATIVE_COMPACT_TRIGGER_CHARS` (default
|
|
4090
4103
|
60_000), a cheap LLM call summarises the older slice and the loop
|
|
4091
|
-
keeps only the last `
|
|
4104
|
+
keeps only the last `AGIM_NATIVE_COMPACT_KEEP_TURNS` (default 6)
|
|
4092
4105
|
user/assistant pairs verbatim. Tool round-trips kept intact (the
|
|
4093
4106
|
fix that landed in CR — never start the tail on `role:'tool'`).
|
|
4094
4107
|
- **Provider fallback chain** — native walks the configured role
|
|
@@ -4101,25 +4114,25 @@ multi-hop research turn.
|
|
|
4101
4114
|
content blocks when the provider's `vision: true` (or its model
|
|
4102
4115
|
name matches a known vision family). Anthropic provider remains
|
|
4103
4116
|
text-only for now. Hard cap 20MB per image. Path-safety:
|
|
4104
|
-
attachments must resolve under `
|
|
4117
|
+
attachments must resolve under `AGIM_MEDIA_ROOT`.
|
|
4105
4118
|
- **Tool-call heartbeat** — tool dispatches that take longer than
|
|
4106
|
-
`
|
|
4119
|
+
`AGIM_NATIVE_HEARTBEAT_MS` (default 6000) push a "🔧 调用工具 X
|
|
4107
4120
|
中…" so users know the bot is still working.
|
|
4108
4121
|
- **Turn-level heartbeat** — every
|
|
4109
|
-
`
|
|
4122
|
+
`AGIM_NATIVE_TURN_HEARTBEAT_MS` (default 180_000 = 3 min) since
|
|
4110
4123
|
turn start, push "⏳ 还在处理(已 Nm)…". Survives long
|
|
4111
4124
|
multi-hop research turns where individual tool calls finish but the
|
|
4112
4125
|
outer LLM is reasoning.
|
|
4113
4126
|
- **Cross-channel operator alert** — when outbox delivery fails ≥3
|
|
4114
4127
|
times on any thread, push a "⚠️ outbox 告警" to
|
|
4115
|
-
`
|
|
4128
|
+
`AGIM_OPERATOR_ALERT_PLATFORM` / `AGIM_OPERATOR_ALERT_THREAD_ID`
|
|
4116
4129
|
(throttled per dead-thread, 10-min cooldown). Self-loop protection.
|
|
4117
4130
|
- **agim built-in MCP tools default-allowed** — the 9
|
|
4118
|
-
`
|
|
4131
|
+
`mcp__agim__*` tools (read_skill / list_skills / save_memo /
|
|
4119
4132
|
search_memos / update_memo / delete_memo / push_message /
|
|
4120
4133
|
ask_user / call_agent) are now in native's default allow-list,
|
|
4121
4134
|
matching what claude-code already saw via the MCP sidecar. Override
|
|
4122
|
-
via `
|
|
4135
|
+
via `AGIM_NATIVE_AGENT_DENYLIST=...`.
|
|
4123
4136
|
- **Per-agent native workspace** — `resolveAgentCwd('native', opts)`
|
|
4124
4137
|
pins IM turns to `~/.agim-workspaces/native/` (was `/` under
|
|
4125
4138
|
systemd). AGENTS.md seeded with role-definition cues.
|
|
@@ -4138,7 +4151,7 @@ multi-hop research turn.
|
|
|
4138
4151
|
— native now passes `timeoutMs: 28 * 60 * 1000` to `runAgentLoop`,
|
|
4139
4152
|
matching the IM 30-min hard ceiling. Multi-hop `call_agent` chains
|
|
4140
4153
|
used to abort mid-flight on the 6th minute. Override via
|
|
4141
|
-
`
|
|
4154
|
+
`AGIM_NATIVE_AGENT_TIMEOUT_MS`.
|
|
4142
4155
|
- **wechat-ilink dead-session auto-recovery** — `sendMessage` returning
|
|
4143
4156
|
`-2` (`INVALID_PARAMS`) now invalidates the cached + persisted
|
|
4144
4157
|
context-token for that user, so the next inbound message refreshes
|
|
@@ -4165,12 +4178,12 @@ multi-hop research turn.
|
|
|
4165
4178
|
- Operators who customised `~/.agim-workspaces/native/AGENTS.md` keep
|
|
4166
4179
|
their file unchanged (`ensureAgentWorkspace` never overwrites).
|
|
4167
4180
|
- Default skill mode is `auto` — agim now reads `~/.claude/skills/`
|
|
4168
|
-
etc. Set `
|
|
4169
|
-
- The 9 `
|
|
4170
|
-
default policy. Set `
|
|
4181
|
+
etc. Set `AGIM_SKILLS_MODE=agim-only` to opt out of inheritance.
|
|
4182
|
+
- The 9 `mcp__agim__*` tools are auto-allowed under native's
|
|
4183
|
+
default policy. Set `AGIM_NATIVE_AGENT_DENYLIST=mcp__agim__call_agent,...`
|
|
4171
4184
|
to block individual ones.
|
|
4172
4185
|
- Auto-compact will make one cheap-role LLM call per compaction.
|
|
4173
|
-
Disable with `
|
|
4186
|
+
Disable with `AGIM_NATIVE_COMPACT_TRIGGER_CHARS=0`.
|
|
4174
4187
|
|
|
4175
4188
|
## [1.3.0] - 2026-05-23
|
|
4176
4189
|
|
|
@@ -4233,20 +4246,20 @@ for the architectural stance + anti-patterns.
|
|
|
4233
4246
|
- **agim Skills engine (Stage 3 + P0 #3)** — discover `SKILL.md`
|
|
4234
4247
|
files in `~/.agim/skills/` + bundled `<dist>/skills/builtin/`; 3-tier
|
|
4235
4248
|
progressive disclosure (name+desc auto-injected; body via
|
|
4236
|
-
`
|
|
4249
|
+
`mcp__agim__read_skill`; scripts/refs via normal file read);
|
|
4237
4250
|
`/skill list|show|refresh` + `/settings/agim-skills` web editor. See
|
|
4238
4251
|
[`docs/skills.md`](docs/skills.md). PR #68 + #76.
|
|
4239
4252
|
- **Inline row-age annotations on memory facts (P0 #4)** — every fact
|
|
4240
4253
|
/ persona row gets a `(2d ago)` style annotation in the injected
|
|
4241
4254
|
context so the agent has temporal context for free. `format-age.ts`
|
|
4242
4255
|
utility + `persona-age.test.ts`. PR #69.
|
|
4243
|
-
- **`
|
|
4256
|
+
- **`mcp__agim__ask_user` structured choice (P0 #5)** — agent presents
|
|
4244
4257
|
N choices (2-9) with optional timeout; user replies via button or
|
|
4245
4258
|
text; result returns deterministically as a typed choice index +
|
|
4246
4259
|
free-text. `/tasks/asks` pending-queue admin. See
|
|
4247
4260
|
[`docs/ask-user.md`](docs/ask-user.md). PR #67.
|
|
4248
4261
|
- **Notification evaluator for agent-initiated push (P0 #9)** —
|
|
4249
|
-
`
|
|
4262
|
+
`mcp__agim__push_message` and `POST /api/notify` go through an
|
|
4250
4263
|
LLM-graded "should we deliver this?" filter before hitting the IM
|
|
4251
4264
|
thread. Per-thread rate limit; verdict logged to audit. PR #60.
|
|
4252
4265
|
|
|
@@ -4375,12 +4388,12 @@ for the architectural stance + anti-patterns.
|
|
|
4375
4388
|
|
|
4376
4389
|
### R15 — new
|
|
4377
4390
|
|
|
4378
|
-
- **CLI 向导 "Web 后台 — 监听地址 + 端口" 段** — bind (`
|
|
4391
|
+
- **CLI 向导 "Web 后台 — 监听地址 + 端口" 段** — bind (`AGIM_WEB_BIND`
|
|
4379
4392
|
写到 `~/.agim/env`) + port (`webPort` 写到 `config.json`). 选
|
|
4380
4393
|
`0.0.0.0` 强制 yesNo 二次确认 "你前面有 TLS 反代吗"; port `< 1024`
|
|
4381
4394
|
拒绝。PR #56.
|
|
4382
4395
|
- **ACP port gate 闭合** — `GET /api/config` 现透传 `acpPort` 但只在
|
|
4383
|
-
`
|
|
4396
|
+
`AGIM_ENABLE_REMOTE_AGENT=1` 时; `PUT /api/config` 在 gate 关时丢
|
|
4384
4397
|
incoming.acpPort; Web `/settings/service` Ports 卡的 ACP 输入框
|
|
4385
4398
|
按 `features.remoteAgent` gate (之前一直显示). PR #56.
|
|
4386
4399
|
|
|
@@ -4469,21 +4482,21 @@ for the architectural stance + anti-patterns.
|
|
|
4469
4482
|
`memory_list` 输出对 5W1H 走 `sanitizeForInjection`;
|
|
4470
4483
|
`ensureAgentWorkspace` 启动期扫 AGENTS.md/CLAUDE.md, 11 英文 + 4
|
|
4471
4484
|
中文 prompt-injection 模式命中 → warn + audit. PR #48.
|
|
4472
|
-
- **G4 `
|
|
4485
|
+
- **G4 `AGIM_ACP_BIND` env + non-loopback audit** — ACP 服务监听
|
|
4473
4486
|
地址可配; 改非回环时启动 warn + 持久 audit-event. PR #48.
|
|
4474
|
-
- **G5 advisories** — `
|
|
4475
|
-
小时 reminder; 按 IP WS 限流 (`
|
|
4476
|
-
`
|
|
4477
|
-
warn + audit; 非回环 Web bind 未设 `
|
|
4487
|
+
- **G5 advisories** — `AGIM_TIMEOUT_DEFAULT=allow` 启动横幅 + 每
|
|
4488
|
+
小时 reminder; 按 IP WS 限流 (`AGIM_WS_MAX_PER_IP=20` +
|
|
4489
|
+
`AGIM_WS_MAX_NEW_PER_IP_PER_MIN=30`); `?token=` URL 回退首次使用
|
|
4490
|
+
warn + audit; 非回环 Web bind 未设 `AGIM_WEB_TLS_ACK` 启动横幅.
|
|
4478
4491
|
PR #48.
|
|
4479
4492
|
|
|
4480
4493
|
### R12 — 6 enterprise privacy hardening items + visibility gates
|
|
4481
4494
|
|
|
4482
4495
|
- **① 用户消息日志脱敏** — `sanitizeUserText()` 默认
|
|
4483
|
-
`{len, prefix(6), sha256(12)}`, `
|
|
4496
|
+
`{len, prefix(6), sha256(12)}`, `AGIM_LOG_USER_TEXT=1` 显式启用
|
|
4484
4497
|
原文 (120 字符 cap). PR #48.
|
|
4485
|
-
- **② Memory / Persona / Paste TTL** — `
|
|
4486
|
-
DAYS=90`/`
|
|
4498
|
+
- **② Memory / Persona / Paste TTL** — `AGIM_MEMORY_FACT_RETENTION_
|
|
4499
|
+
DAYS=90`/`AGIM_PERSONA_RETENTION_DAYS=180`/`AGIM_PASTE_RETENTION_
|
|
4487
4500
|
DAYS=30`. facts 按 last_referenced_at (LRU 友好), 0 = 永久. PR #48.
|
|
4488
4501
|
- **③ `agim uninstall` 三模式** — 保留 / 清凭据保留历史 / 完全销毁
|
|
4489
4502
|
(typed "DELETE" + shred + rm -rf). PR #48.
|
|
@@ -4492,10 +4505,10 @@ for the architectural stance + anti-patterns.
|
|
|
4492
4505
|
- **⑤ `audit_events` 持久审计表** — 10 类事件 (approval / admin /
|
|
4493
4506
|
config / env / token / workspace) 持久 180 天, details JSON 只放
|
|
4494
4507
|
字段名 / 长度 / 哈希前缀. `GET /api/audit/events` 暴露. PR #48.
|
|
4495
|
-
- **⑥ `
|
|
4508
|
+
- **⑥ `AGIM_SKILLHUB_ENABLED` 出网开关** — `=0` 关 skillhub
|
|
4496
4509
|
对外 fetch (气隙部署). PR #48.
|
|
4497
|
-
- **Compliance visibility gates** — `
|
|
4498
|
-
Discord+Telegram, `
|
|
4510
|
+
- **Compliance visibility gates** — `AGIM_ENABLE_GLOBAL_IM` 控
|
|
4511
|
+
Discord+Telegram, `AGIM_ENABLE_REMOTE_AGENT` 控 ACP. 默认全关,
|
|
4499
4512
|
三层都 gate (CLI 向导 / Web 设置 / 运行时). PR #48.
|
|
4500
4513
|
|
|
4501
4514
|
### Build
|
|
@@ -4511,12 +4524,12 @@ for the architectural stance + anti-patterns.
|
|
|
4511
4524
|
- **Fresh install white-screens on the web console.** `index.html`
|
|
4512
4525
|
shipped in `dist/web/public/` is the v2 SPA shell since M1 / R10,
|
|
4513
4526
|
but the static-asset router that serves `/assets/<chunk>.js` was
|
|
4514
|
-
gated behind `
|
|
4527
|
+
gated behind `AGIM_WEB_V2=1`. New installs without that env var
|
|
4515
4528
|
set received the SPA HTML (which references `/assets/index-…js`)
|
|
4516
4529
|
but every chunk request fell through to the catch-all 404 — the
|
|
4517
4530
|
browser parsed the shell, failed every module import, and stuck
|
|
4518
4531
|
on a white screen with no obvious error short of devtools.
|
|
4519
|
-
- Default flipped to ON. Set `
|
|
4532
|
+
- Default flipped to ON. Set `AGIM_WEB_V2=0` to drop back to the
|
|
4520
4533
|
legacy v1 page handler (still serves the older
|
|
4521
4534
|
`tasks.html` / `reminders.html` / `memos.html` / `settings.html`
|
|
4522
4535
|
for any operator who customised those files; new operators get
|
|
@@ -4540,7 +4553,7 @@ parallel; this release bumps to 1.2.22 to stay above it.)
|
|
|
4540
4553
|
succeeded if given more time.
|
|
4541
4554
|
- The prompt POST now uses an undici Agent with `bodyTimeout: 0` and
|
|
4542
4555
|
`headersTimeout: 0`. Liveness is still bounded by the SSE-side idle
|
|
4543
|
-
watchdog (`OPENCODE_IDLE_TIMEOUT_MS` / `
|
|
4556
|
+
watchdog (`OPENCODE_IDLE_TIMEOUT_MS` / `AGIM_AGENT_IDLE_TIMEOUT_MS`),
|
|
4544
4557
|
so an actually-hung opencode is still reported — we just stop
|
|
4545
4558
|
killing healthy long-running responses.
|
|
4546
4559
|
- The `opencode.http.prompt_failed` log now captures `error.cause`
|
|
@@ -4571,18 +4584,18 @@ parallel; this release bumps to 1.2.22 to stay above it.)
|
|
|
4571
4584
|
|
|
4572
4585
|
- **opencode MCP sidecar silently exits when probe-reuse picks up a stale
|
|
4573
4586
|
serve.** `approval-bus` picks a fresh random socket path on every agim
|
|
4574
|
-
start (`/tmp/
|
|
4587
|
+
start (`/tmp/agim-approval-<32hex>.sock`); any pre-existing
|
|
4575
4588
|
`opencode serve` left over from a previous agim run carries the old
|
|
4576
4589
|
path in its environ snapshot. `OpencodeServeManager` previously reused
|
|
4577
4590
|
the listener unconditionally, so every new MCP sidecar that the
|
|
4578
4591
|
serve forked tried to connect to a deleted socket and exited at
|
|
4579
|
-
startup — `
|
|
4592
|
+
startup — `mcp__agim__save_memo`, `mcp__agim__create_reminder`,
|
|
4580
4593
|
and friends silently dropped out of opencode's tool set.
|
|
4581
4594
|
- The probe-reuse path now reads `/proc/<listener-pid>/environ`, compares
|
|
4582
|
-
`
|
|
4595
|
+
`AGIM_APPROVAL_SOCK` against the live bus path, and SIGTERMs +
|
|
4583
4596
|
respawns when they mismatch (escalates to SIGKILL after 800 ms).
|
|
4584
4597
|
- Spawn path makes the env injection explicit and warns loudly if
|
|
4585
|
-
`
|
|
4598
|
+
`AGIM_APPROVAL_SOCK` is unset at the moment we launch the serve.
|
|
4586
4599
|
|
|
4587
4600
|
(`1.2.3` through `1.2.17` were auto-bumped by the merge-bot but never
|
|
4588
4601
|
manually published; this is the first npm publish since `1.2.2`.)
|
|
@@ -4678,7 +4691,7 @@ and a handful of P0 / P1 hardening fixes uncovered in pre-release CR.
|
|
|
4678
4691
|
|
|
4679
4692
|
Persistent per-user fact store + auto-distilled "persona" summary that gets
|
|
4680
4693
|
injected into every agent prompt. Default OFF; opt in via Settings →
|
|
4681
|
-
**自动化记忆** toggle (or `
|
|
4694
|
+
**自动化记忆** toggle (or `AGIM_MEMORY_ENABLED=1`).
|
|
4682
4695
|
|
|
4683
4696
|
- **Storage**: `~/.agim/memory.db` (SQLite). FTS5 index for keyword recall.
|
|
4684
4697
|
Per-user partition key `${platform}:${userId}` so the same human across
|
|
@@ -4689,7 +4702,7 @@ injected into every agent prompt. Default OFF; opt in via Settings →
|
|
|
4689
4702
|
- **Daily consolidation cron**: rebuilds the persona summary from the
|
|
4690
4703
|
newest 50 facts so the always-on snippet stays small (~150–300 tokens).
|
|
4691
4704
|
- **4 MCP tools** so agents can introspect / extend memory:
|
|
4692
|
-
`
|
|
4705
|
+
`mcp__agim__memory_query`, `_save`, `_list`, `_delete`.
|
|
4693
4706
|
- **Web admin tab** (`/tasks#memory`): per-user user selector → persona
|
|
4694
4707
|
text editor + paginated facts table with FTS5 search + bulk-delete
|
|
4695
4708
|
filters + JSON export.
|
|
@@ -4712,14 +4725,14 @@ ranked list. Backfill button generates embeddings for existing facts.
|
|
|
4712
4725
|
Clear button wipes the index when switching backends (different model =
|
|
4713
4726
|
incompatible vector space).
|
|
4714
4727
|
|
|
4715
|
-
### Added — Agent-initiated push (`
|
|
4728
|
+
### Added — Agent-initiated push (`mcp__agim__push_message`)
|
|
4716
4729
|
|
|
4717
4730
|
Lets a running agent push a follow-up message back into the IM thread
|
|
4718
4731
|
without an inbound trigger. Useful for long-running jobs ("CI green") or
|
|
4719
4732
|
schedule-aware notifications.
|
|
4720
4733
|
|
|
4721
|
-
- Per-user rate limit (`
|
|
4722
|
-
- Cross-thread push gated by `
|
|
4734
|
+
- Per-user rate limit (`AGIM_PUSH_RATE_PER_HOUR`, default 20).
|
|
4735
|
+
- Cross-thread push gated by `AGIM_PUSH_CROSS_THREAD` (default off:
|
|
4723
4736
|
push must target the same thread the run started in).
|
|
4724
4737
|
- `POST /api/notify` HTTP endpoint exposes the same primitive for
|
|
4725
4738
|
webhooks / cron / external tools.
|
|
@@ -4754,7 +4767,7 @@ WeChat-iLink / DingTalk where buttons aren't a primitive.
|
|
|
4754
4767
|
|
|
4755
4768
|
### Changed — Web auth / env editor
|
|
4756
4769
|
|
|
4757
|
-
- `
|
|
4770
|
+
- `AGIM_MEMORY_VECTOR_OPENAI_API_KEY` joins the SECRET_KEYS allowlist:
|
|
4758
4771
|
masked on GET, click-to-reveal for editing, masked-value writes are
|
|
4759
4772
|
no-ops (defense in depth so a stale masked echo can't overwrite).
|
|
4760
4773
|
- `PUT /api/env` rejects masked echoes for any secret key (was only
|
|
@@ -4802,7 +4815,7 @@ WeChat-iLink / DingTalk where buttons aren't a primitive.
|
|
|
4802
4815
|
|
|
4803
4816
|
### Changed — Telemetry / data
|
|
4804
4817
|
|
|
4805
|
-
- `
|
|
4818
|
+
- `AGIM_MEMORY_*` env keys editable via `PUT /api/env`.
|
|
4806
4819
|
- `~/.agim/memory.db` is new; safe to delete — recreated on next save.
|
|
4807
4820
|
- Vector cache: `~/.agim/cache/transformers` (BGE ONNX model files).
|
|
4808
4821
|
- `audit-log` adds `intent='memory.distill'` rows so distillation cost
|
|
@@ -4850,7 +4863,7 @@ adds token-gated login.
|
|
|
4850
4863
|
SHA-256; raw token is shown once at create time.
|
|
4851
4864
|
- **Cookie**: 30-day `agim_token` cookie set on successful login;
|
|
4852
4865
|
`SameSite=Strict`, `Path=/`. Logout via `POST /api/auth/logout`.
|
|
4853
|
-
- **Disable**: `
|
|
4866
|
+
- **Disable**: `AGIM_WEB_AUTH=off` reverts to pre-1.1.10 open access
|
|
4854
4867
|
(for ops who do auth at the reverse proxy layer).
|
|
4855
4868
|
- **Global fetch interceptor** in `_app.js` auto-attaches `Authorization`
|
|
4856
4869
|
+ redirects to `/login` on 401. Existing pages keep working without
|
|
@@ -4860,10 +4873,10 @@ adds token-gated login.
|
|
|
4860
4873
|
|
|
4861
4874
|
The HSTECH / Lens debate sessions surfaced two pain points:
|
|
4862
4875
|
|
|
4863
|
-
- **Default timeout raised from 10 min → 30 min** (`
|
|
4876
|
+
- **Default timeout raised from 10 min → 30 min** (`AGIM_A2A_TIMEOUT_DEFAULT_MS`).
|
|
4864
4877
|
Codex routinely takes 15-25 min for a 4-API-pull + writing-a-report job;
|
|
4865
4878
|
the old 10 min cutoff killed it mid-flight and left orphan files in
|
|
4866
|
-
`_agim-output/`. New `
|
|
4879
|
+
`_agim-output/`. New `AGIM_A2A_MAX_TIMEOUT_MS` (default 1h) caps the
|
|
4867
4880
|
ceiling so an agent can't accidentally write `timeoutMs: 86400000`.
|
|
4868
4881
|
- **Abort on timeout** — `AgentSendOpts.signal` plumbed through `sendPrompt`
|
|
4869
4882
|
→ `spawnStream` so callees actually get SIGTERM'd when A2A gives up.
|
|
@@ -4876,7 +4889,7 @@ The HSTECH / Lens debate sessions surfaced two pain points:
|
|
|
4876
4889
|
- `⌛ codex 超时 (10m 未返回) — 子进程已停` — timeout
|
|
4877
4890
|
- `❌ codex 失败 ... <err>` — failure
|
|
4878
4891
|
- **Verbose heartbeat mode** detects file changes in `_agim-output/`
|
|
4879
|
-
every `
|
|
4892
|
+
every `AGIM_A2A_HEARTBEAT_MIN` minutes (default 5):
|
|
4880
4893
|
- With change: lists new files + links the first new `.md` once.
|
|
4881
4894
|
- Without change: "still thinking" note.
|
|
4882
4895
|
- **Notify scope**: source='system' (never routes through viewer);
|
|
@@ -4904,7 +4917,7 @@ The HSTECH / Lens debate sessions surfaced two pain points:
|
|
|
4904
4917
|
web port publicly. First start auto-creates a bootstrap token — copy
|
|
4905
4918
|
the value from `journalctl -u agim` or `agim status` output.
|
|
4906
4919
|
- Existing users on a reverse proxy with their own auth: set
|
|
4907
|
-
`
|
|
4920
|
+
`AGIM_WEB_AUTH=off` if you don't want a second factor.
|
|
4908
4921
|
- Local-only / loopback users: nothing changes (auth bypassed on
|
|
4909
4922
|
127.0.0.1).
|
|
4910
4923
|
|
|
@@ -4942,12 +4955,12 @@ otherwise expose their agim host, the viewer can now auto-launch a
|
|
|
4942
4955
|
cloudflared "quick tunnel" so /v/:id links in IM are reachable from
|
|
4943
4956
|
a phone with zero infrastructure setup.
|
|
4944
4957
|
|
|
4945
|
-
- **New env var `
|
|
4958
|
+
- **New env var `AGIM_VIEWER_TUNNEL_MODE`** — `off` (default) or
|
|
4946
4959
|
`quick`. When `quick`, agim startup forks `cloudflared tunnel --url`
|
|
4947
4960
|
pointing at the local web port and captures the assigned
|
|
4948
4961
|
`https://*.trycloudflare.com` URL from its log output. The URL
|
|
4949
4962
|
becomes the effective base for link building.
|
|
4950
|
-
- **Precedence**: `
|
|
4963
|
+
- **Precedence**: `AGIM_VIEWER_PUBLIC_BASE_URL` always wins when set.
|
|
4951
4964
|
Tunnel is only used as a fallback. So operators can keep their
|
|
4952
4965
|
static reverse proxy and only switch to tunnel during travel /
|
|
4953
4966
|
testing without changing anything else.
|
|
@@ -4976,7 +4989,7 @@ Quick-tunnel URLs are ephemeral — they change every time cloudflared
|
|
|
4976
4989
|
process (re)starts. Old `/v/:id` links in IM thus become dead after a
|
|
4977
4990
|
restart. Operators who want permanent links should configure a static
|
|
4978
4991
|
reverse proxy (cloudflared named tunnel, caddy, tailscale funnel,
|
|
4979
|
-
nginx, …) and set `
|
|
4992
|
+
nginx, …) and set `AGIM_VIEWER_PUBLIC_BASE_URL` instead. The
|
|
4980
4993
|
auto-tunnel mode is intentionally a "zero-config fallback", not a
|
|
4981
4994
|
recommended permanent deployment.
|
|
4982
4995
|
|
|
@@ -5027,7 +5040,7 @@ chmod +x ~/.agim/bin/cloudflared
|
|
|
5027
5040
|
- **`GET /api/viewer{,/:id}`** + **`DELETE /api/viewer/:id`** —
|
|
5028
5041
|
list / read / delete pastes from the dashboard or via curl.
|
|
5029
5042
|
- **Permanent storage by default.** No TTL; rows are kept until
|
|
5030
|
-
`
|
|
5043
|
+
`AGIM_VIEWER_MAX_PASTES` (default 10 000) is exceeded, at which
|
|
5031
5044
|
point oldest rows are LRU-pruned.
|
|
5032
5045
|
- **Two-section envelope for agents.** Router prepends a small
|
|
5033
5046
|
`[IM-render hint]` block to every prompt when the viewer is
|
|
@@ -5045,18 +5058,18 @@ chmod +x ~/.agim/bin/cloudflared
|
|
|
5045
5058
|
|
|
5046
5059
|
| Env var | Default | Notes |
|
|
5047
5060
|
|---|---|---|
|
|
5048
|
-
| `
|
|
5049
|
-
| `
|
|
5050
|
-
| `
|
|
5051
|
-
| `
|
|
5052
|
-
| `
|
|
5053
|
-
| `
|
|
5061
|
+
| `AGIM_VIEWER_ENABLED` | `false` | Master switch. |
|
|
5062
|
+
| `AGIM_VIEWER_PUBLIC_BASE_URL` | _(empty)_ | Your public URL pointing at this agim host, e.g. `https://agim.example.com`. Used to build the link placed in IM. |
|
|
5063
|
+
| `AGIM_VIEWER_CHARS` | `500` | Char-count threshold above which routing to web kicks in. |
|
|
5064
|
+
| `AGIM_VIEWER_LINES` | `12` | Line-count threshold. |
|
|
5065
|
+
| `AGIM_VIEWER_CODE_LINES` | `10` | Single-fence code-block line threshold. |
|
|
5066
|
+
| `AGIM_VIEWER_MAX_PASTES` | `10000` | Local SQLite row cap (LRU prune). |
|
|
5054
5067
|
|
|
5055
5068
|
### Notes
|
|
5056
5069
|
|
|
5057
5070
|
- Reverse-proxy your agim web port (default 3000) to a public
|
|
5058
5071
|
hostname via cloudflared / caddy / tailscale-funnel etc. Set
|
|
5059
|
-
`
|
|
5072
|
+
`AGIM_VIEWER_PUBLIC_BASE_URL` to that hostname.
|
|
5060
5073
|
- Privacy posture: content is stored locally on your host only.
|
|
5061
5074
|
The link uses an unguessable uuidv4 — treat it like a private
|
|
5062
5075
|
share link.
|
|
@@ -5146,7 +5159,7 @@ chmod +x ~/.agim/bin/cloudflared
|
|
|
5146
5159
|
|
|
5147
5160
|
### Added — Agent-to-Agent Layer 2 (shared artifacts)
|
|
5148
5161
|
|
|
5149
|
-
- **File exchange between agents.** `
|
|
5162
|
+
- **File exchange between agents.** `mcp__agim__call_agent` now accepts
|
|
5150
5163
|
optional `inputs[]` and `expectOutputs[]` so caller and callee can
|
|
5151
5164
|
hand off files instead of round-tripping bytes through prompts /
|
|
5152
5165
|
results.
|
|
@@ -5166,9 +5179,9 @@ chmod +x ~/.agim/bin/cloudflared
|
|
|
5166
5179
|
`fromCallerOutput` use `link(2)` when source and destination share a
|
|
5167
5180
|
filesystem — near-zero cost for read-only inputs. Falls back to plain
|
|
5168
5181
|
copy on EXDEV.
|
|
5169
|
-
- **Size caps**: `
|
|
5170
|
-
`
|
|
5171
|
-
`
|
|
5182
|
+
- **Size caps**: `AGIM_A2A_ARTIFACT_MAX_BYTES_PER_FILE` (default 50 MB),
|
|
5183
|
+
`AGIM_A2A_ARTIFACT_MAX_BYTES_PER_JOB` (200 MB),
|
|
5184
|
+
`AGIM_A2A_ARTIFACT_MAX_FILES_PER_JOB` (200). Failed setup fails the
|
|
5172
5185
|
job before any tokens are spent.
|
|
5173
5186
|
- **Retention follows the inline-job row.** When job-board's sweep
|
|
5174
5187
|
deletes a row, `pruneArtifactsBatch` removes its directory. Fire-and-
|
|
@@ -5178,7 +5191,7 @@ chmod +x ~/.agim/bin/cloudflared
|
|
|
5178
5191
|
|
|
5179
5192
|
### Changed
|
|
5180
5193
|
|
|
5181
|
-
- `
|
|
5194
|
+
- `mcp__agim__call_agent` description grew a paragraph documenting the
|
|
5182
5195
|
L2 fields; existing L1 callers (no `inputs` / `expectOutputs`) keep
|
|
5183
5196
|
the L1 string-in / string-out behavior unchanged.
|
|
5184
5197
|
|
|
@@ -5204,7 +5217,7 @@ chmod +x ~/.agim/bin/cloudflared
|
|
|
5204
5217
|
- `/outbox failed` rows in `giving_up`.
|
|
5205
5218
|
- `/outbox retry <id>` resurrect a `giving_up` row.
|
|
5206
5219
|
- Retention: 24h after `delivered` / `giving_up`. Override with
|
|
5207
|
-
`
|
|
5220
|
+
`AGIM_OUTBOX_RETENTION_HOURS`.
|
|
5208
5221
|
- **Inline-job tracking.** Every inbound agent-bound message now creates
|
|
5209
5222
|
a row in `jobs.db` with `kind='inline'`, going through the full
|
|
5210
5223
|
lifecycle `pending → running → completed → delivered` (or `failed`).
|
|
@@ -5212,8 +5225,8 @@ chmod +x ~/.agim/bin/cloudflared
|
|
|
5212
5225
|
recovery and A2A both rely on.
|
|
5213
5226
|
- Visible in `/job list` and per-row in `/job check <id>`.
|
|
5214
5227
|
- Retention: 24h (vs 30d for `kind='job'` rows from explicit `/job
|
|
5215
|
-
create`). Override with `
|
|
5216
|
-
- Kill switch: `
|
|
5228
|
+
create`). Override with `AGIM_INLINE_JOB_RETENTION_HOURS`.
|
|
5229
|
+
- Kill switch: `AGIM_INLINE_JOB_TRACKING=0` disables creation; the
|
|
5217
5230
|
user reply path falls back to the unchanged in-memory pipeline.
|
|
5218
5231
|
- **Crash-recovery flow.** When agim exits (SIGTERM/SIGINT/crash), any
|
|
5219
5232
|
in-flight inline job is stamped `interrupted`. On startup, jobs
|
|
@@ -5224,24 +5237,24 @@ chmod +x ~/.agim/bin/cloudflared
|
|
|
5224
5237
|
stamped `replaced_by=<new id>`.
|
|
5225
5238
|
- Reply `2` → old row marked `cancelled`.
|
|
5226
5239
|
- No reply → old row swept to `abandoned` by the next startup.
|
|
5227
|
-
- Window override: `
|
|
5240
|
+
- Window override: `AGIM_RECOVERY_WINDOW_MS` (default 600000).
|
|
5228
5241
|
|
|
5229
5242
|
### Added — Agent-to-Agent (A2A) Layer 1
|
|
5230
5243
|
|
|
5231
|
-
- **`
|
|
5244
|
+
- **`mcp__agim__call_agent` MCP tool.** A running agent (claude-code /
|
|
5232
5245
|
opencode / codex / copilot) can now program-call another agent and
|
|
5233
5246
|
wait for the result inside its own tool loop. The tool description
|
|
5234
5247
|
uses imperative + Chinese trigger phrases so models invoke it
|
|
5235
5248
|
naturally when the user says e.g. "用 codex 帮我跑 git status" or
|
|
5236
5249
|
"ask opencode to run the tests".
|
|
5237
5250
|
- **Guardrails enforced inside agim, not on the model**:
|
|
5238
|
-
- `
|
|
5251
|
+
- `AGIM_A2A_MAX_DEPTH` (default 3) — caps nested call chains.
|
|
5239
5252
|
- Self-call ban — `claude-code` can't recursively call `claude-code`.
|
|
5240
5253
|
- Workspace whitelist — callee must be in the caller's workspace
|
|
5241
5254
|
`agents[]`. Caller's `userId` carries through.
|
|
5242
|
-
- `
|
|
5255
|
+
- `AGIM_A2A_TIMEOUT_DEFAULT_MS` (default 600_000) — accumulation
|
|
5243
5256
|
timeout. Callee keeps running on timeout; caller stops waiting.
|
|
5244
|
-
- Kill switch: `
|
|
5257
|
+
- Kill switch: `AGIM_A2A_ENABLED=0` disables the whole feature.
|
|
5245
5258
|
- **`/a2a stats | recent [N] | tree <id>`** — observability for A2A
|
|
5246
5259
|
traffic. Each callee row is linked to its caller via `parent_id`
|
|
5247
5260
|
+ `call_depth`, so `/a2a tree <root>` renders the full chain.
|
|
@@ -5295,7 +5308,7 @@ chmod +x ~/.agim/bin/cloudflared
|
|
|
5295
5308
|
|
|
5296
5309
|
- **Approval timeout default 30 min → 15 min.** Long enough for slow IM
|
|
5297
5310
|
channels to round-trip a y/n; short enough to unblock downstream tools.
|
|
5298
|
-
Override with `
|
|
5311
|
+
Override with `AGIM_APPROVAL_TIMEOUT_MS`.
|
|
5299
5312
|
- **Agent child-process budget switched from 30-min hard total cap →
|
|
5300
5313
|
60-min idle watchdog.** Every stdout / stderr chunk resets the timer,
|
|
5301
5314
|
so slow human-in-the-loop approvals no longer eat the budget. A truly
|
|
@@ -5321,18 +5334,18 @@ chmod +x ~/.agim/bin/cloudflared
|
|
|
5321
5334
|
|
|
5322
5335
|
### Added
|
|
5323
5336
|
|
|
5324
|
-
- **`
|
|
5337
|
+
- **`AGIM_TIMEOUT_DEFAULT=allow | deny`** env (default `deny`) — what
|
|
5325
5338
|
the bus returns when a normal-mode approval times out with no human
|
|
5326
5339
|
reply. `allow` is "user away" mode. Hot-reloadable from the new Web
|
|
5327
5340
|
Settings → **Approval Policy** card (no service restart needed).
|
|
5328
|
-
- **`
|
|
5341
|
+
- **`AGIM_AGENT_IDLE_TIMEOUT_MS`** global env + `${NAME}_IDLE_TIMEOUT_MS`
|
|
5329
5342
|
per-agent override for the idle watchdog. `0` disables.
|
|
5330
5343
|
- **`OPENCODE_IDLE_TIMEOUT_MS`** env for the opencode HTTP adapter.
|
|
5331
5344
|
- **`humanizeFingerprint()`** — `/approval` listing and auto-allow
|
|
5332
5345
|
receipts now render `命令 git status` / `目录 /tmp` / `主机 api.x.com`
|
|
5333
5346
|
instead of leaking internal scheme prefixes (`cmd:`, `dir:`, `host:`).
|
|
5334
5347
|
- Approval card timeout footer reads the live timeout + the effective
|
|
5335
|
-
`
|
|
5348
|
+
`AGIM_TIMEOUT_DEFAULT` setting (e.g. `15min 未回 → 放行 · req XXX`),
|
|
5336
5349
|
instead of hard-coded "5 分钟未回 = 拒绝".
|
|
5337
5350
|
|
|
5338
5351
|
### Fixed
|
|
@@ -5383,8 +5396,8 @@ chmod +x ~/.agim/bin/cloudflared
|
|
|
5383
5396
|
### Changed — debrand user-facing strings + docs to "agim"
|
|
5384
5397
|
|
|
5385
5398
|
CLI help text, IM messenger adapter error messages, web server log
|
|
5386
|
-
lines, and command-palette titles now say `agim` instead of `
|
|
5387
|
-
or `
|
|
5399
|
+
lines, and command-palette titles now say `agim` instead of `agim`
|
|
5400
|
+
or `agim`. All non-historical docs (README, deployment,
|
|
5388
5401
|
session-model, im-workspaces-guide, etc.) were rewritten accordingly,
|
|
5389
5402
|
including default state-dir / workspace-dir path references
|
|
5390
5403
|
(`~/.agim/`, `~/.agim-workspaces/`).
|
|
@@ -5392,27 +5405,27 @@ including default state-dir / workspace-dir path references
|
|
|
5392
5405
|
### Breaking — Web UI theme key
|
|
5393
5406
|
|
|
5394
5407
|
The localStorage key for the Web UI dark/light theme preference changed
|
|
5395
|
-
from `
|
|
5408
|
+
from `agim-theme` to `agim-theme`. Users will see their theme reset
|
|
5396
5409
|
to system default once on first load after upgrade; re-select if desired.
|
|
5397
5410
|
|
|
5398
5411
|
### Kept for compatibility (intentionally not changed)
|
|
5399
5412
|
|
|
5400
|
-
The following surfaces still use the legacy `
|
|
5413
|
+
The following surfaces still use the legacy `agim` / `agim`
|
|
5401
5414
|
identifier and will not change without a major-version bump:
|
|
5402
5415
|
|
|
5403
|
-
- `
|
|
5416
|
+
- `agim` npm bin alias (`/usr/local/bin/agim` continues to
|
|
5404
5417
|
resolve to the same CLI as `agim`).
|
|
5405
|
-
- `
|
|
5418
|
+
- `agim.service` systemd unit name — installations from the 0.x line
|
|
5406
5419
|
keep their existing unit file; v1.0+ fresh installs write
|
|
5407
5420
|
`agim.service` and `cli-ui/service.ts` falls back to the legacy name.
|
|
5408
|
-
- `X-
|
|
5409
|
-
- WeChat `client_id: '
|
|
5410
|
-
- `~/.
|
|
5421
|
+
- `X-Agim-Token` HTTP header on the ACP server (`acp-server.ts`).
|
|
5422
|
+
- WeChat `client_id: 'agim:…'` (IM-platform-side identifier).
|
|
5423
|
+
- `~/.agim/` data dir + `~/.agim-workspaces/` workspace root are
|
|
5411
5424
|
still detected by `core/agim-paths.ts` as legacy fallback paths; v1.0+
|
|
5412
5425
|
fresh installs land at `~/.agim/` and `~/.agim-workspaces/`.
|
|
5413
5426
|
- `self-protect.ts` process-name regex still matches
|
|
5414
|
-
`(agim|
|
|
5415
|
-
- `npm uninstall -g agim-cli
|
|
5427
|
+
`(agim|agim|agim|dist/cli.js)`.
|
|
5428
|
+
- `npm uninstall -g agim-cli agim agim` (in `cli-ui/cmd-handlers.ts`)
|
|
5416
5429
|
continues to clean up all three historical package names.
|
|
5417
5430
|
|
|
5418
5431
|
## [1.0.14] - 2026-05-13
|
|
@@ -5499,8 +5512,8 @@ who don't restart from WeChat see no behavioral difference.
|
|
|
5499
5512
|
### Removed — Safety card "Skip permissions" toggle
|
|
5500
5513
|
|
|
5501
5514
|
The web /settings Safety card no longer exposes a toggle for
|
|
5502
|
-
`
|
|
5503
|
-
typical systemd deployment:
|
|
5515
|
+
`AGIM_DANGEROUSLY_SKIP_PERMISSIONS`. The toggle was a footgun for the
|
|
5516
|
+
typical systemd deployment: agim runs as root, but Claude CLI itself
|
|
5504
5517
|
hard-refuses `--dangerously-skip-permissions` for uid=0 with
|
|
5505
5518
|
|
|
5506
5519
|
claude-code failed (exit 1):
|
|
@@ -5515,7 +5528,7 @@ The env variable itself is **still honored** by the Claude adapter
|
|
|
5515
5528
|
(`src/plugins/agents/claude-code/index.ts`). Non-root deployments that
|
|
5516
5529
|
genuinely want the bypass can edit `~/.agim/env` manually:
|
|
5517
5530
|
|
|
5518
|
-
|
|
5531
|
+
AGIM_DANGEROUSLY_SKIP_PERMISSIONS=1
|
|
5519
5532
|
|
|
5520
5533
|
The Safety card now contains only the Admin Allowlist editor.
|
|
5521
5534
|
|
|
@@ -5542,14 +5555,14 @@ service mode BEFORE writing the pending file:
|
|
|
5542
5555
|
|
|
5543
5556
|
pgrep -af dist/cli.js # see surviving daemons
|
|
5544
5557
|
pkill -9 -f dist/cli.js
|
|
5545
|
-
systemctl reset-failed
|
|
5546
|
-
systemctl restart
|
|
5558
|
+
systemctl reset-failed agim
|
|
5559
|
+
systemctl restart agim
|
|
5547
5560
|
|
|
5548
5561
|
## [1.0.10] - 2026-05-13
|
|
5549
5562
|
|
|
5550
5563
|
### Added — first-run admin onboarding
|
|
5551
5564
|
|
|
5552
|
-
The v1.0.9 denial message ("set
|
|
5565
|
+
The v1.0.9 denial message ("set AGIM_ADMIN_USERS=… and restart") was
|
|
5553
5566
|
unfriendly to small / non-technical operators. v1.0.10 replaces it with
|
|
5554
5567
|
a guided self-onboarding flow:
|
|
5555
5568
|
|
|
@@ -5565,15 +5578,15 @@ a guided self-onboarding flow:
|
|
|
5565
5578
|
· Token regenerates on every restart while no admin is set.
|
|
5566
5579
|
```
|
|
5567
5580
|
|
|
5568
|
-
2. **Operator** sees this in `journalctl -u
|
|
5569
|
-
~/.
|
|
5581
|
+
2. **Operator** sees this in `journalctl -u agim` (or `tail
|
|
5582
|
+
~/.agim/agim.log`), opens their own IM, and sends
|
|
5570
5583
|
`/setup admin <token>` to the bot.
|
|
5571
5584
|
|
|
5572
5585
|
3. **Bot** verifies the token, calls `promoteAdmin(platform, userId)`
|
|
5573
5586
|
which:
|
|
5574
5587
|
- Adds the entry to the in-memory allowlist (effective immediately,
|
|
5575
5588
|
no restart required)
|
|
5576
|
-
- Persists `
|
|
5589
|
+
- Persists `AGIM_ADMIN_USERS` to `~/.agim/env` so the next restart
|
|
5577
5590
|
keeps it
|
|
5578
5591
|
- Unlinks the token file (single-use)
|
|
5579
5592
|
- Replies "✅ 你 (platform:userId) 已设为管理员"
|
|
@@ -5583,7 +5596,7 @@ a guided self-onboarding flow:
|
|
|
5583
5596
|
|
|
5584
5597
|
### Changed — smarter denial messages
|
|
5585
5598
|
|
|
5586
|
-
The blanket message in v1.0.9 ("
|
|
5599
|
+
The blanket message in v1.0.9 ("AGIM_ADMIN_USERS=… 然后重启服务") leaked
|
|
5587
5600
|
internal env-var format to random visitors. v1.0.10 distinguishes:
|
|
5588
5601
|
|
|
5589
5602
|
- **No admin at all** → "这个 bot 还没配置管理员。如果你是部署者:…
|
|
@@ -5616,7 +5629,7 @@ denial-message + intent/self-protect coverage from v1.0.9. Full suite:
|
|
|
5616
5629
|
|
|
5617
5630
|
### Migration
|
|
5618
5631
|
|
|
5619
|
-
- Existing deployments with `
|
|
5632
|
+
- Existing deployments with `AGIM_ADMIN_USERS` already set: nothing
|
|
5620
5633
|
changes. Token file is auto-cleaned at startup since admins exist.
|
|
5621
5634
|
- New deployments: the bootstrap banner is the entry point. No more
|
|
5622
5635
|
manual env editing required for the typical operator onboarding.
|
|
@@ -5628,7 +5641,7 @@ denial-message + intent/self-protect coverage from v1.0.9. Full suite:
|
|
|
5628
5641
|
A new opt-in lets the operator turn off every approval prompt for Claude
|
|
5629
5642
|
Code, by setting:
|
|
5630
5643
|
|
|
5631
|
-
|
|
5644
|
+
AGIM_DANGEROUSLY_SKIP_PERMISSIONS=1
|
|
5632
5645
|
|
|
5633
5646
|
When set, the Claude Code adapter launches with
|
|
5634
5647
|
`--dangerously-skip-permissions` and skips both the approval-bus pipeline
|
|
@@ -5644,8 +5657,8 @@ respects PreToolUse hooks).
|
|
|
5644
5657
|
|
|
5645
5658
|
1. `opts.planMode` → `--permission-mode plan` (read-only wins over bypass —
|
|
5646
5659
|
you explicitly asked for an exploratory pass).
|
|
5647
|
-
2. `
|
|
5648
|
-
3. `
|
|
5660
|
+
2. `AGIM_DANGEROUSLY_SKIP_PERMISSIONS=1` → `--dangerously-skip-permissions`.
|
|
5661
|
+
3. `AGIM_APPROVAL_DISABLED=1` or no IM context or bus down →
|
|
5649
5662
|
`--permission-mode dontAsk` (unchanged).
|
|
5650
5663
|
4. Default IM-routed → `--permission-mode default --permission-prompt-tool …`
|
|
5651
5664
|
(unchanged).
|
|
@@ -5819,11 +5832,11 @@ just means "no IM channels," not "secretly start WeChat anyway."
|
|
|
5819
5832
|
|
|
5820
5833
|
Agim 的 web 控制台(端口 3000)不再有任何内建鉴权机制:
|
|
5821
5834
|
|
|
5822
|
-
- 删除 `/login` 页面、`POST /api/auth/login` 端点、`
|
|
5835
|
+
- 删除 `/login` 页面、`POST /api/auth/login` 端点、`agim_session` cookie
|
|
5823
5836
|
- 删除 `~/.agim/web-token` 的自动创建(web 端不再读写此文件)
|
|
5824
|
-
- 删除 `
|
|
5837
|
+
- 删除 `AGIM_WEB_REQUIRE_AUTH` 环境变量
|
|
5825
5838
|
- 静态页面 / `/api/*` / `/events` / WebSocket 升级都不再做 token / cookie 校验
|
|
5826
|
-
- 前端代码删除所有 `X-
|
|
5839
|
+
- 前端代码删除所有 `X-Agim-Token` header 注入与 `window.AGIM_TOKEN` 引用
|
|
5827
5840
|
|
|
5828
5841
|
**访问控制责任完全交给上游**——反向代理、防火墙、SSH 隧道、Tailscale /
|
|
5829
5842
|
WireGuard 等。把 web 控制台暴露到 `0.0.0.0` 时务必先在 nginx / Caddy 上加一层
|
|
@@ -5834,7 +5847,7 @@ Basic Auth 或 OAuth2 Proxy;不要直接 HTTP 暴露公网。
|
|
|
5834
5847
|
ACP server 是给第三方 agent 程序化调用的接口,仍走 bearer-token:
|
|
5835
5848
|
|
|
5836
5849
|
- token 文件改为 `~/.agim/acp-token`(自动生成)
|
|
5837
|
-
- 0.x 部署的 `~/.agim/web-token` / `~/.
|
|
5850
|
+
- 0.x 部署的 `~/.agim/web-token` / `~/.agim/web-token` 仍被识别为
|
|
5838
5851
|
legacy 回退路径,已有 ACP 调用方不会断
|
|
5839
5852
|
- 删除 token 文件 + 重启服务即可轮换
|
|
5840
5853
|
|
|
@@ -5842,37 +5855,37 @@ ACP server 是给第三方 agent 程序化调用的接口,仍走 bearer-token
|
|
|
5842
5855
|
|
|
5843
5856
|
- 0.x → 1.0.2 升级:旧 `web-token` 文件留在那里也没事(web 端忽略它,ACP
|
|
5844
5857
|
仍读它做 legacy fallback);可手动删除。
|
|
5845
|
-
- 任何 `X-
|
|
5858
|
+
- 任何 `X-Agim-Token` header 在 web 端会被静默忽略;脚本调用 `/api/*`
|
|
5846
5859
|
现在直接成功,**前提是你已经在反代层加了访问控制**。
|
|
5847
5860
|
|
|
5848
5861
|
## [1.0.1] - 2026-05-12
|
|
5849
5862
|
|
|
5850
|
-
### Changed — config / workspace dir auto-detect (~/.agim/ vs ~/.
|
|
5863
|
+
### Changed — config / workspace dir auto-detect (~/.agim/ vs ~/.agim/)
|
|
5851
5864
|
|
|
5852
5865
|
Follow-up to the v1.0.0 rebrand: the on-disk root is now resolved at
|
|
5853
|
-
startup rather than hard-coded to `~/.
|
|
5866
|
+
startup rather than hard-coded to `~/.agim/`. New module
|
|
5854
5867
|
`src/core/agim-paths.ts` exports `AGIM_HOME` and `AGIM_WORKSPACES`,
|
|
5855
5868
|
computed once with this priority:
|
|
5856
5869
|
|
|
5857
|
-
1. `$AGIM_HOME` / `$AGIM_WORKSPACES` env override (legacy `$
|
|
5870
|
+
1. `$AGIM_HOME` / `$AGIM_WORKSPACES` env override (legacy `$AGIM_HOME`
|
|
5858
5871
|
spelling also honored).
|
|
5859
5872
|
2. `~/.agim/` (or `~/.agim-workspaces/`) if the directory exists — new
|
|
5860
5873
|
canonical name in v1.0+.
|
|
5861
|
-
3. `~/.
|
|
5874
|
+
3. `~/.agim/` (or `~/.agim-workspaces/`) if the directory exists —
|
|
5862
5875
|
legacy 0.x layout. Picked up automatically so upgraded users keep
|
|
5863
5876
|
their data in place with **zero migration**.
|
|
5864
5877
|
4. Default to `~/.agim/` (or `~/.agim-workspaces/`) for fresh installs.
|
|
5865
5878
|
|
|
5866
5879
|
That means:
|
|
5867
|
-
- **Upgraded 0.x user** → `agim` finds the existing `~/.
|
|
5880
|
+
- **Upgraded 0.x user** → `agim` finds the existing `~/.agim/`, uses
|
|
5868
5881
|
it. memos.db / reminders.db / sessions/ / wechat-credentials.json all
|
|
5869
5882
|
stay where they are; nothing is moved.
|
|
5870
5883
|
- **Fresh installer on a clean box** → `agim` creates `~/.agim/`.
|
|
5871
5884
|
- **User who manually moves data** to `~/.agim/` later → `agim` switches
|
|
5872
5885
|
to it automatically on next start.
|
|
5873
5886
|
|
|
5874
|
-
Every hard-coded `join(homedir(), '.
|
|
5875
|
-
`'.
|
|
5887
|
+
Every hard-coded `join(homedir(), '.agim', ...)` and
|
|
5888
|
+
`'.agim-workspaces'` literal across the codebase (22 files,
|
|
5876
5889
|
~30 call sites) was replaced with the resolved root. Modules touched:
|
|
5877
5890
|
`cli.ts`, `web/server.ts`, `core/onboarding.ts`, `core/audit-log.ts`,
|
|
5878
5891
|
`core/job-board.ts`, `core/schedule.ts`, `core/session.ts`,
|
|
@@ -5887,14 +5900,14 @@ literal.
|
|
|
5887
5900
|
|
|
5888
5901
|
## [1.0.0] - 2026-05-12
|
|
5889
5902
|
|
|
5890
|
-
### Changed — Brand rename: `
|
|
5903
|
+
### Changed — Brand rename: `agim` → **Agim · 阿吉姆**
|
|
5891
5904
|
|
|
5892
5905
|
Product upgrade to v1.0 ships under a new brand:
|
|
5893
5906
|
|
|
5894
5907
|
- **English name**: `Agim` (Agent + IM, with a hint of "agile")
|
|
5895
5908
|
- **Chinese name**: `阿吉姆`
|
|
5896
|
-
- **CLI command**: `agim` (was `
|
|
5897
|
-
- **npm package**: `agim-cli` (was `
|
|
5909
|
+
- **CLI command**: `agim` (was `agim`)
|
|
5910
|
+
- **npm package**: `agim-cli` (was `agim`). npm's anti-typosquat
|
|
5898
5911
|
policy rejected the unscoped name `agim` (too similar to existing
|
|
5899
5912
|
`ai`/`aegir`/`gm`), so we ship as `agim-cli` and the installed binary
|
|
5900
5913
|
is still `agim` — the package name only affects the install command
|
|
@@ -5906,33 +5919,33 @@ Cross-cutting policy:
|
|
|
5906
5919
|
|------------------------------------------------------|--------------------|--------|
|
|
5907
5920
|
| npm package name | `agim` | renamed |
|
|
5908
5921
|
| CLI bin command | `agim` | renamed |
|
|
5909
|
-
| Old CLI bin command | `
|
|
5922
|
+
| Old CLI bin command | `agim` | **kept as alias** in the same package — existing systemd units, shell aliases, scripts continue to work |
|
|
5910
5923
|
| Console banner / help text / wizard titles | `Agim` / `阿吉姆` | renamed |
|
|
5911
|
-
| Config dir | `~/.
|
|
5912
|
-
| Workspace dir | `~/.
|
|
5913
|
-
| Env vars | `
|
|
5914
|
-
| HTTP header | `X-
|
|
5915
|
-
| systemd unit name | `agim.service` preferred | **legacy `
|
|
5924
|
+
| Config dir | `~/.agim/` | **unchanged** for backwards compat with all 0.x installs |
|
|
5925
|
+
| Workspace dir | `~/.agim-workspaces/` | **unchanged** |
|
|
5926
|
+
| Env vars | `AGIM_*` | **unchanged** |
|
|
5927
|
+
| HTTP header | `X-Agim-Token` | **unchanged** |
|
|
5928
|
+
| systemd unit name | `agim.service` preferred | **legacy `agim.service` is still recognised** by detection / restart / stop / uninstall code paths |
|
|
5916
5929
|
|
|
5917
5930
|
What this means for users:
|
|
5918
5931
|
- New install: `npm install -g agim` → use `agim …` commands.
|
|
5919
5932
|
- Existing 0.x install: stays working unchanged. Optional upgrade is just
|
|
5920
|
-
`npm uninstall -g
|
|
5921
|
-
(config, env, data) is untouched. The old `
|
|
5933
|
+
`npm uninstall -g agim && npm install -g agim`; everything else
|
|
5934
|
+
(config, env, data) is untouched. The old `agim` bin command
|
|
5922
5935
|
continues to be installed by the new package, so your systemd unit
|
|
5923
|
-
`ExecStart=/usr/local/bin/
|
|
5936
|
+
`ExecStart=/usr/local/bin/agim start` keeps running.
|
|
5924
5937
|
|
|
5925
5938
|
Files touched (non-exhaustive):
|
|
5926
|
-
- `package.json` — name + bin (with `
|
|
5939
|
+
- `package.json` — name + bin (with `agim` alias) + version 1.0.0 + description + keywords
|
|
5927
5940
|
- `src/cli.ts` — banner, program name, help text, comments
|
|
5928
5941
|
- `src/cli-ui/i18n.ts` — every wizard title / status / uninstall string in
|
|
5929
5942
|
both EN and 中文
|
|
5930
5943
|
- `src/cli-ui/service.ts` — accepts either `agim.service` or
|
|
5931
|
-
`
|
|
5944
|
+
`agim.service`; `pgrep` matches both bin names
|
|
5932
5945
|
- `src/cli-ui/cmd-handlers.ts` — restart / uninstall walk both unit paths
|
|
5933
5946
|
- `README.md` + `README.zh-CN.md` — full top-section rewrite, install
|
|
5934
5947
|
commands, migration guide, version history
|
|
5935
|
-
-
|
|
5948
|
+
- agim-site repo — separate brand rollout for the marketing site
|
|
5936
5949
|
|
|
5937
5950
|
## [0.6.3] - 2026-05-12
|
|
5938
5951
|
|
|
@@ -5952,13 +5965,13 @@ the per-platform "what coord system did the payload arrive in?" policy:
|
|
|
5952
5965
|
|
|
5953
5966
|
| Source | Default | Override |
|
|
5954
5967
|
|---------------------------------------|-------------------------|----------|
|
|
5955
|
-
| Telegram native location | WGS-84 pass-through | `
|
|
5968
|
+
| Telegram native location | WGS-84 pass-through | `AGIM_TELEGRAM_COORDS_GCJ02=1` (iOS-zh-CN users) |
|
|
5956
5969
|
| Feishu native location | GCJ-02 → WGS-84 | (server-mandated, no override) |
|
|
5957
5970
|
| DingTalk `link` msgtype, amap.com URL | GCJ-02 → WGS-84 | — |
|
|
5958
5971
|
| DingTalk `link` msgtype, qq.com URL | GCJ-02 → WGS-84 | — |
|
|
5959
5972
|
| DingTalk `link` msgtype, baidu.com URL| **BD-09 → WGS-84** (new)| — |
|
|
5960
5973
|
| DingTalk `link` msgtype, unknown host | WGS-84 pass-through | — |
|
|
5961
|
-
| H5 `/memo here` browser geolocation | WGS-84 pass-through | `
|
|
5974
|
+
| H5 `/memo here` browser geolocation | WGS-84 pass-through | `AGIM_H5_COORDS_GCJ02=1` (iOS Safari users) |
|
|
5962
5975
|
|
|
5963
5976
|
Two **default flips** vs. the old behavior:
|
|
5964
5977
|
1. Telegram: was always GCJ→WGS, now pass-through. Telegram Desktop +
|
|
@@ -6016,7 +6029,7 @@ survive multi-minute agent runs. OpenAPI works for any send.
|
|
|
6016
6029
|
| msgtype on wire | Payload location | Adapter behavior |
|
|
6017
6030
|
|---|---|---|
|
|
6018
6031
|
| `text` | `text.content` | Pass through to agent (no change) |
|
|
6019
|
-
| `picture` | `content.downloadCode` | Download via `/v1.0/robot/messageFiles/download` (the `pictureDownloadCode` field looks tempting but returns 500 — reserved for a different endpoint we don't use). Save under `~/.
|
|
6032
|
+
| `picture` | `content.downloadCode` | Download via `/v1.0/robot/messageFiles/download` (the `pictureDownloadCode` field looks tempting but returns 500 — reserved for a different endpoint we don't use). Save under `~/.agim/media/dingtalk/<thread>/<msgId>.<ext>`. Append `[图片附件:<path>]` to user text. claude-code's Read tool sees the JPG. |
|
|
6020
6033
|
| `audio` | `content.downloadCode` + `content.recognition` | **Prefer the server-side ASR transcript in `recognition`** (zero latency, better Mandarin accuracy than whisper.cpp base model). Still download the source AMR for archive/replay. Fall back to whisper.cpp only when `recognition` is missing. |
|
|
6021
6034
|
| `link` | `link.messageUrl` | Try `tryExtractLatLng()` on the URL (handles Amap, Tencent QMap, generic `?lat=&lng=`, `?location=lat,lng`). On hit → stash in `location-context`, next user text gets the GPS prefix injected. |
|
|
6022
6035
|
| `file` | `content.downloadCode` | Acknowledge only (PDF / Word handling is a separate effort) |
|
|
@@ -6029,7 +6042,7 @@ files land at `msgAB2pLyIgOgo6bJXw9mWAtA__.jpg` and the path-injection
|
|
|
6029
6042
|
guard in `saveDingTalkMedia()` doesn't reject them.
|
|
6030
6043
|
|
|
6031
6044
|
**Config** — `{ dingtalk: { clientId, clientSecret } }` in
|
|
6032
|
-
`~/.
|
|
6045
|
+
`~/.agim/config.json`. `clientId` doubles as `robotCode` for
|
|
6033
6046
|
stream-mode internal apps; we also cache the most-recent `robotCode`
|
|
6034
6047
|
from inbound messages for robustness against multi-bot setups.
|
|
6035
6048
|
|
|
@@ -6056,7 +6069,7 @@ keep existing" for ClientSecret.
|
|
|
6056
6069
|
## [0.5.2] - 2026-05-11
|
|
6057
6070
|
|
|
6058
6071
|
> 0.5.0 introduced the bilingual wizard but 0.5.1 hands-on showed it had
|
|
6059
|
-
> regressed real functionality vs. the old `
|
|
6072
|
+
> regressed real functionality vs. the old `agim config <component>`
|
|
6060
6073
|
> flows — checkbox-only selection couldn't issue WeChat QR codes, prompt
|
|
6061
6074
|
> for Telegram tokens, probe agent CLI installs, etc. 0.5.2 restores all
|
|
6062
6075
|
> of that work inside the new arrow-key UI, plus fixes a pile of paper-
|
|
@@ -6069,7 +6082,7 @@ with the real configuration work the legacy flow did:
|
|
|
6069
6082
|
|
|
6070
6083
|
- **WeChat (iLink)** — `Configure` scans QR via
|
|
6071
6084
|
`ILinkWeChatAdapter.startQRLogin()` + `waitForQRLogin()`; on success the
|
|
6072
|
-
credentials persist to `~/.
|
|
6085
|
+
credentials persist to `~/.agim/wechat-credentials.json` (existing
|
|
6073
6086
|
adapter path) and `wechat-ilink` is added to `cfg.messengers`. Re-running
|
|
6074
6087
|
re-issues a fresh QR.
|
|
6075
6088
|
- **Telegram** — prompts for bot token (hidden) + channel id. On
|
|
@@ -6105,25 +6118,25 @@ default exists is auto-promoted to default.
|
|
|
6105
6118
|
|
|
6106
6119
|
### Added — env reads now find values wherever they actually live
|
|
6107
6120
|
|
|
6108
|
-
The wizard previously only read `~/.
|
|
6121
|
+
The wizard previously only read `~/.agim/env` for SMTP / Baidu prefill,
|
|
6109
6122
|
so machines where those keys were set in the systemd unit's
|
|
6110
6123
|
`Environment=` lines (the common install pattern from before the wizard
|
|
6111
6124
|
existed) showed `(unset)` even though everything was working at runtime.
|
|
6112
6125
|
New `readEffectiveEnv()` falls back through three sources for read:
|
|
6113
6126
|
|
|
6114
|
-
1. `~/.
|
|
6127
|
+
1. `~/.agim/env` (canonical, what the wizard writes)
|
|
6115
6128
|
2. `process.env` (shell-exported)
|
|
6116
|
-
3. `/etc/systemd/system/
|
|
6129
|
+
3. `/etc/systemd/system/agim.service` — parsed `Environment=` lines
|
|
6117
6130
|
(file is world-readable on standard installs, so works for the user's
|
|
6118
|
-
shell-invoked `
|
|
6131
|
+
shell-invoked `agim config`)
|
|
6119
6132
|
|
|
6120
6133
|
Writes still go to the env file only. When `hasProcessEnvOverride(key)`
|
|
6121
6134
|
detects a wizard-managed key that's set somewhere outside the env file,
|
|
6122
6135
|
the SMTP / Baidu save path prints a one-line warning:
|
|
6123
6136
|
|
|
6124
6137
|
```
|
|
6125
|
-
⚠️
|
|
6126
|
-
unit / shell export). Saving to ~/.
|
|
6138
|
+
⚠️ AGIM_BAIDU_MAP_AK is also set by the running environment (systemd
|
|
6139
|
+
unit / shell export). Saving to ~/.agim/env alone will NOT change the
|
|
6127
6140
|
active value — update the unit file or `unset` the shell export first.
|
|
6128
6141
|
```
|
|
6129
6142
|
|
|
@@ -6177,24 +6190,24 @@ this is the actual first published 0.5.x release.
|
|
|
6177
6190
|
|
|
6178
6191
|
## [0.5.0] - 2026-05-11
|
|
6179
6192
|
|
|
6180
|
-
> **核心主题**:`
|
|
6193
|
+
> **核心主题**:`agim` CLI 升级成"运维主入口"——双语 + 上下键交互向导 + 完整服务生命周期管理(status / start --bg / restart / stop / uninstall)。SMTP 和百度地图 AK 终于进入 `config` 一站式配置。
|
|
6181
6194
|
|
|
6182
6195
|
### Added — 双语交互式 `config` 向导
|
|
6183
|
-
之前 `
|
|
6196
|
+
之前 `agim config` 是 per-component 的命令行参数式配置(`config wechat` / `config telegram` / ...),界面是纯 `readline.question` 文本提示,新用户摸不着头脑。
|
|
6184
6197
|
|
|
6185
6198
|
新增基于 `@inquirer/prompts` 的交互向导:
|
|
6186
|
-
- **语言选择**:首次进入弹出 EN / 中文 选择器,记忆到 `~/.
|
|
6199
|
+
- **语言选择**:首次进入弹出 EN / 中文 选择器,记忆到 `~/.agim/cli-lang`,下次进入回车即可
|
|
6187
6200
|
- **5 个分类**(每个分类内部支持 ← Back 回根菜单):
|
|
6188
6201
|
1. **IM 渠道** — 多选 checkbox:微信 / Telegram / 飞书 / Discord / 邮件
|
|
6189
6202
|
2. **AI Agent** — 多选 + 选默认 agent(Claude Code / OpenCode / Codex / Copilot)
|
|
6190
6203
|
3. **远程 ACP agent** — 列表 + 新增 / 编辑 / 删除,支持 Bearer token 认证(输入隐藏)
|
|
6191
|
-
4. **SMTP**(新增)— 4 个预设(Gmail / Outlook / QQ / 163)+ Custom + Skip;写到 `~/.
|
|
6192
|
-
5. **百度地图 AK**(新增)— 输入 / 清除,写到 `~/.
|
|
6204
|
+
4. **SMTP**(新增)— 4 个预设(Gmail / Outlook / QQ / 163)+ Custom + Skip;写到 `~/.agim/env`(chmod 600)
|
|
6205
|
+
5. **百度地图 AK**(新增)— 输入 / 清除,写到 `~/.agim/env`
|
|
6193
6206
|
- **Per-spawn 持久化**:SMTP 密码、Baidu AK 一输入就落盘,wizard 半途崩了不丢
|
|
6194
|
-
- 旧的 `
|
|
6207
|
+
- 旧的 `agim config <component>` 路径保留兼容
|
|
6195
6208
|
|
|
6196
|
-
### Added — bare `
|
|
6197
|
-
直接敲 `
|
|
6209
|
+
### Added — bare `agim` → 运维入口菜单
|
|
6210
|
+
直接敲 `agim`(无参)不再 dump help。改成弹出 8 项菜单:
|
|
6198
6211
|
- Configure
|
|
6199
6212
|
- Show status
|
|
6200
6213
|
- Start (foreground / background)
|
|
@@ -6209,11 +6222,11 @@ this is the actual first published 0.5.x release.
|
|
|
6209
6222
|
|
|
6210
6223
|
| Command | 行为 |
|
|
6211
6224
|
|---|---|
|
|
6212
|
-
| `
|
|
6213
|
-
| `
|
|
6214
|
-
| `
|
|
6215
|
-
| `
|
|
6216
|
-
| `
|
|
6225
|
+
| `agim status` | 探测 systemd / background daemon / foreground;显示 pid + uptime + Web URL |
|
|
6226
|
+
| `agim start --bg` | 后台启动(nohup + setsid + pid 文件 + 日志到 `~/.agim/agim.log`);裸 `start` 仍前台 |
|
|
6227
|
+
| `agim restart` | 自动选 systemctl restart 或 bg daemon 重启 |
|
|
6228
|
+
| `agim stop` | 自动选 systemctl stop 或 SIGTERM bg pid + cleanup pid 文件 |
|
|
6229
|
+
| `agim uninstall` | 双重确认后:停服务 → 卸载 npm 包 → 删 config.json + env + pid + systemd 单元;**保留 `~/.agim-workspaces/`** |
|
|
6217
6230
|
|
|
6218
6231
|
**跨平台后台启动**:Linux / macOS / WSL2 都走 `nohup`+detach 路径。macOS 上想真正开机自启仍要自己写 launchd plist(CHANGELOG 后续版本可加)。
|
|
6219
6232
|
|
|
@@ -6223,7 +6236,7 @@ this is the actual first published 0.5.x release.
|
|
|
6223
6236
|
- `src/cli-ui/lang-picker.ts` — 语言选择 + 持久化
|
|
6224
6237
|
- `src/cli-ui/config-wizard.ts` — 5 个分类的向导主体
|
|
6225
6238
|
- `src/cli-ui/service.ts` — `detectService()` / `spawnBackground()` / `stopService()` / `formatUptime()`
|
|
6226
|
-
- `src/cli-ui/env-file.ts` — 增量更新 `~/.
|
|
6239
|
+
- `src/cli-ui/env-file.ts` — 增量更新 `~/.agim/env`(merge-update + chmod 600)
|
|
6227
6240
|
- `src/cli-ui/cmd-handlers.ts` — status / start / stop / restart / uninstall 实现
|
|
6228
6241
|
- `src/cli-ui/entry-menu.ts` — bare invocation 用的入口菜单
|
|
6229
6242
|
- `src/cli-ui/paths.ts` — 共享路径常量
|
|
@@ -6238,15 +6251,15 @@ this is the actual first published 0.5.x release.
|
|
|
6238
6251
|
- `@inquirer/prompts ^8.4.3` — modern interactive prompts (上下键 / Space / 输入隐藏)。~80KB 加到 dist。
|
|
6239
6252
|
|
|
6240
6253
|
### Migration notes
|
|
6241
|
-
- 老用户升级:`npm install -g
|
|
6242
|
-
- 想跳过新向导:`
|
|
6243
|
-
- 后台启动取代了之前文档里推荐的 `nohup
|
|
6254
|
+
- 老用户升级:`npm install -g agim@0.5.0`。已有 `~/.agim/config.json` 全部兼容,新增 SMTP / Baidu 配置可以走新向导补充
|
|
6255
|
+
- 想跳过新向导:`agim config wechat` / `config telegram` 等老路径仍然能用
|
|
6256
|
+
- 后台启动取代了之前文档里推荐的 `nohup agim start &` 写法
|
|
6244
6257
|
|
|
6245
6258
|
## [0.4.0] - 2026-05-11
|
|
6246
6259
|
|
|
6247
6260
|
> **核心主题(两条)**:
|
|
6248
6261
|
>
|
|
6249
|
-
> 1. **codex 也接
|
|
6262
|
+
> 1. **codex 也接 agim MCP**——/remind 4 工具 + /memo 5 工具,9 个全部对它开放。三大 agent(claude-code / opencode / codex)功能对等。
|
|
6250
6263
|
> 2. **位置消息架构统一化**——Telegram / 飞书的原生位置消息原本走「pending-reply + 启发式拆词」决策链,bug 频出。新版改成 agent-driven:adapter 只缓存坐标,cli.ts 注入结构化 annotation 到用户下一条文本,agent 用 LLM 决策。删除 ~400 行启发式代码,4 个 IM 渠道行为完全一致。
|
|
6251
6264
|
|
|
6252
6265
|
### Refactored — Telegram + 飞书位置消息走 agent-driven 决策(对齐 WeChat H5 流程)
|
|
@@ -6271,32 +6284,32 @@ this is the actual first published 0.5.x release.
|
|
|
6271
6284
|
- 任何长句、短词、混合表达都不再走启发式:「这是我公司」「记下日料店」「不用记了」「这是哪里」都自然处理
|
|
6272
6285
|
- 每个 pin 后续消息额外付出一次 agent 调用(旧版是 deterministic 直存);用稳定性换费用
|
|
6273
6286
|
|
|
6274
|
-
### Added — codex 也能用
|
|
6287
|
+
### Added — codex 也能用 agim MCP 工具
|
|
6275
6288
|
(这一段已在 0.4.0-rc1 时落地,下面是 rc1 的内容)
|
|
6276
6289
|
|
|
6277
6290
|
之前 codex 是唯一一个 reminder/memo 工具完全无法触达的 agent,因为 codex CLI 没有 `--mcp-config` flag。验证发现 codex 0.130.0+ 支持通过 `-c mcp_servers.<name>.{command,args,env}=...` 的 TOML 内联 override 在调用层注册 MCP server——per-spawn、不污染全局 `~/.codex/config.toml`。
|
|
6278
6291
|
|
|
6279
6292
|
实现:
|
|
6280
6293
|
|
|
6281
|
-
- **`src/plugins/agents/codex/build-mcp-cli-args.ts`**:纯函数,输入 `{sockPath, runId}`,输出 6 个 argv entries(3 对 `-c key=value`)。TOML 转义走 `JSON.stringify` 兼容 basic-string 语法。共享 claude-code 那个 `mcp-approval-server.js`(同一个二进制读 `
|
|
6282
|
-
- **`codex/index.ts` 的 `prepareCommand`**:fallback 三道闸——`
|
|
6294
|
+
- **`src/plugins/agents/codex/build-mcp-cli-args.ts`**:纯函数,输入 `{sockPath, runId}`,输出 6 个 argv entries(3 对 `-c key=value`)。TOML 转义走 `JSON.stringify` 兼容 basic-string 语法。共享 claude-code 那个 `mcp-approval-server.js`(同一个二进制读 `AGIM_APPROVAL_SOCK + AGIM_RUN_ID`,已经 channel-agnostic)。
|
|
6295
|
+
- **`codex/index.ts` 的 `prepareCommand`**:fallback 三道闸——`AGIM_APPROVAL_DISABLED=1` / `approvalBus.getSocketPath()` 空 / 无 IM context 任一不满足就降级到无 MCP 模式,codex 仍能正常调用。命中时生成 UUID runId → `approvalBus.registerRun(runId, ...)` → MCP `-c` 参数前置到 argv 头部(codex 的 clap 要求全局参数在 `exec` 之前)→ `cleanup` 在 spawn 退出后 `unregisterRun`。
|
|
6283
6296
|
- **`codex exec resume` 不再接 `-s`**(codex 0.130 改的):resume 路径继承原会话 sandbox,传 `-s` 直接 `unexpected argument` 报错。修复:sandbox flag 仅在 fresh `exec` 加。
|
|
6284
|
-
- **`--dangerously-bypass-approvals-and-sandbox`**:codex 在 `exec --json` 非交互模式下默认会 auto-cancel 所有 MCP 工具调用(找不到 TUI 让用户点 approve)。这个 flag 是 codex 0.130 目前唯一让 MCP 工具在非交互模式下能实际运行的方式。代价是 codex 自己的 bash/edit 也失去 sandbox。提供 `
|
|
6285
|
-
- **AGENTS.md 写明命名差异**:claude-code/opencode 暴露 `
|
|
6297
|
+
- **`--dangerously-bypass-approvals-and-sandbox`**:codex 在 `exec --json` 非交互模式下默认会 auto-cancel 所有 MCP 工具调用(找不到 TUI 让用户点 approve)。这个 flag 是 codex 0.130 目前唯一让 MCP 工具在非交互模式下能实际运行的方式。代价是 codex 自己的 bash/edit 也失去 sandbox。提供 `AGIM_CODEX_SAFE_MODE=1` opt-out(代价:MCP 工具不可用)。
|
|
6298
|
+
- **AGENTS.md 写明命名差异**:claude-code/opencode 暴露 `mcp__agim__save_memo`;codex 暴露 bare name `save_memo`。模型按错名调用会静默失败。
|
|
6286
6299
|
|
|
6287
6300
|
**版本下限**:codex CLI ≥ 0.130.0(`mcp` 子命令 + `-c mcp_servers.*` TOML override 同时存在的最早稳定版)。
|
|
6288
6301
|
|
|
6289
|
-
**不在范围**:codex 自己的 Read/Edit/Bash 走 approval-bus——需要把 codex 跑成 `codex mcp-server` 让
|
|
6302
|
+
**不在范围**:codex 自己的 Read/Edit/Bash 走 approval-bus——需要把 codex 跑成 `codex mcp-server` 让 agim 当 MCP client,是 v0.5.x 级别的大重构。
|
|
6290
6303
|
|
|
6291
6304
|
## [0.3.1] - 2026-05-11
|
|
6292
6305
|
|
|
6293
|
-
### Added — codex 也能用
|
|
6306
|
+
### Added — codex 也能用 agim MCP 工具
|
|
6294
6307
|
之前 codex 是唯一一个 reminder/memo 工具完全无法触达的 agent,因为 codex CLI 没有 `--mcp-config` flag。验证发现 codex 0.130.0+ 支持通过 `-c mcp_servers.<name>.{command,args,env}=...` 的 TOML 内联 override 在调用层注册 MCP server——per-spawn、不污染全局 `~/.codex/config.toml`。
|
|
6295
6308
|
|
|
6296
6309
|
实现:
|
|
6297
6310
|
|
|
6298
|
-
- **`src/plugins/agents/codex/build-mcp-cli-args.ts`**:纯函数,输入 `{sockPath, runId}`,输出 6 个 argv entries(3 对 `-c key=value`)。TOML 转义走 `JSON.stringify` 兼容 basic-string 语法。共享 claude-code 那个 `mcp-approval-server.js`(同一个二进制读 `
|
|
6299
|
-
- **`codex/index.ts` 的 `prepareCommand`**:fallback 三道闸——`
|
|
6311
|
+
- **`src/plugins/agents/codex/build-mcp-cli-args.ts`**:纯函数,输入 `{sockPath, runId}`,输出 6 个 argv entries(3 对 `-c key=value`)。TOML 转义走 `JSON.stringify` 兼容 basic-string 语法。共享 claude-code 那个 `mcp-approval-server.js`(同一个二进制读 `AGIM_APPROVAL_SOCK + AGIM_RUN_ID`,已经 channel-agnostic)。
|
|
6312
|
+
- **`codex/index.ts` 的 `prepareCommand`**:fallback 三道闸——`AGIM_APPROVAL_DISABLED=1` / `approvalBus.getSocketPath()` 空 / 无 IM context(threadId+platform+channelId)任一不满足就降级到无 MCP 模式,codex 仍能正常调用。命中时生成 UUID runId → `approvalBus.registerRun(runId, ...)` → MCP `-c` 参数前置到 argv 头部(codex 的 clap 要求全局参数在 `exec` 之前)→ `cleanup` 在 spawn 退出后 `unregisterRun`。
|
|
6300
6313
|
- **测试**:39 个新单测覆盖 builder(argv shape + TOML 双引号/反斜杠/UUID/空格路径 escaping)+ adapter(fallback 三道、happy path、runId 嵌入、cleanup、cwd+planMode+resume 与 MCP -c 共存、并发产生不同 runId)。
|
|
6301
6314
|
|
|
6302
6315
|
**仍然不做**:
|
|
@@ -6338,7 +6351,7 @@ this is the actual first published 0.5.x release.
|
|
|
6338
6351
|
- 17 单测覆盖 short/heuristic/fallback 各路径 + emoji / 中英混合 / 长句不卷死等 adversarial 输入
|
|
6339
6352
|
|
|
6340
6353
|
### Fixed — 中国境内坐标双重偏移(影响 Telegram + 飞书 + H5 三条路径)
|
|
6341
|
-
**根因**:iOS Core Location(Apple,iOS 7+)和 Android Google Play Services 都会在中国境内**主动**把 WGS-84 偏移成 GCJ-02 才交给应用层(合规要求)。Telegram / 飞书 / 浏览器 `navigator.geolocation` 都吃这个偏移,传给
|
|
6354
|
+
**根因**:iOS Core Location(Apple,iOS 7+)和 Android Google Play Services 都会在中国境内**主动**把 WGS-84 偏移成 GCJ-02 才交给应用层(合规要求)。Telegram / 飞书 / 浏览器 `navigator.geolocation` 都吃这个偏移,传给 agim 时已经是 GCJ-02。我们当 WGS-84 存入库,构 amap URL 时再做一次 WGS→GCJ-02 = 双重偏移,~500m-1km。
|
|
6342
6355
|
|
|
6343
6356
|
**修复**:
|
|
6344
6357
|
|
|
@@ -6355,8 +6368,8 @@ this is the actual first published 0.5.x release.
|
|
|
6355
6368
|
### Fixed — Venue title 在 where_label 中保留
|
|
6356
6369
|
之前 cli.ts pending consumer 写 `where_label` 时是 `venueAddress ?? venueLabel`——`??` 让 venueAddress 优先,title 就被丢了。Telegram venue 通常两者都有("黄龙国际中心" + "学院路77号"),title 是用户最容易认出的那条。改成 `[venueLabel, venueAddress].filter(Boolean).join(' · ')`,两者都存,搜任一 token 都能命中。回复卡片同步加一行 `📍 <title> · <address>` 让用户看见保留。
|
|
6357
6370
|
|
|
6358
|
-
### Site (separate repo:
|
|
6359
|
-
不直接绑 npm 包,但同期
|
|
6371
|
+
### Site (separate repo: agim-site)
|
|
6372
|
+
不直接绑 npm 包,但同期 agim-site 跑了一波 optimization pass:
|
|
6360
6373
|
|
|
6361
6374
|
- 一键安装命令分 Linux / macOS / Windows 三 tab(同一份 install.sh,uname 自检;Windows 走 WSL2)
|
|
6362
6375
|
- `curl ... | bash` 改 `bash -c "$(curl ...)"`:macOS bash 3.2 + /dev/tty 重连不稳的 pipe 形式换成 Homebrew 同款
|
|
@@ -6371,7 +6384,7 @@ this is the actual first published 0.5.x release.
|
|
|
6371
6384
|
> **核心主题**:`/location` 升级为通用 `/memo`(5W1H 持久记忆库),地图服务从腾讯切到百度,opencode HTTP driver 修复 SSE-broken 回归。这是个有意义的里程碑——位置只是 5W1H 中的一个轴。
|
|
6372
6385
|
|
|
6373
6386
|
### Fixed — opencode HTTP driver: SSE 不发事件时从 POST body 拿文本
|
|
6374
|
-
opencode 1.14.45+ 在新的 `node-http-server` runtime 下 `/event` SSE 只发首个 `server.connected` 然后再不广播任何 bus 事件(`message.part.updated` / `session.idle` 全丢),导致
|
|
6387
|
+
opencode 1.14.45+ 在新的 `node-http-server` runtime 下 `/event` SSE 只发首个 `server.connected` 然后再不广播任何 bus 事件(`message.part.updated` / `session.idle` 全丢),导致 agim 这边收 0 字节,用户在微信里看到「opencode无回复」。
|
|
6375
6388
|
|
|
6376
6389
|
直 curl 复现:POST `/session/:id/message` 这个 endpoint 现在改成阻塞直至 LLM 完成,把整条 assistant message 同步以 JSON 还回来。我们就拿这个:
|
|
6377
6390
|
|
|
@@ -6384,7 +6397,7 @@ opencode 1.14.45+ 在新的 `node-http-server` runtime 下 `/event` SSE 只发
|
|
|
6384
6397
|
新增 3 单测覆盖:drained-only / SSE+POST 同 part 的 dedupe / `drainResponseBody` 的过滤逻辑。35/35 adapter 测试全过。
|
|
6385
6398
|
|
|
6386
6399
|
### Added — 部署脚本自动重启 opencode
|
|
6387
|
-
`/root/.claude/bgjobs/scripts/
|
|
6400
|
+
`/root/.claude/bgjobs/scripts/agim-deploy.sh` 末尾加一段:agim 重启完成后如果检测到 `opencode serve --port 14199` 还在跑,调 `opencode-restart.sh` 把它弹一遍,让新 daemon 继承当前 shell 的 `AGIM_APPROVAL_SOCK`(agim 每次重启会换 socket hash,旧 daemon 还指向旧 socket → MCP 工具调用会回「后台消息服务不可用」)。一行钩子,一劳永逸。
|
|
6388
6401
|
|
|
6389
6402
|
### Added — 给 place-like memo 主动追问坐标
|
|
6390
6403
|
agent 落库一条「老孙家」「公司新址」这种**明显是地点但用户没给坐标**的 memo 后,会反问一句「要不要顺带补个坐标?」给三个选项(现在抓 GPS / 告地址解析 / 不用)。`save_memo` tool description 里写死的 PROACTIVE FOLLOW-UP 段。同一段还硬塞一份 TOOL INVENTORY 列表(5 个 memo 工具),并明令「不准跟用户说工具下线了」——之前 agent 在 location→memo 重命名后偶尔会胡说「位置工具已下线」。
|
|
@@ -6409,7 +6422,7 @@ agent 落库一条「老孙家」「公司新址」这种**明显是地点但用
|
|
|
6409
6422
|
- schema 里 `created_at` / `updated_at` 默认值改为 `datetime('now', '+8 hours')`(兜底,正常路径 JS 会显式设)
|
|
6410
6423
|
- tool description 里 `when_at` / `when_after` / `when_before` 都说明:**Asia/Shanghai (UTC+8),"YYYY-MM-DD HH:MM:SS",不要带 T 也不要 Z**
|
|
6411
6424
|
- 11 新增单测覆盖:nowSqliteLocal 形状 / toSqliteLocal +8h shift / normalizeWhenAt 各路径(Z / +08:00 / 已 local / null / unparseable)/ created_at 实际写入 UTC+8 / sweep 用 UTC+8 比较
|
|
6412
|
-
- 时区可调:`
|
|
6425
|
+
- 时区可调:`AGIM_TZ_OFFSET_HOURS` env,默认 8(其他时区部署只改这一个就行)
|
|
6413
6426
|
|
|
6414
6427
|
### Changed — opencode agent 系统提示也加上 memo 工具
|
|
6415
6428
|
opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提了 reminder 那 4 个工具,现在加上 memo 那 5 个 (`save_memo` / `search_memos` / `update_memo` / `delete_memo` / `request_location_capture`) 一起列出,并补一段 timezone 说明。这样 opencode 通过 HTTP daemon mode 跑时也知道要带 `_im_context` + 用 UTC+8。
|
|
@@ -6458,12 +6471,12 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6458
6471
|
- 调整三处用户可见输出:
|
|
6459
6472
|
- `POST /api/loc` 推回的"✅ 已记录" 消息列出 3 条链接
|
|
6460
6473
|
- `/location show <id>` 命令详情列出 3 条
|
|
6461
|
-
- `
|
|
6474
|
+
- `mcp__agim__save_location` 和 `list_locations` 工具返回结构加 `mapUrls: { baidu, amap, google }` 字段;旧 `mapUrl`(百度)保留向后兼容
|
|
6462
6475
|
- MCP 工具描述告诉 agent 优先把三条都展示给用户挑
|
|
6463
6476
|
|
|
6464
6477
|
### Changed — 地图服务从腾讯切到百度
|
|
6465
6478
|
- **地理编码**:`apis.map.qq.com/ws/geocoder/v1/` → `api.map.baidu.com/geocoding/v3/`,强制 `ret_coordtype=wgs84ll`(百度默认返 BD-09,必须显式拉 WGS-84 才和浏览器 `navigator.geolocation` 一致——否则存库坐标 vs 浏览器坐标 50–500m 飘移)
|
|
6466
|
-
- **凭据 env**:`
|
|
6479
|
+
- **凭据 env**:`AGIM_TENCENT_MAP_KEY` / `AGIM_TENCENT_MAP_SK` → `AGIM_BAIDU_MAP_AK`(默认 key 流程不需要 SN 签名;如以后开启 SN 校验,文档说明在 `src/core/locations.ts` 头注释里)
|
|
6467
6480
|
- **地图 URI scheme**:默认从 `apis.map.qq.com/uri/v1/marker?...` 改为 `api.map.baidu.com/marker?location=lat,lng&coord_type=wgs84&...`(注意 `coord_type=wgs84` 关键,否则百度按 BD-09 解读飘 50–500m)
|
|
6468
6481
|
- 错误码分类重写:百度状态码体系不同(200/201/202 = 签名 / Referer / IP;401-405 = 配额;1-4 = 找不到/参数错;5/210/211/220/240 = 各种权限 / 配额家族)
|
|
6469
6482
|
- **腾讯 SK 签名代码移除**:`signTencent` 函数 + 4 条相关单测删除。Baidu 默认 key 流程不需要签名;如以后开启 SN 校验,算法是 `MD5(URLencode(path?qs+sk))`(与腾讯的 `MD5(path?raw_qs+sk)` 不同 —— 多一步整体 URL 编码),实现可参考头注释
|
|
@@ -6483,7 +6496,7 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6483
6496
|
→ bus → location-rpc → 发 token + 返 URL
|
|
6484
6497
|
→ claude 回用户 "好的,点开链接授权: <url>"
|
|
6485
6498
|
→ 用户点 → H5 显示 "正在记录: 车" → 授权 → POST → 写库
|
|
6486
|
-
→
|
|
6499
|
+
→ agim fire-and-forget 推回 "✅ 已记录'车' lat,lng [地图]"
|
|
6487
6500
|
```
|
|
6488
6501
|
```
|
|
6489
6502
|
用户 "我的车在哪" → claude 调 list_locations({query:'车'})
|
|
@@ -6503,11 +6516,11 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6503
6516
|
- **架构权衡**:放弃了 `remind-intent.ts` 那种"消息流前置正则探测器"模式。reminder 的 detector 是历史遗留,每条消息都跑一次额外 LLM 调用(就是修过 80s→3s 那个性能问题的祸根)。location 直接让 agent 看工具描述自己判断,零额外 LLM 调用、零误触代价、对话上下文连续。
|
|
6504
6517
|
|
|
6505
6518
|
### Added — `/location here` 浏览器 GPS 捕获
|
|
6506
|
-
- 新子命令 `/location here [备注]` 或 `/location 当前 [备注]`:bot 回一个一次性 HTTPS 链接,用户在 WeChat 内置浏览器点开,授权后 H5 页面调 `navigator.geolocation.getCurrentPosition` 把坐标 POST 回
|
|
6519
|
+
- 新子命令 `/location here [备注]` 或 `/location 当前 [备注]`:bot 回一个一次性 HTTPS 链接,用户在 WeChat 内置浏览器点开,授权后 H5 页面调 `navigator.geolocation.getCurrentPosition` 把坐标 POST 回 agim,agim 写库 + 推回 IM 线程。
|
|
6507
6520
|
- 数据流:`/location here` → 内存 token store 发 32 hex token (10 min TTL,single-shot) → 用户点 URL → `GET /loc?t=...` 渲 H5 → 用户授权 → `POST /api/loc { t, lat, lng, accuracy }` → 验 token → 写 `location_memos`(source=`browser`)→ messenger.sendMessage 把"✅ 位置已收到 + 地图链接"回推到原线程。
|
|
6508
|
-
- **默认 base URL**:`https://agent.iclaw.host`(公共托管入口)。自托管用户可设 `
|
|
6521
|
+
- **默认 base URL**:`https://agent.iclaw.host`(公共托管入口)。自托管用户可设 `AGIM_LOC_BASE_URL=https://your-host` 覆盖。OSS 用户没有 HTTPS endpoint 时可继续用坐标输入路径。
|
|
6509
6522
|
- 新建 `src/core/location-token.ts`:内存 Map,60s 一次的 sweep timer 清过期;test/diagnostic 钩子 `_pendingCount` `_clearAll` `_stopSweep`。
|
|
6510
|
-
- 新建 `src/web/public/loc.html`:单页 H5(无构建依赖、纯内联 CSS+JS),蓝主题与
|
|
6523
|
+
- 新建 `src/web/public/loc.html`:单页 H5(无构建依赖、纯内联 CSS+JS),蓝主题与 agim-site 视觉一致。错误分支覆盖:缺 token / 浏览器不支持 / 用户拒绝授权 / 网络错误。
|
|
6511
6524
|
- 新增 `src/web/server.ts` 公开路由 `GET /loc` + `POST /api/loc`,放在 auth gate 之前(token 即凭证)。`POST /api/loc` 失败时分类回 410(链接过期 / 已使用)/ 400(参数错);写库/dispatch 是 fail-soft,不阻塞 H5 端 200 响应。
|
|
6512
6525
|
- **agent.iclaw.host 部署**:路由复用现有 :3000,CDN 必须配路径白名单只放行 `/loc` 与 `/api/loc`,其他路径(`/tasks` `/reminders` `/api/*`)必须在 CDN 层 404,否则操作员控制台会被外网暴露。
|
|
6513
6526
|
- 7 单测 `location-token.test.ts`:issue/consume 圆环、单次消费、过期回收(Date.now stub)、多 token 独立、跨用户隔离。
|
|
@@ -6515,12 +6528,12 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6515
6528
|
### Added — `/location` 位置备忘(基础版)
|
|
6516
6529
|
- 新 slash 命令 `/location`(别名 `/loc` `/位置`):记录"在 X 位置干了 Y 事"型备忘。
|
|
6517
6530
|
- **零依赖坐标输入**:`/location 39.908,116.397 [备注]` —— 支持 `,` `,` 或空格分隔,负数支持。
|
|
6518
|
-
- **可选地址解析**:`/location 国贸三期 [备注]`,需配置 `
|
|
6519
|
-
- **腾讯地图 SK 签名支持**:开启了"WebServiceAPI 强制签名校验"的 key 配 `
|
|
6531
|
+
- **可选地址解析**:`/location 国贸三期 [备注]`,需配置 `AGIM_TENCENT_MAP_KEY`([lbs.qq.com](https://lbs.qq.com) 注册免费 key)。无 key 时给友好错误提示,引导用户用坐标路径。
|
|
6532
|
+
- **腾讯地图 SK 签名支持**:开启了"WebServiceAPI 强制签名校验"的 key 配 `AGIM_TENCENT_MAP_SK`,自动 MD5 签名。算法:参数按 key 字典序排序、用未 URL-encode 的原值拼 `k=v&...`、与 `path?qs+SK` 整体 MD5 → 32 位 lowercase hex。已对照官方 API 实测验证。
|
|
6520
6533
|
- **细分错误反馈**:地理编码失败按状态码分类(`signature`/`quota`/`not_found`/`http`/`unknown`),命令直接告诉用户是配额满了还是签名错了或地址不对。
|
|
6521
6534
|
- 子命令:`list [N]` / `show <id>` / `delete <id>` / `help`,全部 per-user owner-scoped(同 `/remind` `/cron` 模式)。
|
|
6522
6535
|
- **地图链接回显**:每条记录附 `https://apis.map.qq.com/uri/v1/marker?...` URI,WeChat 内置浏览器/地图 App 可直接唤起。
|
|
6523
|
-
- 数据:`~/.
|
|
6536
|
+
- 数据:`~/.agim/locations.db`(路径可通过 `AGIM_LOCATIONS_DB` 覆盖),fail-soft via 现有 `sqlite-helper`。
|
|
6524
6537
|
- 18 单测:坐标解析(中文逗号 / 负数 / 范围校验)、地图 URL 构建、地理编码 env 探测、SK 签名(含 reference fixture)、CRUD 全流程 + owner scoping。
|
|
6525
6538
|
- **不包含**:浏览器 geolocation 链接(Phase 2,要求 HTTPS endpoint),LLM 自然语言识别(Phase 3)。
|
|
6526
6539
|
|
|
@@ -6533,7 +6546,7 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6533
6546
|
|
|
6534
6547
|
### Added — 只读工具自动放行(默认开启)
|
|
6535
6548
|
- 新增 `READONLY_TOOLS` 短路:`Read` / `Grep` / `Glob` / `LS` / `NotebookRead` 这 5 个 Claude Code 原生只读工具的审批请求在 `approval-bus._registerPending` 入口被直接放行——不建 pending、不通知、不写 IM 卡片。零 IM 往返,给 LLM 自由探索代码而不打扰用户。
|
|
6536
|
-
- 全局开关:`
|
|
6549
|
+
- 全局开关:`AGIM_AUTOALLOW_READONLY=0`(默认 1)关闭。
|
|
6537
6550
|
- per-thread 开关:`/approval readonly off|on`(别名 `/approval ro`)。仅本会话内存生效,重启后回到全局默认。
|
|
6538
6551
|
- 审计:每次短路写一行 `approval.bus.readonly_auto_allow` info log,并在 metrics 新增 `totalReadonlyAutoAllowed` 计数。
|
|
6539
6552
|
- `/approval`(无参)和 `/approval readonly` 都会显示当前状态行 `🛡 只读自动放行:开启 ...`。
|
|
@@ -6597,7 +6610,7 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6597
6610
|
**Agent MCP 工具(提醒兜底创建)**
|
|
6598
6611
|
- 4 个工具:`create_reminder` / `list_reminders` / `cancel_reminder` / `snooze_reminder`
|
|
6599
6612
|
- claude-code:复用现有 `--mcp-config` per-spawn 注入
|
|
6600
|
-
- opencode (stdio):`prepareCommand` 注入 `
|
|
6613
|
+
- opencode (stdio):`prepareCommand` 注入 `AGIM_RUN_ID` extraEnv,全局 `mcp.agim` config 自动注册
|
|
6601
6614
|
- opencode (http):常驻 daemon 共享 MCP server,agent-asserted `_im_context` 兜底(**单用户限定**——agent 可伪造身份)
|
|
6602
6615
|
- codex:未实施(`codex exec` 不支持外部 MCP)
|
|
6603
6616
|
|
|
@@ -6607,13 +6620,13 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6607
6620
|
|
|
6608
6621
|
### Added — 邮件投递通道
|
|
6609
6622
|
- 注册为 `email` messenger(`threadId` 即邮箱地址)
|
|
6610
|
-
- nodemailer + Gmail / QQ / 163 / 任意 SMTP(env:`
|
|
6623
|
+
- nodemailer + Gmail / QQ / 163 / 任意 SMTP(env:`AGIM_SMTP_HOST/PORT/USER/PASS/FROM/SECURE`)
|
|
6611
6624
|
- `/remind email <addr> <time> <text>` 内联 / `/remind bindemail` 绑定默认 / `/remind email <time> <text>` 走默认
|
|
6612
6625
|
- 邮件 + 循环 + LLM 润色组合自由
|
|
6613
6626
|
|
|
6614
6627
|
### Added — WeChat context_token 持久化
|
|
6615
6628
|
- iLink Bot API 30 分钟 context_token TTL 之前只存内存,重启即丢,导致循环提醒在 wechat 端高概率失败
|
|
6616
|
-
- 新 SQLite 表(`~/.
|
|
6629
|
+
- 新 SQLite 表(`~/.agim/wechat-context.db`),收消息时写穿,启动时 warm 内存 Map,cleanup 同步清 DB
|
|
6617
6630
|
|
|
6618
6631
|
### Schema migrations
|
|
6619
6632
|
新建 / 扩展三张表(在 `reminders.db` 内):
|
|
@@ -6642,7 +6655,7 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6642
6655
|
### Added — WeChat & Telegram rich media support
|
|
6643
6656
|
|
|
6644
6657
|
- **WeChat 图片 / 文件 / 语音 / 视频接收**:`handleIncomingMessage` 现在处理 iLink `item_list` 的全部 5 种类型(TEXT=1, IMAGE=2, VOICE=3, FILE=4, VIDEO=5),此前只处理 TEXT。
|
|
6645
|
-
- **图片**:通过 iLink CDN 下载到 `~/.
|
|
6658
|
+
- **图片**:通过 iLink CDN 下载到 `~/.agim/media/wechat/<userId>/`,转为 `[图片附件:/path]` 标记传递给 Agent
|
|
6646
6659
|
- **语音**:优先使用微信自带转写(`voice_item.text`),无转写时下载音频后走 OpenAI Whisper 或 whisper.cpp(复用 `src/core/transcribe.ts`)
|
|
6647
6660
|
- **文件**:下载并保留原始文件名,显示大小,转为 `[文件附件:/path (name, size)]`
|
|
6648
6661
|
- **视频**:下载并显示时长和大小,转为 `[视频附件:/path (duration, size)]`
|
|
@@ -6671,7 +6684,7 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6671
6684
|
- **审批总线 composite key 测试同步**:P0 #4 把 `ApprovalBus` 的内部 keying 从裸 threadId 改成 `platform:channelId:threadId`,但单元测试仍然按裸 `'thread-A'` 调 `hasPendingFor` / `resolvePending`,导致 `bun test` 红 37 项。所有相关测试(approval-bus、synthetic、router、approval 命令、mcp-approval、opencode-http、discord)改用 `threadKey()` 显式构造 composite,注释中误导性的 "backward compat" 承诺一并删除。
|
|
6672
6685
|
- **Claude session 标记顺序回归**:P1 #5 把 `markClaudeSessionPrimed` 从 `routeMessage` 之前挪到了之后;如果 claude 已写出 jsonl 但 run 中途出错,下一轮就会用 `--session-id` 而不是 `--resume`,触发 "session already exists"。0.2.33 把 markPrimed 移回 `onAgentResolved` 内部、紧跟 `setClaudeSessionId`,恢复"先 mark 再调 adapter"的语义。
|
|
6673
6686
|
- **Cookie 加固**:`web.public_bind_warning` 改在 server 启动时打一次(之前每次登录都打);`Set-Cookie` 在 public bind 或 `X-Forwarded-Proto: https` 时自动附加 `Secure`,纯 localhost dev 不加。
|
|
6674
|
-
- **静态页测试改写**:原 `/tasks` 用例还在断言 `
|
|
6687
|
+
- **静态页测试改写**:原 `/tasks` 用例还在断言 `AGIM_TOKEN` 注入到 HTML,改成走真实流程:未登录 302 到 `/login`,POST `/api/auth/login` 拿 cookie 后 200,断言 HTML 中不再含 token。
|
|
6675
6688
|
- **死代码清理**:`editCardOnThreadResolution` 的 thread-scan fallback 在 composite key 下永远 miss,删掉;签名从 `(threadId, info, decision, by)` 缩为 `(info, decision, by)`。
|
|
6676
6689
|
- **小项**:`web/server.ts` 删未使用的 `lstat` import;`settings.html` toast 调用末尾被误删的 `;` 补回。
|
|
6677
6690
|
- **测试 flake 修复**:`test/integration/acp-server.test.ts` 在全套并发下被 `intent.test.ts` 注册的空-yield 子代理污染(router intent fallback 到 opencode → 返回 '')。ACP 测试在 `beforeAll` 重新注册 4 个 profile 名同名 stub 让其也产出内容。
|
|
@@ -6687,8 +6700,8 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6687
6700
|
|
|
6688
6701
|
### Release
|
|
6689
6702
|
|
|
6690
|
-
- 重新发布生产硬化修复到 npm,确保生产环境通过 `npm install -g
|
|
6691
|
-
- 包含子任务会话隔离、WebSocket 入站串行化、session 元数据写锁、安全默认值加固、release/CI 门禁收紧,以及 `
|
|
6703
|
+
- 重新发布生产硬化修复到 npm,确保生产环境通过 `npm install -g agim@0.2.31` 可以拿到 v0.2.30 严格代码审查后的全部修复。
|
|
6704
|
+
- 包含子任务会话隔离、WebSocket 入站串行化、session 元数据写锁、安全默认值加固、release/CI 门禁收紧,以及 `agim --version` 跟随 `package.json` 的修复。
|
|
6692
6705
|
|
|
6693
6706
|
---
|
|
6694
6707
|
|
|
@@ -6701,10 +6714,10 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6701
6714
|
- **WebSocket 入站串行化**:Web Chat 同一浏览器连接上的多条消息按顺序逐条进入 `routeMessage`,降低快速连发时 Agent 子进程并行、历史乱序和流式回复交错风险。
|
|
6702
6715
|
- **Session 元数据写锁**:`patchSession`、usage roll-up、Claude/OpenCode/Codex session id setters、subtask counter/update、agent switch/reset 等读改写路径纳入 per-key lock;`nextSubtaskId` 并发调用保持唯一递增。
|
|
6703
6716
|
- **安全默认值**:
|
|
6704
|
-
- Web 控制台默认监听 `127.0.0.1`;需要对外暴露时显式设置 `
|
|
6705
|
-
- `~/.
|
|
6717
|
+
- Web 控制台默认监听 `127.0.0.1`;需要对外暴露时显式设置 `AGIM_WEB_BIND=0.0.0.0`,建议放在 HTTPS 反代后。
|
|
6718
|
+
- `~/.agim/config.json` 写入时强制 `0600`,目录创建使用 `0700`。
|
|
6706
6719
|
- Telegram 媒体下载的 `curl` 保留 `--location` 但加 `--max-redirs 0`,拒绝跟随重定向到任意主机。
|
|
6707
|
-
- **CLI 版本号**:`
|
|
6720
|
+
- **CLI 版本号**:`agim --version` 改为读取包内 `package.json`,不再硬编码旧值(之前可能输出 `0.2.18`)。
|
|
6708
6721
|
|
|
6709
6722
|
### Build / release
|
|
6710
6723
|
|
|
@@ -6720,38 +6733,38 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6720
6733
|
|
|
6721
6734
|
## [0.2.26] - 2026-05-08
|
|
6722
6735
|
|
|
6723
|
-
### Changed — Rebrand to `
|
|
6736
|
+
### Changed — Rebrand to `agim`
|
|
6724
6737
|
|
|
6725
|
-
- **npm 包名**:`
|
|
6726
|
-
- **CLI 命令**:`
|
|
6727
|
-
- **仓库 URL**:`package.json.repository.url` 从原作者 `ceociocto/
|
|
6728
|
-
- **Web 控制台品牌**:`/`、`/tasks`、`/settings` 三个静态页的浏览器标题、欢迎语、左上角 logo、Settings 卡里的 `
|
|
6729
|
-
- **README + README.zh-CN**:`What's new` / 安装命令 / Quick Start / CLI 命令表 / Project Structure ASCII 树标签,全部改为新品牌;新增「Migrating from `
|
|
6738
|
+
- **npm 包名**:`agim` → `agim`(产品化分支)。
|
|
6739
|
+
- **CLI 命令**:`agim` → `agim`(`bin` 字段同步更新)。
|
|
6740
|
+
- **仓库 URL**:`package.json.repository.url` 从原作者 `ceociocto/agim` 切到当前仓库 `benking007/agim`,新增 `homepage` / `bugs` / `publishConfig{access:public,provenance:true}` 字段。
|
|
6741
|
+
- **Web 控制台品牌**:`/`、`/tasks`、`/settings` 三个静态页的浏览器标题、欢迎语、左上角 logo、Settings 卡里的 `agim config wechat` 提示文案,全部改为 `agim`。
|
|
6742
|
+
- **README + README.zh-CN**:`What's new` / 安装命令 / Quick Start / CLI 命令表 / Project Structure ASCII 树标签,全部改为新品牌;新增「Migrating from `agim`」回退指引。
|
|
6730
6743
|
- **LICENSE 文件**:补齐 MIT 全文(之前 `package.json` 声明 MIT 但根目录无 LICENSE 文件),版权归属保持 `Jerry`。
|
|
6731
|
-
- **`THEME_KEY`**:localStorage 主题 key 从 `
|
|
6744
|
+
- **`THEME_KEY`**:localStorage 主题 key 从 `agim-theme` → `agim-theme`(用户在升级后第一次访问会丢失主题偏好;其他 localStorage key `agim-lang` / `agim-history` 保留以保住语言与对话历史)。
|
|
6732
6745
|
|
|
6733
6746
|
### Unchanged — drop-in compat
|
|
6734
6747
|
|
|
6735
|
-
为了让老用户 `npm uninstall -g
|
|
6736
|
-
- **配置目录**:`~/.
|
|
6737
|
-
- **环境变量**:60+ 处 `
|
|
6738
|
-
- **HTTP 头**:`X-
|
|
6739
|
-
- **Window 全局**:`window.
|
|
6740
|
-
- **ACP 服务名**:`
|
|
6741
|
-
- **MCP 测试 fixture**:`mcpServers.
|
|
6742
|
-
- **内部 client ID**:`
|
|
6748
|
+
为了让老用户 `npm uninstall -g agim && npm install -g agim` 后零迁移成本运行:
|
|
6749
|
+
- **配置目录**:`~/.agim/`、`~/.agim-workspaces/<agent>/` 路径不变
|
|
6750
|
+
- **环境变量**:60+ 处 `AGIM_*` 前缀不变
|
|
6751
|
+
- **HTTP 头**:`X-Agim-Token` / `x-agim-token` 不变
|
|
6752
|
+
- **Window 全局**:`window.AGIM_TOKEN` 不变
|
|
6753
|
+
- **ACP 服务名**:`agim-gateway` 不变(线上 ACP 客户端通过这个名字 discover)
|
|
6754
|
+
- **MCP 测试 fixture**:`mcpServers.agim` 不变
|
|
6755
|
+
- **内部 client ID**:`agim:${ts}` 格式不变
|
|
6743
6756
|
|
|
6744
6757
|
### Notes
|
|
6745
6758
|
|
|
6746
|
-
- 发布走 npm OIDC trusted publishing(`release.yml` 不需要改),首次发布前需在 npmjs.com 上为 `
|
|
6747
|
-
- 老 `
|
|
6759
|
+
- 发布走 npm OIDC trusted publishing(`release.yml` 不需要改),首次发布前需在 npmjs.com 上为 `agim` 配置 trusted publisher 指向 `benking007/agim` 仓库 + `release.yml` workflow。
|
|
6760
|
+
- 老 `agim@0.2.25` 包在 npmjs.com 上保持不动,可继续安装。
|
|
6748
6761
|
|
|
6749
6762
|
---
|
|
6750
6763
|
|
|
6751
6764
|
## [0.2.23] - 2026-05-07
|
|
6752
6765
|
|
|
6753
6766
|
### Added — Web console PR-D
|
|
6754
|
-
- **Agent workspace 文件浏览器**:`/tasks` 新增 **Files** tab,只读浏览 `~/.
|
|
6767
|
+
- **Agent workspace 文件浏览器**:`/tasks` 新增 **Files** tab,只读浏览 `~/.agim-workspaces/<agent>/`(CLAUDE.md / AGENTS.md / 临时笔记等)。左侧目录树 + 右侧文件预览,点目录进入、点文件预览,文件 1 MiB 上限 + 二进制(首 8 KB NUL 探测)走 base64。后端 `GET /api/workspace-files?agent=&path=` 双重防 traversal:agent 必须在 `registry.listAgents()` 白名单,路径必须等于或位于 `defaultAgentCwd(agent)` base 之下,否则 400。
|
|
6755
6768
|
- **Job 批量操作**:Jobs tab 加多选 checkbox + 全选表头 + 隐藏式批量工具栏(Run selected / Cancel selected);选中态跨刷新保留——按可见行 reconcile,不会被 list mutation 抹掉。后端新 `POST /api/jobs/batch-cancel` / `batch-run` 接受 `{ ids: number[] }`(最多 100),per-id 结果不互相阻断。
|
|
6756
6769
|
|
|
6757
6770
|
### Changed
|
|
@@ -6764,7 +6777,7 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6764
6777
|
- **SSE 实时事件流**:新建 `src/core/event-bus.ts`——进程内 publish/subscribe,4 类事件(`audit` / `approval` / `job` / `metrics`),200 条 ring buffer。新连接 replay 一次避免空白等待。
|
|
6765
6778
|
- **`GET /events` 端点**:token 走 `?token=...`(EventSource 不支持自定义 header),25s 心跳防 nginx idle close,listener 错误在 `publish()` 内吞掉避免拖坏起源动作。
|
|
6766
6779
|
- **Dashboard 实时刷新**:`tasks.html` 用 `EventSource('/events?token=...')`,事件触发 `refreshIfVisible(paneId, loader)` 只刷可见 tab;轮询保留作为 fallback。`approval requested` 事件让 Approvals tab 标签闪一下高亮(动态注入的 CSS keyframe)。
|
|
6767
|
-
- **Workspace 完整 CRUD UI**:`settings.html` 新增 Workspaces 卡片,列表 + 新增 / 编辑 / 删除表单(id 锁定防误改、default 行不可删)。后端 `GET /api/workspaces?full=1` / `POST` upsert / `PATCH /:id` / `DELETE /:id`,每次 mutation persist 回 `~/.
|
|
6780
|
+
- **Workspace 完整 CRUD UI**:`settings.html` 新增 Workspaces 卡片,列表 + 新增 / 编辑 / 删除表单(id 锁定防误改、default 行不可删)。后端 `GET /api/workspaces?full=1` / `POST` upsert / `PATCH /:id` / `DELETE /:id`,每次 mutation persist 回 `~/.agim/config.json`。
|
|
6768
6781
|
- `WorkspaceRegistry.remove(id)` 拒绝 `'default'`,`listFull()` 返回完整 `WorkspaceConfig[]`(含 member ids)。
|
|
6769
6782
|
|
|
6770
6783
|
## [0.2.21] - 2026-05-07
|
|
@@ -6778,7 +6791,7 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6778
6791
|
|
|
6779
6792
|
### Added — Web console PR-A
|
|
6780
6793
|
- **三态主题**:light / dark / system 三档循环切换,按钮在 head 加载完前同步应用 `:root[data-theme]`,避免主题闪烁。`prefers-color-scheme: dark` 仅在 `data-theme` 缺失(system 模式)时生效。语言 + 主题偏好都落在 localStorage。
|
|
6781
|
-
- **错误边界**:新建 `src/web/public/_app.js`——`window.
|
|
6794
|
+
- **错误边界**:新建 `src/web/public/_app.js`——`window.agim` 命名空间提供 `theme` / `i18n` / `api` / `showError`,自动安装 `window.onerror` + `unhandledrejection` 监听,让脚本错误以浮层形式可见,不再静默死掉。
|
|
6782
6795
|
- **In-chat 审批卡**:`/` 聊天界面收到工具审批请求时弹出 inline 卡片(Allow / Deny / Allow + Auto),点击通过 WS `approval-action` 走回 `approvalBus.resolvePending()`,跟 Telegram inline-button 同一条路径。
|
|
6783
6796
|
- `approval-router` 默认 `buttonCallbackPlatforms` 加 `'discord'` / `'web'`;新导出 `bindButtonHandlerForPlatform(platform)` 给延迟注册的 messenger(web 是其中之一)调用,避免 install-before-register 时序问题。
|
|
6784
6797
|
|
|
@@ -6820,7 +6833,7 @@ opencode http adapter 的 `buildImContextInstruction` system prompt 之前只提
|
|
|
6820
6833
|
### Fixed — P2 web/HTTP hardening
|
|
6821
6834
|
- **M1** 静态页响应头:`X-Frame-Options: DENY` / `X-Content-Type-Options: nosniff` / `Referrer-Policy: no-referrer` / Content-Type 加 `charset=utf-8` / CSP 锁第三方资源(`script-src` / `style-src` 暂留 `'unsafe-inline'`,nonce 化留 P3)。
|
|
6822
6835
|
- **M2** Prometheus 标签基数白名单:`KNOWN_INTENTS = {default,explicit,fallback,llm,topic,keyword,sticky}`、`KNOWN_PLATFORMS = {telegram,feishu,wechat,discord,web,acp,acp-server,rest,rest-msg}`,命中外的桶到 `'other'`。
|
|
6823
|
-
- **M3** WS 连接上限:默认 100,env `
|
|
6836
|
+
- **M3** WS 连接上限:默认 100,env `AGIM_MAX_WS_CLIENTS` 覆盖;超限时 `1013 Try Again Later`。
|
|
6824
6837
|
- **M4** `/api/health` 改为 token gate 之前公开(k8s liveness 友好)。
|
|
6825
6838
|
- **M11** ACP 测试入口的 `JSON.parse` 包 `try/catch` + endpoint 类型校验,错误 body 落 400 而非 500。
|
|
6826
6839
|
|
|
@@ -6863,21 +6876,21 @@ P0 + P1 安全收口,配 `docs/code-review-2026-05-06-main.md`。
|
|
|
6863
6876
|
|
|
6864
6877
|
### Fixed — P0 hotfix
|
|
6865
6878
|
- **H1** Web REST/WS token 比较切到 `crypto.timingSafeEqual`,抽 `src/utils/safe-equal.ts` 与 `acp-server.ts` 共用。
|
|
6866
|
-
- **H2** `serveIndexHtml` 用 `JSON.stringify(token)` 注入 `window.
|
|
6867
|
-
- **H3** Schedule `notify_url` SSRF 防护:`validateWebhookUrl` 白名单 `http(s)`、黑名单 RFC1918 / loopback / link-local / CGNAT / IPv6 ULA / fe80::;`
|
|
6879
|
+
- **H2** `serveIndexHtml` 用 `JSON.stringify(token)` 注入 `window.AGIM_TOKEN`,防 token 含 `'` / `</script>` 破坏 JS 字面量。
|
|
6880
|
+
- **H3** Schedule `notify_url` SSRF 防护:`validateWebhookUrl` 白名单 `http(s)`、黑名单 RFC1918 / loopback / link-local / CGNAT / IPv6 ULA / fe80::;`AGIM_ALLOW_PRIVATE_WEBHOOKS=1` 显式 opt-in;fetch 加 10s `AbortSignal` + `redirect: 'manual'` + 64 KiB 响应上限;`createSchedule` 与 `fireSchedule` 双层校验。
|
|
6868
6881
|
- **H8** `settings.html` ACP 测试按钮:原代码 `const res` 重复声明 + 引用未定义 `endpoint`/`auth`,整页脚本 SyntaxError,功能必坏。改读 `agent.endpoint` / `agent.auth`。
|
|
6869
|
-
- **H10** Telegram bot token 不再随错误日志泄露:`logger.ts` 加 `redact.paths`(`*.token` / `*.botToken` / `*.apiKey` / `headers.authorization` / `x-
|
|
6882
|
+
- **H10** Telegram bot token 不再随错误日志泄露:`logger.ts` 加 `redact.paths`(`*.token` / `*.botToken` / `*.apiKey` / `headers.authorization` / `x-agim-token` 等);图片 / 语音下载 catch 路径用本地 `scrub()` 把 token 字面量替换 `[REDACTED]`,覆盖 curl stderr 带回 URL 的场景。
|
|
6870
6883
|
|
|
6871
6884
|
### Fixed — P1 runtime hardening
|
|
6872
6885
|
- **H4** `RateLimiter` bucket 无界:`allow()` 内置 `maybeSweep`,每 30 min 机会式触发 cleanup(不引入 `setInterval` timer);新增 `size()` 诊断访问器。
|
|
6873
|
-
- **H6** Job result 大小:`resolveMaxResultBytes()` 默认 1 MiB,env `
|
|
6886
|
+
- **H6** Job result 大小:`resolveMaxResultBytes()` 默认 1 MiB,env `AGIM_JOB_RESULT_MAX_BYTES` 覆盖;超过 cap 整 chunk 丢弃(边界落在 UTF-8/JSON 事件分隔上),尾部拼 truncation footer,落 warn `event: 'job.result.truncated'`。
|
|
6874
6887
|
- **H9** WeChat 凭证文件权限:`saveCredentials` 用 `mkdir(.., {mode:0o700})` + `writeFile(.., {mode:0o600})`;`loadCredentials` 读时 `stat`,松权落 warn 提示用户 `chmod 600`(不主动改老文件)。
|
|
6875
6888
|
- **H11** Approval socket 路径熵 + 权限:`defaultSocketPath` 改用 `randomBytes(16).toString('hex')`(128 位熵),listen 后 `chmod 0o600` + `stat` 验证;防同主机非特权用户预占 socket 的 TOCTOU。
|
|
6876
6889
|
- **H12** `Session.addMessage` 并发:`SessionManager` 加 `writeQueues<key, Promise>` + `withLock<T>(key, fn)`,per-key 串行化 RMW,跨 thread 仍并行。
|
|
6877
6890
|
|
|
6878
6891
|
### Fixed — P1 multi-tenant ACL
|
|
6879
6892
|
- **H5** `/job` `/schedule` `/audit` 命令补 owner 隔离:`jobs` / `schedules` 表加 `creator_id` / `workspace_id`(幂等 `ALTER TABLE`,老库无痛升级);`createJob` / `createSchedule` 接 `{ creatorId, workspaceId }` 由 handler 注入;查询/取消/删/启停加 `OwnerOpts`,`creator_id = ? OR creator_id = ''`(老库 `''` 对所有 owner 可见,避免升级当天列表看似消失);`/audit user=<other>` 强制 overwrite 到 `ctx.userId`,结果末尾追加忽略提示。
|
|
6880
|
-
- **H7** Job 表 retention:`resolveRetentionDays()` 默认 30 天,env `
|
|
6893
|
+
- **H7** Job 表 retention:`resolveRetentionDays()` 默认 30 天,env `AGIM_JOB_RETENTION_DAYS` 覆盖;`pruneOldJobs()` 删 `completed`/`failed`/`cancelled` 超期行,`pending`/`running` 永不修剪;启动跑一次 + 每 6h `setInterval(..unref())`;新增 `idx_jobs_created` / `idx_jobs_creator` / `idx_jobs_status_created` 索引。
|
|
6881
6894
|
- **M6** Workspace 白名单从路由层下沉到命令层:`/job create <agent>` 与 `/schedule create <agent>` 在 `createJob` / `createSchedule` 之前调 `workspaceRegistry.resolve(ctx.userId).hasAgent(agent.name)`。
|
|
6882
6895
|
|
|
6883
6896
|
### Tests
|
|
@@ -6896,13 +6909,13 @@ P0 + P1 安全收口,配 `docs/code-review-2026-05-06-main.md`。
|
|
|
6896
6909
|
|
|
6897
6910
|
### Added
|
|
6898
6911
|
- **Discord messenger adapter** — full IM bridge for Discord (Gateway WebSocket via `discord.js`)
|
|
6899
|
-
- `
|
|
6912
|
+
- `agim config discord` interactive setup wizard
|
|
6900
6913
|
- Typing indicator (10s TTL, 8s refresh)
|
|
6901
6914
|
- Markdown → Discord-flavored format conversion
|
|
6902
6915
|
- Guild / Channel whitelist filtering
|
|
6903
6916
|
- Setup guide: [`docs/discord-setup.md`](docs/discord-setup.md)
|
|
6904
6917
|
- **Tasks dashboard upgrades** — `/tasks` page now surfaces background work
|
|
6905
|
-
- **Background tab**: lists `~/.claude/bgjobs` + `~/.config/opencode/bgjobs` jobs (override via `
|
|
6918
|
+
- **Background tab**: lists `~/.claude/bgjobs` + `~/.config/opencode/bgjobs` jobs (override via `AGIM_BGJOB_ROOTS`); per-root selector, 5s auto-refresh, detail modal with `cmd` / `workdir` / `log_tail`
|
|
6906
6919
|
- **Subtasks tab**: flattens every subtask in every session file, with parent platform / threadId / agent attached
|
|
6907
6920
|
- Bilingual labels (EN + ZH)
|
|
6908
6921
|
- **REST endpoints (read-only)**:
|
|
@@ -6927,8 +6940,8 @@ P0 + P1 安全收口,配 `docs/code-review-2026-05-06-main.md`。
|
|
|
6927
6940
|
- Replaces the legacy `--permission-mode dontAsk + blanket-allow PreToolUse hook` shortcut with a real approval flow over IM.
|
|
6928
6941
|
- Architecture:
|
|
6929
6942
|
```
|
|
6930
|
-
claude --permission-prompt-tool
|
|
6931
|
-
└─> MCP sidecar (mcp-approval-server.ts) ── unix socket ──>
|
|
6943
|
+
claude --permission-prompt-tool mcp__agim__request --mcp-config <tmp>
|
|
6944
|
+
└─> MCP sidecar (mcp-approval-server.ts) ── unix socket ──> agim
|
|
6932
6945
|
└─> approval-bus
|
|
6933
6946
|
└─> approval-router → messenger.sendMessage
|
|
6934
6947
|
↑
|
|
@@ -6936,7 +6949,7 @@ P0 + P1 安全收口,配 `docs/code-review-2026-05-06-main.md`。
|
|
|
6936
6949
|
```
|
|
6937
6950
|
- cli intercepts approval replies *before* the agent router; unrecognized replies during a pending request auto-deny so the sidecar (and Claude) don't hang.
|
|
6938
6951
|
- Per-spawn state lives in the `SpawnPlan` returned by `AgentBase.prepareCommand` (closure-local, not `this.*`) — fixes a singleton race where parallel IM threads running claude clobbered each other's `mcp-config` and the second run died with *MCP config file not found*.
|
|
6939
|
-
- Graceful fallbacks: `
|
|
6952
|
+
- Graceful fallbacks: `AGIM_APPROVAL_DISABLED=1`, missing IM context, approval-bus not started, or `mkdtemp/writeFile` failure all degrade to the legacy `--permission-mode dontAsk` path.
|
|
6940
6953
|
|
|
6941
6954
|
### Notes
|
|
6942
6955
|
- Approvals are platform-agnostic — the same chain works for WeChat / Telegram / Feishu / Discord with no per-platform changes.
|
|
@@ -6954,7 +6967,7 @@ A large multi-phase release: structured logging, observability, multi-tenant rou
|
|
|
6954
6967
|
- **Zod config schema validation** at startup and PUT `/api/config` — invalid configs reject with a useful error instead of crashing the bridge mid-run.
|
|
6955
6968
|
- **`AgentBase` abstraction** for CLI-based adapters (claude-code / codex / copilot / opencode) — shared spawn-stream, abort/timeout, line buffer, error formatting, healthCheck. ADR: [`docs/adr/0001-agent-base-abstraction.md`](docs/adr/0001-agent-base-abstraction.md).
|
|
6956
6969
|
- **Agent availability TTL cache** on top of `healthCheck` — avoids spawning a probe process on every `/<agent>` switch.
|
|
6957
|
-
- **Audit log** with SQLite (`~/.
|
|
6970
|
+
- **Audit log** with SQLite (`~/.agim/audit.db`, 30-day retention) + `/audit [n]` chat command.
|
|
6958
6971
|
|
|
6959
6972
|
#### Fixed
|
|
6960
6973
|
- P0 batch: WebSocket auth, nested config-mask leaks, timeout coercion, `/api/notify` token validation, agent-name prefix collisions, session path traversal (ADR [`0003`](docs/adr/0003-session-path-safety.md)).
|
|
@@ -6975,10 +6988,10 @@ A large multi-phase release: structured logging, observability, multi-tenant rou
|
|
|
6975
6988
|
### Phase 3 — ACP server, workspaces, persistent jobs
|
|
6976
6989
|
|
|
6977
6990
|
#### Added
|
|
6978
|
-
- **ACP server mode** —
|
|
6991
|
+
- **ACP server mode** — agim itself is now an ACP-compatible agent at `POST /tasks` (sync + SSE) with timing-safe auth and a 1 MiB body cap.
|
|
6979
6992
|
- **`/.well-known/acp` discovery** for ACP custom agents (A-1).
|
|
6980
6993
|
- **Multi-tenant workspace registry** (`src/core/workspace.ts`) with per-workspace agent whitelist + rate limits + member lists.
|
|
6981
|
-
- **Persistent Job Board** with SQLite (`~/.
|
|
6994
|
+
- **Persistent Job Board** with SQLite (`~/.agim/jobs.db`) and `/job` chat commands — survives restarts; ACP-server tasks become durable jobs.
|
|
6982
6995
|
- **Subtask sessions** + `/task` aliases for backward compatibility.
|
|
6983
6996
|
- **`AbortController` signal** plumbed through job board for real cancellation (Phase 3.5).
|
|
6984
6997
|
- **Cron scheduler** (`src/core/schedule.ts`) — 30-second tick, fires registered job specs.
|