@scemoon/cdh 1.0.6 → 1.0.7
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/package.json +2 -2
- package/ai-dlc-skill/SKILL.md +0 -77
- package/ai-dlc-skill/agents/deliver-agent.md +0 -24
- package/ai-dlc-skill/agents/master.md +0 -50
- package/ai-dlc-skill/agents/plan-agent.md +0 -23
- package/ai-dlc-skill/agents/understand-agent.md +0 -23
- package/ai-dlc-skill/agents/verify-agent.md +0 -27
- package/ai-dlc-skill/architecture/project-structure.md +0 -78
- package/ai-dlc-skill/brownfield/README.md +0 -30
- package/ai-dlc-skill/brownfield/generate-context.sh +0 -64
- package/ai-dlc-skill/brownfield/scripts/deps.sh +0 -27
- package/ai-dlc-skill/brownfield/scripts/discover.sh +0 -34
- package/ai-dlc-skill/brownfield/scripts/extract-api.sh +0 -45
- package/ai-dlc-skill/components/backend.md +0 -34
- package/ai-dlc-skill/components/desktop.md +0 -30
- package/ai-dlc-skill/components/mya.md +0 -29
- package/ai-dlc-skill/components/native.md +0 -30
- package/ai-dlc-skill/components/tta.md +0 -29
- package/ai-dlc-skill/components/web.md +0 -31
- package/ai-dlc-skill/components/wxa.md +0 -29
- package/ai-dlc-skill/contracts/README.md +0 -25
- package/ai-dlc-skill/core/adaptive-flow.md +0 -36
- package/ai-dlc-skill/core/security.md +0 -29
- package/ai-dlc-skill/cross-tool/cline/export.sh +0 -31
- package/ai-dlc-skill/cross-tool/copilot/export.sh +0 -47
- package/ai-dlc-skill/cross-tool/cursor/export.sh +0 -32
- package/ai-dlc-skill/cross-tool/export.sh +0 -22
- package/ai-dlc-skill/cross-tool/onecode/config.yaml.tpl +0 -17
- package/ai-dlc-skill/cross-tool/onecode/export-skills.sh +0 -35
- package/ai-dlc-skill/cross-tool/onecode/export.sh +0 -54
- package/ai-dlc-skill/phases/deliver/entry.md +0 -26
- package/ai-dlc-skill/phases/deliver/lifecycle.md +0 -185
- package/ai-dlc-skill/phases/deliver/prompt.md +0 -40
- package/ai-dlc-skill/phases/deliver/rules.md +0 -61
- package/ai-dlc-skill/phases/plan/entry.md +0 -25
- package/ai-dlc-skill/phases/plan/lifecycle.md +0 -204
- package/ai-dlc-skill/phases/plan/prompt.md +0 -38
- package/ai-dlc-skill/phases/plan/rules.md +0 -25
- package/ai-dlc-skill/phases/understand/entry.md +0 -26
- package/ai-dlc-skill/phases/understand/lifecycle.md +0 -184
- package/ai-dlc-skill/phases/understand/prompt.md +0 -41
- package/ai-dlc-skill/phases/understand/rules.md +0 -37
- package/ai-dlc-skill/phases/verify/entry.md +0 -26
- package/ai-dlc-skill/phases/verify/lifecycle.md +0 -192
- package/ai-dlc-skill/phases/verify/prompt.md +0 -43
- package/ai-dlc-skill/phases/verify/rules.md +0 -73
- package/ai-dlc-skill/practices/bdd.md +0 -91
- package/ai-dlc-skill/practices/sdd.md +0 -84
- package/ai-dlc-skill/practices/tdd.md +0 -95
- package/ai-dlc-skill/providers/README.md +0 -114
- package/ai-dlc-skill/providers/aliyun/deployment.yaml +0 -66
- package/ai-dlc-skill/providers/aliyun/preview.yaml +0 -84
- package/ai-dlc-skill/providers/aliyun/provider.yaml +0 -160
- package/ai-dlc-skill/providers/tcb/deployment.yaml +0 -69
- package/ai-dlc-skill/providers/tcb/preview.yaml +0 -83
- package/ai-dlc-skill/providers/tcb/provider.yaml +0 -172
- package/ai-dlc-skill/requirements.md +0 -140
- package/ai-dlc-skill/skill.yaml +0 -147
- package/ai-dlc-skill/templates/integration/CHANGELOG.md +0 -41
- package/ai-dlc-skill/templates/integration/asyncapi.yaml +0 -43
- package/ai-dlc-skill/templates/integration/contract-diff.md +0 -63
- package/ai-dlc-skill/templates/integration/contract-spec.md +0 -49
- package/ai-dlc-skill/templates/integration/openapi.yaml +0 -18
- package/ai-dlc-skill/templates/integration/runtime-contract.yaml +0 -36
- package/ai-dlc-skill/templates/plan/design.md +0 -49
- package/ai-dlc-skill/templates/plan/task-list.md +0 -32
- package/ai-dlc-skill/templates/project/README.md +0 -126
- package/ai-dlc-skill/templates/project/template.md +0 -119
- package/ai-dlc-skill/templates/understand/feature.feature +0 -23
- package/ai-dlc-skill/templates/understand/intent.md +0 -29
- package/ai-dlc-skill/templates/understand/spec-delta.md +0 -47
- package/ai-dlc-skill/templates/verify/test-unit.py +0 -27
- package/ai-dlc-skill/walkthrough/collect.sh +0 -50
- package/ai-dlc-skill/walkthrough/template.md +0 -54
- package/ai-dlc-skill/workflows/ai-dlc.yaml +0 -110
- package/ai-dlc-skill/workflows/deployment.yaml +0 -199
- package/cdh/__init__.py +0 -0
- package/cdh/__main__.py +0 -4
- package/cdh/__pycache__/__init__.cpython-314.pyc +0 -0
- package/cdh/__pycache__/cdh_mcp_injector.cpython-314.pyc +0 -0
- package/cdh/__pycache__/cdh_mcp_loader.cpython-314.pyc +0 -0
- package/cdh/__pycache__/cdh_mcp_manager.cpython-314.pyc +0 -0
- package/cdh/__pycache__/cdh_session_aggregator.cpython-314.pyc +0 -0
- package/cdh/__pycache__/cdh_skill_loader.cpython-314.pyc +0 -0
- package/cdh/__pycache__/cdh_skill_manager.cpython-314.pyc +0 -0
- package/cdh/__pycache__/cli.cpython-313.pyc +0 -0
- package/cdh/__pycache__/cli.cpython-314.pyc +0 -0
- package/cdh/__pycache__/scaffold.cpython-314.pyc +0 -0
- package/cdh/cdh_mcp_injector.py +0 -115
- package/cdh/cdh_mcp_loader.py +0 -67
- package/cdh/cdh_mcp_manager.py +0 -73
- package/cdh/cdh_session_aggregator.py +0 -258
- package/cdh/cdh_skill_manager.py +0 -105
- package/cdh/cli.py +0 -807
- package/cdh/scaffold.py +0 -728
- package/onecode/__init__.py +0 -1
- package/onecode/__main__.py +0 -4
- package/onecode/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/__pycache__/cli.cpython-314.pyc +0 -0
- package/onecode/__pycache__/commands.cpython-314.pyc +0 -0
- package/onecode/__pycache__/config.cpython-314.pyc +0 -0
- package/onecode/__pycache__/config_screen.cpython-314.pyc +0 -0
- package/onecode/__pycache__/migrate.cpython-314.pyc +0 -0
- package/onecode/agent/__init__.py +0 -0
- package/onecode/agent/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/cdh_loader.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/context.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/engine.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/hooks.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/onecode_agent_acp.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/permissions.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/permissions_store.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/project_doc.cpython-314.pyc +0 -0
- package/onecode/agent/__pycache__/session.cpython-314.pyc +0 -0
- package/onecode/agent/agents/__init__.py +0 -29
- package/onecode/agent/agents/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/agent/agents/__pycache__/types.cpython-314.pyc +0 -0
- package/onecode/agent/agents/types.py +0 -589
- package/onecode/agent/attachments.py +0 -112
- package/onecode/agent/cdh_loader.py +0 -267
- package/onecode/agent/context.py +0 -343
- package/onecode/agent/engine.py +0 -2700
- package/onecode/agent/hooks.py +0 -86
- package/onecode/agent/onecode_agent_acp.py +0 -2743
- package/onecode/agent/onecode_agent_acp.py.bak +0 -2447
- package/onecode/agent/permissions.py +0 -150
- package/onecode/agent/permissions_store.py +0 -62
- package/onecode/agent/project_doc.py +0 -19
- package/onecode/agent/session.py +0 -195
- package/onecode/agent/snapshot.py +0 -144
- package/onecode/agent/tools/__init__.py +0 -17
- package/onecode/agent/tools/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/agent_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/apply_patch_tool.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/bash_tool.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/communication_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/config_tool.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/cron_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/errors.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/file_ops.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/file_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/git_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/lsp_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/mcp_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/permission_handler.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/permissions.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/protocol.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/registry.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/sandbox.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/schema_validation.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/skill_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/todo_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/__pycache__/web_tools.cpython-314.pyc +0 -0
- package/onecode/agent/tools/agent_tools.py +0 -132
- package/onecode/agent/tools/apply_patch_tool.py +0 -138
- package/onecode/agent/tools/bash_tool.py +0 -111
- package/onecode/agent/tools/communication_tools.py +0 -148
- package/onecode/agent/tools/config_tool.py +0 -130
- package/onecode/agent/tools/cron_tools.py +0 -178
- package/onecode/agent/tools/errors.py +0 -17
- package/onecode/agent/tools/file_ops.py +0 -221
- package/onecode/agent/tools/file_tools.py +0 -225
- package/onecode/agent/tools/git_tools.py +0 -88
- package/onecode/agent/tools/lsp_tools.py +0 -404
- package/onecode/agent/tools/mcp_tools.py +0 -127
- package/onecode/agent/tools/permission_handler.py +0 -46
- package/onecode/agent/tools/permissions.py +0 -77
- package/onecode/agent/tools/protocol.py +0 -20
- package/onecode/agent/tools/registry.py +0 -201
- package/onecode/agent/tools/sandbox.py +0 -358
- package/onecode/agent/tools/schema_validation.py +0 -100
- package/onecode/agent/tools/skill_tools.py +0 -52
- package/onecode/agent/tools/todo_tools.py +0 -207
- package/onecode/agent/tools/web_tools.py +0 -169
- package/onecode/builtin_skills/agent-browser/SKILL.md +0 -212
- package/onecode/builtin_skills/agent-browser/skill.yaml +0 -8
- package/onecode/builtin_skills/git/SKILL.md +0 -64
- package/onecode/builtin_skills/git/skill.yaml +0 -7
- package/onecode/builtin_skills/shell/SKILL.md +0 -58
- package/onecode/builtin_skills/shell/skill.yaml +0 -8
- package/onecode/builtin_skills/skill-creator/SKILL.md +0 -106
- package/onecode/builtin_skills/skill-creator/skill.yaml +0 -8
- package/onecode/cli.py +0 -935
- package/onecode/cloud/__init__.py +0 -0
- package/onecode/cloud/base.py +0 -20
- package/onecode/codebase/__init__.py +0 -69
- package/onecode/codebase/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/codebase/__pycache__/chunker.cpython-314.pyc +0 -0
- package/onecode/codebase/__pycache__/indexer.cpython-314.pyc +0 -0
- package/onecode/codebase/__pycache__/retriever.cpython-314.pyc +0 -0
- package/onecode/codebase/__pycache__/storage.cpython-314.pyc +0 -0
- package/onecode/codebase/__pycache__/tools.cpython-314.pyc +0 -0
- package/onecode/codebase/chunker.py +0 -125
- package/onecode/codebase/indexer.py +0 -149
- package/onecode/codebase/retriever.py +0 -203
- package/onecode/codebase/storage.py +0 -131
- package/onecode/codebase/tools.py +0 -59
- package/onecode/commands.py +0 -596
- package/onecode/config.py +0 -314
- package/onecode/config_screen.py +0 -600
- package/onecode/cron/__init__.py +0 -3
- package/onecode/lsp/__init__.py +0 -3
- package/onecode/mcp/__init__.py +0 -4
- package/onecode/mcp/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/mcp/__pycache__/client.cpython-314.pyc +0 -0
- package/onecode/mcp/__pycache__/manager.cpython-314.pyc +0 -0
- package/onecode/mcp/client.py +0 -193
- package/onecode/mcp/manager.py +0 -190
- package/onecode/memory/__init__.py +0 -49
- package/onecode/memory/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/memory/__pycache__/backend.cpython-314.pyc +0 -0
- package/onecode/memory/__pycache__/offload.cpython-314.pyc +0 -0
- package/onecode/memory/__pycache__/pyramid.cpython-314.pyc +0 -0
- package/onecode/memory/__pycache__/recall.cpython-314.pyc +0 -0
- package/onecode/memory/__pycache__/symbolic.cpython-314.pyc +0 -0
- package/onecode/memory/backend.py +0 -159
- package/onecode/memory/pyramid.py +0 -133
- package/onecode/memory/recall.py +0 -203
- package/onecode/migrate.py +0 -122
- package/onecode/models/__init__.py +0 -4
- package/onecode/models/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/models/__pycache__/errors.cpython-314.pyc +0 -0
- package/onecode/models/__pycache__/messages.cpython-314.pyc +0 -0
- package/onecode/models/__pycache__/provider.cpython-314.pyc +0 -0
- package/onecode/models/__pycache__/registry.cpython-314.pyc +0 -0
- package/onecode/models/errors.py +0 -104
- package/onecode/models/messages.py +0 -739
- package/onecode/models/provider.py +0 -699
- package/onecode/models/providers/__init__.py +0 -17
- package/onecode/models/providers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/anthropic_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/deepseek_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/glm_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/minimax_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/minimaxi_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/ollama_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/__pycache__/openai_provider.cpython-314.pyc +0 -0
- package/onecode/models/providers/anthropic_provider.py +0 -273
- package/onecode/models/providers/deepseek_provider.py +0 -212
- package/onecode/models/providers/glm_provider.py +0 -195
- package/onecode/models/providers/minimax_provider.py +0 -158
- package/onecode/models/providers/minimaxi_provider.py +0 -417
- package/onecode/models/providers/ollama_provider.py +0 -100
- package/onecode/models/providers/openai_provider.py +0 -237
- package/onecode/models/registry.py +0 -212
- package/onecode/server/__init__.py +0 -3
- package/onecode/server/app.py +0 -224
- package/onecode/skills/__init__.py +0 -11
- package/onecode/skills/__pycache__/__init__.cpython-314.pyc +0 -0
- package/onecode/skills/__pycache__/argument_substitution.cpython-314.pyc +0 -0
- package/onecode/skills/__pycache__/bootstrap.cpython-314.pyc +0 -0
- package/onecode/skills/__pycache__/create.cpython-314.pyc +0 -0
- package/onecode/skills/__pycache__/frontmatter.cpython-314.pyc +0 -0
- package/onecode/skills/__pycache__/loader.cpython-314.pyc +0 -0
- package/onecode/skills/__pycache__/manager.cpython-314.pyc +0 -0
- package/onecode/skills/__pycache__/model.cpython-314.pyc +0 -0
- package/onecode/skills/argument_substitution.py +0 -38
- package/onecode/skills/bootstrap.py +0 -124
- package/onecode/skills/create.py +0 -56
- package/onecode/skills/frontmatter.py +0 -33
- package/onecode/skills/loader.py +0 -139
- package/onecode/skills/manager.py +0 -75
- package/onecode/skills/model.py +0 -43
- package/onecode/storage/__init__.py +0 -0
- package/onecode/storage/activity.py +0 -63
- package/onecode/storage/project.py +0 -54
- package/onecode/storage/session.py +0 -112
- package/onecode/tasks/__init__.py +0 -26
- package/onecode/tasks/manager.py +0 -232
- package/onecode/tasks/models.py +0 -240
- package/onecode/trace/__init__.py +0 -0
- package/onecode/trace/tracer.py +0 -173
- package/onecode/utils/__init__.py +0 -0
- package/onecode/utils/helpers.py +0 -20
- package/pyproject.toml +0 -74
- package/tui/__init__.py +0 -46
- package/tui/__main__.py +0 -4
- package/tui/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tui/__pycache__/_loop.cpython-314.pyc +0 -0
- package/tui/__pycache__/_path_fuzzy_search.cpython-314.pyc +0 -0
- package/tui/__pycache__/_path_match.cpython-314.pyc +0 -0
- package/tui/__pycache__/about.cpython-314.pyc +0 -0
- package/tui/__pycache__/agent.cpython-314.pyc +0 -0
- package/tui/__pycache__/agent_schema.cpython-314.pyc +0 -0
- package/tui/__pycache__/agents.cpython-314.pyc +0 -0
- package/tui/__pycache__/answer.cpython-314.pyc +0 -0
- package/tui/__pycache__/app.cpython-313.pyc +0 -0
- package/tui/__pycache__/app.cpython-314.pyc +0 -0
- package/tui/__pycache__/atomic.cpython-314.pyc +0 -0
- package/tui/__pycache__/complete.cpython-314.pyc +0 -0
- package/tui/__pycache__/constants.cpython-314.pyc +0 -0
- package/tui/__pycache__/conversation_markdown.cpython-314.pyc +0 -0
- package/tui/__pycache__/danger.cpython-314.pyc +0 -0
- package/tui/__pycache__/db.cpython-314.pyc +0 -0
- package/tui/__pycache__/dec.cpython-314.pyc +0 -0
- package/tui/__pycache__/directory.cpython-314.pyc +0 -0
- package/tui/__pycache__/directory_suggester.cpython-314.pyc +0 -0
- package/tui/__pycache__/directory_watcher.cpython-314.pyc +0 -0
- package/tui/__pycache__/format_path.cpython-314.pyc +0 -0
- package/tui/__pycache__/fuzzy.cpython-314.pyc +0 -0
- package/tui/__pycache__/fuzzy_index.cpython-314.pyc +0 -0
- package/tui/__pycache__/history.cpython-314.pyc +0 -0
- package/tui/__pycache__/jsonrpc.cpython-314.pyc +0 -0
- package/tui/__pycache__/menus.cpython-314.pyc +0 -0
- package/tui/__pycache__/message_log.cpython-314.pyc +0 -0
- package/tui/__pycache__/messages.cpython-314.pyc +0 -0
- package/tui/__pycache__/path_complete.cpython-314.pyc +0 -0
- package/tui/__pycache__/path_filter.cpython-314.pyc +0 -0
- package/tui/__pycache__/paths.cpython-314.pyc +0 -0
- package/tui/__pycache__/pill.cpython-314.pyc +0 -0
- package/tui/__pycache__/platform_commands.cpython-314.pyc +0 -0
- package/tui/__pycache__/protocol.cpython-314.pyc +0 -0
- package/tui/__pycache__/session_tracker.cpython-314.pyc +0 -0
- package/tui/__pycache__/settings.cpython-314.pyc +0 -0
- package/tui/__pycache__/settings_schema.cpython-314.pyc +0 -0
- package/tui/__pycache__/shell.cpython-314.pyc +0 -0
- package/tui/__pycache__/shell_read.cpython-314.pyc +0 -0
- package/tui/__pycache__/slash_command.cpython-314.pyc +0 -0
- package/tui/__pycache__/version.cpython-314.pyc +0 -0
- package/tui/_loop.py +0 -86
- package/tui/_path_fuzzy_search.py +0 -48
- package/tui/_path_match.py +0 -141
- package/tui/about.py +0 -95
- package/tui/acp/__pycache__/agent.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/api.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/encode_tool_call_id.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/messages.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/prompt.cpython-314.pyc +0 -0
- package/tui/acp/__pycache__/protocol.cpython-314.pyc +0 -0
- package/tui/acp/agent.py +0 -1002
- package/tui/acp/api.py +0 -73
- package/tui/acp/encode_tool_call_id.py +0 -12
- package/tui/acp/messages.py +0 -203
- package/tui/acp/prompt.py +0 -53
- package/tui/acp/protocol.py +0 -499
- package/tui/agent.py +0 -70
- package/tui/agent_schema.py +0 -76
- package/tui/agents.py +0 -46
- package/tui/ansi/__init__.py +0 -1
- package/tui/ansi/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tui/ansi/__pycache__/_ansi.cpython-314.pyc +0 -0
- package/tui/ansi/__pycache__/_ansi_colors.cpython-314.pyc +0 -0
- package/tui/ansi/__pycache__/_control_codes.cpython-314.pyc +0 -0
- package/tui/ansi/__pycache__/_keys.cpython-314.pyc +0 -0
- package/tui/ansi/__pycache__/_sgr_styles.cpython-314.pyc +0 -0
- package/tui/ansi/__pycache__/_stream_parser.cpython-314.pyc +0 -0
- package/tui/ansi/_ansi.py +0 -1689
- package/tui/ansi/_ansi_colors.py +0 -264
- package/tui/ansi/_control_codes.py +0 -37
- package/tui/ansi/_keys.py +0 -251
- package/tui/ansi/_sgr_styles.py +0 -64
- package/tui/ansi/_stream_parser.py +0 -418
- package/tui/answer.py +0 -12
- package/tui/app.py +0 -1266
- package/tui/atomic.py +0 -37
- package/tui/cli.py +0 -313
- package/tui/code_analyze.py +0 -27
- package/tui/complete.py +0 -38
- package/tui/constants.py +0 -61
- package/tui/conversation_markdown.py +0 -30
- package/tui/danger.py +0 -372
- package/tui/data/agents/ampcode.com.toml +0 -52
- package/tui/data/agents/augmentcode.com.toml +0 -41
- package/tui/data/agents/cdh.cloud-dev-harness.toml +0 -23
- package/tui/data/agents/claude.com.toml +0 -41
- package/tui/data/agents/copilot.github.com.toml +0 -29
- package/tui/data/agents/crowai.dev.toml +0 -36
- package/tui/data/agents/cursor.com.toml +0 -38
- package/tui/data/agents/deepagents.langchain.com +0 -34
- package/tui/data/agents/docker.com.toml +0 -60
- package/tui/data/agents/geminicli.com.toml +0 -28
- package/tui/data/agents/goose.ai.toml +0 -52
- package/tui/data/agents/inference.huggingface.co.toml +0 -41
- package/tui/data/agents/kimi.com.toml +0 -35
- package/tui/data/agents/kiro.dev.toml +0 -43
- package/tui/data/agents/onecode.dev.toml +0 -22
- package/tui/data/agents/openai.com.toml +0 -53
- package/tui/data/agents/openclaw.ai.toml +0 -37
- package/tui/data/agents/opencode.ai.toml +0 -39
- package/tui/data/agents/openhands.dev.toml +0 -46
- package/tui/data/agents/stakpak.dev.toml +0 -62
- package/tui/data/agents/vibe.mistral.ai.toml +0 -31
- package/tui/data/agents/vtcode.dev.toml +0 -63
- package/tui/data/images/frog.png +0 -0
- package/tui/data/sounds/question.wav +0 -0
- package/tui/data/sounds/turn-over.wav +0 -0
- package/tui/db.py +0 -213
- package/tui/dec.py +0 -332
- package/tui/directory.py +0 -234
- package/tui/directory_suggester.py +0 -93
- package/tui/directory_watcher.py +0 -231
- package/tui/format_path.py +0 -25
- package/tui/fuzzy.py +0 -140
- package/tui/fuzzy_index.py +0 -275
- package/tui/gist.py +0 -33
- package/tui/history.py +0 -138
- package/tui/jsonrpc.py +0 -578
- package/tui/menus.py +0 -14
- package/tui/message_log.py +0 -69
- package/tui/messages.py +0 -144
- package/tui/option_content.py +0 -51
- package/tui/os.py +0 -0
- package/tui/path_complete.py +0 -217
- package/tui/path_filter.py +0 -124
- package/tui/paths.py +0 -87
- package/tui/pill.py +0 -23
- package/tui/platform_commands.py +0 -52
- package/tui/prompt/__pycache__/extract.cpython-314.pyc +0 -0
- package/tui/prompt/__pycache__/resource.cpython-314.pyc +0 -0
- package/tui/prompt/extract.py +0 -19
- package/tui/prompt/resource.py +0 -68
- package/tui/protocol.py +0 -28
- package/tui/screens/__init__.py +0 -0
- package/tui/screens/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/agent_modal.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/component_picker.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/diff_screen.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/log.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/main.cpython-313.pyc +0 -0
- package/tui/screens/__pycache__/main.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/permissions.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/projects_app.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/projects_screen.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/sessions.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/store.cpython-314.pyc +0 -0
- package/tui/screens/__pycache__/tool_content_screen.cpython-314.pyc +0 -0
- package/tui/screens/action_modal.py +0 -94
- package/tui/screens/agent_modal.py +0 -175
- package/tui/screens/command_edit_modal.py +0 -74
- package/tui/screens/component_picker.py +0 -168
- package/tui/screens/diff_screen.py +0 -84
- package/tui/screens/log.py +0 -553
- package/tui/screens/main.py +0 -385
- package/tui/screens/main.tcss +0 -655
- package/tui/screens/permissions.py +0 -404
- package/tui/screens/permissions.tcss +0 -72
- package/tui/screens/projects.tcss +0 -80
- package/tui/screens/projects_app.py +0 -347
- package/tui/screens/projects_screen.py +0 -284
- package/tui/screens/session_resume_modal.py +0 -172
- package/tui/screens/session_resume_modal.tcss +0 -35
- package/tui/screens/sessions.py +0 -164
- package/tui/screens/sessions.tcss +0 -119
- package/tui/screens/settings.py +0 -254
- package/tui/screens/settings.tcss +0 -101
- package/tui/screens/store.py +0 -500
- package/tui/screens/store.tcss +0 -274
- package/tui/screens/tool_content_screen.py +0 -59
- package/tui/session_tracker.py +0 -123
- package/tui/settings.py +0 -353
- package/tui/settings_schema.py +0 -431
- package/tui/shell.py +0 -304
- package/tui/shell_read.py +0 -42
- package/tui/slash_command.py +0 -34
- package/tui/tui.tcss +0 -246
- package/tui/twitter.py +0 -38
- package/tui/version.py +0 -80
- package/tui/visuals/__init__.py +0 -0
- package/tui/visuals/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tui/visuals/__pycache__/columns.cpython-314.pyc +0 -0
- package/tui/visuals/columns.py +0 -272
- package/tui/widgets/__init__.py +0 -0
- package/tui/widgets/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/acp_content.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/agent_response.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/agent_thought.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/ask_user.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/condensed_path.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/context_stats.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/conversation.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/diff_view.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/directory_input.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/flash.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/future_text.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/grid_select.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/highlighted_textarea.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/load_more.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/mandelbrot.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/markdown_note.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/menu.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/modified_files.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/non_selectable_label.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/note.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/path_search.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/plan.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/project_directory_tree.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/project_grid_select.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/project_summary.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/prompt.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/question.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/session_grid_select.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/session_summary.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/session_tabs.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/shell_result.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/shell_terminal.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/side_bar.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/slash_complete.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/strike_text.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/subagent.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/subagent_screen.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/terminal.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/throbber.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/tool_call.cpython-314.pyc +0 -0
- package/tui/widgets/__pycache__/user_input.cpython-314.pyc +0 -0
- package/tui/widgets/acp_content.py +0 -70
- package/tui/widgets/agent_response.py +0 -76
- package/tui/widgets/agent_thought.py +0 -167
- package/tui/widgets/ask_user.py +0 -264
- package/tui/widgets/command_pane.py +0 -223
- package/tui/widgets/condensed_path.py +0 -115
- package/tui/widgets/context_stats.py +0 -66
- package/tui/widgets/conversation.py +0 -2641
- package/tui/widgets/danger_warning.py +0 -65
- package/tui/widgets/diff_view.py +0 -69
- package/tui/widgets/directory_input.py +0 -8
- package/tui/widgets/flash.py +0 -81
- package/tui/widgets/future_text.py +0 -126
- package/tui/widgets/grid_select.py +0 -234
- package/tui/widgets/highlighted_textarea.py +0 -180
- package/tui/widgets/load_more.py +0 -24
- package/tui/widgets/mandelbrot.py +0 -294
- package/tui/widgets/markdown_note.py +0 -13
- package/tui/widgets/menu.py +0 -147
- package/tui/widgets/modified_files.py +0 -306
- package/tui/widgets/non_selectable_label.py +0 -5
- package/tui/widgets/note.py +0 -18
- package/tui/widgets/path_search.py +0 -492
- package/tui/widgets/plan.py +0 -285
- package/tui/widgets/project_directory_tree.py +0 -102
- package/tui/widgets/project_grid_select.py +0 -64
- package/tui/widgets/project_summary.py +0 -33
- package/tui/widgets/prompt.py +0 -795
- package/tui/widgets/question.py +0 -360
- package/tui/widgets/session_grid_select.py +0 -230
- package/tui/widgets/session_summary.py +0 -115
- package/tui/widgets/session_tabs.py +0 -188
- package/tui/widgets/shell_result.py +0 -35
- package/tui/widgets/shell_terminal.py +0 -40
- package/tui/widgets/side_bar.py +0 -124
- package/tui/widgets/slash_complete.py +0 -235
- package/tui/widgets/strike_text.py +0 -70
- package/tui/widgets/subagent.py +0 -287
- package/tui/widgets/subagent_screen.py +0 -709
- package/tui/widgets/terminal.py +0 -576
- package/tui/widgets/terminal_tool.py +0 -360
- package/tui/widgets/throbber.py +0 -100
- package/tui/widgets/tool_call.py +0 -398
- package/tui/widgets/user_input.py +0 -23
- package/tui/widgets/version.py +0 -5
- package/tui/widgets/welcome.py +0 -31
package/tui/fuzzy.py
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Fuzzy matcher.
|
|
3
|
-
|
|
4
|
-
This class is used by the [command palette](/guide/command_palette) to match search terms.
|
|
5
|
-
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
from functools import lru_cache
|
|
11
|
-
from operator import itemgetter
|
|
12
|
-
from re import finditer
|
|
13
|
-
from typing import Iterable, Sequence
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
from textual.cache import LRUCache
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class FuzzySearch:
|
|
20
|
-
"""Performs a fuzzy search.
|
|
21
|
-
|
|
22
|
-
Unlike a regex solution, this will finds all possible matches.
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
def __init__(
|
|
26
|
-
self, case_sensitive: bool = False, *, cache_size: int = 1024 * 4
|
|
27
|
-
) -> None:
|
|
28
|
-
"""Initialize fuzzy search.
|
|
29
|
-
|
|
30
|
-
Args:
|
|
31
|
-
case_sensitive: Is the match case sensitive?
|
|
32
|
-
cache_size: Number of queries to cache.
|
|
33
|
-
"""
|
|
34
|
-
|
|
35
|
-
self.case_sensitive = case_sensitive
|
|
36
|
-
self.cache: LRUCache[tuple[str, str], tuple[float, Sequence[int]]] = LRUCache(
|
|
37
|
-
cache_size
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
def match(self, query: str, candidate: str) -> tuple[float, Sequence[int]]:
|
|
41
|
-
"""Match against a query.
|
|
42
|
-
|
|
43
|
-
Args:
|
|
44
|
-
query: The fuzzy query.
|
|
45
|
-
candidate: A candidate to check,.
|
|
46
|
-
|
|
47
|
-
Returns:
|
|
48
|
-
A pair of (score, tuple of offsets). `(0, ())` for no result.
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
cache_key = (query, candidate)
|
|
52
|
-
if cache_key in self.cache:
|
|
53
|
-
return self.cache[cache_key]
|
|
54
|
-
default: tuple[float, Sequence[int]] = (0.0, [])
|
|
55
|
-
result = max(self._match(query, candidate), key=itemgetter(0), default=default)
|
|
56
|
-
self.cache[cache_key] = result
|
|
57
|
-
return result
|
|
58
|
-
|
|
59
|
-
@classmethod
|
|
60
|
-
@lru_cache(maxsize=1024)
|
|
61
|
-
def get_first_letters(cls, candidate: str) -> frozenset[int]:
|
|
62
|
-
return frozenset({match.start() for match in finditer(r"\w+", candidate)})
|
|
63
|
-
|
|
64
|
-
def score(self, candidate: str, positions: Sequence[int]) -> float:
|
|
65
|
-
"""Score a search.
|
|
66
|
-
|
|
67
|
-
Args:
|
|
68
|
-
search: Search object.
|
|
69
|
-
|
|
70
|
-
Returns:
|
|
71
|
-
Score.
|
|
72
|
-
"""
|
|
73
|
-
|
|
74
|
-
first_letters = self.get_first_letters(candidate)
|
|
75
|
-
# This is a heuristic, and can be tweaked for better results
|
|
76
|
-
# Boost first letter matches
|
|
77
|
-
offset_count = len(positions)
|
|
78
|
-
score: float = offset_count + len(first_letters.intersection(positions))
|
|
79
|
-
|
|
80
|
-
groups = 1
|
|
81
|
-
last_offset, *offsets = positions
|
|
82
|
-
for offset in offsets:
|
|
83
|
-
if offset != last_offset + 1:
|
|
84
|
-
groups += 1
|
|
85
|
-
last_offset = offset
|
|
86
|
-
|
|
87
|
-
# Boost to favor less groups
|
|
88
|
-
normalized_groups = (offset_count - (groups - 1)) / offset_count
|
|
89
|
-
score *= 1 + (normalized_groups * normalized_groups)
|
|
90
|
-
return score
|
|
91
|
-
|
|
92
|
-
def _match(
|
|
93
|
-
self, query: str, candidate: str
|
|
94
|
-
) -> Iterable[tuple[float, Sequence[int]]]:
|
|
95
|
-
letter_positions: list[list[int]] = []
|
|
96
|
-
position = 0
|
|
97
|
-
|
|
98
|
-
if not self.case_sensitive:
|
|
99
|
-
candidate = candidate.casefold()
|
|
100
|
-
query = query.casefold()
|
|
101
|
-
|
|
102
|
-
score = self.score
|
|
103
|
-
|
|
104
|
-
for offset, letter in enumerate(query):
|
|
105
|
-
last_index = len(candidate) - offset
|
|
106
|
-
positions: list[int] = []
|
|
107
|
-
letter_positions.append(positions)
|
|
108
|
-
index = position
|
|
109
|
-
while (location := candidate.find(letter, index)) != -1:
|
|
110
|
-
positions.append(location)
|
|
111
|
-
index = location + 1
|
|
112
|
-
if index >= last_index:
|
|
113
|
-
break
|
|
114
|
-
if not positions:
|
|
115
|
-
yield (0.0, ())
|
|
116
|
-
return
|
|
117
|
-
position = positions[0] + 1
|
|
118
|
-
|
|
119
|
-
possible_offsets: list[list[int]] = []
|
|
120
|
-
query_length = len(query)
|
|
121
|
-
|
|
122
|
-
def get_offsets(offsets: list[int], positions_index: int) -> None:
|
|
123
|
-
"""Recursively match offsets.
|
|
124
|
-
|
|
125
|
-
Args:
|
|
126
|
-
offsets: A list of offsets.
|
|
127
|
-
positions_index: Index of query letter.
|
|
128
|
-
|
|
129
|
-
"""
|
|
130
|
-
for offset in letter_positions[positions_index]:
|
|
131
|
-
if not offsets or offset > offsets[-1]:
|
|
132
|
-
new_offsets = [*offsets, offset]
|
|
133
|
-
if len(new_offsets) == query_length:
|
|
134
|
-
possible_offsets.append(new_offsets)
|
|
135
|
-
else:
|
|
136
|
-
get_offsets(new_offsets, positions_index + 1)
|
|
137
|
-
|
|
138
|
-
get_offsets([], 0)
|
|
139
|
-
for offsets in possible_offsets:
|
|
140
|
-
yield score(candidate, offsets), offsets
|
package/tui/fuzzy_index.py
DELETED
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
|
|
3
|
-
from collections import Counter, defaultdict
|
|
4
|
-
from asyncio import Lock
|
|
5
|
-
from itertools import islice
|
|
6
|
-
from operator import itemgetter
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class FuzzyIndex:
|
|
10
|
-
"""An index for path searching.
|
|
11
|
-
|
|
12
|
-
This reduces the number of paths that need to be considered by the relativley expensive scoring function.
|
|
13
|
-
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
def __init__(self) -> None:
|
|
17
|
-
self._paths: list[str] = []
|
|
18
|
-
self._normalized_paths: list[str] = []
|
|
19
|
-
self._index: dict[str, set[int]] = {}
|
|
20
|
-
self._weights_cache: dict[str, dict[int, float]] = {}
|
|
21
|
-
self._path_counter_cache: dict[str, Counter[str]] = {}
|
|
22
|
-
self._lock = Lock()
|
|
23
|
-
|
|
24
|
-
async def update_paths(self, paths: list[str]) -> None:
|
|
25
|
-
"""Update the paths and rebuild the index.
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
paths: New paths.
|
|
29
|
-
"""
|
|
30
|
-
async with self._lock:
|
|
31
|
-
self._paths = paths
|
|
32
|
-
self._normalized_paths = await asyncio.to_thread(
|
|
33
|
-
self._normalize_paths, paths
|
|
34
|
-
)
|
|
35
|
-
self._index = await asyncio.to_thread(
|
|
36
|
-
self._build_trigram_index, self._normalized_paths
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
@classmethod
|
|
40
|
-
def _normalize_paths(cls, paths: list[str]) -> list[str]:
|
|
41
|
-
"""Normalize the paths for searching.
|
|
42
|
-
|
|
43
|
-
Args:
|
|
44
|
-
paths: List of paths as strings.
|
|
45
|
-
|
|
46
|
-
"""
|
|
47
|
-
normalized_paths = list(map(str.casefold, paths))
|
|
48
|
-
return normalized_paths
|
|
49
|
-
|
|
50
|
-
@classmethod
|
|
51
|
-
def _extract_trigrams(cls, text: str) -> set[str]:
|
|
52
|
-
"""Return the set of all 3-character substrings (trigrams) in text.
|
|
53
|
-
|
|
54
|
-
Padding with spaces ensures the start and end of the string are
|
|
55
|
-
represented, so short strings and prefixes still produce trigrams.
|
|
56
|
-
|
|
57
|
-
Args:
|
|
58
|
-
text: candidate text (path).
|
|
59
|
-
|
|
60
|
-
Returns:
|
|
61
|
-
A set of 3 character strings.
|
|
62
|
-
"""
|
|
63
|
-
padded = f" {text} "
|
|
64
|
-
return {padded[index : index + 3] for index in range(len(padded) - 2)}
|
|
65
|
-
|
|
66
|
-
@classmethod
|
|
67
|
-
def _build_trigram_index(cls, paths: list[str]) -> dict[str, set[int]]:
|
|
68
|
-
"""Build an inverted index mapping each trigram to the indices of paths containing it."""
|
|
69
|
-
index: dict[str, set[int]] = defaultdict(set)
|
|
70
|
-
for path_index, path in enumerate(paths):
|
|
71
|
-
for trigram in cls._extract_trigrams(path):
|
|
72
|
-
index[trigram].add(path_index)
|
|
73
|
-
return index
|
|
74
|
-
|
|
75
|
-
def _find_candidates(
|
|
76
|
-
self,
|
|
77
|
-
query: str,
|
|
78
|
-
min_trigram_overlap: float = 0.3,
|
|
79
|
-
) -> list[tuple[str, str]]:
|
|
80
|
-
"""Return the indices of paths that share enough trigrams with the query.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
Args:
|
|
84
|
-
query: The query to apply to the candidates.
|
|
85
|
-
min_trigram_overlap: The overlap threshold (default 30%) controls the trade-off between
|
|
86
|
-
recall (not missing real matches) and how many candidates get passed
|
|
87
|
-
on to the slower detailed scoring stage.
|
|
88
|
-
|
|
89
|
-
"""
|
|
90
|
-
# An upper limit to the number of candidates
|
|
91
|
-
# If there are this many matches, the user will need to type an additional character or two
|
|
92
|
-
MAX_CANDIDATES = 2000
|
|
93
|
-
|
|
94
|
-
query = query.casefold()
|
|
95
|
-
query_length = len(query)
|
|
96
|
-
if query_length == 1:
|
|
97
|
-
# One character
|
|
98
|
-
# Find paths which have the query on the first component
|
|
99
|
-
slash_query = f"/{query}"
|
|
100
|
-
candidates = list(
|
|
101
|
-
islice(
|
|
102
|
-
(
|
|
103
|
-
(path, normalized_path)
|
|
104
|
-
for path, normalized_path in zip(
|
|
105
|
-
self._paths, self._normalized_paths
|
|
106
|
-
)
|
|
107
|
-
if (
|
|
108
|
-
normalized_path.startswith(query)
|
|
109
|
-
or slash_query in normalized_path
|
|
110
|
-
)
|
|
111
|
-
),
|
|
112
|
-
None,
|
|
113
|
-
MAX_CANDIDATES,
|
|
114
|
-
)
|
|
115
|
-
)
|
|
116
|
-
return candidates
|
|
117
|
-
|
|
118
|
-
if query_length <= 3:
|
|
119
|
-
# Find paths which have all the characters
|
|
120
|
-
query_set = set(query)
|
|
121
|
-
candidates = list(
|
|
122
|
-
islice(
|
|
123
|
-
(
|
|
124
|
-
(path, normalized_path)
|
|
125
|
-
for path, normalized_path in zip(
|
|
126
|
-
self._paths, self._normalized_paths
|
|
127
|
-
)
|
|
128
|
-
if query_set.issubset(normalized_path)
|
|
129
|
-
),
|
|
130
|
-
None,
|
|
131
|
-
MAX_CANDIDATES,
|
|
132
|
-
)
|
|
133
|
-
)
|
|
134
|
-
return candidates
|
|
135
|
-
|
|
136
|
-
index = self._index
|
|
137
|
-
query_trigrams = self._extract_trigrams(query)
|
|
138
|
-
matching_buckets = [
|
|
139
|
-
index[trigram] for trigram in query_trigrams if trigram in index
|
|
140
|
-
]
|
|
141
|
-
|
|
142
|
-
trigram_match_counts = Counter(
|
|
143
|
-
sorted(path_index for bucket in matching_buckets for path_index in bucket)
|
|
144
|
-
)
|
|
145
|
-
minimum_shared_trigrams = len(query_trigrams) * min_trigram_overlap
|
|
146
|
-
unique_candidates = dict.fromkeys(
|
|
147
|
-
islice(
|
|
148
|
-
(
|
|
149
|
-
(self._paths[path_index], self._normalized_paths[path_index])
|
|
150
|
-
for path_index, count in trigram_match_counts.items()
|
|
151
|
-
if count >= minimum_shared_trigrams
|
|
152
|
-
),
|
|
153
|
-
None,
|
|
154
|
-
MAX_CANDIDATES,
|
|
155
|
-
)
|
|
156
|
-
)
|
|
157
|
-
candidates = list(unique_candidates.keys())
|
|
158
|
-
return candidates
|
|
159
|
-
|
|
160
|
-
@classmethod
|
|
161
|
-
def make_weights(cls, path: str) -> dict[int, float]:
|
|
162
|
-
"""Assign relative weights to positions with a path.
|
|
163
|
-
|
|
164
|
-
Initial characters are weighted more highly, and the last component
|
|
165
|
-
is weighted higher still.
|
|
166
|
-
|
|
167
|
-
Args:
|
|
168
|
-
path: A path string.
|
|
169
|
-
|
|
170
|
-
Returns:
|
|
171
|
-
A mapping of string indices to relative weights.
|
|
172
|
-
"""
|
|
173
|
-
weights: dict[int, float] = dict.fromkeys(
|
|
174
|
-
range(path.rfind("/") + 1, len(path)), 1.0
|
|
175
|
-
) | {0: 1.0}
|
|
176
|
-
|
|
177
|
-
index = path.find("/", None, -1)
|
|
178
|
-
while index != -1:
|
|
179
|
-
weights[index + 1] = weights.setdefault(index + 1, 1.0) + 1.0
|
|
180
|
-
index = path.find("/", index + 1, -1)
|
|
181
|
-
return weights
|
|
182
|
-
|
|
183
|
-
async def search(self, query: str) -> list[str]:
|
|
184
|
-
|
|
185
|
-
normalized_query = query.casefold()
|
|
186
|
-
query_counter = Counter(normalized_query)
|
|
187
|
-
|
|
188
|
-
scores: list[tuple[float, str]] = []
|
|
189
|
-
|
|
190
|
-
TOP_COUNT = 1000
|
|
191
|
-
|
|
192
|
-
async with self._lock:
|
|
193
|
-
for path, normalized_path in self._find_candidates(normalized_query):
|
|
194
|
-
if (
|
|
195
|
-
path_counter := self._path_counter_cache.get(normalized_path)
|
|
196
|
-
) is None:
|
|
197
|
-
path_counter = self._path_counter_cache[normalized_path] = Counter(
|
|
198
|
-
normalized_path
|
|
199
|
-
)
|
|
200
|
-
if query_counter - path_counter:
|
|
201
|
-
# Not all query characters are matched in the path
|
|
202
|
-
continue
|
|
203
|
-
|
|
204
|
-
if (weights := self._weights_cache.get(normalized_path)) is None:
|
|
205
|
-
weights = self._weights_cache[normalized_path] = self.make_weights(
|
|
206
|
-
normalized_path
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
score = sum(
|
|
210
|
-
[
|
|
211
|
-
weights.get(normalized_query.rfind(character), 0.0)
|
|
212
|
-
for character in normalized_path
|
|
213
|
-
]
|
|
214
|
-
)
|
|
215
|
-
if normalized_path.endswith(normalized_query):
|
|
216
|
-
score *= 2
|
|
217
|
-
if normalized_path.endswith(f"/{normalized_query}"):
|
|
218
|
-
score *= 2
|
|
219
|
-
scores.append((score, path))
|
|
220
|
-
|
|
221
|
-
scores.sort(reverse=True)
|
|
222
|
-
top_scores = scores[:TOP_COUNT]
|
|
223
|
-
|
|
224
|
-
return list(map(itemgetter(1), top_scores))
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if __name__ == "__main__":
|
|
228
|
-
|
|
229
|
-
# from textual._profile import timer
|
|
230
|
-
|
|
231
|
-
from time import perf_counter
|
|
232
|
-
import contextlib
|
|
233
|
-
from typing import Generator
|
|
234
|
-
|
|
235
|
-
@contextlib.contextmanager
|
|
236
|
-
def timer(
|
|
237
|
-
subject: str = "time", threshold: float = 0
|
|
238
|
-
) -> Generator[None, None, None]:
|
|
239
|
-
"""print the elapsed time. (only used in debugging).
|
|
240
|
-
|
|
241
|
-
Args:
|
|
242
|
-
subject: Text shown in log.
|
|
243
|
-
threshold: Time in second after which the log is written.
|
|
244
|
-
|
|
245
|
-
"""
|
|
246
|
-
start = perf_counter()
|
|
247
|
-
yield
|
|
248
|
-
elapsed = perf_counter() - start
|
|
249
|
-
if elapsed >= threshold:
|
|
250
|
-
elapsed_ms = elapsed * 1000
|
|
251
|
-
print(f"{subject} elapsed {elapsed_ms:.4f}ms")
|
|
252
|
-
|
|
253
|
-
async def run():
|
|
254
|
-
with open("paths.txt") as f:
|
|
255
|
-
PATHS = [line.rstrip() for line in f.readlines()]
|
|
256
|
-
print(len(PATHS))
|
|
257
|
-
# PATHS = [
|
|
258
|
-
# "~/foo/",
|
|
259
|
-
# "~/foo/bar/",
|
|
260
|
-
# "~/foo/bar/baz",
|
|
261
|
-
# "~/worldhello/foo",
|
|
262
|
-
# "~/Hello/world",
|
|
263
|
-
# ]
|
|
264
|
-
fuzzy = FuzzyIndex()
|
|
265
|
-
with timer("update"):
|
|
266
|
-
await fuzzy.update_paths(PATHS)
|
|
267
|
-
with timer("search"):
|
|
268
|
-
scores = await fuzzy.search("LICE")
|
|
269
|
-
import rich
|
|
270
|
-
|
|
271
|
-
rich.print(scores)
|
|
272
|
-
|
|
273
|
-
import asyncio
|
|
274
|
-
|
|
275
|
-
asyncio.run(run())
|
package/tui/gist.py
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import httpx
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
# This doesn't work anonymously
|
|
5
|
-
# TODO: Implement login
|
|
6
|
-
def create_gist(
|
|
7
|
-
files: dict[str, str],
|
|
8
|
-
description: str = "",
|
|
9
|
-
public: bool = True,
|
|
10
|
-
) -> str:
|
|
11
|
-
"""Create a GitHub Gist and return its URL.
|
|
12
|
-
|
|
13
|
-
Args:
|
|
14
|
-
files: A mapping of filename to file content.
|
|
15
|
-
description: An optional description for the gist.
|
|
16
|
-
public: Whether the gist should be public.
|
|
17
|
-
|
|
18
|
-
Returns:
|
|
19
|
-
The URL of the created gist.
|
|
20
|
-
"""
|
|
21
|
-
payload = {
|
|
22
|
-
"description": description,
|
|
23
|
-
"public": public,
|
|
24
|
-
"files": {name: {"content": content} for name, content in files.items()},
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
response = httpx.post(
|
|
28
|
-
"https://api.github.com/gists",
|
|
29
|
-
json=payload,
|
|
30
|
-
headers={"Accept": "application/vnd.github+json"},
|
|
31
|
-
)
|
|
32
|
-
response.raise_for_status()
|
|
33
|
-
return response.json()["html_url"]
|
package/tui/history.py
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
from typing import TypedDict
|
|
2
|
-
import asyncio
|
|
3
|
-
import json
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from time import time
|
|
6
|
-
|
|
7
|
-
import rich.repr
|
|
8
|
-
|
|
9
|
-
from tui.complete import Complete
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class HistoryEntry(TypedDict):
|
|
13
|
-
"""An entry in the history file."""
|
|
14
|
-
|
|
15
|
-
input: str
|
|
16
|
-
timestamp: float
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@rich.repr.auto
|
|
20
|
-
class History:
|
|
21
|
-
"""Manages a history file."""
|
|
22
|
-
|
|
23
|
-
def __init__(self, path: Path) -> None:
|
|
24
|
-
self.path = path
|
|
25
|
-
self._lines: list[str] = []
|
|
26
|
-
self._opened: bool = False
|
|
27
|
-
self._current: str | None = None
|
|
28
|
-
self.complete = Complete()
|
|
29
|
-
|
|
30
|
-
def __rich_repr__(self) -> rich.repr.Result:
|
|
31
|
-
yield self.path
|
|
32
|
-
|
|
33
|
-
@property
|
|
34
|
-
def current(self) -> str | None:
|
|
35
|
-
return self._current
|
|
36
|
-
|
|
37
|
-
@current.setter
|
|
38
|
-
def current(self, current: str) -> None:
|
|
39
|
-
self._current = current
|
|
40
|
-
|
|
41
|
-
@property
|
|
42
|
-
def size(self) -> int:
|
|
43
|
-
return len(self._lines)
|
|
44
|
-
|
|
45
|
-
async def open(self) -> bool:
|
|
46
|
-
"""Open the history file, read initial lines.
|
|
47
|
-
|
|
48
|
-
Returns:
|
|
49
|
-
`True` if lines were read, otherwise `False`.
|
|
50
|
-
"""
|
|
51
|
-
if self._opened:
|
|
52
|
-
return True
|
|
53
|
-
|
|
54
|
-
def read_history() -> bool:
|
|
55
|
-
"""Read the history file (in a thread).
|
|
56
|
-
|
|
57
|
-
Returns:
|
|
58
|
-
`True` on success.
|
|
59
|
-
"""
|
|
60
|
-
try:
|
|
61
|
-
self.path.touch(exist_ok=True)
|
|
62
|
-
with self.path.open("r") as history_file:
|
|
63
|
-
self._lines = history_file.readlines()
|
|
64
|
-
|
|
65
|
-
inputs: list[str] = []
|
|
66
|
-
for line in self._lines:
|
|
67
|
-
if (input := json.loads(line).get("input")) is not None:
|
|
68
|
-
inputs.append(input.split(" ", 1)[0])
|
|
69
|
-
self.complete.add_words(inputs)
|
|
70
|
-
except Exception:
|
|
71
|
-
return False
|
|
72
|
-
return True
|
|
73
|
-
|
|
74
|
-
self._opened = await asyncio.to_thread(read_history)
|
|
75
|
-
return self._opened
|
|
76
|
-
|
|
77
|
-
async def append(self, input: str) -> bool:
|
|
78
|
-
"""Append a history entry.
|
|
79
|
-
|
|
80
|
-
Args:
|
|
81
|
-
text: Text in the history.
|
|
82
|
-
shell: Boolean that indicates if the text is shell (`True`) or prompt (`False`).
|
|
83
|
-
|
|
84
|
-
Returns:
|
|
85
|
-
`True` on success.
|
|
86
|
-
"""
|
|
87
|
-
|
|
88
|
-
if not input:
|
|
89
|
-
return True
|
|
90
|
-
self.complete.add_words([input.split(" ")[0]])
|
|
91
|
-
|
|
92
|
-
def write_line() -> bool:
|
|
93
|
-
"""Append a line to the history.
|
|
94
|
-
|
|
95
|
-
Returns:
|
|
96
|
-
`True` on success, `False` if write failed.
|
|
97
|
-
"""
|
|
98
|
-
history_entry: HistoryEntry = {
|
|
99
|
-
"input": input,
|
|
100
|
-
"timestamp": time(),
|
|
101
|
-
}
|
|
102
|
-
line = json.dumps(history_entry)
|
|
103
|
-
self._lines.append(line)
|
|
104
|
-
try:
|
|
105
|
-
with self.path.open("a") as history_file:
|
|
106
|
-
history_file.write(f"{line}\n")
|
|
107
|
-
except Exception:
|
|
108
|
-
return False
|
|
109
|
-
self._current = None
|
|
110
|
-
return True
|
|
111
|
-
|
|
112
|
-
if not self._opened:
|
|
113
|
-
await self.open()
|
|
114
|
-
|
|
115
|
-
return await asyncio.to_thread(write_line)
|
|
116
|
-
|
|
117
|
-
async def get_entry(self, index: int) -> HistoryEntry:
|
|
118
|
-
"""Get a history entry via its index.
|
|
119
|
-
|
|
120
|
-
Args:
|
|
121
|
-
index: Index of entry. 0 for the last entry, negative indexes for previous entries.
|
|
122
|
-
|
|
123
|
-
Returns:
|
|
124
|
-
A history entry dict.
|
|
125
|
-
"""
|
|
126
|
-
if index > 0:
|
|
127
|
-
raise IndexError("History indices must be 0 or negative.")
|
|
128
|
-
if not self._opened:
|
|
129
|
-
await self.open()
|
|
130
|
-
|
|
131
|
-
if index == 0:
|
|
132
|
-
return {"input": self.current or "", "timestamp": time()}
|
|
133
|
-
try:
|
|
134
|
-
entry_line = self._lines[index]
|
|
135
|
-
except IndexError:
|
|
136
|
-
raise IndexError(f"No history entry at index {index}")
|
|
137
|
-
history_entry: HistoryEntry = json.loads(entry_line)
|
|
138
|
-
return history_entry
|