killeros 1.5.0 → 1.5.2
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/CHANGELOG.md +22 -0
- package/README.md +1 -1
- package/killeros/concise.ts +51 -9
- package/killeros/subagents.ts +13 -34
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,28 @@ All notable changes to KillerOS are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.5.2] - 2026-08-03
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Hardened always-on concise guidance around low-friction action, visible multi-turn state, evidence-backed outcomes, material ambiguity, diagnostic resets, and explicit safety and correctness precedence.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Resolved bundled subagent role discovery from the package `agents/` directory; the module-relative path broke when subagent modules moved under `killeros/` in v1.5.0, leaving fresh installs with `Unknown subagent "<role>". Available: none`.
|
|
16
|
+
|
|
17
|
+
## [1.5.1] - 2026-08-03
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Added a fixed pragmatic response style, low GPT-5 Responses API verbosity, and concise reasoning summaries without changing reasoning effort.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Replaced the `subagent` tool's top-level union with a provider-compatible object schema, fixing request rejection by Console Go and other providers that require function schemas with `type: "object"`.
|
|
26
|
+
- Kept strict action-specific subagent validation at runtime, including single, parallel, chain, steering, interruption, collection, and closure requests.
|
|
27
|
+
- Scoped native concise settings to supported Responses APIs while leaving completion and unrelated provider payloads unchanged.
|
|
28
|
+
|
|
7
29
|
## [1.5.0] - 2026-08-03
|
|
8
30
|
|
|
9
31
|
### Changed
|
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ pi install git:github.com/KyrosHendrix/pi-KillerOS
|
|
|
33
33
|
Pin an install to a release:
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
-
pi install git:github.com/KyrosHendrix/pi-KillerOS@v1.5.
|
|
36
|
+
pi install git:github.com/KyrosHendrix/pi-KillerOS@v1.5.2
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
Add `-l` to either command for a project-only install. Restart Pi after installing.
|
package/killeros/concise.ts
CHANGED
|
@@ -1,17 +1,58 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
|
|
3
3
|
export const CONCISE_SYSTEM_PROMPT = `
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
# Action-oriented response guidance
|
|
5
|
+
|
|
6
|
+
Make each response easy to start and easy to follow. Keep the state the user needs on screen instead of expecting them to remember missing context. Concise means low friction, not minimal detail: preserve everything required for safety, correctness, and action.
|
|
7
|
+
|
|
8
|
+
## Serve the immediate need
|
|
9
|
+
|
|
10
|
+
The first line serves the user's immediate need: give the answer for an informational request, the next action for executable work, or the failure and recovery when blocked. Omit conversational preambles. If the agent can continue the work, continue instead of asking permission; if the task is complete, do not manufacture a next step.
|
|
11
|
+
|
|
12
|
+
Finish the primary task before raising a separate concern. Mention an unrelated issue only when it materially affects safety, correctness, or the user's next decision. Ask one concrete question only when a material ambiguity remains after checking available code and context.
|
|
13
|
+
|
|
14
|
+
## Reduce action and memory friction
|
|
15
|
+
|
|
16
|
+
Use structure by meaning: numbered steps for sequence, bullets for parallel facts or options, and short headings when they make a longer answer easier to scan or re-enter. Keep each step bounded. When a list grows beyond about five items, rank or group it instead of omitting required detail.
|
|
17
|
+
|
|
18
|
+
Use a compact state anchor only when multi-step work spans turns or resumes after interruption. During tool-driven work, report meaningful phase changes, long-running verification, failures, and required decisions rather than narrating routine actions.
|
|
19
|
+
|
|
20
|
+
## Make outcomes and failures concrete
|
|
21
|
+
|
|
22
|
+
When work completes, make the verified outcome prominent: state what now works and the evidence that proves it. Do not append a redundant recap. State failures matter-of-factly with the cause, impact, and recovery action. After three consecutive turns leave the same issue broken, stop speculative edits, name the likely invalid assumption from the observed evidence, and ask one diagnostic question.
|
|
23
|
+
|
|
24
|
+
Never invent facts, completion claims, or timing. Give a concrete human execution estimate only when requested or supported by evidence, state its assumptions, and never predict the agent's own completion time. Preserve exact code, commands, paths, quoted text, warnings, and user-requested formats.
|
|
25
|
+
|
|
26
|
+
## Resolve conflicts deliberately
|
|
27
|
+
|
|
28
|
+
Safety and harness constraints come first, followed by the user's explicit depth or format request, then correctness and completeness, then these concise defaults. Explain fully when asked, confirm before destructive actions, and retain necessary uncertainty rather than manufacturing confidence.
|
|
29
|
+
|
|
30
|
+
Before sending, check that the first line serves the immediate need, filler and tangents are gone, exact artifacts and necessary uncertainty remain, and the ending is either the verified outcome or one action the user must take. Use a pragmatic tone: direct, plain, and focused on the task. Omit generic praise, recap sections, and closing pleasantries.
|
|
13
31
|
`.trim();
|
|
14
32
|
|
|
33
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
34
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function applyConciseModelSettings(payload: unknown, api: unknown, modelId: unknown): unknown {
|
|
38
|
+
if (!isRecord(payload) || !Array.isArray(payload.input)) return payload;
|
|
39
|
+
|
|
40
|
+
const supportsSummary = api === "openai-codex-responses" || api === "openai-responses" || api === "azure-openai-responses";
|
|
41
|
+
const supportsVerbosity = api === "openai-codex-responses"
|
|
42
|
+
|| api === "openai-responses" && typeof modelId === "string" && /^gpt-5(?:[.-]|$)/u.test(modelId);
|
|
43
|
+
let updated = payload;
|
|
44
|
+
if (supportsVerbosity) {
|
|
45
|
+
updated = {
|
|
46
|
+
...updated,
|
|
47
|
+
text: { ...(isRecord(payload.text) ? payload.text : {}), verbosity: "low" },
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (supportsSummary && isRecord(payload.reasoning)) {
|
|
51
|
+
updated = { ...updated, reasoning: { ...payload.reasoning, summary: "concise" } };
|
|
52
|
+
}
|
|
53
|
+
return updated;
|
|
54
|
+
}
|
|
55
|
+
|
|
15
56
|
export function isConcisedEnabled(): boolean {
|
|
16
57
|
return true;
|
|
17
58
|
}
|
|
@@ -20,4 +61,5 @@ export function registerConcisePrompt(pi: ExtensionAPI): void {
|
|
|
20
61
|
pi.on("before_agent_start", (event) => ({
|
|
21
62
|
systemPrompt: `${event.systemPrompt}\n\n${CONCISE_SYSTEM_PROMPT}`,
|
|
22
63
|
}));
|
|
64
|
+
pi.on("before_provider_request", (event, ctx) => applyConciseModelSettings(event.payload, ctx.model?.api, ctx.model?.id));
|
|
23
65
|
}
|
package/killeros/subagents.ts
CHANGED
|
@@ -357,7 +357,7 @@ export function discoverAgentRoles(
|
|
|
357
357
|
options: Pick<SubagentRuntimeOptions, "bundledAgentsDir" | "userAgentsDir" | "limits"> = {},
|
|
358
358
|
): AgentDiscoveryResult {
|
|
359
359
|
const limits = { ...SUBAGENT_LIMITS, ...options.limits };
|
|
360
|
-
const bundledDir = options.bundledAgentsDir ?? fileURLToPath(new URL("
|
|
360
|
+
const bundledDir = options.bundledAgentsDir ?? fileURLToPath(new URL("../agents/", import.meta.url));
|
|
361
361
|
const userDir = options.userAgentsDir ?? path.join(getAgentDir(), "agents");
|
|
362
362
|
const wantsProject = scope === "project" || scope === "both";
|
|
363
363
|
if (wantsProject && !projectTrusted) throw new Error("Project agents require a trusted project");
|
|
@@ -959,45 +959,24 @@ function createSubagentParams(limits: Pick<SubagentLimits, "maxTasks" | "maxRead
|
|
|
959
959
|
agent: Type.String({ minLength: 1, maxLength: 64, description: "Agent role name" }),
|
|
960
960
|
task: Type.String({ minLength: 1, maxLength: limits.taskCharacters, description: "Task with optional {previous} handoff placeholder" }),
|
|
961
961
|
}, { additionalProperties: false });
|
|
962
|
-
const
|
|
963
|
-
|
|
962
|
+
const threadId = Type.String({ minLength: 1, maxLength: 128, description: "Stable child thread ID" });
|
|
963
|
+
return Type.Object({
|
|
964
|
+
action: Type.Optional(StringEnum(SUBAGENT_ACTIONS, { default: SUBAGENT_ACTION.spawn, description: "Spawn, list, inspect, steer, interrupt, collect, or close" })),
|
|
965
|
+
threadId: Type.Optional(threadId),
|
|
966
|
+
message: Type.Optional(Type.String({ minLength: 1, maxLength: 4_000, description: "Steering message; valid only with action steer" })),
|
|
967
|
+
all: Type.Optional(Type.Literal(true, { description: "Interrupt every active child thread" })),
|
|
968
|
+
agent: Type.Optional(Type.String({ minLength: 1, maxLength: 64, description: "Agent role for single mode" })),
|
|
969
|
+
task: Type.Optional(Type.String({ minLength: 1, maxLength: limits.taskCharacters, description: "Task for single mode" })),
|
|
970
|
+
tasks: Type.Optional(Type.Array(taskSchema, { minItems: 1, maxItems: limits.maxTasks, description: `Parallel role tasks: read-only batches run concurrently up to ${limits.maxReadConcurrency}; batches with writers use one shared slot by default. Set writerConcurrency to opt into a larger shared pool; concurrent writers share the parent worktree, so callers must prove path ownership` })),
|
|
971
|
+
writerConcurrency: Type.Optional(Type.Integer({ minimum: 1, maximum: limits.maxTasks, description: `Optional shared-pool cap for parallel tasks that include writers. Defaults to 1 when writers are selected; values above 1 opt into concurrent shared-worktree writes. Concurrent writers must prove path ownership` })),
|
|
972
|
+
chain: Type.Optional(Type.Array(chainTaskSchema, { minItems: 1, maxItems: limits.maxTasks, description: "Sequential role tasks; {previous} inserts the prior result" })),
|
|
964
973
|
model: Type.Optional(Type.String({ minLength: 1, maxLength: 256, description: "Model for every task as provider/model; inherit uses each role setting or the active parent" })),
|
|
965
974
|
thinking: Type.Optional(Type.String({ minLength: 1, maxLength: 16, description: "Thinking effort for every task: off, minimal, low, medium, high, xhigh, max, or inherit" })),
|
|
966
975
|
agentScope: Type.Optional(StringEnum(["user", "project", "both"] as const, {
|
|
967
976
|
default: "user",
|
|
968
977
|
description: "Role sources: user includes bundled and personal; project includes bundled and trusted project; both includes all",
|
|
969
978
|
})),
|
|
970
|
-
};
|
|
971
|
-
const threadId = Type.String({ minLength: 1, maxLength: 128, description: "Stable child thread ID" });
|
|
972
|
-
const exportProperties = {
|
|
973
|
-
action: Type.String({ description: "Spawn, list, inspect, steer, interrupt, collect, or close" }),
|
|
974
|
-
threadId: Type.String({ description: "Child thread ID for a lifecycle action" }),
|
|
975
|
-
message: Type.String({ description: "Steering message; valid only with action steer" }),
|
|
976
|
-
all: Type.Boolean({ description: "Interrupt every active child thread" }),
|
|
977
|
-
agent: Type.String({ description: "Agent role for a single spawn" }),
|
|
978
|
-
task: Type.String({ description: "Task for a single spawn" }),
|
|
979
|
-
tasks: Type.Array(Type.Any(), { description: "Parallel role tasks" }),
|
|
980
|
-
writerConcurrency: Type.Integer({ description: "Shared-pool cap for parallel writer tasks" }),
|
|
981
|
-
chain: Type.Array(Type.Any(), { description: "Sequential role tasks" }),
|
|
982
|
-
model: Type.String({ description: "Model for every spawned task" }),
|
|
983
|
-
thinking: Type.String({ description: "Thinking effort for every spawned task" }),
|
|
984
|
-
agentScope: Type.String({ description: "Role sources for a spawn" }),
|
|
985
|
-
};
|
|
986
|
-
const schema = Type.Union([
|
|
987
|
-
Type.Object({ action, agent: Type.String({ minLength: 1, maxLength: 64, description: "Agent role for single mode" }), task: Type.String({ minLength: 1, maxLength: limits.taskCharacters, description: "Task for single mode" }), ...spawnOptions }, { additionalProperties: false }),
|
|
988
|
-
Type.Object({ action, tasks: Type.Array(taskSchema, { minItems: 1, maxItems: limits.maxTasks, description: `Parallel role tasks: read-only batches run concurrently up to ${limits.maxReadConcurrency}; batches with writers use one shared slot by default. Set writerConcurrency to opt into a larger shared pool; concurrent writers share the parent worktree, so callers must prove path ownership` }), writerConcurrency: Type.Optional(Type.Integer({ minimum: 1, maximum: limits.maxTasks, description: `Optional shared-pool cap for parallel tasks that include writers. Defaults to 1 when writers are selected; values above 1 opt into concurrent shared-worktree writes. Concurrent writers must prove path ownership` })), ...spawnOptions }, { additionalProperties: false }),
|
|
989
|
-
Type.Object({ action, chain: Type.Array(chainTaskSchema, { minItems: 1, maxItems: limits.maxTasks, description: "Sequential role tasks; {previous} inserts the prior result" }), ...spawnOptions }, { additionalProperties: false }),
|
|
990
|
-
Type.Object({ action: Type.Literal(SUBAGENT_ACTION.list) }, { additionalProperties: false }),
|
|
991
|
-
Type.Object({ action: Type.Literal(SUBAGENT_ACTION.inspect), threadId }, { additionalProperties: false }),
|
|
992
|
-
Type.Object({ action: Type.Literal(SUBAGENT_ACTION.steer), threadId, message: Type.String({ minLength: 1, maxLength: 4_000, description: "Bounded steering message" }) }, { additionalProperties: false }),
|
|
993
|
-
Type.Object({ action: Type.Literal(SUBAGENT_ACTION.interrupt), threadId }, { additionalProperties: false }),
|
|
994
|
-
Type.Object({ action: Type.Literal(SUBAGENT_ACTION.interrupt), all: Type.Literal(true, { description: "Interrupt every active child thread" }) }, { additionalProperties: false }),
|
|
995
|
-
Type.Object({ action: Type.Literal(SUBAGENT_ACTION.collect), threadId }, { additionalProperties: false }),
|
|
996
|
-
Type.Object({ action: Type.Literal(SUBAGENT_ACTION.close), threadId }, { additionalProperties: false }),
|
|
997
|
-
]);
|
|
998
|
-
// Pi's HTML export reads properties; providers receive only the action-specific union.
|
|
999
|
-
Object.defineProperty(schema, "properties", { value: exportProperties });
|
|
1000
|
-
return schema;
|
|
979
|
+
}, { additionalProperties: false });
|
|
1001
980
|
}
|
|
1002
981
|
|
|
1003
982
|
type ToolUpdate = (partial: { content: Array<{ type: "text"; text: string }>; details: SubagentDetails }) => void;
|