@commandgarden/cli 2.2.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/main.js +1 -0
  2. package/node_modules/@commandgarden/app/dist/client/assets/index--IDuJWmP.js +397 -0
  3. package/node_modules/@commandgarden/app/dist/client/assets/index-qunCIeG9.css +1 -0
  4. package/node_modules/@commandgarden/app/dist/client/index.html +19 -19
  5. package/node_modules/@commandgarden/app/dist/server/daemon-client.test.js +47 -0
  6. package/node_modules/@commandgarden/app/dist/server/routes/index.js +2 -0
  7. package/node_modules/@commandgarden/app/dist/server/routes/routes.test.js +137 -0
  8. package/node_modules/@commandgarden/app/dist/server/routes/trusted-peers-cache.d.ts +3 -0
  9. package/node_modules/@commandgarden/app/dist/server/routes/trusted-peers-cache.js +17 -0
  10. package/node_modules/@commandgarden/app/dist/server/store.d.ts +5 -0
  11. package/node_modules/@commandgarden/app/dist/server/store.js +50 -31
  12. package/node_modules/@commandgarden/app/dist/server/store.test.js +59 -0
  13. package/node_modules/@commandgarden/app/package.json +42 -42
  14. package/node_modules/@commandgarden/chrome/dist/content-script.js.map +1 -1
  15. package/node_modules/@commandgarden/chrome/dist/fetch-interceptor.js +44 -0
  16. package/node_modules/@commandgarden/chrome/dist/manifest.json +16 -16
  17. package/node_modules/@commandgarden/chrome/dist/popup.html +218 -218
  18. package/node_modules/@commandgarden/chrome/dist/popup.js.map +1 -1
  19. package/node_modules/@commandgarden/chrome/dist/service-worker.js +2 -1
  20. package/node_modules/@commandgarden/chrome/dist/service-worker.js.map +2 -2
  21. package/node_modules/@commandgarden/chrome/package.json +25 -25
  22. package/node_modules/@commandgarden/daemon/connectors/ado-git-commits.eval.js +143 -143
  23. package/node_modules/@commandgarden/daemon/connectors/ado-git-commits.yaml +70 -70
  24. package/node_modules/@commandgarden/daemon/connectors/gcs-kb-content.yaml +58 -58
  25. package/node_modules/@commandgarden/daemon/connectors/gcs-kb-pages.yaml +47 -47
  26. package/node_modules/@commandgarden/daemon/connectors/jira-my-tickets.eval.js +115 -115
  27. package/node_modules/@commandgarden/daemon/connectors/jira-my-tickets.yaml +54 -54
  28. package/node_modules/@commandgarden/daemon/connectors/lib/msal-token.js +20 -20
  29. package/node_modules/@commandgarden/daemon/connectors/outlook-my-meetings.eval.js +186 -186
  30. package/node_modules/@commandgarden/daemon/connectors/outlook-my-meetings.yaml +41 -41
  31. package/node_modules/@commandgarden/daemon/connectors/saba-pending-training.eval.js +94 -94
  32. package/node_modules/@commandgarden/daemon/connectors/saba-pending-training.yaml +34 -34
  33. package/node_modules/@commandgarden/daemon/connectors/socket-security-news.yaml +63 -63
  34. package/node_modules/@commandgarden/daemon/connectors/teams-room-availability.eval.js +342 -341
  35. package/node_modules/@commandgarden/daemon/connectors/teams-room-availability.yaml +47 -46
  36. package/node_modules/@commandgarden/daemon/connectors/teams-rooms-availability.eval.js +439 -0
  37. package/node_modules/@commandgarden/daemon/connectors/teams-rooms-availability.yaml +48 -0
  38. package/node_modules/@commandgarden/daemon/connectors/timetracking-projects.eval.js +52 -52
  39. package/node_modules/@commandgarden/daemon/connectors/timetracking-projects.yaml +42 -42
  40. package/node_modules/@commandgarden/daemon/connectors/timetracking-report.eval.js +81 -81
  41. package/node_modules/@commandgarden/daemon/connectors/timetracking-report.yaml +52 -52
  42. package/node_modules/@commandgarden/daemon/connectors/tldrsec-newsletter.eval.js +27 -27
  43. package/node_modules/@commandgarden/daemon/connectors/tldrsec-newsletter.yaml +38 -38
  44. package/node_modules/@commandgarden/daemon/connectors/tokenmaster-clients-list.yaml +55 -55
  45. package/node_modules/@commandgarden/daemon/dist/audit-store.js +8 -8
  46. package/node_modules/@commandgarden/daemon/dist/cdp-client.d.ts +24 -0
  47. package/node_modules/@commandgarden/daemon/dist/cdp-client.d.ts.map +1 -0
  48. package/node_modules/@commandgarden/daemon/dist/cdp-client.js +150 -0
  49. package/node_modules/@commandgarden/daemon/dist/cdp-client.js.map +1 -0
  50. package/node_modules/@commandgarden/daemon/package.json +32 -32
  51. package/node_modules/@commandgarden/shared/dist/connector.d.ts +3 -0
  52. package/node_modules/@commandgarden/shared/dist/connector.d.ts.map +1 -1
  53. package/node_modules/@commandgarden/shared/dist/connector.js +1 -0
  54. package/node_modules/@commandgarden/shared/dist/connector.js.map +1 -1
  55. package/node_modules/@commandgarden/shared/package.json +32 -32
  56. package/package.json +58 -58
  57. package/node_modules/@commandgarden/app/dist/client/assets/index-Cglxej9D.css +0 -1
  58. package/node_modules/@commandgarden/app/dist/client/assets/index-Cju0_G1Y.js +0 -397
