ask-pro 0.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 (55) hide show
  1. package/.codex-plugin/plugin.json +30 -0
  2. package/LICENSE +21 -0
  3. package/README.md +231 -0
  4. package/assets/ask-pro_logo.png +0 -0
  5. package/dist/bin/ask-pro-cli.js +507 -0
  6. package/dist/scripts/run-cli.js +27 -0
  7. package/dist/src/ask-pro/atomicWrite.js +26 -0
  8. package/dist/src/ask-pro/browserRunner.js +796 -0
  9. package/dist/src/ask-pro/responseZip.js +349 -0
  10. package/dist/src/ask-pro/session.js +662 -0
  11. package/dist/src/ask-pro/sessionControllerLease.js +64 -0
  12. package/dist/src/ask-pro/toon.js +26 -0
  13. package/dist/src/ask-pro/zip.js +85 -0
  14. package/dist/src/browser/actions/assistantResponse.js +1245 -0
  15. package/dist/src/browser/actions/attachmentDataTransfer.js +140 -0
  16. package/dist/src/browser/actions/attachments.js +1720 -0
  17. package/dist/src/browser/actions/composerSendReadiness.js +369 -0
  18. package/dist/src/browser/actions/domEvents.js +31 -0
  19. package/dist/src/browser/actions/inputGuard.js +52 -0
  20. package/dist/src/browser/actions/modelPickerDom.js +68 -0
  21. package/dist/src/browser/actions/modelSelection.js +576 -0
  22. package/dist/src/browser/actions/navigation.js +510 -0
  23. package/dist/src/browser/actions/promptComposer.js +824 -0
  24. package/dist/src/browser/actions/remoteFileTransfer.js +37 -0
  25. package/dist/src/browser/actions/thinkingStatus.js +408 -0
  26. package/dist/src/browser/actions/thinkingTime.js +635 -0
  27. package/dist/src/browser/actions/windowState.js +47 -0
  28. package/dist/src/browser/attachRunning.js +31 -0
  29. package/dist/src/browser/chatgptModelCatalog.js +321 -0
  30. package/dist/src/browser/chromeLifecycle.js +807 -0
  31. package/dist/src/browser/config.js +110 -0
  32. package/dist/src/browser/constants.js +85 -0
  33. package/dist/src/browser/cookies.js +191 -0
  34. package/dist/src/browser/detect.js +337 -0
  35. package/dist/src/browser/domDebug.js +72 -0
  36. package/dist/src/browser/errors.js +20 -0
  37. package/dist/src/browser/format.js +16 -0
  38. package/dist/src/browser/index.js +2631 -0
  39. package/dist/src/browser/language.js +97 -0
  40. package/dist/src/browser/liveTabs.js +434 -0
  41. package/dist/src/browser/modelStrategy.js +13 -0
  42. package/dist/src/browser/pageActions.js +5 -0
  43. package/dist/src/browser/profilePaths.js +282 -0
  44. package/dist/src/browser/profileState.js +413 -0
  45. package/dist/src/browser/providerDomFlow.js +17 -0
  46. package/dist/src/browser/providers/chatgptDomProvider.js +50 -0
  47. package/dist/src/browser/reattach.js +534 -0
  48. package/dist/src/browser/reattachHelpers.js +387 -0
  49. package/dist/src/browser/utils.js +122 -0
  50. package/dist/src/browserMode.js +1 -0
  51. package/dist/src/version.js +39 -0
  52. package/package.json +114 -0
  53. package/scripts/refresh-local-plugin.mjs +179 -0
  54. package/scripts/refresh-local-plugin.ps1 +93 -0
  55. package/skills/ask-pro/SKILL.md +181 -0
