@amaster.ai/employee-runtime-connector 0.1.1-beta.10 → 0.1.1-beta.12

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.
@@ -3,7 +3,7 @@
3
3
 
4
4
  // src/amaster-runtime-daemon.mjs
5
5
  import { createHash as createHash13 } from "node:crypto";
6
- import { chmodSync as chmodSync6, copyFileSync as copyFileSync3, existsSync as existsSync14, lstatSync as lstatSync7, mkdirSync as mkdirSync9, mkdtempSync, readFileSync as readFileSync11, readdirSync as readdirSync9, realpathSync as realpathSync5, renameSync as renameSync6, rmSync as rmSync7, statSync as statSync7, symlinkSync as symlinkSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "node:fs";
6
+ import { chmodSync as chmodSync6, copyFileSync as copyFileSync3, existsSync as existsSync14, lstatSync as lstatSync7, mkdirSync as mkdirSync9, mkdtempSync, readFileSync as readFileSync11, readdirSync as readdirSync9, realpathSync as realpathSync5, renameSync as renameSync6, rmSync as rmSync7, statSync as statSync8, symlinkSync as symlinkSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "node:fs";
7
7
  import { arch as arch3, homedir as homedir3, hostname as hostname2, platform as platform3, tmpdir } from "node:os";
8
8
  import { basename as basename6, delimiter as delimiter3, dirname as dirname9, extname as extname2, isAbsolute as isAbsolute8, join as join15, relative as relative9, resolve as resolve12 } from "node:path";
9
9
  import { spawn as spawn2, spawnSync as spawnSync6 } from "node:child_process";
@@ -3021,6 +3021,7 @@ function createManagedPiMcpProfileApi(options = {}) {
3021
3021
  throw new Error("pi_managed_mcp_source_acquisition_extension_missing");
3022
3022
  }
3023
3023
  copyPrivateFile(join4(source, "models.json"), join4(agentDir, "models.json"));
3024
+ copyPrivateFile(join4(source, "SYSTEM.md"), join4(agentDir, "SYSTEM.md"));
3024
3025
  const authSource = join4(source, "auth.json");
3025
3026
  const protectedValues = [];
3026
3027
  if (copyPrivateFile(authSource, join4(agentDir, "auth.json"))) {
@@ -7073,13 +7074,27 @@ function createRuntimeArtifactIngestQueue({ ingest, onError }) {
7073
7074
 
7074
7075
  // src/amaster-runtime-daemon/workspace-guard.mjs
7075
7076
  import { createHash as createHash6 } from "node:crypto";
7076
- import { existsSync as existsSync7, mkdirSync as mkdirSync6, realpathSync as realpathSync4, statSync as statSync3 } from "node:fs";
7077
+ import { existsSync as existsSync7, mkdirSync as mkdirSync6, realpathSync as realpathSync4, statSync as statSync4 } from "node:fs";
7077
7078
  import { basename as basename4, join as join8, isAbsolute as isAbsolute4, relative as relative4, resolve as resolve4 } from "node:path";
7078
7079
 
7079
7080
  // src/amaster-runtime-daemon/workspace-manifest.mjs
7080
- import { existsSync as existsSync6, readFileSync as readFileSync7, renameSync as renameSync4, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "node:fs";
7081
+ import { chownSync, existsSync as existsSync6, readFileSync as readFileSync7, renameSync as renameSync4, rmSync as rmSync4, statSync as statSync3, writeFileSync as writeFileSync6 } from "node:fs";
7081
7082
  import { basename as basename3, dirname as dirname5, join as join7 } from "node:path";
7082
7083
  var WORKSPACE_MANIFEST_FILENAME = ".amaster-runtime.json";
7084
+ function syncManifestDirOwnership(manifestPath, deps = {}) {
7085
+ const stat = deps.statSync ?? statSync3;
7086
+ const chown = deps.chownSync ?? chownSync;
7087
+ const geteuid = deps.geteuid ?? (typeof process.geteuid === "function" ? process.geteuid.bind(process) : () => null);
7088
+ try {
7089
+ if (geteuid() !== 0) return false;
7090
+ const dirStat = stat(dirname5(manifestPath));
7091
+ if (dirStat.uid === 0 && dirStat.gid === 0) return false;
7092
+ chown(manifestPath, dirStat.uid, dirStat.gid);
7093
+ return true;
7094
+ } catch {
7095
+ return false;
7096
+ }
7097
+ }
7083
7098
  function nowIso() {
7084
7099
  return (/* @__PURE__ */ new Date()).toISOString();
7085
7100
  }
@@ -7098,7 +7113,7 @@ function readWorkspaceManifest(manifestPath) {
7098
7113
  return null;
7099
7114
  }
7100
7115
  }
7101
- function writeWorkspaceManifest(manifestPath, manifest) {
7116
+ function writeWorkspaceManifest(manifestPath, manifest, deps) {
7102
7117
  const tempPath = join7(
7103
7118
  dirname5(manifestPath),
7104
7119
  `.${basename3(manifestPath)}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`
@@ -7107,6 +7122,7 @@ function writeWorkspaceManifest(manifestPath, manifest) {
7107
7122
  writeFileSync6(tempPath, `${JSON.stringify(manifest, null, 2)}
7108
7123
  `, { mode: 384 });
7109
7124
  renameSync4(tempPath, manifestPath);
7125
+ syncManifestDirOwnership(manifestPath, deps);
7110
7126
  } catch (err) {
7111
7127
  rmSync4(tempPath, { force: true });
7112
7128
  throw err;
@@ -7177,7 +7193,7 @@ function resolveWorkspaceCwd(config, command) {
7177
7193
  if (!allowed) {
7178
7194
  throw new Error(`Workspace path is outside AMASTER_WORKSPACE_ALLOWLIST: ${cwd}`);
7179
7195
  }
7180
- if (!existsSync7(cwd) || !statSync3(cwd).isDirectory()) {
7196
+ if (!existsSync7(cwd) || !statSync4(cwd).isDirectory()) {
7181
7197
  throw new Error(`Workspace path does not exist or is not a directory: ${cwd}`);
7182
7198
  }
7183
7199
  return cwd;
@@ -7247,7 +7263,7 @@ function resolveExecutionWorkspace(config, command, opts = {}) {
7247
7263
  }
7248
7264
 
7249
7265
  // src/amaster-runtime-daemon/workspace-gc.mjs
7250
- import { existsSync as existsSync8, readdirSync as readdirSync4, statSync as statSync4 } from "node:fs";
7266
+ import { existsSync as existsSync8, readdirSync as readdirSync4, statSync as statSync5 } from "node:fs";
7251
7267
  import { join as join9, resolve as resolve5 } from "node:path";
7252
7268
  function readIsoTime(value) {
7253
7269
  if (typeof value !== "string" || !value.trim()) return null;
@@ -7289,7 +7305,7 @@ function directorySizeBytes(path) {
7289
7305
  if (!current) continue;
7290
7306
  let stat;
7291
7307
  try {
7292
- stat = statSync4(current, { throwIfNoEntry: false });
7308
+ stat = statSync5(current, { throwIfNoEntry: false });
7293
7309
  } catch {
7294
7310
  continue;
7295
7311
  }
@@ -7375,7 +7391,7 @@ function planManagedWorkspaceGcDryRun(input) {
7375
7391
  }
7376
7392
 
7377
7393
  // src/amaster-runtime-daemon/runtime-status-summary.mjs
7378
- import { existsSync as existsSync9, readdirSync as readdirSync5, statSync as statSync5 } from "node:fs";
7394
+ import { existsSync as existsSync9, readdirSync as readdirSync5, statSync as statSync6 } from "node:fs";
7379
7395
  import { dirname as dirname6, join as join10, resolve as resolve6 } from "node:path";
7380
7396
  function runtimeStatusDirectoryEntries(path) {
7381
7397
  try {
@@ -7392,7 +7408,7 @@ function runtimeStatusDirectorySizeBytes(path) {
7392
7408
  if (!current) continue;
7393
7409
  let stat;
7394
7410
  try {
7395
- stat = statSync5(current, { throwIfNoEntry: false });
7411
+ stat = statSync6(current, { throwIfNoEntry: false });
7396
7412
  } catch {
7397
7413
  continue;
7398
7414
  }
@@ -7630,13 +7646,13 @@ function summarizeAmasterRuntimeVersionDrift(input = {}) {
7630
7646
  import { createHash as createHash7 } from "node:crypto";
7631
7647
  import {
7632
7648
  chmodSync as chmodSync3,
7633
- chownSync,
7649
+ chownSync as chownSync2,
7634
7650
  lchownSync,
7635
7651
  lstatSync as lstatSync4,
7636
7652
  readdirSync as readdirSync6
7637
7653
  } from "node:fs";
7638
7654
  import { resolve as resolve7, sep } from "node:path";
7639
- var defaultFs = { chmodSync: chmodSync3, chownSync, lchownSync, lstatSync: lstatSync4, readdirSync: readdirSync6 };
7655
+ var defaultFs = { chmodSync: chmodSync3, chownSync: chownSync2, lchownSync, lstatSync: lstatSync4, readdirSync: readdirSync6 };
7640
7656
  function defaultHashRunId(runId) {
7641
7657
  return Number.parseInt(createHash7("sha256").update(runId).digest("hex").slice(0, 8), 16);
7642
7658
  }
@@ -7765,7 +7781,7 @@ function preparePiChildIsolation(input) {
7765
7781
  import { createHash as createHash8 } from "node:crypto";
7766
7782
  import {
7767
7783
  chmodSync as chmodSync4,
7768
- chownSync as chownSync2,
7784
+ chownSync as chownSync3,
7769
7785
  existsSync as existsSync10,
7770
7786
  lchownSync as lchownSync2,
7771
7787
  lstatSync as lstatSync5,
@@ -7785,7 +7801,7 @@ var DEFAULT_GID_BASE = 1e5;
7785
7801
  var DEFAULT_GID_SPAN = 1e6;
7786
7802
  var defaultFs2 = {
7787
7803
  chmodSync: chmodSync4,
7788
- chownSync: chownSync2,
7804
+ chownSync: chownSync3,
7789
7805
  existsSync: existsSync10,
7790
7806
  lchownSync: lchownSync2,
7791
7807
  lstatSync: lstatSync5,
@@ -8528,7 +8544,7 @@ function verifyTrustedPiRuntimeAssertion(input) {
8528
8544
  // src/amaster-runtime-daemon/workspace-status.mjs
8529
8545
  import { spawnSync as spawnSync4 } from "node:child_process";
8530
8546
  import { createHash as createHash10 } from "node:crypto";
8531
- import { existsSync as existsSync12, readdirSync as readdirSync8, readFileSync as readFileSync10, statSync as statSync6 } from "node:fs";
8547
+ import { existsSync as existsSync12, readdirSync as readdirSync8, readFileSync as readFileSync10, statSync as statSync7 } from "node:fs";
8532
8548
  import { basename as basename5, extname, isAbsolute as isAbsolute7, join as join13, relative as relative7, resolve as resolve10 } from "node:path";
8533
8549
  var WORKSPACE_RUNTIME_SERVICES_FILENAME = ".amaster-runtime-services.json";
8534
8550
  var ARTIFACT_EXTENSIONS = /* @__PURE__ */ new Map([
@@ -8661,7 +8677,7 @@ function scanArtifactCandidates(cwd, opts = {}) {
8661
8677
  const type = ARTIFACT_EXTENSIONS.get(ext) ?? "file";
8662
8678
  let stat;
8663
8679
  try {
8664
- stat = statSync6(fullPath);
8680
+ stat = statSync7(fullPath);
8665
8681
  } catch {
8666
8682
  continue;
8667
8683
  }
@@ -9394,7 +9410,7 @@ function assertSourceAcquisitionRuntimeAuthority({
9394
9410
  }
9395
9411
 
9396
9412
  // src/amaster-runtime-daemon.mjs
9397
- var CONNECTOR_VERSION = "0.1.1-beta.10";
9413
+ var CONNECTOR_VERSION = "0.1.1-beta.12";
9398
9414
  var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
9399
9415
  var SOURCE_ACQUISITION_CAPABILITY = "source_acquisition_v1";
9400
9416
  var SOURCE_ACQUISITION_PROFILE_VERSION = "source_acquisition_v1";
@@ -9681,7 +9697,7 @@ function safeDirectorySummary(pathValue) {
9681
9697
  return { configured: false, available: false, entryCount: 0 };
9682
9698
  }
9683
9699
  try {
9684
- const stat = statSync7(pathValue);
9700
+ const stat = statSync8(pathValue);
9685
9701
  if (!stat.isDirectory()) {
9686
9702
  return { configured: true, available: false, entryCount: 0, reason: "not_directory" };
9687
9703
  }
@@ -9715,7 +9731,7 @@ function safeSkillRootSummary(kind, source, pathValue) {
9715
9731
  if (name.startsWith(".")) continue;
9716
9732
  const skillDir = join15(pathValue, name);
9717
9733
  try {
9718
- if (!statSync7(skillDir).isDirectory()) continue;
9734
+ if (!statSync8(skillDir).isDirectory()) continue;
9719
9735
  if (!existsSync14(join15(skillDir, "SKILL.md"))) continue;
9720
9736
  skillCount += 1;
9721
9737
  if (skillCount >= MAX_PI_CAPABILITY_SOURCE_ENTRIES) {
@@ -9744,7 +9760,7 @@ function safeJsonConfigSummary(source, pathValue, counter) {
9744
9760
  return { source, configured: false, available: false, parseable: false };
9745
9761
  }
9746
9762
  try {
9747
- const stat = statSync7(pathValue);
9763
+ const stat = statSync8(pathValue);
9748
9764
  if (!stat.isFile()) {
9749
9765
  return { source, configured: true, available: false, parseable: false, reason: "not_file" };
9750
9766
  }
@@ -10065,8 +10081,10 @@ function buildHeartbeatPayload(config, options = {}) {
10065
10081
  const desktopPlatformCredential = desktopPlatformCredentialStatus(config);
10066
10082
  const headedBrowserAuth = browserCapabilityStatus(config, "headed_browser_auth");
10067
10083
  const sourceAcquisition = sourceAcquisitionRuntimeReadiness(config);
10084
+ const status = options.status === "offline" ? "offline" : "online";
10085
+ const daemonStatus = status === "offline" ? "stopping" : "running";
10068
10086
  return {
10069
- status: "online",
10087
+ status,
10070
10088
  workspaceBindings: config.workspaceBindings,
10071
10089
  networkDomains: config.networkDomains,
10072
10090
  executors: config.executors,
@@ -10078,8 +10096,9 @@ function buildHeartbeatPayload(config, options = {}) {
10078
10096
  arch: process.arch,
10079
10097
  ...trustedPiRuntimeProvenancePayload(config),
10080
10098
  runtimeStatus: {
10081
- daemon: "running",
10099
+ daemon: daemonStatus,
10082
10100
  pid: process.pid,
10101
+ ...status === "offline" ? { offlineReason: readString(options.offlineReason) ?? "daemon_shutdown" } : {},
10083
10102
  ...heartbeatMode === "diagnostic" ? { heartbeatMode: "diagnostic" } : {},
10084
10103
  ...diagnosticSource ? { diagnosticSource } : {},
10085
10104
  ...orphanCheck === "startup" ? { orphanCheck: "startup" } : {},
@@ -10349,7 +10368,11 @@ async function register(config, options = {}) {
10349
10368
  async function heartbeat(config, options = {}) {
10350
10369
  const connectorId = requireConnectorId(config);
10351
10370
  const mode = heartbeatLogMode(options.logMode) || heartbeatLogMode(process.env.AMASTER_HEARTBEAT_LOG_MODE) || "compact";
10352
- const payload = buildHeartbeatPayload(config, { orphanCheck: options.orphanCheck });
10371
+ const payload = buildHeartbeatPayload(config, {
10372
+ orphanCheck: options.orphanCheck,
10373
+ status: options.status,
10374
+ offlineReason: options.offlineReason
10375
+ });
10353
10376
  writeLocalRuntimeStatus(config, payload.runtimeStatus);
10354
10377
  const body = await postJson(
10355
10378
  config,
@@ -10361,6 +10384,38 @@ async function heartbeat(config, options = {}) {
10361
10384
  `);
10362
10385
  return body;
10363
10386
  }
10387
+ async function reportOfflineHeartbeat(config, reason) {
10388
+ if (!readString(config.connectorId)) {
10389
+ return;
10390
+ }
10391
+ await heartbeat(config, {
10392
+ logMode: "compact",
10393
+ status: "offline",
10394
+ offlineReason: reason
10395
+ });
10396
+ }
10397
+ var shutdownHeartbeatInFlight = false;
10398
+ function installShutdownHeartbeatHandlers() {
10399
+ const shutdown = (signal) => {
10400
+ if (shutdownHeartbeatInFlight) return;
10401
+ shutdownHeartbeatInFlight = true;
10402
+ const exitCode = signal === "SIGINT" ? 130 : 0;
10403
+ const timeout = setTimeout(() => process.exit(exitCode), 3e3);
10404
+ timeout.unref?.();
10405
+ const latestConfig = buildConfig(process.env, {});
10406
+ reportOfflineHeartbeat(latestConfig, signal.toLowerCase()).catch((err) => {
10407
+ const message = err instanceof Error ? err.stack || err.message : String(err);
10408
+ process.stderr.write(`AMaster daemon offline heartbeat failed during ${signal}; exiting anyway:
10409
+ ${message}
10410
+ `);
10411
+ }).finally(() => {
10412
+ clearTimeout(timeout);
10413
+ process.exit(exitCode);
10414
+ });
10415
+ };
10416
+ process.once("SIGTERM", () => shutdown("SIGTERM"));
10417
+ process.once("SIGINT", () => shutdown("SIGINT"));
10418
+ }
10364
10419
  function activeRunHeartbeatIntervalMs(config) {
10365
10420
  const configured = Number(config.pollIntervalSeconds);
10366
10421
  const baseMs = Number.isFinite(configured) && configured > 0 ? configured * 1e3 : 1e4;
@@ -13685,7 +13740,7 @@ async function materializeIssueCheckpoint(config, command, workspace) {
13685
13740
  }
13686
13741
  if (!existsSync14(sourceCandidate)) throw new Error(`issue checkpoint file is missing: ${relativePath}`);
13687
13742
  const source = realpathSync5(sourceCandidate);
13688
- if (!pathWithin2(source, filesRoot) || !statSync7(source).isFile()) {
13743
+ if (!pathWithin2(source, filesRoot) || !statSync8(source).isFile()) {
13689
13744
  throw new Error(`issue checkpoint source escapes its storage root: ${relativePath}`);
13690
13745
  }
13691
13746
  const expectedSha256 = readString(file.sha256);
@@ -13693,7 +13748,7 @@ async function materializeIssueCheckpoint(config, command, workspace) {
13693
13748
  if (!expectedSha256 || expectedByteSize === null || expectedByteSize <= 0) {
13694
13749
  throw new Error(`issue checkpoint evidence is incomplete: ${relativePath}`);
13695
13750
  }
13696
- if (hashFileSha256(source) !== expectedSha256 || statSync7(source).size !== expectedByteSize) {
13751
+ if (hashFileSha256(source) !== expectedSha256 || statSync8(source).size !== expectedByteSize) {
13697
13752
  throw new Error(`issue checkpoint integrity mismatch: ${relativePath}`);
13698
13753
  }
13699
13754
  totalBytes += expectedByteSize;
@@ -13746,12 +13801,12 @@ async function saveIssueCheckpoint(config, command, workspace, candidates) {
13746
13801
  for (const candidate of candidates.slice(0, 20)) {
13747
13802
  const relativePath = safeCheckpointRelativePath(candidate.rawPath);
13748
13803
  const source = readString(candidate.filePath);
13749
- if (!relativePath || !source || !existsSync14(source) || !statSync7(source).isFile()) continue;
13804
+ if (!relativePath || !source || !existsSync14(source) || !statSync8(source).isFile()) continue;
13750
13805
  const ownedSource = realpathSync5(source);
13751
13806
  if (!pathWithin2(ownedSource, workspaceRoot)) {
13752
13807
  throw new Error(`issue checkpoint source escapes its execution workspace: ${relativePath}`);
13753
13808
  }
13754
- const byteSize = statSync7(ownedSource).size;
13809
+ const byteSize = statSync8(ownedSource).size;
13755
13810
  if (byteSize <= 0 || totalBytes + byteSize > MAX_CHECKPOINT_BYTES) continue;
13756
13811
  const target = resolve12(filesDir, relativePath);
13757
13812
  if (!pathWithin2(target, filesDir)) continue;
@@ -14871,7 +14926,11 @@ async function main() {
14871
14926
  `);
14872
14927
  break;
14873
14928
  case "render-heartbeat-payload":
14874
- process.stdout.write(`${JSON.stringify(buildHeartbeatPayload(config, { orphanCheck: flags.orphanCheck ?? flags.orphan_check ?? flags["orphan-check"] }), null, 2)}
14929
+ process.stdout.write(`${JSON.stringify(buildHeartbeatPayload(config, {
14930
+ orphanCheck: flags.orphanCheck ?? flags.orphan_check ?? flags["orphan-check"],
14931
+ status: flags.status,
14932
+ offlineReason: flags.offlineReason ?? flags.offline_reason ?? flags["offline-reason"]
14933
+ }), null, 2)}
14875
14934
  `);
14876
14935
  break;
14877
14936
  case "print-smoke":
@@ -14881,7 +14940,11 @@ async function main() {
14881
14940
  await register(config);
14882
14941
  break;
14883
14942
  case "heartbeat":
14884
- await heartbeat(config, { logMode: "full" });
14943
+ await heartbeat(config, {
14944
+ logMode: "full",
14945
+ status: flags.status,
14946
+ offlineReason: flags.offlineReason ?? flags.offline_reason ?? flags["offline-reason"]
14947
+ });
14885
14948
  break;
14886
14949
  case "poll":
14887
14950
  await poll(config);
@@ -14903,6 +14966,7 @@ async function main() {
14903
14966
  break;
14904
14967
  case "start":
14905
14968
  case "run":
14969
+ installShutdownHeartbeatHandlers();
14906
14970
  await runLoop(config);
14907
14971
  break;
14908
14972
  case "help":
@@ -6,7 +6,7 @@ import { basename, dirname, join, resolve } from "node:path";
6
6
  import { homedir, hostname } from "node:os";
7
7
  import { fileURLToPath } from "node:url";
8
8
 
9
- const CONNECTOR_VERSION = "0.1.1-beta.10";
9
+ const CONNECTOR_VERSION = "0.1.1-beta.12";
10
10
 
11
11
  const CAPABILITIES = [
12
12
  "remote_registration",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amaster.ai/employee-runtime-connector",
3
- "version": "0.1.1-beta.10",
3
+ "version": "0.1.1-beta.12",
4
4
  "description": "MirrorX runtime connector CLI and daemon",
5
5
  "license": "MIT",
6
6
  "type": "module",