@themoltnet/pi-runtime 0.9.0 → 0.10.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/dist/index.d.ts CHANGED
@@ -849,6 +849,12 @@ export declare interface MoltNetToolsConfig {
849
849
  * entry creation behaves as before (env-derived diary, no auto-tags).
850
850
  */
851
851
  getTaskContext?(): MoltNetTaskContext | null;
852
+ /** Records recoverable task-provenance failures without ending the task. */
853
+ onTaskProvenanceEvent?(event: 'task.provenance.entry_denied', details: {
854
+ taskId: string;
855
+ diaryId: string;
856
+ error: string;
857
+ }): void | Promise<void>;
852
858
  }
853
859
 
854
860
  export declare function normalizeRetryTriageResult(value: unknown): PiRetryTriageResult;
package/dist/index.js CHANGED
@@ -7,17 +7,8 @@ import { Type } from "@earendil-works/pi-ai";
7
7
  import { AuthStorage, DEFAULT_MAX_BYTES, DefaultResourceLoader, ModelRegistry, SessionManager, createAgentSession, createBashToolDefinition, createEditToolDefinition, createFindToolDefinition, createGrepToolDefinition, createLsToolDefinition, createReadToolDefinition, createSyntheticSourceInfo, createWriteToolDefinition, defineTool, formatSize, parseFrontmatter, truncateHead, truncateLine } from "@earendil-works/pi-coding-agent";
8
8
  import { SpanStatusCode, context, metrics, trace } from "@opentelemetry/api";
9
9
  import { CID } from "multiformats/cid";
10
- import "multiformats/codecs/raw";
11
- import "multiformats/hashes/digest";
12
- import { sha256 } from "multiformats/hashes/sha2";
13
- import "@noble/hashes/sha2";
14
- import "multiformats/bases/base32";
15
- import "@noble/curves/ed25519.js";
16
- import * as ed from "@noble/ed25519";
17
- import { createHash } from "crypto";
18
- import { createHash as createHash$1 } from "node:crypto";
19
10
  import * as json from "multiformats/codecs/json";
20
- import "@ipld/dag-cbor";
11
+ import { sha256 } from "multiformats/hashes/sha2";
21
12
  import { FREEFORM_TYPE, SUBMIT_OUTPUT_GATE_ID, TaskContext, buildTaskUserPrompt, getSubmitOutputContract, materializeTaskOutput, mergeRuntimeProfileContext, resolveTaskContext, taskTypeUsesSubagents, traceRuntimePhase, validateTaskOutput, validateTaskSubmission } from "@themoltnet/agent-runtime";
22
13
  import { connect } from "@themoltnet/sdk/node";
23
14
  import { ShellCommandAnalyzer } from "@themoltnet/shell-command-analyzer";
@@ -25,6 +16,7 @@ import { homedir } from "node:os";
25
16
  import { MemoryProvider, RealFSProvider, ShadowProvider, VM, VmCheckpoint, createHttpHooks, createShadowPathPredicate, ensureImageSelector, isWriteFlag, loadGuestAssets } from "@earendil-works/gondolin";
26
17
  import { Type as Type$1 } from "typebox";
27
18
  import { Value } from "typebox/value";
19
+ import { createHash } from "node:crypto";
28
20
  import { parseEnv } from "node:util";
29
21
  //#region src/path-containment.ts
