pocket-coding 0.2.1__tar.gz → 0.3.0__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.
Files changed (46) hide show
  1. pocket_coding-0.3.0/PKG-INFO +129 -0
  2. pocket_coding-0.3.0/README.md +108 -0
  3. pocket_coding-0.3.0/README.zh-CN.md +110 -0
  4. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/__init__.py +1 -1
  5. pocket_coding-0.3.0/poco/app.py +124 -0
  6. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/config/__init__.py +20 -0
  7. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/config/store.py +202 -10
  8. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/providers/__init__.py +6 -0
  9. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/providers/codex.py +1 -1
  10. pocket_coding-0.3.0/poco/providers/cursor.py +424 -0
  11. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/providers/models.py +10 -0
  12. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/relay/app.py +38 -5
  13. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/relay/cards.py +33 -22
  14. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/relay/messenger.py +1 -1
  15. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/relay/models.py +4 -0
  16. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/relay/runtime.py +25 -34
  17. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/relay/stores.py +3 -1
  18. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/runtime.py +22 -13
  19. pocket_coding-0.3.0/poco/tui/app.py +1119 -0
  20. pocket_coding-0.3.0/poco/tui/resources.py +192 -0
  21. pocket_coding-0.3.0/poco/tui/sections.py +219 -0
  22. pocket_coding-0.3.0/poco/tui/state.py +121 -0
  23. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/pyproject.toml +1 -1
  24. pocket_coding-0.2.1/PKG-INFO +0 -231
  25. pocket_coding-0.2.1/README.md +0 -210
  26. pocket_coding-0.2.1/README.zh-CN.md +0 -211
  27. pocket_coding-0.2.1/poco/app.py +0 -104
  28. pocket_coding-0.2.1/poco/bootstrap/__init__.py +0 -5
  29. pocket_coding-0.2.1/poco/bootstrap/feishu.py +0 -393
  30. pocket_coding-0.2.1/poco/tui/app.py +0 -787
  31. pocket_coding-0.2.1/poco/tui/menus/__init__.py +0 -9
  32. pocket_coding-0.2.1/poco/tui/menus/config/__init__.py +0 -37
  33. pocket_coding-0.2.1/poco/tui/menus/config/claude.py +0 -513
  34. pocket_coding-0.2.1/poco/tui/menus/config/controller.py +0 -233
  35. pocket_coding-0.2.1/poco/tui/menus/config/render_base.py +0 -119
  36. pocket_coding-0.2.1/poco/tui/menus/config/render_forms.py +0 -56
  37. pocket_coding-0.2.1/poco/tui/menus/config/sections.py +0 -194
  38. pocket_coding-0.2.1/poco/tui/menus/config/types.py +0 -117
  39. pocket_coding-0.2.1/poco/tui/menus/root.py +0 -34
  40. pocket_coding-0.2.1/poco/tui/resources.py +0 -276
  41. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/.gitignore +0 -0
  42. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/providers/base.py +0 -0
  43. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/providers/claude.py +0 -0
  44. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/relay/__init__.py +0 -0
  45. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/relay/utils.py +0 -0
  46. {pocket_coding-0.2.1 → pocket_coding-0.3.0}/poco/tui/__init__.py +0 -0
