gdharness 1.2.5 → 1.2.7

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/build/cli.js CHANGED
@@ -8129,7 +8129,7 @@ function alive(pid) {
8129
8129
  var init_alive = () => {};
8130
8130
 
8131
8131
  // src/scratch.ts
8132
- import { existsSync as existsSync6, mkdtempSync, readdirSync as readdirSync2, rmSync as rmSync4 } from "node:fs";
8132
+ import { existsSync as existsSync6, mkdtempSync, readdirSync as readdirSync3, rmSync as rmSync4 } from "node:fs";
8133
8133
  import { tmpdir } from "node:os";
8134
8134
  import { join as join6 } from "node:path";
8135
8135
  import process6 from "node:process";
@@ -8139,7 +8139,7 @@ function scratchDirectory(kind) {
8139
8139
  function sweepAbandonedScratch(directory = tmpdir()) {
8140
8140
  let entries;
8141
8141
  try {
8142
- entries = readdirSync2(directory);
8142
+ entries = readdirSync3(directory);
8143
8143
  } catch {
8144
8144
  return;
8145
8145
  }
@@ -9461,7 +9461,7 @@ var init_gdscript_source = __esm(() => {
9461
9461
  });
9462
9462
 
9463
9463
  // src/class-cache.ts
9464
- import { existsSync as existsSync9, readdirSync as readdirSync3, readFileSync as readFileSync7, statSync as statSync4 } from "node:fs";
9464
+ import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync7, statSync as statSync4 } from "node:fs";
9465
9465
  import { join as join9, posix } from "node:path";
9466
9466
  function isToolScript(source) {
9467
9467
  return TOOL.test(codeOf(source));
@@ -9481,7 +9481,7 @@ function eachScript(projectPath, each) {
9481
9481
  if (existsSync9(join9(directory, ".gdignore"))) {
9482
9482
  return;
9483
9483
  }
9484
- for (const entry of readdirSync3(directory, { withFileTypes: true })) {
9484
+ for (const entry of readdirSync4(directory, { withFileTypes: true })) {
9485
9485
  if (entry.name.startsWith(".")) {
9486
9486
  continue;
9487
9487
  }
@@ -17266,7 +17266,7 @@ import {
17266
17266
  cpSync,
17267
17267
  existsSync as existsSync10,
17268
17268
  mkdirSync as mkdirSync4,
17269
- readdirSync as readdirSync4,
17269
+ readdirSync as readdirSync5,
17270
17270
  readFileSync as readFileSync9,
17271
17271
  rmdirSync,
17272
17272
  rmSync as rmSync5,
@@ -17284,7 +17284,7 @@ function runtimeAddonDigest(from = shippedAddonsDirectory()) {
17284
17284
  function addonsDigest(names, from) {
17285
17285
  const hash = createHash3("sha256");
17286
17286
  const walk = (directory, relative) => {
17287
- for (const name of readdirSync4(directory).sort()) {
17287
+ for (const name of readdirSync5(directory).sort()) {
17288
17288
  if (name === VERSION_MARKER || name === DIGEST_MARKER) {
17289
17289
  continue;
17290
17290
  }
@@ -17386,7 +17386,7 @@ function removeAddons(projectPath) {
17386
17386
  }
17387
17387
  }
17388
17388
  const addons = join10(projectPath, "addons");
17389
- if (removed.length > 0 && existsSync10(addons) && readdirSync4(addons).length === 0) {
17389
+ if (removed.length > 0 && existsSync10(addons) && readdirSync5(addons).length === 0) {
17390
17390
  rmdirSync(addons);
17391
17391
  removed.push(addons);
17392
17392
  }
@@ -33897,7 +33897,7 @@ var init_stdio2 = __esm(() => {
33897
33897
  });
33898
33898
 
33899
33899
  // src/runtime-client.ts
33900
- import { existsSync as existsSync12, readdirSync as readdirSync6, readFileSync as readFileSync11, statSync as statSync6, unlinkSync } from "node:fs";
33900
+ import { existsSync as existsSync12, readdirSync as readdirSync7, readFileSync as readFileSync11, statSync as statSync6, unlinkSync } from "node:fs";
33901
33901
  import { createConnection } from "node:net";
33902
33902
  import { tmpdir as tmpdir3 } from "node:os";
33903
33903
  import { dirname as dirname8, join as join13, resolve as resolve4 } from "node:path";
@@ -34067,7 +34067,7 @@ function announcedIn(directory) {
34067
34067
  const found = [];
34068
34068
  const candidates = [];
34069
34069
  const entries = [];
34070
- for (const entry of readdirSync6(directory)) {
34070
+ for (const entry of readdirSync7(directory)) {
34071
34071
  const report = ERROR_REPORT_PATTERN.exec(entry);
34072
34072
  if (report) {
34073
34073
  sweepErrorReport(join13(directory, entry), Number.parseInt(report[1] ?? "", 10));
@@ -40554,7 +40554,7 @@ var init_process_time = __esm(() => {
40554
40554
  });
40555
40555
 
40556
40556
  // src/project-scan.ts
40557
- import { existsSync as existsSync17, readdirSync as readdirSync7, readFileSync as readFileSync18 } from "node:fs";
40557
+ import { existsSync as existsSync17, readdirSync as readdirSync8, readFileSync as readFileSync18 } from "node:fs";
40558
40558
  import { join as join21 } from "node:path";
40559
40559
  function skipped(name) {
40560
40560
  return name.startsWith(".") || SKIPPED.has(name);
@@ -40568,7 +40568,7 @@ function projectStructure(projectPath) {
40568
40568
  if (steppedOver(directory)) {
40569
40569
  return;
40570
40570
  }
40571
- for (const entry of readdirSync7(directory, { withFileTypes: true })) {
40571
+ for (const entry of readdirSync8(directory, { withFileTypes: true })) {
40572
40572
  if (skipped(entry.name)) {
40573
40573
  continue;
40574
40574
  }
@@ -40597,7 +40597,7 @@ function scriptsWithoutUid(projectPath) {
40597
40597
  if (steppedOver(directory)) {
40598
40598
  return;
40599
40599
  }
40600
- for (const entry of readdirSync7(directory, { withFileTypes: true })) {
40600
+ for (const entry of readdirSync8(directory, { withFileTypes: true })) {
40601
40601
  if (skipped(entry.name)) {
40602
40602
  continue;
40603
40603
  }
@@ -40627,7 +40627,7 @@ function projectTexts(projectPath) {
40627
40627
  if (steppedOver(directory)) {
40628
40628
  return;
40629
40629
  }
40630
- for (const entry of readdirSync7(directory, { withFileTypes: true })) {
40630
+ for (const entry of readdirSync8(directory, { withFileTypes: true })) {
40631
40631
  if (skipped(entry.name)) {
40632
40632
  continue;
40633
40633
  }
@@ -40654,7 +40654,7 @@ function ignoredTexts(projectPath) {
40654
40654
  const found = [];
40655
40655
  const visit = (directory, prefix, ignored) => {
40656
40656
  const under = ignored || steppedOver(directory);
40657
- for (const entry of readdirSync7(directory, { withFileTypes: true })) {
40657
+ for (const entry of readdirSync8(directory, { withFileTypes: true })) {
40658
40658
  if (skipped(entry.name)) {
40659
40659
  continue;
40660
40660
  }
@@ -40691,7 +40691,7 @@ function searchProject(projectPath, options) {
40691
40691
  if (steppedOver(directory)) {
40692
40692
  return;
40693
40693
  }
40694
- for (const entry of readdirSync7(directory, { withFileTypes: true })) {
40694
+ for (const entry of readdirSync8(directory, { withFileTypes: true })) {
40695
40695
  if (full()) {
40696
40696
  return;
40697
40697
  }
@@ -41550,7 +41550,7 @@ var init_rename = __esm(() => {
41550
41550
  });
41551
41551
 
41552
41552
  // src/rename-symbol.ts
41553
- import { existsSync as existsSync19, mkdirSync as mkdirSync12, readdirSync as readdirSync8, realpathSync as realpathSync5, rmSync as rmSync10, writeFileSync as writeFileSync14 } from "node:fs";
41553
+ import { existsSync as existsSync19, mkdirSync as mkdirSync12, readdirSync as readdirSync9, realpathSync as realpathSync5, rmSync as rmSync10, writeFileSync as writeFileSync14 } from "node:fs";
41554
41554
  import { basename as basename5, dirname as dirname16, join as join22, relative as relative4, resolve as resolve6 } from "node:path";
41555
41555
  function resourcePathOf(projectPath, absolute) {
41556
41556
  const inside = relative4(onDiskSpelling(projectPath), onDiskSpelling(absolute));
@@ -41998,7 +41998,7 @@ function writeLeftAloneDetail(projectPath, symbol, detail) {
41998
41998
  const path = join22(directory, `${String(Date.now())}-${String(detailWrites).padStart(6, "0")}-${String(process.pid)}-${symbol}.json`);
41999
41999
  writeFileSync14(path, `${JSON.stringify(detail, null, 2)}
42000
42000
  `, "utf8");
42001
- const kept = readdirSync8(directory).filter((name) => name.endsWith(".json")).sort().reverse();
42001
+ const kept = readdirSync9(directory).filter((name) => name.endsWith(".json")).sort().reverse();
42002
42002
  for (const old of kept.slice(10)) {
42003
42003
  rmSync10(join22(directory, old), { force: true });
42004
42004
  }
@@ -42087,7 +42087,7 @@ import { createHash as createHash4 } from "node:crypto";
42087
42087
  import {
42088
42088
  mkdirSync as mkdirSync14,
42089
42089
  openSync as openSync2,
42090
- readdirSync as readdirSync9,
42090
+ readdirSync as readdirSync10,
42091
42091
  readFileSync as readFileSync21,
42092
42092
  realpathSync as realpathSync6,
42093
42093
  rmSync as rmSync12,
@@ -42213,7 +42213,7 @@ function everyRunRecord() {
42213
42213
  for (const directory of runtimeDirectories()) {
42214
42214
  let entries;
42215
42215
  try {
42216
- entries = readdirSync9(join24(directory, "runs"));
42216
+ entries = readdirSync10(join24(directory, "runs"));
42217
42217
  } catch {
42218
42218
  continue;
42219
42219
  }
@@ -42454,7 +42454,7 @@ function sweepTranscripts(keepMs = 24 * 60 * 60 * 1000, now = Date.now()) {
42454
42454
  ]));
42455
42455
  let entries;
42456
42456
  try {
42457
- entries = readdirSync9(directory);
42457
+ entries = readdirSync10(directory);
42458
42458
  } catch {
42459
42459
  return;
42460
42460
  }
@@ -42721,7 +42721,7 @@ function callersOf(totals, name, scripts) {
42721
42721
  sites.sort((a, b) => (b.withinTotalMs ?? -1) - (a.withinTotalMs ?? -1) || a.script.localeCompare(b.script) || a.line - b.line);
42722
42722
  return { target, sites: sites.slice(0, CALL_SITES), omitted: Math.max(0, sites.length - CALL_SITES) };
42723
42723
  }
42724
- var QUEUE_SETTING = "limits/debugger/max_queued_messages", QUEUE_DEFAULT = 2048, QUEUE_HEADROOM = 512, UNNAMED_PREFIX = "#", ms = (seconds) => Math.round(seconds * 1e6) / 1000, RUNTIME_SCRIPT = "gdharness_runtime/runtime_autoload.gd", PROFILER_PROBE = "_profiler_probe", PROFILER_CALIBRATOR = "_calibrate_the_profiler", CALL_SITES = 40;
42724
+ var QUEUE_SETTING = "limits/debugger/max_queued_messages", QUEUE_DEFAULT = 2048, QUEUE_HEADROOM = 512, UNNAMED_PREFIX = "#", PROFILE_FROM_START = "GDHARNESS_PROFILE_FROM_START", ms = (seconds) => Math.round(seconds * 1e6) / 1000, RUNTIME_SCRIPT = "gdharness_runtime/runtime_autoload.gd", PROFILER_PROBE = "_profiler_probe", PROFILER_CALIBRATOR = "_calibrate_the_profiler", CALL_SITES = 40;
42725
42725
  var init_script_profile = __esm(() => {
42726
42726
  init_gdscript_source();
42727
42727
  init_godot_variant();
@@ -42740,7 +42740,7 @@ import {
42740
42740
  fstatSync,
42741
42741
  mkdirSync as mkdirSync15,
42742
42742
  openSync as openSync3,
42743
- readdirSync as readdirSync10,
42743
+ readdirSync as readdirSync11,
42744
42744
  readFileSync as readFileSync23,
42745
42745
  readSync as readSync2,
42746
42746
  rmdirSync as rmdirSync2,
@@ -43624,7 +43624,7 @@ function elsewhereIn(projectPath, asked) {
43624
43624
  const root = (wanted.split("/")[0] ?? "").toLowerCase();
43625
43625
  let near = [];
43626
43626
  try {
43627
- near = readdirSync10(projectPath, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.toLowerCase() !== root).map((entry) => entry.name).filter((name) => name.toLowerCase().startsWith("test") || root.startsWith(name.toLowerCase()));
43627
+ near = readdirSync11(projectPath, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.toLowerCase() !== root).map((entry) => entry.name).filter((name) => name.toLowerCase().startsWith("test") || root.startsWith(name.toLowerCase()));
43628
43628
  } catch {
43629
43629
  return "";
43630
43630
  }
@@ -43718,7 +43718,7 @@ function scriptsUnder(directory, prefix) {
43718
43718
  return [];
43719
43719
  }
43720
43720
  const found = [];
43721
- for (const entry of readdirSync10(directory, { withFileTypes: true }).sort((a, b) => a.name < b.name ? -1 : 1)) {
43721
+ for (const entry of readdirSync11(directory, { withFileTypes: true }).sort((a, b) => a.name < b.name ? -1 : 1)) {
43722
43722
  if (entry.name.startsWith(".")) {
43723
43723
  continue;
43724
43724
  }
@@ -45393,7 +45393,7 @@ class GodotServer {
45393
45393
  let report = null;
45394
45394
  let reportProblem = null;
45395
45395
  try {
45396
- const written = existsSync20(reportsDir) ? readdirSync10(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
45396
+ const written = existsSync20(reportsDir) ? readdirSync11(reportsDir).filter((name) => name.startsWith("report_")).sort((a, b) => Number(a.slice("report_".length)) - Number(b.slice("report_".length))) : [];
45397
45397
  const newest = written.at(-1);
45398
45398
  if (newest !== undefined) {
45399
45399
  report = parseJUnit(readFileSync23(join26(reportsDir, newest, "results.xml"), "utf8"));
@@ -46929,10 +46929,11 @@ class GodotServer {
46929
46929
  const startedAt = Date.now();
46930
46930
  const transcript = openTranscript(startedAt);
46931
46931
  closeSync2(transcript.fd);
46932
+ const gameEnv = profiled ? { ...env ?? process.env, [PROFILE_FROM_START]: "1" } : env;
46932
46933
  const launched = await launchOutsideTheTree({
46933
46934
  command: godotPath,
46934
46935
  args: cmdArgs,
46935
- ...env === undefined ? {} : { env },
46936
+ ...gameEnv === undefined ? {} : { env: gameEnv },
46936
46937
  run: {
46937
46938
  transcript: transcript.path,
46938
46939
  startedAt,
@@ -48822,7 +48823,7 @@ import { existsSync as existsSync21 } from "node:fs";
48822
48823
  import { join as join27, resolve as resolve8 } from "node:path";
48823
48824
 
48824
48825
  // src/harnesses.ts
48825
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
48826
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync as readdirSync2, readFileSync as readFileSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
48826
48827
  import { homedir as homedir2 } from "node:os";
48827
48828
  import { basename as basename2, dirname as dirname3, join as join4, relative as relative2, resolve as resolve2 } from "node:path";
48828
48829
  import process4 from "node:process";
@@ -49569,6 +49570,30 @@ function mainCheckoutOf(projectPath) {
49569
49570
  const main = join4(dirname3(common), relative2(top, resolve2(projectPath)));
49570
49571
  return isSameDirectory(main, projectPath) || !existsSync4(join4(main, "project.godot")) ? null : main;
49571
49572
  }
49573
+ function worktreeCheckoutsOf(projectPath) {
49574
+ let top = resolve2(projectPath);
49575
+ while (!existsSync4(join4(top, ".git"))) {
49576
+ const up = dirname3(top);
49577
+ if (up === top) {
49578
+ return [];
49579
+ }
49580
+ top = up;
49581
+ }
49582
+ const listed = join4(top, ".git", "worktrees");
49583
+ if (!statSync2(join4(top, ".git")).isDirectory() || !existsSync4(listed)) {
49584
+ return [];
49585
+ }
49586
+ const below = relative2(top, resolve2(projectPath));
49587
+ return readdirSync2(listed).flatMap((name) => {
49588
+ const pointer = join4(listed, name, "gitdir");
49589
+ if (!existsSync4(pointer)) {
49590
+ return [];
49591
+ }
49592
+ const checkout = dirname3(resolve2(listed, name, readFileSync2(pointer, "utf8").trim()));
49593
+ const project = join4(checkout, below);
49594
+ return existsSync4(join4(project, "project.godot")) ? [project] : [];
49595
+ });
49596
+ }
49572
49597
  function entryEnvironment(harness, projectPath) {
49573
49598
  if (harness.toml || harness.yaml || harness.snippet) {
49574
49599
  return;
@@ -49760,7 +49785,7 @@ init_setup();
49760
49785
  init_setup();
49761
49786
  init_tool_definitions();
49762
49787
  init_tool_reference();
49763
- import { existsSync as existsSync11, mkdirSync as mkdirSync5, readdirSync as readdirSync5, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "node:fs";
49788
+ import { existsSync as existsSync11, mkdirSync as mkdirSync5, readdirSync as readdirSync6, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "node:fs";
49764
49789
  import { basename as basename4, dirname as dirname6, join as join11 } from "node:path";
49765
49790
  var SKILL_NAME = "gdharness";
49766
49791
  var SHARED_SKILLS = join11(".agents", "skills");
@@ -50007,7 +50032,7 @@ function pruneEmpty(directory, projectPath) {
50007
50032
  const shared = join11(projectPath, ".agents");
50008
50033
  let path = directory;
50009
50034
  while (path !== projectPath && (basename4(path) === "skills" || path === shared)) {
50010
- if (readdirSync5(path).length > 0) {
50035
+ if (readdirSync6(path).length > 0) {
50011
50036
  return;
50012
50037
  }
50013
50038
  rmSync6(path, { recursive: true, force: true });
@@ -50360,6 +50385,17 @@ On ${version}. What is left for you:`);
50360
50385
  ` + " editor_launch restart tool, which closes and reopens the window.");
50361
50386
  const serving = await serverServing(projectPath);
50362
50387
  console.log(harnessNote({ moved, written, byHand }, [launch.command, ...launch.args].join(" "), serving === null ? null : { server: serving, isThisVersion: serving.version === version }));
50388
+ const trailing = worktreeCheckoutsOf(projectPath).flatMap((path) => {
50389
+ const addon = inspectProject(path).addons.find((one) => one.installed);
50390
+ return addon === undefined || addon.version === version ? [] : [{ path, version: addon.version }];
50391
+ });
50392
+ if (trailing.length > 0) {
50393
+ console.log(`
50394
+ Git worktrees of this project keep untracked addons of their own, which this upgrade does not reach:`);
50395
+ for (const worktree of trailing) {
50396
+ console.log(` ${worktree.path}: ${worktree.version ?? "an unmarked copy"}. Run gdharness upgrade ${worktree.path}`);
50397
+ }
50398
+ }
50363
50399
  }
50364
50400
  function doctorReport(projectPath) {
50365
50401
  const report = inspectProject(projectPath);
@@ -22,6 +22,9 @@ const DEBUGGER_CLASS: String = "ScriptEditorDebugger"
22
22
  const PROFILE_CAPTURE: String = "gdharness"
23
23
  const PROFILE_SENT: String = "gdharness:profile_sent"
24
24
  const PROFILE_RECEIVED: String = "gdharness:profile_received"
25
+ ## Set in the environment a played game inherits, when the play is to be profiled from its start.
26
+ ## Kept in step with the runtime addon's runtime_autoload.gd.
27
+ const PROFILE_FROM_START: String = "GDHARNESS_PROFILE_FROM_START"
25
28
 
26
29
 
27
30
  ## The editor's debugger sessions, numbered as the editor numbers its debugger tabs.
@@ -106,6 +109,10 @@ func profile_start(args: Dictionary) -> Dictionary:
106
109
  _frame_functions = asked if asked > 0 else FRAME_FUNCTIONS
107
110
  if Read.as_bool(args.get("arm", false)):
108
111
  _armed = true
112
+ # The game the editor starts next inherits the editor's environment, and this tells its
113
+ # runtime addon to hold its start until the profiler is on, which the session's start
114
+ # switches on with a message the game reads only on a later poll.
115
+ OS.set_environment(PROFILE_FROM_START, "1")
109
116
  return {"ok": true, "started": false, "armed": true, "session": -1}
110
117
  var active: int = _active_session()
111
118
  if active < 0:
@@ -137,6 +144,7 @@ func profile_read(_args: Dictionary) -> Dictionary:
137
144
 
138
145
  func _reset() -> void:
139
146
  _armed = false
147
+ OS.unset_environment(PROFILE_FROM_START)
140
148
  _session = -1
141
149
  _frames = 0
142
150
  _complete = false
@@ -172,6 +180,8 @@ func _on_session_started(session_id: int) -> void:
172
180
  _reset()
173
181
  return
174
182
  _armed = false
183
+ # The game has started with it by now, and a later play must not.
184
+ OS.unset_environment(PROFILE_FROM_START)
175
185
  if _hook() > 0:
176
186
  _switch_on(session_id)
177
187
 
@@ -47,6 +47,13 @@ const PROFILER_PROBE_CALLS: int = 10000
47
47
  ## on every 2048th call and only counts the others.
48
48
  const POLLS_PER_READ: int = 2048
49
49
 
50
+ ## Set in a game's environment by whatever starts it to be profiled from its start: the server for
51
+ ## a run it spawns, the editor for a play. Kept in step with `PROFILE_FROM_START` in the server.
52
+ const PROFILE_FROM_START: String = "GDHARNESS_PROFILE_FROM_START"
53
+
54
+ ## How long such a game waits for its debugger to switch the profiler on before carrying on.
55
+ const PROFILER_WAIT_MS: int = 5000
56
+
50
57
  ## How the engine is told to run a script instead of the game: `godot -s thing.gd`.
51
58
  const SCRIPT_FLAGS: PackedStringArray = ["-s", "--script"]
52
59
 
@@ -134,6 +141,37 @@ func _init() -> void:
134
141
  "wait_signal": _waits.wait_signal,
135
142
  "wait_until": _waits.wait_until,
136
143
  }
144
+ _wait_for_the_profiler()
145
+
146
+
147
+ ## Holds the game's start until the profiler is on, when whatever started the game asked for a
148
+ ## profile from its start. The debugger switches the profiler on with a message the game reads only
149
+ ## on a poll, which comes every [constant POLLS_PER_READ] lines of script, so the main scene's _ready
150
+ ## could run first: a game played on a macOS runner counted 25 calls of a function called 26 times,
151
+ ## the first of them from _ready. Run at the autoload's construction, before the main scene loads.
152
+ func _wait_for_the_profiler() -> void:
153
+ if OS.get_environment(PROFILE_FROM_START).is_empty():
154
+ return
155
+ # Read once: a process this game starts inherits its environment and must not wait as well.
156
+ OS.unset_environment(PROFILE_FROM_START)
157
+ if not EngineDebugger.is_active():
158
+ return
159
+ var deadline: int = Time.get_ticks_msec() + PROFILER_WAIT_MS
160
+ while not EngineDebugger.is_profiling("servers"):
161
+ if Time.get_ticks_msec() >= deadline:
162
+ push_warning(
163
+ (
164
+ (
165
+ "gdharness: this game was started to be profiled from its start, and the profiler"
166
+ + " was not on %d ms later, so what ran before it is not counted"
167
+ )
168
+ % PROFILER_WAIT_MS
169
+ )
170
+ )
171
+ return
172
+ for _poll: int in POLLS_PER_READ:
173
+ EngineDebugger.line_poll()
174
+ OS.delay_msec(1)
137
175
 
138
176
 
139
177
  func _ready() -> void:
package/build/index.js CHANGED
@@ -33393,6 +33393,7 @@ function queuedMessagesOf(projectGodot) {
33393
33393
  return typeof set === "number" && Number.isInteger(set) && set > 0 ? set : QUEUE_DEFAULT;
33394
33394
  }
33395
33395
  var UNNAMED_PREFIX = "#";
33396
+ var PROFILE_FROM_START = "GDHARNESS_PROFILE_FROM_START";
33396
33397
  function signatureParts(signature) {
33397
33398
  const parts = signature.split("::");
33398
33399
  if (parts.length < 3) {
@@ -39426,10 +39427,11 @@ class GodotServer {
39426
39427
  const startedAt = Date.now();
39427
39428
  const transcript = openTranscript(startedAt);
39428
39429
  closeSync2(transcript.fd);
39430
+ const gameEnv = profiled ? { ...env ?? process.env, [PROFILE_FROM_START]: "1" } : env;
39429
39431
  const launched = await launchOutsideTheTree({
39430
39432
  command: godotPath,
39431
39433
  args: cmdArgs,
39432
- ...env === undefined ? {} : { env },
39434
+ ...gameEnv === undefined ? {} : { env: gameEnv },
39433
39435
  run: {
39434
39436
  transcript: transcript.path,
39435
39437
  startedAt,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdharness",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "mcpName": "io.github.Aureliolo/gdharness",
5
5
  "description": "A harness for driving a Godot 4 project from an agent: editor addons, a runtime bridge into the running game, an MCP server in front of them, and a CLI that installs and diagnoses the Godot side.",
6
6
  "type": "module",