@themoltnet/pi-extension 0.24.1 → 0.25.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 CHANGED
@@ -505,6 +505,12 @@ export declare interface PiTaskExecutionPlan {
505
505
  * worktree is required.
506
506
  */
507
507
  worktreeBranch: string | null;
508
+ /**
509
+ * Base ref a NEW `worktreeBranch` is cut from. Used by `fork` continuations
510
+ * to branch from the parent's tip instead of the default (main/HEAD). Ignored
511
+ * when `worktreeBranch` already exists.
512
+ */
513
+ worktreeBaseRef?: string | null;
508
514
  /**
509
515
  * Lifetime of the task workspace from the daemon's point of view.
510
516
  * `attempt` = disposable; `session` = keep stable for the reuse key.
package/dist/index.js CHANGED
@@ -13482,6 +13482,54 @@ function validateRubricWeights(rubric) {
13482
13482
  return null;
13483
13483
  }
13484
13484
  //#endregion
13485
+ //#region ../tasks/src/runtime-models.ts
13486
+ /**
13487
+ * Runtime model catalog: a list of supported provider/model couples that
13488
+ * MoltNet daemons can target. Backed by the `runtime_models` table.
13489
+ *
13490
+ * Scope is intrinsic to the row:
13491
+ * - `teamId == null` => global entry (MoltNet-seeded, read-only to most callers)
13492
+ * - `teamId != null` => team-owned custom entry
13493
+ *
13494
+ * The REST API exposes a single shape regardless of scope; the team header
13495
+ * gates which rows are returned.
13496
+ */
13497
+ var RuntimeModelProvider = String$1({
13498
+ minLength: 1,
13499
+ maxLength: 100,
13500
+ pattern: "^[a-zA-Z0-9][a-zA-Z0-9._-]{0,99}$"
13501
+ });
13502
+ var RuntimeModelName = String$1({
13503
+ minLength: 1,
13504
+ maxLength: 200,
13505
+ pattern: "^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,199}$"
13506
+ });
13507
+ var RuntimeModelCapabilities = Record(String$1({
13508
+ minLength: 1,
13509
+ maxLength: 64
13510
+ }), Union([
13511
+ Boolean$1(),
13512
+ Number$1(),
13513
+ String$1({ maxLength: 256 })
13514
+ ]));
13515
+ _Object_({
13516
+ id: String$1({ format: "uuid" }),
13517
+ teamId: Union([String$1({ format: "uuid" }), Null()]),
13518
+ provider: RuntimeModelProvider,
13519
+ model: RuntimeModelName,
13520
+ displayName: Union([String$1({ maxLength: 200 }), Null()]),
13521
+ description: Union([String$1({ maxLength: 4096 }), Null()]),
13522
+ capabilities: RuntimeModelCapabilities,
13523
+ isActive: Boolean$1(),
13524
+ createdByAgentId: Union([String$1({ format: "uuid" }), Null()]),
13525
+ createdByHumanId: Union([String$1({ format: "uuid" }), Null()]),
13526
+ createdAt: String$1({ format: "date-time" }),
13527
+ updatedAt: String$1({ format: "date-time" })
13528
+ }, {
13529
+ $id: "RuntimeModel",
13530
+ additionalProperties: false
13531
+ });
13532
+ //#endregion
13485
13533
  //#region ../tasks/src/runtime-profiles.ts
13486
13534
  var RuntimeProfileName = String$1({
13487
13535
  minLength: 1,
@@ -14022,20 +14070,17 @@ var FreeformOutput = _Object_({
14022
14070
  * 3. `freeform.sourceAttemptNotCompleted` — named attempt is missing
14023
14071
  * or not in `completed` state; warm continuation only makes sense
14024
14072
  * once the parent has produced a terminal output.
14025
- * 4. `freeform.forkModeNotImplemented` — `mode: 'fork'` is the wire
14026
- * surface for copy-on-write continuation tracked in #1293; v1
14027
- * rejects it server-side so daemons never have to branch.
14028
- * 5. `freeform.executionWorkspaceNotInheritable` — caller set
14073
+ * 4. `freeform.executionWorkspaceNotInheritable` — caller set
14029
14074
  * `execution.workspace` together with `continueFrom`. Workspace
14030
14075
  * mode for a continuation is inherited from the parent slot
14031
14076
  * (`maybeAttachWarmSlotContext` forces `dedicated_worktree` +
14032
14077
  * the parent's worktreeBranch), so any caller-supplied override
14033
14078
  * is silently dropped at the daemon plan stage. Reject explicitly
14034
14079
  * so misconfiguration surfaces at create time.
14035
- * 6. `freeform.sourceNotResumeEligible` — `daemonState` is null or
14080
+ * 5. `freeform.sourceNotResumeEligible` — `daemonState` is null or
14036
14081
  * `slotResumableUntil` is null. Older completions (pre-#1287) and
14037
14082
  * daemons that opt out fall here.
14038
- * 7. `freeform.sourceResumeExpired` — `slotResumableUntil` is in the
14083
+ * 6. `freeform.sourceResumeExpired` — `slotResumableUntil` is in the
14039
14084
  * past; the warm slot's TTL has elapsed and no daemon is
14040
14085
  * guaranteed to still hold it.
14041
14086
  *
@@ -14056,11 +14101,6 @@ async function validateFreeformInputAsync(input, ctx) {
14056
14101
  message: `Source task type '${source.taskType}' is not continuable; only freeform → freeform is supported in v1`,
14057
14102
  code: "freeform.sourceTaskTypeNotSupported"
14058
14103
  }];
14059
- if (cf.mode === "fork") return [{
14060
- field: "input/continueFrom/mode",
14061
- message: "fork mode not yet implemented; see https://github.com/getlarge/themoltnet/issues/1293",
14062
- code: "freeform.forkModeNotImplemented"
14063
- }];
14064
14104
  if (input.execution?.workspace) return [{
14065
14105
  field: "input/execution/workspace",
14066
14106
  message: "execution.workspace is inherited from the parent slot when continueFrom is set; omit it",
@@ -23215,10 +23255,11 @@ function prepareTaskWorkspace(task, requestedMountPath, executionPlan) {
23215
23255
  const relMount = relative(mainRepo, requestedMountPath);
23216
23256
  const cwdPath = relMount === "" || relMount.startsWith("..") ? worktreeDir : join(worktreeDir, relMount);
23217
23257
  const keepWorkspace = executionPlan?.workspaceScope === "session" && executionPlan.sessionKey !== null;
23218
- if (keepWorkspace) ensureReusableTaskWorktree(mainRepo, worktreeDir, branch);
23258
+ const baseRefOverride = executionPlan?.worktreeBaseRef ?? null;
23259
+ if (keepWorkspace) ensureReusableTaskWorktree(mainRepo, worktreeDir, branch, baseRefOverride);
23219
23260
  else {
23220
23261
  removeExistingTaskWorktree(mainRepo, worktreeDir);
23221
- addTaskWorktree(mainRepo, worktreeDir, branch);
23262
+ addTaskWorktree(mainRepo, worktreeDir, branch, baseRefOverride);
23222
23263
  }
23223
23264
  return {
23224
23265
  mountPath: mainRepo,
@@ -23243,14 +23284,15 @@ function resolveTaskWorktreePath(mainRepo, workspaceId) {
23243
23284
  function resolveTaskScratchPath(mainRepo, workspaceId) {
23244
23285
  return join(mainRepo, ".moltnet", "d", "task-workspaces", workspaceId);
23245
23286
  }
23246
- function ensureReusableTaskWorktree(mainRepo, worktreeDir, branch) {
23287
+ function ensureReusableTaskWorktree(mainRepo, worktreeDir, branch, baseRefOverride = null) {
23247
23288
  if (isRegisteredWorktree(mainRepo, worktreeDir)) return;
23248
23289
  if (existsSync(worktreeDir)) throw new Error(`Expected reusable worktree ${worktreeDir} to be git-managed, but it exists outside git worktree metadata.`);
23249
- addTaskWorktree(mainRepo, worktreeDir, branch);
23290
+ addTaskWorktree(mainRepo, worktreeDir, branch, baseRefOverride);
23250
23291
  }
23251
- function addTaskWorktree(mainRepo, worktreeDir, branch) {
23252
- const baseRef = resolveWorktreeBaseRef(mainRepo);
23253
- execFileSync("git", gitRefExists(mainRepo, `refs/heads/${branch}`) ? [
23292
+ function addTaskWorktree(mainRepo, worktreeDir, branch, baseRefOverride = null) {
23293
+ const branchExists = gitRefExists(mainRepo, `refs/heads/${branch}`);
23294
+ const baseRef = baseRefOverride ?? resolveWorktreeBaseRef(mainRepo);
23295
+ execFileSync("git", branchExists ? [
23254
23296
  "-C",
23255
23297
  mainRepo,
23256
23298
  "worktree",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@themoltnet/pi-extension",
3
- "version": "0.24.1",
3
+ "version": "0.25.0",
4
4
  "type": "module",
5
5
  "description": "MoltNet pi extension — sandboxed tool execution in Gondolin VMs with MoltNet identity and persistent memory",
6
6
  "keywords": [
@@ -36,8 +36,8 @@
36
36
  "@earendil-works/gondolin": "^0.9.1",
37
37
  "@opentelemetry/api": "^1.9.0",
38
38
  "typebox": "^1.2.8",
39
- "@themoltnet/agent-runtime": "0.25.0",
40
- "@themoltnet/sdk": "0.108.0"
39
+ "@themoltnet/sdk": "0.108.0",
40
+ "@themoltnet/agent-runtime": "0.25.0"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "@earendil-works/pi-coding-agent": ">=0.74.0",
@@ -53,7 +53,7 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "@earendil-works/pi-ai": "^0.74.0",
56
- "@earendil-works/pi-coding-agent": "^0.74.0",
56
+ "@earendil-works/pi-coding-agent": "^0.79.4",
57
57
  "@opentelemetry/sdk-metrics": "^2.5.1",
58
58
  "@opentelemetry/sdk-trace-base": "^2.5.1",
59
59
  "@types/node": "^22.19.0",
@@ -61,8 +61,8 @@
61
61
  "vite": "^8.0.0",
62
62
  "vite-plugin-dts": "^4.5.4",
63
63
  "vitest": "^3.0.0",
64
- "@moltnet/crypto-service": "0.1.0",
65
- "@moltnet/tasks": "0.1.0"
64
+ "@moltnet/tasks": "0.1.0",
65
+ "@moltnet/crypto-service": "0.1.0"
66
66
  },
67
67
  "engines": {
68
68
  "node": ">=22"