30
22
  /**
@@ -678,13 +670,27 @@ function createMoltNetTools(config) {
678
670
  } else targetDiaryId = params.diaryId ?? envDiaryId;
679
671
  const userTags = params.tags ?? [];
680
672
  const mergedTags = autoTags.length ? [...autoTags, ...userTags.filter((t) => !autoTags.includes(t))] : userTags;
681
- const entry = await agent.entries.create(targetDiaryId, {
682
- title: params.title,
683
- content: params.content,
684
- tags: mergedTags,
685
- importance: params.importance ?? 5,
686
- ...params.entryType ? { entryType: params.entryType } : {}
687
- });
673
+ let entry;
674
+ try {
675
+ entry = await agent.entries.create(targetDiaryId, {
676
+ title: params.title,
677
+ content: params.content,
678
+ tags: mergedTags,
679
+ importance: params.importance ?? 5,
680
+ ...params.entryType ? { entryType: params.entryType } : {}
681
+ });
682
+ } catch (error) {
683
+ const message = error instanceof Error ? error.message : String(error);
684
+ if (taskCtx && /\b403\b|forbidden|not authorized|permission/i.test(message)) {
685
+ await config.onTaskProvenanceEvent?.("task.provenance.entry_denied", {
686
+ taskId: taskCtx.taskId,
687
+ diaryId: targetDiaryId,
688
+ error: message
689
+ });
690
+ throw new Error(`entries_create: the task provenance diary denied this entry. The diary may have moved to another team or its grants may have changed. The task and runtime session remain active; ask a diary manager to restore write access, then retry. (${message})`, { cause: error });
691
+ }
692
+ throw error;
693
+ }
688
694
  return {
689
695
  content: [{
690
696
  type: "text",
@@ -1296,21 +1302,6 @@ async function resolvePersistentSessionManager(args) {
1296
1302
  await SessionManager.list(args.cwd, args.sessionDir);
1297
1303
  return SessionManager.continueRecent(args.cwd, args.sessionDir);
1298
1304
  }
1299
- new TextEncoder();
1300
- //#endregion
1301
- //#region ../crypto-service/src/crypto.service.ts
1302
- ed.etc.sha512Sync = (...m) => {
1303
- const hash = createHash("sha512");
1304
- m.forEach((msg) => hash.update(msg));
1305
- return hash.digest();
1306
- };
1307
- //#endregion
1308
- //#region ../crypto-service/src/executor-attestation.ts
1309
- ed.etc.sha512Sync = (...m) => {
1310
- const hash = createHash$1("sha512");
1311
- m.forEach((msg) => hash.update(msg));
1312
- return hash.digest();
1313
- };
1314
1305
  //#endregion
1315
1306
  //#region ../crypto-service/src/json-cid.ts
1316
1307
  /**
@@ -1326,19 +1317,6 @@ async function computeJsonCid(value) {
1326
1317
  return CID.create(1, json.code, hash).toString();
1327
1318
  }
1328
1319
  //#endregion
1329
- //#region ../crypto-service/src/ssh.ts
1330
- /**
1331
- * SSH key format conversion for MoltNet Ed25519 keys
1332
- *
1333
- * Converts MoltNet agent keys (ed25519:<base64>) to OpenSSH format
1334
- * for use with git commit signing and SSH authentication.
1335
- */
1336
- if (!ed.etc.sha512Sync) ed.etc.sha512Sync = (...m) => {
1337
- const hash = createHash("sha512");
1338
- m.forEach((msg) => hash.update(msg));
1339
- return hash.digest();
1340
- };
1341
- //#endregion
1342
1320
  //#region src/config.ts
1343
1321
  /** Resolve Pi's host-side auth/config directory from process configuration. */
1344
1322
  function resolvePiCodingAgentDir() {
@@ -1953,10 +1931,10 @@ Type$1.Object({
1953
1931
  Type$1.Literal("completed"),
1954
1932
  Type$1.Literal("failed")
1955
1933
  ]),
1956
- githubCode: Type$1.Optional(Type$1.String()),
1934
+ githubCode: Type$1.Optional(Type$1.String({ description: "GitHub manifest code sealed to the onboarding agent public key." })),
1957
1935
  identityId: Type$1.Optional(Type$1.String()),
1958
1936
  clientId: Type$1.Optional(Type$1.String()),
1959
- clientSecret: Type$1.Optional(Type$1.String()),
1937
+ clientSecret: Type$1.Optional(Type$1.String({ description: "OAuth2 client secret sealed to the onboarding agent public key." })),
1960
1938
  installationId: Type$1.Optional(Type$1.String())
1961
1939
  });