@@ -1,218 +1,218 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <link rel="preconnect" href="https://fonts.googleapis.com" />
6
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
7
- <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
8
- <style>
9
- * { margin: 0; padding: 0; box-sizing: border-box; border-radius: 0 !important; }
10
- body {
11
- width: 320px;
12
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
13
- font-size: 13px;
14
- background: #0a0a0a;
15
- color: #e5e5e5;
16
- }
17
- .header {
18
- padding: 12px 16px;
19
- border-bottom: 1px solid #262626;
20
- }
21
- .header-title {
22
- font-family: 'Space Grotesk', -apple-system, BlinkMacSystemFont, sans-serif;
23
- font-size: 14px;
24
- font-weight: 700;
25
- letter-spacing: -0.02em;
26
- color: #e5e5e5;
27
- }
28
- .header-title span {
29
- font-weight: 400;
30
- opacity: 0.6;
31
- }
32
- .header-sub {
33
- font-family: 'JetBrains Mono', ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
34
- font-size: 0.6rem;
35
- font-weight: 500;
36
- text-transform: uppercase;
37
- letter-spacing: 0.12em;
38
- opacity: 0.4;
39
- margin-top: 2px;
40
- }
41
- .status-row {
42
- display: flex;
43
- align-items: center;
44
- gap: 8px;
45
- padding: 10px 16px;
46
- border-bottom: 1px solid #262626;
47
- }
48
- .dot {
49
- width: 8px;
50
- height: 8px;
51
- flex-shrink: 0;
52
- }
53
- .dot.connected { background: #4ade80; }
54
- .dot.disconnected { background: #f87171; }
55
- .dot.disabled { background: #737373; }
56
- .status-text { flex: 1; }
57
- .toggle {
58
- position: relative;
59
- width: 36px;
60
- height: 20px;
61
- flex-shrink: 0;
62
- cursor: pointer;
63
- }
64
- .toggle input {
65
- opacity: 0;
66
- width: 0;
67
- height: 0;
68
- }
69
- .toggle-track {
70
- position: absolute;
71
- inset: 0;
72
- background: #262626;
73
- transition: background 0.15s;
74
- }
75
- .toggle input:checked + .toggle-track {
76
- background: #4ade80;
77
- }
78
- .toggle-knob {
79
- position: absolute;
80
- top: 2px;
81
- left: 2px;
82
- width: 16px;
83
- height: 16px;
84
- background: #e5e5e5;
85
- transition: transform 0.15s;
86
- pointer-events: none;
87
- }
88
- .toggle input:checked ~ .toggle-knob {
89
- transform: translateX(16px);
90
- }
91
- .activity-list {
92
- max-height: 240px;
93
- overflow-y: auto;
94
- }
95
- .activity-item {
96
- display: flex;
97
- align-items: center;
98
- gap: 8px;
99
- padding: 8px 16px;
100
- border-bottom: 1px solid #171717;
101
- transition: background 0.1s;
102
- }
103
- .activity-item:hover {
104
- background: #171717;
105
- }
106
- .activity-icon { font-size: 12px; flex-shrink: 0; }
107
- .activity-icon.ok { color: #4ade80; }
108
- .activity-icon.fail { color: #f87171; }
109
- .activity-name { flex: 1; font-family: 'JetBrains Mono', ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace; font-size: 12px; }
110
- .activity-time { color: #a3a3a3; font-size: 11px; flex-shrink: 0; }
111
- .empty {
112
- padding: 16px;
113
- text-align: center;
114
- color: #737373;
115
- font-style: italic;
116
- }
117
- /* Approval section */
118
- .approval-section {
119
- border-bottom: 1px solid #262626;
120
- background: #171717;
121
- }
122
- .approval-header {
123
- padding: 10px 16px 4px;
124
- font-size: 12px;
125
- font-weight: 600;
126
- color: #e5e5e5;
127
- }
128
- .approval-count {
129
- display: inline-block;
130
- font-size: 10px;
131
- min-width: 16px;
132
- text-align: center;
133
- padding: 0 5px;
134
- line-height: 16px;
135
- background: rgba(251, 191, 36, 0.15);
136
- color: #fbbf24;
137
- font-weight: 700;
138
- margin-left: 6px;
139
- vertical-align: 1px;
140
- }
141
- .approval-card {
142
- padding: 10px 16px;
143
- display: flex;
144
- flex-direction: column;
145
- gap: 6px;
146
- }
147
- .approval-card + .approval-card {
148
- border-top: 1px solid #262626;
149
- }
150
- .approval-connector {
151
- font-family: 'JetBrains Mono', ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
152
- font-size: 12px;
153
- color: #e5e5e5;
154
- }
155
- .approval-detail {
156
- font-size: 11px;
157
- color: #a3a3a3;
158
- }
159
- .approval-cap {
160
- display: inline-block;
161
- font-size: 10px;
162
- padding: 1px 6px;
163
- background: rgba(251, 191, 36, 0.12);
164
- color: #fbbf24;
165
- font-family: 'JetBrains Mono', ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
166
- }
167
- .approval-actions {
168
- display: flex;
169
- gap: 8px;
170
- margin-top: 2px;
171
- }
172
- .btn-approve, .btn-reject {
173
- font-size: 11px;
174
- padding: 4px 14px;
175
- border: none;
176
- cursor: pointer;
177
- font-weight: 600;
178
- transition: background 0.15s, color 0.15s;
179
- }
180
- .btn-approve {
181
- background: #4ade80;
182
- color: #0a0a0a;
183
- }
184
- .btn-approve:hover { background: #22c55e; }
185
- .btn-approve:active { background: #16a34a; }
186
- .btn-reject {
187
- background: transparent;
188
- color: #a3a3a3;
189
- border: 1px solid #262626;
190
- }
191
- .btn-reject:hover { background: #171717; color: #e5e5e5; }
192
- .btn-reject:active { background: #262626; }
193
- /* Scrollbar */
194
- ::-webkit-scrollbar { width: 6px; height: 6px; }
195
- ::-webkit-scrollbar-track { background: transparent; }
196
- ::-webkit-scrollbar-thumb { background: rgba(229, 229, 229, 0.2); }
197
- ::-webkit-scrollbar-thumb:hover { background: rgba(229, 229, 229, 0.35); }
198
- </style>
199
- </head>
200
- <body>
201
- <div class="header">
202
- <div class="header-title"><span>command</span>Garden</div>
203
- <div class="header-sub">browser automation</div>
204
- </div>
205
- <div class="status-row">
206
- <div id="dot" class="dot disabled"></div>
207
- <span id="status-text" class="status-text">Checking…</span>
208
- <label class="toggle">
209
- <input type="checkbox" id="toggle-input">
210
- <div class="toggle-track"></div>
211
- <div class="toggle-knob"></div>
212
- </label>
213
- </div>
214
- <div id="approvals"></div>
215
- <div id="activity" class="activity-list"></div>
216
- <script src="popup.js"></script>
217
- </body>
218
- </html>
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
6
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
7
+ <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
8
+ <style>
9
+ * { margin: 0; padding: 0; box-sizing: border-box; border-radius: 0 !important; }
10
+ body {
11
+ width: 320px;
12
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
13
+ font-size: 13px;
14
+ background: #0a0a0a;
15
+ color: #e5e5e5;
16
+ }
17
+ .header {
18
+ padding: 12px 16px;
19
+ border-bottom: 1px solid #262626;
20
+ }
21
+ .header-title {
22
+ font-family: 'Space Grotesk', -apple-system, BlinkMacSystemFont, sans-serif;
23
+ font-size: 14px;
24
+ font-weight: 700;
25
+ letter-spacing: -0.02em;
26
+ color: #e5e5e5;
27
+ }
28
+ .header-title span {
29
+ font-weight: 400;
30
+ opacity: 0.6;
31
+ }
32
+ .header-sub {
33
+ font-family: 'JetBrains Mono', ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
34
+ font-size: 0.6rem;
35
+ font-weight: 500;
36
+ text-transform: uppercase;
37
+ letter-spacing: 0.12em;
38
+ opacity: 0.4;
39
+ margin-top: 2px;
40
+ }
41
+ .status-row {
42
+ display: flex;
43
+ align-items: center;
44
+ gap: 8px;
45
+ padding: 10px 16px;
46
+ border-bottom: 1px solid #262626;
47
+ }
48
+ .dot {
49
+ width: 8px;
50
+ height: 8px;
51
+ flex-shrink: 0;
52
+ }
53
+ .dot.connected { background: #4ade80; }
54
+ .dot.disconnected { background: #f87171; }
55
+ .dot.disabled { background: #737373; }
56
+ .status-text { flex: 1; }
57
+ .toggle {
58
+ position: relative;
59
+ width: 36px;
60
+ height: 20px;
61
+ flex-shrink: 0;
62
+ cursor: pointer;
63
+ }
64
+ .toggle input {
65
+ opacity: 0;
66
+ width: 0;
67
+ height: 0;
68
+ }
69
+ .toggle-track {
70
+ position: absolute;
71
+ inset: 0;
72
+ background: #262626;
73
+ transition: background 0.15s;
74
+ }
75
+ .toggle input:checked + .toggle-track {
76
+ background: #4ade80;
77
+ }
78
+ .toggle-knob {
79
+ position: absolute;
80
+ top: 2px;
81
+ left: 2px;
82
+ width: 16px;
83
+ height: 16px;
84
+ background: #e5e5e5;
85
+ transition: transform 0.15s;
86
+ pointer-events: none;
87
+ }
88
+ .toggle input:checked ~ .toggle-knob {
89
+ transform: translateX(16px);
90
+ }
91
+ .activity-list {
92
+ max-height: 240px;
93
+ overflow-y: auto;
94
+ }
95
+ .activity-item {
96
+ display: flex;
97
+ align-items: center;
98
+ gap: 8px;
99
+ padding: 8px 16px;
100
+ border-bottom: 1px solid #171717;
101
+ transition: background 0.1s;
102
+ }
103
+ .activity-item:hover {
104
+ background: #171717;
105
+ }
106
+ .activity-icon { font-size: 12px; flex-shrink: 0; }
107
+ .activity-icon.ok { color: #4ade80; }
108
+ .activity-icon.fail { color: #f87171; }
109
+ .activity-name { flex: 1; font-family: 'JetBrains Mono', ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace; font-size: 12px; }
110
+ .activity-time { color: #a3a3a3; font-size: 11px; flex-shrink: 0; }
111
+ .empty {
112
+ padding: 16px;
113
+ text-align: center;
114
+ color: #737373;
115
+ font-style: italic;
116
+ }
117
+ /* Approval section */
118
+ .approval-section {
119
+ border-bottom: 1px solid #262626;
120
+ background: #171717;
121
+ }
122
+ .approval-header {
123
+ padding: 10px 16px 4px;
124
+ font-size: 12px;
125
+ font-weight: 600;
126
+ color: #e5e5e5;
127
+ }
128
+ .approval-count {
129
+ display: inline-block;
130
+ font-size: 10px;
131
+ min-width: 16px;
132
+ text-align: center;
133
+ padding: 0 5px;
134
+ line-height: 16px;
135
+ background: rgba(251, 191, 36, 0.15);
136
+ color: #fbbf24;
137
+ font-weight: 700;
138
+ margin-left: 6px;
139
+ vertical-align: 1px;
140
+ }
141
+ .approval-card {
142
+ padding: 10px 16px;
143
+ display: flex;
144
+ flex-direction: column;
145
+ gap: 6px;
146
+ }
147
+ .approval-card + .approval-card {
148
+ border-top: 1px solid #262626;
149
+ }
150
+ .approval-connector {
151
+ font-family: 'JetBrains Mono', ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
152
+ font-size: 12px;
153
+ color: #e5e5e5;
154
+ }
155
+ .approval-detail {
156
+ font-size: 11px;
157
+ color: #a3a3a3;
158
+ }
159
+ .approval-cap {
160
+ display: inline-block;
161
+ font-size: 10px;
162
+ padding: 1px 6px;
163
+ background: rgba(251, 191, 36, 0.12);
164
+ color: #fbbf24;
165
+ font-family: 'JetBrains Mono', ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
166
+ }
167
+ .approval-actions {
168
+ display: flex;
169
+ gap: 8px;
170
+ margin-top: 2px;
171
+ }
172
+ .btn-approve, .btn-reject {
173
+ font-size: 11px;
174
+ padding: 4px 14px;
175
+ border: none;
176
+ cursor: pointer;
177
+ font-weight: 600;
178
+ transition: background 0.15s, color 0.15s;
179
+ }
180
+ .btn-approve {
181
+ background: #4ade80;
182
+ color: #0a0a0a;
183
+ }
184
+ .btn-approve:hover { background: #22c55e; }
185
+ .btn-approve:active { background: #16a34a; }
186
+ .btn-reject {
187
+ background: transparent;
188
+ color: #a3a3a3;
189
+ border: 1px solid #262626;
190
+ }
191
+ .btn-reject:hover { background: #171717; color: #e5e5e5; }
192
+ .btn-reject:active { background: #262626; }
193
+ /* Scrollbar */
194
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
195
+ ::-webkit-scrollbar-track { background: transparent; }
196
+ ::-webkit-scrollbar-thumb { background: rgba(229, 229, 229, 0.2); }
197
+ ::-webkit-scrollbar-thumb:hover { background: rgba(229, 229, 229, 0.35); }
198
+ </style>
199
+ </head>
200
+ <body>
201
+ <div class="header">
202
+ <div class="header-title"><span>command</span>Garden</div>
203
+ <div class="header-sub">browser automation</div>
204
+ </div>
205
+ <div class="status-row">
206
+ <div id="dot" class="dot disabled"></div>
207
+ <span id="status-text" class="status-text">Checking…</span>
208
+ <label class="toggle">
209
+ <input type="checkbox" id="toggle-input">
210
+ <div class="toggle-track"></div>
211
+ <div class="toggle-knob"></div>
212
+ </label>
213
+ </div>
214
+ <div id="approvals"></div>
215
+ <div id="activity" class="activity-list"></div>
216
+ <script src="popup.js"></script>
217
+ </body>
218
+ </html>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/popup/time-ago.ts", "../src/popup/popup.ts"],
4
- "sourcesContent": ["// src/popup/time-ago.ts\r\nexport function timeAgo(timestamp: number, now: number = Date.now()): string {\r\n const seconds = Math.floor((now - timestamp) / 1000);\r\n if (seconds < 60) return 'just now';\r\n const minutes = Math.floor(seconds / 60);\r\n if (minutes < 60) return `${minutes}m ago`;\r\n const hours = Math.floor(minutes / 60);\r\n if (hours < 24) return `${hours}h ago`;\r\n const days = Math.floor(hours / 24);\r\n return `${days}d ago`;\r\n}\r\n", "// src/popup/popup.ts\r\n/// <reference lib=\"dom\" />\r\nimport type { PopupStatusResponse, ApprovalInfo } from './popup-types.js';\r\nimport { timeAgo } from './time-ago.js';\r\n\r\nconst dot = document.getElementById('dot')!;\r\nconst statusText = document.getElementById('status-text')!;\r\nconst toggleInput = document.getElementById('toggle-input') as HTMLInputElement;\r\nconst activityEl = document.getElementById('activity')!;\r\nconst approvalsEl = document.getElementById('approvals')!;\r\n\r\nlet currentEnabled = true;\r\n\r\nfunction escapeHtml(text: string): string {\r\n const el = document.createElement('span');\r\n el.textContent = text;\r\n return el.innerHTML;\r\n}\r\n\r\nfunction renderApprovals(approvals: ApprovalInfo[]): void {\r\n if (approvals.length === 0) {\r\n approvalsEl.innerHTML = '';\r\n return;\r\n }\r\n\r\n const cards = approvals.map(a =>\r\n `<div class=\"approval-card\" data-id=\"${escapeHtml(a.approvalId)}\">\r\n <div class=\"approval-connector\">${escapeHtml(a.connectorKey)}</div>\r\n <div class=\"approval-detail\">Step ${a.stepIndex + 1} [${escapeHtml(a.stepType)}] <span class=\"approval-cap\">${escapeHtml(a.capability)}</span></div>\r\n <div class=\"approval-actions\">\r\n <button class=\"btn-approve\" data-approval-id=\"${escapeHtml(a.approvalId)}\" data-approved=\"true\">Approve</button>\r\n <button class=\"btn-reject\" data-approval-id=\"${escapeHtml(a.approvalId)}\" data-approved=\"false\">Reject</button>\r\n </div>\r\n </div>`\r\n ).join('');\r\n\r\n approvalsEl.innerHTML =\r\n `<div class=\"approval-section\">\r\n <div class=\"approval-header\">Pending approvals <span class=\"approval-count\">${approvals.length}</span></div>\r\n ${cards}\r\n </div>`;\r\n\r\n approvalsEl.querySelectorAll('[data-approval-id]').forEach(btn => {\r\n btn.addEventListener('click', () => {\r\n const approvalId = (btn as HTMLElement).dataset.approvalId!;\r\n const approved = (btn as HTMLElement).dataset.approved === 'true';\r\n (btn as HTMLButtonElement).disabled = true;\r\n chrome.runtime.sendMessage(\r\n { type: 'approvalDecision', approvalId, approved },\r\n () => { fetchStatus(); },\r\n );\r\n });\r\n });\r\n}\r\n\r\nfunction render(status: PopupStatusResponse): void {\r\n currentEnabled = status.enabled;\r\n toggleInput.checked = status.enabled;\r\n\r\n if (!status.enabled) {\r\n dot.className = 'dot disabled';\r\n statusText.textContent = 'Disabled';\r\n } else if (status.connected) {\r\n dot.className = 'dot connected';\r\n statusText.textContent = 'Connected';\r\n } else {\r\n dot.className = 'dot disconnected';\r\n statusText.textContent = 'Disconnected';\r\n }\r\n\r\n renderApprovals(status.pendingApprovals ?? []);\r\n\r\n if (status.recentActivity.length === 0) {\r\n activityEl.innerHTML = '<div class=\"empty\">No recent activity</div>';\r\n return;\r\n }\r\n\r\n const now = Date.now();\r\n activityEl.innerHTML = status.recentActivity\r\n .map(entry => {\r\n const icon = entry.ok\r\n ? '<span class=\"activity-icon ok\">\u2713</span>'\r\n : '<span class=\"activity-icon fail\">\u2717</span>';\r\n return `<div class=\"activity-item\">${icon}<span class=\"activity-name\">${escapeHtml(entry.connector)}</span><span class=\"activity-time\">${timeAgo(entry.timestamp, now)}</span></div>`;\r\n })\r\n .join('');\r\n}\r\n\r\nfunction fetchStatus(): void {\r\n chrome.runtime.sendMessage({ type: 'getStatus' }, (response: PopupStatusResponse) => {\r\n if (chrome.runtime.lastError) {\r\n statusText.textContent = 'Error';\r\n return;\r\n }\r\n render(response);\r\n });\r\n}\r\n\r\ntoggleInput.addEventListener('change', () => {\r\n const newEnabled = toggleInput.checked;\r\n toggleInput.disabled = true;\r\n chrome.runtime.sendMessage({ type: 'setEnabled', enabled: newEnabled }, (response: PopupStatusResponse) => {\r\n toggleInput.disabled = false;\r\n if (chrome.runtime.lastError) {\r\n toggleInput.checked = currentEnabled;\r\n return;\r\n }\r\n render(response);\r\n });\r\n});\r\n\r\n// Listen for push updates from the service worker (approval state changes)\r\nchrome.runtime.onMessage.addListener((msg) => {\r\n if (msg.type === 'approvalUpdate') {\r\n renderApprovals(msg.pendingApprovals ?? []);\r\n }\r\n});\r\n\r\nfetchStatus();\r\n"],
4
+ "sourcesContent": ["// src/popup/time-ago.ts\nexport function timeAgo(timestamp: number, now: number = Date.now()): string {\n const seconds = Math.floor((now - timestamp) / 1000);\n if (seconds < 60) return 'just now';\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return `${days}d ago`;\n}\n", "// src/popup/popup.ts\n/// <reference lib=\"dom\" />\nimport type { PopupStatusResponse, ApprovalInfo } from './popup-types.js';\nimport { timeAgo } from './time-ago.js';\n\nconst dot = document.getElementById('dot')!;\nconst statusText = document.getElementById('status-text')!;\nconst toggleInput = document.getElementById('toggle-input') as HTMLInputElement;\nconst activityEl = document.getElementById('activity')!;\nconst approvalsEl = document.getElementById('approvals')!;\n\nlet currentEnabled = true;\n\nfunction escapeHtml(text: string): string {\n const el = document.createElement('span');\n el.textContent = text;\n return el.innerHTML;\n}\n\nfunction renderApprovals(approvals: ApprovalInfo[]): void {\n if (approvals.length === 0) {\n approvalsEl.innerHTML = '';\n return;\n }\n\n const cards = approvals.map(a =>\n `<div class=\"approval-card\" data-id=\"${escapeHtml(a.approvalId)}\">\n <div class=\"approval-connector\">${escapeHtml(a.connectorKey)}</div>\n <div class=\"approval-detail\">Step ${a.stepIndex + 1} [${escapeHtml(a.stepType)}] <span class=\"approval-cap\">${escapeHtml(a.capability)}</span></div>\n <div class=\"approval-actions\">\n <button class=\"btn-approve\" data-approval-id=\"${escapeHtml(a.approvalId)}\" data-approved=\"true\">Approve</button>\n <button class=\"btn-reject\" data-approval-id=\"${escapeHtml(a.approvalId)}\" data-approved=\"false\">Reject</button>\n </div>\n </div>`\n ).join('');\n\n approvalsEl.innerHTML =\n `<div class=\"approval-section\">\n <div class=\"approval-header\">Pending approvals <span class=\"approval-count\">${approvals.length}</span></div>\n ${cards}\n </div>`;\n\n approvalsEl.querySelectorAll('[data-approval-id]').forEach(btn => {\n btn.addEventListener('click', () => {\n const approvalId = (btn as HTMLElement).dataset.approvalId!;\n const approved = (btn as HTMLElement).dataset.approved === 'true';\n (btn as HTMLButtonElement).disabled = true;\n chrome.runtime.sendMessage(\n { type: 'approvalDecision', approvalId, approved },\n () => { fetchStatus(); },\n );\n });\n });\n}\n\nfunction render(status: PopupStatusResponse): void {\n currentEnabled = status.enabled;\n toggleInput.checked = status.enabled;\n\n if (!status.enabled) {\n dot.className = 'dot disabled';\n statusText.textContent = 'Disabled';\n } else if (status.connected) {\n dot.className = 'dot connected';\n statusText.textContent = 'Connected';\n } else {\n dot.className = 'dot disconnected';\n statusText.textContent = 'Disconnected';\n }\n\n renderApprovals(status.pendingApprovals ?? []);\n\n if (status.recentActivity.length === 0) {\n activityEl.innerHTML = '<div class=\"empty\">No recent activity</div>';\n return;\n }\n\n const now = Date.now();\n activityEl.innerHTML = status.recentActivity\n .map(entry => {\n const icon = entry.ok\n ? '<span class=\"activity-icon ok\">\u2713</span>'\n : '<span class=\"activity-icon fail\">\u2717</span>';\n return `<div class=\"activity-item\">${icon}<span class=\"activity-name\">${escapeHtml(entry.connector)}</span><span class=\"activity-time\">${timeAgo(entry.timestamp, now)}</span></div>`;\n })\n .join('');\n}\n\nfunction fetchStatus(): void {\n chrome.runtime.sendMessage({ type: 'getStatus' }, (response: PopupStatusResponse) => {\n if (chrome.runtime.lastError) {\n statusText.textContent = 'Error';\n return;\n }\n render(response);\n });\n}\n\ntoggleInput.addEventListener('change', () => {\n const newEnabled = toggleInput.checked;\n toggleInput.disabled = true;\n chrome.runtime.sendMessage({ type: 'setEnabled', enabled: newEnabled }, (response: PopupStatusResponse) => {\n toggleInput.disabled = false;\n if (chrome.runtime.lastError) {\n toggleInput.checked = currentEnabled;\n return;\n }\n render(response);\n });\n});\n\n// Listen for push updates from the service worker (approval state changes)\nchrome.runtime.onMessage.addListener((msg) => {\n if (msg.type === 'approvalUpdate') {\n renderApprovals(msg.pendingApprovals ?? []);\n }\n});\n\nfetchStatus();\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -4378,6 +4378,7 @@ var connectorSchema = external_exports.object({
4378
4378
  version: external_exports.string(),
4379
4379
  description: external_exports.string().optional(),
4380
4380
  access: external_exports.enum(["read", "write"]).default("read"),
4381
+ cdp: external_exports.boolean().optional().default(false),
4381
4382
  vars: external_exports.record(external_exports.unknown()).optional(),
4382
4383
  domains: external_exports.array(external_exports.string()).min(1),
4383
4384
  capabilities: external_exports.array(capabilityEnum).min(1),
@@ -7441,7 +7442,7 @@ function createApprovalGate(requestId, connectorKey, timeoutMs) {
7441
7442
  };
7442
7443
  }
7443
7444
  client.onRequest(async (request) => {
7444
- const useCdp = request.connector.pipeline.some((s) => s.step === "intercept");
7445
+ const useCdp = request.connector.cdp === true || request.connector.pipeline.some((s) => s.step === "intercept");
7445
7446
  const adapter = new RealChromeAdapter({ useCdp });
7446
7447
  const connectorKey = `${request.connector.site}/${request.connector.name}`;
7447
7448
  const approvalGate = request.approvalConfig ? createApprovalGate(request.id, connectorKey, request.approvalConfig.approvalTimeoutMs) : void 0;