@commandgarden/cli 1.4.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/main.js +67 -8
  2. package/node_modules/@commandgarden/app/dist/client/assets/index-GpK1-Tyq.js +255 -0
  3. package/node_modules/@commandgarden/app/dist/client/assets/index-JB_Cdl_F.css +1 -0
  4. package/node_modules/@commandgarden/app/dist/client/index.html +2 -2
  5. package/node_modules/@commandgarden/app/dist/server/journal/journal.config.d.ts +25 -0
  6. package/node_modules/@commandgarden/app/dist/server/journal/journal.config.js +31 -0
  7. package/node_modules/@commandgarden/app/dist/server/journal/journal.service.d.ts +37 -0
  8. package/node_modules/@commandgarden/app/dist/server/journal/journal.service.js +142 -0
  9. package/node_modules/@commandgarden/app/dist/server/journal/journal.types.d.ts +91 -0
  10. package/node_modules/@commandgarden/app/dist/server/journal/journal.types.js +4 -0
  11. package/node_modules/@commandgarden/app/dist/server/journal/sources/git.source.d.ts +21 -0
  12. package/node_modules/@commandgarden/app/dist/server/journal/sources/git.source.js +72 -0
  13. package/node_modules/@commandgarden/app/dist/server/journal/sources/jira.source.d.ts +15 -0
  14. package/node_modules/@commandgarden/app/dist/server/journal/sources/jira.source.js +42 -0
  15. package/node_modules/@commandgarden/app/dist/server/journal/sources/meetings.source.d.ts +21 -0
  16. package/node_modules/@commandgarden/app/dist/server/journal/sources/meetings.source.js +25 -0
  17. package/node_modules/@commandgarden/app/dist/server/journal/sources/timetracking.source.d.ts +17 -0
  18. package/node_modules/@commandgarden/app/dist/server/journal/sources/timetracking.source.js +83 -0
  19. package/node_modules/@commandgarden/app/dist/server/routes/connectors.js +2 -0
  20. package/node_modules/@commandgarden/app/dist/server/routes/index.js +6 -0
  21. package/node_modules/@commandgarden/app/dist/server/routes/journal.d.ts +9 -0
  22. package/node_modules/@commandgarden/app/dist/server/routes/journal.js +56 -0
  23. package/node_modules/@commandgarden/app/dist/server/routes/security-news-cache.d.ts +3 -0
  24. package/node_modules/@commandgarden/app/dist/server/routes/security-news-cache.js +17 -0
  25. package/node_modules/@commandgarden/app/dist/server/routes/skills.d.ts +2 -0
  26. package/node_modules/@commandgarden/app/dist/server/routes/skills.js +65 -0
  27. package/node_modules/@commandgarden/app/dist/server/store.d.ts +5 -0
  28. package/node_modules/@commandgarden/app/dist/server/store.js +19 -0
  29. package/node_modules/@commandgarden/chrome/dist/content-script.js +84 -2
  30. package/node_modules/@commandgarden/chrome/dist/content-script.js.map +2 -2
  31. package/node_modules/@commandgarden/chrome/dist/popup.html +74 -53
  32. package/node_modules/@commandgarden/chrome/dist/service-worker.js +73 -8
  33. package/node_modules/@commandgarden/chrome/dist/service-worker.js.map +3 -3
  34. package/node_modules/@commandgarden/daemon/connectors/ado-git-commits.eval.js +143 -0
  35. package/node_modules/@commandgarden/daemon/connectors/ado-git-commits.yaml +70 -0
  36. package/node_modules/@commandgarden/daemon/connectors/gcs-kb-content.yaml +58 -0
  37. package/node_modules/@commandgarden/daemon/connectors/gcs-kb-pages.yaml +47 -0
  38. package/node_modules/@commandgarden/daemon/connectors/jira-my-tickets.eval.js +115 -0
  39. package/node_modules/@commandgarden/daemon/connectors/jira-my-tickets.yaml +54 -0
  40. package/node_modules/@commandgarden/daemon/connectors/outlook-my-meetings.eval.js +186 -0
  41. package/node_modules/@commandgarden/daemon/connectors/outlook-my-meetings.yaml +41 -0
  42. package/node_modules/@commandgarden/daemon/connectors/socket-security-news.yaml +63 -0
  43. package/node_modules/@commandgarden/daemon/connectors/tldrsec-newsletter.eval.js +27 -0
  44. package/node_modules/@commandgarden/daemon/connectors/tldrsec-newsletter.yaml +38 -0
  45. package/node_modules/@commandgarden/daemon/connectors/tokenmaster-client-trustedby.yaml +62 -0
  46. package/node_modules/@commandgarden/daemon/connectors/tokenmaster-clients-list.yaml +55 -0
  47. package/node_modules/@commandgarden/daemon/connectors/wiz-blog-security.eval.js +29 -0
  48. package/node_modules/@commandgarden/daemon/connectors/wiz-blog-security.yaml +44 -0
  49. package/node_modules/@commandgarden/daemon/dist/daemon-runner.d.ts +12 -0
  50. package/node_modules/@commandgarden/daemon/dist/daemon-runner.d.ts.map +1 -0
  51. package/node_modules/@commandgarden/daemon/dist/daemon-runner.js +65 -0
  52. package/node_modules/@commandgarden/daemon/dist/daemon-runner.js.map +1 -0
  53. package/node_modules/@commandgarden/daemon/dist/server.d.ts.map +1 -1
  54. package/node_modules/@commandgarden/daemon/dist/server.js +87 -13
  55. package/node_modules/@commandgarden/daemon/dist/server.js.map +1 -1
  56. package/node_modules/@commandgarden/daemon/dist/transforms.d.ts +3 -0
  57. package/node_modules/@commandgarden/daemon/dist/transforms.d.ts.map +1 -0
  58. package/node_modules/@commandgarden/daemon/dist/transforms.js +36 -0
  59. package/node_modules/@commandgarden/daemon/dist/transforms.js.map +1 -0
  60. package/node_modules/@commandgarden/daemon/package.json +4 -2
  61. package/node_modules/@commandgarden/shared/dist/connector.d.ts +175 -0
  62. package/node_modules/@commandgarden/shared/dist/connector.d.ts.map +1 -1
  63. package/node_modules/@commandgarden/shared/dist/connector.js +2 -0
  64. package/node_modules/@commandgarden/shared/dist/connector.js.map +1 -1
  65. package/node_modules/@commandgarden/shared/dist/expression/evaluator.d.ts +2 -0
  66. package/node_modules/@commandgarden/shared/dist/expression/evaluator.d.ts.map +1 -1
  67. package/node_modules/@commandgarden/shared/dist/expression/evaluator.js.map +1 -1
  68. package/node_modules/@commandgarden/shared/dist/expression/filters.d.ts.map +1 -1
  69. package/node_modules/@commandgarden/shared/dist/expression/filters.js +5 -0
  70. package/node_modules/@commandgarden/shared/dist/expression/filters.js.map +1 -1
  71. package/node_modules/@commandgarden/shared/dist/fan-out.d.ts +28 -0
  72. package/node_modules/@commandgarden/shared/dist/fan-out.d.ts.map +1 -0
  73. package/node_modules/@commandgarden/shared/dist/fan-out.js +55 -0
  74. package/node_modules/@commandgarden/shared/dist/fan-out.js.map +1 -0
  75. package/node_modules/@commandgarden/shared/dist/index.d.ts +2 -1
  76. package/node_modules/@commandgarden/shared/dist/index.d.ts.map +1 -1
  77. package/node_modules/@commandgarden/shared/dist/index.js +3 -1
  78. package/node_modules/@commandgarden/shared/dist/index.js.map +1 -1
  79. package/node_modules/@commandgarden/shared/dist/loader.d.ts.map +1 -1
  80. package/node_modules/@commandgarden/shared/dist/loader.js +17 -0
  81. package/node_modules/@commandgarden/shared/dist/loader.js.map +1 -1
  82. package/node_modules/@commandgarden/shared/dist/pipeline.d.ts +223 -1
  83. package/node_modules/@commandgarden/shared/dist/pipeline.d.ts.map +1 -1
  84. package/node_modules/@commandgarden/shared/dist/pipeline.js +58 -2
  85. package/node_modules/@commandgarden/shared/dist/pipeline.js.map +1 -1
  86. package/node_modules/@commandgarden/shared/dist/protocol.d.ts +1 -0
  87. package/node_modules/@commandgarden/shared/dist/protocol.d.ts.map +1 -1
  88. package/node_modules/@commandgarden/shared/dist/protocol.js.map +1 -1
  89. package/package.json +1 -1
  90. package/node_modules/@commandgarden/app/dist/client/assets/index-B-_w54e9.css +0 -1
  91. package/node_modules/@commandgarden/app/dist/client/assets/index-Bb1BOK1E.js +0 -252
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/messages.ts", "../src/content/dom-executor.ts", "../src/content/content-script.ts"],
4
- "sourcesContent": ["// src/messages.ts\nconst randomUUID = () => crypto.randomUUID();\n\nexport type DomAction = 'wait' | 'extract' | 'click' | 'type' | 'fetch';\n\nexport interface DomRequest {\n id: string;\n action: DomAction;\n params: Record<string, unknown>;\n}\n\nexport interface DomResponse {\n requestId: string;\n ok: boolean;\n data?: unknown;\n error?: string;\n}\n\nexport function createDomRequest(action: DomAction, params: Record<string, unknown>): DomRequest {\n return { id: randomUUID(), action, params };\n}\n\nexport function createDomResponse(\n requestId: string, ok: boolean, data?: unknown, error?: string,\n): DomResponse {\n return { requestId, ok, data, error };\n}\n\nexport function isDomRequest(value: unknown): value is DomRequest {\n if (value == null || typeof value !== 'object') return false;\n const obj = value as Record<string, unknown>;\n return typeof obj.id === 'string' && typeof obj.action === 'string' && typeof obj.params === 'object';\n}\n\nexport function isDomResponse(value: unknown): value is DomResponse {\n if (value == null || typeof value !== 'object') return false;\n const obj = value as Record<string, unknown>;\n return typeof obj.requestId === 'string' && typeof obj.ok === 'boolean';\n}\n", "// src/content/dom-executor.ts\n\nexport function waitForSelector(selector: string, timeout: number): Promise<void> {\n return new Promise((resolve, reject) => {\n if (document.querySelector(selector)) { resolve(); return; }\n const interval = 100;\n let elapsed = 0;\n const timer = setInterval(() => {\n if (document.querySelector(selector)) { clearInterval(timer); resolve(); return; }\n elapsed += interval;\n if (elapsed >= timeout) {\n clearInterval(timer);\n reject(new Error(`Selector \"${selector}\" timed out after ${timeout}ms`));\n }\n }, interval);\n });\n}\n\nexport function extractData(\n rowSelector: string,\n fields: Record<string, string>,\n): Record<string, string>[] {\n const rows = document.querySelectorAll(rowSelector);\n return Array.from(rows).map(row => {\n const record: Record<string, string> = {};\n for (const [name, selector] of Object.entries(fields)) {\n record[name] = row.querySelector(selector)?.textContent?.trim() ?? '';\n }\n return record;\n });\n}\n\nexport async function clickElement(selector: string): Promise<void> {\n const el = document.querySelector(selector);\n if (!el) throw new Error(`Element \"${selector}\" not found`);\n (el as HTMLElement).click();\n}\n\nexport async function typeIntoElement(selector: string, value: string): Promise<void> {\n const el = document.querySelector(selector) as HTMLInputElement | null;\n if (!el) throw new Error(`Element \"${selector}\" not found`);\n el.focus();\n el.value = value;\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n}\n\nexport async function fetchFromPage(\n url: string, method = 'GET', headers?: Record<string, string>, body?: string,\n): Promise<unknown> {\n const resp = await fetch(url, {\n method, headers, body, credentials: 'include',\n });\n const contentType = resp.headers.get('content-type') ?? '';\n if (contentType.includes('application/json')) return resp.json();\n return resp.text();\n}\n", "// src/content/content-script.ts\nimport { isDomRequest, createDomResponse, type DomRequest } from '../messages.js';\nimport { waitForSelector, extractData, clickElement, typeIntoElement, fetchFromPage } from './dom-executor.js';\n\nchrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {\n if (!isDomRequest(message)) return false;\n const req = message as DomRequest;\n handleRequest(req).then(\n (data) => sendResponse(createDomResponse(req.id, true, data)),\n (err) => sendResponse(createDomResponse(req.id, false, undefined, err.message)),\n );\n return true; // Keep channel open for async response\n});\n\nasync function handleRequest(req: DomRequest): Promise<unknown> {\n const p = req.params;\n switch (req.action) {\n case 'wait':\n await waitForSelector(p.selector as string, (p.timeout as number) ?? 10000);\n return undefined;\n case 'extract':\n return extractData(p.selector as string, p.fields as Record<string, string>);\n case 'click':\n await clickElement(p.selector as string);\n return undefined;\n case 'type':\n await typeIntoElement(p.selector as string, p.value as string);\n return undefined;\n case 'fetch':\n return fetchFromPage(\n p.url as string, p.method as string,\n p.headers as Record<string, string>, p.body as string,\n );\n default:\n throw new Error(`Unknown action: ${req.action}`);\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// src/messages.ts\nconst randomUUID = () => crypto.randomUUID();\n\nexport type DomAction = 'wait' | 'extract' | 'extract_tree' | 'extract_html' | 'click' | 'click_all' | 'type' | 'fetch';\n\nexport interface DomRequest {\n id: string;\n action: DomAction;\n params: Record<string, unknown>;\n}\n\nexport interface DomResponse {\n requestId: string;\n ok: boolean;\n data?: unknown;\n error?: string;\n}\n\nexport function createDomRequest(action: DomAction, params: Record<string, unknown>): DomRequest {\n return { id: randomUUID(), action, params };\n}\n\nexport function createDomResponse(\n requestId: string, ok: boolean, data?: unknown, error?: string,\n): DomResponse {\n return { requestId, ok, data, error };\n}\n\nexport function isDomRequest(value: unknown): value is DomRequest {\n if (value == null || typeof value !== 'object') return false;\n const obj = value as Record<string, unknown>;\n return typeof obj.id === 'string' && typeof obj.action === 'string' && typeof obj.params === 'object';\n}\n\nexport function isDomResponse(value: unknown): value is DomResponse {\n if (value == null || typeof value !== 'object') return false;\n const obj = value as Record<string, unknown>;\n return typeof obj.requestId === 'string' && typeof obj.ok === 'boolean';\n}\n", "// src/content/dom-executor.ts\n\nexport function waitForSelector(selector: string, timeout: number): Promise<void> {\n return new Promise((resolve, reject) => {\n if (document.querySelector(selector)) { resolve(); return; }\n const interval = 100;\n let elapsed = 0;\n const timer = setInterval(() => {\n if (document.querySelector(selector)) { clearInterval(timer); resolve(); return; }\n elapsed += interval;\n if (elapsed >= timeout) {\n clearInterval(timer);\n reject(new Error(`Selector \"${selector}\" timed out after ${timeout}ms`));\n }\n }, interval);\n });\n}\n\nexport function extractData(\n rowSelector: string,\n fields: Record<string, string>,\n): Record<string, string>[] {\n const rows = document.querySelectorAll(rowSelector);\n return Array.from(rows).map(row => {\n const record: Record<string, string> = {};\n for (const [name, selector] of Object.entries(fields)) {\n record[name] = row.querySelector(selector)?.textContent?.trim() ?? '';\n }\n return record;\n });\n}\n\nexport function extractHtml(selector: string): string {\n const el = document.querySelector(selector);\n if (!el) throw new Error(`Element \"${selector}\" not found`);\n return el.innerHTML;\n}\n\nexport function extractTree(\n rootSelector: string,\n group: { match: string; title: string; children: string },\n leaf: { match: string; fields: Record<string, string> },\n pathSeparator: string,\n): Record<string, unknown>[] {\n const root = document.querySelector(rootSelector);\n if (!root) throw new Error(`Root \"${rootSelector}\" not found`);\n\n function extractField(el: Element, spec: string): string {\n if (spec === 'textContent') return el.textContent?.trim().replace(/\\s+/g, ' ') ?? '';\n if (spec === 'href') return el.getAttribute('href') ?? '';\n if (spec.startsWith('attr:')) return el.getAttribute(spec.slice(5)) ?? '';\n return el.textContent?.trim() ?? '';\n }\n\n function walk(container: Element, ancestors: string[], depth: number): Record<string, unknown>[] {\n const results: Record<string, unknown>[] = [];\n for (const child of Array.from(container.children)) {\n if (child.matches(leaf.match)) {\n const row: Record<string, unknown> = {};\n for (const [name, spec] of Object.entries(leaf.fields)) {\n row[name] = extractField(child, spec);\n }\n const title = (row.title as string) || child.textContent?.trim() || '';\n const section = ancestors.length > 0 ? ancestors[0] : title;\n const pathParts = [...ancestors, title];\n row.section = section;\n row.path = pathParts.join(pathSeparator);\n row.depth = depth;\n results.push(row);\n } else if (child.matches(group.match)) {\n const titleEl = child.querySelector(group.title);\n const groupTitle = titleEl?.textContent?.trim().replace(/\\s+/g, ' ') ?? '';\n const childContainer = child.querySelector(group.children);\n if (childContainer) {\n results.push(...walk(childContainer, [...ancestors, groupTitle], depth + 1));\n }\n } else {\n results.push(...walk(child, ancestors, depth));\n }\n }\n return results;\n }\n\n return walk(root, [], 0);\n}\n\nexport async function clickAll(\n selector: string, pause: number, maxRounds: number, settle: number,\n): Promise<void> {\n for (let round = 0; round < maxRounds; round++) {\n const elements = document.querySelectorAll(selector);\n if (elements.length === 0) break;\n for (const el of Array.from(elements)) {\n (el as HTMLElement).click();\n if (pause > 0) await new Promise(r => setTimeout(r, pause));\n }\n }\n if (settle > 0) await new Promise(r => setTimeout(r, settle));\n}\n\nexport async function clickElement(selector: string): Promise<void> {\n const el = document.querySelector(selector);\n if (!el) throw new Error(`Element \"${selector}\" not found`);\n (el as HTMLElement).click();\n}\n\nexport async function typeIntoElement(selector: string, value: string): Promise<void> {\n const el = document.querySelector(selector) as HTMLInputElement | null;\n if (!el) throw new Error(`Element \"${selector}\" not found`);\n el.focus();\n el.value = value;\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n}\n\nexport async function fetchFromPage(\n url: string, method = 'GET', headers?: Record<string, string>, body?: string,\n): Promise<unknown> {\n const resp = await fetch(url, {\n method, headers, body, credentials: 'include',\n });\n const contentType = resp.headers.get('content-type') ?? '';\n if (contentType.includes('application/json')) return resp.json();\n return resp.text();\n}\n", "// src/content/content-script.ts\nimport { isDomRequest, createDomResponse, type DomRequest } from '../messages.js';\nimport { waitForSelector, extractData, extractHtml, extractTree, clickElement, clickAll, typeIntoElement, fetchFromPage } from './dom-executor.js';\n\nchrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {\n if (!isDomRequest(message)) return false;\n const req = message as DomRequest;\n handleRequest(req).then(\n (data) => sendResponse(createDomResponse(req.id, true, data)),\n (err) => sendResponse(createDomResponse(req.id, false, undefined, err.message)),\n );\n return true; // Keep channel open for async response\n});\n\nasync function handleRequest(req: DomRequest): Promise<unknown> {\n const p = req.params;\n switch (req.action) {\n case 'wait':\n await waitForSelector(p.selector as string, (p.timeout as number) ?? 10000);\n return undefined;\n case 'extract':\n return extractData(p.selector as string, p.fields as Record<string, string>);\n case 'extract_html':\n return extractHtml(p.selector as string);\n case 'extract_tree':\n return extractTree(\n p.root as string,\n p.group as { match: string; title: string; children: string },\n p.leaf as { match: string; fields: Record<string, string> },\n (p.pathSeparator as string) ?? ' / ',\n );\n case 'click':\n await clickElement(p.selector as string);\n return undefined;\n case 'click_all':\n await clickAll(\n p.selector as string,\n (p.pause as number) ?? 200,\n (p.maxRounds as number) ?? 10,\n (p.settle as number) ?? 300,\n );\n return undefined;\n case 'type':\n await typeIntoElement(p.selector as string, p.value as string);\n return undefined;\n case 'fetch': {\n const result = await fetchFromPage(\n p.url as string, p.method as string,\n p.headers as Record<string, string>, p.body as string,\n );\n if (p.dataPath && result != null && typeof result === 'object' && !Array.isArray(result)) {\n let nested: unknown = result;\n for (const key of (p.dataPath as string).split('.')) {\n if (nested == null || typeof nested !== 'object') return [];\n nested = (nested as Record<string, unknown>)[key];\n }\n return Array.isArray(nested) ? nested : [];\n }\n return result;\n }\n default:\n throw new Error(`Unknown action: ${req.action}`);\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -2,39 +2,57 @@
2
2
  <html lang="en">
3
3
  <head>
4
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" />
5
8
  <style>
6
- * { margin: 0; padding: 0; box-sizing: border-box; }
9
+ * { margin: 0; padding: 0; box-sizing: border-box; border-radius: 0 !important; }
7
10
  body {
8
11
  width: 320px;
9
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
12
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
10
13
  font-size: 13px;
11
- background: #1e1e1e;
12
- color: #ccc;
14
+ background: #0a0a0a;
15
+ color: #e5e5e5;
13
16
  }
14
17
  .header {
15
18
  padding: 12px 16px;
16
- font-family: 'SF Mono', SFMono-Regular, ui-monospace, Menlo, Consolas, monospace;
17
- font-size: 13px;
18
- font-weight: 600;
19
- color: #e0e0e0;
20
- border-bottom: 1px solid #333;
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;
21
40
  }
22
41
  .status-row {
23
42
  display: flex;
24
43
  align-items: center;
25
44
  gap: 8px;
26
45
  padding: 10px 16px;
27
- border-bottom: 1px solid #333;
46
+ border-bottom: 1px solid #262626;
28
47
  }
29
48
  .dot {
30
49
  width: 8px;
31
50
  height: 8px;
32
- border-radius: 50%;
33
51
  flex-shrink: 0;
34
52
  }
35
- .dot.connected { background: #4caf50; }
36
- .dot.disconnected { background: #f44336; }
37
- .dot.disabled { background: #666; }
53
+ .dot.connected { background: #4ade80; }
54
+ .dot.disconnected { background: #f87171; }
55
+ .dot.disabled { background: #737373; }
38
56
  .status-text { flex: 1; }
39
57
  .toggle {
40
58
  position: relative;
@@ -51,12 +69,11 @@
51
69
  .toggle-track {
52
70
  position: absolute;
53
71
  inset: 0;
54
- background: #555;
55
- border-radius: 10px;
56
- transition: background 0.2s;
72
+ background: #262626;
73
+ transition: background 0.15s;
57
74
  }
58
75
  .toggle input:checked + .toggle-track {
59
- background: #4caf50;
76
+ background: #4ade80;
60
77
  }
61
78
  .toggle-knob {
62
79
  position: absolute;
@@ -64,9 +81,8 @@
64
81
  left: 2px;
65
82
  width: 16px;
66
83
  height: 16px;
67
- background: #fff;
68
- border-radius: 50%;
69
- transition: transform 0.2s;
84
+ background: #e5e5e5;
85
+ transition: transform 0.15s;
70
86
  pointer-events: none;
71
87
  }
72
88
  .toggle input:checked ~ .toggle-knob {
@@ -81,33 +97,33 @@
81
97
  align-items: center;
82
98
  gap: 8px;
83
99
  padding: 8px 16px;
84
- border-bottom: 1px solid #2a2a2a;
100
+ border-bottom: 1px solid #171717;
85
101
  transition: background 0.1s;
86
102
  }
87
103
  .activity-item:hover {
88
- background: #252525;
104
+ background: #171717;
89
105
  }
90
106
  .activity-icon { font-size: 12px; flex-shrink: 0; }
91
- .activity-icon.ok { color: #4caf50; }
92
- .activity-icon.fail { color: #f44336; }
93
- .activity-name { flex: 1; font-family: monospace; font-size: 12px; }
94
- .activity-time { color: #888; font-size: 11px; 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; }
95
111
  .empty {
96
112
  padding: 16px;
97
113
  text-align: center;
98
- color: #666;
114
+ color: #737373;
99
115
  font-style: italic;
100
116
  }
101
117
  /* Approval section */
102
118
  .approval-section {
103
- border-bottom: 1px solid #333;
104
- background: #252525;
119
+ border-bottom: 1px solid #262626;
120
+ background: #171717;
105
121
  }
106
122
  .approval-header {
107
123
  padding: 10px 16px 4px;
108
124
  font-size: 12px;
109
125
  font-weight: 600;
110
- color: #ccc;
126
+ color: #e5e5e5;
111
127
  }
112
128
  .approval-count {
113
129
  display: inline-block;
@@ -116,9 +132,8 @@
116
132
  text-align: center;
117
133
  padding: 0 5px;
118
134
  line-height: 16px;
119
- border-radius: 8px;
120
- background: rgba(245, 158, 11, 0.18);
121
- color: #F59E0B;
135
+ background: rgba(251, 191, 36, 0.15);
136
+ color: #fbbf24;
122
137
  font-weight: 700;
123
138
  margin-left: 6px;
124
139
  vertical-align: 1px;
@@ -130,25 +145,24 @@
130
145
  gap: 6px;
131
146
  }
132
147
  .approval-card + .approval-card {
133
- border-top: 1px solid #2a2a2a;
148
+ border-top: 1px solid #262626;
134
149
  }
135
150
  .approval-connector {
136
- font-family: monospace;
151
+ font-family: 'JetBrains Mono', ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
137
152
  font-size: 12px;
138
- color: #e0e0e0;
153
+ color: #e5e5e5;
139
154
  }
140
155
  .approval-detail {
141
156
  font-size: 11px;
142
- color: #999;
157
+ color: #a3a3a3;
143
158
  }
144
159
  .approval-cap {
145
160
  display: inline-block;
146
161
  font-size: 10px;
147
162
  padding: 1px 6px;
148
- border-radius: 3px;
149
- background: rgba(245, 158, 11, 0.15);
150
- color: #F59E0B;
151
- font-family: monospace;
163
+ background: rgba(251, 191, 36, 0.12);
164
+ color: #fbbf24;
165
+ font-family: 'JetBrains Mono', ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;
152
166
  }
153
167
  .approval-actions {
154
168
  display: flex;
@@ -158,29 +172,36 @@
158
172
  .btn-approve, .btn-reject {
159
173
  font-size: 11px;
160
174
  padding: 4px 14px;
161
- border-radius: 6px;
162
175
  border: none;
163
176
  cursor: pointer;
164
177
  font-weight: 600;
165
178
  transition: background 0.15s, color 0.15s;
166
179
  }
167
180
  .btn-approve {
168
- background: #4caf50;
169
- color: #fff;
181
+ background: #4ade80;
182
+ color: #0a0a0a;
170
183
  }
171
- .btn-approve:hover { background: #43a047; }
172
- .btn-approve:active { background: #388e3c; }
184
+ .btn-approve:hover { background: #22c55e; }
185
+ .btn-approve:active { background: #16a34a; }
173
186
  .btn-reject {
174
187
  background: transparent;
175
- color: #999;
176
- border: 1px solid #555;
177
- }
178
- .btn-reject:hover { background: #333; color: #ccc; }
179
- .btn-reject:active { background: #2a2a2a; }
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); }
180
198
  </style>
181
199
  </head>
182
200
  <body>
183
- <div class="header">commandGarden</div>
201
+ <div class="header">
202
+ <div class="header-title"><span>command</span>Garden</div>
203
+ <div class="header-sub">browser automation</div>
204
+ </div>
184
205
  <div class="status-row">
185
206
  <div id="dot" class="dot disabled"></div>
186
207
  <span id="status-text" class="status-text">Checking…</span>
@@ -4227,7 +4227,10 @@ var STEP_CAPABILITY_MAP = {
4227
4227
  navigate: "navigate",
4228
4228
  wait: "navigate",
4229
4229
  extract: "dom_read",
4230
+ extract_tree: "dom_read",
4231
+ extract_html: "dom_read",
4230
4232
  click: "dom_write",
4233
+ click_all: "dom_write",
4231
4234
  type: "dom_write",
4232
4235
  intercept: "intercept_response",
4233
4236
  cookie: "cookie_read",
@@ -4235,6 +4238,7 @@ var STEP_CAPABILITY_MAP = {
4235
4238
  map: null,
4236
4239
  filter: null,
4237
4240
  set: null,
4241
+ transform: null,
4238
4242
  js_evaluate: "js_evaluate"
4239
4243
  };
4240
4244
  var navigateStepSchema = external_exports.object({
@@ -4277,7 +4281,8 @@ var fetchStepSchema = external_exports.object({
4277
4281
  method: external_exports.string().optional(),
4278
4282
  headers: external_exports.record(external_exports.string(), external_exports.string()).optional(),
4279
4283
  body: external_exports.string().optional(),
4280
- as: external_exports.string().optional()
4284
+ as: external_exports.string().optional(),
4285
+ dataPath: external_exports.string().optional()
4281
4286
  });
4282
4287
  var mapStepSchema = external_exports.object({
4283
4288
  step: external_exports.literal("map"),
@@ -4294,6 +4299,39 @@ var setStepSchema = external_exports.object({
4294
4299
  name: external_exports.string(),
4295
4300
  value: external_exports.string()
4296
4301
  });
4302
+ var extractHtmlStepSchema = external_exports.object({
4303
+ step: external_exports.literal("extract_html"),
4304
+ selector: external_exports.string(),
4305
+ as: external_exports.string()
4306
+ });
4307
+ var transformStepSchema = external_exports.object({
4308
+ step: external_exports.literal("transform"),
4309
+ type: external_exports.string(),
4310
+ input: external_exports.string(),
4311
+ as: external_exports.string(),
4312
+ options: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
4313
+ });
4314
+ var extractTreeStepSchema = external_exports.object({
4315
+ step: external_exports.literal("extract_tree"),
4316
+ root: external_exports.string(),
4317
+ group: external_exports.object({
4318
+ match: external_exports.string(),
4319
+ title: external_exports.string(),
4320
+ children: external_exports.string()
4321
+ }),
4322
+ leaf: external_exports.object({
4323
+ match: external_exports.string(),
4324
+ fields: external_exports.record(external_exports.string(), external_exports.string())
4325
+ }),
4326
+ pathSeparator: external_exports.string().optional()
4327
+ });
4328
+ var clickAllStepSchema = external_exports.object({
4329
+ step: external_exports.literal("click_all"),
4330
+ selector: external_exports.string(),
4331
+ pause: external_exports.number().positive().optional(),
4332
+ maxRounds: external_exports.number().positive().optional(),
4333
+ settle: external_exports.number().nonnegative().optional()
4334
+ });
4297
4335
  var jsEvaluateStepSchema = external_exports.object({
4298
4336
  step: external_exports.literal("js_evaluate"),
4299
4337
  code: external_exports.string().optional(),
@@ -4312,6 +4350,10 @@ var pipelineStepSchema = external_exports.discriminatedUnion("step", [
4312
4350
  mapStepSchema,
4313
4351
  filterStepSchema,
4314
4352
  setStepSchema,
4353
+ extractHtmlStepSchema,
4354
+ transformStepSchema,
4355
+ extractTreeStepSchema,
4356
+ clickAllStepSchema,
4315
4357
  jsEvaluateStepSchema
4316
4358
  ]);
4317
4359
 
@@ -4323,7 +4365,8 @@ var connectorArgSchema = external_exports.object({
4323
4365
  required: external_exports.boolean().default(false),
4324
4366
  default: external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()]).optional(),
4325
4367
  help: external_exports.string().optional(),
4326
- pattern: external_exports.string().optional()
4368
+ pattern: external_exports.string().optional(),
4369
+ enum: external_exports.array(external_exports.string()).optional()
4327
4370
  });
4328
4371
  var connectorColumnSchema = external_exports.object({
4329
4372
  name: external_exports.string(),
@@ -4335,6 +4378,7 @@ var connectorSchema = external_exports.object({
4335
4378
  version: external_exports.string(),
4336
4379
  description: external_exports.string().optional(),
4337
4380
  access: external_exports.enum(["read", "write"]).default("read"),
4381
+ vars: external_exports.record(external_exports.unknown()).optional(),
4338
4382
  domains: external_exports.array(external_exports.string()).min(1),
4339
4383
  capabilities: external_exports.array(capabilityEnum).min(1),
4340
4384
  args: external_exports.array(connectorArgSchema).optional().default([]),
@@ -6776,7 +6820,12 @@ var BUILT_IN_FILTERS = {
6776
6820
  number: (value) => Number(value),
6777
6821
  trim: (value) => String(value).trim(),
6778
6822
  upper: (value) => String(value).toUpperCase(),
6779
- lower: (value) => String(value).toLowerCase()
6823
+ lower: (value) => String(value).toLowerCase(),
6824
+ lookup: (value, map2) => {
6825
+ if (map2 == null || typeof map2 !== "object")
6826
+ return void 0;
6827
+ return map2[String(value)];
6828
+ }
6780
6829
  };
6781
6830
 
6782
6831
  // ../shared/dist/expression/evaluator.js
@@ -6832,8 +6881,9 @@ var PipelineContext = class {
6832
6881
  cookies = {};
6833
6882
  data = [];
6834
6883
  args;
6835
- constructor(args) {
6884
+ constructor(args, initialVars) {
6836
6885
  this.args = args;
6886
+ if (initialVars) Object.assign(this.vars, initialVars);
6837
6887
  }
6838
6888
  setVar(name, value) {
6839
6889
  this.vars[name] = value;
@@ -6841,6 +6891,9 @@ var PipelineContext = class {
6841
6891
  getVar(name) {
6842
6892
  return this.vars[name];
6843
6893
  }
6894
+ getVars() {
6895
+ return { ...this.vars };
6896
+ }
6844
6897
  setCookies(cookies) {
6845
6898
  Object.assign(this.cookies, cookies);
6846
6899
  }
@@ -6861,7 +6914,8 @@ var PipelineContext = class {
6861
6914
  const rowCtx = {
6862
6915
  args: this.args,
6863
6916
  vars: { ...this.vars, row },
6864
- cookies: this.cookies
6917
+ cookies: this.cookies,
6918
+ row
6865
6919
  };
6866
6920
  mapped[key] = interpolate(expr, rowCtx);
6867
6921
  }
@@ -6917,7 +6971,7 @@ var PipelineRunner = class {
6917
6971
  }
6918
6972
  }
6919
6973
  async run(connector, args) {
6920
- const ctx = new PipelineContext(args);
6974
+ const ctx = new PipelineContext(args, connector.vars);
6921
6975
  let tabId = -1;
6922
6976
  const stepSummaries = [];
6923
6977
  try {
@@ -6935,6 +6989,7 @@ var PipelineRunner = class {
6935
6989
  }
6936
6990
  case "wait":
6937
6991
  case "click":
6992
+ case "click_all":
6938
6993
  await this.adapter.executeInContent(tabId, step);
6939
6994
  break;
6940
6995
  case "type":
@@ -6948,6 +7003,16 @@ var PipelineRunner = class {
6948
7003
  ctx.setData(data);
6949
7004
  break;
6950
7005
  }
7006
+ case "extract_tree": {
7007
+ const treeData = await this.adapter.executeInContent(tabId, step);
7008
+ ctx.setData(treeData);
7009
+ break;
7010
+ }
7011
+ case "extract_html": {
7012
+ const html = await this.adapter.executeInContent(tabId, step);
7013
+ if (step.as) ctx.setVar(step.as, html);
7014
+ break;
7015
+ }
6951
7016
  case "fetch": {
6952
7017
  const fetchStep = {
6953
7018
  ...step,
@@ -7014,9 +7079,9 @@ var PipelineRunner = class {
7014
7079
  throw err;
7015
7080
  }
7016
7081
  }
7017
- return { id: "", ok: true, data: ctx.getData(), steps: stepSummaries };
7082
+ return { id: "", ok: true, data: ctx.getData(), vars: ctx.getVars(), steps: stepSummaries };
7018
7083
  } catch (err) {
7019
- return { id: "", ok: false, data: [], error: err instanceof Error ? err.message : String(err), steps: stepSummaries };
7084
+ return { id: "", ok: false, data: [], vars: {}, error: err instanceof Error ? err.message : String(err), steps: stepSummaries };
7020
7085
  }
7021
7086
  }
7022
7087
  };