opensober 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +147 -0
  3. package/README.zh-CN.md +144 -0
  4. package/dist/cli/doctor.d.ts +11 -0
  5. package/dist/cli/doctor.d.ts.map +1 -0
  6. package/dist/cli/format-error.d.ts +3 -0
  7. package/dist/cli/format-error.d.ts.map +1 -0
  8. package/dist/cli/index.d.ts +3 -0
  9. package/dist/cli/index.d.ts.map +1 -0
  10. package/dist/cli/index.js +29606 -0
  11. package/dist/cli/run.d.ts +15 -0
  12. package/dist/cli/run.d.ts.map +1 -0
  13. package/dist/config/defaults.d.ts +6 -0
  14. package/dist/config/defaults.d.ts.map +1 -0
  15. package/dist/config/discovery.d.ts +30 -0
  16. package/dist/config/discovery.d.ts.map +1 -0
  17. package/dist/config/extends.d.ts +25 -0
  18. package/dist/config/extends.d.ts.map +1 -0
  19. package/dist/config/loader.d.ts +9 -0
  20. package/dist/config/loader.d.ts.map +1 -0
  21. package/dist/config/merge.d.ts +10 -0
  22. package/dist/config/merge.d.ts.map +1 -0
  23. package/dist/config/prompt-source.d.ts +24 -0
  24. package/dist/config/prompt-source.d.ts.map +1 -0
  25. package/dist/config/schema.d.ts +127 -0
  26. package/dist/config/schema.d.ts.map +1 -0
  27. package/dist/config/types.d.ts +24 -0
  28. package/dist/config/types.d.ts.map +1 -0
  29. package/dist/hooks/context-injection.d.ts +25 -0
  30. package/dist/hooks/context-injection.d.ts.map +1 -0
  31. package/dist/hooks/index.d.ts +3 -0
  32. package/dist/hooks/index.d.ts.map +1 -0
  33. package/dist/hooks/truncation.d.ts +6 -0
  34. package/dist/hooks/truncation.d.ts.map +1 -0
  35. package/dist/index.d.ts +5 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +28250 -0
  38. package/dist/meta.d.ts +3 -0
  39. package/dist/meta.d.ts.map +1 -0
  40. package/dist/opensober.schema.json +304 -0
  41. package/dist/plugin/register-agents.d.ts +4 -0
  42. package/dist/plugin/register-agents.d.ts.map +1 -0
  43. package/dist/shared/log.d.ts +9 -0
  44. package/dist/shared/log.d.ts.map +1 -0
  45. package/dist/tools/ast-grep/ast-grep-replace.d.ts +4 -0
  46. package/dist/tools/ast-grep/ast-grep-replace.d.ts.map +1 -0
  47. package/dist/tools/ast-grep/ast-grep-search.d.ts +4 -0
  48. package/dist/tools/ast-grep/ast-grep-search.d.ts.map +1 -0
  49. package/dist/tools/common/auth.d.ts +6 -0
  50. package/dist/tools/common/auth.d.ts.map +1 -0
  51. package/dist/tools/common/format.d.ts +17 -0
  52. package/dist/tools/common/format.d.ts.map +1 -0
  53. package/dist/tools/common/guards.d.ts +19 -0
  54. package/dist/tools/common/guards.d.ts.map +1 -0
  55. package/dist/tools/edit/edit.d.ts +4 -0
  56. package/dist/tools/edit/edit.d.ts.map +1 -0
  57. package/dist/tools/glob/glob.d.ts +4 -0
  58. package/dist/tools/glob/glob.d.ts.map +1 -0
  59. package/dist/tools/grep/grep.d.ts +4 -0
  60. package/dist/tools/grep/grep.d.ts.map +1 -0
  61. package/dist/tools/hashline-edit/annotate.d.ts +9 -0
  62. package/dist/tools/hashline-edit/annotate.d.ts.map +1 -0
  63. package/dist/tools/hashline-edit/apply.d.ts +22 -0
  64. package/dist/tools/hashline-edit/apply.d.ts.map +1 -0
  65. package/dist/tools/hashline-edit/file-meta.d.ts +13 -0
  66. package/dist/tools/hashline-edit/file-meta.d.ts.map +1 -0
  67. package/dist/tools/hashline-edit/hash.d.ts +3 -0
  68. package/dist/tools/hashline-edit/hash.d.ts.map +1 -0
  69. package/dist/tools/hashline-edit/index.d.ts +5 -0
  70. package/dist/tools/hashline-edit/index.d.ts.map +1 -0
  71. package/dist/tools/index.d.ts +16 -0
  72. package/dist/tools/index.d.ts.map +1 -0
  73. package/dist/tools/read/read.d.ts +4 -0
  74. package/dist/tools/read/read.d.ts.map +1 -0
  75. package/dist/tools/task/runner.d.ts +37 -0
  76. package/dist/tools/task/runner.d.ts.map +1 -0
  77. package/dist/tools/task/task.d.ts +5 -0
  78. package/dist/tools/task/task.d.ts.map +1 -0
  79. package/package.json +77 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tt-a1i
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,147 @@
1
+ # opensober
2
+
3
+ > *Stay sober. Nothing is magic.*
4
+
5
+ **English** | [简体中文](./README.zh-CN.md)
6
+
7
+ An opencode plugin that doesn't try to be clever. Agent tools keep getting smarter, more magical, more opinionated. opensober goes the other way: every behavior is visible, disable-able, and fails loud.
8
+
9
+ **Status:** v0.1.x, API not yet stable. Not yet published to npm.
10
+
11
+ ## Why
12
+
13
+ - **No invisible automation.** No keyword-driven modes. No prompt-derived command execution. Every context injection is named in config.
14
+ - **Readonly agents cannot escape their sandbox.** A readonly agent delegating to a writable agent is rejected at runtime — enforced by the `task` tool, not by documentation.
15
+ - **Edits can't silently clobber stale state.** `read` annotates each line with a content hash; `edit` rejects the whole batch if any hash has changed.
16
+
17
+ ## Install
18
+
19
+ Not yet published to npm. For local development:
20
+
21
+ ```bash
22
+ git clone <this-repo>
23
+ cd opensober
24
+ bun install
25
+ bun run build
26
+ npm pack # produces opensober-0.1.0.tgz
27
+ ```
28
+
29
+ Then install into your opencode config:
30
+
31
+ ```bash
32
+ cd ~/.config/opencode
33
+ bun add /path/to/opensober-0.1.0.tgz
34
+ ```
35
+
36
+ Add to `~/.config/opencode/opencode.json`:
37
+
38
+ ```jsonc
39
+ {
40
+ // Register opensober as a plugin (file URL to the built entry)
41
+ "plugin": ["file:///path/to/.config/opencode/node_modules/opensober/dist/index.js"],
42
+
43
+ // opensober's orchestrator must be declared as a static primary agent
44
+ // for it to appear in the opencode agent selector UI.
45
+ "agent": {
46
+ "orchestrator": {
47
+ "model": "your-provider/your-model",
48
+ "mode": "primary"
49
+ }
50
+ // ... your other agents
51
+ }
52
+ }
53
+ ```
54
+
55
+ > **Note:** opencode's UI agent list reads from static config, not solely from plugin
56
+ > dynamic registration. The `orchestrator` entry above is the UI anchor; opensober's
57
+ > `explore` and `reviewer` subagents are registered dynamically and accessible via
58
+ > the `task` tool, but don't need static entries.
59
+
60
+ Peer requirement: `@opencode-ai/plugin ^1.4.0`. Bun-only (>= 1.3.0); no Node fallback.
61
+
62
+ ## Quickstart
63
+
64
+ Create `.opensober/config.jsonc` at your project root:
65
+
66
+ ```jsonc
67
+ {
68
+ "version": 1,
69
+ "model": "anthropic/claude-opus-4-6",
70
+ "agents": {
71
+ "quick": {
72
+ "extends": "orchestrator",
73
+ "model": "openai/gpt-5-mini"
74
+ }
75
+ }
76
+ }
77
+ ```
78
+
79
+ Check it loads cleanly:
80
+
81
+ ```
82
+ $ bunx opensober doctor
83
+
84
+ == opensober doctor ==
85
+
86
+ config
87
+ version: 1
88
+ global model: anthropic/claude-opus-4-6
89
+ layers:
90
+ default (built-in)
91
+ project /repo/.opensober/config.jsonc
92
+
93
+ agents
94
+ explore anthropic/claude-opus-4-6 readonly, no-delegate
95
+ orchestrator anthropic/claude-opus-4-6 writable, delegates
96
+ reviewer anthropic/claude-opus-4-6 readonly, delegates (readonly-only)
97
+ quick openai/gpt-5-mini writable, delegates
98
+
99
+ tools
100
+ edit, read, task
101
+
102
+ warnings
103
+ (none)
104
+ ```
105
+
106
+ Exit codes: `0` clean, `1` warnings, `2` config failed to load.
107
+
108
+ ## Commands
109
+
110
+ | Command | Purpose |
111
+ |---|---|
112
+ | `bunx opensober doctor` | Health check: config summary, agents, tools, warnings |
113
+ | `bunx opensober run` | Load config and print a session-ready summary |
114
+ | `bunx opensober install` | *(not yet implemented)* |
115
+
116
+ Both `doctor` and `run` take `--cwd <dir>` and `--config <path>`.
117
+
118
+ ## Config layering
119
+
120
+ Four layers merge in order (later wins):
121
+
122
+ 1. **default** — built-in baselines
123
+ 2. **user** — `~/.config/opensober/config.jsonc`
124
+ 3. **project** — `<project-root>/.opensober/config.jsonc`
125
+ 4. **cli-override** — `--config <path>`
126
+
127
+ Project root is the nearest ancestor directory containing `.git`. If none is found, the project layer is silently skipped — single-file or CI scratch directories just work.
128
+
129
+ ## Built-in agents
130
+
131
+ Three agents ship in the box:
132
+
133
+ - `orchestrator` — writable, may delegate to any agent
134
+ - `explore` — readonly, cannot delegate
135
+ - `reviewer` — readonly, may delegate only to other readonly agents
136
+
137
+ User-defined agents extend these via `extends`. Permission flags (`readonly`, `can_delegate`) inherit from the parent chain; overriding them explicitly is allowed but the `task` tool still enforces that readonly callers cannot reach writable targets.
138
+
139
+ ## Learn more
140
+
141
+ - [`v1-scope.md`](./v1-scope.md) — frozen v1 scope
142
+ - [`CONTRIBUTING.md`](./CONTRIBUTING.md) — the nine hard rules
143
+ - [`round-7.5-memo.md`](./round-7.5-memo.md) — SDK investigation memo
144
+
145
+ ## License
146
+
147
+ [MIT](./LICENSE)
@@ -0,0 +1,144 @@
1
+ # opensober
2
+
3
+ > *Stay sober. Nothing is magic.*
4
+
5
+ [English](./README.md) | **简体中文**
6
+
7
+ 一个不装聪明的 opencode 插件。Agent 工具越来越"聪明"、越来越"贴心"、越来越有主张——prompt 背着你被注入、关键字悄悄切模式、fallback 链在你睡觉时烧光 API 配额。opensober 走反方向:每个行为都可见、可关、错了就明摆着让你看见。
8
+
9
+ **状态:** v0.1.x,API 尚未稳定,尚未发布到 npm。
10
+
11
+ ## 为什么
12
+
13
+ - **没有隐形自动化。** 不做关键字切模式。不从 prompt 文本里自动执行命令。每一处上下文注入都在配置里明确命名。
14
+ - **Readonly agent 逃不出沙盒。** Readonly agent 想把任务委派给 writable agent,会在运行时被拒——由 `task` 工具强制,不是靠文档约定。
15
+ - **编辑不会悄悄覆盖过期状态。** `read` 给每一行标上内容哈希;`edit` 如果任何一行的哈希变了,整批拒绝。
16
+
17
+ ## 安装
18
+
19
+ 尚未发布到 npm。本地开发:
20
+
21
+ ```bash
22
+ git clone <本仓库>
23
+ cd opensober
24
+ bun install
25
+ bun run build
26
+ npm pack # 生成 opensober-0.1.0.tgz
27
+ ```
28
+
29
+ 安装到 opencode:
30
+
31
+ ```bash
32
+ cd ~/.config/opencode
33
+ bun add /path/to/opensober-0.1.0.tgz
34
+ ```
35
+
36
+ 在 `~/.config/opencode/opencode.json` 中注册:
37
+
38
+ ```jsonc
39
+ {
40
+ // 用 file URL 指向 opensober 的构建入口
41
+ "plugin": ["file:///path/to/.config/opencode/node_modules/opensober/dist/index.js"],
42
+
43
+ // orchestrator 必须作为静态 primary agent 声明,才会出现在 opencode 的 agent 选择器里
44
+ "agent": {
45
+ "orchestrator": {
46
+ "model": "your-provider/your-model",
47
+ "mode": "primary"
48
+ }
49
+ }
50
+ }
51
+ ```
52
+
53
+ > **注意**:opencode 的 UI agent 列表依赖静态配置,不仅仅来自插件动态注册。
54
+ > 上面的 `orchestrator` 条目是 UI 锚点;opensober 的 `explore` 和 `reviewer`
55
+ > 子 agent 由插件动态注册,通过 `task` 工具调用,不需要静态配置。
56
+
57
+ Peer 依赖:`@opencode-ai/plugin ^1.4.0`。仅支持 Bun(>= 1.3.0),不提供 Node fallback。
58
+
59
+ ## 快速上手
60
+
61
+ 在项目根目录创建 `.opensober/config.jsonc`:
62
+
63
+ ```jsonc
64
+ {
65
+ "version": 1,
66
+ "model": "anthropic/claude-opus-4-6",
67
+ "agents": {
68
+ "quick": {
69
+ "extends": "orchestrator",
70
+ "model": "openai/gpt-5-mini"
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ 检查配置是否加载成功:
77
+
78
+ ```
79
+ $ bunx opensober doctor
80
+
81
+ == opensober doctor ==
82
+
83
+ config
84
+ version: 1
85
+ global model: anthropic/claude-opus-4-6
86
+ layers:
87
+ default (built-in)
88
+ project /repo/.opensober/config.jsonc
89
+
90
+ agents
91
+ explore anthropic/claude-opus-4-6 readonly, no-delegate
92
+ orchestrator anthropic/claude-opus-4-6 writable, delegates
93
+ reviewer anthropic/claude-opus-4-6 readonly, delegates (readonly-only)
94
+ quick openai/gpt-5-mini writable, delegates
95
+
96
+ tools
97
+ edit, read, task
98
+
99
+ warnings
100
+ (none)
101
+ ```
102
+
103
+ 退出码:`0` 干净,`1` 有警告,`2` 配置加载失败。
104
+
105
+ ## 命令
106
+
107
+ | 命令 | 用途 |
108
+ |---|---|
109
+ | `bunx opensober doctor` | 健康检查:配置摘要、agents、工具、警告 |
110
+ | `bunx opensober run` | 加载配置并打印一份 session-ready 摘要 |
111
+ | `bunx opensober install` | *(尚未实现)* |
112
+
113
+ `doctor` 和 `run` 都接受 `--cwd <dir>` 和 `--config <path>`。
114
+
115
+ ## 配置分层
116
+
117
+ 四层按顺序合并,后面的覆盖前面的:
118
+
119
+ 1. **default** — 内置基线
120
+ 2. **user** — `~/.config/opensober/config.jsonc`
121
+ 3. **project** — `<项目根>/.opensober/config.jsonc`
122
+ 4. **cli-override** — `--config <path>`
123
+
124
+ 项目根是向上找最近一个含 `.git` 的目录。找不到时会静默跳过 project 层——单文件 / CI 临时目录也能正常工作。
125
+
126
+ ## 内置 agent
127
+
128
+ 三个开箱即用的 agent:
129
+
130
+ - `orchestrator` — writable,可以委派给任意 agent
131
+ - `explore` — readonly,不能委派
132
+ - `reviewer` — readonly,只能委派给同样 readonly 的 agent
133
+
134
+ 用户自定义 agent 通过 `extends` 继承。权限标记(`readonly`、`can_delegate`)从 parent 链继承;显式覆盖也允许,但 `task` 工具仍会强制:readonly 调用方不能触及 writable 目标。
135
+
136
+ ## 延伸阅读
137
+
138
+ - [`v1-scope.md`](./v1-scope.md) — v1 冻结范围
139
+ - [`CONTRIBUTING.md`](./CONTRIBUTING.md) — 九条硬规则
140
+ - [`round-7.5-memo.md`](./round-7.5-memo.md) — SDK 调研备忘录
141
+
142
+ ## 许可证
143
+
144
+ [MIT](./LICENSE)
@@ -0,0 +1,11 @@
1
+ import { type ErrorSink } from "./format-error";
2
+ export type OutSink = (line: string) => void;
3
+ export interface DoctorOptions {
4
+ readonly cwd?: string | undefined;
5
+ readonly configOverride?: string | undefined;
6
+ readonly userHome?: string | undefined;
7
+ readonly out?: OutSink | undefined;
8
+ readonly err?: ErrorSink | undefined;
9
+ }
10
+ export declare function doctorCommand(opts?: DoctorOptions): number;
11
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,gBAAgB,CAAA;AAE5D,MAAM,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAE5C,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;CACrC;AAYD,wBAAgB,aAAa,CAAC,IAAI,GAAE,aAAkB,GAAG,MAAM,CA8B9D"}
@@ -0,0 +1,3 @@
1
+ export type ErrorSink = (line: string) => void;
2
+ export declare function formatError(err: unknown, write?: ErrorSink): void;
3
+ //# sourceMappingURL=format-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-error.d.ts","sourceRoot":"","sources":["../../src/cli/format-error.ts"],"names":[],"mappings":"AAcA,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAM9C,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,SAAwB,GAAG,IAAI,CA6B/E"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bun
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}