@ikenga/contract 0.6.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/README.md +56 -11
- package/dist/canvas/Canvas.d.ts +7 -0
- package/dist/canvas/Canvas.d.ts.map +1 -0
- package/dist/canvas/Canvas.js +115 -0
- package/dist/canvas/Canvas.js.map +1 -0
- package/dist/canvas/canvas.css +579 -0
- package/dist/canvas/index.d.ts +7 -0
- package/dist/canvas/index.d.ts.map +1 -0
- package/dist/canvas/index.js +4 -0
- package/dist/canvas/index.js.map +1 -0
- package/dist/canvas/types.d.ts +45 -0
- package/dist/canvas/types.d.ts.map +1 -0
- package/dist/canvas/types.js +2 -0
- package/dist/canvas/types.js.map +1 -0
- package/dist/canvas/use-drag-snap.d.ts +33 -0
- package/dist/canvas/use-drag-snap.d.ts.map +1 -0
- package/dist/canvas/use-drag-snap.js +73 -0
- package/dist/canvas/use-drag-snap.js.map +1 -0
- package/dist/canvas/use-pan-zoom.d.ts +32 -0
- package/dist/canvas/use-pan-zoom.d.ts.map +1 -0
- package/dist/canvas/use-pan-zoom.js +161 -0
- package/dist/canvas/use-pan-zoom.js.map +1 -0
- package/dist/engine/index.d.ts +2 -0
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +2 -0
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/portability.d.ts +113 -0
- package/dist/engine/portability.d.ts.map +1 -0
- package/dist/engine/portability.js +17 -0
- package/dist/engine/portability.js.map +1 -0
- package/dist/engine/subagent-transcoder.d.ts +24 -0
- package/dist/engine/subagent-transcoder.d.ts.map +1 -0
- package/dist/engine/subagent-transcoder.js +341 -0
- package/dist/engine/subagent-transcoder.js.map +1 -0
- package/dist/engine.d.ts +574 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +85 -0
- package/dist/engine.js.map +1 -0
- package/dist/host-verbs.d.ts +194 -0
- package/dist/host-verbs.d.ts.map +1 -0
- package/dist/host-verbs.js +15 -0
- package/dist/host-verbs.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/manifest.d.ts +376 -19
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +95 -4
- package/dist/manifest.js.map +1 -1
- package/dist/registry.d.ts +364 -36
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +9 -0
- package/dist/registry.js.map +1 -1
- package/dist/scopes.js +1 -1
- package/dist/scopes.js.map +1 -1
- package/package.json +36 -10
- package/schemas/registry/index-v1.json +11 -0
- package/src/canvas/Canvas.tsx +161 -0
- package/src/canvas/canvas.css +579 -0
- package/src/canvas/index.ts +14 -0
- package/src/canvas/types.ts +48 -0
- package/src/canvas/use-drag-snap.ts +107 -0
- package/src/canvas/use-pan-zoom.ts +211 -0
- package/src/engine/index.ts +2 -0
- package/src/engine/portability.ts +123 -0
- package/src/engine/subagent-transcoder.test.ts +306 -0
- package/src/engine/subagent-transcoder.ts +333 -0
- package/src/host-verbs.ts +207 -0
- package/src/index.ts +1 -0
- package/src/manifest.test.ts +97 -0
- package/src/manifest.ts +109 -4
- package/src/registry.ts +9 -0
- package/src/scopes.ts +1 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Scale-aware grid-snap drag for the <Canvas> primitive.
|
|
2
|
+
//
|
|
3
|
+
// Owns the in-flight drag gesture (which item, where it started) and the
|
|
4
|
+
// pointer math that moves it: cursor delta is divided by the current viewport
|
|
5
|
+
// scale (so a 10px screen move at scale 0.5 becomes a 20px canvas move, and at
|
|
6
|
+
// scale 2.0 a 5px canvas move), then snapped to the `gridSnap` lattice.
|
|
7
|
+
//
|
|
8
|
+
// nx = round((startPos.x + dx / scale) / gridSnap) * gridSnap
|
|
9
|
+
//
|
|
10
|
+
// Does NOT own `layout` — it reads the current placement to seed the gesture
|
|
11
|
+
// and emits the moved layout through `onLayoutChange`. The parent stays the
|
|
12
|
+
// source of truth.
|
|
13
|
+
//
|
|
14
|
+
// Extracted verbatim (behavior-preserving) from shell home.tsx's canvas block.
|
|
15
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
16
|
+
export function useDragSnap(args) {
|
|
17
|
+
const { layout, gridSnap, scale, onLayoutChange, stageRef } = args;
|
|
18
|
+
const dragState = useRef(null);
|
|
19
|
+
// Keep the freshest layout/scale/snap reachable from the global listener
|
|
20
|
+
// without re-subscribing it on every render.
|
|
21
|
+
const layoutRef = useRef(layout);
|
|
22
|
+
layoutRef.current = layout;
|
|
23
|
+
const scaleRef = useRef(scale);
|
|
24
|
+
scaleRef.current = scale;
|
|
25
|
+
const gridSnapRef = useRef(gridSnap);
|
|
26
|
+
gridSnapRef.current = gridSnap;
|
|
27
|
+
const onLayoutChangeRef = useRef(onLayoutChange);
|
|
28
|
+
onLayoutChangeRef.current = onLayoutChange;
|
|
29
|
+
const beginDrag = useCallback((id, clientX, clientY) => {
|
|
30
|
+
const w = layoutRef.current[id];
|
|
31
|
+
if (!w)
|
|
32
|
+
return;
|
|
33
|
+
dragState.current = {
|
|
34
|
+
id,
|
|
35
|
+
startMouse: { x: clientX, y: clientY },
|
|
36
|
+
startPos: { x: w.x, y: w.y },
|
|
37
|
+
};
|
|
38
|
+
stageRef.current?.classList.add('is-dragging');
|
|
39
|
+
}, [stageRef]);
|
|
40
|
+
const isDragging = useCallback(() => dragState.current != null, []);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const onMove = (e) => {
|
|
43
|
+
if (!dragState.current)
|
|
44
|
+
return;
|
|
45
|
+
const s = scaleRef.current || 1;
|
|
46
|
+
const snap = gridSnapRef.current;
|
|
47
|
+
const dx = e.clientX - dragState.current.startMouse.x;
|
|
48
|
+
const dy = e.clientY - dragState.current.startMouse.y;
|
|
49
|
+
const nx = Math.round((dragState.current.startPos.x + dx / s) / snap) * snap;
|
|
50
|
+
const ny = Math.round((dragState.current.startPos.y + dy / s) / snap) * snap;
|
|
51
|
+
const id = dragState.current.id;
|
|
52
|
+
const cur = layoutRef.current;
|
|
53
|
+
const prev = cur[id];
|
|
54
|
+
if (!prev || (prev.x === nx && prev.y === ny))
|
|
55
|
+
return;
|
|
56
|
+
onLayoutChangeRef.current?.({ ...cur, [id]: { ...prev, x: nx, y: ny } });
|
|
57
|
+
};
|
|
58
|
+
const onUp = () => {
|
|
59
|
+
if (dragState.current) {
|
|
60
|
+
dragState.current = null;
|
|
61
|
+
stageRef.current?.classList.remove('is-dragging');
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
window.addEventListener('mousemove', onMove);
|
|
65
|
+
window.addEventListener('mouseup', onUp);
|
|
66
|
+
return () => {
|
|
67
|
+
window.removeEventListener('mousemove', onMove);
|
|
68
|
+
window.removeEventListener('mouseup', onUp);
|
|
69
|
+
};
|
|
70
|
+
}, [stageRef]);
|
|
71
|
+
return { dragState, beginDrag, isDragging };
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=use-drag-snap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-drag-snap.js","sourceRoot":"","sources":["../../src/canvas/use-drag-snap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ItemId, Placement, Viewport } from './types.js';
|
|
2
|
+
export interface UsePanZoomArgs {
|
|
3
|
+
/** Controlled layout (id → placement) the auto-fit bounding box reads. */
|
|
4
|
+
layout: Record<ItemId, Placement>;
|
|
5
|
+
/** Controlled edit-mode flag — auto-fit reserves palette width when true. */
|
|
6
|
+
editMode: boolean;
|
|
7
|
+
/** Re-fit on window resize. Default true. */
|
|
8
|
+
autoFitOnResize?: boolean;
|
|
9
|
+
/** Notified whenever the viewport pan/scale changes (controlled mirror). */
|
|
10
|
+
onViewportChange?: (viewport: Viewport) => void;
|
|
11
|
+
/** Escape exits edit mode → parent owns the state flip. */
|
|
12
|
+
onEditModeChange?: (editMode: boolean) => void;
|
|
13
|
+
/** Escape clears selection. */
|
|
14
|
+
onSelectionChange?: (selectedId: ItemId | null) => void;
|
|
15
|
+
}
|
|
16
|
+
export interface UsePanZoom {
|
|
17
|
+
/** Live viewport (x/y/scale). Mirrors `pan` in the original home code. */
|
|
18
|
+
pan: Viewport;
|
|
19
|
+
setPan: React.Dispatch<React.SetStateAction<Viewport>>;
|
|
20
|
+
/** Imperative re-fit. `animate=false` snaps without the transition. */
|
|
21
|
+
autoFit: (animate?: boolean) => void;
|
|
22
|
+
canvasRef: React.RefObject<HTMLDivElement | null>;
|
|
23
|
+
stageRef: React.RefObject<HTMLDivElement | null>;
|
|
24
|
+
/** True while Space is held — drag/pan branch reads this. */
|
|
25
|
+
spaceDown: React.MutableRefObject<boolean>;
|
|
26
|
+
/** Begin a pan gesture from a mousedown at screen (clientX, clientY). */
|
|
27
|
+
beginPan: (clientX: number, clientY: number) => void;
|
|
28
|
+
/** Is a pan gesture in flight? */
|
|
29
|
+
isPanning: () => boolean;
|
|
30
|
+
}
|
|
31
|
+
export declare function usePanZoom(args: UsePanZoomArgs): UsePanZoom;
|
|
32
|
+
//# sourceMappingURL=use-pan-zoom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-pan-zoom.d.ts","sourceRoot":"","sources":["../../src/canvas/use-pan-zoom.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,WAAW,cAAc;IAC7B,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClC,6EAA6E;IAC7E,QAAQ,EAAE,OAAO,CAAC;IAClB,6CAA6C;IAC7C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IAChD,2DAA2D;IAC3D,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,+BAA+B;IAC/B,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CACzD;AAED,MAAM,WAAW,UAAU;IACzB,0EAA0E;IAC1E,GAAG,EAAE,QAAQ,CAAC;IACd,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;IACvD,uEAAuE;IACvE,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAClD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACjD,6DAA6D;IAC7D,SAAS,EAAE,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC3C,yEAAyE;IACzE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,kCAAkC;IAClC,SAAS,EAAE,MAAM,OAAO,CAAC;CAC1B;AAID,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,CAoK3D"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// Pan / zoom / auto-fit for the <Canvas> primitive.
|
|
2
|
+
//
|
|
3
|
+
// Owns the viewport pan offset + scale, the imperative auto-fit math, the
|
|
4
|
+
// pan gesture (Space-drag / middle-mouse / empty-canvas drag), and the
|
|
5
|
+
// Space/Escape keyboard affordances + window-resize re-fit. It deliberately
|
|
6
|
+
// does NOT own `layout`, `selectedId`, or `editMode` — those stay parent-held
|
|
7
|
+
// and are threaded in as values so the auto-fit closure can read them.
|
|
8
|
+
//
|
|
9
|
+
// Extracted verbatim (behavior-preserving) from shell home.tsx's canvas block.
|
|
10
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
11
|
+
const RESERVED_PALETTE_WIDTH = 320;
|
|
12
|
+
export function usePanZoom(args) {
|
|
13
|
+
const { layout, editMode, autoFitOnResize = true, onViewportChange, onEditModeChange, onSelectionChange, } = args;
|
|
14
|
+
const [pan, setPan] = useState({ x: 0, y: 0, scale: 1 });
|
|
15
|
+
const canvasRef = useRef(null);
|
|
16
|
+
const stageRef = useRef(null);
|
|
17
|
+
const spaceDown = useRef(false);
|
|
18
|
+
const panStart = useRef(null);
|
|
19
|
+
// Latest pan reachable synchronously (for beginPan's offset seed) without
|
|
20
|
+
// adding `pan` to the gesture callbacks' deps.
|
|
21
|
+
const panRef = useRef(pan);
|
|
22
|
+
panRef.current = pan;
|
|
23
|
+
// Mirror viewport changes to the controlled parent in an effect (never
|
|
24
|
+
// inside a setState updater — that would setState-during-render the parent
|
|
25
|
+
// and trip React's "Cannot update a component while rendering a different
|
|
26
|
+
// component" warning). The ref skips the initial mount so the parent isn't
|
|
27
|
+
// notified of the default {0,0,1} before any real fit.
|
|
28
|
+
const viewportCbRef = useRef(onViewportChange);
|
|
29
|
+
viewportCbRef.current = onViewportChange;
|
|
30
|
+
const mountedViewport = useRef(false);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (!mountedViewport.current) {
|
|
33
|
+
mountedViewport.current = true;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
viewportCbRef.current?.(pan);
|
|
37
|
+
}, [pan]);
|
|
38
|
+
// Auto-fit: scale the bounding box of all items into the visible area,
|
|
39
|
+
// scaling down only (never up). Reserves the palette gutter in edit mode.
|
|
40
|
+
// Threads `layout` + `editMode` as deps so the closure never goes stale.
|
|
41
|
+
const autoFit = useCallback((animate = true) => {
|
|
42
|
+
const canvas = canvasRef.current;
|
|
43
|
+
const items = Object.values(layout);
|
|
44
|
+
if (!canvas || !items.length)
|
|
45
|
+
return;
|
|
46
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
47
|
+
for (const w of items) {
|
|
48
|
+
if (w.x < minX)
|
|
49
|
+
minX = w.x;
|
|
50
|
+
if (w.y < minY)
|
|
51
|
+
minY = w.y;
|
|
52
|
+
if (w.x + w.w > maxX)
|
|
53
|
+
maxX = w.x + w.w;
|
|
54
|
+
if (w.y + w.h > maxY)
|
|
55
|
+
maxY = w.y + w.h;
|
|
56
|
+
}
|
|
57
|
+
const cw = canvas.clientWidth - (editMode ? RESERVED_PALETTE_WIDTH : 0) - 40;
|
|
58
|
+
const ch = canvas.clientHeight - 44 - 32;
|
|
59
|
+
const bw = maxX - minX;
|
|
60
|
+
const bh = maxY - minY;
|
|
61
|
+
const sx = bw > 0 ? cw / bw : 1;
|
|
62
|
+
const sy = bh > 0 ? ch / bh : 1;
|
|
63
|
+
const scale = Math.min(1, sx, sy);
|
|
64
|
+
const offX = Math.round((cw + 40 - bw * scale) / 2 - minX * scale);
|
|
65
|
+
const offY = Math.round((ch + 32 - bh * scale) / 2 - minY * scale + 22);
|
|
66
|
+
setPan({ x: offX, y: offY, scale });
|
|
67
|
+
if (stageRef.current)
|
|
68
|
+
stageRef.current.classList.toggle('is-dragging', !animate);
|
|
69
|
+
}, [layout, editMode, setPan]);
|
|
70
|
+
// Initial fit + window-resize re-fit. Empty dep array on purpose — autoFit
|
|
71
|
+
// is read through the ref-stable callback, matching the original effect.
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
requestAnimationFrame(() => autoFit(false));
|
|
74
|
+
if (!autoFitOnResize)
|
|
75
|
+
return;
|
|
76
|
+
const onResize = () => autoFit(true);
|
|
77
|
+
window.addEventListener('resize', onResize);
|
|
78
|
+
return () => window.removeEventListener('resize', onResize);
|
|
79
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
80
|
+
}, []);
|
|
81
|
+
// Re-fit whenever edit mode toggles (palette gutter changes the fit box).
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
autoFit(true);
|
|
84
|
+
}, [editMode, autoFit]);
|
|
85
|
+
// Keyboard — Escape exits edit, Space arms the pan-grab cursor.
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
const down = (e) => {
|
|
88
|
+
if (e.key === 'Escape' && editMode) {
|
|
89
|
+
onEditModeChange?.(false);
|
|
90
|
+
onSelectionChange?.(null);
|
|
91
|
+
}
|
|
92
|
+
if (e.code === 'Space' &&
|
|
93
|
+
!e.repeat &&
|
|
94
|
+
document.activeElement === document.body &&
|
|
95
|
+
canvasRef.current) {
|
|
96
|
+
spaceDown.current = true;
|
|
97
|
+
canvasRef.current.style.cursor = 'grab';
|
|
98
|
+
e.preventDefault();
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
const up = (e) => {
|
|
102
|
+
if (e.code === 'Space') {
|
|
103
|
+
spaceDown.current = false;
|
|
104
|
+
if (canvasRef.current)
|
|
105
|
+
canvasRef.current.style.cursor = '';
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
window.addEventListener('keydown', down);
|
|
109
|
+
window.addEventListener('keyup', up);
|
|
110
|
+
return () => {
|
|
111
|
+
window.removeEventListener('keydown', down);
|
|
112
|
+
window.removeEventListener('keyup', up);
|
|
113
|
+
};
|
|
114
|
+
}, [editMode, onEditModeChange, onSelectionChange]);
|
|
115
|
+
const beginPan = useCallback((clientX, clientY) => {
|
|
116
|
+
const p = panRef.current;
|
|
117
|
+
panStart.current = { x: clientX - p.x, y: clientY - p.y };
|
|
118
|
+
stageRef.current?.classList.add('is-dragging');
|
|
119
|
+
if (canvasRef.current)
|
|
120
|
+
canvasRef.current.style.cursor = 'grabbing';
|
|
121
|
+
}, []);
|
|
122
|
+
const isPanning = useCallback(() => panStart.current != null, []);
|
|
123
|
+
// Global pan move/up. Drag (item) move/up lives in use-drag-snap so this
|
|
124
|
+
// effect only owns the pan branch + its own cleanup.
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
const onMove = (e) => {
|
|
127
|
+
if (panStart.current) {
|
|
128
|
+
setPan((p) => ({
|
|
129
|
+
...p,
|
|
130
|
+
x: e.clientX - panStart.current.x,
|
|
131
|
+
y: e.clientY - panStart.current.y,
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const onUp = () => {
|
|
136
|
+
if (panStart.current) {
|
|
137
|
+
panStart.current = null;
|
|
138
|
+
stageRef.current?.classList.remove('is-dragging');
|
|
139
|
+
if (canvasRef.current)
|
|
140
|
+
canvasRef.current.style.cursor = spaceDown.current ? 'grab' : '';
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
window.addEventListener('mousemove', onMove);
|
|
144
|
+
window.addEventListener('mouseup', onUp);
|
|
145
|
+
return () => {
|
|
146
|
+
window.removeEventListener('mousemove', onMove);
|
|
147
|
+
window.removeEventListener('mouseup', onUp);
|
|
148
|
+
};
|
|
149
|
+
}, [setPan]);
|
|
150
|
+
return {
|
|
151
|
+
pan,
|
|
152
|
+
setPan,
|
|
153
|
+
autoFit,
|
|
154
|
+
canvasRef,
|
|
155
|
+
stageRef,
|
|
156
|
+
spaceDown,
|
|
157
|
+
beginPan,
|
|
158
|
+
isPanning,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=use-pan-zoom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-pan-zoom.js","sourceRoot":"","sources":["../../src/canvas/use-pan-zoom.ts"],"names":[],"mappings":"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"}
|
package/dist/engine/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC"}
|
package/dist/engine/index.js
CHANGED
package/dist/engine/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portability surface for engine pkgs — ADR-012.
|
|
3
|
+
*
|
|
4
|
+
* Engine pkgs implement this in parallel to the runtime adapter
|
|
5
|
+
* (`AcpEngine` in `./acp.ts`). The kernel's `engine_assets` registry calls
|
|
6
|
+
* these methods at pkg install / uninstall time, fanning the operation out
|
|
7
|
+
* to every installed `EngineAdapter` so a user's pkg investment (skills,
|
|
8
|
+
* commands, agents, MCP servers) survives an engine swap.
|
|
9
|
+
*
|
|
10
|
+
* No manifest schema changes — pkgs continue to declare `skills`,
|
|
11
|
+
* `commands`, `agents` as folder paths and `mcp[]` as inline entries.
|
|
12
|
+
* This file is a runtime interface; it has no Zod schema and no
|
|
13
|
+
* compile-time dependency on the manifest schema beyond reusing
|
|
14
|
+
* `McpServer` for the spec passed to `registerMcpServer`.
|
|
15
|
+
*/
|
|
16
|
+
import type { McpServer } from '../manifest.js';
|
|
17
|
+
/**
|
|
18
|
+
* Result of an install / register operation. Per ADR §2 the kernel's pkg
|
|
19
|
+
* manager UI surfaces these so the user can see exactly what each engine
|
|
20
|
+
* adapter wrote.
|
|
21
|
+
*/
|
|
22
|
+
export interface InstallReport {
|
|
23
|
+
/** Absolute paths the adapter wrote or symlinked. */
|
|
24
|
+
wrote: string[];
|
|
25
|
+
/** Targets that were already correct — idempotent no-op. */
|
|
26
|
+
skipped: string[];
|
|
27
|
+
/** Non-fatal notes (e.g. "commands not supported on Codex; skipped"). */
|
|
28
|
+
warnings: string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Dry-run output for `EngineAdapter.plan()`. Shape mirrors `InstallReport`
|
|
32
|
+
* plus the `(engineId, pkgId)` tuple so the pkg manager UI can render a
|
|
33
|
+
* per-engine breakdown ("this pkg will install assets into 3 engines").
|
|
34
|
+
*/
|
|
35
|
+
export interface InstallPlan extends InstallReport {
|
|
36
|
+
/** Engine the plan was computed against — matches `EngineAdapter.id`. */
|
|
37
|
+
engineId: string;
|
|
38
|
+
/** Pkg the plan was computed for — matches the manifest `id` field. */
|
|
39
|
+
pkgId: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Minimal pkg manifest slice the adapter needs to compute a plan. Carved
|
|
43
|
+
* narrow on purpose: `plan()` runs before install, so it shouldn't load
|
|
44
|
+
* disk content the adapter wouldn't otherwise touch. Folder paths are
|
|
45
|
+
* relative to the pkg root (same convention as the on-disk manifest).
|
|
46
|
+
*/
|
|
47
|
+
export interface ManifestSnapshot {
|
|
48
|
+
/** Pkg id (e.g. `com.ikenga.studio`). */
|
|
49
|
+
id: string;
|
|
50
|
+
/** Pkg slug used to namespace materialized dirs (id with `.` → `-`). */
|
|
51
|
+
slug: string;
|
|
52
|
+
/** Relative folder for `skills/<name>/SKILL.md` files, if any. */
|
|
53
|
+
skills?: string;
|
|
54
|
+
/** Relative folder for `commands/<name>.md` files, if any. */
|
|
55
|
+
commands?: string;
|
|
56
|
+
/** Relative folder for `agents/<name>.md` files, if any. */
|
|
57
|
+
agents?: string;
|
|
58
|
+
/** Inline MCP server specs from the manifest's `mcp[]` block. */
|
|
59
|
+
mcp: McpServer[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Portability adapter exported by every engine pkg alongside its runtime
|
|
63
|
+
* `AcpEngine`. The kernel resolves both at load time (ADR §2).
|
|
64
|
+
*
|
|
65
|
+
* Folder-level methods. Each `install*` call is the adapter's chance to
|
|
66
|
+
* symlink, copy, or walk-and-transcode the whole folder — the choice
|
|
67
|
+
* depends on what the engine accepts natively. Idempotent by contract:
|
|
68
|
+
* re-running with unchanged inputs is a no-op.
|
|
69
|
+
*
|
|
70
|
+
* `registerMcpServer` writes a single entry into the engine's external
|
|
71
|
+
* settings file (`~/.claude/settings.json`, `~/.gemini/settings.json`,
|
|
72
|
+
* `~/.codex/config.toml`). Entries are keyed `ikenga.<pkg-slug>.<name>`
|
|
73
|
+
* per ADR §7 so they never collide with user-authored entries.
|
|
74
|
+
*
|
|
75
|
+
* Inverses tear down only what this pkg owned — user content in the same
|
|
76
|
+
* dir / settings file is left untouched.
|
|
77
|
+
*/
|
|
78
|
+
export interface EngineAdapter {
|
|
79
|
+
/** Engine identifier — matches `engine.agentId` in the pkg manifest. */
|
|
80
|
+
readonly id: string;
|
|
81
|
+
/**
|
|
82
|
+
* Materialize the pkg's skills folder into the engine's recognized
|
|
83
|
+
* location. Idempotent.
|
|
84
|
+
*/
|
|
85
|
+
installSkills(folder: string, pkgId: string, pkgSlug: string): Promise<InstallReport>;
|
|
86
|
+
/**
|
|
87
|
+
* Materialize the pkg's commands folder. Engines without a first-class
|
|
88
|
+
* commands primitive (Codex) may emit warnings and skip per-file
|
|
89
|
+
* instead of erroring — see ADR §5.
|
|
90
|
+
*/
|
|
91
|
+
installCommands(folder: string, pkgId: string, pkgSlug: string): Promise<InstallReport>;
|
|
92
|
+
/** Materialize the pkg's agents folder. Codex transcodes MD→TOML. */
|
|
93
|
+
installAgents(folder: string, pkgId: string, pkgSlug: string): Promise<InstallReport>;
|
|
94
|
+
/**
|
|
95
|
+
* Register one MCP server in the engine's external settings file.
|
|
96
|
+
* Idempotent on the `(pkgSlug, server name)` key.
|
|
97
|
+
*/
|
|
98
|
+
registerMcpServer(spec: McpServer, pkgId: string, pkgSlug: string): Promise<InstallReport>;
|
|
99
|
+
/** Inverse of `installSkills`. Removes only entries this pkg owned. */
|
|
100
|
+
uninstallSkills(pkgId: string, pkgSlug: string): Promise<void>;
|
|
101
|
+
/** Inverse of `installCommands`. */
|
|
102
|
+
uninstallCommands(pkgId: string, pkgSlug: string): Promise<void>;
|
|
103
|
+
/** Inverse of `installAgents`. */
|
|
104
|
+
uninstallAgents(pkgId: string, pkgSlug: string): Promise<void>;
|
|
105
|
+
/** Inverse of `registerMcpServer`. */
|
|
106
|
+
unregisterMcpServer(serverName: string, pkgId: string, pkgSlug: string): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Dry-run used by the pkg manager UI. Returns the same shape as a real
|
|
109
|
+
* install would produce, without touching the filesystem.
|
|
110
|
+
*/
|
|
111
|
+
plan(pkgId: string, pkgSlug: string, manifestSnapshot: ManifestSnapshot): Promise<InstallPlan>;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=portability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portability.d.ts","sourceRoot":"","sources":["../../src/engine/portability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAY,SAAQ,aAAa;IAChD,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,GAAG,EAAE,SAAS,EAAE,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAEtF;;;;OAIG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAExF,qEAAqE;IACrE,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAEtF;;;OAGG;IACH,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE3F,uEAAuE;IACvE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,oCAAoC;IACpC,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,kCAAkC;IAClC,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,sCAAsC;IACtC,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvF;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAChG"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portability surface for engine pkgs — ADR-012.
|
|
3
|
+
*
|
|
4
|
+
* Engine pkgs implement this in parallel to the runtime adapter
|
|
5
|
+
* (`AcpEngine` in `./acp.ts`). The kernel's `engine_assets` registry calls
|
|
6
|
+
* these methods at pkg install / uninstall time, fanning the operation out
|
|
7
|
+
* to every installed `EngineAdapter` so a user's pkg investment (skills,
|
|
8
|
+
* commands, agents, MCP servers) survives an engine swap.
|
|
9
|
+
*
|
|
10
|
+
* No manifest schema changes — pkgs continue to declare `skills`,
|
|
11
|
+
* `commands`, `agents` as folder paths and `mcp[]` as inline entries.
|
|
12
|
+
* This file is a runtime interface; it has no Zod schema and no
|
|
13
|
+
* compile-time dependency on the manifest schema beyond reusing
|
|
14
|
+
* `McpServer` for the spec passed to `registerMcpServer`.
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=portability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portability.js","sourceRoot":"","sources":["../../src/engine/portability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subagent format transcoder — ADR-012 §5.
|
|
3
|
+
*
|
|
4
|
+
* Translates between the canonical Markdown + YAML-frontmatter shape used
|
|
5
|
+
* by Claude Code and Gemini CLI and the TOML shape used by Codex CLI.
|
|
6
|
+
* Zero external dependencies: hand-rolled mini-parsers for YAML
|
|
7
|
+
* frontmatter and the TOML keys ADR §5 lists.
|
|
8
|
+
*
|
|
9
|
+
* Supported keys (top-level):
|
|
10
|
+
* - Canonical (round-trips): name, description, tools, model, system_prompt
|
|
11
|
+
* - Codex extras (preserved when present): developer_instructions,
|
|
12
|
+
* sandbox_mode, mcp_servers, skills
|
|
13
|
+
* - Claude/Gemini extras (preserved in YAML, ignored by Codex):
|
|
14
|
+
* temperature, max_turns, timeout_mins
|
|
15
|
+
*
|
|
16
|
+
* Nested table support is limited to `[mcp_servers]` — that's the only
|
|
17
|
+
* realistic surface for subagents. Arrays of tables, inline tables, and
|
|
18
|
+
* comments are not parsed; the transcoder operates on files we generate
|
|
19
|
+
* or files following ADR §5's spec.
|
|
20
|
+
*/
|
|
21
|
+
export declare function mdToCodexToml(md: string): string;
|
|
22
|
+
export declare function codexTomlToMd(toml: string): string;
|
|
23
|
+
export declare function mdToGeminiCommandToml(md: string): string;
|
|
24
|
+
//# sourceMappingURL=subagent-transcoder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagent-transcoder.d.ts","sourceRoot":"","sources":["../../src/engine/subagent-transcoder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAOhD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAOxD"}
|