@@ -0,0 +1,129 @@
1
+ Metadata-Version: 2.4
2
+ Name: pocket-coding
3
+ Version: 0.3.0
4
+ Summary: PoCo: Pocket Coding for Feishu
5
+ Author: PoCo contributors
6
+ Keywords: bot,codex,feishu,lark,tui
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Environment :: Console
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Topic :: Communications :: Chat
16
+ Classifier: Topic :: Software Development :: User Interfaces
17
+ Requires-Python: >=3.11
18
+ Requires-Dist: lark-oapi==1.5.3
19
+ Requires-Dist: textual<1,>=0.75
20
+ Description-Content-Type: text/markdown
21
+
22
+ # PoCo
23
+
24
+ [中文说明](README.zh-CN.md)
25
+
26
+ **PoCo** (Pocket-Coding) is a bot runtime that connects different coding agents to workplace chat software.
27
+
28
+ It currently supports Codex, Claude Code, and Feishu bots.
29
+
30
+ ## Quick Start
31
+
32
+ See [Quick Start](docs/quickstart.md).
33
+
34
+ ## How It Works
35
+
36
+ - DM with the bot: management console
37
+ - Group chat with the bot: project workspace
38
+ - Each project group gets its own worker process
39
+ - Each project is configured from the DM console card
40
+ - PoCo uses Feishu long-connection mode, so no public callback URL is required
41
+
42
+ ## Usage
43
+
44
+ DM console:
45
+
46
+ - send `poco`
47
+ - use the card UI to create a project and manage projects
48
+
49
+ Project group:
50
+
51
+ - just talk to the agent
52
+ - if you want to send an image, send one Feishu post message that contains both the image and the text prompt
53
+
54
+ ## Provider
55
+
56
+ - `codex`: fully implemented through `codex app-server`
57
+ - `claude`: implemented through the Claude Code CLI with streamed JSON output
58
+
59
+ Current provider notes:
60
+
61
+ - Codex is the default runtime path
62
+ - Claude currently supports session attach, image input, and streamed replies
63
+
64
+ ## TUI
65
+
66
+ The TUI is a two-panel terminal UI:
67
+
68
+ - left panel: logo and runtime summary
69
+ - right panel: the current interaction panel
70
+ - bottom: an input line that is only enabled when a config field needs text input
71
+
72
+ Shortcuts:
73
+
74
+ - `Ctrl+R`: Save and restart
75
+ - `q`: go back one level
76
+ - `↑ / ↓`: move in the main menu or config menu
77
+ - `Enter`: open the selected item
78
+ - `Esc`: go back one level
79
+
80
+ The default home screen is menu-driven:
81
+
82
+ - the right panel shows:
83
+ - `Agent & Model`
84
+ - `Bot (feishu)`
85
+ - `PoCo`
86
+ - `Language`
87
+ - `Quit`
88
+ - use `↑ / ↓` to select an item
89
+ - press `Enter` to open it
90
+
91
+ Top-level items open their config sections directly:
92
+
93
+ - the right panel turns into a selection menu
94
+ - `↑ / ↓` moves between sections or fields
95
+ - `Enter` opens the current selection
96
+ - `Esc` returns to the previous level
97
+ - `Language` lets you switch between English and Chinese
98
+ - `Bot (feishu)` contains Feishu settings such as `App ID` and `App Secret`
99
+ - `Agent & Model` contains `codex` and `claude`
100
+ - `claude` opens a provider menu first
101
+ - choose a provider such as `anthropic`, `minimax`, `deepseek`, or `kimi`
102
+ - then edit that provider's `base_url`, `auth_token`, `model`, and `extra_env`
103
+ - `model` opens another menu; pick a model first, then run `set_as_default`
104
+ - `extra_env` also opens a submenu; manage env entries one by one instead of editing raw JSON
105
+ - `show` opens the current config in a scrollable view
106
+ - the bottom input line is only active while editing a text field
107
+
108
+ ## Files
109
+
110
+ - Workspace bindings: `~/.config/poco/workspaces.json`
111
+ - Per-bot config file: `~/.config/poco/bindings/<app_id>/config.json`
112
+ - Per-bot state directory: `~/.local/state/poco/<app_id>/`
113
+ - Legacy default config/state are still under:
114
+ - `~/.config/poco/config.json`
115
+ - `~/.local/state/poco/`
116
+
117
+ ## Development
118
+
119
+ Build packages:
120
+
121
+ ```bash
122
+ uv build
123
+ ```
124
+
125
+ Quick syntax check:
126
+
127
+ ```bash
128
+ uv run python -m py_compile poco/__init__.py poco/app.py poco/runtime.py poco/relay/app.py poco/config/store.py poco/tui/app.py
129
+ ```
@@ -0,0 +1,108 @@
1
+ # PoCo
2
+
3
+ [中文说明](README.zh-CN.md)
4
+
5
+ **PoCo** (Pocket-Coding) is a bot runtime that connects different coding agents to workplace chat software.
6
+
7
+ It currently supports Codex, Claude Code, and Feishu bots.
8
+
9
+ ## Quick Start
10
+
11
+ See [Quick Start](docs/quickstart.md).
12
+
13
+ ## How It Works
14
+
15
+ - DM with the bot: management console
16
+ - Group chat with the bot: project workspace
17
+ - Each project group gets its own worker process
18
+ - Each project is configured from the DM console card
19
+ - PoCo uses Feishu long-connection mode, so no public callback URL is required
20
+
21
+ ## Usage
22
+
23
+ DM console:
24
+
25
+ - send `poco`
26
+ - use the card UI to create a project and manage projects
27
+
28
+ Project group:
29
+
30
+ - just talk to the agent
31
+ - if you want to send an image, send one Feishu post message that contains both the image and the text prompt
32
+
33
+ ## Provider
34
+
35
+ - `codex`: fully implemented through `codex app-server`
36
+ - `claude`: implemented through the Claude Code CLI with streamed JSON output
37
+
38
+ Current provider notes:
39
+
40
+ - Codex is the default runtime path
41
+ - Claude currently supports session attach, image input, and streamed replies
42
+
43
+ ## TUI
44
+
45
+ The TUI is a two-panel terminal UI:
46
+
47
+ - left panel: logo and runtime summary
48
+ - right panel: the current interaction panel
49
+ - bottom: an input line that is only enabled when a config field needs text input
50
+
51
+ Shortcuts:
52
+
53
+ - `Ctrl+R`: Save and restart
54
+ - `q`: go back one level
55
+ - `↑ / ↓`: move in the main menu or config menu
56
+ - `Enter`: open the selected item
57
+ - `Esc`: go back one level
58
+
59
+ The default home screen is menu-driven:
60
+
61
+ - the right panel shows:
62
+ - `Agent & Model`
63
+ - `Bot (feishu)`
64
+ - `PoCo`
65
+ - `Language`
66
+ - `Quit`
67
+ - use `↑ / ↓` to select an item
68
+ - press `Enter` to open it
69
+
70
+ Top-level items open their config sections directly:
71
+
72
+ - the right panel turns into a selection menu
73
+ - `↑ / ↓` moves between sections or fields
74
+ - `Enter` opens the current selection
75
+ - `Esc` returns to the previous level
76
+ - `Language` lets you switch between English and Chinese
77
+ - `Bot (feishu)` contains Feishu settings such as `App ID` and `App Secret`
78
+ - `Agent & Model` contains `codex` and `claude`
79
+ - `claude` opens a provider menu first
80
+ - choose a provider such as `anthropic`, `minimax`, `deepseek`, or `kimi`
81
+ - then edit that provider's `base_url`, `auth_token`, `model`, and `extra_env`
82
+ - `model` opens another menu; pick a model first, then run `set_as_default`
83
+ - `extra_env` also opens a submenu; manage env entries one by one instead of editing raw JSON
84
+ - `show` opens the current config in a scrollable view
85
+ - the bottom input line is only active while editing a text field
86
+
87
+ ## Files
88
+
89
+ - Workspace bindings: `~/.config/poco/workspaces.json`
90
+ - Per-bot config file: `~/.config/poco/bindings/<app_id>/config.json`
91
+ - Per-bot state directory: `~/.local/state/poco/<app_id>/`
92
+ - Legacy default config/state are still under:
93
+ - `~/.config/poco/config.json`
94
+ - `~/.local/state/poco/`
95
+
96
+ ## Development
97
+
98
+ Build packages:
99
+
100
+ ```bash
101
+ uv build
102
+ ```
103
+
104
+ Quick syntax check:
105
+
106
+ ```bash
107
+ uv run python -m py_compile poco/__init__.py poco/app.py poco/runtime.py poco/relay/app.py poco/config/store.py poco/tui/app.py
108
+ ```
@@ -0,0 +1,110 @@
1
+ # PoCo
2
+
3
+ [English](README.md)
4
+
5
+ **PoCo** (Pocket-Coding) 是一个把不同 Coding-Agent 接入办公软件机器人程序。
6
+
7
+ 当前已经支持了 Codex, Claude Code 等 Coding-Agent;已经支持了飞书机器人。
8
+
9
+ ## 快速开始
10
+
11
+ 点击这里[快速开始](docs/quickstart.zh-CN.md)。
12
+
13
+ ## 工作方式
14
+
15
+ - 单聊机器人:管理控制台
16
+ - 群聊机器人:项目工作区
17
+ - 每个项目群会启动一个独立的 worker 进程
18
+ - 每个项目都通过 DM 控制台卡片配置
19
+ - PoCo 使用飞书长连接模式,不需要公网回调地址
20
+
21
+ ## 使用方式
22
+
23
+ 单聊控制台:
24
+
25
+ - 发 `poco`
26
+ - 用卡片完成新建项目和管理项目
27
+
28
+ 项目群:
29
+
30
+ - 直接聊天即可
31
+ - 如果要发图片,请发送一条同时包含图片和文字说明的飞书图文消息
32
+
33
+ ## Provider
34
+
35
+ - `codex`:已通过 `codex app-server` 完整接通
36
+ - `claude`:已通过 Claude Code CLI 接通,支持流式 JSON 输出
37
+
38
+ 当前 provider 能力说明:
39
+
40
+ - Codex 是默认运行路径
41
+ - Claude 当前支持 session attach、图片输入和流式回复
42
+
43
+ ## TUI
44
+
45
+ 页面:
46
+
47
+ 当前 TUI 是一个双栏终端界面:
48
+
49
+ - 左侧:logo 和运行状态摘要
50
+ - 右侧:当前交互面板
51
+ - 底部:一个输入栏,但只有在需要输入配置值时才会启用
52
+
53
+ 快捷键:
54
+
55
+ - `Ctrl+R`:保存并重启
56
+ - `q`:返回上一级
57
+ - `↑ / ↓`:在主菜单或 config 菜单中移动
58
+ - `Enter`:进入当前选项
59
+ - `Esc`:返回上一级
60
+
61
+ 默认首页是菜单驱动的:
62
+
63
+ - 右侧会显示:
64
+ - `Agent & Model`
65
+ - `Bot (feishu)`
66
+ - `PoCo`
67
+ - `Language`
68
+ - `Quit`
69
+ - 用 `↑ / ↓` 选择项目
70
+ - 按 `Enter` 进入
71
+
72
+ 顶层菜单会直接进入对应配置分类:
73
+
74
+ - 右侧面板会变成选择菜单
75
+ - `↑ / ↓` 可以切换 section 或字段
76
+ - `Enter` 进入当前项
77
+ - `Esc` 返回上一级
78
+ - `Language` 可以切换英文和中文
79
+ - `Bot (feishu)` 里包含 `feishu` 相关设置,比如 `App ID`、`App Secret`
80
+ - `Agent & Model` 里包含 `codex` 和 `claude`
81
+ - `claude` 会先进入 provider 菜单
82
+ - 先选一个 provider,例如 `anthropic`、`minimax`、`deepseek`、`kimi`
83
+ - 再编辑这个 provider 的 `base_url`、`auth_token`、`model`、`extra_env`
84
+ - `model` 会再进入一个模型菜单;先选模型,再执行 `set_as_default`
85
+ - `extra_env` 也会进入子菜单;按项管理环境变量,不再直接编辑原始 JSON
86
+ - `show` 会打开当前配置文件的滚动视图
87
+ - 只有在编辑文本字段时,底部输入栏才会启用
88
+
89
+ ## 文件位置
90
+
91
+ - 工作区绑定:`~/.config/poco/workspaces.json`
92
+ - 每个 bot 的配置文件:`~/.config/poco/bindings/<app_id>/config.json`
93
+ - 每个 bot 的状态目录:`~/.local/state/poco/<app_id>/`
94
+ - 兼容旧版时,默认配置 / 状态仍在:
95
+ - `~/.config/poco/config.json`
96
+ - `~/.local/state/poco/`
97
+
98
+ ## 开发
99
+
100
+ 构建安装包:
101
+
102
+ ```bash
103
+ uv build
104
+ ```
105
+
106
+ 快速语法检查:
107
+
108
+ ```bash
109
+ uv run python -m py_compile poco/__init__.py poco/app.py poco/runtime.py poco/relay/app.py poco/config/store.py poco/tui/app.py
110
+ ```
@@ -1,4 +1,4 @@
1
1
  """PoCo package."""