1962
1940
  Type$1.Object({
@@ -2139,6 +2117,23 @@ var DiaryGrantResponseSchema = Type$1.Object({
2139
2117
  });
2140
2118
  Type$1.Object({ grants: Type$1.Array(DiaryGrantResponseSchema) });
2141
2119
  Type$1.Object({ revoked: Type$1.Boolean() });
2120
+ var TaskGrantRoleSchema = Type$1.Union([Type$1.Literal("writer"), Type$1.Literal("manager")]);
2121
+ Type$1.Object({
2122
+ subjectId: UuidSchema,
2123
+ subjectNs: GrantSubjectNsSchema,
2124
+ role: TaskGrantRoleSchema
2125
+ });
2126
+ Type$1.Object({
2127
+ subjectId: UuidSchema,
2128
+ subjectNs: GrantSubjectNsSchema,
2129
+ role: TaskGrantRoleSchema
2130
+ });
2131
+ var TaskGrantResponseSchema = Type$1.Object({
2132
+ subjectId: UuidSchema,
2133
+ subjectNs: GrantSubjectNsSchema,
2134
+ role: TaskGrantRoleSchema
2135
+ });
2136
+ Type$1.Object({ grants: Type$1.Array(TaskGrantResponseSchema) });
2142
2137
  Type$1.Object({ "x-moltnet-team-id": Type$1.String({
2143
2138
  format: "uuid",
2144
2139
  description: "Team ID (UUID) that will own the resource. Required."
@@ -3851,7 +3846,7 @@ Type$1.Object({
3851
3846
  allowedProfiles: Type$1.Array(RuntimeProfileRef, { maxItems: 16 }),
3852
3847
  status: TaskStatus,
3853
3848
  queuedAt: IsoTimestamp,
3854
- completedAt: Type$1.Union([IsoTimestamp, Type$1.Null()]),
3849
+ completedAt: Type$1.Union([IsoTimestamp, Type$1.Null()], { description: "First time the task entered completed, failed, cancelled, or expired; null until terminal." }),
3855
3850
  expiresAt: Type$1.Union([IsoTimestamp, Type$1.Null()]),
3856
3851
  cancelledByAgentId: Type$1.Union([Uuid, Type$1.Null()]),
3857
3852
  cancelledByHumanId: Type$1.Union([Uuid, Type$1.Null()]),
@@ -4028,7 +4023,7 @@ function getCacheDir() {
4028
4023
  return path.join(base, "moltnet", "gondolin");
4029
4024
  }
4030
4025
  function computeConfigHash(config) {
4031
- const h = createHash$1("sha256");
4026
+ const h = createHash("sha256");
4032
4027
  h.update(JSON.stringify({
4033
4028
  baseAlpine: BASE_ALPINE_PACKAGES,
4034
4029
  ghVersion: GH_VERSION,
@@ -5470,7 +5465,7 @@ function decideToolCall(input) {
5470
5465
  return fenced(input.enforcement, "tool_not_permitted", `not permitted by tool policy: ${missing.join(", ")}`, `would block (watch): ${missing.join(", ")}`, missing, missingShellCommands);
5471
5466
  }
5472
5467
  function fingerprintArgv(argv) {
5473
- return `sha256:${createHash$1("sha256").update(JSON.stringify(argv.map((token) => token === null ? { dynamic: true } : token))).digest("hex").slice(0, 16)}`;
5468
+ return `sha256:${createHash("sha256").update(JSON.stringify(argv.map((token) => token === null ? { dynamic: true } : token))).digest("hex").slice(0, 16)}`;
5474
5469
  }
5475
5470
  function toMatchedShellCommand(executable, argvPrefix) {
5476
5471
  return {
@@ -7662,6 +7657,11 @@ async function executePiTask(claimedTask, reporter, opts) {
7662
7657
  attemptN,
7663
7658
  diaryId,
7664
7659
  correlationId: task.correlationId ?? null
7660
+ }),
7661
+ onTaskProvenanceEvent: (event, details) => emit("info", {
7662
+ event,
7663
+ severity: "warn",
7664
+ ...details
7665
7665
  })
7666
7666
  });
7667
7667
  const piAuthDir = resolvePiCodingAgentDir();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@themoltnet/pi-runtime",
3
- "version": "0.9.0",
3
+ "version": "0.10.1",
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.42.0",
34
+ "@themoltnet/agent-runtime": "0.43.1",
35
+ "@themoltnet/sdk": "0.135.0",
35
36
  "@themoltnet/os-keyring": "0.2.0",
36
- "@themoltnet/sdk": "0.133.0",
37
37
  "@themoltnet/shell-command-analyzer": "0.3.0"
38
38
  },
39
39
  "peerDependencies": {
@@ -52,8 +52,8 @@
52
52
  "vite-plugin-dts": "^4.5.4",
53
53
  "vitest": "^3.0.0",
54
54
  "@moltnet/models": "0.1.0",
55
- "@moltnet/tasks": "0.1.0",
56
- "@moltnet/crypto-service": "0.1.0"
55
+ "@moltnet/crypto-service": "0.1.0",
56
+ "@moltnet/tasks": "0.1.0"
57
57
  },
58
58
  "engines": {
59
59
  "node": ">=24"