@themoltnet/agent-daemon 0.62.0 → 0.63.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 +27 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +192 -77
- package/package.json +12 -10
package/README.md
CHANGED
|
@@ -649,10 +649,36 @@ Server configuration root. **Reset to release defaults** clears those overrides
|
|
|
649
649
|
when applied; it does not delete agent credentials. Launch environment values
|
|
650
650
|
have priority and appear read-only. Operators who explicitly set both
|
|
651
651
|
`MOLTNET_OPERATOR_API_URL` and `MOLTNET_OPERATOR_OAUTH_ISSUER` should also use
|
|
652
|
-
`
|
|
652
|
+
`MOLTNET_HOME` to select a dedicated environment root.
|
|
653
653
|
|
|
654
654
|
Release defaults use `https://api.themolt.net`, `https://auth.themolt.net`, and
|
|
655
655
|
public client IDs `moltnet-native` / `moltnet-console`. Hosted client registration
|
|
656
656
|
and coordinated configuration are tracked in
|
|
657
657
|
[moltnet-operations #8](https://github.com/getlarge/moltnet-operations/issues/8).
|
|
658
658
|
These IDs are public configuration; they do not contain a client secret.
|
|
659
|
+
|
|
660
|
+
### Isolated local development
|
|
661
|
+
|
|
662
|
+
Use the development targets to keep development state and installations in
|
|
663
|
+
separate directories:
|
|
664
|
+
|
|
665
|
+
```bash
|
|
666
|
+
pnpm exec nx run @moltnet/agent-desktop:tauri:dev
|
|
667
|
+
pnpm exec nx run @themoltnet/agent-daemon:dev -- server
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
The launchers choose `~/.local/share/moltnet/development/<worktree-id>/store`
|
|
671
|
+
and the sibling `agent` installation directory. The worktree ID is a stable
|
|
672
|
+
hash of the canonical checkout path. Repeated launches reuse that environment;
|
|
673
|
+
another worktree gets its own environment. Use `MOLTNET_DEV_HOME` and `MOLTNET_DEV_AGENT_HOME` to override these development
|
|
674
|
+
locations. Use absolute overrides: relative paths start at the Nx target’s
|
|
675
|
+
working directory (`apps/agent-daemon` for daemon `dev`, the repository root
|
|
676
|
+
for Desktop `tauri:dev`). All daemon `dev` commands, including `poll`, use
|
|
677
|
+
this isolated store.
|
|
678
|
+
The launchers ignore inherited production store and installation selectors.
|
|
679
|
+
The renderer-only Desktop `dev` target starts Vite without a native server.
|
|
680
|
+
|
|
681
|
+
For direct CLI or SDK development commands, set `MOLTNET_HOME` explicitly. See
|
|
682
|
+
[Store selection and keyring namespaces](../../docs/reference/agent-configuration.md#store-selection-and-keyring-namespaces)
|
|
683
|
+
for precedence, secret namespaces and daemon discovery. Automated tests use fresh
|
|
684
|
+
temporary roots.
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGzD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,OAAO,EAAE,oBAAoB,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyDlB"}
|
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ import "typebox/value";
|
|
|
11
11
|
import { execFile, spawn } from "node:child_process";
|
|
12
12
|
import { basename, dirname, isAbsolute, join, resolve, sep } from "node:path";
|
|
13
13
|
import { parseArgs, parseEnv, promisify } from "node:util";
|
|
14
|
-
import { CredentialPersistenceError, EnrollmentRecoveryError, FILE_SECRET_PROVIDER, FileSecretProvider, ProjectConfigError, ProvisioningNotStartedError, RegisterIdentityError, WORKSPACE_STRATEGIES, boundedIdentitySignal, canonicalDirectory, connect, createNodeSecretProviderRegistry, enrollTeam, getProjectConfigPath, readProjectConfig, register, resolveProjectBinding } from "@themoltnet/sdk/node";
|
|
14
|
+
import { CredentialPersistenceError, EnrollmentRecoveryError, FILE_SECRET_PROVIDER, FileSecretProvider, ProjectConfigError, ProvisioningNotStartedError, RegisterIdentityError, WORKSPACE_STRATEGIES, boundedIdentitySignal, canonicalDirectory, canonicalStoreRoot, connect, createNodeSecretProviderRegistry, defaultStoreRoot, enrollTeam, getProjectConfigPath, isDefaultStore, readProjectConfig, register, resolveProjectBinding, resolveStoreRoot, resolveStoreSelection } from "@themoltnet/sdk/node";
|
|
15
15
|
import { constants, copyFileSync, createReadStream, createWriteStream, existsSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
|
|
16
16
|
import { AuthenticationError, IDENTITY_ALIAS_PATTERN, MoltNetError, assertIdentityAlias, assertTrustedConfigApiUrl, createExecutorAttestor, formatSecretReferenceString, getConfigDir, getIdentityDir, hasAgentKeyConfiguration, isCanonicalConfig, parseSecretReferenceString, readConfig, requireSecureCredentialApiUrl, resolveAgentKey, resolveEnvSecretReference, resolveIdentitySeed, selectAgentKeyReference, signBytes } from "@themoltnet/sdk";
|
|
17
17
|
import { AgentRuntime, ApiTaskReporter, ApiTaskSource, PollingApiTaskSource, RuntimeProfilePrerequisiteError, createLocalSeedSigner, resolveAgentIdentity, resolveRuntimeProfile, resolveRuntimeProfiles, validateRuntimeProfilePrerequisites } from "@themoltnet/agent-runtime";
|
|
@@ -3757,6 +3757,13 @@ async function resolveSelectionApiUrl(agentName, options) {
|
|
|
3757
3757
|
* here, so the rest of the daemon imports typed values rather than
|
|
3758
3758
|
* sprinkling string lookups across the codebase.
|
|
3759
3759
|
*/
|
|
3760
|
+
/** All daemon commands announce the same legacy alias policy as Go and Desktop. */
|
|
3761
|
+
function markLegacyStoreNoticeShown() {
|
|
3762
|
+
process.env["MOLTNET_LEGACY_STORE_NOTICE_SHOWN"] = "1";
|
|
3763
|
+
}
|
|
3764
|
+
function legacyStoreNotice() {
|
|
3765
|
+
return process.env["MOLTNET_AGENT_SERVER_ROOT"] !== void 0 && process.env["MOLTNET_LEGACY_STORE_NOTICE_SHOWN"] !== "1" ? "MOLTNET_AGENT_SERVER_ROOT is deprecated; use MOLTNET_HOME. Both select the entire store; no data is migrated." : void 0;
|
|
3766
|
+
}
|
|
3760
3767
|
function loadConfig() {
|
|
3761
3768
|
assertSingleCredentialForm("MOLTNET_AGENT_KEY", "MOLTNET_AGENT_KEY_REF");
|
|
3762
3769
|
assertSingleCredentialForm("MOLTNET_PRIVATE_KEY", "MOLTNET_PRIVATE_KEY_REF");
|
|
@@ -3767,7 +3774,7 @@ function loadConfig() {
|
|
|
3767
3774
|
profilePrerequisiteEnv: process.env,
|
|
3768
3775
|
profilePrerequisitePath: process.env.PATH ?? "",
|
|
3769
3776
|
piCodingAgentDir: process.env["PI_CODING_AGENT_DIR"] ?? "",
|
|
3770
|
-
agentServerRoot:
|
|
3777
|
+
agentServerRoot: resolveStoreRoot(),
|
|
3771
3778
|
credentialSource: detectCredentialSource(process.env),
|
|
3772
3779
|
apiUrl: process.env["MOLTNET_API_URL"] ?? "",
|
|
3773
3780
|
signingPrivateKey: process.env["MOLTNET_PRIVATE_KEY"] ?? "",
|
|
@@ -3815,7 +3822,8 @@ function activatePiCodingAgentDir(path, env = {}) {
|
|
|
3815
3822
|
process.env["PI_CODING_AGENT_DIR"] = path;
|
|
3816
3823
|
Object.assign(process.env, env);
|
|
3817
3824
|
}
|
|
3818
|
-
function loadAgentServerEnvConfig() {
|
|
3825
|
+
function loadAgentServerEnvConfig(root) {
|
|
3826
|
+
const selection = resolveStoreSelection({ root });
|
|
3819
3827
|
const issuer = process.env["MOLTNET_OPERATOR_OAUTH_ISSUER"];
|
|
3820
3828
|
const publicUrl = process.env["MOLTNET_OPERATOR_OAUTH_PUBLIC_URL"] ?? issuer;
|
|
3821
3829
|
const nativeClientId = process.env["MOLTNET_NATIVE_OAUTH_CLIENT_ID"];
|
|
@@ -3831,7 +3839,8 @@ function loadAgentServerEnvConfig() {
|
|
|
3831
3839
|
},
|
|
3832
3840
|
port: process.env["MOLTNET_AGENT_SERVER_PORT"] ?? "",
|
|
3833
3841
|
allowedOrigins: process.env["MOLTNET_AGENT_SERVER_ALLOWED_ORIGINS"] ?? "",
|
|
3834
|
-
root:
|
|
3842
|
+
root: selection.root,
|
|
3843
|
+
rootSource: selection.source,
|
|
3835
3844
|
apiUrl: process.env["MOLTNET_API_URL"] ?? "",
|
|
3836
3845
|
logLevel: process.env["LOG_LEVEL"] ?? "",
|
|
3837
3846
|
activeIdentity: process.env["MOLTNET_ACTIVE_IDENTITY"] ?? ""
|
|
@@ -3841,8 +3850,9 @@ function loadAgentServerEnvConfig() {
|
|
|
3841
3850
|
function processEnvSnapshot() {
|
|
3842
3851
|
return process.env;
|
|
3843
3852
|
}
|
|
3844
|
-
function loadUpdateEnvConfig() {
|
|
3853
|
+
function loadUpdateEnvConfig(root) {
|
|
3845
3854
|
return {
|
|
3855
|
+
...!isDefaultStore({ root }) ? { storeRoot: resolveStoreRoot({ root }) } : {},
|
|
3846
3856
|
xdgCacheHome: process.env["XDG_CACHE_HOME"] ?? "",
|
|
3847
3857
|
localAppData: process.env["LOCALAPPDATA"] ?? ""
|
|
3848
3858
|
};
|
|
@@ -4162,7 +4172,9 @@ Example:
|
|
|
4162
4172
|
--agent legreffier \\
|
|
4163
4173
|
--state idle`;
|
|
4164
4174
|
function isHelpFlag(args) {
|
|
4165
|
-
|
|
4175
|
+
const separator = args.indexOf("--");
|
|
4176
|
+
const flags = separator === -1 ? args : args.slice(0, separator);
|
|
4177
|
+
return flags.includes("--help") || flags.includes("-h");
|
|
4166
4178
|
}
|
|
4167
4179
|
var AGENT_SERVER_HELP = `\
|
|
4168
4180
|
agent-daemon server — local supervisor for managed runs.
|
|
@@ -4172,14 +4184,14 @@ Agent Desktop instead uses a private Unix socket with a process-scoped grant.
|
|
|
4172
4184
|
Both modes configure agents and providers and start/stop child runs.
|
|
4173
4185
|
|
|
4174
4186
|
Options:
|
|
4175
|
-
--port <n> Loopback port. Default: 17374.
|
|
4187
|
+
--port <n> Loopback port. Default store: 17374; isolated stores: an available port.
|
|
4176
4188
|
Env: MOLTNET_AGENT_SERVER_PORT.
|
|
4177
4189
|
--allowed-origins <csv> Exact browser-controller origins allowed
|
|
4178
4190
|
local control.
|
|
4179
4191
|
Default: https://console.themolt.net.
|
|
4180
4192
|
Env: MOLTNET_AGENT_SERVER_ALLOWED_ORIGINS.
|
|
4181
4193
|
--root <path> Config root. Default: ~/.config/moltnet
|
|
4182
|
-
(or MOLTNET_AGENT_SERVER_ROOT).
|
|
4194
|
+
(or MOLTNET_HOME; legacy MOLTNET_AGENT_SERVER_ROOT).
|
|
4183
4195
|
--api-url <url> Default MoltNet API for new managed agents.
|
|
4184
4196
|
Default: https://api.themolt.net.
|
|
4185
4197
|
--heartbeat-interval-ms <n> Child reporter heartbeat cadence. Default: 60000.
|
|
@@ -4208,8 +4220,8 @@ Usage:
|
|
|
4208
4220
|
[--root <path>]
|
|
4209
4221
|
moltnet-agent providers logout <id> [--yes] [--root <path>]
|
|
4210
4222
|
|
|
4211
|
-
The default root is ~/.config/moltnet.
|
|
4212
|
-
|
|
4223
|
+
The default root is ~/.config/moltnet. MOLTNET_HOME selects another store.
|
|
4224
|
+
MOLTNET_AGENT_SERVER_ROOT is a legacy alias; conflicting values fail. API keys are accepted only from redirected stdin; they
|
|
4213
4225
|
are stored separately and providers.json contains only a secret reference.
|
|
4214
4226
|
|
|
4215
4227
|
--model declares a text-only model. --model-input declares a model together
|
|
@@ -5655,20 +5667,9 @@ var AgentServerStoreError = class extends Error {
|
|
|
5655
5667
|
this.code = code;
|
|
5656
5668
|
}
|
|
5657
5669
|
};
|
|
5658
|
-
/**
|
|
5659
|
-
* `MOLTNET_AGENT_SERVER_ROOT` override, else `~/.config/moltnet`.
|
|
5660
|
-
*
|
|
5661
|
-
* Deliberately does NOT consult `XDG_CONFIG_HOME`. The Go CLI's GetConfigDir
|
|
5662
|
-
* and @moltnet/agent-config's getConfigDir both resolve `~/.config/moltnet`,
|
|
5663
|
-
* so honouring XDG here gave one application two config roots: on a machine
|
|
5664
|
-
* with the variable set, the daemon wrote identities the CLI and SDK could not
|
|
5665
|
-
* read. `MOLTNET_AGENT_SERVER_ROOT` remains the explicit escape hatch for a
|
|
5666
|
-
* genuinely custom location.
|
|
5667
|
-
*/
|
|
5670
|
+
/** Explicit root, MOLTNET_HOME, legacy alias, then the unchanged default store. */
|
|
5668
5671
|
function resolveAgentServerRoot(input) {
|
|
5669
|
-
|
|
5670
|
-
if (override) return override;
|
|
5671
|
-
return getConfigDir();
|
|
5672
|
+
return getConfigDir(input);
|
|
5672
5673
|
}
|
|
5673
5674
|
/**
|
|
5674
5675
|
* Copy a model entry, dropping an empty `input` so it never reaches the wire.
|
|
@@ -6102,7 +6103,7 @@ async function resolvePiAgentDir(cfg, agentRoot, profiles, options = {}) {
|
|
|
6102
6103
|
};
|
|
6103
6104
|
}
|
|
6104
6105
|
const repoPiDir = join(agentRoot, ".pi");
|
|
6105
|
-
const store = new AgentServerStore(resolveAgentServerRoot({ root: cfg.agentServerRoot }));
|
|
6106
|
+
const store = new AgentServerStore(resolveAgentServerRoot({ root: cfg.agentServerRoot || void 0 }));
|
|
6106
6107
|
const providers = store.readProviders();
|
|
6107
6108
|
const storeHasAuth = existsSync(store.piAuthJsonPath);
|
|
6108
6109
|
if (Object.keys(providers).length === 0 && !storeHasAuth) {
|
|
@@ -6183,7 +6184,7 @@ function mergePiModels(store, repo) {
|
|
|
6183
6184
|
//#endregion
|
|
6184
6185
|
//#region src/lib/state-dir.ts
|
|
6185
6186
|
function ensureDaemonStateDirs(mountPath) {
|
|
6186
|
-
const rootDir =
|
|
6187
|
+
const rootDir = canonicalStoreRoot(join(mountPath, ".moltnet", "d"));
|
|
6187
6188
|
const piSessionsDir = join(rootDir, "pi-sessions");
|
|
6188
6189
|
mkdirSync(rootDir, {
|
|
6189
6190
|
recursive: true,
|
|
@@ -6198,17 +6199,6 @@ function ensureDaemonStateDirs(mountPath) {
|
|
|
6198
6199
|
piSessionsDir: realpathSync(piSessionsDir)
|
|
6199
6200
|
};
|
|
6200
6201
|
}
|
|
6201
|
-
function canonicalStatePath(path) {
|
|
6202
|
-
let parent = resolve(path);
|
|
6203
|
-
const missing = [];
|
|
6204
|
-
while (!existsSync(parent)) {
|
|
6205
|
-
missing.unshift(basename(parent));
|
|
6206
|
-
const next = dirname(parent);
|
|
6207
|
-
if (next === parent) throw new Error(`Cannot resolve daemon state root ${path}`);
|
|
6208
|
-
parent = next;
|
|
6209
|
-
}
|
|
6210
|
-
return join(realpathSync(parent), ...missing);
|
|
6211
|
-
}
|
|
6212
6202
|
//#endregion
|
|
6213
6203
|
//#region src/lib/prepare-runtime-profile.ts
|
|
6214
6204
|
/** Validate and prepare a profile through the shared daemon execution path. */
|
|
@@ -8865,12 +8855,13 @@ function parseProviderArgs(command, args) {
|
|
|
8865
8855
|
}
|
|
8866
8856
|
}
|
|
8867
8857
|
async function createContext(rootFlag, dependencies, installInterruptHandler) {
|
|
8868
|
-
const
|
|
8858
|
+
const root = resolveAgentServerRoot({ root: rootFlag ?? dependencies.envRoot ?? loadAgentServerEnvConfig().root });
|
|
8859
|
+
const store = new AgentServerStore(root).ensure();
|
|
8869
8860
|
const secrets = new FileSecretProvider({
|
|
8870
8861
|
root: store.secretsDir,
|
|
8871
8862
|
writable: true
|
|
8872
8863
|
});
|
|
8873
|
-
const secretProviders = createNodeSecretProviderRegistry().register(secrets);
|
|
8864
|
+
const secretProviders = createNodeSecretProviderRegistry({ store: { root } }).register(secrets);
|
|
8874
8865
|
const stderr = dependencies.stderr ?? console.error;
|
|
8875
8866
|
const logger = createCliLogger(stderr);
|
|
8876
8867
|
const configuration = dependencies.configuration ?? new ProviderConfigurationService({
|
|
@@ -9358,11 +9349,67 @@ var ConnectionSettingsStore = class {
|
|
|
9358
9349
|
};
|
|
9359
9350
|
/** A custom service gets its own identities, keys and runtime configuration. */
|
|
9360
9351
|
function connectionStateRoot(root, settings) {
|
|
9361
|
-
const identity = [settings.apiUrl.replace(
|
|
9352
|
+
const identity = [settings.apiUrl.replace(/\/+$/u, ""), settings.issuer.replace(/\/+$/u, "")];
|
|
9362
9353
|
if (identity[0] === RELEASE_CONNECTION.apiUrl && identity[1] === RELEASE_CONNECTION.issuer) return root;
|
|
9363
9354
|
return join(root, "environments", createHash("sha256").update(JSON.stringify(identity)).digest("hex"));
|
|
9364
9355
|
}
|
|
9365
9356
|
//#endregion
|
|
9357
|
+
//#region src/lib/agent-server/endpoint.ts
|
|
9358
|
+
function defaultAgentServerPort(root) {
|
|
9359
|
+
return isDefaultStore({ root }) ? OPERATOR_OAUTH.serverPort : 0;
|
|
9360
|
+
}
|
|
9361
|
+
function endpointPath(root) {
|
|
9362
|
+
return join(root, "agent-server-endpoint.json");
|
|
9363
|
+
}
|
|
9364
|
+
function validateUrl(value) {
|
|
9365
|
+
const url = new URL(value);
|
|
9366
|
+
if (url.protocol !== "http:" || url.hostname !== "127.0.0.1" || url.port === "0" || url.username || url.password || url.pathname !== "/" || url.search || url.hash || !/^http:\/\/127\.0\.0\.1(?::[1-9]\d{0,4})?$/.test(value)) throw new Error("Agent Server discovery requires a loopback HTTP origin");
|
|
9367
|
+
}
|
|
9368
|
+
function readAgentServerEndpoint(root) {
|
|
9369
|
+
let raw;
|
|
9370
|
+
try {
|
|
9371
|
+
raw = readFileSync(endpointPath(root), "utf8");
|
|
9372
|
+
} catch (cause) {
|
|
9373
|
+
if (cause.code === "ENOENT") return null;
|
|
9374
|
+
throw cause;
|
|
9375
|
+
}
|
|
9376
|
+
try {
|
|
9377
|
+
const value = JSON.parse(raw);
|
|
9378
|
+
if (value.version !== 1 || typeof value.instanceId !== "string" || value.instanceId.length !== 36 || !/^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/iu.test(value.instanceId) || typeof value.url !== "string") throw new Error("Invalid Agent Server discovery metadata");
|
|
9379
|
+
validateUrl(value.url);
|
|
9380
|
+
if (value.pid !== void 0) {
|
|
9381
|
+
if (!Number.isSafeInteger(value.pid) || value.pid <= 0 || value.pid > 2147483647) throw new Error("Invalid process ID");
|
|
9382
|
+
try {
|
|
9383
|
+
process.kill(value.pid, 0);
|
|
9384
|
+
} catch (cause) {
|
|
9385
|
+
if (cause.code === "ESRCH") return null;
|
|
9386
|
+
}
|
|
9387
|
+
}
|
|
9388
|
+
return value;
|
|
9389
|
+
} catch (cause) {
|
|
9390
|
+
throw new Error(`Invalid Agent Server discovery at ${endpointPath(root)}: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
|
|
9391
|
+
}
|
|
9392
|
+
}
|
|
9393
|
+
/** Publish and release only while holding the selected store's singleton lock. */
|
|
9394
|
+
function publishAgentServerEndpoint(root, url) {
|
|
9395
|
+
validateUrl(url);
|
|
9396
|
+
const endpoint = {
|
|
9397
|
+
version: 1,
|
|
9398
|
+
instanceId: randomUUID(),
|
|
9399
|
+
pid: process.pid,
|
|
9400
|
+
url
|
|
9401
|
+
};
|
|
9402
|
+
writeJsonAtomic(endpointPath(root), endpoint);
|
|
9403
|
+
return {
|
|
9404
|
+
record: endpoint,
|
|
9405
|
+
release() {
|
|
9406
|
+
try {
|
|
9407
|
+
if (readAgentServerEndpoint(root)?.instanceId === endpoint.instanceId) rmSync(endpointPath(root), { force: true });
|
|
9408
|
+
} catch {}
|
|
9409
|
+
}
|
|
9410
|
+
};
|
|
9411
|
+
}
|
|
9412
|
+
//#endregion
|
|
9366
9413
|
//#region src/lib/agent-server/lock.ts
|
|
9367
9414
|
var AgentServerLockError = class extends Error {
|
|
9368
9415
|
name = "AgentServerLockError";
|
|
@@ -9396,7 +9443,14 @@ async function acquireAgentServerLock(root, options = {}) {
|
|
|
9396
9443
|
}
|
|
9397
9444
|
});
|
|
9398
9445
|
} catch (cause) {
|
|
9399
|
-
if (cause.code === "ELOCKED")
|
|
9446
|
+
if (cause.code === "ELOCKED") {
|
|
9447
|
+
let holder = "";
|
|
9448
|
+
try {
|
|
9449
|
+
const endpoint = readAgentServerEndpoint(root);
|
|
9450
|
+
if (endpoint?.pid) holder = ` (PID ${endpoint.pid}, instance ${endpoint.instanceId})`;
|
|
9451
|
+
} catch {}
|
|
9452
|
+
throw new AgentServerLockError("held", `another moltnet-agent server process already owns ${path}${holder}; stop that process before retrying`, { cause });
|
|
9453
|
+
}
|
|
9400
9454
|
throw new AgentServerLockError("failed", `could not acquire Agent Server lock ${path}: ${cause.message}`, { cause });
|
|
9401
9455
|
}
|
|
9402
9456
|
let released = false;
|
|
@@ -9411,11 +9465,15 @@ async function acquireAgentServerLock(root, options = {}) {
|
|
|
9411
9465
|
}
|
|
9412
9466
|
/** Always release after normal completion or startup/runtime failure. */
|
|
9413
9467
|
async function withAgentServerLock(root, work, options) {
|
|
9414
|
-
const held =
|
|
9468
|
+
const held = [];
|
|
9415
9469
|
try {
|
|
9470
|
+
held.push(await acquireAgentServerLock(root, options));
|
|
9471
|
+
if (options?.stateRoot && options.stateRoot !== root) held.push(await acquireAgentServerLock(options.stateRoot, options));
|
|
9416
9472
|
return await work();
|
|
9417
9473
|
} finally {
|
|
9418
|
-
|
|
9474
|
+
for (const entry of held.reverse()) await entry.release().catch((error) => {
|
|
9475
|
+
console.error(`Could not release Agent Server lock ${entry.path}: ${String(error)}`);
|
|
9476
|
+
});
|
|
9419
9477
|
}
|
|
9420
9478
|
}
|
|
9421
9479
|
//#endregion
|
|
@@ -9450,6 +9508,10 @@ function applyNativeClientGrant(options) {
|
|
|
9450
9508
|
nativeGrant.grantNative(token);
|
|
9451
9509
|
return true;
|
|
9452
9510
|
}
|
|
9511
|
+
//#endregion
|
|
9512
|
+
//#region src/lib/agent-server/native-grant-service.ts
|
|
9513
|
+
/** Process-only native grant. Browser authorization belongs to OperatorOAuth. */
|
|
9514
|
+
var NATIVE_CLIENT_ORIGIN = "moltnet-agent-desktop://native";
|
|
9453
9515
|
var NativeGrantError = class extends Error {
|
|
9454
9516
|
code = "native_token_invalid";
|
|
9455
9517
|
};
|
|
@@ -10585,6 +10647,8 @@ var RunManager = class {
|
|
|
10585
10647
|
const homeDir = join(dirname(piDir), "home");
|
|
10586
10648
|
const env = {
|
|
10587
10649
|
HOME: homeDir,
|
|
10650
|
+
MOLTNET_DEFAULT_STORE_ROOT: defaultStoreRoot({ env: this.options.baseEnv }),
|
|
10651
|
+
MOLTNET_HOME: getConfigDir({ root: this.options.storeRoot ?? this.store.root }),
|
|
10588
10652
|
PI_CODING_AGENT_DIR: piDir,
|
|
10589
10653
|
XDG_CACHE_HOME: join(homeDir, ".cache"),
|
|
10590
10654
|
XDG_CONFIG_HOME: join(homeDir, ".config"),
|
|
@@ -10628,7 +10692,7 @@ var RunManager = class {
|
|
|
10628
10692
|
env["MOLTNET_AGENT_KEY"] = requireCredentialSnapshot(agent).agentKey;
|
|
10629
10693
|
env["MOLTNET_API_URL"] = activation.apiUrl ?? (activation.source === "external" ? activation.configApiUrl : "");
|
|
10630
10694
|
if (activation.source === "managed") {
|
|
10631
|
-
if (
|
|
10695
|
+
if (config.keys.private_key_ref?.provider !== "file") throw new AgentServerRunError("invalid_store", "The managed identity store is inconsistent: its signing key must be file-backed. Restore the identity store or use credential recovery.");
|
|
10632
10696
|
env["MOLTNET_PRIVATE_KEY_REF"] = formatSecretReferenceString(config.keys.private_key_ref);
|
|
10633
10697
|
env["MOLTNET_SECRET_ROOT"] = this.store.secretsDir;
|
|
10634
10698
|
} else try {
|
|
@@ -11231,6 +11295,20 @@ function writeRegistry(path, entries) {
|
|
|
11231
11295
|
renameSync(temp, path);
|
|
11232
11296
|
}
|
|
11233
11297
|
//#endregion
|
|
11298
|
+
//#region src/lib/agent-server/secret-providers.ts
|
|
11299
|
+
function createAgentServerSecretProviders(settings, store) {
|
|
11300
|
+
const secrets = new FileSecretProvider({
|
|
11301
|
+
root: store.secretsDir,
|
|
11302
|
+
writable: true
|
|
11303
|
+
});
|
|
11304
|
+
const registry = () => createNodeSecretProviderRegistry({ store: { root: settings.root } });
|
|
11305
|
+
return {
|
|
11306
|
+
secrets,
|
|
11307
|
+
secretProviders: registry().register(secrets),
|
|
11308
|
+
externalSecretProviders: registry()
|
|
11309
|
+
};
|
|
11310
|
+
}
|
|
11311
|
+
//#endregion
|
|
11234
11312
|
//#region src/lib/agent-server/readiness.ts
|
|
11235
11313
|
/**
|
|
11236
11314
|
* Whether a runtime profile can execute on *this* machine.
|
|
@@ -11997,7 +12075,8 @@ function requestOperationSignal(request, shutdownSignal) {
|
|
|
11997
12075
|
else request.raw.once("aborted", () => disconnected.abort({ source: "request" }));
|
|
11998
12076
|
return shutdownSignal ? AbortSignal.any([disconnected.signal, shutdownSignal]) : disconnected.signal;
|
|
11999
12077
|
}
|
|
12000
|
-
function buildAgentServer(
|
|
12078
|
+
function buildAgentServer(input) {
|
|
12079
|
+
const options = { ...input };
|
|
12001
12080
|
const { nativeGrant } = options;
|
|
12002
12081
|
const oauth = options.operatorOAuth;
|
|
12003
12082
|
let restartRequired = false;
|
|
@@ -12006,12 +12085,13 @@ function buildAgentServer(options) {
|
|
|
12006
12085
|
...fastifyOptions,
|
|
12007
12086
|
loggerInstance: options.logger
|
|
12008
12087
|
}) : Fastify(fastifyOptions);
|
|
12088
|
+
app.addHook("onListen", async () => {
|
|
12089
|
+
const address = app.server.address();
|
|
12090
|
+
if (address && typeof address !== "string") options.selfOrigin = `http://127.0.0.1:${address.port}`;
|
|
12091
|
+
});
|
|
12009
12092
|
options.registerOpenApi?.(app);
|
|
12010
12093
|
for (const schema of AGENT_SERVER_SCHEMAS) app.addSchema(schema);
|
|
12011
|
-
const
|
|
12012
|
-
registerLoopbackSecurity(app, {
|
|
12013
|
-
isOriginAllowed: (origin) => origin === "moltnet-agent-desktop://native" || browserOrigins.has(origin),
|
|
12014
|
-
...options.selfOrigin ? { selfOrigins: [options.selfOrigin] } : {},
|
|
12094
|
+
const securityOptions = {
|
|
12015
12095
|
allowedHeaders: [AGENT_SERVER_TOKEN_HEADER],
|
|
12016
12096
|
methods: [
|
|
12017
12097
|
"GET",
|
|
@@ -12020,7 +12100,18 @@ function buildAgentServer(options) {
|
|
|
12020
12100
|
"DELETE",
|
|
12021
12101
|
"OPTIONS"
|
|
12022
12102
|
]
|
|
12103
|
+
};
|
|
12104
|
+
if (options.nativeOnly) registerLoopbackSecurity(app, {
|
|
12105
|
+
...securityOptions,
|
|
12106
|
+
isOriginAllowed: (origin) => origin === NATIVE_CLIENT_ORIGIN
|
|
12023
12107
|
});
|
|
12108
|
+
else {
|
|
12109
|
+
const browserOrigins = new OriginAllowlist(options.allowedOrigins);
|
|
12110
|
+
registerLoopbackSecurity(app, {
|
|
12111
|
+
...securityOptions,
|
|
12112
|
+
isOriginAllowed: (origin) => origin === "moltnet-agent-desktop://native" || origin === options.selfOrigin || browserOrigins.has(origin)
|
|
12113
|
+
});
|
|
12114
|
+
}
|
|
12024
12115
|
let verificationWindow = Date.now();
|
|
12025
12116
|
let verifications = 0;
|
|
12026
12117
|
const browserVerification = /* @__PURE__ */ new WeakMap();
|
|
@@ -12641,7 +12732,7 @@ function corsHeadersFor(request, options) {
|
|
|
12641
12732
|
return {};
|
|
12642
12733
|
}
|
|
12643
12734
|
function isConfiguredOrigin(origin, options) {
|
|
12644
|
-
return typeof origin === "string" && (origin === "moltnet-agent-desktop://native" || options.allowedOrigins.includes(origin) || origin === options.selfOrigin);
|
|
12735
|
+
return typeof origin === "string" && (origin === "moltnet-agent-desktop://native" || !options.nativeOnly && (options.allowedOrigins.includes(origin) || origin === options.selfOrigin));
|
|
12645
12736
|
}
|
|
12646
12737
|
function normalizeAgentServerError(error) {
|
|
12647
12738
|
if (error instanceof TeamCredentialError) return {
|
|
@@ -12670,7 +12761,7 @@ function normalizeAgentServerError(error) {
|
|
|
12670
12761
|
message: error.message
|
|
12671
12762
|
};
|
|
12672
12763
|
if (error instanceof AgentServerRunError) return {
|
|
12673
|
-
statusCode: error.code === "run_not_found" ? 404 : 400,
|
|
12764
|
+
statusCode: error.code === "run_not_found" ? 404 : error.code === "invalid_store" ? 409 : 400,
|
|
12674
12765
|
code: error.code,
|
|
12675
12766
|
message: error.message
|
|
12676
12767
|
};
|
|
@@ -12709,7 +12800,6 @@ function normalizeAgentServerError(error) {
|
|
|
12709
12800
|
* waits for an authorized controller to configure agents/providers and
|
|
12710
12801
|
* start or stop runs.
|
|
12711
12802
|
*/
|
|
12712
|
-
var DEFAULT_PORT = OPERATOR_OAUTH.serverPort;
|
|
12713
12803
|
var DEFAULT_ALLOWED_ORIGINS = "https://console.themolt.net";
|
|
12714
12804
|
var SHUTDOWN_TIMEOUT_MS = 15e3;
|
|
12715
12805
|
var LOCK_HELD_EXIT_CODE = 75;
|
|
@@ -12734,7 +12824,6 @@ async function runAgentServer(argv) {
|
|
|
12734
12824
|
console.log(AGENT_SERVER_HELP);
|
|
12735
12825
|
return 0;
|
|
12736
12826
|
}
|
|
12737
|
-
const envConfig = loadAgentServerEnvConfig();
|
|
12738
12827
|
const { values } = parseArgs({
|
|
12739
12828
|
args: argv,
|
|
12740
12829
|
options: {
|
|
@@ -12748,6 +12837,7 @@ async function runAgentServer(argv) {
|
|
|
12748
12837
|
"native-socket": { type: "string" }
|
|
12749
12838
|
}
|
|
12750
12839
|
});
|
|
12840
|
+
const envConfig = loadAgentServerEnvConfig(values.root);
|
|
12751
12841
|
const nativeSocket = values["native-socket"];
|
|
12752
12842
|
const nativeSocketError = validateNativeSocketOptions(nativeSocketValidationOptions({
|
|
12753
12843
|
...nativeSocket ? { nativeSocket } : {},
|
|
@@ -12761,13 +12851,14 @@ async function runAgentServer(argv) {
|
|
|
12761
12851
|
console.error(nativeSocketError);
|
|
12762
12852
|
return 1;
|
|
12763
12853
|
}
|
|
12764
|
-
const port = Number.parseInt(values.port ?? (envConfig.port || `${
|
|
12765
|
-
if (!Number.isInteger(port) || port <
|
|
12854
|
+
const port = Number.parseInt(values.port ?? (envConfig.port || `${defaultAgentServerPort(envConfig.root)}`), 10);
|
|
12855
|
+
if (!Number.isInteger(port) || port < 0 || port > 65535) {
|
|
12766
12856
|
console.error(`Invalid --port: ${String(values.port)}`);
|
|
12767
12857
|
return 1;
|
|
12768
12858
|
}
|
|
12769
12859
|
const allowedOrigins = parseAllowedOrigins(values["allowed-origins"] ?? (envConfig.allowedOrigins || DEFAULT_ALLOWED_ORIGINS));
|
|
12770
|
-
const
|
|
12860
|
+
const settingsRoot = envConfig.root;
|
|
12861
|
+
const connectionSettings = new ConnectionSettingsStore(settingsRoot, {
|
|
12771
12862
|
...envConfig.operatorOAuth,
|
|
12772
12863
|
...values["api-url"] || envConfig.apiUrl ? { apiUrl: values["api-url"] || envConfig.apiUrl } : {}
|
|
12773
12864
|
});
|
|
@@ -12780,15 +12871,11 @@ async function runAgentServer(argv) {
|
|
|
12780
12871
|
name: "agent-daemon.server",
|
|
12781
12872
|
level: envConfig.logLevel || "info"
|
|
12782
12873
|
});
|
|
12874
|
+
const shutdownDisposers = [];
|
|
12783
12875
|
try {
|
|
12784
12876
|
try {
|
|
12785
|
-
return await withAgentServerLock(
|
|
12786
|
-
const secrets =
|
|
12787
|
-
root: store.secretsDir,
|
|
12788
|
-
writable: true
|
|
12789
|
-
});
|
|
12790
|
-
const secretProviders = createNodeSecretProviderRegistry().register(secrets);
|
|
12791
|
-
const externalSecretProviders = createNodeSecretProviderRegistry();
|
|
12877
|
+
return await withAgentServerLock(settingsRoot, async () => {
|
|
12878
|
+
const { secrets, secretProviders, externalSecretProviders } = createAgentServerSecretProviders(connectionSettings, store);
|
|
12792
12879
|
const nativeGrant = new NativeGrantService();
|
|
12793
12880
|
const nativeClient = applyNativeClientGrant({
|
|
12794
12881
|
nativeGrant,
|
|
@@ -12812,6 +12899,7 @@ async function runAgentServer(argv) {
|
|
|
12812
12899
|
const runtimeRegistry = new RuntimeRegistry(store.root);
|
|
12813
12900
|
const runs = new RunManager({
|
|
12814
12901
|
store,
|
|
12902
|
+
storeRoot: settingsRoot,
|
|
12815
12903
|
secretProviders,
|
|
12816
12904
|
externalSecretProviders,
|
|
12817
12905
|
baseEnv: processEnvSnapshot(),
|
|
@@ -12852,28 +12940,39 @@ async function runAgentServer(argv) {
|
|
|
12852
12940
|
logger,
|
|
12853
12941
|
shutdownSignal: shutdownController.signal
|
|
12854
12942
|
});
|
|
12943
|
+
let endpoint;
|
|
12855
12944
|
try {
|
|
12856
12945
|
const address = await app.listen(nativeSocket ? { path: nativeSocket } : {
|
|
12857
12946
|
host: "127.0.0.1",
|
|
12858
12947
|
port
|
|
12859
12948
|
});
|
|
12860
12949
|
if (nativeSocket) await chmod(nativeSocket, 384);
|
|
12950
|
+
if (!nativeSocket) {
|
|
12951
|
+
endpoint = publishAgentServerEndpoint(settingsRoot, address);
|
|
12952
|
+
console.error(`discovery: ${join(settingsRoot, "agent-server-endpoint.json")}`);
|
|
12953
|
+
}
|
|
12861
12954
|
console.error(`moltnet-agent server listening on ${address}`);
|
|
12862
|
-
console.error(`
|
|
12955
|
+
console.error(`store root: ${settingsRoot} (${envConfig.rootSource})`);
|
|
12956
|
+
console.error(`connection state: ${root}`);
|
|
12863
12957
|
if (nativeSocket) console.error(`native control socket: ${nativeSocket}`);
|
|
12864
12958
|
else console.error(`allowed origins: ${allowedOrigins.join(", ")}`);
|
|
12865
12959
|
if (nativeClient) console.error("native desktop client: authorized");
|
|
12866
12960
|
if (!nativeSocket) console.error("Connect from an allowed local-control client after operator authorization.");
|
|
12867
|
-
return await waitForAgentServerShutdown(runs, app, shutdownController, Boolean(values.supervised));
|
|
12961
|
+
return await waitForAgentServerShutdown(runs, app, shutdownController, Boolean(values.supervised), (dispose) => shutdownDisposers.push(dispose));
|
|
12868
12962
|
} catch (cause) {
|
|
12869
12963
|
await app.close().catch(() => void 0);
|
|
12870
12964
|
throw cause;
|
|
12965
|
+
} finally {
|
|
12966
|
+
endpoint?.release();
|
|
12871
12967
|
}
|
|
12872
|
-
}, {
|
|
12873
|
-
|
|
12874
|
-
|
|
12875
|
-
|
|
12876
|
-
|
|
12968
|
+
}, {
|
|
12969
|
+
stateRoot: root,
|
|
12970
|
+
onCompromised: (error) => {
|
|
12971
|
+
console.error(error.message);
|
|
12972
|
+
process.exitCode = 1;
|
|
12973
|
+
process.kill(process.pid, "SIGTERM");
|
|
12974
|
+
}
|
|
12975
|
+
});
|
|
12877
12976
|
} catch (cause) {
|
|
12878
12977
|
if (cause instanceof AgentServerLockError) {
|
|
12879
12978
|
console.error(cause.message);
|
|
@@ -12882,10 +12981,14 @@ async function runAgentServer(argv) {
|
|
|
12882
12981
|
throw cause;
|
|
12883
12982
|
}
|
|
12884
12983
|
} finally {
|
|
12885
|
-
|
|
12984
|
+
try {
|
|
12985
|
+
await shutdownLogger();
|
|
12986
|
+
} finally {
|
|
12987
|
+
for (const dispose of shutdownDisposers) dispose();
|
|
12988
|
+
}
|
|
12886
12989
|
}
|
|
12887
12990
|
}
|
|
12888
|
-
function waitForAgentServerShutdown(runs, app, shutdownController, supervised) {
|
|
12991
|
+
function waitForAgentServerShutdown(runs, app, shutdownController, supervised, registerDisposer) {
|
|
12889
12992
|
return new Promise((resolvePromise) => {
|
|
12890
12993
|
let shuttingDown = false;
|
|
12891
12994
|
const shutdown = (source) => {
|
|
@@ -12916,8 +13019,6 @@ function waitForAgentServerShutdown(runs, app, shutdownController, supervised) {
|
|
|
12916
13019
|
if (forcedExitTimer) clearTimeout(forcedExitTimer);
|
|
12917
13020
|
const failures = results.filter((result) => result.status === "rejected");
|
|
12918
13021
|
for (const failure of failures) console.error(`shutdown cleanup failed: ${failure.reason.message}`);
|
|
12919
|
-
handlers.dispose();
|
|
12920
|
-
stdinGuard.dispose();
|
|
12921
13022
|
const exitCode = typeof process.exitCode === "number" ? process.exitCode : 0;
|
|
12922
13023
|
resolvePromise(failures.length > 0 ? 1 : exitCode);
|
|
12923
13024
|
})();
|
|
@@ -12930,6 +13031,10 @@ function waitForAgentServerShutdown(runs, app, shutdownController, supervised) {
|
|
|
12930
13031
|
enabled: supervised,
|
|
12931
13032
|
shutdown: () => shutdown("stdin")
|
|
12932
13033
|
});
|
|
13034
|
+
registerDisposer(() => {
|
|
13035
|
+
handlers.dispose();
|
|
13036
|
+
stdinGuard.dispose();
|
|
13037
|
+
});
|
|
12933
13038
|
});
|
|
12934
13039
|
}
|
|
12935
13040
|
/** Makes the supervising process's stdin pipe part of the server lifecycle. */
|
|
@@ -13278,6 +13383,7 @@ function compareVersions(a, b) {
|
|
|
13278
13383
|
}
|
|
13279
13384
|
function cachePath() {
|
|
13280
13385
|
const env = loadUpdateEnvConfig();
|
|
13386
|
+
if (env.storeRoot) return join(env.storeRoot, "cache", "updates", "agent.json");
|
|
13281
13387
|
return join(env.xdgCacheHome || (platform() === "win32" ? env.localAppData || join(homedir(), "AppData", "Local") : join(homedir(), ".cache")), "moltnet", "updates", "agent.json");
|
|
13282
13388
|
}
|
|
13283
13389
|
async function readCache() {
|
|
@@ -13297,16 +13403,25 @@ async function writeCache(cache) {
|
|
|
13297
13403
|
}
|
|
13298
13404
|
//#endregion
|
|
13299
13405
|
//#region src/version.ts
|
|
13300
|
-
var DAEMON_VERSION = "0.
|
|
13406
|
+
var DAEMON_VERSION = "0.63.1";
|
|
13301
13407
|
//#endregion
|
|
13302
13408
|
//#region src/cli.ts
|
|
13303
13409
|
async function runAgentDaemonCli(options) {
|
|
13304
13410
|
const [subcommand, ...rest] = options.argv ?? process.argv.slice(2);
|
|
13305
|
-
|
|
13411
|
+
const help = subcommand === "--help" || subcommand === "-h" || [
|
|
13306
13412
|
"poll",
|
|
13307
13413
|
"drain",
|
|
13308
|
-
"
|
|
13309
|
-
|
|
13414
|
+
"once",
|
|
13415
|
+
"server",
|
|
13416
|
+
"providers",
|
|
13417
|
+
"sync-sessions"
|
|
13418
|
+
].includes(subcommand ?? "") && isHelpFlag(rest);
|
|
13419
|
+
const notice = legacyStoreNotice();
|
|
13420
|
+
if (notice && !help) {
|
|
13421
|
+
console.error(notice);
|
|
13422
|
+
markLegacyStoreNoticeShown();
|
|
13423
|
+
}
|
|
13424
|
+
if (["poll", "drain"].includes(subcommand ?? "") && !isWorkspaceInvocation()) checkDaemonUpdate({ currentVersion: DAEMON_VERSION }).then((update) => {
|
|
13310
13425
|
if (update.updateAvailable) pino({ name: "moltnet.agent-daemon" }).info({
|
|
13311
13426
|
event: "agent-daemon.update_available",
|
|
13312
13427
|
update
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@themoltnet/agent-daemon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.63.1",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Universal MoltNet agent daemon host with a built-in Pi/Gondolin runtime and support for trusted operator-owned runtime modules. CLI: moltnet-agent.",
|
|
@@ -84,10 +84,10 @@
|
|
|
84
84
|
"pino-pretty": "^13.1.3",
|
|
85
85
|
"proper-lockfile": "4.1.2",
|
|
86
86
|
"typebox": "^1.2.8",
|
|
87
|
-
"@themoltnet/
|
|
88
|
-
"@themoltnet/
|
|
89
|
-
"@themoltnet/
|
|
90
|
-
"@themoltnet/sdk": "0.
|
|
87
|
+
"@themoltnet/os-keyring": "0.4.0",
|
|
88
|
+
"@themoltnet/agent-runtime": "1.3.0",
|
|
89
|
+
"@themoltnet/pi-runtime": "0.18.3",
|
|
90
|
+
"@themoltnet/sdk": "0.145.0"
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
93
|
"@fastify/swagger": "^9.6.1",
|
|
@@ -97,16 +97,16 @@
|
|
|
97
97
|
"vite": "^8.0.0",
|
|
98
98
|
"vite-plugin-dts": "^4.5.4",
|
|
99
99
|
"vitest": "^3.0.0",
|
|
100
|
-
"@moltnet/api-client": "0.1.0",
|
|
101
100
|
"@moltnet/agent-eval": "0.1.0",
|
|
102
|
-
"@moltnet/bootstrap": "0.1.0",
|
|
103
101
|
"@moltnet/crypto-service": "0.1.0",
|
|
104
102
|
"@moltnet/execution-integrations": "0.1.0",
|
|
105
|
-
"@moltnet/models": "0.1.0",
|
|
106
|
-
"@moltnet/observability": "0.1.0",
|
|
107
103
|
"@moltnet/loopback-companion": "0.1.0",
|
|
104
|
+
"@moltnet/bootstrap": "0.1.0",
|
|
105
|
+
"@moltnet/api-client": "0.1.0",
|
|
106
|
+
"@moltnet/models": "0.1.0",
|
|
108
107
|
"@moltnet/execution-plan": "0.1.0",
|
|
109
108
|
"@moltnet/runtime-profiles": "0.1.0",
|
|
109
|
+
"@moltnet/observability": "0.1.0",
|
|
110
110
|
"@moltnet/tasks": "0.1.0"
|
|
111
111
|
},
|
|
112
112
|
"nx": {
|
|
@@ -137,6 +137,8 @@
|
|
|
137
137
|
"inputs": [
|
|
138
138
|
"default",
|
|
139
139
|
"^production",
|
|
140
|
+
"{workspaceRoot}/test-fixtures/agent-server-endpoint.json",
|
|
141
|
+
"{workspaceRoot}/test-fixtures/connection-state-root.json",
|
|
140
142
|
"{workspaceRoot}/docs/operate/*.md",
|
|
141
143
|
"{workspaceRoot}/docs/.vitepress/config.ts"
|
|
142
144
|
]
|
|
@@ -145,7 +147,7 @@
|
|
|
145
147
|
},
|
|
146
148
|
"scripts": {
|
|
147
149
|
"cli": "tsx src/main.ts",
|
|
148
|
-
"dev": "tsx watch src/main.ts",
|
|
150
|
+
"dev": "tsx ../../tools/src/desktop-development.ts tsx watch src/main.ts",
|
|
149
151
|
"start": "node dist/main.js",
|
|
150
152
|
"build": "vite build",
|
|
151
153
|
"generate:openapi": "tsx scripts/generate-openapi.ts",
|