@hopping-dev/hub 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.
- package/assets/hopping-skill/SKILL.md +221 -0
- package/dist/approval/manager.d.ts +60 -0
- package/dist/approval/manager.d.ts.map +1 -0
- package/dist/approval/manager.js +101 -0
- package/dist/approval/manager.js.map +1 -0
- package/dist/approval/session-memory.d.ts +37 -0
- package/dist/approval/session-memory.d.ts.map +1 -0
- package/dist/approval/session-memory.js +63 -0
- package/dist/approval/session-memory.js.map +1 -0
- package/dist/cli/config-writer.d.ts +57 -0
- package/dist/cli/config-writer.d.ts.map +1 -0
- package/dist/cli/config-writer.js +318 -0
- package/dist/cli/config-writer.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +82 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/path-resolver.d.ts +48 -0
- package/dist/cli/path-resolver.d.ts.map +1 -0
- package/dist/cli/path-resolver.js +212 -0
- package/dist/cli/path-resolver.js.map +1 -0
- package/dist/cli/setup.d.ts +10 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +268 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cloud/connector.d.ts +74 -0
- package/dist/cloud/connector.d.ts.map +1 -0
- package/dist/cloud/connector.js +524 -0
- package/dist/cloud/connector.js.map +1 -0
- package/dist/cloud/index.d.ts +3 -0
- package/dist/cloud/index.d.ts.map +1 -0
- package/dist/cloud/index.js +6 -0
- package/dist/cloud/index.js.map +1 -0
- package/dist/config/manager.d.ts +76 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +296 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/dev-mode.d.ts +30 -0
- package/dist/dev-mode.d.ts.map +1 -0
- package/dist/dev-mode.js +53 -0
- package/dist/dev-mode.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +354 -0
- package/dist/index.js.map +1 -0
- package/dist/ipc/index.d.ts +12 -0
- package/dist/ipc/index.d.ts.map +1 -0
- package/dist/ipc/index.js +15 -0
- package/dist/ipc/index.js.map +1 -0
- package/dist/ipc/watcher.d.ts +226 -0
- package/dist/ipc/watcher.d.ts.map +1 -0
- package/dist/ipc/watcher.js +745 -0
- package/dist/ipc/watcher.js.map +1 -0
- package/dist/local/approval-dialog.d.ts +30 -0
- package/dist/local/approval-dialog.d.ts.map +1 -0
- package/dist/local/approval-dialog.js +214 -0
- package/dist/local/approval-dialog.js.map +1 -0
- package/dist/local/index.d.ts +8 -0
- package/dist/local/index.d.ts.map +1 -0
- package/dist/local/index.js +13 -0
- package/dist/local/index.js.map +1 -0
- package/dist/local/local-approval.d.ts +55 -0
- package/dist/local/local-approval.d.ts.map +1 -0
- package/dist/local/local-approval.js +125 -0
- package/dist/local/local-approval.js.map +1 -0
- package/dist/local/notifier.d.ts +19 -0
- package/dist/local/notifier.d.ts.map +1 -0
- package/dist/local/notifier.js +110 -0
- package/dist/local/notifier.js.map +1 -0
- package/dist/local/sanitize.d.ts +20 -0
- package/dist/local/sanitize.d.ts.map +1 -0
- package/dist/local/sanitize.js +28 -0
- package/dist/local/sanitize.js.map +1 -0
- package/dist/mcp/file-extractor.d.ts +11 -0
- package/dist/mcp/file-extractor.d.ts.map +1 -0
- package/dist/mcp/file-extractor.js +74 -0
- package/dist/mcp/file-extractor.js.map +1 -0
- package/dist/mcp/risk-level.d.ts +44 -0
- package/dist/mcp/risk-level.d.ts.map +1 -0
- package/dist/mcp/risk-level.js +127 -0
- package/dist/mcp/risk-level.js.map +1 -0
- package/dist/mcp/schemas.d.ts +83 -0
- package/dist/mcp/schemas.d.ts.map +1 -0
- package/dist/mcp/schemas.js +84 -0
- package/dist/mcp/schemas.js.map +1 -0
- package/dist/mcp/summary.d.ts +11 -0
- package/dist/mcp/summary.d.ts.map +1 -0
- package/dist/mcp/summary.js +150 -0
- package/dist/mcp/summary.js.map +1 -0
- package/dist/mcp/tools.d.ts +45 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +1217 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/pairing/auto-pairing.d.ts +37 -0
- package/dist/pairing/auto-pairing.d.ts.map +1 -0
- package/dist/pairing/auto-pairing.js +144 -0
- package/dist/pairing/auto-pairing.js.map +1 -0
- package/dist/pairing/binding-poller.d.ts +26 -0
- package/dist/pairing/binding-poller.d.ts.map +1 -0
- package/dist/pairing/binding-poller.js +108 -0
- package/dist/pairing/binding-poller.js.map +1 -0
- package/dist/pairing/pairing-server.d.ts +14 -0
- package/dist/pairing/pairing-server.d.ts.map +1 -0
- package/dist/pairing/pairing-server.js +277 -0
- package/dist/pairing/pairing-server.js.map +1 -0
- package/dist/pairing/qr-display.d.ts +14 -0
- package/dist/pairing/qr-display.d.ts.map +1 -0
- package/dist/pairing/qr-display.js +40 -0
- package/dist/pairing/qr-display.js.map +1 -0
- package/dist/policy/engine.d.ts +31 -0
- package/dist/policy/engine.d.ts.map +1 -0
- package/dist/policy/engine.js +187 -0
- package/dist/policy/engine.js.map +1 -0
- package/dist/policy/store.d.ts +26 -0
- package/dist/policy/store.d.ts.map +1 -0
- package/dist/policy/store.js +70 -0
- package/dist/policy/store.js.map +1 -0
- package/dist/policy/system-policies.d.ts +15 -0
- package/dist/policy/system-policies.d.ts.map +1 -0
- package/dist/policy/system-policies.js +265 -0
- package/dist/policy/system-policies.js.map +1 -0
- package/dist/policy/tool-mapping.d.ts +45 -0
- package/dist/policy/tool-mapping.d.ts.map +1 -0
- package/dist/policy/tool-mapping.js +88 -0
- package/dist/policy/tool-mapping.js.map +1 -0
- package/dist/policy/tool-registry.json +85 -0
- package/dist/store/db.d.ts +17 -0
- package/dist/store/db.d.ts.map +1 -0
- package/dist/store/db.js +193 -0
- package/dist/store/db.js.map +1 -0
- package/dist/store/index.d.ts +4 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +7 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/metadata.d.ts +31 -0
- package/dist/store/metadata.d.ts.map +1 -0
- package/dist/store/metadata.js +178 -0
- package/dist/store/metadata.js.map +1 -0
- package/dist/store/operations.d.ts +26 -0
- package/dist/store/operations.d.ts.map +1 -0
- package/dist/store/operations.js +171 -0
- package/dist/store/operations.js.map +1 -0
- package/dist/utils/json.d.ts +7 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +33 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +58 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/open-browser.d.ts +8 -0
- package/dist/utils/open-browser.d.ts.map +1 -0
- package/dist/utils/open-browser.js +38 -0
- package/dist/utils/open-browser.js.map +1 -0
- package/node_modules/@hopping/shared/dist/types.d.ts +649 -0
- package/node_modules/@hopping/shared/dist/types.js +48 -0
- package/node_modules/@hopping/shared/dist/types.js.map +1 -0
- package/node_modules/@hopping/shared/package.json +14 -0
- package/node_modules/@hopping/shared/tsconfig.json +16 -0
- package/node_modules/@hopping/shared/types.d.ts +650 -0
- package/node_modules/@hopping/shared/types.d.ts.map +1 -0
- package/node_modules/@hopping/shared/types.js +48 -0
- package/node_modules/@hopping/shared/types.js.map +1 -0
- package/node_modules/@hopping/shared/types.ts +895 -0
- package/package.json +52 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hopping-skill
|
|
3
|
+
description: HopPing AI Agent Remote Control — call hopping.check before risky operations (shell commands, file writes, git pushes, database changes, .env access). For agents without Hook support, also call hopping.report after each significant operation.
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# HopPing — AI Agent Remote Control
|
|
8
|
+
|
|
9
|
+
HopPing lets users approve, control, and observe AI Agent operations from their phone. When `hopping.check` is available as an MCP tool, follow these guidelines to keep users in the loop.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## When to Call `hopping.check`
|
|
14
|
+
|
|
15
|
+
Call `hopping.check` **before** executing any of the following:
|
|
16
|
+
|
|
17
|
+
| Risk Level | Operations |
|
|
18
|
+
| ------------ | ---------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| **Critical** | `rm -rf`, `rm -r`, `DROP TABLE`, `TRUNCATE`, accessing `.env` / credentials / secrets / private keys |
|
|
20
|
+
| **High** | `sudo`, `chmod 777`, `curl \| bash`, `wget \| bash`, production deployments |
|
|
21
|
+
| **Medium** | `git push --force`, `git reset --hard`, `git clean -f`, any `rm` command |
|
|
22
|
+
| **Audit** | All shell commands (`Bash` tool), all file writes (`Edit`, `Write` tools), all database mutations |
|
|
23
|
+
|
|
24
|
+
**Skip `hopping.check` for low-risk operations:**
|
|
25
|
+
`Read`, `Glob`, `Grep`, `WebSearch`, `WebFetch`, `TodoRead`, `TodoWrite`
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## How to Call `hopping.check`
|
|
30
|
+
|
|
31
|
+
**Required fields:** `toolName`, `toolInput`
|
|
32
|
+
**Optional but recommended:** `sessionId`, `cwd`, `context`
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"toolName": "Bash",
|
|
37
|
+
"toolInput": { "command": "rm -rf dist/" },
|
|
38
|
+
"sessionId": "session-abc123",
|
|
39
|
+
"cwd": "/Users/dev/my-project",
|
|
40
|
+
"context": {
|
|
41
|
+
"recentFiles": ["src/index.ts", "package.json"],
|
|
42
|
+
"branch": "main",
|
|
43
|
+
"project": "my-project"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Handling the Response
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"approvalId": "uuid",
|
|
53
|
+
"decision": "approved | denied | conditional | timeout | pending",
|
|
54
|
+
"riskLevel": "low | medium | high | critical",
|
|
55
|
+
"message": "human-readable explanation"
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
| `decision` | Action |
|
|
60
|
+
| ------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
61
|
+
| `approved` | Proceed with the operation |
|
|
62
|
+
| `denied` | **Stop.** Do not execute. Tell the user: _"Operation denied by HopPing: [message]"_ |
|
|
63
|
+
| `conditional` | Read `message` carefully. Only proceed if all stated conditions are met |
|
|
64
|
+
| `timeout` | User did not respond in time. For `high`/`critical` risk: do not proceed. For `low`/`medium`: use judgment |
|
|
65
|
+
| `pending` | **Ask the user for local approval.** See "Handling Pending Decisions" below |
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Handling Pending Decisions (`hopping.respond`)
|
|
70
|
+
|
|
71
|
+
When `hopping.check` returns `decision="pending"`, the remote approval timed out but the operation still requires the user's explicit approval (typically `high` or `critical` risk). **Do not proceed without user confirmation.**
|
|
72
|
+
|
|
73
|
+
### Steps
|
|
74
|
+
|
|
75
|
+
1. **Show the pending operation to the user.** Include the tool name, risk level, and the message from `hopping.check`.
|
|
76
|
+
2. **Ask the user directly:** _"This operation requires your approval. Do you want to approve or deny it?"_
|
|
77
|
+
3. **Wait for the user's response.** Do not auto-approve or guess.
|
|
78
|
+
4. **Call `hopping.respond`** with the user's decision:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"approvalId": "the-approval-id-from-hopping-check",
|
|
83
|
+
"decision": "approved",
|
|
84
|
+
"reason": "User approved locally"
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
5. **Check the response from `hopping.respond`:**
|
|
89
|
+
- `{ "success": true, "source": "local" }` → User's decision was recorded. Proceed if approved, stop if denied.
|
|
90
|
+
- `{ "success": true, "decision": "approved", "source": "remote" }` → The user already approved on their phone. Proceed.
|
|
91
|
+
- `{ "success": true, "decision": "denied", "source": "remote" }` → The user already denied on their phone. Stop.
|
|
92
|
+
- `{ "success": false, "error": "..." }` → Something went wrong. Tell the user and do not proceed.
|
|
93
|
+
|
|
94
|
+
### Important Rules
|
|
95
|
+
|
|
96
|
+
- **Never call `hopping.respond` without asking the user first.** The purpose of `pending` is to ensure a human makes the decision.
|
|
97
|
+
- If the user says "approve all" or similar blanket statements, still ask for confirmation for each individual `pending` operation.
|
|
98
|
+
- If you are unsure about the user's intent, default to `denied`.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Using `hopping.report` (Agents Without Hook Support)
|
|
103
|
+
|
|
104
|
+
If you are running on **Codex, Gemini CLI, or any agent without Claude Code Hooks**, call `hopping.report` after each significant operation to enable observation:
|
|
105
|
+
|
|
106
|
+
**Required:** `toolName` only. All other fields are recommended.
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"toolName": "Bash",
|
|
111
|
+
"toolParams": { "command": "pnpm install" },
|
|
112
|
+
"result": "Successfully installed 23 packages",
|
|
113
|
+
"duration": 4521,
|
|
114
|
+
"success": true,
|
|
115
|
+
"filePaths": ["package.json", "pnpm-lock.yaml"]
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**When to report:**
|
|
120
|
+
|
|
121
|
+
- After any shell command execution
|
|
122
|
+
- After file writes or edits
|
|
123
|
+
- After git operations
|
|
124
|
+
- After database queries
|
|
125
|
+
|
|
126
|
+
> **Agents with Claude Code Hooks (Claude Code, Cursor):** Hooks automatically observe all operations — `hopping.report` is not required unless you want to add extra context.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Using `hopping.status`
|
|
131
|
+
|
|
132
|
+
Check Hub connectivity at session start or when debugging:
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{ "query": "all" }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Returns: `activeSessions`, `pendingApprovals`, `todayOperations`, `hubUptime`, `connectedToCloud`.
|
|
139
|
+
|
|
140
|
+
Call `hopping.status` when:
|
|
141
|
+
|
|
142
|
+
- Starting a new session (verify Hub is running)
|
|
143
|
+
- Debugging why approvals are not arriving on phone
|
|
144
|
+
- Checking how many operations were recorded today
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Reporting Task Completion
|
|
149
|
+
|
|
150
|
+
When you have **finished all steps of the user's task**, call `hopping.report` with `context.taskCompleted: true`. This notifies the user's phone that the agent is now idle and ready for new instructions.
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"toolName": "task_completed",
|
|
155
|
+
"result": "All requested tasks have been completed successfully.",
|
|
156
|
+
"success": true,
|
|
157
|
+
"context": {
|
|
158
|
+
"taskCompleted": true,
|
|
159
|
+
"project": "my-project"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**When to send task completion:**
|
|
165
|
+
|
|
166
|
+
- After completing all steps in the user's current prompt/task
|
|
167
|
+
- When you have nothing more to do and are returning control to the user
|
|
168
|
+
- Do NOT send for intermediate milestones — only when the entire task is done
|
|
169
|
+
|
|
170
|
+
**Why this matters:** The user may be away from their computer. This notification lets them know they can return to give new instructions, or simply enjoy their coffee a bit longer.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Examples
|
|
175
|
+
|
|
176
|
+
### Before a destructive shell command
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
1. Call hopping.check: toolName="Bash", toolInput={"command": "rm -rf node_modules/"}
|
|
180
|
+
2. If decision="approved" → run the Bash command
|
|
181
|
+
3. If decision="denied" → tell user: "Hub denied: [message]"
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Before writing to a sensitive file
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
1. Call hopping.check: toolName="Write", toolInput={"file_path": ".env", "content": "..."}
|
|
188
|
+
2. Wait for decision
|
|
189
|
+
3. Only write if decision="approved"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Reporting an operation (no Hook)
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
1. Execute: pnpm install
|
|
196
|
+
2. Call hopping.report: toolName="Bash", toolParams={"command":"pnpm install"},
|
|
197
|
+
result="installed 23 packages", success=true, duration=4521
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Pending operation (user away, returns to computer)
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
1. Call hopping.check: toolName="Bash", toolInput={"command": "rm -rf /var/data/old-backups"}
|
|
204
|
+
2. decision="pending" (remote approval timed out, critical risk)
|
|
205
|
+
3. Tell user: "⏳ A critical operation is pending your approval:
|
|
206
|
+
- Tool: Bash
|
|
207
|
+
- Command: rm -rf /var/data/old-backups
|
|
208
|
+
Do you approve or deny?"
|
|
209
|
+
4. User says "approve"
|
|
210
|
+
5. Call hopping.respond: approvalId="abc-123", decision="approved", reason="User approved locally"
|
|
211
|
+
6. Response: { success: true, source: "local" }
|
|
212
|
+
7. Proceed with the Bash command
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Session start check
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
1. Call hopping.status: query="all"
|
|
219
|
+
2. If connectedToCloud=false → note that phone approval is unavailable
|
|
220
|
+
3. Proceed normally — local policies still apply
|
|
221
|
+
```
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Logger } from '../utils/logger';
|
|
2
|
+
/**
|
|
3
|
+
* waitForApproval() 回傳的結果
|
|
4
|
+
* - timedOut=true: 超時(未收到 Mobile 回應)
|
|
5
|
+
* - timedOut=false: 正常 resolve(收到 Mobile 回應或 clearAll)
|
|
6
|
+
*/
|
|
7
|
+
export interface ApprovalResult {
|
|
8
|
+
approved: boolean;
|
|
9
|
+
reason?: string;
|
|
10
|
+
timedOut: boolean;
|
|
11
|
+
/** 決策來源(如 'mobile'、'local_dialog'、'local_respond') */
|
|
12
|
+
source?: string;
|
|
13
|
+
/** Rich response: 用戶選擇的選項 ID(responseType='choice' 時) */
|
|
14
|
+
selectedOption?: string;
|
|
15
|
+
/** Rich response: 用戶輸入的自由文字(responseType='freetext' 時) */
|
|
16
|
+
freetext?: string;
|
|
17
|
+
/** Rich response: isOther 選項的自訂文字 */
|
|
18
|
+
customText?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Rich response 欄位(從 PermissionResponsePayload 或 Mobile 回傳) */
|
|
21
|
+
export interface RichResponseFields {
|
|
22
|
+
selectedOption?: string;
|
|
23
|
+
freetext?: string;
|
|
24
|
+
customText?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Approval Manager
|
|
28
|
+
* 管理待審核請求、超時處理、決策回傳
|
|
29
|
+
*/
|
|
30
|
+
export declare class ApprovalManager {
|
|
31
|
+
private pending;
|
|
32
|
+
private logger;
|
|
33
|
+
private defaultTimeoutMs;
|
|
34
|
+
constructor(logger: Logger, defaultTimeoutMs?: number);
|
|
35
|
+
/**
|
|
36
|
+
* 建立新的審核請求,回傳 Promise 等待用戶決策
|
|
37
|
+
*/
|
|
38
|
+
waitForApproval(requestId: string, timeoutMs?: number): Promise<ApprovalResult>;
|
|
39
|
+
/**
|
|
40
|
+
* 處理用戶的審核決策
|
|
41
|
+
*/
|
|
42
|
+
resolveApproval(requestId: string, approved: boolean, reason?: string, source?: string, richResponse?: RichResponseFields): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* 檢查特定請求是否仍在 pending map 中
|
|
45
|
+
*/
|
|
46
|
+
isPending(requestId: string): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* 取得所有待審核的請求 ID
|
|
49
|
+
*/
|
|
50
|
+
getPendingIds(): string[];
|
|
51
|
+
/**
|
|
52
|
+
* 待審核數量
|
|
53
|
+
*/
|
|
54
|
+
get pendingCount(): number;
|
|
55
|
+
/**
|
|
56
|
+
* 清除所有待審核(例如關閉時)
|
|
57
|
+
*/
|
|
58
|
+
clearAll(): void;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/approval/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,gEAAgE;AAChE,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AASD;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAA2C;IAC1D,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,gBAAgB,CAAS;gBAErB,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAE,MAAc;IAK5D;;OAEG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAyB/E;;OAEG;IACH,eAAe,CACb,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,OAAO,EACjB,MAAM,CAAC,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,kBAAkB,GAChC,OAAO;IAgCV;;OAEG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIrC;;OAEG;IACH,aAAa,IAAI,MAAM,EAAE;IAIzB;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED;;OAEG;IACH,QAAQ,IAAI,IAAI;CAQjB"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApprovalManager = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Approval Manager
|
|
6
|
+
* 管理待審核請求、超時處理、決策回傳
|
|
7
|
+
*/
|
|
8
|
+
class ApprovalManager {
|
|
9
|
+
pending = new Map();
|
|
10
|
+
logger;
|
|
11
|
+
defaultTimeoutMs;
|
|
12
|
+
constructor(logger, defaultTimeoutMs = 60000) {
|
|
13
|
+
this.logger = logger;
|
|
14
|
+
this.defaultTimeoutMs = defaultTimeoutMs;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 建立新的審核請求,回傳 Promise 等待用戶決策
|
|
18
|
+
*/
|
|
19
|
+
waitForApproval(requestId, timeoutMs) {
|
|
20
|
+
const timeout = timeoutMs ?? this.defaultTimeoutMs;
|
|
21
|
+
return new Promise((resolve) => {
|
|
22
|
+
const timer = setTimeout(() => {
|
|
23
|
+
this.logger.warn('Approval timeout', { requestId, timeoutMs: timeout });
|
|
24
|
+
this.pending.delete(requestId);
|
|
25
|
+
resolve({ approved: false, reason: 'Approval timeout', timedOut: true });
|
|
26
|
+
}, timeout);
|
|
27
|
+
this.pending.set(requestId, {
|
|
28
|
+
id: requestId,
|
|
29
|
+
resolve,
|
|
30
|
+
timeout: timer,
|
|
31
|
+
createdAt: Date.now(),
|
|
32
|
+
});
|
|
33
|
+
this.logger.info('Approval request created', {
|
|
34
|
+
requestId,
|
|
35
|
+
timeoutMs: timeout,
|
|
36
|
+
pendingCount: this.pending.size,
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 處理用戶的審核決策
|
|
42
|
+
*/
|
|
43
|
+
resolveApproval(requestId, approved, reason, source, richResponse) {
|
|
44
|
+
const pending = this.pending.get(requestId);
|
|
45
|
+
if (!pending) {
|
|
46
|
+
this.logger.warn('No pending approval found', { requestId });
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
clearTimeout(pending.timeout);
|
|
50
|
+
this.pending.delete(requestId);
|
|
51
|
+
const waitTimeMs = Date.now() - pending.createdAt;
|
|
52
|
+
this.logger.info('Approval resolved', {
|
|
53
|
+
requestId,
|
|
54
|
+
approved,
|
|
55
|
+
reason,
|
|
56
|
+
source,
|
|
57
|
+
waitTimeMs,
|
|
58
|
+
});
|
|
59
|
+
pending.resolve({
|
|
60
|
+
approved,
|
|
61
|
+
reason,
|
|
62
|
+
timedOut: false,
|
|
63
|
+
source,
|
|
64
|
+
selectedOption: richResponse?.selectedOption,
|
|
65
|
+
freetext: richResponse?.freetext,
|
|
66
|
+
customText: richResponse?.customText,
|
|
67
|
+
});
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 檢查特定請求是否仍在 pending map 中
|
|
72
|
+
*/
|
|
73
|
+
isPending(requestId) {
|
|
74
|
+
return this.pending.has(requestId);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 取得所有待審核的請求 ID
|
|
78
|
+
*/
|
|
79
|
+
getPendingIds() {
|
|
80
|
+
return Array.from(this.pending.keys());
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* 待審核數量
|
|
84
|
+
*/
|
|
85
|
+
get pendingCount() {
|
|
86
|
+
return this.pending.size;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 清除所有待審核(例如關閉時)
|
|
90
|
+
*/
|
|
91
|
+
clearAll() {
|
|
92
|
+
for (const [, pending] of this.pending.entries()) {
|
|
93
|
+
clearTimeout(pending.timeout);
|
|
94
|
+
pending.resolve({ approved: false, reason: 'System shutdown', timedOut: false });
|
|
95
|
+
}
|
|
96
|
+
this.pending.clear();
|
|
97
|
+
this.logger.info('All pending approvals cleared');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.ApprovalManager = ApprovalManager;
|
|
101
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/approval/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { RiskLevel } from '@hopping/shared';
|
|
2
|
+
/**
|
|
3
|
+
* SessionMemory — Hub in-memory "don't ask again" store (S4-HUB-DONTASK-001).
|
|
4
|
+
*
|
|
5
|
+
* Records (toolName, riskLevel) pairs when Mobile approves with reason='dont_ask_again'.
|
|
6
|
+
* Subsequent hopping.check / IpcWatcher away-mode calls for the same tool auto-approve
|
|
7
|
+
* if the current riskLevel is less than or equal to the stored ceiling.
|
|
8
|
+
*
|
|
9
|
+
* Cleared on Hub process restart (session scope, intentionally not persisted).
|
|
10
|
+
*/
|
|
11
|
+
export declare class SessionMemory {
|
|
12
|
+
private readonly allowedTools;
|
|
13
|
+
/**
|
|
14
|
+
* Add a tool to the don't-ask-again list.
|
|
15
|
+
* Trust expansion: if the tool already exists with a lower riskLevel, upgrade to the higher value.
|
|
16
|
+
* Trust does NOT shrink: adding a lower riskLevel than the existing entry is a no-op.
|
|
17
|
+
*/
|
|
18
|
+
add(toolName: string, riskLevel: RiskLevel): void;
|
|
19
|
+
/**
|
|
20
|
+
* Check if a tool call should be auto-approved.
|
|
21
|
+
* Returns true only if the tool is in the list AND currentRiskLevel <= storedRiskLevel.
|
|
22
|
+
*/
|
|
23
|
+
has(toolName: string, currentRiskLevel: RiskLevel): boolean;
|
|
24
|
+
/** Remove a specific tool from the list. Returns true if the entry existed. */
|
|
25
|
+
remove(toolName: string): boolean;
|
|
26
|
+
/** Clear all entries (simulates Hub restart for testing). */
|
|
27
|
+
clear(): void;
|
|
28
|
+
/** Number of tools currently in the list. */
|
|
29
|
+
get size(): number;
|
|
30
|
+
/** Return all entries as an array (used by hopping.status). */
|
|
31
|
+
getAll(): Array<{
|
|
32
|
+
toolName: string;
|
|
33
|
+
riskLevel: RiskLevel;
|
|
34
|
+
addedAt: number;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=session-memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-memory.d.ts","sourceRoot":"","sources":["../../src/approval/session-memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQjD;;;;;;;;GAQG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgE;IAE7F;;;;OAIG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI;IAMjD;;;OAGG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,GAAG,OAAO;IAM3D,+EAA+E;IAC/E,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIjC,6DAA6D;IAC7D,KAAK,IAAI,IAAI;IAIb,6CAA6C;IAC7C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,+DAA+D;IAC/D,MAAM,IAAI,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,SAAS,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAO7E"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SessionMemory = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Risk level ordering for ceiling comparison.
|
|
6
|
+
* Lower index = lower risk. has() returns true only if currentRisk <= storedRisk.
|
|
7
|
+
*/
|
|
8
|
+
const RISK_ORDER = { low: 0, medium: 1, high: 2, critical: 3 };
|
|
9
|
+
/**
|
|
10
|
+
* SessionMemory — Hub in-memory "don't ask again" store (S4-HUB-DONTASK-001).
|
|
11
|
+
*
|
|
12
|
+
* Records (toolName, riskLevel) pairs when Mobile approves with reason='dont_ask_again'.
|
|
13
|
+
* Subsequent hopping.check / IpcWatcher away-mode calls for the same tool auto-approve
|
|
14
|
+
* if the current riskLevel is less than or equal to the stored ceiling.
|
|
15
|
+
*
|
|
16
|
+
* Cleared on Hub process restart (session scope, intentionally not persisted).
|
|
17
|
+
*/
|
|
18
|
+
class SessionMemory {
|
|
19
|
+
allowedTools = new Map();
|
|
20
|
+
/**
|
|
21
|
+
* Add a tool to the don't-ask-again list.
|
|
22
|
+
* Trust expansion: if the tool already exists with a lower riskLevel, upgrade to the higher value.
|
|
23
|
+
* Trust does NOT shrink: adding a lower riskLevel than the existing entry is a no-op.
|
|
24
|
+
*/
|
|
25
|
+
add(toolName, riskLevel) {
|
|
26
|
+
const existing = this.allowedTools.get(toolName);
|
|
27
|
+
if (existing && RISK_ORDER[existing.riskLevel] >= RISK_ORDER[riskLevel])
|
|
28
|
+
return;
|
|
29
|
+
this.allowedTools.set(toolName, { riskLevel, addedAt: Date.now() });
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Check if a tool call should be auto-approved.
|
|
33
|
+
* Returns true only if the tool is in the list AND currentRiskLevel <= storedRiskLevel.
|
|
34
|
+
*/
|
|
35
|
+
has(toolName, currentRiskLevel) {
|
|
36
|
+
const entry = this.allowedTools.get(toolName);
|
|
37
|
+
if (!entry)
|
|
38
|
+
return false;
|
|
39
|
+
return RISK_ORDER[currentRiskLevel] <= RISK_ORDER[entry.riskLevel];
|
|
40
|
+
}
|
|
41
|
+
/** Remove a specific tool from the list. Returns true if the entry existed. */
|
|
42
|
+
remove(toolName) {
|
|
43
|
+
return this.allowedTools.delete(toolName);
|
|
44
|
+
}
|
|
45
|
+
/** Clear all entries (simulates Hub restart for testing). */
|
|
46
|
+
clear() {
|
|
47
|
+
this.allowedTools.clear();
|
|
48
|
+
}
|
|
49
|
+
/** Number of tools currently in the list. */
|
|
50
|
+
get size() {
|
|
51
|
+
return this.allowedTools.size;
|
|
52
|
+
}
|
|
53
|
+
/** Return all entries as an array (used by hopping.status). */
|
|
54
|
+
getAll() {
|
|
55
|
+
return Array.from(this.allowedTools.entries()).map(([toolName, { riskLevel, addedAt }]) => ({
|
|
56
|
+
toolName,
|
|
57
|
+
riskLevel,
|
|
58
|
+
addedAt,
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.SessionMemory = SessionMemory;
|
|
63
|
+
//# sourceMappingURL=session-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-memory.js","sourceRoot":"","sources":["../../src/approval/session-memory.ts"],"names":[],"mappings":";;;AAEA;;;GAGG;AACH,MAAM,UAAU,GAA8B,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AAE1F;;;;;;;;GAQG;AACH,MAAa,aAAa;IACP,YAAY,GAAG,IAAI,GAAG,EAAqD,CAAC;IAE7F;;;;OAIG;IACH,GAAG,CAAC,QAAgB,EAAE,SAAoB;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,QAAQ,IAAI,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO;QAChF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACtE,CAAC;IAED;;;OAGG;IACH,GAAG,CAAC,QAAgB,EAAE,gBAA2B;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzB,OAAO,UAAU,CAAC,gBAAgB,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACrE,CAAC;IAED,+EAA+E;IAC/E,MAAM,CAAC,QAAgB;QACrB,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,6DAA6D;IAC7D,KAAK;QACH,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED,6CAA6C;IAC7C,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;IAChC,CAAC;IAED,+DAA+D;IAC/D,MAAM;QACJ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YAC1F,QAAQ;YACR,SAAS;YACT,OAAO;SACR,CAAC,CAAC,CAAC;IACN,CAAC;CACF;AA/CD,sCA+CC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { DetectedAgent } from './path-resolver';
|
|
2
|
+
export interface McpServerEntry {
|
|
3
|
+
type?: string;
|
|
4
|
+
command: string;
|
|
5
|
+
args: string[];
|
|
6
|
+
env?: Record<string, string>;
|
|
7
|
+
}
|
|
8
|
+
export interface WriteResult {
|
|
9
|
+
path: string;
|
|
10
|
+
action: 'created' | 'updated';
|
|
11
|
+
backedUp: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface WriteOptions {
|
|
14
|
+
hubCommand: string;
|
|
15
|
+
hubArgs: string[];
|
|
16
|
+
devMode: string;
|
|
17
|
+
preHookPath: string;
|
|
18
|
+
postHookPath: string;
|
|
19
|
+
cursorAdapterPath: string;
|
|
20
|
+
scope: 'project' | 'user';
|
|
21
|
+
skipHooks: boolean;
|
|
22
|
+
dryRun: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 寫入 Claude Code / Cursor MCP config(JSON 格式)
|
|
26
|
+
* - Claude Code: .mcp.json(project) / ~/.claude.json(user)
|
|
27
|
+
* - Cursor: .cursor/mcp.json(project) / ~/.cursor/mcp.json(user)
|
|
28
|
+
*/
|
|
29
|
+
export declare function writeMcpJson(agent: DetectedAgent, options: WriteOptions): Promise<WriteResult>;
|
|
30
|
+
/**
|
|
31
|
+
* 寫入 Codex MCP config(TOML 格式)
|
|
32
|
+
* - .codex/config.toml(project / user)
|
|
33
|
+
*/
|
|
34
|
+
export declare function writeMcpToml(agent: DetectedAgent, options: WriteOptions): Promise<WriteResult>;
|
|
35
|
+
/**
|
|
36
|
+
* 寫入 MCP config(根據 agent 自動分派 JSON 或 TOML)
|
|
37
|
+
*/
|
|
38
|
+
export declare function writeMcpConfig(agent: DetectedAgent, options: WriteOptions): Promise<WriteResult>;
|
|
39
|
+
/**
|
|
40
|
+
* 寫入 Claude Code Hooks config(.claude/settings.json,巢狀格式,PascalCase)
|
|
41
|
+
*/
|
|
42
|
+
export declare function writeClaudeCodeHooks(hooksConfigPath: string, options: WriteOptions): Promise<WriteResult>;
|
|
43
|
+
/**
|
|
44
|
+
* 檢查 cursor-adapter.js 是否已實作(非空檔案)
|
|
45
|
+
*/
|
|
46
|
+
export declare function isCursorAdapterReady(adapterPath: string): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* 寫入 Cursor Hooks config(.cursor/hooks.json,扁平格式,camelCase,version: 1)
|
|
49
|
+
* 只有在 cursor-adapter.js 存在且已實作時才寫入
|
|
50
|
+
*/
|
|
51
|
+
export declare function writeCursorHooks(hooksConfigPath: string, cursorAdapterPath: string, options: WriteOptions): Promise<WriteResult | null>;
|
|
52
|
+
/**
|
|
53
|
+
* 寫入 Hooks config(根據 agent 自動分派)
|
|
54
|
+
* 回傳 WriteResult(成功)、null(跳過,如 Cursor adapter 未實作)、或 'unsupported'(如 Codex)
|
|
55
|
+
*/
|
|
56
|
+
export declare function writeHooksConfig(agent: DetectedAgent, options: WriteOptions): Promise<WriteResult | null | 'unsupported'>;
|
|
57
|
+
//# sourceMappingURL=config-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-writer.d.ts","sourceRoot":"","sources":["../../src/cli/config-writer.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAOrD,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACjB;AA6HD;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,WAAW,CAAC,CAStB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,WAAW,CAAC,CAetB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,WAAW,CAAC,CAKtB;AASD;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,WAAW,CAAC,CA+CtB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAWjE;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,eAAe,EAAE,MAAM,EACvB,iBAAiB,EAAE,MAAM,EACzB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAoC7B;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,WAAW,GAAG,IAAI,GAAG,aAAa,CAAC,CAuB7C"}
|