@x-otto/env 0.1.0-alpha.0 → 0.1.0-alpha.10
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/README.md +7 -9
- package/dist/index.d.ts +67 -43
- package/dist/index.js +2 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
# @otto/env
|
|
1
|
+
# @x-otto/env
|
|
2
2
|
|
|
3
3
|
> Environment variable standardization, path constants, and resilience configuration. Zero internal dependencies — the foundational layer of the monorepo.
|
|
4
4
|
|
|
5
|
-
`@otto/env` provides the canonical path constants (dot-otto root, auth path, session dirs, etc.), environment variable normalization helpers, Claude compatibility toggles, process enumeration/liveness probes, config-layer resolution, and the unified resilience config contract. Every other package in the monorepo depends on it — it is the leaf of the dependency graph.
|
|
5
|
+
`@x-otto/env` provides the canonical path constants (dot-otto root, auth path, session dirs, etc.), environment variable normalization helpers, Claude compatibility toggles, process enumeration/liveness probes, config-layer resolution, and the unified resilience config contract. Every other package in the monorepo depends on it — it is the leaf of the dependency graph.
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
pnpm add @otto/env
|
|
10
|
+
pnpm add @x-otto/env
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
## Usage
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
resolveConfigLayers,
|
|
24
24
|
listOttoProcesses,
|
|
25
25
|
isProcessAlive,
|
|
26
|
-
} from '@otto/env'
|
|
26
|
+
} from '@x-otto/env'
|
|
27
27
|
|
|
28
28
|
// Canonical paths
|
|
29
29
|
console.log(OTTO_HOME) // ~/.otto (overridable via OTTO_HOME env)
|
|
@@ -78,7 +78,7 @@ console.log(processes.map(p => `${p.pid}: ${p.command} (${p.etimeMs}ms)`))
|
|
|
78
78
|
### Config Layers
|
|
79
79
|
- `resolveConfigLayers(options)` — enumerate `.otto`/`.claude` × project/user layers
|
|
80
80
|
|
|
81
|
-
### Process Management
|
|
81
|
+
### Process Management
|
|
82
82
|
- `listOttoProcesses(pattern?)` — enumerate otto main processes via `ps`
|
|
83
83
|
- `parseOttoProcessTable(stdout)` — parse `ps` output for testing
|
|
84
84
|
- `isProcessAlive(pid)` — probe process via `process.kill(pid, 0)`
|
|
@@ -86,11 +86,9 @@ console.log(processes.map(p => `${p.pid}: ${p.command} (${p.etimeMs}ms)`))
|
|
|
86
86
|
- `currentHostname()` — local hostname
|
|
87
87
|
- `isContainerEnvironment()` — detect Docker/k8s
|
|
88
88
|
|
|
89
|
-
### Resilience Config
|
|
89
|
+
### Resilience Config
|
|
90
90
|
- `DEFAULT_RESILIENCE_CONFIG` — defaults for all 6 subsystems (stream, network, mcp, schedule, error-retry, oauth)
|
|
91
|
-
- `
|
|
92
|
-
- `parseResilienceEnv(raw, warn?)` — parse `OTTO_RESILIENCE_CONFIG` env
|
|
93
|
-
- `validateResilienceOverride(input, warn)` — validate partial override shape
|
|
91
|
+
- `mergeResilienceConfig(...layers)` — pure merge of already-validated override layers (right wins). Validation moved to `@x-otto/setting` (`validateResilienceOverride`/`parseResilienceEnvOverride`, zod single source, RFC-412 M3)
|
|
94
92
|
|
|
95
93
|
## Dependencies
|
|
96
94
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
//#region src/path-utils.d.ts
|
|
2
|
+
/** 归一化路径并统一为正斜杠分隔(跨平台一致)。 */
|
|
3
|
+
declare function normalizePath(path: string): string;
|
|
4
|
+
//#endregion
|
|
1
5
|
//#region src/build-id.d.ts
|
|
2
|
-
declare const BUILD_ID =
|
|
6
|
+
declare const BUILD_ID = 5515;
|
|
3
7
|
//#endregion
|
|
4
8
|
//#region src/config-layers.d.ts
|
|
5
9
|
/**
|
|
@@ -10,7 +14,7 @@ declare const BUILD_ID = 4512;
|
|
|
10
14
|
* 不含信任门。纯函数、确定性、无副作用。
|
|
11
15
|
*
|
|
12
16
|
* 现状(RFC-044 review S1 + RFC-081 终局复审定档):真实职责 = 派生插件根
|
|
13
|
-
* (`@otto/coding discoverPlugins` 取 otto 层得 `<.otto>/plugins`)。**「四轴收编中央源」经复审判定不迁**
|
|
17
|
+
* (`@x-otto/coding discoverPlugins` 取 otto 层得 `<.otto>/plugins`)。**「四轴收编中央源」经复审判定不迁**
|
|
14
18
|
* (不是待办):command/agent 两个目录扫描轴的 precedence 已完全一致
|
|
15
19
|
* (`plugin < user/claude < user/otto < project/claude < project/otto`,各有 RFC-032 测试守护漂移),
|
|
16
20
|
* 强迁会把清晰的本地 layer 数组换成 `resolveConfigLayers().reverse().filter().map()` 徒增耦合;
|
|
@@ -125,20 +129,26 @@ declare function isContainerEnvironment(): boolean;
|
|
|
125
129
|
//#endregion
|
|
126
130
|
//#region src/resilience.d.ts
|
|
127
131
|
/**
|
|
128
|
-
*
|
|
132
|
+
* 统一重试/超时/退避配置契约 + 纯合并(RFC-230 / RFC-412 M3)。
|
|
129
133
|
*
|
|
130
|
-
* 归口在零依赖叶包 `@otto/env
|
|
131
|
-
* 29 行不该独立成包先例)。四层配置源优先级(右覆盖左):
|
|
134
|
+
* 归口在零依赖叶包 `@x-otto/env`。四层配置源优先级(右覆盖左):
|
|
132
135
|
*
|
|
133
136
|
* 硬编码默认值 → env(`OTTO_RESILIENCE_CONFIG`,JSON 字符串)→ settings(`.otto/config.json`
|
|
134
137
|
* 的 `resilience` 字段)→ 程序化注入(`AppOptions.resilience`)
|
|
135
138
|
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* `
|
|
139
|
-
*
|
|
139
|
+
* **RFC-412 M3 职责收缩**:本文件只负责**契约类型 + 默认值 + 纯合并逻辑**。校验(JSON 解析、
|
|
140
|
+
* 值域约束、字段剔除)已上移到调用方——`@x-otto/setting` 提供唯一的 zod 校验真源
|
|
141
|
+
* (`validateResilienceOverride`/`parseResilienceEnvOverride`),`@x-otto/coding` 的 `App` 在装配
|
|
142
|
+
* 时读 env、经 setting 校验后连同 settings/explicit 三层传入 `mergeResilienceConfig`。
|
|
143
|
+
*
|
|
144
|
+
* 为什么删掉 env 侧的手写校验:此前 env 手写递归校验器与 setting 的 zod schema 是**同一套规则
|
|
145
|
+
* 的两处实现**(stream positive、mcp/schedule nonnegative、oauth min 1000 逐字对应),
|
|
146
|
+
* 注释曾书面自认"不能假设两者永远同步"——双实现漂移风险。收敛到 setting zod 单一真源后,
|
|
147
|
+
* env 回归"默认值 + 合并层"的纯粹职责,零外部依赖特性完整保留(不引入 zod)。
|
|
140
148
|
*
|
|
141
|
-
*
|
|
149
|
+
* 行为变化(有意收敛):字段级非法值此前 env 层会 `console.warn`、settings 层静默 catch——
|
|
150
|
+
* 两层不一致。上移后统一走 setting zod 的静默剔除(`lenient = optional().catch(undefined)`),
|
|
151
|
+
* 消除该不一致;`OTTO_RESILIENCE_CONFIG` 的**整体 JSON 解析失败**仍由 coding 侧 warn(重要诊断)。
|
|
142
152
|
*/
|
|
143
153
|
/** 统一重试/超时/退避配置的完整形状(六个子系统,全部字段均为必填——`DEFAULT_RESILIENCE_CONFIG` 保证完整性)。 */
|
|
144
154
|
interface ResilienceConfig {
|
|
@@ -171,15 +181,17 @@ interface ResilienceConfig {
|
|
|
171
181
|
};
|
|
172
182
|
/** OAuth 跨进程刷新锁(陈旧锁清理阈值 = 等待超时 = 心跳间隔×3,三者必须同步派生,见 RFC-137 规则9)。 */
|
|
173
183
|
oauth: {
|
|
174
|
-
/** 刷新锁超时(ms)。默认 15_000,下限 1_000(心跳间隔 = timeoutMs/3,过小值会导致 setInterval 忙循环,见 RFC-230 二轮评审 P1
|
|
184
|
+
/** 刷新锁超时(ms)。默认 15_000,下限 1_000(心跳间隔 = timeoutMs/3,过小值会导致 setInterval 忙循环,见 RFC-230 二轮评审 P1)。校验在 setting zod(`min(1000)`)。 */refreshLockTimeoutMs: number;
|
|
175
185
|
};
|
|
176
186
|
}
|
|
177
187
|
declare const DEFAULT_RESILIENCE_CONFIG: ResilienceConfig;
|
|
178
188
|
/**
|
|
179
189
|
* `ResilienceConfig` 的深度可选覆盖形状。
|
|
180
190
|
*
|
|
181
|
-
* 手写局部类型,不引入 `@otto/shared` 的 `DeepPartial`——`@otto/env` 是比 `@otto/shared`
|
|
191
|
+
* 手写局部类型,不引入 `@x-otto/shared` 的 `DeepPartial`——`@x-otto/env` 是比 `@x-otto/shared`
|
|
182
192
|
* 更底层的依赖叶子(`shared` 依赖 `env`,反向引入会成环),见 RFC-230 §3 D2 依赖方向核实。
|
|
193
|
+
* `@x-otto/setting` 的 zod `resilienceConfigSchema` 经 `satisfies z.ZodType<ResilienceConfigOverride>`
|
|
194
|
+
* 钉死与本类型同构(字段增减/改名 → 编译报错),是校验真源。
|
|
183
195
|
*/
|
|
184
196
|
interface ResilienceConfigOverride {
|
|
185
197
|
stream?: Partial<ResilienceConfig['stream']>;
|
|
@@ -190,32 +202,21 @@ interface ResilienceConfigOverride {
|
|
|
190
202
|
oauth?: Partial<ResilienceConfig['oauth']>;
|
|
191
203
|
}
|
|
192
204
|
/**
|
|
193
|
-
*
|
|
194
|
-
* `
|
|
205
|
+
* 纯合并:把默认值与若干**已校验**的覆盖层按参数顺序(右覆盖左)深合并为完整的
|
|
206
|
+
* `ResilienceConfig`(永远齐全,不含 undefined 字段)。
|
|
195
207
|
*
|
|
196
|
-
*
|
|
197
|
-
* -
|
|
198
|
-
* - 顶层 key 不在已知的 6 个 key 之内 → 该未知 key 整体剔除(防止拼写错误静默生效误导用户)。
|
|
199
|
-
* - 子字段存在但不是"合法数值"(见 `isValidFieldValue`)→ 单字段剔除,兄弟字段不受影响。
|
|
200
|
-
* - 子字段名不在已知字段名集合内 → 该未知子字段剔除。
|
|
201
|
-
*/
|
|
202
|
-
declare function validateResilienceOverride(input: unknown, warn: (message: string) => void): ResilienceConfigOverride | undefined;
|
|
203
|
-
/** 解析 `OTTO_RESILIENCE_CONFIG` 环境变量(JSON 字符串),非法值整体回退(无法字段级容错,因为连结构都没解析出来)。 */
|
|
204
|
-
declare function parseResilienceEnv(raw: string | undefined, warn?: (message: string) => void): ResilienceConfigOverride | undefined;
|
|
205
|
-
/**
|
|
206
|
-
* 合并四层配置源,返回完整的 `ResilienceConfig`(永远齐全,不含 undefined 字段)。
|
|
208
|
+
* 调用约定(RFC-412 M3):本函数**信任输入已校验**(越界/非法字段应在传入前由调用方经
|
|
209
|
+
* `@x-otto/setting` 的 zod 校验剔除),不做任何值域检查——校验单一真源在 setting。
|
|
207
210
|
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
+
* 典型调用(`@x-otto/coding` App,右覆盖左):
|
|
212
|
+
* `mergeResilienceConfig(fromEnv, fromSettings, explicit)`
|
|
213
|
+
* 其中 fromEnv 来自 `OTTO_RESILIENCE_CONFIG`(经 setting 校验)、fromSettings 来自 settings
|
|
214
|
+
* (加载时已过 setting zod)、explicit 来自程序化注入(经 setting 校验)。
|
|
211
215
|
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
* 携带越界数值(如 settings 层理论上应已被 `@otto/setting` 的 zod schema 拦下,但那是另一个包
|
|
215
|
-
* 的独立校验实现,不能假设它与本包的规则永远同步;`explicit` 是程序化注入,TS 类型只保证是
|
|
216
|
-
* `number` 不保证范围)。统一在合并入口做一次权威校验,避免"同一条规则两处实现、日后漂移"。
|
|
216
|
+
* 实现:层维度循环化——消除此前"每层手写 6 域 `mergeSubObject` 展开"的重复(RFC-412 M3)。
|
|
217
|
+
* 每个覆盖层的每个存在子对象 `Object.assign` 进结果对应域,兄弟字段不丢失。
|
|
217
218
|
*/
|
|
218
|
-
declare function
|
|
219
|
+
declare function mergeResilienceConfig(...layers: readonly (ResilienceConfigOverride | undefined)[]): ResilienceConfig;
|
|
219
220
|
//#endregion
|
|
220
221
|
//#region src/index.d.ts
|
|
221
222
|
/** 清空队列并逐条调 sink。调用方应包一层 `(msg) => process.stderr.write(msg)` 绑定 this。 */
|
|
@@ -229,21 +230,20 @@ declare const normalizeEnv: (value: string | undefined, defaultValue: number) =>
|
|
|
229
230
|
* 到 (0,1](比例语义:0 无意义、>1 超出窗口无意义),越界或非数回退默认值(不静默接受错值)。
|
|
230
231
|
*/
|
|
231
232
|
declare const normalizeEnvFraction: (value: string | undefined, defaultValue: number) => number;
|
|
232
|
-
declare function normalizePath(path: string): string;
|
|
233
233
|
/**
|
|
234
234
|
* 从 `startDir` 向上查找最近的 `pnpm-workspace.yaml`(monorepo root 标志文件),返回其所在目录。
|
|
235
235
|
* 找不到(如在非本仓的用户项目里运行)返回 `undefined`。
|
|
236
236
|
*
|
|
237
|
-
* RFC-130:单一真源实现——原先在 `@otto/coding`(`install-plugin.ts`,供 CLI `--repo` 消费)与
|
|
238
|
-
* `@otto/plugin`(`discovery.ts`,供仓库级插件发现消费)各自维护一份逐字相同的实现(copy-paste),
|
|
239
|
-
* 无法互相 import(`@otto/plugin` 是 `@otto/coding` 的依赖,反向 import 会成环)。收敛到零依赖的
|
|
240
|
-
* `@otto/env`(两者共同的底层依赖)消除维护漂移风险(终局审核 finding,2026-07-09)。
|
|
237
|
+
* RFC-130:单一真源实现——原先在 `@x-otto/coding`(`install-plugin.ts`,供 CLI `--repo` 消费)与
|
|
238
|
+
* `@x-otto/plugin`(`discovery.ts`,供仓库级插件发现消费)各自维护一份逐字相同的实现(copy-paste),
|
|
239
|
+
* 无法互相 import(`@x-otto/plugin` 是 `@x-otto/coding` 的依赖,反向 import 会成环)。收敛到零依赖的
|
|
240
|
+
* `@x-otto/env`(两者共同的底层依赖)消除维护漂移风险(终局审核 finding,2026-07-09)。
|
|
241
241
|
*
|
|
242
242
|
* 终止条件用 `dirname(dir) === dir`(到达文件系统根)而非固定层数上限——后者在深层嵌套路径下
|
|
243
243
|
* 会误截断(旧实现的 `i < 20` 上限已移除,审核 finding:该上限是冗余约束)。
|
|
244
244
|
*/
|
|
245
245
|
declare function findWorkspaceRoot(startDir: string): string | undefined;
|
|
246
|
-
/** SDK 版本号(`@otto/env` package.json version),会话创建时戳入 metadata。 */
|
|
246
|
+
/** SDK 版本号(`@x-otto/env` package.json version),会话创建时戳入 metadata。 */
|
|
247
247
|
declare const SDK_VERSION: string;
|
|
248
248
|
declare const OTTO_USER_AGENT: string;
|
|
249
249
|
declare const OTTO_ROOT = ".otto";
|
|
@@ -315,6 +315,30 @@ declare const SERVICE_URL: string;
|
|
|
315
315
|
* 当前 env,既 testable(测试可运行时改 env)又始终反映真实值。
|
|
316
316
|
*/
|
|
317
317
|
declare const resolveNpmSniffRegistries: () => readonly string[];
|
|
318
|
+
/**
|
|
319
|
+
* RFC-341 B6/D9 同模式:内网可达性探测目标 URL(逗号分隔候选,缺省空)。
|
|
320
|
+
*
|
|
321
|
+
* 用途(两处消费方,同一份判断结果):① Setup Wizard 是否展示企业内网 provider 选项
|
|
322
|
+
* (此前只查"用户是否已手动 /registry add 内网源",新用户从未配过就永远看不到);
|
|
323
|
+
* ② 走企业内网网关的 provider 模型可用性判定——即使凭据配置正确,脱离内网时物理不可达,
|
|
324
|
+
* 此前只判凭据不判网络,用户要等真正发请求失败才发现模型选错了。
|
|
325
|
+
*
|
|
326
|
+
* 公网源码缺省空 = 零内网痕迹(D1 隔离红线,同 `resolveNpmSniffRegistries` doc)——本文件
|
|
327
|
+
* 及其消费方是公网发布包,不硬编码任何具体内网域名/凭据环境变量名(含本 doc 注释本身,
|
|
328
|
+
* 敏感词扫描 `scan-public-sensitive.mjs` 会扫描含注释的 `.d.ts` 产物)。内网构建/用户
|
|
329
|
+
* 通过环境变量注入真实探测地址。call-time 解析,消费方 `intranet-probe.ts` 每次查表都
|
|
330
|
+
* 读当前 env。
|
|
331
|
+
*
|
|
332
|
+
* 2026-08-14 举一反三修复:env 注入不再是唯一候选——消费方可以把「目标资源自身地址」
|
|
333
|
+
* (provider 插件 manifest 声明的 baseUrl)经 `isIntranetReachable(force, extraUrls)`
|
|
334
|
+
* 并入候选。真实内网用户通常不配置本 env,而目标地址就写在插件声明里,探测它才是
|
|
335
|
+
* 可达性最直接的证据(URL 运行时供给,公网发布包仍零内网硬编码)。
|
|
336
|
+
*
|
|
337
|
+
* 探测语义(同日用户指令「ping 通即可」):候选 URL 只取其 host:port 做 TCP 握手,
|
|
338
|
+
* 不要求目标提供 HTTP 服务——探测的是网络层通不通,与应用层无关(见
|
|
339
|
+
* intranet-probe.ts 文件头)。因此候选写任意内网可达的 host 即可,路径无意义。
|
|
340
|
+
*/
|
|
341
|
+
declare const resolveIntranetProbeUrls: () => readonly string[];
|
|
318
342
|
declare const LOG_LEVEL: "info" | "warn" | "error" | "debug" | "trace" | "fatal";
|
|
319
343
|
declare const SETTING_OFFLINE_MODE_ENABLED: boolean;
|
|
320
344
|
/**
|
|
@@ -322,7 +346,7 @@ declare const SETTING_OFFLINE_MODE_ENABLED: boolean;
|
|
|
322
346
|
* 而非 offline 的模块级 const)。
|
|
323
347
|
*
|
|
324
348
|
* 为什么必须函数式而非 const:`OTTO_SHADOW` 由 `packages/cli/src/cli.ts` 在**运行时**
|
|
325
|
-
* 解析 `--shadow` flag 后写入 `process.env`,而 `@otto/env` 在 cli.ts 顶部就被 import——
|
|
349
|
+
* 解析 `--shadow` flag 后写入 `process.env`,而 `@x-otto/env` 在 cli.ts 顶部就被 import——
|
|
326
350
|
* 若用模块级 const,常量在 flag 写入前就已冻结为 false。调用时求值规避此时序陷阱,
|
|
327
351
|
* 也便于测试注入。(offline 模式可用 const 是因为 `OTTO_OFFLINE` 由外部 shell 预设、
|
|
328
352
|
* node 启动前就存在——两者注入时机不同,范式不能照搬。)
|
|
@@ -330,7 +354,7 @@ declare const SETTING_OFFLINE_MODE_ENABLED: boolean;
|
|
|
330
354
|
* 语义:为真时该进程及其全部子进程/worker 在整个生命周期内不向磁盘写入任何 otto 自有
|
|
331
355
|
* 状态(凭据/会话/记忆/配置/trace/日志),既有磁盘状态照常只读继承(overlay 语义)。
|
|
332
356
|
*
|
|
333
|
-
* 传染面:`OTTO_SHADOW` 走 `OTTO_` 前缀,由 `@otto/shared` 的 `buildAllowedEnv` 白名单
|
|
357
|
+
* 传染面:`OTTO_SHADOW` 走 `OTTO_` 前缀,由 `@x-otto/shared` 的 `buildAllowedEnv` 白名单
|
|
334
358
|
* 自动透传给全部 spawn 子进程;worker_threads 共享 `process.env` 天然继承——无需额外接线。
|
|
335
359
|
*
|
|
336
360
|
* 判断该开关的位置受 RFC-345 §D1 白名单约束(架构门禁强制),不得在业务层散落 `if (shadow)`。
|
|
@@ -349,5 +373,5 @@ interface UserIdentity {
|
|
|
349
373
|
/** 从 identity.json 加载 UserIdentity。文件不存在/解析失败返回 null。 */
|
|
350
374
|
declare function loadUserIdentity(path?: string): Promise<UserIdentity | null>;
|
|
351
375
|
//#endregion
|
|
352
|
-
export { AUTH_PATH, BUILD_ID, CLAUDE_HOME, CLAUDE_ROOT, type ConfigLayer, type ConfigLayerKind, type ConfigLayerScope, DEFAULT_RESILIENCE_CONFIG, type DecodedLeaseToken, LOG_FILE, LOG_LEVEL, OTTO_CONFIG_FILENAME, OTTO_DAEMON_DIR, OTTO_HOME, OTTO_IDENTITY_PATH, OTTO_PROJECT_CONFIG_RELPATH, OTTO_PROJECT_DIR, OTTO_ROOT, OTTO_SESSIONS_DIR, OTTO_SESSION_LOCKS_DIR, OTTO_USER_AGENT, OTTO_USER_CONFIG_DIR, type OttoProcessInfo, type ResilienceConfig, type ResilienceConfigOverride, type ResolveConfigLayersOptions, SDK_VERSION, SERVICE_PORT, SERVICE_URL, SETTING_OFFLINE_MODE_ENABLED, UserIdentity, currentHostname, decodeLeaseToken, drainEnvWarnings, encodeLeaseToken, findWorkspaceRoot, flushEnvWarnings, isClaudeCompatEnabled, isClaudeHooksCompatEnabled, isClaudeSettingsCompatEnabled, isContainerEnvironment, isProcessAlive, isShadowModeEnabled, listOttoProcesses, loadUserIdentity, normalizeEnv, normalizeEnvFraction, normalizePath, parseEtimeMs, parseOttoProcessTable,
|
|
376
|
+
export { AUTH_PATH, BUILD_ID, CLAUDE_HOME, CLAUDE_ROOT, type ConfigLayer, type ConfigLayerKind, type ConfigLayerScope, DEFAULT_RESILIENCE_CONFIG, type DecodedLeaseToken, LOG_FILE, LOG_LEVEL, OTTO_CONFIG_FILENAME, OTTO_DAEMON_DIR, OTTO_HOME, OTTO_IDENTITY_PATH, OTTO_PROJECT_CONFIG_RELPATH, OTTO_PROJECT_DIR, OTTO_ROOT, OTTO_SESSIONS_DIR, OTTO_SESSION_LOCKS_DIR, OTTO_USER_AGENT, OTTO_USER_CONFIG_DIR, type OttoProcessInfo, type ResilienceConfig, type ResilienceConfigOverride, type ResolveConfigLayersOptions, SDK_VERSION, SERVICE_PORT, SERVICE_URL, SETTING_OFFLINE_MODE_ENABLED, UserIdentity, currentHostname, decodeLeaseToken, drainEnvWarnings, encodeLeaseToken, findWorkspaceRoot, flushEnvWarnings, isClaudeCompatEnabled, isClaudeHooksCompatEnabled, isClaudeSettingsCompatEnabled, isContainerEnvironment, isProcessAlive, isShadowModeEnabled, listOttoProcesses, loadUserIdentity, mergeResilienceConfig, normalizeEnv, normalizeEnvFraction, normalizePath, parseEtimeMs, parseOttoProcessTable, resolveConfigLayers, resolveIntranetProbeUrls, resolveNpmSniffRegistries };
|
|
353
377
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{homedir as e,hostname as t}from"node:os";import{existsSync as n,readFileSync as r}from"node:fs";import{dirname as i,join as a,normalize as o,sep as s}from"node:path";import{spawnSync as c}from"node:child_process";const
|
|
2
|
-
`)){if(!r.includes(t))continue;let e=r.match(/^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(.*)$/);if(!e)continue;let[,i,a,o,s,c,l]=e;l.includes(`spawn-helper`)||n.push({pid:Number(i),ppid:Number(a),rssKb:Number(o),tty:s,etimeMs:
|
|
1
|
+
import{homedir as e,hostname as t}from"node:os";import{existsSync as n,readFileSync as r}from"node:fs";import{dirname as i,join as a,normalize as o,sep as s}from"node:path";import{spawnSync as c}from"node:child_process";function l(e){return o(e).replaceAll(s===`\\`?`\\`:s,`/`)}const u=5515;function d(e){let{cwd:t,homedir:n,workspaceRoot:r}=e,i=e.claudeCompat??U(),o=[];return o.push({kind:`otto`,scope:`project`,dir:l(a(t,`.otto`))}),r&&l(r)!==l(t)&&o.push({kind:`otto`,scope:`repository`,dir:l(a(r,`.otto`))}),i&&o.push({kind:`claude`,scope:`project`,dir:l(a(t,`.claude`))}),n&&o.push({kind:`otto`,scope:`user`,dir:l(a(n,`.otto`))}),i&&n&&o.push({kind:`claude`,scope:`user`,dir:l(a(n,`.claude`))}),o}function f(e){try{return process.kill(e,0),!0}catch{return!1}}function p(){return t()}function m(e,t,n){return`${e}:${t}:${n}`}function h(e){let t=e.indexOf(`:`);if(t===-1)return{token:e};let n=e.indexOf(`:`,t+1);if(n===-1)return{token:e};let r=e.slice(0,t),i=e.slice(t+1,n),a=e.slice(n+1),o=Number(i),s=Number.isFinite(o)&&o>0?o:void 0;return s!==void 0&&a.length>0?{token:r,pid:s,host:a}:{token:r}}function g(e){let t=e.trim().match(/^(?:(\d+)-)?(?:(\d+):)?(\d+):(\d+)$/);if(!t)return 0;let[,n,r,i,a]=t;return(Number(n??0)*86400+Number(r??0)*3600+Number(i)*60+Number(a))*1e3}function _(e){return e.match(/--continue\s+([0-9a-f-]{36})/)?.[1]}function v(e){let t=e.match(/--restart-generation=(\d+)/);return t?Number(t[1]):void 0}function y(e=`bin/otto.js`){let t=c(`ps`,[`-axo`,`pid=,ppid=,rss=,tty=,etime=,args=`],{encoding:`utf8`,timeout:1e4,maxBuffer:16*1024*1024});return t.status!==0||!t.stdout?[]:b(t.stdout,e)}function b(e,t=`bin/otto.js`){let n=[];for(let r of e.split(`
|
|
2
|
+
`)){if(!r.includes(t))continue;let e=r.match(/^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(.*)$/);if(!e)continue;let[,i,a,o,s,c,l]=e;l.includes(`spawn-helper`)||n.push({pid:Number(i),ppid:Number(a),rssKb:Number(o),tty:s,etimeMs:g(c),command:l,sessionId:_(l),generation:v(l)})}return n}function x(){if(process.platform===`darwin`)return!1;try{if(n(`/.dockerenv`))return!0;if(n(`/proc/1/cgroup`)){let e=r(`/proc/1/cgroup`,`utf8`);return/docker|kubepods|containerd/.test(e)}}catch{}return!1}const S={stream:{maxRetries:5,initialDelayMs:500,backoffFactor:2,maxDelayMs:6e4},networkDisconnect:{maxRetries:5,intervalMs:3e4},mcp:{maxReconnectAttempts:3,reconnectDelayMs:500,requestTimeoutMs:3e4},schedule:{retryBackoffMs:0},errorRetry:{maxAttempts:5,intervalMs:3e4},oauth:{refreshLockTimeoutMs:15e3}};function C(...e){let t={stream:{...S.stream},networkDisconnect:{...S.networkDisconnect},mcp:{...S.mcp},schedule:{...S.schedule},errorRetry:{...S.errorRetry},oauth:{...S.oauth}};for(let n of e)if(n)for(let e of Object.keys(t)){let r=n[e];r&&Object.assign(t[e],r)}return t}const w=[];function ee(e){let t=w.splice(0);for(let n of t)e(n)}function T(){return w.splice(0)}const E=(e,t)=>{if(e===void 0)return t;let n=parseInt(e,10);return isNaN(n)||n<=0?(w.push(`Invalid environment variable value: ${e}. Using default: ${t}`),t):n},D=(e,t)=>{if(e===void 0)return t;let n=parseFloat(e);return isNaN(n)||n<=0||n>1?(w.push(`Invalid fraction environment variable value: ${e}. Using default: ${t}`),t):n};function O(e){let t=e;for(;;){if(n(a(t,`pnpm-workspace.yaml`)))return t;let e=i(t);if(e===t)return;t=e}}function k(){try{let e=l(`${l(new URL(`.`,import.meta.url).pathname)}/../package.json`);return JSON.parse(r(e,`utf-8`)).version||`unknown`}catch{return`unknown`}}const A=k(),j=`otto/${A}`,M=`.otto`,N=process.env.OTTO_CONFIG_FILENAME||`config.json`,P=`${M}/${N}`,F=l(process.env.OTTO_HOME||`${e()}/.otto`),I=`${F}/sessions`,L=`${I}/locks`,R=`${F}/daemon`,z=l(e()+`/.config/otto`),B=l(`${process.cwd()}/${M}`),V=`.claude`,H=l(`${e()}/${V}`);function U(){let e=process.env.OTTO_CLAUDE_COMPAT?.toLowerCase();return!(e===`0`||e===`false`||e===`no`||e===`off`)}function W(){if(!U())return!1;let e=process.env.OTTO_CLAUDE_COMPAT_SETTINGS?.toLowerCase();return e===`1`||e===`true`||e===`yes`||e===`on`}function G(){if(!U())return!1;let e=process.env.OTTO_CLAUDE_COMPAT_HOOKS?.toLowerCase();return e===`1`||e===`true`||e===`yes`||e===`on`}const K=process.env.OTTO_LOG_FILE?l(process.env.OTTO_LOG_FILE):``,q=E(process.env.OTTO_SERVICE_PORT,8417),J=process.env.OTTO_SERVICE_URL??`http://127.0.0.1:${q}`,Y=()=>(process.env.OTTO_NPM_SNIFF_REGISTRIES??``).split(`,`).map(e=>e.trim().replace(/\/+$/,``)).filter(e=>e.length>0),X=()=>(process.env.OTTO_INTRANET_PROBE_URLS??``).split(`,`).map(e=>e.trim().replace(/\/+$/,``)).filter(e=>e.length>0),Z=process.env.OTTO_LOG_LEVEL||(process.env.NODE_ENV===`production`?`info`:`trace`),Q=process.env.OTTO_OFFLINE===`1`||process.env.OTTO_OFFLINE?.toLowerCase()===`true`||process.env.OTTO_OFFLINE?.toLowerCase()===`yes`;function te(){let e=process.env.OTTO_SHADOW?.toLowerCase();return e===`1`||e===`true`||e===`yes`||e===`on`}const ne=l(process.env.OTTO_AUTH_PATH||`${z}/auth.json`),$=l(process.env.OTTO_IDENTITY_PATH||`${F}/identity.json`);async function re(e){let t=e??$;try{let{readFile:e}=await import(`node:fs/promises`),n=await e(t,`utf-8`),r=JSON.parse(n);return typeof r.userId==`string`&&typeof r.token==`string`&&typeof r.serviceUrl==`string`&&typeof r.loginAt==`number`?r:null}catch{return null}}export{ne as AUTH_PATH,u as BUILD_ID,H as CLAUDE_HOME,V as CLAUDE_ROOT,S as DEFAULT_RESILIENCE_CONFIG,K as LOG_FILE,Z as LOG_LEVEL,N as OTTO_CONFIG_FILENAME,R as OTTO_DAEMON_DIR,F as OTTO_HOME,$ as OTTO_IDENTITY_PATH,P as OTTO_PROJECT_CONFIG_RELPATH,B as OTTO_PROJECT_DIR,M as OTTO_ROOT,I as OTTO_SESSIONS_DIR,L as OTTO_SESSION_LOCKS_DIR,j as OTTO_USER_AGENT,z as OTTO_USER_CONFIG_DIR,A as SDK_VERSION,q as SERVICE_PORT,J as SERVICE_URL,Q as SETTING_OFFLINE_MODE_ENABLED,p as currentHostname,h as decodeLeaseToken,T as drainEnvWarnings,m as encodeLeaseToken,O as findWorkspaceRoot,ee as flushEnvWarnings,U as isClaudeCompatEnabled,G as isClaudeHooksCompatEnabled,W as isClaudeSettingsCompatEnabled,x as isContainerEnvironment,f as isProcessAlive,te as isShadowModeEnabled,y as listOttoProcesses,re as loadUserIdentity,C as mergeResilienceConfig,E as normalizeEnv,D as normalizeEnvFraction,l as normalizePath,g as parseEtimeMs,b as parseOttoProcessTable,d as resolveConfigLayers,X as resolveIntranetProbeUrls,Y as resolveNpmSniffRegistries};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@x-otto/env",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.10",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist"
|
|
6
6
|
],
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
"tag": "alpha"
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
|
-
"build": "tsdown && rm -f dist/*.map && sed -i '' '\\|//# sourceMappingURL=|d' dist/*.js
|
|
22
|
+
"build": "node ../../scripts/gen-build-id.mjs && tsdown && rm -f dist/*.map && sed -i '' '\\|//# sourceMappingURL=|d' dist/*.js 2>/dev/null; true",
|
|
23
23
|
"typecheck:project": "tsc -p tsconfig.json --noEmit",
|
|
24
24
|
"typecheck:file": "tsc src/index.ts --noEmit --target ES2024 --module ESNext --moduleResolution bundler --esModuleInterop --skipLibCheck",
|
|
25
25
|
"typecheck": "tsc --noEmit",
|
|
26
26
|
"clean": "rm -rf dist"
|
|
27
27
|
}
|
|
28
|
-
}
|
|
28
|
+
}
|