@commandgarden/cli 2.9.0 → 2.11.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 (63) hide show
  1. package/dist/main.js +0 -0
  2. package/node_modules/@commandgarden/app/dist/client/assets/{Slides-D3xcxd9t.js → Slides-BvMlkL-3.js} +5 -15
  3. package/node_modules/@commandgarden/app/dist/client/assets/index-BD8reQ8T.js +496 -0
  4. package/node_modules/@commandgarden/app/dist/client/assets/{index-DbqYLIqy.css → index-wgb9-PIF.css} +1 -1
  5. package/node_modules/@commandgarden/app/dist/client/index.html +19 -19
  6. package/node_modules/@commandgarden/app/dist/server/daemon-client.test.js +47 -0
  7. package/node_modules/@commandgarden/app/dist/server/journal/journal.service.d.ts +1 -0
  8. package/node_modules/@commandgarden/app/dist/server/journal/journal.service.js +25 -6
  9. package/node_modules/@commandgarden/app/dist/server/journal/journal.types.d.ts +26 -0
  10. package/node_modules/@commandgarden/app/dist/server/journal/sources/meetings.source.d.ts +10 -4
  11. package/node_modules/@commandgarden/app/dist/server/journal/sources/meetings.source.js +36 -29
  12. package/node_modules/@commandgarden/app/dist/server/journal/sources/timetracking.source.d.ts +10 -1
  13. package/node_modules/@commandgarden/app/dist/server/journal/sources/timetracking.source.js +62 -8
  14. package/node_modules/@commandgarden/app/dist/server/routes/journal.d.ts +12 -0
  15. package/node_modules/@commandgarden/app/dist/server/routes/journal.js +87 -5
  16. package/node_modules/@commandgarden/app/dist/server/routes/routes.test.js +137 -0
  17. package/node_modules/@commandgarden/app/dist/server/store.d.ts +27 -0
  18. package/node_modules/@commandgarden/app/dist/server/store.js +130 -39
  19. package/node_modules/@commandgarden/app/dist/server/store.test.js +59 -0
  20. package/node_modules/@commandgarden/app/package.json +42 -42
  21. package/node_modules/@commandgarden/chrome/dist/content-script.js.map +1 -1
  22. package/node_modules/@commandgarden/chrome/dist/fetch-interceptor.js +44 -0
  23. package/node_modules/@commandgarden/chrome/dist/manifest.json +26 -26
  24. package/node_modules/@commandgarden/chrome/dist/popup.html +218 -218
  25. package/node_modules/@commandgarden/chrome/dist/popup.js.map +1 -1
  26. package/node_modules/@commandgarden/chrome/dist/service-worker.js +14 -4
  27. package/node_modules/@commandgarden/chrome/dist/service-worker.js.map +2 -2
  28. package/node_modules/@commandgarden/chrome/package.json +26 -26
  29. package/node_modules/@commandgarden/daemon/connectors/ado-git-commits.eval.js +100 -100
  30. package/node_modules/@commandgarden/daemon/connectors/ado-git-commits.yaml +70 -70
  31. package/node_modules/@commandgarden/daemon/connectors/gcs-kb-content.yaml +61 -58
  32. package/node_modules/@commandgarden/daemon/connectors/gcs-kb-pages.yaml +54 -47
  33. package/node_modules/@commandgarden/daemon/connectors/jira-my-tickets.eval.js +115 -115
  34. package/node_modules/@commandgarden/daemon/connectors/jira-my-tickets.yaml +54 -54
  35. package/node_modules/@commandgarden/daemon/connectors/lib/msal-token.js +20 -20
  36. package/node_modules/@commandgarden/daemon/connectors/outlook-my-meetings.eval.js +204 -198
  37. package/node_modules/@commandgarden/daemon/connectors/outlook-my-meetings.yaml +42 -42
  38. package/node_modules/@commandgarden/daemon/connectors/saba-pending-training.eval.js +94 -94
  39. package/node_modules/@commandgarden/daemon/connectors/saba-pending-training.yaml +34 -34
  40. package/node_modules/@commandgarden/daemon/connectors/socket-security-news.yaml +63 -63
  41. package/node_modules/@commandgarden/daemon/connectors/teams-room-availability.eval.js +437 -437
  42. package/node_modules/@commandgarden/daemon/connectors/teams-room-availability.yaml +53 -53
  43. package/node_modules/@commandgarden/daemon/connectors/teams-rooms-availability.eval.js +547 -547
  44. package/node_modules/@commandgarden/daemon/connectors/teams-rooms-availability.yaml +48 -48
  45. package/node_modules/@commandgarden/daemon/connectors/timetracking-projects.eval.js +52 -52
  46. package/node_modules/@commandgarden/daemon/connectors/timetracking-projects.yaml +42 -42
  47. package/node_modules/@commandgarden/daemon/connectors/timetracking-report.eval.js +81 -81
  48. package/node_modules/@commandgarden/daemon/connectors/timetracking-report.yaml +52 -52
  49. package/node_modules/@commandgarden/daemon/connectors/tldrsec-newsletter.eval.js +27 -27
  50. package/node_modules/@commandgarden/daemon/connectors/tldrsec-newsletter.yaml +38 -38
  51. package/node_modules/@commandgarden/daemon/connectors/tokenmaster-clients-list.yaml +55 -55
  52. package/node_modules/@commandgarden/daemon/dist/audit-store.js +8 -8
  53. package/node_modules/@commandgarden/daemon/dist/cdp-client.d.ts +24 -0
  54. package/node_modules/@commandgarden/daemon/dist/cdp-client.d.ts.map +1 -0
  55. package/node_modules/@commandgarden/daemon/dist/cdp-client.js +150 -0
  56. package/node_modules/@commandgarden/daemon/dist/cdp-client.js.map +1 -0
  57. package/node_modules/@commandgarden/daemon/package.json +32 -32
  58. package/node_modules/@commandgarden/shared/dist/expression/filters.d.ts.map +1 -1
  59. package/node_modules/@commandgarden/shared/dist/expression/filters.js +2 -0
  60. package/node_modules/@commandgarden/shared/dist/expression/filters.js.map +1 -1
  61. package/node_modules/@commandgarden/shared/package.json +32 -32
  62. package/package.json +58 -58
  63. package/node_modules/@commandgarden/app/dist/client/assets/index-_jNYPoLF.js +0 -461
