@ticktockbent/charlotte 0.6.0 → 0.6.2

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 (78) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +2 -4
  3. package/dist/browser/browser-manager.d.ts +3 -0
  4. package/dist/browser/browser-manager.d.ts.map +1 -1
  5. package/dist/browser/browser-manager.js +13 -2
  6. package/dist/browser/browser-manager.js.map +1 -1
  7. package/dist/cli.d.ts +1 -0
  8. package/dist/cli.d.ts.map +1 -1
  9. package/dist/cli.js +41 -16
  10. package/dist/cli.js.map +1 -1
  11. package/dist/index.js +2 -6
  12. package/dist/index.js.map +1 -1
  13. package/dist/renderer/interactive-extractor.d.ts.map +1 -1
  14. package/dist/renderer/interactive-extractor.js +10 -2
  15. package/dist/renderer/interactive-extractor.js.map +1 -1
  16. package/dist/renderer/layout-extractor.d.ts.map +1 -1
  17. package/dist/renderer/layout-extractor.js +10 -2
  18. package/dist/renderer/layout-extractor.js.map +1 -1
  19. package/dist/renderer/renderer-pipeline.d.ts +2 -2
  20. package/dist/renderer/renderer-pipeline.d.ts.map +1 -1
  21. package/dist/renderer/renderer-pipeline.js +5 -3
  22. package/dist/renderer/renderer-pipeline.js.map +1 -1
  23. package/dist/server.d.ts.map +1 -1
  24. package/dist/server.js +9 -4
  25. package/dist/server.js.map +1 -1
  26. package/dist/state/snapshot-store.d.ts +4 -0
  27. package/dist/state/snapshot-store.d.ts.map +1 -1
  28. package/dist/state/snapshot-store.js +15 -3
  29. package/dist/state/snapshot-store.js.map +1 -1
  30. package/dist/tools/dev-mode.d.ts.map +1 -1
  31. package/dist/tools/dev-mode.js +10 -10
  32. package/dist/tools/dev-mode.js.map +1 -1
  33. package/dist/tools/dialog.js +5 -5
  34. package/dist/tools/dialog.js.map +1 -1
  35. package/dist/tools/evaluate.d.ts +1 -1
  36. package/dist/tools/evaluate.d.ts.map +1 -1
  37. package/dist/tools/evaluate.js +3 -2
  38. package/dist/tools/evaluate.js.map +1 -1
  39. package/dist/tools/interaction-helpers.d.ts +55 -0
  40. package/dist/tools/interaction-helpers.d.ts.map +1 -0
  41. package/dist/tools/interaction-helpers.js +312 -0
  42. package/dist/tools/interaction-helpers.js.map +1 -0
  43. package/dist/tools/interaction.d.ts +1 -17
  44. package/dist/tools/interaction.d.ts.map +1 -1
  45. package/dist/tools/interaction.js +120 -500
  46. package/dist/tools/interaction.js.map +1 -1
  47. package/dist/tools/meta-tool.d.ts +2 -2
  48. package/dist/tools/meta-tool.js +3 -3
  49. package/dist/tools/monitoring.js +9 -9
  50. package/dist/tools/monitoring.js.map +1 -1
  51. package/dist/tools/navigation.d.ts.map +1 -1
  52. package/dist/tools/navigation.js +36 -76
  53. package/dist/tools/navigation.js.map +1 -1
  54. package/dist/tools/observation.d.ts.map +1 -1
  55. package/dist/tools/observation.js +94 -98
  56. package/dist/tools/observation.js.map +1 -1
  57. package/dist/tools/session.d.ts.map +1 -1
  58. package/dist/tools/session.js +135 -184
  59. package/dist/tools/session.js.map +1 -1
  60. package/dist/tools/tool-groups.d.ts +8 -8
  61. package/dist/tools/tool-groups.d.ts.map +1 -1
  62. package/dist/tools/tool-groups.js +113 -142
  63. package/dist/tools/tool-groups.js.map +1 -1
  64. package/dist/tools/tool-helpers.d.ts +18 -0
  65. package/dist/tools/tool-helpers.d.ts.map +1 -1
  66. package/dist/tools/tool-helpers.js +69 -2
  67. package/dist/tools/tool-helpers.js.map +1 -1
  68. package/dist/tools/wait-for.d.ts +5 -0
  69. package/dist/tools/wait-for.d.ts.map +1 -0
  70. package/dist/tools/wait-for.js +169 -0
  71. package/dist/tools/wait-for.js.map +1 -0
  72. package/dist/types/config.d.ts +16 -0
  73. package/dist/types/config.d.ts.map +1 -1
  74. package/dist/types/config.js +15 -0
  75. package/dist/types/config.js.map +1 -1
  76. package/dist/utils/wait.js +11 -5
  77. package/dist/utils/wait.js.map +1 -1
  78. package/package.json +1 -1
