agentwake 1.0.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/.cursor/hooks.json +15 -0
- package/.env.example +19 -0
- package/README.md +137 -0
- package/dist/adapters/claude-hook-adapter.d.ts +3 -0
- package/dist/adapters/claude-hook-adapter.d.ts.map +1 -0
- package/dist/adapters/claude-hook-adapter.js +25 -0
- package/dist/adapters/claude-hook-adapter.js.map +1 -0
- package/dist/adapters/cursor-hook-adapter.d.ts +3 -0
- package/dist/adapters/cursor-hook-adapter.d.ts.map +1 -0
- package/dist/adapters/cursor-hook-adapter.js +144 -0
- package/dist/adapters/cursor-hook-adapter.js.map +1 -0
- package/dist/adapters/cursor-terminal-hook.d.ts +20 -0
- package/dist/adapters/cursor-terminal-hook.d.ts.map +1 -0
- package/dist/adapters/cursor-terminal-hook.js +120 -0
- package/dist/adapters/cursor-terminal-hook.js.map +1 -0
- package/dist/adapters/hook-common.d.ts +6 -0
- package/dist/adapters/hook-common.d.ts.map +1 -0
- package/dist/adapters/hook-common.js +69 -0
- package/dist/adapters/hook-common.js.map +1 -0
- package/dist/adapters/qoder-log-adapter.d.ts +19 -0
- package/dist/adapters/qoder-log-adapter.d.ts.map +1 -0
- package/dist/adapters/qoder-log-adapter.js +320 -0
- package/dist/adapters/qoder-log-adapter.js.map +1 -0
- package/dist/bootstrap.d.ts +19 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +106 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +187 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +21 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +63 -0
- package/dist/config.js.map +1 -0
- package/dist/domain/notify-event.d.ts +17 -0
- package/dist/domain/notify-event.d.ts.map +1 -0
- package/dist/domain/notify-event.js +10 -0
- package/dist/domain/notify-event.js.map +1 -0
- package/dist/gateway/adapter-registry.d.ts +9 -0
- package/dist/gateway/adapter-registry.d.ts.map +1 -0
- package/dist/gateway/adapter-registry.js +26 -0
- package/dist/gateway/adapter-registry.js.map +1 -0
- package/dist/gateway/adapter.d.ts +14 -0
- package/dist/gateway/adapter.d.ts.map +1 -0
- package/dist/gateway/adapter.js +3 -0
- package/dist/gateway/adapter.js.map +1 -0
- package/dist/gateway/event-router.d.ts +20 -0
- package/dist/gateway/event-router.d.ts.map +1 -0
- package/dist/gateway/event-router.js +72 -0
- package/dist/gateway/event-router.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +9 -0
- package/dist/main.js.map +1 -0
- package/dist/notifiers/desktop-notifier.d.ts +11 -0
- package/dist/notifiers/desktop-notifier.d.ts.map +1 -0
- package/dist/notifiers/desktop-notifier.js +78 -0
- package/dist/notifiers/desktop-notifier.js.map +1 -0
- package/dist/notifiers/mobile-ws-notifier.d.ts +13 -0
- package/dist/notifiers/mobile-ws-notifier.d.ts.map +1 -0
- package/dist/notifiers/mobile-ws-notifier.js +65 -0
- package/dist/notifiers/mobile-ws-notifier.js.map +1 -0
- package/dist/notifiers/notifier.d.ts +6 -0
- package/dist/notifiers/notifier.d.ts.map +1 -0
- package/dist/notifiers/notifier.js +3 -0
- package/dist/notifiers/notifier.js.map +1 -0
- package/dist/notifiers/pwa-push-notifier.d.ts +12 -0
- package/dist/notifiers/pwa-push-notifier.d.ts.map +1 -0
- package/dist/notifiers/pwa-push-notifier.js +69 -0
- package/dist/notifiers/pwa-push-notifier.js.map +1 -0
- package/dist/run-gateway.d.ts +3 -0
- package/dist/run-gateway.d.ts.map +1 -0
- package/dist/run-gateway.js +66 -0
- package/dist/run-gateway.js.map +1 -0
- package/dist/utils/approval-match.d.ts +2 -0
- package/dist/utils/approval-match.d.ts.map +1 -0
- package/dist/utils/approval-match.js +32 -0
- package/dist/utils/approval-match.js.map +1 -0
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +19 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +60 -0
- package/scripts/cursor-hook-forwarder.mjs +269 -0
- package/web/app.js +350 -0
- package/web/icons/icon-192.svg +6 -0
- package/web/icons/icon-512.svg +6 -0
- package/web/index.html +117 -0
- package/web/manifest.webmanifest +25 -0
- package/web/sw.js +32 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"hooks": {
|
|
4
|
+
"beforeShellExecution": [
|
|
5
|
+
{
|
|
6
|
+
"command": "sh -lc 'CAROOT=\"$(mkcert -CAROOT 2>/dev/null)\"; EXTRA_CA=\"${NODE_EXTRA_CA_CERTS:-$CAROOT/rootCA.pem}\"; AGENTWAKE_GATEWAY_URL=\"${AGENTWAKE_GATEWAY_URL:-https://127.0.0.1:3199/hooks/cursor}\" NODE_EXTRA_CA_CERTS=\"$EXTRA_CA\" AGENTWAKE_CURSOR_APPROVAL_MODE=\"${AGENTWAKE_CURSOR_APPROVAL_MODE:-cursor-ask}\" AGENTWAKE_CURSOR_ENFORCE_ASK=\"${AGENTWAKE_CURSOR_ENFORCE_ASK:-0}\" node \"./scripts/cursor-hook-forwarder.mjs\"'"
|
|
7
|
+
}
|
|
8
|
+
],
|
|
9
|
+
"afterShellExecution": [
|
|
10
|
+
{
|
|
11
|
+
"command": "sh -lc 'CAROOT=\"$(mkcert -CAROOT 2>/dev/null)\"; EXTRA_CA=\"${NODE_EXTRA_CA_CERTS:-$CAROOT/rootCA.pem}\"; AGENTWAKE_GATEWAY_URL=\"${AGENTWAKE_GATEWAY_URL:-https://127.0.0.1:3199/hooks/cursor}\" NODE_EXTRA_CA_CERTS=\"$EXTRA_CA\" AGENTWAKE_CURSOR_APPROVAL_MODE=\"${AGENTWAKE_CURSOR_APPROVAL_MODE:-cursor-ask}\" AGENTWAKE_CURSOR_ENFORCE_ASK=\"${AGENTWAKE_CURSOR_ENFORCE_ASK:-0}\" node \"./scripts/cursor-hook-forwarder.mjs\"'"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
}
|
package/.env.example
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
AGENTWAKE_HOST=0.0.0.0
|
|
2
|
+
AGENTWAKE_PORT=3199
|
|
3
|
+
AGENTWAKE_HTTPS_ENABLED=1
|
|
4
|
+
AGENTWAKE_HTTPS_CERT_PATH=certs/dev-cert.pem
|
|
5
|
+
AGENTWAKE_HTTPS_KEY_PATH=certs/dev-key.pem
|
|
6
|
+
AGENTWAKE_CURSOR_HOOK_PATH=/hooks/cursor
|
|
7
|
+
AGENTWAKE_CLAUDE_HOOK_PATH=/hooks/claude
|
|
8
|
+
AGENTWAKE_QODER_LOG_PATH=/path/to/qoder.log
|
|
9
|
+
AGENTWAKE_WS_PATH=/ws
|
|
10
|
+
AGENTWAKE_DEDUPE_WINDOW_MS=10000
|
|
11
|
+
AGENTWAKE_RATE_LIMIT_WINDOW_MS=10000
|
|
12
|
+
AGENTWAKE_RATE_LIMIT_MAX_EVENTS=40
|
|
13
|
+
AGENTWAKE_ALLOWED_HOOK_IPS=
|
|
14
|
+
AGENTWAKE_VAPID_SUBJECT=mailto:agentwake@example.com
|
|
15
|
+
AGENTWAKE_DESKTOP_MODE=notification
|
|
16
|
+
AGENTWAKE_CURSOR_APPROVAL_MODE=cursor-ask
|
|
17
|
+
AGENTWAKE_CURSOR_ENFORCE_ASK=0
|
|
18
|
+
# AGENTWAKE_VAPID_PUBLIC_KEY=
|
|
19
|
+
# AGENTWAKE_VAPID_PRIVATE_KEY=
|
package/README.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# AgentWake 🚀
|
|
2
|
+
|
|
3
|
+
**AgentWake** 是一个跨编辑器(Cursor / Claude Code / Qoder)的终端授权提醒网关。
|
|
4
|
+
当你在使用 AI 辅助编程工具时,终端任务经常会进入“等待用户同意(Approval)”状态。AgentWake 会在桌面和移动端为你提供实时通知,让你无需时刻盯着屏幕,告别阻塞等待!
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 🌟 核心特性
|
|
9
|
+
|
|
10
|
+
- **多编辑器支持**:原生支持监听 Cursor Hook、Claude Hook 以及 Qoder 日志中的授权等待信号。
|
|
11
|
+
- **全平台桌面通知**:支持 macOS、Windows、Linux 的系统级弹窗提醒。
|
|
12
|
+
- **移动端实时提醒**:内置移动端 Web 应用,支持 PWA 安装,通过 HTTPS + WebSocket 实现手机端毫秒级推送。
|
|
13
|
+
- **智能防打扰**:内置去重和限流机制,避免消息重复轰炸。
|
|
14
|
+
- **开箱即用**:提供极简的 CLI 命令行工具,一键初始化与启动。
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 🚀 快速开始
|
|
19
|
+
|
|
20
|
+
### 环境要求
|
|
21
|
+
|
|
22
|
+
- Node.js (推荐 v18+)
|
|
23
|
+
- [mkcert](https://github.com/FiloSottile/mkcert) (用于生成本地 HTTPS 证书,移动端访问必备)
|
|
24
|
+
|
|
25
|
+
### 安装与启动
|
|
26
|
+
|
|
27
|
+
1. **全局安装 CLI**
|
|
28
|
+
```bash
|
|
29
|
+
npm i -g agentwake
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
2. **初始化项目与证书**
|
|
33
|
+
```bash
|
|
34
|
+
mkdir my-agentwake && cd my-agentwake
|
|
35
|
+
agentwake init
|
|
36
|
+
```
|
|
37
|
+
*注意:初始化过程中会自动使用 mkcert 生成本地 HTTPS 证书。*
|
|
38
|
+
|
|
39
|
+
3. **启动网关服务**
|
|
40
|
+
```bash
|
|
41
|
+
agentwake start
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
启动后,网关默认运行在 `https://localhost:3199` (或者局域网 IP)。
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 🔌 编辑器接入指南
|
|
49
|
+
|
|
50
|
+
### Cursor 接入
|
|
51
|
+
|
|
52
|
+
AgentWake 已经内置了对 Cursor 工作流的支持:
|
|
53
|
+
1. 确保在目标项目中执行过 `agentwake init`。
|
|
54
|
+
2. 保持 `agentwake start` 运行。
|
|
55
|
+
3. 当 Cursor 终端触发需要用户授权的命令时,你将立刻收到通知。
|
|
56
|
+
|
|
57
|
+
### Qoder 接入
|
|
58
|
+
|
|
59
|
+
AgentWake 会尝试自动发现 Qoder 的日志目录(如 macOS 下的 `~/Library/Application Support/Qoder/logs/.../agent.log`)。
|
|
60
|
+
|
|
61
|
+
如果自动发现失败,你可以通过环境变量手动指定日志路径:
|
|
62
|
+
```bash
|
|
63
|
+
AGENTWAKE_QODER_LOG_PATH="/ABSOLUTE/PATH/TO/agent.log" agentwake start
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 📱 移动端访问与证书信任(必读)
|
|
69
|
+
|
|
70
|
+
为了在手机上接收实时通知,你必须让手机信任电脑上由 `mkcert` 生成的根证书。
|
|
71
|
+
|
|
72
|
+
1. 找到根证书位置:
|
|
73
|
+
在电脑终端运行 `mkcert -CAROOT`,找到目录下的 `rootCA.pem` 文件。
|
|
74
|
+
2. 安装到手机:
|
|
75
|
+
- **iOS**:将文件发送到手机,在“设置”中安装描述文件,并在“通用 -> 关于本机 -> 证书信任设置”中开启“完全信任”。
|
|
76
|
+
- **Android**:将文件发送到手机,在安全设置中“从存储设备安装” CA 证书(部分安卓系统可能需要将后缀改为 `.crt`)。
|
|
77
|
+
3. Node.js TLS 兼容(如果遇到本地转发报错):
|
|
78
|
+
```bash
|
|
79
|
+
export NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 🛠️ 面向开发者
|
|
85
|
+
|
|
86
|
+
如果你想参与 AgentWake 的开发,请参考以下指南:
|
|
87
|
+
|
|
88
|
+
### 技术栈
|
|
89
|
+
- **后端**:Node.js + TypeScript + Express + WebSocket (`ws`) + Zod
|
|
90
|
+
- **前端**:HTML/CSS/JS (PWA 支持)
|
|
91
|
+
- **系统交互**:`node-notifier` (桌面通知)
|
|
92
|
+
|
|
93
|
+
### 本地开发
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# 1. 克隆代码并安装依赖
|
|
97
|
+
git clone https://github.com/your-username/agentwake.git
|
|
98
|
+
cd agentwake
|
|
99
|
+
npm install
|
|
100
|
+
|
|
101
|
+
# 2. 准备环境变量
|
|
102
|
+
cp .env.example .env
|
|
103
|
+
|
|
104
|
+
# 3. 初始化(生成本地证书等)
|
|
105
|
+
npm run init
|
|
106
|
+
|
|
107
|
+
# 4. 启动开发服务器
|
|
108
|
+
npm run dev
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 核心目录结构
|
|
112
|
+
- `src/adapters/`:各类编辑器(Cursor/Claude/Qoder)的输入信号适配器。
|
|
113
|
+
- `src/gateway/`:核心网关,负责 Adapter 注册与事件路由。
|
|
114
|
+
- `src/notifiers/`:通知分发器(桌面系统通知、移动端 WebSocket、PWA Push)。
|
|
115
|
+
- `web/`:移动端 Web App 源码。
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## ❓ 常见问题 (FAQ)
|
|
120
|
+
|
|
121
|
+
**Q: 为什么手机端收不到通知?**
|
|
122
|
+
A: 请按顺序检查:
|
|
123
|
+
1. 手机是否和电脑在同一局域网下。
|
|
124
|
+
2. 手机浏览器是否显示“安全/受信任”的 HTTPS 连接(若显示不安全,请重新检查证书安装步骤)。
|
|
125
|
+
3. 检查 Web 页面上的 WebSocket 连接状态是否显示为“已连接”。
|
|
126
|
+
|
|
127
|
+
**Q: 能否自定义运行端口?**
|
|
128
|
+
A: 可以,通过 CLI 参数或环境变量修改:
|
|
129
|
+
```bash
|
|
130
|
+
agentwake start --port 4000
|
|
131
|
+
# 或者使用环境变量
|
|
132
|
+
AGENTWAKE_PORT=4000 agentwake start
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
*AgentWake - 让 AI 编程更省心。*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-hook-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/claude-hook-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAOzD,wBAAgB,uBAAuB,IAAI,cAAc,CAoBxD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createClaudeHookAdapter = createClaudeHookAdapter;
|
|
4
|
+
const hook_common_1 = require("./hook-common");
|
|
5
|
+
function createClaudeHookAdapter() {
|
|
6
|
+
return {
|
|
7
|
+
id: "claude-hook-adapter",
|
|
8
|
+
start(context) {
|
|
9
|
+
context.app.post(context.config.claudeHookPath, async (req, res) => {
|
|
10
|
+
if (!(0, hook_common_1.validateHookSourceIp)(req, context.config.allowedHookIps)) {
|
|
11
|
+
(0, hook_common_1.forbidden)(res);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const event = (0, hook_common_1.parseHookEvent)("claude-code", "claude-hook", req.body);
|
|
15
|
+
if (!event) {
|
|
16
|
+
res.status(202).json({ ok: true, accepted: false, reason: "ignored" });
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
await context.emit(event);
|
|
20
|
+
res.status(200).json({ ok: true, accepted: true });
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=claude-hook-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-hook-adapter.js","sourceRoot":"","sources":["../../src/adapters/claude-hook-adapter.ts"],"names":[],"mappings":";;AAOA,0DAoBC;AA1BD,+CAIuB;AAEvB,SAAgB,uBAAuB;IACrC,OAAO;QACL,EAAE,EAAE,qBAAqB;QACzB,KAAK,CAAC,OAAO;YACX,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;gBACjE,IAAI,CAAC,IAAA,kCAAoB,EAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;oBAC9D,IAAA,uBAAS,EAAC,GAAG,CAAC,CAAC;oBACf,OAAO;gBACT,CAAC;gBAED,MAAM,KAAK,GAAG,IAAA,4BAAc,EAAC,aAAa,EAAE,aAAa,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;gBACrE,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;oBACvE,OAAO;gBACT,CAAC;gBACD,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC1B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor-hook-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/cursor-hook-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAezD,wBAAgB,uBAAuB,IAAI,cAAc,CA0JxD"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createCursorHookAdapter = createCursorHookAdapter;
|
|
4
|
+
const hook_common_1 = require("./hook-common");
|
|
5
|
+
const hook_common_2 = require("./hook-common");
|
|
6
|
+
const cursor_terminal_hook_1 = require("./cursor-terminal-hook");
|
|
7
|
+
const logger_1 = require("../utils/logger");
|
|
8
|
+
function createCursorHookAdapter() {
|
|
9
|
+
const pendingSignals = new Map();
|
|
10
|
+
const REQUEST_NOTIFY_DELAY_MS = 1_000;
|
|
11
|
+
const WAIT_THRESHOLD_MS = 2_000;
|
|
12
|
+
return {
|
|
13
|
+
id: "cursor-hook-adapter",
|
|
14
|
+
start(context) {
|
|
15
|
+
const cleanupSignal = (key) => {
|
|
16
|
+
const pending = pendingSignals.get(key);
|
|
17
|
+
if (!pending) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
clearTimeout(pending.notifyTimer);
|
|
21
|
+
pendingSignals.delete(key);
|
|
22
|
+
};
|
|
23
|
+
const scheduleWaitingNotify = (key, signal) => {
|
|
24
|
+
cleanupSignal(key);
|
|
25
|
+
const requestedAtMs = Date.now();
|
|
26
|
+
const notifyTimer = setTimeout(() => {
|
|
27
|
+
const pending = pendingSignals.get(key);
|
|
28
|
+
if (!pending || pending.notified) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const waitMs = Date.now() - pending.requestedAtMs;
|
|
32
|
+
pending.notified = true;
|
|
33
|
+
void context
|
|
34
|
+
.emit((0, cursor_terminal_hook_1.createCursorApprovalEvent)({
|
|
35
|
+
signal: pending.signal,
|
|
36
|
+
reason: "time-gap-before-after",
|
|
37
|
+
waitMs,
|
|
38
|
+
}))
|
|
39
|
+
.catch((error) => logger_1.logger.error("cursor delayed notify failed", { error: String(error) }));
|
|
40
|
+
}, REQUEST_NOTIFY_DELAY_MS);
|
|
41
|
+
pendingSignals.set(key, {
|
|
42
|
+
signal,
|
|
43
|
+
requestedAtMs,
|
|
44
|
+
notifyTimer,
|
|
45
|
+
notified: false,
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
context.app.post(context.config.cursorHookPath, async (req, res) => {
|
|
49
|
+
logger_1.logger.info("cursor hook incoming", {
|
|
50
|
+
event: req.body?.hook_event_name,
|
|
51
|
+
command: req.body?.command,
|
|
52
|
+
permission: req.body?.permission,
|
|
53
|
+
requiresApproval: req.body?.requiresApproval,
|
|
54
|
+
ip: req.ip || req.socket.remoteAddress,
|
|
55
|
+
});
|
|
56
|
+
if (!(0, hook_common_1.validateHookSourceIp)(req, context.config.allowedHookIps)) {
|
|
57
|
+
(0, hook_common_1.forbidden)(res);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const signal = (0, cursor_terminal_hook_1.parseCursorTerminalSignal)(req.body);
|
|
61
|
+
if (signal) {
|
|
62
|
+
const key = (0, cursor_terminal_hook_1.resolveCursorSignalKey)(signal);
|
|
63
|
+
if (signal.hookEvent === "beforeShellExecution") {
|
|
64
|
+
if (signal.explicitApproval) {
|
|
65
|
+
const event = (0, cursor_terminal_hook_1.createCursorApprovalEvent)({
|
|
66
|
+
signal,
|
|
67
|
+
reason: "explicit-hook-signal",
|
|
68
|
+
});
|
|
69
|
+
void context.emit(event).catch((error) => logger_1.logger.error("cursor notify emit failed", { error: String(error) }));
|
|
70
|
+
logger_1.logger.info("cursor hook accepted", {
|
|
71
|
+
dedupeKey: event.dedupeKey,
|
|
72
|
+
title: event.title,
|
|
73
|
+
level: event.level,
|
|
74
|
+
reason: "explicit-hook-signal",
|
|
75
|
+
});
|
|
76
|
+
res.status(200).json({ ok: true, accepted: true });
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
scheduleWaitingNotify(key, signal);
|
|
80
|
+
logger_1.logger.info("cursor hook pending approval watch", {
|
|
81
|
+
key,
|
|
82
|
+
command: signal.command,
|
|
83
|
+
delayMs: REQUEST_NOTIFY_DELAY_MS,
|
|
84
|
+
});
|
|
85
|
+
res.status(202).json({ ok: true, accepted: false, reason: "pending-time-check" });
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const pending = pendingSignals.get(key);
|
|
89
|
+
if (pending) {
|
|
90
|
+
const waitMs = Math.max(typeof signal.durationMs === "number" ? signal.durationMs : 0, Date.now() - pending.requestedAtMs);
|
|
91
|
+
clearTimeout(pending.notifyTimer);
|
|
92
|
+
pendingSignals.delete(key);
|
|
93
|
+
if (!pending.notified && waitMs >= WAIT_THRESHOLD_MS) {
|
|
94
|
+
const event = (0, cursor_terminal_hook_1.createCursorApprovalEvent)({
|
|
95
|
+
signal: pending.signal,
|
|
96
|
+
reason: "time-gap-after-shell",
|
|
97
|
+
waitMs,
|
|
98
|
+
});
|
|
99
|
+
void context.emit(event).catch((error) => logger_1.logger.error("cursor notify emit failed", { error: String(error) }));
|
|
100
|
+
logger_1.logger.info("cursor hook accepted", {
|
|
101
|
+
dedupeKey: event.dedupeKey,
|
|
102
|
+
title: event.title,
|
|
103
|
+
level: event.level,
|
|
104
|
+
reason: "time-gap-after-shell",
|
|
105
|
+
waitMs,
|
|
106
|
+
});
|
|
107
|
+
res.status(200).json({ ok: true, accepted: true });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
logger_1.logger.info("cursor hook resolved quickly", {
|
|
111
|
+
key,
|
|
112
|
+
waitMs,
|
|
113
|
+
});
|
|
114
|
+
res.status(202).json({ ok: true, accepted: false, reason: "resolved-quickly" });
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const event = (0, cursor_terminal_hook_1.parseCursorTerminalHookEvent)(req.body) ?? (0, hook_common_2.parseHookEvent)("cursor", "cursor-hook", req.body);
|
|
119
|
+
if (!event) {
|
|
120
|
+
logger_1.logger.info("cursor hook ignored", {
|
|
121
|
+
event: req.body?.hook_event_name,
|
|
122
|
+
command: req.body?.command,
|
|
123
|
+
});
|
|
124
|
+
res.status(202).json({ ok: true, accepted: false, reason: "ignored" });
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
logger_1.logger.info("cursor hook accepted", {
|
|
128
|
+
dedupeKey: event.dedupeKey,
|
|
129
|
+
title: event.title,
|
|
130
|
+
level: event.level,
|
|
131
|
+
});
|
|
132
|
+
await context.emit(event);
|
|
133
|
+
res.status(200).json({ ok: true, accepted: true });
|
|
134
|
+
});
|
|
135
|
+
return () => {
|
|
136
|
+
for (const pending of pendingSignals.values()) {
|
|
137
|
+
clearTimeout(pending.notifyTimer);
|
|
138
|
+
}
|
|
139
|
+
pendingSignals.clear();
|
|
140
|
+
};
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=cursor-hook-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor-hook-adapter.js","sourceRoot":"","sources":["../../src/adapters/cursor-hook-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type NotifyEvent } from "../domain/notify-event";
|
|
2
|
+
export type CursorTerminalSignal = {
|
|
3
|
+
hookEvent: "beforeShellExecution" | "afterShellExecution";
|
|
4
|
+
command: string;
|
|
5
|
+
cwd?: string;
|
|
6
|
+
conversationId?: string;
|
|
7
|
+
generationId?: string;
|
|
8
|
+
timestampMs: number;
|
|
9
|
+
explicitApproval: boolean;
|
|
10
|
+
durationMs?: number;
|
|
11
|
+
};
|
|
12
|
+
export declare function parseCursorTerminalSignal(body: unknown): CursorTerminalSignal | null;
|
|
13
|
+
export declare function resolveCursorSignalKey(signal: CursorTerminalSignal): string;
|
|
14
|
+
export declare function createCursorApprovalEvent(params: {
|
|
15
|
+
signal: CursorTerminalSignal;
|
|
16
|
+
reason?: string;
|
|
17
|
+
waitMs?: number;
|
|
18
|
+
}): NotifyEvent;
|
|
19
|
+
export declare function parseCursorTerminalHookEvent(body: unknown): NotifyEvent | null;
|
|
20
|
+
//# sourceMappingURL=cursor-terminal-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor-terminal-hook.d.ts","sourceRoot":"","sources":["../../src/adapters/cursor-terminal-hook.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AA4B7E,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,sBAAsB,GAAG,qBAAqB,CAAC;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AA2BF,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG,oBAAoB,GAAG,IAAI,CAwBpF;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAG3E;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE;IAChD,MAAM,EAAE,oBAAoB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,WAAW,CA+Bd;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI,CAM9E"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseCursorTerminalSignal = parseCursorTerminalSignal;
|
|
4
|
+
exports.resolveCursorSignalKey = resolveCursorSignalKey;
|
|
5
|
+
exports.createCursorApprovalEvent = createCursorApprovalEvent;
|
|
6
|
+
exports.parseCursorTerminalHookEvent = parseCursorTerminalHookEvent;
|
|
7
|
+
const zod_1 = require("zod");
|
|
8
|
+
const notify_event_1 = require("../domain/notify-event");
|
|
9
|
+
const approval_match_1 = require("../utils/approval-match");
|
|
10
|
+
const cursorTerminalSchema = zod_1.z.object({
|
|
11
|
+
hook_event_name: zod_1.z.string().optional(),
|
|
12
|
+
conversation_id: zod_1.z.string().optional(),
|
|
13
|
+
generation_id: zod_1.z.string().optional(),
|
|
14
|
+
command: zod_1.z.string().optional(),
|
|
15
|
+
cwd: zod_1.z.string().optional(),
|
|
16
|
+
status: zod_1.z.string().optional(),
|
|
17
|
+
state: zod_1.z.string().optional(),
|
|
18
|
+
message: zod_1.z.string().optional(),
|
|
19
|
+
userMessage: zod_1.z.string().optional(),
|
|
20
|
+
agentMessage: zod_1.z.string().optional(),
|
|
21
|
+
reason: zod_1.z.string().optional(),
|
|
22
|
+
requiresApproval: zod_1.z.boolean().optional(),
|
|
23
|
+
approvalRequired: zod_1.z.boolean().optional(),
|
|
24
|
+
pendingApproval: zod_1.z.boolean().optional(),
|
|
25
|
+
permission: zod_1.z.string().optional(),
|
|
26
|
+
decision: zod_1.z.string().optional(),
|
|
27
|
+
continue: zod_1.z.boolean().optional(),
|
|
28
|
+
exit_code: zod_1.z.number().optional(),
|
|
29
|
+
duration: zod_1.z.number().optional(),
|
|
30
|
+
output: zod_1.z.string().optional(),
|
|
31
|
+
sandbox: zod_1.z.boolean().optional(),
|
|
32
|
+
workspace_roots: zod_1.z.array(zod_1.z.string()).optional(),
|
|
33
|
+
});
|
|
34
|
+
function compactBody(parts) {
|
|
35
|
+
return parts
|
|
36
|
+
.map((item) => item?.trim())
|
|
37
|
+
.filter((item) => Boolean(item))
|
|
38
|
+
.join("\n");
|
|
39
|
+
}
|
|
40
|
+
function resolveExplicitApproval(payload) {
|
|
41
|
+
return (payload.requiresApproval === true ||
|
|
42
|
+
payload.approvalRequired === true ||
|
|
43
|
+
payload.pendingApproval === true ||
|
|
44
|
+
payload.permission === "ask" ||
|
|
45
|
+
payload.decision === "ask" ||
|
|
46
|
+
payload.state === "awaiting_user_approval" ||
|
|
47
|
+
payload.state === "waiting_for_user_approval" ||
|
|
48
|
+
payload.status === "awaiting_user_approval" ||
|
|
49
|
+
payload.status === "waiting_for_user_approval" ||
|
|
50
|
+
(0, approval_match_1.isApprovalWaitingText)(payload.message ?? "") ||
|
|
51
|
+
(0, approval_match_1.isApprovalWaitingText)(payload.userMessage ?? "") ||
|
|
52
|
+
(0, approval_match_1.isApprovalWaitingText)(payload.agentMessage ?? "") ||
|
|
53
|
+
(0, approval_match_1.isApprovalWaitingText)(payload.reason ?? ""));
|
|
54
|
+
}
|
|
55
|
+
function parseCursorTerminalSignal(body) {
|
|
56
|
+
const parsed = cursorTerminalSchema.safeParse(body);
|
|
57
|
+
if (!parsed.success) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
const payload = parsed.data;
|
|
61
|
+
const hookEvent = payload.hook_event_name?.trim();
|
|
62
|
+
if (hookEvent !== "beforeShellExecution" && hookEvent !== "afterShellExecution") {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const command = payload.command?.trim();
|
|
66
|
+
if (!command) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
hookEvent,
|
|
71
|
+
command,
|
|
72
|
+
...(payload.cwd ? { cwd: payload.cwd } : {}),
|
|
73
|
+
...(payload.conversation_id ? { conversationId: payload.conversation_id } : {}),
|
|
74
|
+
...(payload.generation_id ? { generationId: payload.generation_id } : {}),
|
|
75
|
+
timestampMs: Date.now(),
|
|
76
|
+
explicitApproval: resolveExplicitApproval(payload),
|
|
77
|
+
...(typeof payload.duration === "number" ? { durationMs: payload.duration } : {}),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function resolveCursorSignalKey(signal) {
|
|
81
|
+
const idPart = signal.generationId ?? signal.conversationId ?? "unknown";
|
|
82
|
+
return `${idPart}:${signal.command}`;
|
|
83
|
+
}
|
|
84
|
+
function createCursorApprovalEvent(params) {
|
|
85
|
+
const { signal } = params;
|
|
86
|
+
const waitSec = typeof params.waitMs === "number" && Number.isFinite(params.waitMs) ? params.waitMs / 1000 : undefined;
|
|
87
|
+
const waitToken = typeof waitSec === "number" ? `${waitSec.toFixed(1)}s` : undefined;
|
|
88
|
+
const bodyText = compactBody([
|
|
89
|
+
`命令: ${signal.command}`,
|
|
90
|
+
signal.cwd ? `目录: ${signal.cwd}` : undefined,
|
|
91
|
+
params.reason ? `原因: ${params.reason}` : undefined,
|
|
92
|
+
waitToken ? `等待时长: ${waitToken}` : undefined,
|
|
93
|
+
]) || signal.command;
|
|
94
|
+
return (0, notify_event_1.createNotifyEvent)({
|
|
95
|
+
source: "cursor-hook",
|
|
96
|
+
editor: "cursor",
|
|
97
|
+
level: "warn",
|
|
98
|
+
title: "Cursor 终端等待用户同意",
|
|
99
|
+
body: bodyText,
|
|
100
|
+
dedupeKey: `cursor:approval:${resolveCursorSignalKey(signal)}`,
|
|
101
|
+
meta: {
|
|
102
|
+
hookEvent: signal.hookEvent,
|
|
103
|
+
command: signal.command,
|
|
104
|
+
cwd: signal.cwd,
|
|
105
|
+
conversationId: signal.conversationId,
|
|
106
|
+
generationId: signal.generationId,
|
|
107
|
+
reason: params.reason,
|
|
108
|
+
waitMs: params.waitMs,
|
|
109
|
+
explicitApproval: signal.explicitApproval,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function parseCursorTerminalHookEvent(body) {
|
|
114
|
+
const signal = parseCursorTerminalSignal(body);
|
|
115
|
+
if (!signal || signal.hookEvent !== "beforeShellExecution" || !signal.explicitApproval) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
return createCursorApprovalEvent({ signal, reason: "explicit-hook-signal" });
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=cursor-terminal-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor-terminal-hook.js","sourceRoot":"","sources":["../../src/adapters/cursor-terminal-hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Request, Response } from "express";
|
|
2
|
+
import { type EditorKind, type NotifyEvent } from "../domain/notify-event";
|
|
3
|
+
export declare function parseHookEvent(editor: EditorKind, source: string, body: unknown): NotifyEvent | null;
|
|
4
|
+
export declare function validateHookSourceIp(req: Request, allowlist: string[]): boolean;
|
|
5
|
+
export declare function forbidden(res: Response): void;
|
|
6
|
+
//# sourceMappingURL=hook-common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-common.d.ts","sourceRoot":"","sources":["../../src/adapters/hook-common.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEjD,OAAO,EAAqB,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAc9F,wBAAgB,cAAc,CAC5B,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACZ,WAAW,GAAG,IAAI,CAiCpB;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAgB/E;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAE7C"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseHookEvent = parseHookEvent;
|
|
4
|
+
exports.validateHookSourceIp = validateHookSourceIp;
|
|
5
|
+
exports.forbidden = forbidden;
|
|
6
|
+
const zod_1 = require("zod");
|
|
7
|
+
const notify_event_1 = require("../domain/notify-event");
|
|
8
|
+
const approval_match_1 = require("../utils/approval-match");
|
|
9
|
+
const hookPayloadSchema = zod_1.z.object({
|
|
10
|
+
title: zod_1.z.string().optional(),
|
|
11
|
+
message: zod_1.z.string().optional(),
|
|
12
|
+
text: zod_1.z.string().optional(),
|
|
13
|
+
event: zod_1.z.string().optional(),
|
|
14
|
+
status: zod_1.z.string().optional(),
|
|
15
|
+
requiresApproval: zod_1.z.boolean().optional(),
|
|
16
|
+
idempotencyKey: zod_1.z.string().optional(),
|
|
17
|
+
meta: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
|
|
18
|
+
});
|
|
19
|
+
function parseHookEvent(editor, source, body) {
|
|
20
|
+
const parsed = hookPayloadSchema.safeParse(body);
|
|
21
|
+
if (!parsed.success) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const payload = parsed.data;
|
|
25
|
+
const title = payload.title?.trim() || `${editor} waiting`;
|
|
26
|
+
const message = payload.message?.trim() || payload.text?.trim() || "";
|
|
27
|
+
const status = payload.status?.trim() ?? "";
|
|
28
|
+
const evt = payload.event?.trim() ?? "";
|
|
29
|
+
const requiresApproval = payload.requiresApproval === true;
|
|
30
|
+
const hit = requiresApproval ||
|
|
31
|
+
(0, approval_match_1.isApprovalWaitingText)(message) ||
|
|
32
|
+
(0, approval_match_1.isApprovalWaitingText)(status) ||
|
|
33
|
+
(0, approval_match_1.isApprovalWaitingText)(evt);
|
|
34
|
+
if (!hit) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const bodyText = message || status || evt || "Agent is waiting for user approval.";
|
|
38
|
+
const idempotencyKey = payload.idempotencyKey?.trim();
|
|
39
|
+
const dedupeKey = idempotencyKey || `${source}:${title}:${bodyText}`;
|
|
40
|
+
return (0, notify_event_1.createNotifyEvent)({
|
|
41
|
+
source,
|
|
42
|
+
editor,
|
|
43
|
+
level: "warn",
|
|
44
|
+
title,
|
|
45
|
+
body: bodyText,
|
|
46
|
+
dedupeKey,
|
|
47
|
+
...(payload.meta ? { meta: payload.meta } : {}),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function validateHookSourceIp(req, allowlist) {
|
|
51
|
+
if (allowlist.length === 0) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
const raw = req.ip ||
|
|
55
|
+
req.socket.remoteAddress ||
|
|
56
|
+
(Array.isArray(req.headers["x-forwarded-for"])
|
|
57
|
+
? req.headers["x-forwarded-for"][0]
|
|
58
|
+
: req.headers["x-forwarded-for"]) ||
|
|
59
|
+
"";
|
|
60
|
+
if (!raw) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const ip = String(raw).split(",")[0]?.trim() ?? "";
|
|
64
|
+
return allowlist.includes(ip);
|
|
65
|
+
}
|
|
66
|
+
function forbidden(res) {
|
|
67
|
+
res.status(403).json({ ok: false, error: "forbidden source ip" });
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=hook-common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-common.js","sourceRoot":"","sources":["../../src/adapters/hook-common.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { GatewayAdapter } from "../gateway/adapter";
|
|
2
|
+
export type QoderLogSignal = {
|
|
3
|
+
type: "permission_requested";
|
|
4
|
+
toolCallId: string;
|
|
5
|
+
toolName: string;
|
|
6
|
+
logTimestampSec: number | undefined;
|
|
7
|
+
} | {
|
|
8
|
+
type: "permission_resolved";
|
|
9
|
+
toolCallId: string;
|
|
10
|
+
outcome: "allow" | "reject" | "cancelled" | "unknown";
|
|
11
|
+
logTimestampSec: number | undefined;
|
|
12
|
+
} | {
|
|
13
|
+
type: "agent_suspended";
|
|
14
|
+
} | {
|
|
15
|
+
type: "agent_resumed";
|
|
16
|
+
};
|
|
17
|
+
export declare function parseQoderLogLine(line: string): QoderLogSignal | null;
|
|
18
|
+
export declare function createQoderLogAdapter(): GatewayAdapter;
|
|
19
|
+
//# sourceMappingURL=qoder-log-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qoder-log-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/qoder-log-adapter.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGtE,MAAM,MAAM,cAAc,GACtB;IACE,IAAI,EAAE,sBAAsB,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC,GACD;IACE,IAAI,EAAE,qBAAqB,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;IACtD,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC,GACD;IACE,IAAI,EAAE,iBAAiB,CAAC;CACzB,GACD;IACE,IAAI,EAAE,eAAe,CAAC;CACvB,CAAC;AA2IN,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAyCrE;AAED,wBAAgB,qBAAqB,IAAI,cAAc,CA0KtD"}
|