@nikelyh/offscript 1.6.0 → 1.6.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/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  **Your users don't follow a script. Neither do ours.**
8
8
 
9
- Current stable release: **v1.0.1** on [npm](https://www.npmjs.com/package/@nikelyh/offscript).
9
+ Current stable release: **v1.7.0** on [npm](https://www.npmjs.com/package/@nikelyh/offscript).
10
10
  Online documentation: [offscript.nikelyh.tech](https://offscript.nikelyh.tech).
11
11
 
12
12
  OFFSCRIPT brings multi-agent software exploration into a local developer workflow: configure a target and goal, choose artificial users, run a bounded session, and inspect observations, investigations and visual evidence in Studio or the terminal.
@@ -36,7 +36,7 @@ npm install -g @nikelyh/offscript
36
36
  Or run directly with `npx`:
37
37
 
38
38
  ```sh
39
- npx --yes @nikelyh/offscript@1.0.1 studio
39
+ npx --yes @nikelyh/offscript studio
40
40
  ```
41
41
 
42
42
  For browser exploration, install the required Chromium binary:
@@ -110,10 +110,10 @@ From the OFFSCRIPT checkout:
110
110
  npm pack
111
111
  ```
112
112
 
113
- This builds `nikelyh-offscript-1.0.1.tgz`. From your target project's directory:
113
+ This builds `nikelyh-offscript-*.tgz`. From your target project's directory:
114
114
 
115
115
  ```sh
116
- npm exec --yes --package="/absolute/path/nikelyh-offscript-1.0.1.tgz" -- offscript studio
116
+ npm exec --yes --package="/absolute/path/nikelyh-offscript-*.tgz" -- offscript studio
117
117
  ```
118
118
 
119
119
  The current directory becomes the project root. Use a real absolute archive path; Windows paths are supported. npm installs dependencies in its execution cache without adding OFFSCRIPT to the target's package manifest. The first run can need network access and native dependency setup.
@@ -22,6 +22,7 @@ export class BrowserManager {
22
22
  try {
23
23
  const browser = await chromium.launch({
24
24
  headless: this.headless,
25
+ args: this.headless ? [] : ["--start-maximized"],
25
26
  });
26
27
  if (this.closed) {
27
28
  await browser.close().catch(() => { });
@@ -50,6 +51,9 @@ export class BrowserManager {
50
51
  if (options.storageState) {
51
52
  contextOptions.storageState = options.storageState;
52
53
  }
54
+ if (!this.headless) {
55
+ contextOptions.viewport = null;
56
+ }
53
57
  const context = await browser.newContext(contextOptions);
54
58
  const session = await BrowserUserSession.create(context, options);
55
59
  this.sessions.add(session);
@@ -60,8 +60,10 @@ export class BrowserUserSession {
60
60
  try {
61
61
  await this.page.goto(resolvedUrl, {
62
62
  timeout: this.navigationTimeoutMs,
63
- waitUntil: "domcontentloaded",
63
+ waitUntil: "load",
64
64
  });
65
+ // Allow client-side frameworks (e.g. Next.js, React) to settle initial hydration
66
+ await this.page.evaluate(() => new Promise((resolve) => setTimeout(resolve, 50))).catch(() => { });
65
67
  return { success: true, action: "navigate", url: this.page.url() };
66
68
  }
67
69
  catch (cause) {
@@ -1,5 +1,5 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { executeAssignInvestigation } from "../application/index.js";
2
+ import { ApplicationError, executeAssignInvestigation } from "../application/index.js";
3
3
  import { decodeEvent, offscriptEventType } from "./event-bridge.js";
4
4
  import { situation } from "./situations.js";
5
5
  export function investigationReaction({ state, id, maxTurns, store, startTurn }) {
@@ -41,6 +41,12 @@ export function investigationReaction({ state, id, maxTurns, store, startTurn })
41
41
  }
42
42
  catch (cause) {
43
43
  state.reactions.delete(key);
44
+ if (cause instanceof ApplicationError && cause.code === "INVESTIGATION_CONFLICT") {
45
+ const reloaded = await store.findInvestigation(decoded.payload.investigation.id).catch(() => undefined);
46
+ if (reloaded && reloaded.investigation.lifecycle.status !== "requested") {
47
+ return;
48
+ }
49
+ }
44
50
  state.fail("investigation-assignment", id, cause);
45
51
  }
46
52
  finally {