@@ -0,0 +1,169 @@
1
+ import { z } from "zod";
2
+ import { CharlotteError, CharlotteErrorCode } from "../types/errors.js";
3
+ import { logger } from "../utils/logger.js";
4
+ import { ensureReady, renderActivePage, renderAfterAction, formatPageResponse, handleToolError, } from "./tool-helpers.js";
5
+ export function registerWaitForTools(server, deps) {
6
+ const tools = {};
7
+ // ─── charlotte_wait_for ───
8
+ tools["charlotte_wait_for"] = server.registerTool("charlotte_wait_for", {
9
+ description: "Wait for a condition to be met on the page. Returns page representation when the condition is satisfied, or a TIMEOUT error.",
10
+ inputSchema: {
11
+ element_id: z.string().optional().describe("Wait for specific element to appear/change"),
12
+ state: z
13
+ .enum(["visible", "hidden", "enabled", "disabled", "exists", "removed"])
14
+ .optional()
15
+ .describe("Target element state to wait for"),
16
+ text: z.string().optional().describe("Wait for text to appear on the page"),
17
+ selector: z.string().optional().describe("Wait for CSS selector to match"),
18
+ js: z.string().optional().describe("Wait for JS expression to return truthy"),
19
+ timeout: z.number().optional().describe("Max wait in ms (default: 10000)"),
20
+ },
21
+ }, async ({ element_id, state, text, selector, js, timeout }) => {
22
+ try {
23
+ await ensureReady(deps);
24
+ const page = deps.pageManager.getActivePage();
25
+ const waitTimeout = timeout ?? 10000;
26
+ // Validate that at least one condition is provided
27
+ if (!element_id && !text && !selector && !js) {
28
+ throw new CharlotteError(CharlotteErrorCode.SESSION_ERROR, "At least one wait condition is required (element_id, text, selector, or js).");
29
+ }
30
+ logger.info("Waiting for condition", {
31
+ element_id,
32
+ state,
33
+ text,
34
+ selector,
35
+ js,
36
+ timeout: waitTimeout,
37
+ });
38
+ // Build a composite wait condition
39
+ const satisfied = await pollWaitForCondition(deps, page, { element_id, state, text, selector, js }, waitTimeout);
40
+ if (!satisfied) {
41
+ const representation = await renderAfterAction(deps);
42
+ const timeoutError = new CharlotteError(CharlotteErrorCode.TIMEOUT, `Wait condition not met within ${waitTimeout}ms.`, "The current page state is included in the response. Consider increasing timeout or adjusting your condition.");
43
+ return {
44
+ content: [
45
+ {
46
+ type: "text",
47
+ text: JSON.stringify({
48
+ ...timeoutError.toResponse(),
49
+ page: representation,
50
+ }),
51
+ },
52
+ ],
53
+ isError: true,
54
+ };
55
+ }
56
+ const representation = await renderAfterAction(deps);
57
+ return formatPageResponse(representation);
58
+ }
59
+ catch (error) {
60
+ return handleToolError(error);
61
+ }
62
+ });
63
+ return tools;
64
+ }
65
+ /**
66
+ * Poll for complex wait_for conditions that may involve element state checks.
67
+ */
68
+ async function pollWaitForCondition(deps, page, condition, timeoutMs) {
69
+ const pollInterval = 100;
70
+ const deadline = Date.now() + timeoutMs;
71
+ while (Date.now() < deadline) {
72
+ let allSatisfied = true;
73
+ // Check element_id + state condition
74
+ if (condition.element_id) {
75
+ const targetState = condition.state ?? "exists";
76
+ const elementSatisfied = await checkElementCondition(deps, condition.element_id, targetState);
77
+ if (!elementSatisfied)
78
+ allSatisfied = false;
79
+ }
80
+ // Check text condition
81
+ if (allSatisfied && condition.text) {
82
+ const textFound = await page.evaluate((searchText) => {
83
+ return document.body?.innerText?.includes(searchText) ?? false;
84
+ }, condition.text);
85
+ if (!textFound)
86
+ allSatisfied = false;
87
+ }
88
+ // Check selector condition
89
+ if (allSatisfied && condition.selector) {
90
+ const selectorMatched = await page.$(condition.selector);
91
+ if (!selectorMatched)
92
+ allSatisfied = false;
93
+ }
94
+ // Check JS condition via CDP Runtime.evaluate (matches evaluate.ts pattern)
95
+ if (allSatisfied && condition.js) {
96
+ const cdpSession = await page.createCDPSession();
97
+ try {
98
+ const evalResult = await cdpSession.send("Runtime.evaluate", {
99
+ expression: condition.js,
100
+ returnByValue: true,
101
+ awaitPromise: true,
102
+ timeout: Math.max(0, deadline - Date.now()),
103
+ });
104
+ const isTruthy = !evalResult.exceptionDetails && !!evalResult.result.value;
105
+ if (!isTruthy)
106
+ allSatisfied = false;
107
+ }
108
+ catch {
109
+ allSatisfied = false;
110
+ }
111
+ finally {
112
+ await cdpSession.detach().catch(() => { });
113
+ }
114
+ }
115
+ if (allSatisfied)
116
+ return true;
117
+ const remainingTime = deadline - Date.now();
118
+ if (remainingTime <= 0)
119
+ break;
120
+ await new Promise((resolve) => setTimeout(resolve, Math.min(pollInterval, remainingTime)));
121
+ }
122
+ return false;
123
+ }
124
+ /**
125
+ * Check if an element meets a specific state condition.
126
+ */
127
+ async function checkElementCondition(deps, elementId, targetState) {
128
+ switch (targetState) {
129
+ case "exists": {
130
+ const backendNodeId = deps.elementIdGenerator.resolveId(elementId);
131
+ return backendNodeId !== null;
132
+ }
133
+ case "removed": {
134
+ const backendNodeId = deps.elementIdGenerator.resolveId(elementId);
135
+ if (backendNodeId !== null) {
136
+ // Re-render to check if it's truly still there
137
+ await renderActivePage(deps, { detail: "minimal" });
138
+ return deps.elementIdGenerator.resolveId(elementId) === null;
139
+ }
140
+ return true;
141
+ }
142
+ case "visible":
143
+ case "hidden":
144
+ case "enabled":
145
+ case "disabled": {
146
+ // Re-render to get fresh state
147
+ const representation = await renderActivePage(deps, { detail: "minimal" });
148
+ const element = representation.interactive.find((el) => el.id === elementId);
149
+ if (!element) {
150
+ // Element doesn't exist — "hidden" and "disabled" are satisfied, others not
151
+ return targetState === "hidden" || targetState === "disabled";
152
+ }
153
+ switch (targetState) {
154
+ case "visible":
155
+ return element.state.visible === true;
156
+ case "hidden":
157
+ return element.state.visible === false;
158
+ case "enabled":
159
+ return element.state.enabled === true;
160
+ case "disabled":
161
+ return element.state.enabled === false;
162
+ }
163
+ return false;
164
+ }
165
+ default:
166
+ return false;
167
+ }
168
+ }
169
+ //# sourceMappingURL=wait-for.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait-for.js","sourceRoot":"","sources":["../../src/tools/wait-for.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,11 @@
1
1
  export type AutoSnapshotMode = "every_action" | "observe_only" | "manual";