2
2
 
3
3
  __all__ = ["__version__"]
4
- __version__ = "0.2.1"
4
+ __version__ = "0.3.0"
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env python3
2
+ import argparse
3
+ import json
4
+ import logging
5
+ import os
6
+ import sys
7
+ from logging.handlers import RotatingFileHandler
8
+ from pathlib import Path
9
+ from .runtime import (
10
+ PoCoService,
11
+ RingLogHandler,
12
+ )
13
+ from .config import ConfigStore, bind_workspace, build_paths, ensure_dirs, get_nested, workspace_binding
14
+ from .tui import PoCoTui
15
+
16
+
17
+ def parse_args() -> argparse.Namespace:
18
+ parser = argparse.ArgumentParser(description="PoCo")
19
+ parser.add_argument("--log-level", default="INFO")
20
+ sub = parser.add_subparsers(dest="command")
21
+ config_cmd = sub.add_parser("config", help="open PoCo and focus config tab")
22
+ config_cmd.add_argument("--show", action="store_true", help="show masked config and exit")
23
+ config_cmd.add_argument("key", nargs="?", help="config key, e.g. app_id or feishu.app_id")
24
+ config_cmd.add_argument("value", nargs="?", help="config value")
25
+ return parser.parse_args()
26
+
27
+
28
+ def _env_flag(name: str) -> bool:
29
+ value = os.getenv(name, "").strip().lower()
30
+ return value in {"1", "true", "yes", "on"}
31
+
32
+
33
+ def _env_feishu_binding() -> tuple[str, str, str] | None:
34
+ if not _env_flag("POCO_BIND_SKIP"):
35
+ return None
36
+ app_id = os.getenv("POCO_FEISHU_APP_ID", "").strip()
37
+ app_secret = os.getenv("POCO_FEISHU_APP_SECRET", "").strip()
38
+ if not app_id or not app_secret:
39
+ return None
40
+ alias = os.getenv("POCO_FEISHU_ALIAS", "").strip()
41
+ return app_id, app_secret, alias
42
+
43
+
44
+ def _apply_env_binding(workspace: Path, app_id: str, app_secret: str, alias: str) -> str:
45
+ bind_workspace(workspace, app_id)
46
+ paths = build_paths(app_id)
47
+ ensure_dirs(paths)
48
+ store = ConfigStore(paths.config_path, paths)
49
+ config = store.load()
50
+ feishu = config.setdefault("feishu", {})
51
+ feishu["app_id"] = app_id
52
+ feishu["app_secret"] = app_secret
53
+ if alias:
54
+ feishu["alias"] = alias
55
+ store.save(config)
56
+ return app_id
57
+
58
+
59
+ def main() -> None:
60
+ args = parse_args()
61
+ workspace = Path.cwd()
62
+ env_binding = _env_feishu_binding()
63
+ binding = workspace_binding(workspace)
64
+ if env_binding is not None:
65
+ binding = _apply_env_binding(workspace, *env_binding)
66
+ root_logger = logging.getLogger()
67
+ root_logger.setLevel(getattr(logging, str(getattr(args, "log_level", "INFO")).upper(), logging.INFO))
68
+ for handler in list(root_logger.handlers):
69
+ if isinstance(handler, logging.StreamHandler) and not isinstance(handler, logging.FileHandler):
70
+ root_logger.removeHandler(handler)
71
+ ring = RingLogHandler()
72
+ ring.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(name)s: %(message)s"))
73
+ root_logger.addHandler(ring)
74
+ file_handler: RotatingFileHandler | None = None
75
+
76
+ def build_service_for(app_id: str | None) -> PoCoService:
77
+ nonlocal file_handler
78
+ paths = build_paths(app_id or "default")
79
+ ensure_dirs(paths)
80
+ if file_handler is not None:
81
+ root_logger.removeHandler(file_handler)
82
+ file_handler.close()
83
+ file_handler = RotatingFileHandler(
84
+ paths.log_path,
85
+ maxBytes=2_000_000,
86
+ backupCount=3,
87
+ encoding="utf-8",
88
+ mode="w",
89
+ )
90
+ file_handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(name)s: %(message)s"))
91
+ root_logger.addHandler(file_handler)
92
+ logging.getLogger("poco").info(
93
+ "Persistent log file enabled at %s (instance=%s)",
94
+ paths.log_path,
95
+ app_id or "default",
96
+ )
97
+ store = ConfigStore(paths.config_path, paths)
98
+ return PoCoService(store, ring, paths)
99
+
100
+ service = build_service_for(binding)
101
+
102
+ if args.command == "config" and args.show:
103
+ print(json.dumps(service.masked_config(), ensure_ascii=False, indent=2))
104
+ return
105
+ if args.command == "config" and args.key:
106
+ if args.value is None:
107
+ raise SystemExit("usage: poco config <key> <value>")
108
+ path, _ = service.set_config_value(args.key, args.value)
109
+ current = get_nested(service.masked_config(), path)
110
+ print(json.dumps({path: current}, ensure_ascii=False, indent=2))
111
+ return
112
+ app = PoCoTui(
113
+ service,
114
+ service_factory=build_service_for,
115
+ focus_config=args.command == "config",
116
+ skip_bind_on_boot=env_binding is not None,
117
+ )
118
+ result = app.run()
119
+ if result == "restart":
120
+ os.execv(sys.executable, [sys.executable, *sys.argv])
121
+
122
+
123
+ if __name__ == "__main__":
124
+ main()
@@ -1,4 +1,7 @@
1
1
  from .store import (
2
+ PoCoPaths,
3
+ SavedFeishuBot,
4
+ WORKSPACE_BINDINGS_PATH,
2
5
  CONFIG_KEY_ALIASES,
3
6
  CONFIG_PATH,
4
7
  DEFAULT_CONFIG,
@@ -8,17 +11,27 @@ from .store import (
8
11
  THREAD_STATE_PATH,
9
12
  WORKER_STATE_PATH,
10
13
  ConfigStore,
14
+ build_paths,
15
+ bind_workspace,
11
16
  config_ready,
12
17
  ensure_dirs,
13
18
  get_nested,
19
+ load_workspace_bindings,
14
20
  mask_secret,
15
21
  missing_required_config_paths,
22
+ normalize_instance_name,
16
23
  normalize_config_key,
17
24
  parse_config_value,
25
+ saved_feishu_bot_ids,
26
+ saved_feishu_bots,
18
27
  set_nested,
28
+ workspace_binding,
19
29
  )
20
30
 
21
31
  __all__ = [
32
+ "PoCoPaths",
33
+ "SavedFeishuBot",
34
+ "WORKSPACE_BINDINGS_PATH",
22
35
  "CONFIG_KEY_ALIASES",
23
36
  "CONFIG_PATH",
24
37
  "DEFAULT_CONFIG",
@@ -28,12 +41,19 @@ __all__ = [
28
41
  "THREAD_STATE_PATH",
29
42
  "WORKER_STATE_PATH",
30
43
  "ConfigStore",
44
+ "build_paths",
45
+ "bind_workspace",
31
46
  "config_ready",
32
47
  "ensure_dirs",
33
48
  "get_nested",
49
+ "load_workspace_bindings",
34
50
  "mask_secret",
35
51
  "missing_required_config_paths",
52
+ "normalize_instance_name",
36
53
  "normalize_config_key",
37
54
  "parse_config_value",
55
+ "saved_feishu_bot_ids",
56
+ "saved_feishu_bots",
38
57
  "set_nested",
58
+ "workspace_binding",
39
59
  ]