haltija 1.5.0 → 1.5.1
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.
- package/CHANGELOG.md +22 -0
- package/apps/desktop/main.js +6 -1
- package/apps/desktop/package.json +1 -1
- package/apps/desktop/resources/component.js +1 -1
- package/bin/arg-utils.mjs +21 -0
- package/bin/hj.mjs +6 -6
- package/bin/version.mjs +1 -1
- package/dist/api-handlers.d.ts +2 -0
- package/dist/component.d.ts +1 -1
- package/dist/component.esm.js +1 -1
- package/dist/component.js +1 -1
- package/dist/hj.js +16 -8
- package/dist/index.js +14 -10
- package/dist/server.js +14 -10
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.1
|
|
4
|
+
|
|
5
|
+
Low-risk follow-ups from the 1.5.0 pre-release review — the two new "instrument must not lie"
|
|
6
|
+
warnings now reach more of the surfaces where they matter.
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- **The hidden-tab / focus-ambiguity warning is no longer dropped on the paths where it's most
|
|
11
|
+
useful.** It's now attached on the **timeout** path — a hidden tab whose rAF-driven `eval` never
|
|
12
|
+
resolves now returns a `Timeout` that *explains* it may be asleep, instead of a bare timeout —
|
|
13
|
+
and preserved by the `hj find` / `hj form` handlers, which previously reshaped the response and
|
|
14
|
+
lost it. (`hj screenshot` already carried it; `hj call` intentionally still returns the raw value
|
|
15
|
+
with no envelope.)
|
|
16
|
+
|
|
17
|
+
### Internal
|
|
18
|
+
|
|
19
|
+
- Extracted the `hj --window <id>` argument handling into a pure, unit-tested helper
|
|
20
|
+
(`bin/arg-utils.mjs`), covering both the leading and trailing positions — the leading form was
|
|
21
|
+
the escape hatch that broke in 1.4.0, and it now has a regression test.
|
|
22
|
+
- A private-app startup that fails to learn its ephemeral port no longer leaves its temp port-files
|
|
23
|
+
behind.
|
|
24
|
+
|
|
3
25
|
## 1.5.0
|
|
4
26
|
|
|
5
27
|
Completes the **private-automation** feature (`--private`) begun in 1.4.1 — now for the Electron
|
package/apps/desktop/main.js
CHANGED
|
@@ -1350,7 +1350,12 @@ async function startEmbeddedServer() {
|
|
|
1350
1350
|
}
|
|
1351
1351
|
const pubPort = await readPort(pubFile)
|
|
1352
1352
|
const intPort = await readPort(intFile)
|
|
1353
|
-
if (!pubPort) {
|
|
1353
|
+
if (!pubPort) {
|
|
1354
|
+
// Don't leak the pid-scoped tmp port-files on the failure path (the success path cleans below).
|
|
1355
|
+
try { fs.rmSync(pubFile, { force: true }); fs.rmSync(intFile, { force: true }) } catch {}
|
|
1356
|
+
console.error('[Haltija Desktop] Private public server did not report its port')
|
|
1357
|
+
return false
|
|
1358
|
+
}
|
|
1354
1359
|
|
|
1355
1360
|
HALTIJA_PORT = pubPort
|
|
1356
1361
|
HALTIJA_SERVER = `http://localhost:${pubPort}`
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure arg helpers for the `hj` CLI, extracted so they can be unit-tested (see
|
|
3
|
+
* src/hj-args.test.ts) — the leading-`--window` form was fully broken and shipped without a test.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Pull a `--window <id>` flag out of `args` from ANY position, returning the id and the remaining
|
|
8
|
+
* args (input is not mutated). Mirrors how `--port`/`--name`/`--token` are pre-parsed, so both
|
|
9
|
+
* `hj --window <id> <cmd>` (leading) and `hj <cmd> --window <id>` (trailing) resolve the same tab.
|
|
10
|
+
* A `--window` with no following value is left in place (treated as not-a-target) so it surfaces as
|
|
11
|
+
* a normal unknown-flag rather than silently swallowing the next real arg.
|
|
12
|
+
*/
|
|
13
|
+
export function extractWindowTarget(args) {
|
|
14
|
+
const i = args.indexOf('--window')
|
|
15
|
+
if (i === -1 || args[i + 1] === undefined) {
|
|
16
|
+
return { windowTarget: null, args: [...args] }
|
|
17
|
+
}
|
|
18
|
+
const rest = [...args]
|
|
19
|
+
rest.splice(i, 2)
|
|
20
|
+
return { windowTarget: args[i + 1], args: rest }
|
|
21
|
+
}
|
package/bin/hj.mjs
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { runSubcommand, isSubcommand, getSuggestion, listSubcommands, COMMAND_HINTS } from './cli-subcommand.mjs'
|
|
14
|
+
import { extractWindowTarget } from './arg-utils.mjs'
|
|
14
15
|
import { HJ_VERSION } from './version.mjs'
|
|
15
16
|
import { differsBeyondPatch } from './semver.mjs'
|
|
16
17
|
import { existsSync, readFileSync, readdirSync } from 'node:fs'
|
|
@@ -313,12 +314,11 @@ if (noLaunchIdx !== -1) {
|
|
|
313
314
|
// died with "Unknown command: '--window'" — i.e. the escape hatch we tell people to use for a
|
|
314
315
|
// hidden/wrong tab didn't work in the shape the docs gave. Pulled out here and re-appended to
|
|
315
316
|
// the subcommand args below, so BOTH positions work.
|
|
316
|
-
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
317
|
+
const { windowTarget, args: argsWithoutWindow } = extractWindowTarget(args)
|
|
318
|
+
// Preserve the `const args` reference (downstream code mutates it in place) while dropping the
|
|
319
|
+
// consumed --window <id> pair.
|
|
320
|
+
args.length = 0
|
|
321
|
+
args.push(...argsWithoutWindow)
|
|
322
322
|
|
|
323
323
|
// Did the shell explicitly target a private instance (--port / --name /
|
|
324
324
|
// HALTIJA_PORT / HALTIJA_NAME / DEV_CHANNEL_PORT)? If so, this is a
|
package/bin/version.mjs
CHANGED
package/dist/api-handlers.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export interface DevResponse {
|
|
|
16
16
|
data?: any;
|
|
17
17
|
error?: string;
|
|
18
18
|
timestamp: number;
|
|
19
|
+
/** Hidden-tab / focus-ambiguity caveat attached by the server (see requestFromBrowser). */
|
|
20
|
+
warning?: string;
|
|
19
21
|
}
|
|
20
22
|
/** Function to send request to browser widget */
|
|
21
23
|
export type RequestFromBrowserFn = (channel: string, action: string, payload: any, timeoutMs?: number, windowId?: string) => Promise<DevResponse>;
|
package/dist/component.d.ts
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* - Option+Tab toggles visibility (but active state always shows briefly)
|
|
21
21
|
* - Localhost only by default
|
|
22
22
|
*/
|
|
23
|
-
export declare const VERSION = "1.5.
|
|
23
|
+
export declare const VERSION = "1.5.1";
|
|
24
24
|
export declare class DevChannel extends HTMLElement {
|
|
25
25
|
static get tagName(): string;
|
|
26
26
|
static elementCreator(): () => DevChannel;
|
package/dist/component.esm.js
CHANGED
package/dist/component.js
CHANGED
package/dist/hj.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
// haltija-cli:do-not-edit v1.5.
|
|
2
|
+
// haltija-cli:do-not-edit v1.5.1
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
5
5
|
|
|
@@ -756,7 +756,7 @@ function substituteGeneratedVars(text, seed) {
|
|
|
756
756
|
}
|
|
757
757
|
|
|
758
758
|
// bin/version.mjs
|
|
759
|
-
var HJ_VERSION = "1.5.
|
|
759
|
+
var HJ_VERSION = "1.5.1";
|
|
760
760
|
|
|
761
761
|
// bin/semver.mjs
|
|
762
762
|
function parseVersion(v) {
|
|
@@ -1906,6 +1906,17 @@ function dim2(s) {
|
|
|
1906
1906
|
return `\x1B[2m${s}\x1B[0m`;
|
|
1907
1907
|
}
|
|
1908
1908
|
|
|
1909
|
+
// bin/arg-utils.mjs
|
|
1910
|
+
function extractWindowTarget(args) {
|
|
1911
|
+
const i = args.indexOf("--window");
|
|
1912
|
+
if (i === -1 || args[i + 1] === undefined) {
|
|
1913
|
+
return { windowTarget: null, args: [...args] };
|
|
1914
|
+
}
|
|
1915
|
+
const rest = [...args];
|
|
1916
|
+
rest.splice(i, 2);
|
|
1917
|
+
return { windowTarget: args[i + 1], args: rest };
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1909
1920
|
// bin/hj.mjs
|
|
1910
1921
|
import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync as readdirSync2 } from "node:fs";
|
|
1911
1922
|
import { homedir as homedir2 } from "node:os";
|
|
@@ -2137,12 +2148,9 @@ if (noLaunchIdx !== -1) {
|
|
|
2137
2148
|
noLaunch = true;
|
|
2138
2149
|
args.splice(noLaunchIdx, 1);
|
|
2139
2150
|
}
|
|
2140
|
-
var windowTarget =
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
windowTarget = args[windowIdx + 1];
|
|
2144
|
-
args.splice(windowIdx, 2);
|
|
2145
|
-
}
|
|
2151
|
+
var { windowTarget, args: argsWithoutWindow } = extractWindowTarget(args);
|
|
2152
|
+
args.length = 0;
|
|
2153
|
+
args.push(...argsWithoutWindow);
|
|
2146
2154
|
var explicitTarget = portSource !== "8700 (default)";
|
|
2147
2155
|
if (args.length >= 2 && isSubcommand(`${args[0]}-${args[1]}`)) {
|
|
2148
2156
|
args.splice(0, 2, `${args[0]}-${args[1]}`);
|
package/dist/index.js
CHANGED
|
@@ -674,7 +674,7 @@ var injectorCode = `
|
|
|
674
674
|
`;
|
|
675
675
|
|
|
676
676
|
// src/version.ts
|
|
677
|
-
var VERSION = "1.5.
|
|
677
|
+
var VERSION = "1.5.1";
|
|
678
678
|
|
|
679
679
|
// src/embedded-assets.ts
|
|
680
680
|
var APP_MD = `# Haltija App
|
|
@@ -3097,7 +3097,7 @@ var COMPONENT_JS = `(() => {
|
|
|
3097
3097
|
});
|
|
3098
3098
|
|
|
3099
3099
|
// src/version.ts
|
|
3100
|
-
var VERSION = "1.5.
|
|
3100
|
+
var VERSION = "1.5.1";
|
|
3101
3101
|
|
|
3102
3102
|
// src/text-selector.ts
|
|
3103
3103
|
var TEXT_PSEUDO_RE = /:(?:text-is|has-text|text)\\(/;
|
|
@@ -13727,6 +13727,9 @@ function inferSuggestion(step, pageContext) {
|
|
|
13727
13727
|
}
|
|
13728
13728
|
|
|
13729
13729
|
// src/api-handlers.ts
|
|
13730
|
+
function withWarning(body, response) {
|
|
13731
|
+
return response.warning ? { ...body, warning: response.warning } : body;
|
|
13732
|
+
}
|
|
13730
13733
|
var handlers = new Map;
|
|
13731
13734
|
function registerHandler(endpoint2, handler) {
|
|
13732
13735
|
handlers.set(endpoint2.path, handler);
|
|
@@ -14557,7 +14560,7 @@ registerHandler(find, async (body, ctx) => {
|
|
|
14557
14560
|
})()`;
|
|
14558
14561
|
const response = await ctx.requestFromBrowser("eval", "exec", { code: findCode }, 5000, windowId);
|
|
14559
14562
|
if (response.success && response.data) {
|
|
14560
|
-
return Response.json({ success: true, ...response.data }, { headers: ctx.headers });
|
|
14563
|
+
return Response.json(withWarning({ success: true, ...response.data }, response), { headers: ctx.headers });
|
|
14561
14564
|
}
|
|
14562
14565
|
return Response.json(response, { headers: ctx.headers });
|
|
14563
14566
|
});
|
|
@@ -14663,7 +14666,7 @@ registerHandler(formData, async (body, ctx) => {
|
|
|
14663
14666
|
})()`;
|
|
14664
14667
|
const response = await ctx.requestFromBrowser("eval", "exec", { code: formCode }, 5000, windowId);
|
|
14665
14668
|
if (response.success && response.data) {
|
|
14666
|
-
return Response.json(response.data, { headers: ctx.headers });
|
|
14669
|
+
return Response.json(withWarning(response.data, response), { headers: ctx.headers });
|
|
14667
14670
|
}
|
|
14668
14671
|
return Response.json(response, { headers: ctx.headers });
|
|
14669
14672
|
});
|
|
@@ -16438,12 +16441,8 @@ async function requestFromBrowser(channel, action, payload, timeoutMs = 5000, wi
|
|
|
16438
16441
|
source: "agent"
|
|
16439
16442
|
};
|
|
16440
16443
|
return new Promise((resolve) => {
|
|
16441
|
-
const timeout = setTimeout(() => {
|
|
16442
|
-
pendingResponses.delete(id);
|
|
16443
|
-
resolve({ id, success: false, error: "Timeout", timestamp: Date.now() });
|
|
16444
|
-
}, timeoutMs);
|
|
16445
16444
|
let sentTo = null;
|
|
16446
|
-
const
|
|
16445
|
+
const attachWarning = (res) => {
|
|
16447
16446
|
const hidden = hiddenTabWarning(sentTo);
|
|
16448
16447
|
const ambiguous = ambiguousFocusWarning({
|
|
16449
16448
|
windows: Array.from(windows2.values()),
|
|
@@ -16453,8 +16452,13 @@ async function requestFromBrowser(channel, action, payload, timeoutMs = 5000, wi
|
|
|
16453
16452
|
const warning = [hidden, ambiguous].filter(Boolean).join(`
|
|
16454
16453
|
|
|
16455
16454
|
`);
|
|
16456
|
-
|
|
16455
|
+
return warning ? { ...res, warning } : res;
|
|
16457
16456
|
};
|
|
16457
|
+
const timeout = setTimeout(() => {
|
|
16458
|
+
pendingResponses.delete(id);
|
|
16459
|
+
resolve(attachWarning({ id, success: false, error: "Timeout", timestamp: Date.now() }));
|
|
16460
|
+
}, timeoutMs);
|
|
16461
|
+
const resolveWithLiveness = (res) => resolve(attachWarning(res));
|
|
16458
16462
|
pendingResponses.set(id, { resolve: resolveWithLiveness, timeout });
|
|
16459
16463
|
if (windowId) {
|
|
16460
16464
|
const win = windows2.get(windowId);
|
package/dist/server.js
CHANGED
|
@@ -674,7 +674,7 @@ var injectorCode = `
|
|
|
674
674
|
`;
|
|
675
675
|
|
|
676
676
|
// src/version.ts
|
|
677
|
-
var VERSION = "1.5.
|
|
677
|
+
var VERSION = "1.5.1";
|
|
678
678
|
|
|
679
679
|
// src/embedded-assets.ts
|
|
680
680
|
var APP_MD = `# Haltija App
|
|
@@ -3097,7 +3097,7 @@ var COMPONENT_JS = `(() => {
|
|
|
3097
3097
|
});
|
|
3098
3098
|
|
|
3099
3099
|
// src/version.ts
|
|
3100
|
-
var VERSION = "1.5.
|
|
3100
|
+
var VERSION = "1.5.1";
|
|
3101
3101
|
|
|
3102
3102
|
// src/text-selector.ts
|
|
3103
3103
|
var TEXT_PSEUDO_RE = /:(?:text-is|has-text|text)\\(/;
|
|
@@ -13727,6 +13727,9 @@ function inferSuggestion(step, pageContext) {
|
|
|
13727
13727
|
}
|
|
13728
13728
|
|
|
13729
13729
|
// src/api-handlers.ts
|
|
13730
|
+
function withWarning(body, response) {
|
|
13731
|
+
return response.warning ? { ...body, warning: response.warning } : body;
|
|
13732
|
+
}
|
|
13730
13733
|
var handlers = new Map;
|
|
13731
13734
|
function registerHandler(endpoint2, handler) {
|
|
13732
13735
|
handlers.set(endpoint2.path, handler);
|
|
@@ -14557,7 +14560,7 @@ registerHandler(find, async (body, ctx) => {
|
|
|
14557
14560
|
})()`;
|
|
14558
14561
|
const response = await ctx.requestFromBrowser("eval", "exec", { code: findCode }, 5000, windowId);
|
|
14559
14562
|
if (response.success && response.data) {
|
|
14560
|
-
return Response.json({ success: true, ...response.data }, { headers: ctx.headers });
|
|
14563
|
+
return Response.json(withWarning({ success: true, ...response.data }, response), { headers: ctx.headers });
|
|
14561
14564
|
}
|
|
14562
14565
|
return Response.json(response, { headers: ctx.headers });
|
|
14563
14566
|
});
|
|
@@ -14663,7 +14666,7 @@ registerHandler(formData, async (body, ctx) => {
|
|
|
14663
14666
|
})()`;
|
|
14664
14667
|
const response = await ctx.requestFromBrowser("eval", "exec", { code: formCode }, 5000, windowId);
|
|
14665
14668
|
if (response.success && response.data) {
|
|
14666
|
-
return Response.json(response.data, { headers: ctx.headers });
|
|
14669
|
+
return Response.json(withWarning(response.data, response), { headers: ctx.headers });
|
|
14667
14670
|
}
|
|
14668
14671
|
return Response.json(response, { headers: ctx.headers });
|
|
14669
14672
|
});
|
|
@@ -16438,12 +16441,8 @@ async function requestFromBrowser(channel, action, payload, timeoutMs = 5000, wi
|
|
|
16438
16441
|
source: "agent"
|
|
16439
16442
|
};
|
|
16440
16443
|
return new Promise((resolve) => {
|
|
16441
|
-
const timeout = setTimeout(() => {
|
|
16442
|
-
pendingResponses.delete(id);
|
|
16443
|
-
resolve({ id, success: false, error: "Timeout", timestamp: Date.now() });
|
|
16444
|
-
}, timeoutMs);
|
|
16445
16444
|
let sentTo = null;
|
|
16446
|
-
const
|
|
16445
|
+
const attachWarning = (res) => {
|
|
16447
16446
|
const hidden = hiddenTabWarning(sentTo);
|
|
16448
16447
|
const ambiguous = ambiguousFocusWarning({
|
|
16449
16448
|
windows: Array.from(windows2.values()),
|
|
@@ -16453,8 +16452,13 @@ async function requestFromBrowser(channel, action, payload, timeoutMs = 5000, wi
|
|
|
16453
16452
|
const warning = [hidden, ambiguous].filter(Boolean).join(`
|
|
16454
16453
|
|
|
16455
16454
|
`);
|
|
16456
|
-
|
|
16455
|
+
return warning ? { ...res, warning } : res;
|
|
16457
16456
|
};
|
|
16457
|
+
const timeout = setTimeout(() => {
|
|
16458
|
+
pendingResponses.delete(id);
|
|
16459
|
+
resolve(attachWarning({ id, success: false, error: "Timeout", timestamp: Date.now() }));
|
|
16460
|
+
}, timeoutMs);
|
|
16461
|
+
const resolveWithLiveness = (res) => resolve(attachWarning(res));
|
|
16458
16462
|
pendingResponses.set(id, { resolve: resolveWithLiveness, timeout });
|
|
16459
16463
|
if (windowId) {
|
|
16460
16464
|
const win = windows2.get(windowId);
|
package/dist/version.d.ts
CHANGED