qi-coding-agent 0.1.1__tar.gz → 0.2.1__tar.gz
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.
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/PKG-INFO +4 -2
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/README.md +3 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/design/development.md +8 -3
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/design/extensions-design.md +2 -2
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/design/overview.md +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/design/pi-alignment.md +2 -2
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/design/plugins.md +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/cli.md +11 -2
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/configuration.md +2 -2
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/extensions.md +5 -5
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/keybindings.md +1 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/models.md +7 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/packages.md +53 -38
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/sessions.md +3 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/slash-commands.md +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/extensions/README.md +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/extensions/hello/README.md +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-agents/README.md +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-agents/pyproject.toml +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-mcp/README.md +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-mcp/pyproject.toml +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/README.md +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/pyproject.toml +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/qi_web/serve.py +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/pyproject.toml +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/__init__.py +1 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/auth.py +39 -3
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/cli.py +211 -57
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/llm.py +37 -3
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/packages.py +106 -19
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/paths.py +2 -2
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/registry.py +17 -18
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/runtime.py +18 -21
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/settings.py +16 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/system_prompt.py +9 -3
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/tui.py +52 -6
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/conftest.py +1 -1
- qi_coding_agent-0.2.1/tests/test_auth_key.py +96 -0
- qi_coding_agent-0.2.1/tests/test_cli_install.py +479 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_entry_points.py +49 -6
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_missing_extension_hints.py +14 -37
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_packages.py +10 -1
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_system_prompt.py +9 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_trust_scope.py +11 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_tui_no_model.py +33 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_tui_style.py +30 -0
- qi_coding_agent-0.1.1/tests/test_cli_install.py +0 -236
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/.github/workflows/publish.yml +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/.gitignore +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/.pi-lens.json +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/LICENSE +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/THIRD_PARTY_NOTICES.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/design/PLAN.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/design/agent-config-design.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/design/bash-allowlist.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/design/dispatcher.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/design/internals.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/design/web.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/compaction.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/containerization.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/docs.json +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/environment-variables.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/how-qi-works.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/index.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/json.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/providers.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/quickstart.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/security.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/session-format.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/settings.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/skills.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/themes.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/tui.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/docs/usage.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/agents/README.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/agents/code-analyst/agent.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/agents/code-analyst/assets/review-rules.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/agents/code-analyst/mcp.json +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/agents/code-analyst/skills/code-review-checklist/SKILL.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/agents/code-reviewer/agent.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/agents/data-analyst/agent.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/agents/doc-writer/agent.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/agents/doc-writer/assets/doc-style.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/agents/general/agent.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/agents/test-runner/agent.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/agents/writer/agent.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/examples/extensions/hello/extension.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-agents/qi_agents/__init__.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-agents/qi_agents/discovery.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-agents/qi_agents/subagent.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-mcp/qi_mcp/__init__.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-mcp/qi_mcp/client.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-mcp/qi_mcp/config.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-mcp/qi_mcp/direct.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-mcp/qi_mcp/proxy.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-mcp/qi_mcp/role.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-mcp/qi_mcp/servers.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/qi_web/__init__.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/qi_web/agui.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/qi_web/app.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/qi_web/browse.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/qi_web/files.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/qi_web/schemas.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/qi_web/security.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/qi_web/state.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/qi_web/static/assets/index-96aT_6NK.js +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/qi_web/static/assets/index-DePFgopp.css +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/qi_web/static/index.html +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/index.html +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/package-lock.json +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/package.json +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/scripts/check-design.mjs +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/scripts/check-dsh-tokens.mjs +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/App.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/api/client.test.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/api/client.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/api/contract.test.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/api/types.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/commands.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/AgentMenu.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/CommandMenu.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/ConfirmDialog.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/DirPicker.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/Dock.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/FilePanel.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/ModelMenu.test.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/ModelMenu.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/ProjectMenu.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/Rail.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/RowMenu.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/Rows.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/Settings.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/SidebarSection.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/components/icons.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/main.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/markdown/cjk.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/markdown/markdown.test.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/markdown/parse.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/markdown/render.tsx +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/state/projects.test.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/state/projects.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/state/route.test.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/state/route.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/state/stats.test.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/state/stats.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/state/turn.test.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/state/turn.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/theme/app.css +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/theme/theme.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/theme/tokens.css +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/src/vite-env.d.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/tsconfig.json +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/vite.config.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/extensions/qi-web/ui/vitest.config.ts +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/pyrightconfig.json +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/scripts/check_versions.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/scripts/e2e_ui_model.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/scripts/prune_empty_sessions.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/abort.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/compaction.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/config.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/export_html.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/extensions.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/loader.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/model_catalog.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/models.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/pep723.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/presets.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/prompt.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/runner.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/session.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/share.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/theme.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/themes/README.md +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/themes/dark.json +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/themes/light.json +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/titling.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/tools/__init__.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/tools/shell.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/trust.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/src/qi_agent/workspaces.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_branch_summary_prompt.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_browse.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_cli_init.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_cli_pi_alignment.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_cli_run.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_cli_tool_flags.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_compaction.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_compaction_events.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_config.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_config_resources.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_contract_p0.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_docs_injection.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_doctor_extensions.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_example_extension.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_export_html.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_alignment.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_bus.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_cli_commands.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_commands.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_deps.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_events.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_exclusions.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_flags.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_interop.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_messages.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_model.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_resolvers.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_run_agent.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_runner_events.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_session.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_tools.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extension_ui.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_extensions.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_interrupt.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_litellm_offline.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_model_catalog.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_model_thinking_levels.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_package_resource_toggle.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_pep723.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_presets.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_prune_empty_sessions.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_qi_agents_extension.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_qi_mcp_config.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_qi_mcp_direct.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_qi_mcp_http.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_qi_mcp_proxy.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_qi_mcp_role.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_qi_mcp_stdio.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_runner_core.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_session_model_entries.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_session_store.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_session_tree.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_settings_skills.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_share.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_shell.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_skill_commands.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_streaming.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_theme.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_thinking.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_thinking_budgets.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_third_party_notices.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_titling.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_tool_execution_mode.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_tui_extension_render.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_tui_model_restore.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_tui_smoke.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_web_api.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_web_extensions_api.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_web_files.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/tests/test_workspaces.py +0 -0
- {qi_coding_agent-0.1.1 → qi_coding_agent-0.2.1}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: qi-coding-agent
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: 编码 agent 框架:单 agent core + 扩展(MCP / 多 agent / web)
|
|
5
5
|
Project-URL: Homepage, https://github.com/viewnah/qi
|
|
6
6
|
Project-URL: Repository, https://github.com/viewnah/qi
|
|
@@ -61,6 +61,7 @@ qi doctor # 冒烟:配置 / 凭证 / 扩展 / 包声
|
|
|
61
61
|
第一次用,**在界面里两步**就能跑起来:
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
|
+
cd /path/to/folder # 先切到你要处理的项目目录(qi 的工作目录 = 启动时的目录)
|
|
64
65
|
qi # 裸 qi 就是界面(装完直接敲)
|
|
65
66
|
```
|
|
66
67
|
|
|
@@ -69,6 +70,7 @@ qi # 裸 qi 就是界面(装完直接敲)
|
|
|
69
70
|
```text
|
|
70
71
|
/login # 选 provider(预置都在列表里)→ 遮罩输入 API key → 写 ~/.qi/agent/auth.json
|
|
71
72
|
/model # 选模型(只列解析得出凭证的;刚才没有模型时 /login 会顺带选中第一个)
|
|
73
|
+
# 选择器里按 ctrl+s = **存为默认**;不按就只对本次会话生效
|
|
72
74
|
```
|
|
73
75
|
|
|
74
76
|
然后直接说你要做什么。三种跑法:
|
|
@@ -103,7 +105,7 @@ qi 的能力可以按需加装 —— 命令、快捷键、工具、事件钩子
|
|
|
103
105
|
qi install <来源> [-l] # 装:调 pip(本地目录只登记)+ 把声明写进 settings.packages(带 -l 写项目)
|
|
104
106
|
qi list # 看装了哪些(含目录通道),并与声明双向比对
|
|
105
107
|
qi doctor # 「声明了没装」「装了没声明」都报出来,并给出可复制的装法
|
|
106
|
-
qi remove <来源> #
|
|
108
|
+
qi remove <来源> # 移除声明;没有别的作用域还声明它就连包一起卸(--force 强制卸)
|
|
107
109
|
qi -e <目录> # 本次运行临时加载一个扩展目录(TUI 与无头都生效,只本进程)
|
|
108
110
|
```
|
|
109
111
|
|
|
@@ -31,6 +31,7 @@ qi doctor # 冒烟:配置 / 凭证 / 扩展 / 包声
|
|
|
31
31
|
第一次用,**在界面里两步**就能跑起来:
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
+
cd /path/to/folder # 先切到你要处理的项目目录(qi 的工作目录 = 启动时的目录)
|
|
34
35
|
qi # 裸 qi 就是界面(装完直接敲)
|
|
35
36
|
```
|
|
36
37
|
|
|
@@ -39,6 +40,7 @@ qi # 裸 qi 就是界面(装完直接敲)
|
|
|
39
40
|
```text
|
|
40
41
|
/login # 选 provider(预置都在列表里)→ 遮罩输入 API key → 写 ~/.qi/agent/auth.json
|
|
41
42
|
/model # 选模型(只列解析得出凭证的;刚才没有模型时 /login 会顺带选中第一个)
|
|
43
|
+
# 选择器里按 ctrl+s = **存为默认**;不按就只对本次会话生效
|
|
42
44
|
```
|
|
43
45
|
|
|
44
46
|
然后直接说你要做什么。三种跑法:
|
|
@@ -73,7 +75,7 @@ qi 的能力可以按需加装 —— 命令、快捷键、工具、事件钩子
|
|
|
73
75
|
qi install <来源> [-l] # 装:调 pip(本地目录只登记)+ 把声明写进 settings.packages(带 -l 写项目)
|
|
74
76
|
qi list # 看装了哪些(含目录通道),并与声明双向比对
|
|
75
77
|
qi doctor # 「声明了没装」「装了没声明」都报出来,并给出可复制的装法
|
|
76
|
-
qi remove <来源> #
|
|
78
|
+
qi remove <来源> # 移除声明;没有别的作用域还声明它就连包一起卸(--force 强制卸)
|
|
77
79
|
qi -e <目录> # 本次运行临时加载一个扩展目录(TUI 与无头都生效,只本进程)
|
|
78
80
|
```
|
|
79
81
|
|
|
@@ -16,7 +16,7 @@ uv sync
|
|
|
16
16
|
`uv sync` 会把 **qi 本体装成 editable**(`.venv/lib/python3.12/site-packages/_editable_impl_qi_agent.pth`)
|
|
17
17
|
并装上 dev 依赖(`pytest` / `pytest-asyncio`)。
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
**三个扩展要单独装**——它们各自是独立 pip 包,而仓库**没有配 uv workspace**(故意的:core 不该
|
|
20
20
|
默认拖上 MCP / FastAPI 那些依赖):
|
|
21
21
|
|
|
22
22
|
```bash
|
|
@@ -26,6 +26,11 @@ pip install -e extensions/qi-agents -e extensions/qi-mcp -e extensions/qi-web
|
|
|
26
26
|
|
|
27
27
|
不装也能跑测试(见 §3);但要在开发机上**手工验证扩展行为**,这三个装上是必须的。
|
|
28
28
|
|
|
29
|
+
> **还要声明它们才会加载** —— pip 通道的 entry point 只有在 `settings.packages` 里
|
|
30
|
+
> 声明过才装载(对齐 pi)。editable 装完再把名字写进 `~/.qi/agent/settings.json`(或项目
|
|
31
|
+
> `.qi/settings.json`)的 `packages`,例如 `"packages": ["qi-mcp", "qi-agents", "qi-web"]`;
|
|
32
|
+
> `qi list` 会把没声明的列在「已装但未声明」。
|
|
33
|
+
|
|
29
34
|
## 2. 从源码跑
|
|
30
35
|
|
|
31
36
|
```bash
|
|
@@ -52,7 +57,7 @@ uv run pytest -q # 等价写法
|
|
|
52
57
|
`tests/conftest.py` 里有一个 autouse 夹具,把 `qi.extensions` 这组 entry point **stub 成空**。
|
|
53
58
|
理由写在那里的注释里,值得抄一遍:
|
|
54
59
|
|
|
55
|
-
>
|
|
60
|
+
> 三个扩展一旦 `pip install -e` 装上(开发机上很常见),entry point 就会在每个测试的 runtime
|
|
56
61
|
> 里被装载 —— 于是**测试结果取决于这台机器上装了什么**。那种漂移最难查:同一条测试在你这里是
|
|
57
62
|
> 绿的、在 CI 上也是绿的,只是因为它们测的不是同一件事。
|
|
58
63
|
|
|
@@ -146,7 +151,7 @@ uv build --out-dir dist && uv build extensions/qi-mcp --out-dir dist \
|
|
|
146
151
|
- **打 tag 发布**:`git tag v0.1.0 && git push origin v0.1.0` → 构建 + 发布到 **PyPI**;
|
|
147
152
|
- **手动触发**:Actions → publish → Run workflow,两个输入:
|
|
148
153
|
- `target`:`testpypi`(默认,试跑)/ `pypi`;
|
|
149
|
-
- `packages`:**`core`(默认,只发 `qi-coding-agent`)** / `all`(
|
|
154
|
+
- `packages`:**`core`(默认,只发 `qi-coding-agent`)** / `all`(连三个扩展一起发)。
|
|
150
155
|
选 `core` 时版本检查只核 core(四个锁步那条不适用);扩展还没发布时保持默认。
|
|
151
156
|
- **action 全部按 commit SHA 固定**(发布 job 持有 PyPI 权限,不吃可变 tag),并关掉 uv 缓存
|
|
152
157
|
(`cache-poisoning`)、`checkout` 不带 git 凭证(`persist-credentials: false`);
|
|
@@ -309,7 +309,7 @@ qi-agents(唯一知道角色目录的人)
|
|
|
309
309
|
|
|
310
310
|
### A1. 兼容与迁移(一刀切)
|
|
311
311
|
|
|
312
|
-
已定:不保留"
|
|
312
|
+
已定:不保留"扩展自动装载"。`qi web`、`.qi/agents/`、`mcp.json` 都要求**显式装扩展**。
|
|
313
313
|
|
|
314
314
|
#### A1.1 具体后果清单
|
|
315
315
|
|
|
@@ -357,7 +357,7 @@ qi-agents(唯一知道角色目录的人)
|
|
|
357
357
|
| E22 | MCP 工具命名 | **`mcp__<server>__<tool>`**(Claude Code 约定),角色白名单支持 `mcp__<server>__*` 通配。理由:不撞名、可前缀过滤,且“角色只拿某 server 的工具”只能靠通配写 |
|
|
358
358
|
| E23 | MCP 的接口归属 | qi-mcp 的接口(配置层级 / scope 交接 / 工具命名)**全属 qi 自己的决定**,不照搬任何现成形状 |
|
|
359
359
|
| E24 | MCP 工具的暴露方式 | **代理兜底 + 白名单驱动直连**。主会话只给一个 `mcp` 代理工具(~200 token);角色的 `tools:` 里写了 `mcp__github__*` → 对**那个角色**直连匹配的工具、**且不给代理**;没写任何 mcp 条目 → 该角色**完全没有** MCP 访问。**否掉了“代理默认 + `directTools`”**:代理能调**任何** server 的工具,于是角色的 `tools:` 白名单限制不了 MCP —— 而“角色 = 精确的工具范围”是本仓的核心语义,白名单形同虚设是最忌的半对齐。**代价**:两种模式并存 **→ 已由 E25 取代** |
|
|
360
|
-
| E25 | qi-mcp 的形状与依赖方向(取代 E20/E24) | **qi-agents 直接依赖 qi-mcp;agent 层的 MCP 发现归 qi-agents**。理由:① agent 目录是 qi-agents 的**自包含包**,包主人认识包成员不是泄漏;② E24 的白名单顾虑在新形状下**前提消失**(角色的 server 集合本就按需注册);③ 少一层自造协议。代价:`
|
|
360
|
+
| E25 | qi-mcp 的形状与依赖方向(取代 E20/E24) | **qi-agents 直接依赖 qi-mcp;agent 层的 MCP 发现归 qi-agents**。理由:① agent 目录是 qi-agents 的**自包含包**,包主人认识包成员不是泄漏;② E24 的白名单顾虑在新形状下**前提消失**(角色的 server 集合本就按需注册);③ 少一层自造协议。代价:`qi install qi-agents` 会拖上 MCP 栈;角色 `tools:` 对 MCP 的语义与内置工具不一致(要写进角色文档) |
|
|
361
361
|
| E26 | 扩展 API 的命名与参数形状 | **snake_case 是正式名,驼峰是别名**(两者绑定同一个函数对象,`api.registerTool is api.register_tool`);**参数形状两边都收**(options 对象与关键字写法)。事件名、`ctx` 成员名、`ctx.ui` 方法名同样双名。事件 payload 的**键名仍用 snake_case**、不发 `type` 判别字段(见 §12)。理由:两套写法都成立,外来扩展不必改写;代价只是多一层薄别名。**已知尾巴**:`deliver_as` 取值用 `follow_up`/`next_turn`,驼峰别名 `followUp`/`nextTurn` 也认 |
|
|
362
362
|
| E27 | `executionMode` 的并发语义 | **逐工具声明,默认顺序(不声明 = 与以前逐字节一致)**;**相邻**的 `"parallel"` 工具并成一批并发跑,一个顺序工具把批次**打断**(顺序工具永不与并行工具重叠);**并发安全由声明方负责**(写 `"parallel"` 等于说“我的实现是并发安全的”,qi 不做文件变更队列);事件与上下文顺序**仍然确定**(先发完整批 `tool_execution_start`,再按声明序发 end / 结果 / 消息);**没有 session 级默认值**(不先提一个空旋钮)。配套:内部 `AgentEvent(kind="tool_start"/"tool_end")` 现在**必须带 `tool_call_id`** —— 并发时 TUI 工具卡片与 runtime 落盘靠它配对(以前都是单个槽位) |
|
|
363
363
|
| E28 | 模型/思考级别切换的**可观测性与持久化** | **三条一起做,缺一条就是半对齐**:① 落盘 `model_change` / `thinking_level_change` 两个**设置类** entry(`SessionStore.set_context_setting`,同值不重写、只在新会话写起点);② bash/powershell 注入 `QI_SESSION_ID` / `QI_SESSION_FILE` / `QI_PROVIDER` / `QI_MODEL` / `QI_REASONING_LEVEL`(**先删后填**,子运行按自己的模型填);③ `Runtime.bind_session()` 按 entry 还原模型与级别。**为什么必须有**:换模型是**界面状态**、不作为消息进上下文,所以在此之前 agent 既感知不到切换、重启后又丢回去(第一轮对话里 agent 凭记忆答错模型,就是这个洞的表现)。**两处 qi 自己的取舍**:键名用 snake_case `model_id`(本仓约定);还原前多一道 `resolve_key(...).ok` 检查,没凭证就回落默认 + 记 note,而不是发一次注定 401 的请求。**新增的接线**:`bind_session()` —— 换模型/换级别发生在**回合外**,而 `_active_session` 只在一个回合内有效。契约见 [session-format.md §6.1](../docs/session-format.md);测试 `tests/test_session_model_entries.py` 20 项 + `tests/test_shell.py` 4 项 + `tests/test_tui_model_restore.py` 2 项(**TUI 启动路径**:footer 的模型/级别必须与 runtime 真正在用的那个一致 —— `_select_session()` 走的是**同步** bind,不能只靠 `session_start` 那个 async worker) |
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
│ ToolCatalog(内置 8 工具 + clarify)· Session(JSONL + 分支树) │
|
|
25
25
|
│ LLMClient(models.json)· 技能 / 提示词基座 / 主题资源 │
|
|
26
26
|
├──────────────────────────────────────────────────────────────┤
|
|
27
|
-
│
|
|
27
|
+
│ 扩展(独立 pip 包,进程内) │
|
|
28
28
|
│ qi-agents(角色 + subagent)· qi-mcp(MCP)· qi-web(HTTP + UI) │
|
|
29
29
|
└──────────────────────────────────────────────────────────────┘
|
|
30
30
|
```
|
|
@@ -265,7 +265,7 @@ pi 的 `ToolDefinition.executionMode` 是 `"sequential" | "parallel"`(默认顺
|
|
|
265
265
|
- 信任模型:pi 同样把信任决定存在用户 home 里(`trust.json`)、不在仓库里 —— qi「项目级 `defaultProjectTrust` 会被忽略」是同一个模型。
|
|
266
266
|
- hook 粒度:**采用 pi 的粒度,不超出**(per-prompt `before_agent_start` + 通知型 `turn_start`)。
|
|
267
267
|
- 依赖契约:公开 import 白名单是 pi 的 `## Available Imports` 的对应物;**禁止钉宿主版本**这条 —— pi 用 `peerDependencies` + `"*"`,Python 没有 peer,所以 qi 改成「明文规定 + 装载时报」。
|
|
268
|
-
- `qi install` 对齐 pi 的 `pi install <source> [-l]`;`remove`/`uninstall`
|
|
268
|
+
- `qi install` 对齐 pi 的 `pi install <source> [-l]`;`remove`/`uninstall` 也**真卸包**(先从指定作用域删声明,无别的作用域声明时才卸),与 pi 同义。
|
|
269
269
|
|
|
270
270
|
### 11.7 决策记录里被移出手册的上游对照(原 §10 各行)
|
|
271
271
|
|
|
@@ -353,6 +353,6 @@ pi 的 `~/.pi/agent/models-store.json` 不是用户配置,而是**远程模型
|
|
|
353
353
|
| `compaction.md` | `reserveTokens` 16384「pi 默认值」;「split turn(pi 同款)」;「`_history()` 的装配规则(pi 语义)」 |
|
|
354
354
|
| `skills.md` | 层序说明「为了跟 pi 的发现规则对齐,再叠上 qi 自己的私有层」;`/skill:` 段尾「pi 的同一句话是 "use prompting or `/skill:name` to force it"」 |
|
|
355
355
|
| `quickstart.md` | `qi "分析这个仓库"` 注释「对齐 pi 的 `pi "问题"`」 |
|
|
356
|
-
| `packages.md` | 「`qi install` 存在(对齐 pi)」;「`remove`
|
|
356
|
+
| `packages.md` | 「`qi install` 存在(对齐 pi)」;「`remove`/`uninstall` 真卸包(与 pi 同义)」 |
|
|
357
357
|
| `usage.md` | `qi -r` 注释「对齐 pi」 |
|
|
358
358
|
| `development.md` | 「qi 没有 `test.sh`(pi 有 `./test.sh`,照那个敲会失败)」 |
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
| 通道 | 怎么装 | 装到哪 | 发现机制 | 场景 |
|
|
17
17
|
| --- | --- | --- | --- | --- |
|
|
18
|
-
| **pip 包** | `
|
|
18
|
+
| **pip 包** | `qi install qi-db-tools`(PyPI / git / 本地) | venv 的 site-packages(环境级) | **entry point 扫描**(`importlib.metadata`,启动时自动发现) | 分发、团队共享、锁依赖 |
|
|
19
19
|
| **本地目录** | 手动放置/复制源码目录 | `~/.qi/plugins/<name>/`(全局)或 `<项目>/.qi/plugins/<name>/`(项目,需信任) | **目录扫描** | 未发布/私有/本地开发,拷贝即用 |
|
|
20
20
|
|
|
21
21
|
pip 包通过 **entry point** 声明(对齐 pytest/uvicorn 模式),无需维护安装清单:
|
|
@@ -131,13 +131,22 @@ qi --tools read,grep,find,ls -p "审查这个项目"
|
|
|
131
131
|
|
|
132
132
|
```sh
|
|
133
133
|
qi install <来源> [-l] # 调 pip + 写进 settings.packages;本地目录只登记(不调 pip)
|
|
134
|
-
qi remove <来源> [-l]
|
|
135
|
-
qi uninstall <来源> [-l]
|
|
134
|
+
qi remove <来源> [-l] [--force] # 移除声明;没有别的作用域还声明它,就连包一起卸
|
|
135
|
+
qi uninstall <来源> [-l] [--force] # 同 remove(别名)
|
|
136
|
+
qi sync [--dry-run] # 按 settings.packages 对账:补装「声明了但没装」的(只补不删)
|
|
136
137
|
qi update [来源|self] [--self|--extensions|--all|--extension <来源>|--force]
|
|
137
138
|
qi list # 列出已装扩展,并与声明双向比对
|
|
138
139
|
qi doctor # 诊断(含「声明了没装」的可复制装法)
|
|
139
140
|
```
|
|
140
141
|
|
|
142
|
+
`qi remove` / `qi uninstall` **真卸包**(对齐 pi):先从指定作用域删声明,若**没有别的作用域**
|
|
143
|
+
还声明它,就用安装器把包装卸掉(pip / uv,与 `qi install` 同一套);还有别的作用域声明着就只
|
|
144
|
+
删声明、留包(除非 `--force`)—— pip 只有一个环境,包是共享的。
|
|
145
|
+
|
|
146
|
+
`qi sync` 是 qi 版的 `uv sync`:声明是唯一事实来源,环境按它重建 —— 把 `settings.packages` 里
|
|
147
|
+
**声明了但没装**的扩展补回来(uv tool 环境里自动走 uv 的安装器),但**不卸载**多余的东西。
|
|
148
|
+
它不是启动时自动补装,只在显式调用时动环境;`--dry-run` 只列要装什么。
|
|
149
|
+
|
|
141
150
|
`qi update` 默认只更 qi 自己;`--models` 在 qi **无意义**(模型全在 `models.json` 里自己维护,它只说明这一点然后退出)。
|
|
142
151
|
`qi install` 每次都先把要跑的 pip 命令打出来 —— 目标环境(自家 venv / `uv tool` / 只读解释器)的行为真的不同,
|
|
143
152
|
声明与比对的意义见 [packages.md](packages.md)。
|
|
@@ -25,7 +25,7 @@ qi 的配置分**用户级**与**项目级**两层。
|
|
|
25
25
|
| `<agent-dir>/extensions/` | 用户级[扩展](extensions.md),一目录一个扩展 |
|
|
26
26
|
| `<agent-dir>/SYSTEM.md` | **整体替换**默认基座(见下) |
|
|
27
27
|
| `<agent-dir>/AGENTS.md`(或 `AGENTS.override.md` / `CLAUDE.md`) | 跨工作目录的用户指令 |
|
|
28
|
-
| `<agent-dir>/agents/`、`<agent-dir>/mcp.json` |
|
|
28
|
+
| `<agent-dir>/agents/`、`<agent-dir>/mcp.json` | **扩展的约定目录**:角色与 MCP server —— **core 不读它们**,由扩展接手;没有任何扩展读时就是普通目录 |
|
|
29
29
|
|
|
30
30
|
## 项目 `.qi` 目录
|
|
31
31
|
|
|
@@ -36,7 +36,7 @@ qi 的配置分**用户级**与**项目级**两层。
|
|
|
36
36
|
| `.qi/SYSTEM.md` | **整体替换**本项目里的基座 |
|
|
37
37
|
| `.qi/extensions/` | 项目级扩展(**信任后才加载**) |
|
|
38
38
|
| `.qi/skills/` | 项目级技能 |
|
|
39
|
-
| `.qi/agents/`、`.qi/mcp.json` |
|
|
39
|
+
| `.qi/agents/`、`.qi/mcp.json` | 同上:扩展的约定目录与声明 |
|
|
40
40
|
|
|
41
41
|
`SYSTEM.md` 有项目级就用项目级(同名文件**不合并**)。
|
|
42
42
|
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
| 起一个受管的子运行 | `api.run_agent(spec, task)` | §5 |
|
|
17
17
|
| 声明消费型配置(按作用域) | `provides_config` / `register_resolver` / `resolve_tools` | §9 |
|
|
18
18
|
|
|
19
|
-
可跑的样例:[`examples/extensions/hello/`](../examples/extensions/hello/extension.py) —— 一份 `extension.py` 把主要的面各走一遍,复制它改名字就是你的扩展。`extensions/`
|
|
19
|
+
可跑的样例:[`examples/extensions/hello/`](../examples/extensions/hello/extension.py) —— 一份 `extension.py` 把主要的面各走一遍,复制它改名字就是你的扩展。`extensions/` 下的三个自带扩展是更完整的参考实现。
|
|
20
20
|
|
|
21
21
|
> 相关文档:[packages.md](packages.md)(安装与声明)、[how-qi-works.md](how-qi-works.md)(内置工具)、[settings.md](settings.md)(`extensions` / `packages` 字段)。
|
|
22
22
|
|
|
@@ -75,7 +75,7 @@ qi doctor # 诊断:装载失败 / 依赖契约 / 声明不一致
|
|
|
75
75
|
| 项目级 | `<项目>/.qi/extensions/<名>/extension.py`(未信任不加载,见下) |
|
|
76
76
|
| 附加路径 | `settings.json` 的 `extensions[]`:每项可以是扩展目录的**父目录**,也可以直接指向**单个扩展目录**;支持 `-<路径>` 排除 |
|
|
77
77
|
| 单次试用 | `qi -e <目录>` / `--extension`(只本进程,`scope=temporary`) |
|
|
78
|
-
| pip 包 | entry point 组 `qi.extensions` |
|
|
78
|
+
| pip 包 | entry point 组 `qi.extensions`,**且必须在 `settings.packages` 里声明**(没声明的装了也不加载 —— 对齐 pi) |
|
|
79
79
|
|
|
80
80
|
装载顺序:**项目级 → 用户级 → `settings.extensions[]` → entry point**,各组内按名排序。顺序确定,但**不是稳定 API** —— 需要保证先后关系的扩展应当写成一个扩展。
|
|
81
81
|
|
|
@@ -341,7 +341,7 @@ api.register_tool(Tool(
|
|
|
341
341
|
|
|
342
342
|
## 10. 依赖契约
|
|
343
343
|
|
|
344
|
-
**安装目标:统一装进 qi 自己的解释器环境。** 目标是 qi 所在的那个 venv,**不是**用户 cwd 的项目 venv(否则就是那个经典失败:"我在项目里 pip install 了,qi 就是 import 不到")
|
|
344
|
+
**安装目标:统一装进 qi 自己的解释器环境。** 目标是 qi 所在的那个 venv,**不是**用户 cwd 的项目 venv(否则就是那个经典失败:"我在项目里 pip install 了,qi 就是 import 不到")。装法就是 `qi install <来源>` —— 它固定往 `sys.executable` 对应的环境装(uv tool 环境里自动改用 uv 的安装器)。
|
|
345
345
|
|
|
346
346
|
- **公开 import 白名单**:只能 import §3 列的那些名字。别的 `qi_agent.*` 模块算内部实现。
|
|
347
347
|
- **扩展不得把 `qi-coding-agent` 写进 `dependencies`**(否则 pip 会在解析时把 qi 自己降级 —— 宿主被自己的扩展踢掉)。
|
|
@@ -349,9 +349,9 @@ api.register_tool(Tool(
|
|
|
349
349
|
另一条会单独报出来:**旧名 `qi-agent`** —— 那个名字在 PyPI 上属于别的项目,写进依赖不是"多写一条",
|
|
350
350
|
而是会真的装一个不相干的包(还可能与 qi 的 import 包在 `site-packages` 里撞车)。
|
|
351
351
|
- **接受的代价**:所有扩展 + 宿主共用一棵解析树 → **版本冲突无处躲**。三层缓解:① 装载时比对已装版本,**不一致就报告**(不静默);② 冲突就拆成独立进程(自己的环境);③ 重依赖优先走外部进程/服务。
|
|
352
|
-
- **uv tool / pipx 的坑**:uv 文档原话 —— tool 环境 "may be upgraded via `uv tool upgrade`, or **re-created entirely** via subsequent `uv tool install`",所以 pip 装进去的扩展**会被重建抹掉**。规矩:声明永远在 `settings.packages
|
|
352
|
+
- **uv tool / pipx 的坑**:uv 文档原话 —— tool 环境 "may be upgraded via `uv tool upgrade`, or **re-created entirely** via subsequent `uv tool install`",所以 pip 装进去的扩展**会被重建抹掉**。规矩:声明永远在 `settings.packages`,重建后用 **`qi sync`** 一条命令补回来(它按声明对账,自动走 uv 的安装器);也可以用 `qi doctor` / `qi list` **发现**它丢了(并给出装法)。或者这类用户直接用 `uv tool install qi-coding-agent --with <包>`(写进 uv 的托管依赖,升级不丢 —— 这条更省事,推荐)。
|
|
353
353
|
- **宿主环境只读时**(系统 Python / Homebrew 管理的解释器):pip 会自己报错;出路是 `uv tool install qi-coding-agent --with <ext>`,或换一个可写的安装方式。qi 不检测这件事 —— 它不调 pip,所以也不该假装知道装不装得进。
|
|
354
|
-
- **`qi install <来源> [-l]`**
|
|
354
|
+
- **`qi install <来源> [-l]`** 帮你走一步:调安装器(uv tool 环境里**自动改用 uv 的安装器**,目标仍是 qi 自己的解释器)+ 写进 `settings.packages`(带 `-l` 写项目)。它每次都先把要跑的命令打出来。`qi remove` / `uninstall` 从指定作用域删声明,若没有别的作用域还声明它,就连包一起卸(对齐 pi)。详见 [packages.md](packages.md) 与 [cli.md](cli.md)。
|
|
355
355
|
|
|
356
356
|
## 11. 细节与已知限制
|
|
357
357
|
|
|
@@ -19,6 +19,7 @@ TUI 里 `/hotkeys` 会列出当前生效的键位,并如实标出哪些还没做
|
|
|
19
19
|
| `ctrl+x` | 复制最后一条回答 |
|
|
20
20
|
| `ctrl+g` | 用 `$EDITOR` 编辑当前输入 |
|
|
21
21
|
| `ctrl+l` | 模型选择器(与 `/model` 同一个) |
|
|
22
|
+
| 模型选择器里 `enter` / `ctrl+s` | 换模型(**只本会话**,落 `model_change`)/ 换并**存为默认**(写 `settings.defaultProvider`/`defaultModel`) |
|
|
22
23
|
| `ctrl+p` / `ctrl+shift+p` | 下一个 / 上一个模型(轮换清单由 `/scoped-models` 决定) |
|
|
23
24
|
| `ctrl+z` | 挂起(回到 shell) |
|
|
24
25
|
|
|
@@ -30,6 +30,12 @@ qi 通过 litellm 调各家模型。provider 与模型定义都在 `models.json`
|
|
|
30
30
|
真正提交消息才报错;无头路径(`-p` / `--mode json`)直接报错退出,并给出可照抄的迁移命令
|
|
31
31
|
—— 与 pi 的 interactive / 非 interactive 同一取舍。
|
|
32
32
|
- 查看:`qi --list-models [搜索词]`(缺密钥的也列,这是诊断面;解析不出凭证的 provider 不列)。
|
|
33
|
+
- **TUI 里换模型**:`/model`(或 `ctrl+l`)选择器里 `enter` 只换**本会话**(落一条 `model_change`,
|
|
34
|
+
续接这条会话才还原);按 **`ctrl+s`** 则连**默认一起改** —— 写回 `settings.json` 的
|
|
35
|
+
`defaultProvider` / `defaultModel`,下次**新会话**就是它(对齐 pi 的 `app.models.save`)。
|
|
36
|
+
- **登录时顺手定默认**:`/login <provider>` 时如果**还没有模型**,qi 会选中该 provider 的
|
|
37
|
+
第一个模型并**写成全局默认**(对齐 pi 的 `completeProviderAuthentication` 用 `persist: true`)
|
|
38
|
+
—— 所以第一次登录后重启也还是它。已经有模型时不洗掉当前选择(只提示“当前模型不变”)。
|
|
33
39
|
|
|
34
40
|
## 接本地模型
|
|
35
41
|
|
|
@@ -137,4 +143,5 @@ models.json: $QI_AGENT_CONFIG(env 指定文件,最高)
|
|
|
137
143
|
| 模型不在 `/model` 或 `ctrl+p` 清单里 | 清单只列**解析得出凭证**的 provider —— 跑 `qi --list-models` 看 `credential` 列 |
|
|
138
144
|
| "我明明设了环境变量" | `qi doctor` 会给出凭证**来源**(`auth(...)` / `env:XXX` / `config:...`),区分"没读到"与"读到了但为空" |
|
|
139
145
|
| provider 拒收 `reasoning_effort` | qi 会自动去掉参数重试并在 footer 提示一次;也可把该模型的 `reasoning` 改成 `false` |
|
|
146
|
+
| 回合失败出现 `'ascii' codec can't encode` | **API key 里有非 ASCII 字符**(多半是把一段中文提示误粘进了密钥框)。现在 qi 在请求前就报“API key 含非 ASCII 字符(来源:…)”;修:`qi auth list` 看来源 → 重新 `qi auth login <provider>` / 改环境变量 / 改 `models.json` 的 `apiKey` |
|
|
140
147
|
| 相容端点返回 4xx | 先确认 `api` 形态选对(`openai-completions` vs `openai-responses` vs `anthropic-messages`) |
|
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
# 扩展的安装与声明
|
|
2
2
|
|
|
3
|
-
> 装扩展 =
|
|
3
|
+
> 装扩展 = 装一个 pip 包,或放一个目录;`qi install` 帮你做这一步,`qi doctor` / `qi list` 负责「声明层 + 比对」。
|
|
4
4
|
> 相关:[cli.md](cli.md)(命令速查)、[extensions.md](extensions.md)(扩展机制与 API)、[settings.md](settings.md)(`packages` / `extensions` 字段)。
|
|
5
5
|
|
|
6
6
|
## 1. 谁负责跱这一步
|
|
7
7
|
|
|
8
|
-
`qi install`
|
|
8
|
+
`qi install` **存在**,但它只是**帮你跱一步**:调一次安装器,然后把声明写进
|
|
9
9
|
`settings.packages`。**它不替代“想清楚装到哪个环境”这件事** —— 三种目标环境的行为真的不同:
|
|
10
10
|
|
|
11
11
|
1. **目标环境有三种**:qi 自己的 venv、`uv tool` 托管的环境、只读的系统解释器(Homebrew / 系统 Python)。
|
|
12
|
-
qi
|
|
13
|
-
|
|
12
|
+
目标始终是 **qi 自己的解释器**(`sys.executable`),所以不会装到 cwd 的项目 venv。
|
|
13
|
+
`uv tool` 的环境里**没有 pip**(uv 自己解 wheel,不 seed pip),qi 会自动改用 uv 的安装器
|
|
14
|
+
(`uv pip install --python <sys.executable>`,目标不变)。qi 每次都把要跑的命令**先打出来**;
|
|
15
|
+
只读解释器下安装器会自己报错,qi 把输出原样给你并补上 `uv tool install qi-coding-agent --with <包>` 那条出路。
|
|
14
16
|
2. **`uv tool` 会整个重建环境**。uv 文档的原话:tool 环境 "may be upgraded via `uv tool upgrade`,
|
|
15
17
|
or **re-created entirely** via subsequent `uv tool install`"。所以 pip 装进去的扩展**会被抹掉**
|
|
16
18
|
—— 声明还在,`qi doctor` 会把它报出来(这正是“声明层”存在的意义)。
|
|
17
|
-
3. **`remove`
|
|
18
|
-
|
|
19
|
+
3. **`remove` / `uninstall` 真卸包**(对齐 pi):先从指定作用域删声明,若没有别的作用域
|
|
20
|
+
还声明它,就用安装器把包装卸掉;还有别的作用域声明着就只删声明、留包(除非 `--force`)
|
|
21
|
+
—— pip 只有一个环境,包是共享的。
|
|
19
22
|
4. **声明与实装始终是两件事**:声明说"这个环境该有什么",实装由 pip 决定。所以 `qi list` /
|
|
20
23
|
`qi doctor` 永远做**两个方向**的比对 —— 即使你用的是 `qi install`。
|
|
21
24
|
|
|
@@ -34,6 +37,7 @@
|
|
|
34
37
|
| `qi-mcp>=0.2` | pip | 名字 + 版本约束(整个 spec 会进装法) |
|
|
35
38
|
| `Qi.MCP` | pip | **PEP 503 归一** → `qi-mcp`(与「已装」侧同一规则,否则一边算命中一边不算) |
|
|
36
39
|
| `qi-mcp @ git+https://host/repo` | pip | **显式名字**(PEP 508 的 `名字 @ URL`) |
|
|
40
|
+
| `qi_mcp-0.1.1.tar.gz` / `./x.whl` | pip | **本地归档**(wheel / sdist):从文件名取 `qi_mcp-0.1.1.tar.gz` → `qi-mcp` |
|
|
37
41
|
| `local:./extensions/qi-mcp` | 目录 | 目录名 |
|
|
38
42
|
| `/abs/path`、`./rel`、`~/x`、`file:…` | 目录 | `Path(...).name` |
|
|
39
43
|
| `{"name": "pip:qi-mcp"}` | 按内容判 | 取 `name` / `spec` / `source` 里第一个非空的 |
|
|
@@ -50,71 +54,82 @@
|
|
|
50
54
|
|
|
51
55
|
| 通道 | 位置 |
|
|
52
56
|
| --- | --- |
|
|
53
|
-
| pip | entry point 组 `qi.extensions`(`importlib.metadata`) |
|
|
57
|
+
| pip | entry point 组 `qi.extensions`(`importlib.metadata`);**只有 `settings.packages` 声明过的才会装载** |
|
|
54
58
|
| 目录 | `~/.qi/agent/extensions/<名>/extension.py`、项目 `.qi/extensions/<名>/extension.py` |
|
|
55
59
|
| 附加 | `qi -e <dir>`、`settings.extensions[]` |
|
|
56
60
|
|
|
57
|
-
>
|
|
58
|
-
>
|
|
61
|
+
> **pip 通道的声明是装载门** —— 对齐 pi:`settings.packages` 是事实来源。`pip` 装了但没声明的
|
|
62
|
+
> 扩展(`qi list` 会列在「已装但未声明」)**不会被加载**,写进声明才生效。
|
|
63
|
+
>
|
|
64
|
+
> **未信任的项目目录不扫**,项目级声明也不计入 —— 与装载路径同一条门控。否则未信任项目的
|
|
65
|
+
> `.qi/extensions/` 会让报告显得"已装",而实际一个都没加载。
|
|
59
66
|
|
|
60
67
|
同名去重:entry point 先到先得。
|
|
61
68
|
|
|
62
69
|
## 4. 两条装法,失效面不同
|
|
63
70
|
|
|
64
|
-
`qi doctor` / `qi list`
|
|
71
|
+
`qi doctor` / `qi list` 会把两条都打出来,**不替你选**。嫌两条麻烦就直接 `qi sync` ——
|
|
72
|
+
它按 `settings.packages` 把缺的装回来:
|
|
65
73
|
|
|
66
74
|
```bash
|
|
67
|
-
# ①
|
|
68
|
-
|
|
75
|
+
# ① 装进 qi 自己的解释器环境(uv tool 环境里自动改用 uv 的安装器)
|
|
76
|
+
qi install "qi-mcp>=0.2"
|
|
69
77
|
|
|
70
78
|
# ② 写进 uv tool 的托管依赖(uv tool 重建 / 升级后仍然在 —— 推荐)
|
|
71
79
|
uv tool install qi-coding-agent --with "qi-mcp>=0.2"
|
|
72
80
|
```
|
|
73
81
|
|
|
74
|
-
| | ①
|
|
82
|
+
| | ① `qi install` | ② uv 托管依赖 |
|
|
75
83
|
| --- | --- | --- |
|
|
76
|
-
| 装到哪 | `sys.executable`
|
|
84
|
+
| 装到哪 | qi 自己的解释器环境(`sys.executable`;uv tool 环境里自动走 `uv pip --python <sys.executable>`) | uv 的 tool 环境 |
|
|
77
85
|
| uv tool 重建后 | **丢**(声明还在,所以 `qi doctor` 会把它报出来) | 保留 |
|
|
78
|
-
| 只读解释器 | 失败(
|
|
86
|
+
| 只读解释器 | 失败(安装器自己报错) | 可行 |
|
|
79
87
|
| 适合 | 自己管 venv 的人 | 用 `uv tool` 装 qi 的人 |
|
|
80
88
|
|
|
81
89
|
## 5. 怎么读输出
|
|
82
90
|
|
|
83
|
-
装好了但没声明(这份环境里三个扩展都是
|
|
91
|
+
装好了但没声明(这份环境里三个扩展都是 pip 装进来的):
|
|
84
92
|
|
|
85
93
|
```text
|
|
86
94
|
$ qi list
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
┃ 扩展 ┃ 通道 ┃ 版本 ┃ 来源
|
|
90
|
-
|
|
91
|
-
│ qi-mcp │ pip │ 0.1.0 │ qi-mcp 0.1.0 ·
|
|
92
|
-
│ qi-agents │ pip │ 0.1.0 │ qi-agents 0.1.0 ·
|
|
93
|
-
│ qi-web │ pip │ 0.1.0 │ qi-web 0.1.0 ·
|
|
94
|
-
|
|
95
|
-
已装但未声明(3): qi-mcp、qi-agents、qi-web ——
|
|
96
|
-
tool
|
|
95
|
+
扩展
|
|
96
|
+
┏━━━━━━━━━━━┳━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━┓
|
|
97
|
+
┃ 扩展 ┃ 通道 ┃ 版本 ┃ 来源 ┃ 声明 ┃
|
|
98
|
+
┡━━━━━━━━━━━╇━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━┩
|
|
99
|
+
│ qi-mcp │ pip │ 0.1.0 │ qi-mcp 0.1.0 · env │ 否 │
|
|
100
|
+
│ qi-agents │ pip │ 0.1.0 │ qi-agents 0.1.0 · env │ 否 │
|
|
101
|
+
│ qi-web │ pip │ 0.1.0 │ qi-web 0.1.0 · env │ 否 │
|
|
102
|
+
└───────────┴──────┴───────┴───────────────────────┴──────┘
|
|
103
|
+
已装但未声明(3): qi-mcp、qi-agents、qi-web —— pip 扩展只有声明了才会加载;
|
|
104
|
+
写进 settings.packages 才生效(也是 uv tool 重建后能补回的依据)
|
|
97
105
|
```
|
|
98
106
|
|
|
99
|
-
|
|
107
|
+
> **两个「作用域」别混**:`来源` 列的 `· env` 说的是**装在哪** —— pip 扩展都装进 qi 的
|
|
108
|
+
> **同一个解释器环境**,所以固定是 `env`(没有“项目一份 / 全局一份”)。`声明` 列才是
|
|
109
|
+
> **哪一级 `settings.packages` 写了它**:`user` = `~/.qi/agent/settings.json`,
|
|
110
|
+
> `project` = `<git 根>/.qi/settings.json`(`qi install -l` 写的就是后者)。
|
|
111
|
+
|
|
112
|
+
声明里有一条装不上、一条认不出,并且同一个包两级都声明时:
|
|
100
113
|
|
|
101
114
|
```text
|
|
102
115
|
扩展
|
|
103
|
-
|
|
104
|
-
┃ 扩展 ┃ 通道 ┃ 版本 ┃ 来源 ┃ 声明
|
|
105
|
-
|
|
106
|
-
│ qi-mcp │ pip │ 0.1.0 │ qi-mcp 0.1.0 ·
|
|
107
|
-
│ qi-agents │ pip │ 0.1.0 │ qi-agents 0.1.0 ·
|
|
108
|
-
│ qi-web │ pip │ 0.1.0 │ qi-web 0.1.0 ·
|
|
109
|
-
│ qi-todo │ pip │ — │ pip:qi-todo · settings:user │ 未安装
|
|
110
|
-
|
|
116
|
+
┏━━━━━━━━━━━┳━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓
|
|
117
|
+
┃ 扩展 ┃ 通道 ┃ 版本 ┃ 来源 ┃ 声明 ┃
|
|
118
|
+
┡━━━━━━━━━━━╇━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩
|
|
119
|
+
│ qi-mcp │ pip │ 0.1.0 │ qi-mcp 0.1.0 · env │ 否 │
|
|
120
|
+
│ qi-agents │ pip │ 0.1.0 │ qi-agents 0.1.0 · env │ 是(user + project) │
|
|
121
|
+
│ qi-web │ pip │ 0.1.0 │ qi-web 0.1.0 · env │ 否 │
|
|
122
|
+
│ qi-todo │ pip │ — │ pip:qi-todo · settings:user │ 未安装 │
|
|
123
|
+
└───────────┴──────┴───────┴─────────────────────────────┴────────────────────┘
|
|
111
124
|
包声明:
|
|
112
125
|
✗ 声明了但没装: pip:qi-todo (settings:user)
|
|
113
|
-
|
|
126
|
+
qi install "qi-todo"
|
|
114
127
|
uv tool install qi-coding-agent --with "qi-todo"
|
|
115
128
|
⚠ 无法解析的声明: git+https://host/repo
|
|
116
129
|
用 `名字 @ URL` 写法才认得出名(如 qi-mcp @ git+https://host/repo)
|
|
117
|
-
已装但未声明(2): qi-mcp、qi-web ——
|
|
130
|
+
已装但未声明(2): qi-mcp、qi-web —— pip 扩展只有声明了才会加载;
|
|
131
|
+
写进 settings.packages 才生效(也是 uv tool 重建后能补回的依据)
|
|
132
|
+
qi-agents 被多级声明(user + project),以项目级为准
|
|
118
133
|
```
|
|
119
134
|
|
|
120
135
|
四类信息各自的含义:
|
|
@@ -152,4 +167,4 @@ tool 重建后补回
|
|
|
152
167
|
- **目录通道的 PEP 723 声明**:`# /// script` 里的 `dependencies` 目前只用于上面那条宿主依赖检查;
|
|
153
168
|
`qi doctor` 还**不**据它去查"这些依赖装齐了没有"。
|
|
154
169
|
- `settings.packages`(包声明)与 `settings.extensions`(资源路径)是**两件事**:
|
|
155
|
-
|
|
170
|
+
前者既决定这个环境该装什么,**也是 pip 通道的装载门**(声明了才加载),后者是"到哪里去找扩展目录"。
|
|
@@ -100,6 +100,9 @@ TUI 里回放会话、以及网页端显示的用量,都来自 `session.py` 的
|
|
|
100
100
|
在启动提示里说明 —— 不会拿着一个注定 401 的模型继续跑。
|
|
101
101
|
- **CLI 显式给的赢**:`--model` / `--thinking`(含 `--model provider/id:级别`)是当次覆盖,
|
|
102
102
|
不会被会话里的旧值顶掉。
|
|
103
|
+
- **新会话走默认、不是“上次用过”**:裸 `qi` 起的是**新会话**,没有 `model_change` 可还原,
|
|
104
|
+
于是回 `settings.json` 的 `defaultProvider`/`defaultModel`。想让某个模型成为“以后都是它”,
|
|
105
|
+
在选择器里按 `ctrl+s` 存为默认(或直接编辑 `settings.json`)。
|
|
103
106
|
- **换模型与换级别在界面上照旧是即时生效的**(下一回合用到请求里);落 entry 是为了"下次打开"
|
|
104
107
|
与"回放里看得出切换点",不影响本回合行为。
|
|
105
108
|
- **界面显示的与发出去的一致**:TUI 的 footer 缓存(`_model` / `_thinking_level`)在选会话后
|
|
@@ -7,7 +7,7 @@ TUI 里输入 `/` 会补全全部命令(内置的、扩展注册的、技能命
|
|
|
7
7
|
|
|
8
8
|
| 命令 | 说明 |
|
|
9
9
|
| --- | --- |
|
|
10
|
-
| `/model [p/m]` | 不给参数 = 开选择器(与 `ctrl+l` 同一个);给 `p/m` 或唯一模型名 = 直接切。**只列解析得出凭证的模型**。切换会落一条 `model_change
|
|
10
|
+
| `/model [p/m]` | 不给参数 = 开选择器(与 `ctrl+l` 同一个);给 `p/m` 或唯一模型名 = 直接切。**只列解析得出凭证的模型**。切换会落一条 `model_change`,**续接这条会话**时仍用它;想让**下次新会话**也是它,在选择器里按 `ctrl+s`(存为全局默认,写 `settings.defaultProvider`/`defaultModel`) |
|
|
11
11
|
| `/scoped-models` | 挑 `ctrl+p` 轮换哪些模型(空 = 全部,写回 `settings.enabledModels`);已不可用的条目画删除线 + `[unavailable]`,取消勾选才移出 |
|
|
12
12
|
| `/thinking` | 不给参数 = 开选择器;切换落一条 `thinking_level_change` entry,下次打开按它还原 |
|
|
13
13
|
| `/settings` | 偏好面板:主题 / 思考级别 / 交互开关(`enter` 换值、`ctrl+s` 保存到**用户级** settings) |
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
| 形态 | 入口 | 适合 |
|
|
13
13
|
| --- | --- | --- |
|
|
14
14
|
| **目录形态** | `<项目>/.qi/extensions/<名>/extension.py` 或 `~/.qi/agent/extensions/<名>/extension.py` | 自己用、快速试;**项目级要在信任的项目里才装载** |
|
|
15
|
-
| **包形态** | `pyproject.toml` 里声明 `qi.extensions` entry point
|
|
15
|
+
| **包形态** | `pyproject.toml` 里声明 `qi.extensions` entry point,装进 qi 后自动发现 | 要发布/共享(仓库里的三个扩展都是这种) |
|
|
16
16
|
| **临时形态** | `settings.json` 的 `extensions: ["/路径"]` | 开发调试(不写进扩展目录) |
|
|
17
17
|
|
|
18
18
|
## 相关文档
|
|
@@ -146,7 +146,7 @@ def serve(argv: list[str]) -> int:
|
|
|
146
146
|
from .app import create_app
|
|
147
147
|
except ImportError as exc: # fastapi/uvicorn 是**本扩展**的依赖
|
|
148
148
|
err_console.print(f"[red]缺少 web 依赖:[/red] {escape(str(exc))}")
|
|
149
|
-
err_console.print(" 安装: [bold]
|
|
149
|
+
err_console.print(" 安装: [bold]qi install qi-web[/bold]")
|
|
150
150
|
return 2
|
|
151
151
|
|
|
152
152
|
password = args.password or os.environ.get("QI_WEB_PASSWORD") or None
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "qi-coding-agent"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.1"
|
|
8
8
|
description = "编码 agent 框架:单 agent core + 扩展(MCP / 多 agent / web)"
|
|
9
9
|
keywords = ["agent", "coding-agent", "cli", "tui", "llm", "mcp"]
|
|
10
10
|
readme = "README.md"
|