@jwilger/pi-development-system 0.14.0 → 0.16.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/package.json
CHANGED
|
@@ -34,8 +34,8 @@ agent_spawn({path: "/impl-add-flag", type: "implementer", task: "...",
|
|
|
34
34
|
|
|
35
35
|
- Jev judges difficulty and risk; the project's `[routing]` table (slots, never
|
|
36
36
|
model ids) decides. Jev offline means `routine/low`.
|
|
37
|
-
- If the result says the slot is unresolvable, spawning without a pin fails the
|
|
38
|
-
way (the agent's own `models:` list
|
|
37
|
+
- If the result says the slot is unresolvable, spawning without a pin usually fails the
|
|
38
|
+
same way (the agent's own `models:` list defaults to the same candidates). Run `/devsys-models`
|
|
39
39
|
to fix the matrix, or pin a model you know works.
|
|
40
40
|
- A pin is an explicit choice: it bypasses `/scoped-models` and the agent's `models:`
|
|
41
41
|
list, so only pin what the route (or you, with a stated reason) selected.
|
package/src/core/routing.ts
CHANGED
|
@@ -55,7 +55,7 @@ export function recommendRoute(input: {
|
|
|
55
55
|
if (!resolved.ok) {
|
|
56
56
|
return {
|
|
57
57
|
...route,
|
|
58
|
-
note: `${prefix}No model with credentials resolves slot "${route.slot}" (unresolvable); an agent spawned without a pin
|
|
58
|
+
note: `${prefix}No model with credentials resolves slot "${route.slot}" (unresolvable); an agent spawned without a pin usually fails the same way (its models: list defaults to the same candidates), so run /devsys-models to fix the matrix or pin a model you know works.`,
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
return {
|
|
@@ -16,7 +16,7 @@ export type Settings = {
|
|
|
16
16
|
readonly thinkingLevel: ThinkingLevel;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
const MODEL_REF = /^[^\s
|
|
19
|
+
const MODEL_REF = /^[^\s/*]+\/[^\s*]+$/;
|
|
20
20
|
|
|
21
21
|
const isLevel = (value: unknown): value is ThinkingLevel =>
|
|
22
22
|
THINKING_LEVELS.some((level) => level === value);
|
|
@@ -66,7 +66,7 @@ export type ModelSource = "current" | "preferences" | "restored" | "inherited";
|
|
|
66
66
|
* thread keeps the model it was already running instead of falling back to the preferences.
|
|
67
67
|
*/
|
|
68
68
|
export function modelSource(input: {
|
|
69
|
-
mode: "use-current" | "pick-first-scoped" | "pick-first";
|
|
69
|
+
mode: "use-current" | "pick-first-scoped" | "pick-first-available";
|
|
70
70
|
pinned: boolean;
|
|
71
71
|
hasPreferences: boolean;
|
|
72
72
|
hasRestored: boolean;
|
|
@@ -38,3 +38,5 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
38
38
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
39
39
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
40
40
|
SOFTWARE.
|
|
41
|
+
6. Empty scope (I5 review): `orch/runtime.ts` `availableScopedModels` treats an empty `/scoped-models` as no restriction (pi's meaning) instead of "matches nothing", because every devsys agent declares `models:` and would otherwise be unspawnable by default. Pinned models are also re-applied on resume (`resolveInitialSettings`), since a restored session may hold only inherited history.
|
|
42
|
+
7. Bundled agents outside `src/subagents`: `agents/researcher.md` and `agents/reviewer.md` differ from upstream (devsys `models:` family lists; the reviewer's packet format); `agents/{advisor,implementer,lens-*}.md` are new. The agent file format itself is unchanged.
|
|
@@ -153,6 +153,11 @@ export function createDriverFactory(
|
|
|
153
153
|
getInheritedTools: () => InheritedToolSource = () => ({ tools: [], activeNames: [] }),
|
|
154
154
|
): DriverFactory & {
|
|
155
155
|
resolveAgentSettings(type: AgentType, parentPath: string): ResolvedAgentSettings;
|
|
156
|
+
resolveInitialSettings(
|
|
157
|
+
type: AgentType,
|
|
158
|
+
parentPath?: string | null,
|
|
159
|
+
restored?: ReturnType<SessionManager["buildSessionContext"]>,
|
|
160
|
+
): { provider?: string; id?: string; thinkingLevel: ThinkingLevel };
|
|
156
161
|
} {
|
|
157
162
|
// Keep resolved settings even after disposal: descendants inherit settings, not the caller's history.
|
|
158
163
|
const resolved = new Map<string, { provider: string; id: string; thinking: ThinkingLevel }>();
|
|
@@ -165,6 +170,8 @@ export function createDriverFactory(
|
|
|
165
170
|
.map((model) => ({ model }));
|
|
166
171
|
const availableScopedModels = (scopedModels: readonly ScopedModel[]) => {
|
|
167
172
|
const available = new Set(availableModelCandidates().map(({ model }) => modelIdentity(model)));
|
|
173
|
+
// devsys: an empty scope means no /scoped-models restriction in pi, not "matches nothing".
|
|
174
|
+
if (scopedModels.length === 0) return [...availableModelCandidates()];
|
|
168
175
|
return scopedModels.filter(({ model }) => available.has(modelIdentity(model)));
|
|
169
176
|
};
|
|
170
177
|
const selectTypeModelPreference = (
|
|
@@ -232,9 +239,12 @@ export function createDriverFactory(
|
|
|
232
239
|
: undefined;
|
|
233
240
|
const thinkingLevel =
|
|
234
241
|
savedThinking ?? type.thinkingLevel ?? parent?.thinking ?? ctx.thinkingLevel ?? "off";
|
|
235
|
-
// devsys: a per-spawn pin from agent_spawn wins
|
|
236
|
-
|
|
237
|
-
|
|
242
|
+
// devsys: a per-spawn pin from agent_spawn wins. On resume the thinking level is the saved one,
|
|
243
|
+
// but the pinned model still applies: the restored session may only hold inherited history.
|
|
244
|
+
const pins = type.spawnOverrides;
|
|
245
|
+
if (restored === undefined) return applySpawnOverrides({ provider, id, thinkingLevel }, pins);
|
|
246
|
+
if (pins?.model !== undefined)
|
|
247
|
+
return applySpawnOverrides({ provider, id, thinkingLevel }, { model: pins.model });
|
|
238
248
|
return { provider, id, thinkingLevel };
|
|
239
249
|
};
|
|
240
250
|
const resolveAgentSettings = (type: AgentType, parentPath: string): ResolvedAgentSettings => {
|
|
@@ -795,5 +805,6 @@ export function createDriverFactory(
|
|
|
795
805
|
},
|
|
796
806
|
};
|
|
797
807
|
};
|
|
798
|
-
|
|
808
|
+
// devsys: resolveInitialSettings is exposed so resume behaviour can be tested directly.
|
|
809
|
+
return Object.assign(createDriver, { resolveAgentSettings, resolveInitialSettings });
|
|
799
810
|
}
|
package/src/subagents/types.ts
CHANGED
|
@@ -69,7 +69,7 @@ export interface ThreadView {
|
|
|
69
69
|
/** Cumulative output tokens. Live views include the in-progress message. */
|
|
70
70
|
outputTokens?: number;
|
|
71
71
|
/** devsys: per-spawn model/thinkingLevel pin requested through agent_spawn, when any. */
|
|
72
|
-
pinned?:
|
|
72
|
+
pinned?: { model?: string; thinkingLevel?: ThinkingLevel };
|
|
73
73
|
}
|
|
74
74
|
export type DriverEvent =
|
|
75
75
|
| { kind: "activity" | "error"; text: string }
|