@@ -1,26 +1,26 @@
1
- {
2
- "manifest_version": 3,
3
- "name": "commandGarden",
4
- "version": "0.1.0",
5
- "description": "Enterprise browser automation — secure, auditable CLI commands for websites",
6
- "minimum_chrome_version": "116",
7
- "icons": {
8
- "16": "icons/icon-16.png",
9
- "32": "icons/icon-32.png",
10
- "48": "icons/icon-48.png",
11
- "128": "icons/icon-128.png"
12
- },
13
- "permissions": ["alarms", "cookies", "debugger", "idle", "tabs", "scripting", "webRequest", "storage"],
14
- "host_permissions": ["<all_urls>"],
15
- "background": {
16
- "service_worker": "service-worker.js",
17
- "type": "module"
18
- },
19
- "action": {
20
- "default_popup": "popup.html",
21
- "default_icon": {
22
- "16": "icons/icon-16.png",
23
- "32": "icons/icon-32.png"
24
- }
25
- }
26
- }
1
+ {
2
+ "manifest_version": 3,
3
+ "name": "commandGarden",
4
+ "version": "1.0.1",
5
+ "description": "Enterprise browser automation — secure, auditable CLI commands for websites",
6
+ "minimum_chrome_version": "116",
7
+ "icons": {
8
+ "16": "icons/icon-16.png",
9
+ "32": "icons/icon-32.png",
10
+ "48": "icons/icon-48.png",
11
+ "128": "icons/icon-128.png"
12
+ },
13
+ "permissions": ["alarms", "cookies", "debugger", "idle", "tabs", "scripting", "webRequest", "storage"],
14
+ "host_permissions": ["<all_urls>"],
15
+ "background": {
16
+ "service_worker": "service-worker.js",
17
+ "type": "module"
18
+ },
19
+ "action": {
20
+ "default_popup": "popup.html",
21
+ "default_icon": {
22
+ "16": "icons/icon-16.png",
23
+ "32": "icons/icon-32.png"
24
+ }
25
+ }
26
+ }
@@ -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
  }
@@ -6826,7 +6826,9 @@ var BUILT_IN_FILTERS = {
6826
6826
  if (map2 == null || typeof map2 !== "object")
6827
6827
  return void 0;
6828
6828
  return map2[String(value)];
6829
- }
6829
+ },
6830
+ slice: (value, start, end) => String(value).slice(Number(start), end != null ? Number(end) : void 0),
6831
+ replace: (value, search, replacement) => String(value).replace(String(search), String(replacement ?? ""))
6830
6832
  };
6831
6833
 
6832
6834
  // ../shared/dist/expression/evaluator.js
@@ -7366,7 +7368,15 @@ var RealChromeAdapter = class {
7366
7368
  for (const c of cookies) result[c.name] = c.value;
7367
7369
  return result;
7368
7370
  }
7369
- cleanup() {
7371
+ /**
7372
+ * Detach debugger/listeners and optionally close the managed tab.
7373
+ * `closeTab` defaults to false for callers that want to leave the tab
7374
+ * open (e.g. for debugging a specific run). service-worker.ts passes
7375
+ * `closeTab: true` unconditionally so tabs opened by connector runs
7376
+ * (Jira/Meetings/TimeTracking/Saba/etc.) always close after the run,
7377
+ * whether it succeeded or failed.
7378
+ */
7379
+ cleanup(closeTab = false) {
7370
7380
  if (this.cdpEventHandler) {
7371
7381
  chrome.debugger.onEvent.removeListener(this.cdpEventHandler);
7372
7382
  this.cdpEventHandler = null;
@@ -7382,7 +7392,7 @@ var RealChromeAdapter = class {
7382
7392
  this.debuggerAttached = false;
7383
7393
  }
7384
7394
  if (this.tabId) {
7385
- chrome.tabs.remove(this.tabId).catch(() => {
7395
+ if (closeTab) chrome.tabs.remove(this.tabId).catch(() => {
7386
7396
  });
7387
7397
  this.tabId = null;
7388
7398
  }
@@ -7515,7 +7525,7 @@ client.onRequest(async (request) => {
7515
7525
  error: err instanceof Error ? err.message : "Unknown error"
7516
7526
  });
7517
7527
  } finally {
7518
- adapter.cleanup();
7528
+ adapter.cleanup(true);
7519
7529
  recentActivity.unshift({
7520
7530
  connector: connectorKey,
7521
7531
  ok,