@themoltnet/pi-runtime 0.8.0 → 0.9.0
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/dist/index.d.ts +40 -11
- package/dist/index.js +110 -44
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -49,6 +49,8 @@ export declare interface AllowedToolsClient {
|
|
|
49
49
|
argvPrefix: string[];
|
|
50
50
|
}>;
|
|
51
51
|
runtimeKind: string;
|
|
52
|
+
policySnapshotHash?: string;
|
|
53
|
+
runtimeProfileRevision?: number;
|
|
52
54
|
}>;
|
|
53
55
|
};
|
|
54
56
|
}
|
|
@@ -446,8 +448,8 @@ export declare interface ExecutePiTaskOptions {
|
|
|
446
448
|
runtimeProfileContext?: readonly ContextRef[];
|
|
447
449
|
/**
|
|
448
450
|
* Runtime profile id, used to resolve the tool-policy allow-set at session
|
|
449
|
-
* start. Required
|
|
450
|
-
* `tool_call` gate
|
|
451
|
+
* start. Required with `toolEnforcement`; the resolved mode determines
|
|
452
|
+
* whether a `tool_call` gate is installed.
|
|
451
453
|
*/
|
|
452
454
|
runtimeProfileId?: string;
|
|
453
455
|
/** Tool-policy enforcement mode for the selected runtime profile. */
|
|
@@ -604,21 +606,18 @@ export declare function filterModelVisibleTools(tools: readonly ToolDefinition[]
|
|
|
604
606
|
*/
|
|
605
607
|
export declare function findMainWorktree(startPath?: string): string;
|
|
606
608
|
|
|
607
|
-
/**
|
|
608
|
-
* The gate's verdict:
|
|
609
|
-
* - `{ allow: true }` — let the tool run.
|
|
610
|
-
* - `{ allow: false, reason }` — block it (enforce mode).
|
|
611
|
-
* - `{ audit, ... }` — would-block, but proceed and record it (watch mode).
|
|
612
|
-
*/
|
|
613
609
|
export declare type GateDecision = {
|
|
614
610
|
allow: true;
|
|
611
|
+
reasonCode: ToolPolicyDecisionReason;
|
|
615
612
|
matchedShellCommands?: MatchedShellCommand[];
|
|
616
613
|
} | {
|
|
617
614
|
allow: false;
|
|
615
|
+
reasonCode: ToolPolicyDecisionReason;
|
|
618
616
|
reason: string;
|
|
619
617
|
missing?: string[];
|
|
620
618
|
missingShellCommands?: MissingShellCommand[];
|
|
621
619
|
} | {
|
|
620
|
+
reasonCode: ToolPolicyDecisionReason;
|
|
622
621
|
audit: string;
|
|
623
622
|
missing?: string[];
|
|
624
623
|
missingShellCommands?: MissingShellCommand[];
|
|
@@ -1106,8 +1105,9 @@ export declare function resolveHostExecBaseEnv(guestCredentialMode: GuestCredent
|
|
|
1106
1105
|
/**
|
|
1107
1106
|
* Resolve the session's tool policy at start-up.
|
|
1108
1107
|
*
|
|
1109
|
-
*
|
|
1110
|
-
*
|
|
1108
|
+
* The latest allowed-tool set and enforcement mode are fetched from the API,
|
|
1109
|
+
* including when the daemon's cached profile says `off`. If that fetch fails,
|
|
1110
|
+
* the cached mode decides the fallback:
|
|
1111
1111
|
* `enforce` **fails closed** (empty allow-set → every non-`off` tool is
|
|
1112
1112
|
* blocked); `watch` fails open (empty allow-set → every tool is audited but
|
|
1113
1113
|
* allowed).
|
|
@@ -1291,6 +1291,10 @@ export declare interface SessionToolPolicy {
|
|
|
1291
1291
|
enforcement: ToolEnforcement;
|
|
1292
1292
|
allowedTools: ReadonlySet<string>;
|
|
1293
1293
|
allowedShellCommands: readonly ShellCommandRule[];
|
|
1294
|
+
/** Latest effective policy hash resolved for this Pi session. */
|
|
1295
|
+
executionPolicySnapshotHash?: string;
|
|
1296
|
+
/** Latest runtime profile revision resolved with the session policy. */
|
|
1297
|
+
executionRuntimeProfileRevision?: number;
|
|
1294
1298
|
/**
|
|
1295
1299
|
* `true` when the allow-set is a **degraded fallback** — the allowed-tools
|
|
1296
1300
|
* fetch failed or timed out and this policy is the fail-closed/fail-open
|
|
@@ -1298,7 +1302,7 @@ export declare interface SessionToolPolicy {
|
|
|
1298
1302
|
* empty-but-resolved policy (e.g. a profile with no bound tools) has
|
|
1299
1303
|
* `degraded: false`. Surfaced in every audit/block log so an operator can tell
|
|
1300
1304
|
* "blocked because the policy is empty" from "blocked because we couldn't read
|
|
1301
|
-
* the policy".
|
|
1305
|
+
* the policy". Successful resolutions are never degraded.
|
|
1302
1306
|
*/
|
|
1303
1307
|
degraded: boolean;
|
|
1304
1308
|
}
|
|
@@ -1354,10 +1358,35 @@ declare const ToolEnforcementSchema = Type.Union(toolEnforcementLiterals, {
|
|
|
1354
1358
|
'Runtime tool-policy enforcement mode: off (inert), watch (audit only), enforce (block disallowed tools, fail-closed).',
|
|
1355
1359
|
});
|
|
1356
1360
|
|
|
1361
|
+
/** Correlation and claim evidence repeated on every tool-policy decision. */
|
|
1362
|
+
export declare interface ToolPolicyDecisionContext {
|
|
1363
|
+
taskId: string;
|
|
1364
|
+
attemptN: number;
|
|
1365
|
+
teamId: string;
|
|
1366
|
+
claimantAgentId?: string;
|
|
1367
|
+
leaseId?: string;
|
|
1368
|
+
proposerKind?: 'agent' | 'human';
|
|
1369
|
+
proposerId?: string;
|
|
1370
|
+
claimRuntimeProfileId?: string;
|
|
1371
|
+
executionRuntimeProfileId?: string;
|
|
1372
|
+
claimRuntimeProfileRevision?: number;
|
|
1373
|
+
claimPolicySnapshotHash?: string;
|
|
1374
|
+
claimedExecutorFingerprint?: string;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
/**
|
|
1378
|
+
* The gate's verdict:
|
|
1379
|
+
* - `{ allow: true }` — let the tool run.
|
|
1380
|
+
* - `{ allow: false, reason }` — block it (enforce mode).
|
|
1381
|
+
* - `{ audit, ... }` — would-block, but proceed and record it (watch mode).
|
|
1382
|
+
*/
|
|
1383
|
+
export declare type ToolPolicyDecisionReason = 'policy_off' | 'executor_protocol_tool' | 'policy_allowed' | 'shell_command_prefix_allowed' | 'shell_command_unresolvable' | 'arbitrary_code_interpreter' | 'shell_output_redirection_requires_broad_permission' | 'tool_not_permitted';
|
|
1384
|
+
|
|
1357
1385
|
export declare interface ToolPolicyExtensionDeps {
|
|
1358
1386
|
policy: SessionToolPolicy;
|
|
1359
1387
|
analyzer: ShellCommandAnalyzer;
|
|
1360
1388
|
logger: ToolPolicyLogger;
|
|
1389
|
+
context?: ToolPolicyDecisionContext;
|
|
1361
1390
|
}
|
|
1362
1391
|
|
|
1363
1392
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1925,6 +1925,11 @@ Type$1.Object({ id: UuidSchema });
|
|
|
1925
1925
|
Type$1.Object({
|
|
1926
1926
|
publicKey: PublicKeySchema,
|
|
1927
1927
|
fingerprint: FingerprintSchema,
|
|
1928
|
+
proof: Type$1.String({
|
|
1929
|
+
minLength: 1,
|
|
1930
|
+
maxLength: 256
|
|
1931
|
+
}),
|
|
1932
|
+
credentialType: Type$1.Literal("oauth2"),
|
|
1928
1933
|
agentName: Type$1.String({
|
|
1929
1934
|
minLength: 1,
|
|
1930
1935
|
maxLength: 34
|
|
@@ -2198,7 +2203,6 @@ var ProblemCodeSchema = Type$1.Union([
|
|
|
2198
2203
|
Type$1.Literal("VALIDATION_FAILED"),
|
|
2199
2204
|
Type$1.Literal("INVALID_CHALLENGE"),
|
|
2200
2205
|
Type$1.Literal("INVALID_SIGNATURE"),
|
|
2201
|
-
Type$1.Literal("VOUCHER_LIMIT"),
|
|
2202
2206
|
Type$1.Literal("RATE_LIMIT_EXCEEDED"),
|
|
2203
2207
|
Type$1.Literal("SERIALIZATION_EXHAUSTED"),
|
|
2204
2208
|
Type$1.Literal("SIGNING_REQUEST_EXPIRED"),
|
|
@@ -5420,16 +5424,25 @@ function createGondolinBashOps(vm, localCwd, guestWorkspace) {
|
|
|
5420
5424
|
* capability-aware allow-set) is tracked as future work.
|
|
5421
5425
|
*/
|
|
5422
5426
|
function decideToolCall(input) {
|
|
5423
|
-
if (input.enforcement === "off") return {
|
|
5424
|
-
|
|
5427
|
+
if (input.enforcement === "off") return {
|
|
5428
|
+
allow: true,
|
|
5429
|
+
reasonCode: "policy_off"
|
|
5430
|
+
};
|
|
5431
|
+
if (input.toolName.startsWith("submit_") || input.toolName === "subagent") return {
|
|
5432
|
+
allow: true,
|
|
5433
|
+
reasonCode: "executor_protocol_tool"
|
|
5434
|
+
};
|
|
5425
5435
|
const resolved = resolveNames(input);
|
|
5426
|
-
if (resolved.kind === "unresolvable") return fenced(input.enforcement, "shell command could not be statically authorized", "unresolvable shell command (watch)");
|
|
5436
|
+
if (resolved.kind === "unresolvable") return fenced(input.enforcement, "shell_command_unresolvable", "shell command could not be statically authorized", "unresolvable shell command (watch)");
|
|
5427
5437
|
const arbitraryCode = [...new Set(resolved.tools.filter((tool) => tool.risk === "arbitrary-code").map((tool) => tool.name))];
|
|
5428
|
-
if (arbitraryCode.length > 0) return fenced(input.enforcement, `arbitrary-code interpreter not authorizable by tool policy: ${arbitraryCode.join(", ")}`, `would block — arbitrary-code interpreter (watch): ${arbitraryCode.join(", ")}`, arbitraryCode);
|
|
5438
|
+
if (arbitraryCode.length > 0) return fenced(input.enforcement, "arbitrary_code_interpreter", `arbitrary-code interpreter not authorizable by tool policy: ${arbitraryCode.join(", ")}`, `would block — arbitrary-code interpreter (watch): ${arbitraryCode.join(", ")}`, arbitraryCode);
|
|
5429
5439
|
if (input.toolName !== "bash") {
|
|
5430
5440
|
const missing = resolved.tools.map((tool) => tool.name).filter((name) => !input.allowedTools.has(name));
|
|
5431
|
-
if (missing.length === 0) return {
|
|
5432
|
-
|
|
5441
|
+
if (missing.length === 0) return {
|
|
5442
|
+
allow: true,
|
|
5443
|
+
reasonCode: "policy_allowed"
|
|
5444
|
+
};
|
|
5445
|
+
return fenced(input.enforcement, "tool_not_permitted", `not permitted by tool policy: ${missing.join(", ")}`, `would block (watch): ${missing.join(", ")}`, missing);
|
|
5433
5446
|
}
|
|
5434
5447
|
const matchedShellCommands = [];
|
|
5435
5448
|
const missingShellCommands = resolved.tools.filter((tool) => {
|
|
@@ -5439,7 +5452,7 @@ function decideToolCall(input) {
|
|
|
5439
5452
|
matchedShellCommands.push(toMatchedShellCommand(tool.name, matched.argvPrefix));
|
|
5440
5453
|
return false;
|
|
5441
5454
|
}).map(toMissingShellCommand);
|
|
5442
|
-
if (missingShellCommands.length === 0 && resolved.hasOutputRedirection && matchedShellCommands.length > 0) return fenced(input.enforcement, "shell output redirection requires broad executable permission", "would block shell output redirection under scoped command policy", [...new Set(matchedShellCommands.map(({ executable }) => executable))], matchedShellCommands.map(({ executable, argvPrefixFingerprint, argvPrefixLength }) => ({
|
|
5455
|
+
if (missingShellCommands.length === 0 && resolved.hasOutputRedirection && matchedShellCommands.length > 0) return fenced(input.enforcement, "shell_output_redirection_requires_broad_permission", "shell output redirection requires broad executable permission", "would block shell output redirection under scoped command policy", [...new Set(matchedShellCommands.map(({ executable }) => executable))], matchedShellCommands.map(({ executable, argvPrefixFingerprint, argvPrefixLength }) => ({
|
|
5443
5456
|
executable,
|
|
5444
5457
|
argvFingerprint: argvPrefixFingerprint,
|
|
5445
5458
|
argvLength: argvPrefixLength,
|
|
@@ -5447,10 +5460,14 @@ function decideToolCall(input) {
|
|
|
5447
5460
|
})));
|
|
5448
5461
|
if (missingShellCommands.length === 0) return matchedShellCommands.length > 0 ? {
|
|
5449
5462
|
allow: true,
|
|
5463
|
+
reasonCode: "shell_command_prefix_allowed",
|
|
5450
5464
|
matchedShellCommands
|
|
5451
|
-
} : {
|
|
5465
|
+
} : {
|
|
5466
|
+
allow: true,
|
|
5467
|
+
reasonCode: "policy_allowed"
|
|
5468
|
+
};
|
|
5452
5469
|
const missing = [...new Set(missingShellCommands.map(({ executable }) => executable))];
|
|
5453
|
-
return fenced(input.enforcement, `not permitted by tool policy: ${missing.join(", ")}`, `would block (watch): ${missing.join(", ")}`, missing, missingShellCommands);
|
|
5470
|
+
return fenced(input.enforcement, "tool_not_permitted", `not permitted by tool policy: ${missing.join(", ")}`, `would block (watch): ${missing.join(", ")}`, missing, missingShellCommands);
|
|
5454
5471
|
}
|
|
5455
5472
|
function fingerprintArgv(argv) {
|
|
5456
5473
|
return `sha256:${createHash$1("sha256").update(JSON.stringify(argv.map((token) => token === null ? { dynamic: true } : token))).digest("hex").slice(0, 16)}`;
|
|
@@ -5477,14 +5494,16 @@ function matchesArgvPrefix(argv, prefix) {
|
|
|
5477
5494
|
* Shared enforce/watch branch: block in `enforce`, audit-and-allow in `watch`.
|
|
5478
5495
|
* `enforcement` is never `off` here (short-circuited by the caller).
|
|
5479
5496
|
*/
|
|
5480
|
-
function fenced(enforcement, blockReason, auditReason, missing, missingShellCommands) {
|
|
5497
|
+
function fenced(enforcement, reasonCode, blockReason, auditReason, missing, missingShellCommands) {
|
|
5481
5498
|
if (enforcement === "enforce") return {
|
|
5482
5499
|
allow: false,
|
|
5500
|
+
reasonCode,
|
|
5483
5501
|
reason: blockReason,
|
|
5484
5502
|
...missing ? { missing } : {},
|
|
5485
5503
|
...missingShellCommands?.length ? { missingShellCommands } : {}
|
|
5486
5504
|
};
|
|
5487
5505
|
return {
|
|
5506
|
+
reasonCode,
|
|
5488
5507
|
audit: auditReason,
|
|
5489
5508
|
...missing ? { missing } : {},
|
|
5490
5509
|
...missingShellCommands?.length ? { missingShellCommands } : {}
|
|
@@ -5527,8 +5546,9 @@ function resolveNames(input) {
|
|
|
5527
5546
|
/**
|
|
5528
5547
|
* Resolve the session's tool policy at start-up.
|
|
5529
5548
|
*
|
|
5530
|
-
*
|
|
5531
|
-
*
|
|
5549
|
+
* The latest allowed-tool set and enforcement mode are fetched from the API,
|
|
5550
|
+
* including when the daemon's cached profile says `off`. If that fetch fails,
|
|
5551
|
+
* the cached mode decides the fallback:
|
|
5532
5552
|
* `enforce` **fails closed** (empty allow-set → every non-`off` tool is
|
|
5533
5553
|
* blocked); `watch` fails open (empty allow-set → every tool is audited but
|
|
5534
5554
|
* allowed).
|
|
@@ -5539,12 +5559,6 @@ function resolveNames(input) {
|
|
|
5539
5559
|
* session, stable enforcement for the run) accepted over re-fetching per call.
|
|
5540
5560
|
*/
|
|
5541
5561
|
async function resolveSessionToolPolicy(input) {
|
|
5542
|
-
if (input.enforcement === "off") return {
|
|
5543
|
-
enforcement: "off",
|
|
5544
|
-
allowedTools: /* @__PURE__ */ new Set(),
|
|
5545
|
-
allowedShellCommands: [],
|
|
5546
|
-
degraded: false
|
|
5547
|
-
};
|
|
5548
5562
|
const timeoutMs = input.timeoutMs ?? 5e3;
|
|
5549
5563
|
try {
|
|
5550
5564
|
const resolved = await withTimeout$1(input.agent.runtimeProfiles.allowedTools(input.profileId, { teamId: input.teamId }), timeoutMs);
|
|
@@ -5560,6 +5574,8 @@ async function resolveSessionToolPolicy(input) {
|
|
|
5560
5574
|
if (rule.argvPrefix.length < 2 || rule.argvPrefix.length > 8 || rule.argvPrefix.some((token) => !token)) throw new Error("runtime returned an invalid shell command rule");
|
|
5561
5575
|
return { argvPrefix: rule.argvPrefix };
|
|
5562
5576
|
}),
|
|
5577
|
+
executionPolicySnapshotHash: resolved.policySnapshotHash,
|
|
5578
|
+
executionRuntimeProfileRevision: resolved.runtimeProfileRevision,
|
|
5563
5579
|
degraded: false
|
|
5564
5580
|
};
|
|
5565
5581
|
} catch (err) {
|
|
@@ -5632,34 +5648,46 @@ function decideForEvent(event, policy, analyze) {
|
|
|
5632
5648
|
* `off`. Register it in a session's `extensionFactories`.
|
|
5633
5649
|
*/
|
|
5634
5650
|
function createToolPolicyExtension(deps) {
|
|
5651
|
+
if (deps.context?.claimPolicySnapshotHash && deps.policy.executionPolicySnapshotHash && deps.context.claimPolicySnapshotHash !== deps.policy.executionPolicySnapshotHash) deps.logger.info({
|
|
5652
|
+
...decisionContext(deps),
|
|
5653
|
+
decision: "continue",
|
|
5654
|
+
reason: "claim_execution_policy_drift"
|
|
5655
|
+
}, "tool_policy.snapshot_drift");
|
|
5635
5656
|
return (pi) => {
|
|
5636
5657
|
if (deps.policy.enforcement === "off") return;
|
|
5637
5658
|
pi.on("tool_call", (event) => {
|
|
5638
5659
|
const decision = decideForEvent(event, deps.policy, (command) => deps.analyzer.analyze(command));
|
|
5639
5660
|
if ("allow" in decision && decision.allow) {
|
|
5640
|
-
|
|
5661
|
+
deps.logger.info({
|
|
5662
|
+
...decisionContext(deps),
|
|
5641
5663
|
toolName: event.toolName,
|
|
5642
5664
|
toolCallId: event.toolCallId,
|
|
5643
|
-
|
|
5644
|
-
|
|
5665
|
+
decision: "allowed",
|
|
5666
|
+
reason: decision.reasonCode,
|
|
5667
|
+
...decision.matchedShellCommands?.length ? { shellFingerprints: decision.matchedShellCommands } : {}
|
|
5668
|
+
}, "tool_policy.allowed");
|
|
5645
5669
|
return;
|
|
5646
5670
|
}
|
|
5647
5671
|
if ("audit" in decision) {
|
|
5648
5672
|
deps.logger.info({
|
|
5673
|
+
...decisionContext(deps),
|
|
5649
5674
|
toolName: event.toolName,
|
|
5650
5675
|
toolCallId: event.toolCallId,
|
|
5651
|
-
|
|
5652
|
-
decision
|
|
5676
|
+
decision: "audit",
|
|
5677
|
+
reason: decision.reasonCode,
|
|
5678
|
+
...decision.missing?.length ? { missingExecutables: decision.missing } : {},
|
|
5679
|
+
...decision.missingShellCommands?.length ? { shellFingerprints: decision.missingShellCommands } : {}
|
|
5653
5680
|
}, "tool_policy.audit");
|
|
5654
5681
|
return;
|
|
5655
5682
|
}
|
|
5656
5683
|
deps.logger.warn({
|
|
5684
|
+
...decisionContext(deps),
|
|
5657
5685
|
toolName: event.toolName,
|
|
5658
5686
|
toolCallId: event.toolCallId,
|
|
5659
|
-
|
|
5660
|
-
reason: decision.
|
|
5661
|
-
missingExecutables: decision.missing,
|
|
5662
|
-
missingShellCommands: decision.missingShellCommands
|
|
5687
|
+
decision: "blocked",
|
|
5688
|
+
reason: decision.reasonCode,
|
|
5689
|
+
...decision.missing?.length ? { missingExecutables: decision.missing } : {},
|
|
5690
|
+
...decision.missingShellCommands?.length ? { shellFingerprints: decision.missingShellCommands } : {}
|
|
5663
5691
|
}, "tool_policy.blocked");
|
|
5664
5692
|
return {
|
|
5665
5693
|
block: true,
|
|
@@ -5668,6 +5696,15 @@ function createToolPolicyExtension(deps) {
|
|
|
5668
5696
|
});
|
|
5669
5697
|
};
|
|
5670
5698
|
}
|
|
5699
|
+
function decisionContext(deps) {
|
|
5700
|
+
return {
|
|
5701
|
+
...deps.context ?? {},
|
|
5702
|
+
enforcement: deps.policy.enforcement,
|
|
5703
|
+
degraded: deps.policy.degraded,
|
|
5704
|
+
executionPolicySnapshotHash: deps.policy.executionPolicySnapshotHash,
|
|
5705
|
+
executionRuntimeProfileRevision: deps.policy.executionRuntimeProfileRevision
|
|
5706
|
+
};
|
|
5707
|
+
}
|
|
5671
5708
|
//#endregion
|
|
5672
5709
|
//#region src/runtime/capability-discovery.ts
|
|
5673
5710
|
var GuestExecutableProbeError = class extends Error {
|
|
@@ -7647,28 +7684,34 @@ async function executePiTask(claimedTask, reporter, opts) {
|
|
|
7647
7684
|
...obj
|
|
7648
7685
|
}))
|
|
7649
7686
|
};
|
|
7650
|
-
|
|
7651
|
-
|
|
7687
|
+
const toolPolicyDecisionContext = buildToolPolicyDecisionContext(claimedTask, opts.runtimeProfileId);
|
|
7688
|
+
if (opts.runtimeProfileId && opts.toolEnforcement) {
|
|
7689
|
+
const policy = await resolveSessionToolPolicy({
|
|
7652
7690
|
agent: moltnetAgent,
|
|
7653
7691
|
profileId: opts.runtimeProfileId,
|
|
7654
7692
|
teamId: taskTeamId,
|
|
7655
7693
|
runtimeKind: opts.runtimeDefinition?.runtimeKind ?? "gondolin_pi",
|
|
7656
7694
|
enforcement: opts.toolEnforcement,
|
|
7657
7695
|
logger: toolPolicyLogger
|
|
7658
|
-
})
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
allowedShellCommands
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7696
|
+
});
|
|
7697
|
+
resolvedToolPolicy = policy;
|
|
7698
|
+
if (policy.enforcement !== "off") {
|
|
7699
|
+
const analyzer = await ShellCommandAnalyzer.create();
|
|
7700
|
+
verifiedGuestExecutables = (await discoverGuestExecutables(managed.vm, [...policy.allowedShellCommands.map(({ argvPrefix }) => argvPrefix[0]), ...policy.enforcement === "watch" ? resolvedVmTemplate?.executables ?? [] : []], { signal: reporter.cancelSignal })).available;
|
|
7701
|
+
const availableExecutables = new Set(verifiedGuestExecutables);
|
|
7702
|
+
const allowedShellCommands = policy.allowedShellCommands.filter(({ argvPrefix }) => availableExecutables.has(argvPrefix[0]));
|
|
7703
|
+
unavailableRuntimeShellCommands = policy.allowedShellCommands.filter(({ argvPrefix }) => !availableExecutables.has(argvPrefix[0]));
|
|
7704
|
+
resolvedToolPolicy = {
|
|
7705
|
+
...policy,
|
|
7706
|
+
allowedShellCommands
|
|
7707
|
+
};
|
|
7708
|
+
toolPolicyExtensions.push(createToolPolicyExtension({
|
|
7709
|
+
policy: resolvedToolPolicy,
|
|
7710
|
+
analyzer,
|
|
7711
|
+
logger: toolPolicyLogger,
|
|
7712
|
+
context: toolPolicyDecisionContext
|
|
7713
|
+
}));
|
|
7714
|
+
}
|
|
7672
7715
|
}
|
|
7673
7716
|
const runtimeToolContext = {
|
|
7674
7717
|
agent: moltnetAgent,
|
|
@@ -8048,6 +8091,29 @@ async function executePiTask(claimedTask, reporter, opts) {
|
|
|
8048
8091
|
});
|
|
8049
8092
|
}
|
|
8050
8093
|
}
|
|
8094
|
+
function buildToolPolicyDecisionContext(claimedTask, executionRuntimeProfileId) {
|
|
8095
|
+
const { task, attemptN, claimAuthority } = claimedTask;
|
|
8096
|
+
const proposer = task.proposedByAgentId ? {
|
|
8097
|
+
proposerKind: "agent",
|
|
8098
|
+
proposerId: task.proposedByAgentId
|
|
8099
|
+
} : task.proposedByHumanId ? {
|
|
8100
|
+
proposerKind: "human",
|
|
8101
|
+
proposerId: task.proposedByHumanId
|
|
8102
|
+
} : {};
|
|
8103
|
+
return {
|
|
8104
|
+
taskId: task.id,
|
|
8105
|
+
attemptN,
|
|
8106
|
+
teamId: task.teamId,
|
|
8107
|
+
...proposer,
|
|
8108
|
+
...claimAuthority?.claimantAgentId ? { claimantAgentId: claimAuthority.claimantAgentId } : {},
|
|
8109
|
+
...claimAuthority?.leaseId ? { leaseId: claimAuthority.leaseId } : {},
|
|
8110
|
+
...claimAuthority?.runtimeProfileId ? { claimRuntimeProfileId: claimAuthority.runtimeProfileId } : {},
|
|
8111
|
+
...executionRuntimeProfileId ? { executionRuntimeProfileId } : {},
|
|
8112
|
+
...typeof claimAuthority?.runtimeProfileRevision === "number" ? { claimRuntimeProfileRevision: claimAuthority.runtimeProfileRevision } : {},
|
|
8113
|
+
...claimAuthority?.policySnapshotHash ? { claimPolicySnapshotHash: claimAuthority.policySnapshotHash } : {},
|
|
8114
|
+
...claimAuthority?.executorFingerprint ? { claimedExecutorFingerprint: claimAuthority.executorFingerprint } : {}
|
|
8115
|
+
};
|
|
8116
|
+
}
|
|
8051
8117
|
function createSessionTurnState() {
|
|
8052
8118
|
return {
|
|
8053
8119
|
assistantText: "",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@themoltnet/pi-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Composable MoltNet runtime kernel for Pi agents in Gondolin VMs",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"@opentelemetry/api": "^1.9.0",
|
|
32
32
|
"multiformats": "^13.3.0",
|
|
33
33
|
"typebox": "^1.2.8",
|
|
34
|
-
"@themoltnet/agent-runtime": "0.
|
|
34
|
+
"@themoltnet/agent-runtime": "0.42.0",
|
|
35
35
|
"@themoltnet/os-keyring": "0.2.0",
|
|
36
|
-
"@themoltnet/sdk": "0.
|
|
36
|
+
"@themoltnet/sdk": "0.133.0",
|
|
37
37
|
"@themoltnet/shell-command-analyzer": "0.3.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
"vite": "^8.0.0",
|
|
52
52
|
"vite-plugin-dts": "^4.5.4",
|
|
53
53
|
"vitest": "^3.0.0",
|
|
54
|
-
"@moltnet/
|
|
54
|
+
"@moltnet/models": "0.1.0",
|
|
55
55
|
"@moltnet/tasks": "0.1.0",
|
|
56
|
-
"@moltnet/
|
|
56
|
+
"@moltnet/crypto-service": "0.1.0"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">=24"
|