@oas-framework/pi 0.4.0 → 0.5.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.
Files changed (2) hide show
  1. package/extension/index.ts +16 -27
  2. package/package.json +1 -1
@@ -17,7 +17,7 @@ import { StringEnum } from "@earendil-works/pi-ai";
17
17
  import {
18
18
  appendLogEntry, createAgent, defaultRepo, ensureRoot, findAgent, findRoot, listAgentDefs, listAgents,
19
19
  listInstances, retireInstance, spawnInstance, upsertTmpAgent, workspaceOf, writeSoul, PACKAGED_SKILLS_DIR,
20
- workspaceConfigSkillDirs, isOasWorkspace, resolveOasConfig, runLifecycleHooks,
20
+ workspaceConfigSkillDirs, isOasWorkspace,
21
21
  } from "./core-loader.mjs";
22
22
  import { existsSync, readFileSync } from "node:fs";
23
23
  import { dirname, join, resolve } from "node:path";
@@ -94,11 +94,15 @@ export default function (pi: ExtensionAPI) {
94
94
  const agentHome = process.env.PI_AGENT_HOME;
95
95
  const isInstance = !!agentHome && existsSync(join(agentHome ?? "", "instance.json"));
96
96
 
97
- // ---------- kernel + workspace skills: only inside OAS workspaces ----------
98
- // (a workspace/repo with an oas-config, an agents/ root, or an instance home —
99
- // agents elsewhere on the machine do not get OAS skills)
97
+ // ---------- OAS skills ----------
98
+ // getting-started is GLOBAL (it bootstraps must be discoverable before any OAS
99
+ // workspace exists). The rest of the bundle is gated to OAS contexts (instance
100
+ // home, or a workspace/repo with an oas-config / agents root). Workspace and
101
+ // config skills stay trust-gated.
100
102
  pi.on("resources_discover", async (event, ctx) => {
101
103
  const paths: string[] = [];
104
+ const gettingStarted = join(PACKAGED_SKILLS_DIR, "oas-getting-started");
105
+ if (existsSync(gettingStarted)) paths.push(gettingStarted);
102
106
  const inOas = isInstance || isOasWorkspace(event.cwd);
103
107
  if (inOas && existsSync(PACKAGED_SKILLS_DIR)) paths.push(PACKAGED_SKILLS_DIR);
104
108
  if (ctx.isProjectTrusted()) {
@@ -135,25 +139,9 @@ export default function (pi: ExtensionAPI) {
135
139
  }, { deliverAs: "steer" });
136
140
  });
137
141
 
138
- // Post-commit lifecycle: after a successful `git commit` by this instance, fire
139
- // the integrations' post-commit hooks (e.g. oas-okf spawns a knowledge-harvest
140
- // agent attached to this instance's work tree). Kernel stays layer-agnostic.
141
- pi.on("tool_result", async (event) => {
142
- if (event.toolName !== "bash" || event.isError) return;
143
- const cmd = String((event.input as { command?: string })?.command ?? "");
144
- if (!/\bgit\b[^\n;&|]*\bcommit\b/.test(cmd)) return;
145
- try {
146
- const meta = JSON.parse(readFileSync(join(agentHome!, "instance.json"), "utf8"));
147
- const root = findRoot(agentHome!);
148
- if (!root || !meta.repo) return;
149
- runLifecycleHooks("post-commit", {
150
- home: agentHome!, instance: meta.instance, agentName: meta.agent,
151
- soulDir: join(agentHome!, "soul"), contextDir: meta.repo,
152
- workspaceDir: workspaceOf(root), rootDir: root,
153
- resolved: resolveOasConfig(meta.repo), priorMeta: meta.providerMeta || {},
154
- });
155
- } catch { /* hooks never break the session */ }
156
- });
142
+ // (post-commit harvest is agent-initiated now the okf injection/skill tell the
143
+ // instance to run the integration's `harvest` entry after committing with notes;
144
+ // the kernel no longer watches git commits.)
157
145
 
158
146
  // Resume nudge: on any later session in this home (restart, model switch, /new),
159
147
  // point the model at its own memory before it does anything else.
@@ -202,9 +190,10 @@ export default function (pi: ExtensionAPI) {
202
190
  purpose: Type.Optional(Type.String({ description: "Short kebab slug describing what this instance is for; names the instance <agent>-<purpose>" })),
203
191
  model: Type.Optional(Type.String({ description: "Model as provider/id (must be enabled in pi); defaults to the soul's model or pi's default" })),
204
192
  repo: Type.Optional(Type.String({ description: "Target repo (absolute, or relative to the agents root's parent). Defaults to the soul's repo, else the current git repo" })),
205
- work: Type.Optional(StringEnum(["worktree", "checkout"] as const, {
206
- description: "worktree = own git worktree + branch; checkout = work directly on the repo's checked-out branch. Defaults to the soul's setting",
193
+ work: Type.Optional(StringEnum(["worktree", "checkout", "attached"] as const, {
194
+ description: "worktree = own git worktree + branch; checkout = work directly on the repo's checked-out branch; attached = share ANOTHER instance's work tree (requires workDir). Defaults to the soul's setting",
207
195
  })),
196
+ workDir: Type.Optional(Type.String({ description: "attached mode: the owning instance's work tree (its <home>/work) to attach to" })),
208
197
  runtime: Type.Optional(StringEnum(["pi", "claude"] as const, { description: "Session runtime (default: soul's setting, else pi)" })),
209
198
  branch: Type.Optional(Type.String({ description: "Branch name for worktree mode (default: agents/<instance>)" })),
210
199
  launch: Type.Optional(Type.Boolean({ description: "Launch in tmux (default true). false = scaffold only and return the launch command" })),
@@ -235,7 +224,7 @@ export default function (pi: ExtensionAPI) {
235
224
 
236
225
  const result = spawnInstance(root, agent!, {
237
226
  instance: undefined, purpose: p.purpose, repo: p.repo || agent!.repo || defaultRepo(ctx.cwd),
238
- work: p.work, runtime: p.runtime, model, task: p.task, branch: p.branch, launch: p.launch,
227
+ work: p.work, workDir: p.workDir, runtime: p.runtime, model, task: p.task, branch: p.branch, launch: p.launch,
239
228
  });
240
229
  return { ...text(JSON.stringify(result, null, 2)), details: result };
241
230
  },
@@ -418,7 +407,7 @@ export default function (pi: ExtensionAPI) {
418
407
  parameters: Type.Object({
419
408
  name: Type.String(),
420
409
  repo: Type.Optional(Type.String({ description: "Target repo (absolute, or relative to the agents root's parent)" })),
421
- work: Type.Optional(StringEnum(["worktree", "checkout"] as const)),
410
+ work: Type.Optional(StringEnum(["worktree", "checkout", "attached"] as const)),
422
411
  runtime: Type.Optional(StringEnum(["pi", "claude"] as const)),
423
412
  model: Type.Optional(Type.String({ description: "Default model as provider/id (must be enabled in pi)" })),
424
413
  description: Type.Optional(Type.String()),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oas-framework/pi",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "OAS pi adapter — agent tools (spawn_agent, agents_status, retire_agent) and skill discovery for pi, over the globally installed @oas-framework/oas kernel",
5
5
  "keywords": [
6
6
  "pi-package",