Compare commits
2
Commits
b2
...
docs/sync-outdated
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5dbefb27e | ||
|
|
1c1abf3069 |
+31
-16
@@ -4,23 +4,38 @@
|
|||||||
|
|
||||||
## High-Level Flow
|
## High-Level Flow
|
||||||
|
|
||||||
1. `internal/market` fetches the registry and server metadata.
|
1. `cmd` is the CLI entrypoint, invoking `internal/app` to build the root Cobra command tree.
|
||||||
2. `internal/discovery` resolves runtime server capabilities and caches results.
|
2. `internal/app` wires static utility commands (`auth`, `audit`, `schema`, `completion`) and dynamically loads product commands via `internal/plugin`.
|
||||||
3. `internal/ir` normalizes discovery output into one canonical tool catalog.
|
3. `internal/helpers` contains the main command handlers for all product surfaces (`dev`, `chat`, `calendar`, `contact`, `aitable`, etc.).
|
||||||
4. `internal/cli` and `internal/app` mount that catalog into the public Cobra command tree.
|
4. `internal/executor` and `internal/transport` execute MCP JSON-RPC calls; `internal/output` formats responses.
|
||||||
5. `internal/transport` executes MCP JSON-RPC calls and `internal/output` formats responses.
|
5. `internal/auth` manages login state, PAT tokens, and agent-code detection.
|
||||||
|
|
||||||
## Repository Structure
|
## Repository Structure
|
||||||
|
|
||||||
- `cmd`: CLI entrypoint
|
- `cmd`: CLI entrypoint
|
||||||
- `internal/app`: root command wiring and static utility commands
|
- `internal/app`: root command wiring, static utility commands, and plugin loading
|
||||||
- `internal/discovery`, `internal/market`, `internal/transport`: runtime discovery and execution
|
- `internal/helpers`: product command handlers (dev, chat, calendar, contact, etc.)
|
||||||
- `internal/ir`: canonical intermediate representation for discovered tools
|
- `internal/plugin`: plugin-based dynamic command loader
|
||||||
- `internal/generator`: docs, schema, and skill generation pipeline
|
- `internal/cli`: catalog types and endpoint loader (static endpoint mode)
|
||||||
- `internal/compat`, `internal/helpers`: legacy-compatible overlays and helper commands
|
- `internal/executor`: invocation dispatch and result handling
|
||||||
- `skills/`: bundled agent skills source and generated skill docs
|
- `internal/transport`: MCP HTTP client and request signing
|
||||||
- `test/`: CLI, compatibility, integration, contract, and script tests
|
- `internal/auth`: login, token management, agent-code detection, identity
|
||||||
|
- `internal/audit`: user operation audit log (JSONL, hash chain, forwarding)
|
||||||
## Public Repository Contract
|
- `internal/errors`: structured error model with categories and hints
|
||||||
|
- `internal/keychain`: OS keychain integration for credential storage
|
||||||
This repository ships source, docs, tests, packaging templates, and install scripts. Generated or release-only artifacts are produced by repository scripts and are not required to exist in a clean checkout unless explicitly committed as part of a release workflow.
|
- `internal/security`: endpoint allowlist and domain trust
|
||||||
|
- `internal/safety`: runtime safety checks (confirm prompts, dry-run guards)
|
||||||
|
- `internal/cobracmd`: shared Cobra command builders
|
||||||
|
- `internal/pat`: PAT (Personal Access Token) authorization flow
|
||||||
|
- `internal/output`: response formatting (json, table, raw, pretty)
|
||||||
|
- `internal/logging`: structured logging and argument sanitization
|
||||||
|
- `internal/tui`: terminal UI helpers
|
||||||
|
- `internal/recovery`: panic recovery and graceful degradation
|
||||||
|
- `pkg/configmeta`: environment variable registry and documentation
|
||||||
|
- `pkg/config`: configuration constants and paths
|
||||||
|
- `pkg/edition`: edition detection (oss vs enterprise)
|
||||||
|
- `pkg/mcptypes`: MCP protocol type definitions
|
||||||
|
- `skills/`: bundled agent skills (mono/ and multi/ layouts)
|
||||||
|
- `test/`: CLI, integration, contract, unit, and skill E2E tests
|
||||||
|
- `scripts/`: install scripts, policy checks, and CI helpers
|
||||||
|
- `envelope/`: pre-built discovery payloads for offline use
|
||||||
|
|||||||
@@ -0,0 +1,227 @@
|
|||||||
|
# 审计日志(Audit Log)
|
||||||
|
|
||||||
|
DWS 自动记录每次 MCP HTTP 调用的审计事件,用于合规追溯和安全审查。默认启用,无需额外配置。
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
- **自动记录**:每次命令执行产生一条 JSONL 审计事件
|
||||||
|
- **按天轮转**:日志文件按日期分割(`audit-YYYYMMDD.jsonl`),默认留存 90 天
|
||||||
|
- **防篡改**:L1 哈希链(sha256),每条事件链接前一条的 hash,可验证完整性
|
||||||
|
- **远端转发**:支持 POST 到外部 SIEM 或审计平台
|
||||||
|
- **三级脱敏**:转发时可按 none/hashed/minimal 脱敏敏感字段
|
||||||
|
- **CLI 命令**:内置 `dws audit tail/export/verify` 查看和验证
|
||||||
|
|
||||||
|
## 环境变量
|
||||||
|
|
||||||
|
| 变量 | 默认值 | 说明 |
|
||||||
|
|------|--------|------|
|
||||||
|
| `DWS_AUDIT` | 启用 | 设 `0`/`false`/`off` 关闭审计 |
|
||||||
|
| `DWS_AUDIT_DIR` | `~/.dws/audit` | 审计日志目录 |
|
||||||
|
| `DWS_AUDIT_RETENTION_DAYS` | `90` | 日志留存天数 |
|
||||||
|
| `DWS_AUDIT_FORWARD_URL` | (空) | 远端转发 URL(POST JSON) |
|
||||||
|
| `DWS_AUDIT_FORWARD_TOKEN` | (空) | 远端转发 Bearer Token |
|
||||||
|
| `DWS_AUDIT_FORWARD_REDACT` | `none` | 转发脱敏级别:`none`/`hashed`/`minimal` |
|
||||||
|
|
||||||
|
## 审计事件格式
|
||||||
|
|
||||||
|
每条事件是一行 JSON,字段如下:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ts": "2026-07-06T10:59:06+08:00",
|
||||||
|
"execution_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
||||||
|
"agent_id": "agent-xxx",
|
||||||
|
"actor": {
|
||||||
|
"user_id": "525018",
|
||||||
|
"name": "胡奕舟",
|
||||||
|
"corp_id": "ding8196cd9a2b2405da24f2f5cc6abecb85",
|
||||||
|
"corp_name": "钉钉"
|
||||||
|
},
|
||||||
|
"product": "calendar",
|
||||||
|
"command": "list_events",
|
||||||
|
"endpoint": "https://api.dingtalk.com/v1.0/calendar/users/xxx/calendars/primary/events",
|
||||||
|
"params_summary": "maxResults=20",
|
||||||
|
"result": "success",
|
||||||
|
"error_category": "",
|
||||||
|
"error_reason": "",
|
||||||
|
"duration_ms": 234,
|
||||||
|
"cli_version": "1.0.47",
|
||||||
|
"os": "darwin",
|
||||||
|
"arch": "arm64",
|
||||||
|
"prev_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||||
|
"hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**字段说明**:
|
||||||
|
|
||||||
|
- `ts`:事件时间戳(RFC3339)
|
||||||
|
- `execution_id`:本次命令执行的唯一 ID
|
||||||
|
- `agent_id`:Agent 标识(若有)
|
||||||
|
- `actor`:执行者信息(从登录态获取)
|
||||||
|
- `product`:调用的产品(如 `calendar`、`chat`、`contact`)
|
||||||
|
- `command`:调用的命令(如 `list_events`、`send_message`)
|
||||||
|
- `endpoint`:实际请求的 API 端点(已脱敏)
|
||||||
|
- `params_summary`:参数摘要(已脱敏)
|
||||||
|
- `result`:`success` 或 `error`
|
||||||
|
- `error_category` / `error_reason`:错误分类和原因(成功时为空)
|
||||||
|
- `duration_ms`:命令执行耗时(毫秒)
|
||||||
|
- `prev_hash` / `hash`:哈希链字段,用于防篡改验证
|
||||||
|
|
||||||
|
## CLI 命令
|
||||||
|
|
||||||
|
### 查看最近日志
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看最近 20 条审计事件(默认)
|
||||||
|
dws audit tail
|
||||||
|
|
||||||
|
# 查看最近 50 条
|
||||||
|
dws audit tail -n 50
|
||||||
|
```
|
||||||
|
|
||||||
|
输出示例:
|
||||||
|
|
||||||
|
```
|
||||||
|
2026-07-06 10:59:06 calendar list_events user=525018 result=success 234ms
|
||||||
|
2026-07-06 10:58:42 chat send_message user=525018 result=success 156ms
|
||||||
|
2026-07-06 10:57:15 contact search user=525018 result=success 89ms
|
||||||
|
```
|
||||||
|
|
||||||
|
### 导出日志
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 导出最近 7 天的 JSONL
|
||||||
|
dws audit export --since 2026-06-29 --until 2026-07-06 --format jsonl > audit-7d.jsonl
|
||||||
|
|
||||||
|
# 导出为 CSV(方便 Excel 打开)
|
||||||
|
dws audit export --since 2026-07-01 --format csv > audit-july.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
### 验证哈希链
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 验证当前最新日志文件的哈希链完整性
|
||||||
|
dws audit verify
|
||||||
|
|
||||||
|
# 验证指定文件
|
||||||
|
dws audit verify --file ~/.dws/audit/audit-20260706.jsonl
|
||||||
|
```
|
||||||
|
|
||||||
|
输出:
|
||||||
|
|
||||||
|
```
|
||||||
|
✓ 哈希链完整:234 条事件全部校验通过
|
||||||
|
```
|
||||||
|
|
||||||
|
或:
|
||||||
|
|
||||||
|
```
|
||||||
|
✗ 哈希链断裂:第 156 条事件的 hash 不匹配
|
||||||
|
```
|
||||||
|
|
||||||
|
## 哈希链防篡改
|
||||||
|
|
||||||
|
每条事件的 `hash` 字段由以下公式计算:
|
||||||
|
|
||||||
|
```
|
||||||
|
hash = sha256(prev_hash + event_json_without_hash_fields)
|
||||||
|
```
|
||||||
|
|
||||||
|
- 首条事件的 `prev_hash` 为空字符串
|
||||||
|
- 后续事件的 `prev_hash` = 前一条的 `hash`
|
||||||
|
- 任何对历史事件的篡改都会导致后续所有 hash 失效
|
||||||
|
|
||||||
|
**验证流程**:
|
||||||
|
|
||||||
|
1. 读取日志文件,逐行解析
|
||||||
|
2. 对每条事件,移除 `prev_hash` 和 `hash` 字段,重新序列化
|
||||||
|
3. 用前一条的 hash + 当前事件 JSON 计算新 hash
|
||||||
|
4. 对比计算结果与文件中记录的 hash
|
||||||
|
5. 全部匹配 = 完整;某条不匹配 = 被篡改
|
||||||
|
|
||||||
|
## 远端转发
|
||||||
|
|
||||||
|
设置 `DWS_AUDIT_FORWARD_URL` 后,每条审计事件会异步 POST 到指定端点:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export DWS_AUDIT_FORWARD_URL=https://siem.example.com/ingest/audit
|
||||||
|
export DWS_AUDIT_FORWARD_TOKEN=your-bearer-token # 可选
|
||||||
|
```
|
||||||
|
|
||||||
|
**请求格式**:
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /ingest/audit HTTP/1.1
|
||||||
|
Host: siem.example.com
|
||||||
|
Authorization: Bearer your-bearer-token
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{"ts":"2026-07-06T10:59:06+08:00","product":"calendar",...}
|
||||||
|
```
|
||||||
|
|
||||||
|
**超时与重试**:3 秒超时,失败不阻塞命令执行(best-effort),不自动重试。
|
||||||
|
|
||||||
|
## 脱敏分级
|
||||||
|
|
||||||
|
转发时可通过 `DWS_AUDIT_FORWARD_REDACT` 控制脱敏级别:
|
||||||
|
|
||||||
|
| 级别 | 行为 | 适用场景 |
|
||||||
|
|------|------|----------|
|
||||||
|
| `none`(默认) | 原样转发,不脱敏 | 内部审计平台 |
|
||||||
|
| `hashed` | actor.name 哈希化,params_summary 脱敏 | 跨部门共享 |
|
||||||
|
| `minimal` | 仅保留 ts/product/command/result/duration_ms,移除 actor/endpoint/params | 对外合规报告 |
|
||||||
|
|
||||||
|
**示例**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 最小化脱敏(仅保留元数据)
|
||||||
|
export DWS_AUDIT_FORWARD_REDACT=minimal
|
||||||
|
export DWS_AUDIT_FORWARD_URL=https://compliance.example.com/audit
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### Q: 审计日志占多少磁盘?
|
||||||
|
|
||||||
|
典型场景(每天 100 条命令)约 50KB/天,90 天约 4.5MB。日志文件是 JSONL 纯文本,gzip 压缩后约 1/5。
|
||||||
|
|
||||||
|
### Q: 关闭审计会影响性能吗?
|
||||||
|
|
||||||
|
设置 `DWS_AUDIT=0` 后,审计模块不初始化,零开销。默认启用时,每条事件写入耗时 <1ms(异步磁盘 IO)。
|
||||||
|
|
||||||
|
### Q: 哈希链断了怎么办?
|
||||||
|
|
||||||
|
可能原因:
|
||||||
|
1. 手动编辑过日志文件
|
||||||
|
2. 磁盘损坏
|
||||||
|
3. 并发写入导致顺序错乱(罕见)
|
||||||
|
|
||||||
|
**处理**:
|
||||||
|
- 备份当前日志
|
||||||
|
- 用 `dws audit verify` 定位断裂位置
|
||||||
|
- 从断裂点之后的事件可继续验证(前缀已不可信)
|
||||||
|
|
||||||
|
### Q: 如何清理旧日志?
|
||||||
|
|
||||||
|
自动清理:`DWS_AUDIT_RETENTION_DAYS=90`(默认),超过 90 天的文件在下次启动时 best-effort 删除。
|
||||||
|
|
||||||
|
手动清理:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 删除 2026 年 6 月之前的日志
|
||||||
|
rm ~/.dws/audit/audit-202605*.jsonl
|
||||||
|
```
|
||||||
|
|
||||||
|
## 技术实现
|
||||||
|
|
||||||
|
- **核心包**:`internal/audit`
|
||||||
|
- **集成点**:`internal/app/runner.go` 的 `executeInvocation` 方法(defer 调用 `emitAudit`)
|
||||||
|
- **身份获取**:从 `auth.LoadTokenData` 读取当前登录用户
|
||||||
|
- **参数脱敏**:调用 `logging.SanitizeArguments`(与现有日志脱敏逻辑一致)
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [环境变量参考](./reference.md)
|
||||||
|
- [架构概览](./architecture.md)
|
||||||
|
- [自动化与脚本](./automation.md)
|
||||||
+26
-25
@@ -13,40 +13,44 @@ repository root while preserving repo-local guidance for automation.
|
|||||||
## Project Snapshot
|
## Project Snapshot
|
||||||
|
|
||||||
- `dws` is a Go-based DingTalk Workspace CLI and MCP runtime bridge.
|
- `dws` is a Go-based DingTalk Workspace CLI and MCP runtime bridge.
|
||||||
- One internal Tool IR drives canonical CLI, schema, docs, skills, and snapshots.
|
- Product commands are loaded dynamically via `internal/plugin` from bundled descriptors.
|
||||||
- Compatibility and helper surfaces are overlays, not the canonical truth.
|
- Command handlers live in `internal/helpers`; runtime execution flows through `internal/executor` and `internal/transport`.
|
||||||
|
|
||||||
## Repository Map
|
## Repository Map
|
||||||
|
|
||||||
- `cmd`: public CLI entrypoint
|
- `cmd`: public CLI entrypoint
|
||||||
- `internal/app`: root command wiring and command tree mount points
|
- `internal/app`: root command wiring, static utility commands, plugin loading
|
||||||
- `internal/discovery`, `internal/market`, `internal/transport`: runtime discovery and MCP transport
|
- `internal/helpers`: product command handlers (dev, chat, calendar, contact, etc.)
|
||||||
- `internal/generator`: CLI/schema/docs/skills generation pipeline
|
- `internal/plugin`: plugin-based dynamic command loader
|
||||||
- `internal/compat`, `internal/helpers`: legacy-compatible aliases and helper commands
|
- `internal/cli`: catalog types and static endpoint loader
|
||||||
|
- `internal/executor`: invocation dispatch and result handling
|
||||||
|
- `internal/transport`: MCP HTTP client and request signing
|
||||||
|
- `internal/auth`: login, token management, agent-code detection
|
||||||
|
- `internal/audit`: user operation audit log
|
||||||
|
- `internal/errors`: structured error model with categories and hints
|
||||||
|
- `internal/keychain`: OS keychain integration for credential storage
|
||||||
|
- `internal/security`: endpoint allowlist and domain trust
|
||||||
|
- `internal/pat`: PAT (Personal Access Token) authorization flow
|
||||||
- `docs/`: public architecture and reference docs
|
- `docs/`: public architecture and reference docs
|
||||||
- `hack/`: developer-only helper commands not shipped as public binaries
|
|
||||||
- `scripts/`: build, test, lint, packaging, and policy checks
|
- `scripts/`: build, test, lint, packaging, and policy checks
|
||||||
- `test/`: integration, contract, compatibility, and script validation suites
|
- `test/`: CLI, integration, contract, unit, and skill E2E test suites
|
||||||
|
|
||||||
## Task Routing
|
## Task Routing
|
||||||
|
|
||||||
- Add or fix a command path: start from `internal/app` and the related module under `internal/*`
|
- Add or fix a command path: start from `internal/helpers` (handler implementations) or `internal/app` (command tree wiring)
|
||||||
- Discovery or protocol issues: inspect `internal/discovery`, `internal/market`, `internal/transport`
|
- Protocol or transport issues: inspect `internal/transport`
|
||||||
- Generated output drift: inspect `internal/generator` and run drift checks
|
- Auth or login issues: inspect `internal/auth`, `internal/pat`, `internal/keychain`
|
||||||
- Legacy behavior mismatch: inspect `internal/compat` and `test/cli_compat`
|
- Error message or category issues: inspect `internal/errors`
|
||||||
- Failure or degraded mode: inspect `internal/discovery`, `internal/errors`
|
- Audit log issues: inspect `internal/audit`
|
||||||
|
- Plugin loading or command surface: inspect `internal/plugin`
|
||||||
|
- Failure or degraded mode: inspect `internal/errors`, `internal/recovery`
|
||||||
|
|
||||||
## Generated Artifacts
|
## Policy Checks
|
||||||
|
|
||||||
Prefer editing source logic instead of generated files directly.
|
When command surface or plugin descriptors change, run:
|
||||||
|
|
||||||
- Generated-heavy paths:
|
- `./scripts/policy/check-command-surface.sh --strict`
|
||||||
- `docs/generated/`
|
- `./scripts/policy/check-open-source-assets.sh`
|
||||||
- `skills/generated/`
|
|
||||||
- `test/golden/generated_outputs/`
|
|
||||||
- When generator or command surface changes, run:
|
|
||||||
- `./scripts/policy/check-generated-drift.sh`
|
|
||||||
- `./scripts/policy/check-command-surface.sh --strict`
|
|
||||||
|
|
||||||
## Common Commands
|
## Common Commands
|
||||||
|
|
||||||
@@ -55,9 +59,6 @@ make build
|
|||||||
make test
|
make test
|
||||||
make lint
|
make lint
|
||||||
./scripts/dev/ci-local.sh
|
./scripts/dev/ci-local.sh
|
||||||
./scripts/policy/check-generated-drift.sh
|
|
||||||
./scripts/policy/check-command-surface.sh --strict
|
|
||||||
./scripts/policy/check-open-source-assets.sh
|
|
||||||
git diff --check
|
git diff --check
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,11 @@
|
|||||||
|
|
||||||
Every runtime command the `dws` CLI exposes when loaded with the **pre** environment configuration.
|
Every runtime command the `dws` CLI exposes when loaded with the **pre** environment configuration.
|
||||||
|
|
||||||
- **Source**: `dws-wukong/envelope/channel/open/pre/config.json`
|
|
||||||
- **Products**: 13
|
- **Products**: 13
|
||||||
- **Total commands**: 160
|
- **Total commands**: 160
|
||||||
- **Generated from**: `internal/compat.BuildDynamicCommands` rendering of the pre config — the same code path the CLI uses at runtime.
|
- **Generated from**: `internal/plugin` command descriptors — the same code path the CLI uses at runtime.
|
||||||
|
|
||||||
> Auto-generated. Edit `pre/config.json`, not this file.
|
> Auto-generated. Update plugin descriptors in `internal/plugin/`, not this file.
|
||||||
|
|
||||||
## Global flags
|
## Global flags
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Running the connector as a 7x24 service
|
# Running the connector as a 7x24 service
|
||||||
|
|
||||||
`dws devapp robot connect` keeps a DingTalk robot wired to a local agent over a
|
`dws dev connect` keeps a DingTalk robot wired to a local agent over a
|
||||||
Stream long-connection. By default it runs in the foreground and dies when the
|
Stream long-connection. By default it runs in the foreground and dies when the
|
||||||
terminal closes. For an unattended "digital employee" you have two options.
|
terminal closes. For an unattended "digital employee" you have two options.
|
||||||
|
|
||||||
@@ -15,14 +15,14 @@ terminal closes. For an unattended "digital employee" you have two options.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Detach into a background supervisor that restarts the connector if it crashes.
|
# Detach into a background supervisor that restarts the connector if it crashes.
|
||||||
dws devapp robot connect --daemon \
|
dws dev connect --daemon \
|
||||||
--channel claudecode \
|
--channel claudecode \
|
||||||
--unified-app-id <unifiedAppId>
|
--unified-app-id <unifiedAppId>
|
||||||
|
|
||||||
# Inspect / stop / restart it (locate the daemon by unifiedAppId).
|
# Inspect / stop / restart it (locate the daemon by unifiedAppId).
|
||||||
dws devapp robot connect status --unified-app-id <unifiedAppId>
|
dws dev connect status --unified-app-id <unifiedAppId>
|
||||||
dws devapp robot connect stop --unified-app-id <unifiedAppId>
|
dws dev connect stop --unified-app-id <unifiedAppId>
|
||||||
dws devapp robot connect restart --unified-app-id <unifiedAppId>
|
dws dev connect restart --unified-app-id <unifiedAppId>
|
||||||
```
|
```
|
||||||
|
|
||||||
- The parent prints the daemon pid and the log path, then exits.
|
- The parent prints the daemon pid and the log path, then exits.
|
||||||
@@ -60,8 +60,7 @@ and `REPLACE_UNIFIED_APP_ID`, then `launchctl load -w <path>`.
|
|||||||
<key>ProgramArguments</key>
|
<key>ProgramArguments</key>
|
||||||
<array>
|
<array>
|
||||||
<string>/usr/local/bin/dws</string>
|
<string>/usr/local/bin/dws</string>
|
||||||
<string>devapp</string>
|
<string>dev</string>
|
||||||
<string>robot</string>
|
|
||||||
<string>connect</string>
|
<string>connect</string>
|
||||||
<string>--channel</string>
|
<string>--channel</string>
|
||||||
<string>claudecode</string>
|
<string>claudecode</string>
|
||||||
@@ -110,7 +109,7 @@ Wants=network-online.target
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
ExecStart=/usr/local/bin/dws devapp robot connect \
|
ExecStart=/usr/local/bin/dws dev connect \
|
||||||
--channel claudecode \
|
--channel claudecode \
|
||||||
--unified-app-id REPLACE_UNIFIED_APP_ID
|
--unified-app-id REPLACE_UNIFIED_APP_ID
|
||||||
Restart=always
|
Restart=always
|
||||||
@@ -136,7 +135,7 @@ security warning to stderr. This form:
|
|||||||
- exposes `clientSecret` to every user on the box via `ps -ef`;
|
- exposes `clientSecret` to every user on the box via `ps -ef`;
|
||||||
- gets baked into launchd `ProgramArguments` / systemd `ExecStart`, which
|
- gets baked into launchd `ProgramArguments` / systemd `ExecStart`, which
|
||||||
makes rotation harder;
|
makes rotation harder;
|
||||||
- means `dws devapp robot connect restart` cannot re-fetch credentials — you
|
- means `dws dev connect restart` cannot re-fetch credentials — you
|
||||||
must re-run the full command yourself.
|
must re-run the full command yourself.
|
||||||
|
|
||||||
Prefer `--unified-app-id`. Only fall back to the pair when you understand the
|
Prefer `--unified-app-id`. Only fall back to the pair when you understand the
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/cobracmd"
|
||||||
apperrors "github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/errors"
|
apperrors "github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/errors"
|
||||||
|
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/executor"
|
||||||
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/logging"
|
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/logging"
|
||||||
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/tui"
|
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/tui"
|
||||||
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/pkg/config"
|
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/pkg/config"
|
||||||
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/cobracmd"
|
|
||||||
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/executor"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -61,13 +61,13 @@ const (
|
|||||||
// supervisor pid plus enough context for `status` to report without re-deriving
|
// supervisor pid plus enough context for `status` to report without re-deriving
|
||||||
// it (start time for uptime, log path, the dir key it was filed under).
|
// it (start time for uptime, log path, the dir key it was filed under).
|
||||||
type daemonState struct {
|
type daemonState struct {
|
||||||
Pid int `json:"pid"`
|
Pid int `json:"pid"`
|
||||||
StartUnix int64 `json:"startUnix"`
|
StartUnix int64 `json:"startUnix"`
|
||||||
LogPath string `json:"logPath"`
|
LogPath string `json:"logPath"`
|
||||||
DirKey string `json:"dirKey"`
|
DirKey string `json:"dirKey"`
|
||||||
ClientID string `json:"clientId,omitempty"`
|
ClientID string `json:"clientId,omitempty"`
|
||||||
UnifiedAppID string `json:"unifiedAppId,omitempty"`
|
UnifiedAppID string `json:"unifiedAppId,omitempty"`
|
||||||
Channel string `json:"channel,omitempty"`
|
Channel string `json:"channel,omitempty"`
|
||||||
NotifyStaffID string `json:"notifyStaffId,omitempty"`
|
NotifyStaffID string `json:"notifyStaffId,omitempty"`
|
||||||
// Profile records the --profile selector the connector was started with,
|
// Profile records the --profile selector the connector was started with,
|
||||||
// so `restart` re-fetches credentials against the same org instead of the
|
// so `restart` re-fetches credentials against the same org instead of the
|
||||||
@@ -112,7 +112,7 @@ func connectDaemonDir(dirKey string) (string, error) {
|
|||||||
|
|
||||||
func daemonPidPath(dir string) string { return filepath.Join(dir, "daemon.pid") }
|
func daemonPidPath(dir string) string { return filepath.Join(dir, "daemon.pid") }
|
||||||
func daemonStatePath(dir string) string { return filepath.Join(dir, "daemon-state.json") }
|
func daemonStatePath(dir string) string { return filepath.Join(dir, "daemon-state.json") }
|
||||||
func daemonLogPath(dir string) string { return filepath.Join(dir, "daemon.log") }
|
func daemonLogPath(dir string) string { return filepath.Join(dir, "daemon.log") }
|
||||||
|
|
||||||
// writeDaemonState atomically persists the daemon state to daemon-state.json
|
// writeDaemonState atomically persists the daemon state to daemon-state.json
|
||||||
// (persistent, survives supervisor exit) so restart/list can recover config.
|
// (persistent, survives supervisor exit) so restart/list can recover config.
|
||||||
@@ -641,9 +641,9 @@ func newDevAppRobotConnectStopCommand() *cobra.Command {
|
|||||||
// platform — no secrets stored on disk.
|
// platform — no secrets stored on disk.
|
||||||
func newDevAppRobotConnectRestartCommand() *cobra.Command {
|
func newDevAppRobotConnectRestartCommand() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "restart",
|
Use: "restart",
|
||||||
Short: "重启连接器守护进程(通过持久化的 unifiedAppId 重新拉取密钥,无需本地存密钥)",
|
Short: "重启连接器守护进程(通过持久化的 unifiedAppId 重新拉取密钥,无需本地存密钥)",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
dirKey, err := connectDaemonDirKeyFromFlags(cmd)
|
dirKey, err := connectDaemonDirKeyFromFlags(cmd)
|
||||||
|
|||||||
@@ -677,7 +677,7 @@ func connectAgentOptionsFromCommand(cmd *cobra.Command) connectAgentOptions {
|
|||||||
auditSheetTab = "Sheet1"
|
auditSheetTab = "Sheet1"
|
||||||
}
|
}
|
||||||
return connectAgentOptions{Model: model, WorkDir: workDir, Memory: memory,
|
return connectAgentOptions{Model: model, WorkDir: workDir, Memory: memory,
|
||||||
Timeout: time.Duration(agentTimeoutSec) * time.Second,
|
Timeout: time.Duration(agentTimeoutSec) * time.Second,
|
||||||
ReplyCard: replyCard, CardTemplate: cardTemplate,
|
ReplyCard: replyCard, CardTemplate: cardTemplate,
|
||||||
KnowledgeDir: knowledgeDir,
|
KnowledgeDir: knowledgeDir,
|
||||||
KnowledgeSource: knowledgeSource,
|
KnowledgeSource: knowledgeSource,
|
||||||
|
|||||||
Reference in New Issue
Block a user