@@ -0,0 +1,31 @@
1
+ import { discoverDevToolsActivePortCandidates, } from "./detect.js";
2
+ export async function resolveAttachRunningConnection(config, logger) {
3
+ const host = config.remoteChrome?.host ?? "127.0.0.1";
4
+ const port = config.remoteChrome?.port ?? 9222;
5
+ if (config.chromePath) {
6
+ logger("Note: the explicit Chrome path is ignored while ask-pro is attaching to an already-running browser.");
7
+ }
8
+ logger(config.remoteChrome
9
+ ? `Using explicit attach-running target ${host}:${port}.`
10
+ : `Using default attach-running target ${host}:${port}.`);
11
+ const candidates = (await discoverDevToolsActivePortCandidates({ host }))
12
+ .filter((candidate) => candidate.port === port)
13
+ .sort(compareDevToolsCandidates);
14
+ if (candidates.length === 0) {
15
+ throw new Error(`No running browser with attach metadata matched ${host}:${port}. Enable remote debugging in chrome://inspect/#remote-debugging first.`);
16
+ }
17
+ const candidate = candidates[0];
18
+ logger(`Selected attach-running browser metadata from ${candidate.path}`);
19
+ return {
20
+ host,
21
+ port: candidate.port,
22
+ browserWSEndpoint: candidate.browserWSEndpoint,
23
+ profileRoot: candidate.profileRoot,
24
+ };
25
+ }
26
+ function compareDevToolsCandidates(left, right) {
27
+ if (right.mtimeMs !== left.mtimeMs) {
28
+ return right.mtimeMs - left.mtimeMs;
29
+ }
30
+ return left.path.localeCompare(right.path);
31
+ }
@@ -0,0 +1,321 @@
1
+ export const LATEST_CHATGPT_BROWSER_PRO_MODEL = "gpt-5.6-pro";
2
+ export const DEFAULT_CHATGPT_BROWSER_MODEL_LABEL = "Latest";
3
+ const CHATGPT_BROWSER_MODEL_TARGETS = [
4
+ {
5
+ model: "gpt-5.6-pro",
6
+ label: "GPT-5.6 Sol Pro",
7
+ version: "5-6",
8
+ kind: "pro",
9
+ visibleAliases: [{ includes: ["pro"], excludes: ["thinking", "instant", "search", "project"] }],
10
+ },
11
+ {
12
+ model: "gpt-5.5-pro",
13
+ label: "GPT-5.5 Pro",
14
+ version: "5-5",
15
+ kind: "pro",
16
+ visibleAliases: [
17
+ { includes: ["pro"], excludes: ["thinking", "instant", "search", "project"] },
18
+ { includes: ["pro", "extended"], excludes: ["thinking"] },
19
+ { includes: ["pro", "langer"], excludes: ["thinking"] },
20
+ ],
21
+ },
22
+ {
23
+ model: "gpt-5.5",
24
+ label: "Thinking 5.5",
25
+ version: "5-5",
26
+ kind: "thinking",
27
+ visibleAliases: [{ includes: ["thinking", "heavy"], excludes: ["pro"] }],
28
+ },
29
+ { model: "gpt-5.4-pro", label: "GPT-5.4 Pro", version: "5-4", kind: "pro" },
30
+ { model: "gpt-5.4", label: "Thinking 5.4", version: "5-4", kind: "thinking" },
31
+ { model: "gpt-5.2-pro", label: "GPT-5.2 Pro", version: "5-2", kind: "pro" },
32
+ { model: "gpt-5.2-thinking", label: "GPT-5.2 Thinking", version: "5-2", kind: "thinking" },
33
+ { model: "gpt-5.2-instant", label: "GPT-5.2 Instant", version: "5-2", kind: "instant" },
34
+ { model: "gpt-5.2", label: "GPT-5.2", version: "5-2", kind: null },
35
+ { model: "gpt-5.1-pro", label: "GPT-5.1 Pro", version: "5-1", kind: "pro" },
36
+ { model: "gpt-5.1", label: "GPT-5.1", version: "5-1", kind: null },
37
+ { model: "gpt-5-pro", label: "GPT-5 Pro", version: "5-0", kind: "pro" },
38
+ ];
39
+ const CHATGPT_BROWSER_ALIASES = new Map([
40
+ ["gpt-5-pro", LATEST_CHATGPT_BROWSER_PRO_MODEL],
41
+ ["gpt-5.1-pro", LATEST_CHATGPT_BROWSER_PRO_MODEL],
42
+ ["gpt-5.2-pro", LATEST_CHATGPT_BROWSER_PRO_MODEL],
43
+ ["gpt-5.1", "gpt-5.2"],
44
+ ]);
45
+ export const CHATGPT_BROWSER_VERSION_PATTERNS = [
46
+ {
47
+ version: "5-6",
48
+ textTokens: ["5 6", "gpt56"],
49
+ testIdTokens: ["5-6", "5.6", "gpt-5-6", "gpt-5.6", "gpt56"],
50
+ },
51
+ {
52
+ version: "5-5",
53
+ textTokens: ["5 5", "gpt55"],
54
+ testIdTokens: ["5-5", "5.5", "gpt-5-5", "gpt-5.5", "gpt55"],
55
+ },
56
+ {
57
+ version: "5-4",
58
+ textTokens: ["5 4", "gpt54"],
59
+ testIdTokens: ["5-4", "5.4", "gpt-5-4", "gpt-5.4", "gpt54"],
60
+ },
61
+ {
62
+ version: "5-2",
63
+ textTokens: ["5 2", "gpt52"],
64
+ testIdTokens: ["5-2", "5.2", "gpt-5-2", "gpt-5.2", "gpt52"],
65
+ },
66
+ {
67
+ version: "5-1",
68
+ textTokens: ["5 1", "gpt51"],
69
+ testIdTokens: ["5-1", "5.1", "gpt-5-1", "gpt-5.1", "gpt51"],
70
+ },
71
+ {
72
+ version: "5-0",
73
+ textTokens: ["5 0", "gpt50", "gpt 5 pro", "gpt 5"],
74
+ testIdTokens: ["5-0", "5.0", "gpt-5-0", "gpt-5.0", "gpt50"],
75
+ },
76
+ ];
77
+ export function isChatGptModelForBrowser(model) {
78
+ const normalized = model.toLowerCase();
79
+ return normalized.startsWith("gpt-") && !normalized.includes("codex");
80
+ }
81
+ export function normalizeChatGptBrowserModelForBrowser(model) {
82
+ const normalized = model.toLowerCase();
83
+ if (!isChatGptModelForBrowser(normalized)) {
84
+ return model;
85
+ }
86
+ return (CHATGPT_BROWSER_ALIASES.get(normalized) ?? getChatGptBrowserTarget(normalized)?.model ?? model);
87
+ }
88
+ export function mapChatGptModelToBrowserLabel(model) {
89
+ const normalized = normalizeChatGptBrowserModelForBrowser(model);
90
+ return getChatGptBrowserTarget(normalized)?.label;
91
+ }
92
+ export function inferChatGptBrowserModelFromLabel(label) {
93
+ const normalized = label.trim().toLowerCase();
94
+ if (!normalized) {
95
+ return undefined;
96
+ }
97
+ if (getChatGptBrowserTarget(normalized)) {
98
+ return normalized;
99
+ }
100
+ const version = inferVersionFromText(normalized);
101
+ const kind = inferKindFromText(normalized);
102
+ if (version === "5-6") {
103
+ return kind === "pro" ? "gpt-5.6-pro" : "gpt-5.6";
104
+ }
105
+ if (version === "5-5") {
106
+ return kind === "pro" ? "gpt-5.5-pro" : "gpt-5.5";
107
+ }
108
+ if (version === "5-4") {
109
+ return kind === "pro" ? "gpt-5.4-pro" : "gpt-5.4";
110
+ }
111
+ if (version === "5-2") {
112
+ if (kind === "pro")
113
+ return "gpt-5.2-pro";
114
+ if (kind === "thinking")
115
+ return "gpt-5.2-thinking";
116
+ if (kind === "instant")
117
+ return "gpt-5.2-instant";
118
+ return "gpt-5.2";
119
+ }
120
+ if (version === "5-1") {
121
+ return kind === "pro" ? "gpt-5.1-pro" : "gpt-5.1";
122
+ }
123
+ if (version === "5-0") {
124
+ return "gpt-5-pro";
125
+ }
126
+ if (kind === "pro") {
127
+ return LATEST_CHATGPT_BROWSER_PRO_MODEL;
128
+ }
129
+ if (kind === "thinking") {
130
+ return "gpt-5.2-thinking";
131
+ }
132
+ if (kind === "instant") {
133
+ return "gpt-5.2-instant";
134
+ }
135
+ return undefined;
136
+ }
137
+ export function buildChatGptModelMatchers(targetModel) {
138
+ const base = targetModel.trim().toLowerCase();
139
+ const inferredModel = inferChatGptBrowserModelFromLabel(base);
140
+ const target = inferredModel ? getChatGptBrowserTarget(inferredModel) : undefined;
141
+ const targetVersion = inferVersionFromText(base) ?? target?.version ?? null;
142
+ const targetKind = inferKindFromText(base) ?? target?.kind ?? null;
143
+ const labelTokens = new Set();
144
+ const testIdTokens = new Set();
145
+ const push = (value, set) => {
146
+ const normalized = value?.trim();
147
+ if (normalized) {
148
+ set.add(normalized);
149
+ }
150
+ };
151
+ push(base, labelTokens);
152
+ push(base.replace(/\s+/g, " "), labelTokens);
153
+ const collapsed = base.replace(/\s+/g, "");
154
+ push(collapsed, labelTokens);
155
+ const dotless = base.replace(/[.]/g, "");
156
+ push(dotless, labelTokens);
157
+ push(`chatgpt ${base}`, labelTokens);
158
+ push(`chatgpt ${dotless}`, labelTokens);
159
+ push(`gpt ${base}`, labelTokens);
160
+ push(`gpt ${dotless}`, labelTokens);
161
+ if (targetVersion) {
162
+ addVersionMatcherTokens(targetVersion, labelTokens, testIdTokens);
163
+ }
164
+ if (targetKind === "thinking") {
165
+ push("thinking", labelTokens);
166
+ if (targetVersion === "5-5") {
167
+ push("thinking heavy", labelTokens);
168
+ push("heavy thinking", labelTokens);
169
+ }
170
+ addKindTestIdTokens(targetVersion, "thinking", testIdTokens);
171
+ }
172
+ if (targetKind === "instant") {
173
+ push("instant", labelTokens);
174
+ addKindTestIdTokens(targetVersion, "instant", testIdTokens);
175
+ }
176
+ if (targetKind === "pro") {
177
+ push("proresearch", labelTokens);
178
+ push("research grade", labelTokens);
179
+ push("advanced reasoning", labelTokens);
180
+ if (targetVersion === "5-5") {
181
+ push("pro extended", labelTokens);
182
+ push("extended pro", labelTokens);
183
+ }
184
+ addKindTestIdTokens(targetVersion, "pro", testIdTokens);
185
+ testIdTokens.add("pro");
186
+ testIdTokens.add("proresearch");
187
+ }
188
+ if (targetVersion && !targetKind) {
189
+ addBaseModelTestIdToken(targetVersion, testIdTokens);
190
+ }
191
+ base
192
+ .split(/\s+/)
193
+ .map((token) => token.trim())
194
+ .filter(Boolean)
195
+ .forEach((token) => {
196
+ push(token, labelTokens);
197
+ });
198
+ const hyphenated = base.replace(/\s+/g, "-");
199
+ push(hyphenated, testIdTokens);
200
+ push(collapsed, testIdTokens);
201
+ push(dotless, testIdTokens);
202
+ push(`model-switcher-${hyphenated}`, testIdTokens);
203
+ push(`model-switcher-${collapsed}`, testIdTokens);
204
+ push(`model-switcher-${dotless}`, testIdTokens);
205
+ if (!labelTokens.size) {
206
+ labelTokens.add(base);
207
+ }
208
+ if (!testIdTokens.size) {
209
+ testIdTokens.add(base.replace(/\s+/g, "-"));
210
+ }
211
+ return {
212
+ labelTokens: Array.from(labelTokens).filter(Boolean),
213
+ testIdTokens: Array.from(testIdTokens).filter(Boolean),
214
+ targetVersion,
215
+ targetKind,
216
+ visibleAliases: target?.visibleAliases ?? visibleAliasesFor(targetVersion, targetKind),
217
+ versionPatterns: CHATGPT_BROWSER_VERSION_PATTERNS,
218
+ };
219
+ }
220
+ export function getChatGptModelKindTestIdTokens() {
221
+ const tokens = {
222
+ pro: new Set(["-pro-"]),
223
+ thinking: new Set(["-thinking-thinking-effort"]),
224
+ };
225
+ for (const target of CHATGPT_BROWSER_MODEL_TARGETS) {
226
+ if (target.kind !== "pro" && target.kind !== "thinking") {
227
+ continue;
228
+ }
229
+ addKindTestIdTokens(target.version, target.kind, tokens[target.kind]);
230
+ }
231
+ return {
232
+ pro: Array.from(tokens.pro),
233
+ thinking: Array.from(tokens.thinking),
234
+ };
235
+ }
236
+ function getChatGptBrowserTarget(model) {
237
+ const normalized = model.toLowerCase();
238
+ return CHATGPT_BROWSER_MODEL_TARGETS.find((target) => target.model === normalized);
239
+ }
240
+ function inferVersionFromText(value) {
241
+ const normalized = value.replace(/_/g, ".").replace(/\s+/g, " ");
242
+ if (/(^|[^0-9])5[.\-\s]?6([^0-9]|$)/.test(normalized) || normalized.includes("gpt56")) {
243
+ return "5-6";
244
+ }
245
+ if (/(^|[^0-9])5[.\-\s]?5([^0-9]|$)/.test(normalized) || normalized.includes("gpt55")) {
246
+ return "5-5";
247
+ }
248
+ if (/(^|[^0-9])5[.\-\s]?4([^0-9]|$)/.test(normalized) || normalized.includes("gpt54")) {
249
+ return "5-4";
250
+ }
251
+ if (/(^|[^0-9])5[.\-\s]?2([^0-9]|$)/.test(normalized) || normalized.includes("gpt52")) {
252
+ return "5-2";
253
+ }
254
+ if (/(^|[^0-9])5[.\-\s]?1([^0-9]|$)/.test(normalized) || normalized.includes("gpt51")) {
255
+ return "5-1";
256
+ }
257
+ if (/(^|[^0-9])5[.\-\s]?0([^0-9]|$)/.test(normalized) ||
258
+ normalized.includes("gpt50") ||
259
+ normalized.includes("gpt-5-pro") ||
260
+ normalized === "gpt-5") {
261
+ return "5-0";
262
+ }
263
+ return null;
264
+ }
265
+ function inferKindFromText(value) {
266
+ if (value.includes("pro")) {
267
+ return "pro";
268
+ }
269
+ if (value.includes("thinking")) {
270
+ return "thinking";
271
+ }
272
+ if (value.includes("instant") || value.includes("fast")) {
273
+ return "instant";
274
+ }
275
+ return null;
276
+ }
277
+ function visibleAliasesFor(version, kind) {
278
+ if (version === "5-6" && kind === "pro") {
279
+ return [{ includes: ["pro"], excludes: ["thinking", "instant", "search", "project"] }];
280
+ }
281
+ if (version === "5-5" && kind === "pro") {
282
+ return [
283
+ { includes: ["pro"], excludes: ["thinking", "instant", "search", "project"] },
284
+ { includes: ["pro", "extended"], excludes: ["thinking"] },
285
+ { includes: ["pro", "langer"], excludes: ["thinking"] },
286
+ ];
287
+ }
288
+ if (version === "5-5" && kind === "thinking") {
289
+ return [{ includes: ["thinking", "heavy"], excludes: ["pro"] }];
290
+ }
291
+ return [];
292
+ }
293
+ function addVersionMatcherTokens(version, labelTokens, testIdTokens) {
294
+ const dotted = version.replace("-", ".");
295
+ const hyphenated = version;
296
+ const compact = version.replace("-", "");
297
+ labelTokens.add(dotted);
298
+ labelTokens.add(`gpt-${dotted}`);
299
+ labelTokens.add(`gpt${dotted}`);
300
+ labelTokens.add(`gpt-${hyphenated}`);
301
+ labelTokens.add(`gpt${hyphenated}`);
302
+ labelTokens.add(`gpt${compact}`);
303
+ labelTokens.add(`chatgpt ${dotted}`);
304
+ testIdTokens.add(`gpt-${hyphenated}`);
305
+ testIdTokens.add(`gpt${hyphenated}`);
306
+ testIdTokens.add(`gpt${compact}`);
307
+ }
308
+ function addBaseModelTestIdToken(version, testIdTokens) {
309
+ testIdTokens.add(`model-switcher-gpt-${version}`);
310
+ }
311
+ function addKindTestIdTokens(version, kind, testIdTokens) {
312
+ if (!version) {
313
+ return;
314
+ }
315
+ const dotted = version.replace("-", ".");
316
+ testIdTokens.add(`gpt-${dotted}-${kind}`);
317
+ testIdTokens.add(`gpt-${version}-${kind}`);
318
+ testIdTokens.add(`gpt${version.replace("-", "")}${kind}`);
319
+ testIdTokens.add(`model-switcher-gpt-${version}-${kind}`);
320
+ testIdTokens.add(`model-switcher-gpt-${dotted}-${kind}`);
321
+ }