@oas-framework/pi 0.6.2 → 0.7.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/README.md CHANGED
@@ -1,31 +1,30 @@
1
1
  # @oas-framework/pi
2
2
 
3
- The OAS pi adapter for [pi](https://github.com/earendil-works/pi). It
4
- handles the pi-specific glue over the globally installed OAS kernel:
3
+ Minimal pi adapter for [OAS](https://github.com/josep-reyero/oas-framework).
5
4
 
6
- - **Skill discovery** the global `oas-getting-started` skill, the OAS
7
- skill bundle inside OAS workspaces, and workspace skills above the git
8
- repo boundary.
9
- - **Instance memory automation** — compaction journaling and STATE.md
10
- resume nudges for spawned agent instances.
5
+ The runtime-neutral kernel and universal `oas` CLI live in
6
+ `@oas-framework/oas`. This adapter registers no operational tools. It only:
11
7
 
12
- It registers **no tools**: all agent operations (status, create, spawn,
13
- retire) and configuration run through the universal `oas` CLI, which agents
14
- invoke with the bash tool identically in pi, Claude Code, or a plain
15
- shell. The kernel, CLI, skills, injects, and bundled integrations all live
16
- in the globally installed
17
- [`@oas-framework/oas`](https://www.npmjs.com/package/@oas-framework/oas)
18
- package — the single source of truth shared by every runtime adapter.
8
+ - exposes `oas-getting-started` before an OAS workspace exists;
9
+ - points spawned sessions at their exact instance-local `.agents/skills` set;
10
+ - journals compaction summaries and sends resume nudges when the active
11
+ knowledge capability created `STATE.md`/`log.md`.
19
12
 
20
- ## Install
13
+ The kernel launches pi with `--no-skills --skill <instance>/.agents/skills`,
14
+ so user, project, settings, ancestor, and pi-package skill discovery cannot
15
+ pollute one soul's selected runtime surface.
21
16
 
22
17
  ```bash
23
- npm install -g @oas-framework/oas # the kernel + oas CLI (required)
24
- pi install npm:@oas-framework/pi # this adapter
18
+ npm install -g @oas-framework/oas
19
+ pi install npm:@oas-framework/pi
25
20
  ```
26
21
 
27
- The adapter locates the kernel via the `oas` binary on PATH (override with
28
- `OAS_PKG_ROOT`, e.g. to point at a dev clone).
22
+ Install matching versions and upgrade both packages together. Exact isolation
23
+ needs the new kernel launch flags and this adapter's instance-only discovery.
24
+ An older adapter still contributes workspace and package skill roots. OAS
25
+ publishes both packages from the same version tag. Reload pi after an adapter
26
+ install or upgrade.
29
27
 
30
- See the [oas-framework repo](https://github.com/josep-reyero/oas-framework)
31
- for the full documentation.
28
+ All lifecycle/config/package operations use the shell-visible CLI: `oas
29
+ status`, `oas spawn`, `oas doctor`, `oas install`, `oas trust`, `oas use`, and
30
+ `oas retire`.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * core-loader.mjs — locate the globally installed @oas-framework/oas kernel and
3
3
  * re-export its lib/core.mjs. The pi package is a thin adapter: it never ships
4
- * the kernel, skills, injects, or integrations — those live in the global CLI
4
+ * the kernel, skills, injects, or capabilities — those live in the global CLI
5
5
  * package (npm i -g @oas-framework/oas), the single source of truth that the
6
6
  * future Claude plugin shares.
7
7
  *
@@ -54,9 +54,7 @@ if (!OAS_PKG_ROOT) {
54
54
 
55
55
  const core = await import(pathToFileURL(join(OAS_PKG_ROOT, "lib", "core.mjs")).href);
56
56
 
57
- export const {
58
- appendLogEntry, PACKAGED_SKILLS_DIR, workspaceConfigSkillDirs, isOasWorkspace,
59
- } = core;
57
+ export const { appendLogEntry, PACKAGED_SKILLS_DIR } = core;
60
58
 
61
59
  /** Kernel package version (for skew diagnostics against the adapter). */
62
60
  export function kernelVersion() {
@@ -1,79 +1,29 @@
1
1
  /**
2
- * oas pi adapter — pi-specific glue over the globally installed OAS kernel.
2
+ * OAS pi adapter — minimal runtime glue.
3
3
  *
4
- * Everything agents DO goes through the universal `oas` CLI (status, spawn,
5
- * retire, create, doctor, integration commands) from the bash tool. This
6
- * extension only handles what a runtime must integrate natively:
7
- *
8
- * - skill discovery (resources_discover): the global getting-started skill,
9
- * the OAS skill bundle inside OAS contexts, workspace skills above the
10
- * repo boundary, and config-cascade skill dirs
11
- * - instance memory automation: compaction journaling + STATE.md steers,
12
- * and the resume nudge on session start
4
+ * Skill visibility is deliberately instance-local. Outside an instance, only
5
+ * oas-getting-started is contributed as pre-workspace bootstrap. The kernel
6
+ * materializes every spawned instance's exact set in .agents/skills.
13
7
  */
14
8
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
15
- import {
16
- appendLogEntry, isOasWorkspace, workspaceConfigSkillDirs, PACKAGED_SKILLS_DIR,
17
- } from "./core-loader.mjs";
9
+ import { appendLogEntry, PACKAGED_SKILLS_DIR } from "./core-loader.mjs";
18
10
  import { existsSync, readFileSync } from "node:fs";
19
- import { dirname, join, resolve } from "node:path";
20
-
21
- /** .agents/skills dirs in ancestors ABOVE the git repo root — pi's own walk stops at the
22
- * repo root, so workspace-level skills (e.g. <workspace>/.agents/skills) need contributing. */
23
- function workspaceSkillDirs(cwd: string): string[] {
24
- let repoRoot: string | undefined;
25
- let d = resolve(cwd);
26
- while (true) {
27
- if (existsSync(join(d, ".git"))) { repoRoot = d; break; }
28
- const parent = dirname(d);
29
- if (parent === d) break;
30
- d = parent;
31
- }
32
- if (!repoRoot) return []; // not in a repo: pi already walks to the filesystem root
33
- const dirs: string[] = [];
34
- d = dirname(repoRoot);
35
- while (true) {
36
- const cand = join(d, ".agents", "skills");
37
- if (existsSync(cand)) dirs.push(cand);
38
- const parent = dirname(d);
39
- if (parent === d) break;
40
- d = parent;
41
- }
42
- return dirs;
43
- }
11
+ import { join } from "node:path";
44
12
 
45
13
  export default function (pi: ExtensionAPI) {
46
- // (PI_AGENT_HOME is set by the kernel's launch command)
47
14
  const agentHome = process.env.PI_AGENT_HOME;
48
- const isInstance = !!agentHome && existsSync(join(agentHome ?? "", "instance.json"));
15
+ const isInstance = !!agentHome && existsSync(join(agentHome, "instance.json"));
49
16
 
50
- // ---------- OAS skills ----------
51
- // getting-started is GLOBAL (it bootstraps — must be discoverable before any OAS
52
- // workspace exists). The rest of the bundle is gated to OAS contexts (instance
53
- // home, or a workspace/repo with an oas-config / agents root). Workspace and
54
- // config skills stay trust-gated.
55
- pi.on("resources_discover", async (event, ctx) => {
56
- const paths: string[] = [];
57
- const gettingStarted = join(PACKAGED_SKILLS_DIR, "oas-getting-started");
58
- if (existsSync(gettingStarted)) paths.push(gettingStarted);
59
- const inOas = isInstance || isOasWorkspace(event.cwd);
60
- if (inOas && existsSync(PACKAGED_SKILLS_DIR)) paths.push(PACKAGED_SKILLS_DIR);
61
- if (ctx.isProjectTrusted()) {
62
- paths.push(...workspaceSkillDirs(event.cwd));
63
- for (const p of workspaceConfigSkillDirs(event.cwd)) if (!paths.includes(p)) paths.push(p);
17
+ pi.on("resources_discover", async () => {
18
+ if (isInstance) {
19
+ const local = join(agentHome!, ".agents", "skills");
20
+ return existsSync(local) ? { skillPaths: [local] } : undefined;
64
21
  }
65
- if (paths.length === 0) return;
66
- return { skillPaths: paths };
22
+ const gettingStarted = join(PACKAGED_SKILLS_DIR, "oas-getting-started");
23
+ return existsSync(gettingStarted) ? { skillPaths: [gettingStarted] } : undefined;
67
24
  });
68
25
 
69
- // ---------- inside a spawned instance: memory automation ----------
70
26
  if (isInstance) {
71
- // Memory automation is gated on the knowledge integration having scaffolded
72
- // instance memory (STATE.md/log.md are OKF conventions — kernel is agnostic;
73
- // an instance without a knowledge integration has neither file, so both
74
- // hooks below no-op for it).
75
- // Compaction survival: journal every compaction summary to the instance log,
76
- // and remind the model to refresh STATE.md — zero agent discipline required.
77
27
  pi.on("session_compact", async (event) => {
78
28
  if (!existsSync(join(agentHome!, "STATE.md"))) return;
79
29
  try {
@@ -83,7 +33,7 @@ export default function (pi: ExtensionAPI) {
83
33
  `**Compaction** (${event.reason}): ${summary.slice(0, 400)}${summary.length > 400 ? "…" : ""}`,
84
34
  "Instance Log",
85
35
  );
86
- } catch { /* never break the session over journaling */ }
36
+ } catch { /* memory automation must never break a session */ }
87
37
  pi.sendMessage({
88
38
  customType: "oas-memory",
89
39
  content: "Context was just compacted. Before continuing, update ./STATE.md (Plan/Progress/Next) so a fresh session could resume from files alone.",
@@ -91,15 +41,13 @@ export default function (pi: ExtensionAPI) {
91
41
  }, { deliverAs: "steer" });
92
42
  });
93
43
 
94
- // Resume nudge: on any later session in this home (restart, model switch, /new),
95
- // point the model at its own memory before it does anything else.
96
44
  pi.on("session_start", async (event) => {
97
45
  if (event.reason !== "startup" && event.reason !== "resume" && event.reason !== "new") return;
98
46
  const statePath = join(agentHome!, "STATE.md");
99
47
  if (!existsSync(statePath)) return;
100
48
  const state = readFileSync(statePath, "utf8");
101
49
  const touched = !/_No task assigned yet/.test(state) || !/_\(the single next action/.test(state);
102
- if (event.reason === "startup" && !touched) return; // fresh spawn — TASK.md covers it
50
+ if (event.reason === "startup" && !touched) return;
103
51
  pi.sendMessage({
104
52
  customType: "oas-memory",
105
53
  content: `You are agent instance home ${agentHome}. Read ./STATE.md and the recent entries of ./log.md now, then continue from STATE.md's "Next" section. Keep STATE.md current as you work.`,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oas-framework/pi",
3
- "version": "0.6.2",
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",
3
+ "version": "0.7.0",
4
+ "description": "Minimal OAS pi adapter — instance-local skill discovery and memory session events over the runtime-neutral @oas-framework/oas kernel",
5
5
  "keywords": [
6
6
  "pi-package",
7
7
  "agents",