2
2
  export type DialogAutoDismiss = "none" | "accept_alerts" | "accept_all" | "dismiss_all";
3
+ export type DeviceType = "mobile" | "tablet" | "desktop";
4
+ /** Default viewport dimensions for each device type. */
5
+ export declare const DEVICE_VIEWPORT_PRESETS: Record<DeviceType, {
6
+ width: number;
7
+ height: number;
8
+ }>;
3
9
  export interface CharlotteConfig {
4
10
  /** Root directory boundary for dev_serve to prevent path traversal */
5
11
  allowedWorkspaceRoot?: string;
@@ -14,6 +20,16 @@ export interface CharlotteConfig {
14
20
  includeIframes: boolean;
15
21
  /** Maximum iframe nesting depth to traverse. Default: 3. */
16
22
  iframeDepth: number;
23
+ /** Default viewport dimensions used at browser launch and as fallback. */
24
+ defaultViewport: {
25
+ width: number;
26
+ height: number;
27
+ };
28
+ /** Named device viewport presets for the charlotte_viewport tool. */
29
+ deviceViewportPresets: Record<DeviceType, {
30
+ width: number;
31
+ height: number;
32
+ }>;
17
33
  }
18
34
  export declare function createDefaultConfig(): CharlotteConfig;
19
35
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,cAAc,GAAG,QAAQ,CAAC;AAC1E,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,eAAe,GAAG,YAAY,GAAG,aAAa,CAAC;AAExF,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kGAAkG;IAClG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,cAAc,EAAE,OAAO,CAAC;IACxB,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,mBAAmB,IAAI,eAAe,CASrD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,cAAc,GAAG,QAAQ,CAAC;AAC1E,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,eAAe,GAAG,YAAY,GAAG,aAAa,CAAC;AACxF,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzD,wDAAwD;AACxD,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,UAAU,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAOzF,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kGAAkG;IAClG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,cAAc,EAAE,OAAO,CAAC;IACxB,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,eAAe,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,qEAAqE;IACrE,qBAAqB,EAAE,MAAM,CAAC,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9E;AAED,wBAAgB,mBAAmB,IAAI,eAAe,CAerD"}
@@ -1,3 +1,12 @@
1
+ /** Default viewport dimensions for each device type. */
2
+ export const DEVICE_VIEWPORT_PRESETS = {
3
+ /** Common Modern Laptop Effective Resolution */
4
+ desktop: { width: 1440, height: 900 },
5
+ /** iPhone 14 Pro Effective Resolution */
6
+ mobile: { width: 393, height: 852 },
7
+ /** Standard Tablet Resolution */
8
+ tablet: { width: 768, height: 1024 },
9
+ };
1
10
  export function createDefaultConfig() {
2
11
  return {
3
12
  snapshotDepth: 50,
@@ -6,6 +15,12 @@ export function createDefaultConfig() {
6
15
  allowedWorkspaceRoot: process.cwd(), // Default to cwd for universal safety
7
16
  includeIframes: false,
8
17
  iframeDepth: 3,
18
+ defaultViewport: { ...DEVICE_VIEWPORT_PRESETS.desktop },
19
+ deviceViewportPresets: {
20
+ desktop: { ...DEVICE_VIEWPORT_PRESETS.desktop },
21
+ mobile: { ...DEVICE_VIEWPORT_PRESETS.mobile },
22
+ tablet: { ...DEVICE_VIEWPORT_PRESETS.tablet },
23
+ },
9
24
  };
10
25
  }
11
26
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAmBA,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL,aAAa,EAAE,EAAE;QACjB,YAAY,EAAE,cAAc;QAC5B,iBAAiB,EAAE,MAAM;QACzB,oBAAoB,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,sCAAsC;QAC3E,cAAc,EAAE,KAAK;QACrB,WAAW,EAAE,CAAC;KACf,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAIA,wDAAwD;AACxD,MAAM,CAAC,MAAM,uBAAuB,GAA0D;IAC5F,gDAAgD;IAChD,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;IACrC,yCAAyC;IACzC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;IACnC,iCAAiC;IACjC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;CACrC,CAAC;AAsBF,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL,aAAa,EAAE,EAAE;QACjB,YAAY,EAAE,cAAc;QAC5B,iBAAiB,EAAE,MAAM;QACzB,oBAAoB,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,sCAAsC;QAC3E,cAAc,EAAE,KAAK;QACrB,WAAW,EAAE,CAAC;QACd,eAAe,EAAE,EAAE,GAAG,uBAAuB,CAAC,OAAO,EAAE;QACvD,qBAAqB,EAAE;YACrB,OAAO,EAAE,EAAE,GAAG,uBAAuB,CAAC,OAAO,EAAE;YAC/C,MAAM,EAAE,EAAE,GAAG,uBAAuB,CAAC,MAAM,EAAE;YAC7C,MAAM,EAAE,EAAE,GAAG,uBAAuB,CAAC,MAAM,EAAE;SAC9C;KACF,CAAC;AACJ,CAAC"}
@@ -35,17 +35,23 @@ async function evaluateCondition(page, condition) {
35
35
  return false;
36
36
  }
37
37
  if (condition.js) {
38
- const jsExpression = condition.js;
38
+ const cdpSession = await page.createCDPSession();
39
39
  try {
40
- const result = await page.evaluate((expression) => {
41
- return !!new Function("return " + expression)();
42
- }, jsExpression);
43
- if (!result)
40
+ const evalResult = await cdpSession.send("Runtime.evaluate", {
41
+ expression: condition.js,
42
+ returnByValue: true,
43
+ awaitPromise: true,
44
+ });
45
+ const isTruthy = !evalResult.exceptionDetails && !!evalResult.result.value;
46
+ if (!isTruthy)
44
47
  return false;
45
48
  }
46
49
  catch {
47
50
  return false;
48
51
  }
52
+ finally {
53
+ await cdpSession.detach().catch(() => { });
54
+ }
49
55
  }
50
56
  return true;
51
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"wait.js","sourceRoot":"","sources":["../../src/utils/wait.ts"],"names":[],"mappings":"AAkBA,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAErC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAU,EACV,SAAwB,EACxB,OAAoB;IAEpB,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,wBAAwB,CAAC;IACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAE9C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC3D,IAAI,SAAS;YAAE,OAAO,IAAI,CAAC;QAE3B,MAAM,aAAa,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5C,IAAI,aAAa,IAAI,CAAC;YAAE,MAAM;QAE9B,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,iBAAiB,CAAC,IAAU,EAAE,SAAwB;IACnE,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;IAC7B,CAAC;IAED,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC;QACnB,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC;QAClC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,UAAU,EAAE,EAAE;YAC/C,OAAO,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC;QACjE,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;IAC3B,CAAC;IAED,IAAI,SAAS,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,YAAY,GAAG,SAAS,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,UAAU,EAAE,EAAE;gBAChD,OAAO,CAAC,CAAC,IAAI,QAAQ,CAAC,SAAS,GAAG,UAAU,CAAC,EAAE,CAAC;YAClD,CAAC,EAAE,YAAY,CAAC,CAAC;YACjB,IAAI,CAAC,MAAM;gBAAE,OAAO,KAAK,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
1
+ {"version":3,"file":"wait.js","sourceRoot":"","sources":["../../src/utils/wait.ts"],"names":[],"mappings":"AAkBA,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAErC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAU,EACV,SAAwB,EACxB,OAAoB;IAEpB,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,wBAAwB,CAAC;IACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAE9C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC3D,IAAI,SAAS;YAAE,OAAO,IAAI,CAAC;QAE3B,MAAM,aAAa,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5C,IAAI,aAAa,IAAI,CAAC;YAAE,MAAM;QAE9B,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,iBAAiB,CAAC,IAAU,EAAE,SAAwB;IACnE,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;IAC7B,CAAC;IAED,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC;QACnB,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC;QAClC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,UAAU,EAAE,EAAE;YAC/C,OAAO,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC;QACjE,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;IAC3B,CAAC;IAED,IAAI,SAAS,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,kBAAkB,EAAE;gBAC3D,UAAU,EAAE,SAAS,CAAC,EAAE;gBACxB,aAAa,EAAE,IAAI;gBACnB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;YACH,MAAM,QAAQ,GAAG,CAAC,UAAU,CAAC,gBAAgB,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;YAC3E,IAAI,CAAC,QAAQ;gBAAE,OAAO,KAAK,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;gBAAS,CAAC;YACT,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ticktockbent/charlotte",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "Token-efficient browser MCP server — structured web pages for AI agents, not raw accessibility dumps",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",