sortie-dogs 0.14.4 → 0.14.6
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/.agents/skills/sortie-dogs/SKILL.md +1 -1
- package/README.md +13 -10
- package/dist/asset-version.d.ts +2 -2
- package/dist/asset-version.js +2 -2
- package/dist/cli/codex-mission.d.ts +1 -1
- package/dist/cli/codex-mission.js +2 -1
- package/dist/core/mission-context.d.ts +16 -0
- package/dist/core/mission-context.js +42 -4
- package/dist/core/operator-mission.js +3 -2
- package/dist/plugin/docker-validation.js +10 -1
- package/dist/plugin/model-cost.d.ts +3 -3
- package/dist/plugin/model-cost.js +6 -3
- package/dist/plugin/profiled.js +4 -3
- package/dist/plugin/v2.js +35 -5
- package/dist/runtime-assets-v010.js +2 -1
- package/dist/runtime-mission-assets.js +11 -1
- package/package.json +1 -1
|
@@ -32,7 +32,7 @@ Use the natural-language Mission route on POSIX and Windows:
|
|
|
32
32
|
|
|
33
33
|
Forward `--model`, `--effort`, or `--permissions` only when the user selected those values. Never silently widen the native permission profile. If an existing Mission is reported, resume only its exact root with `--resume`; do not launch replacement work.
|
|
34
34
|
|
|
35
|
-
Leave `--model` unset to retain role-specific defaults: Sol 6.1 Operator/Coordinator/Reviewer and
|
|
35
|
+
Leave `--model` unset to retain role-specific defaults: Sol 6.1 Operator/Coordinator/Reviewer and ordinary Terra 6.1 Standard/max Worker (no Fast/priority). Scout and dedicated Luna routes remain unchanged. The Codex adapter retains the shared Luna-fast alias mapping to native `gpt-6-luna` plus the `priority` (Fast) service tier. Fast consumes subscription limits faster than Standard; no metered API fallback is allowed.
|
|
36
36
|
|
|
37
37
|
On Windows the same Mission command resolves existing PowerShell 7 automatically. Add `--trusted-pwsh <absolute-pwsh.exe>` only when an exact existing executable needs to be selected; do not add a separate shell preflight or approval step.
|
|
38
38
|
|
package/README.md
CHANGED
|
@@ -19,8 +19,8 @@ evidence-backed result, not more agents for their own sake.
|
|
|
19
19
|
[](https://www.npmjs.com/package/sortie-dogs)
|
|
20
20
|
[](LICENSE)
|
|
21
21
|
|
|
22
|
-
**Current release: [v0.14.
|
|
23
|
-
· [Release notes](docs/release-v0.14.
|
|
22
|
+
**Current release: [v0.14.6](https://github.com/zufall-upon/Sortie-dogs/releases/tag/v0.14.6)**
|
|
23
|
+
· [Release notes](docs/release-v0.14.6.md) · [Execution vision](docs/v0.14.0-execution-vision.md)
|
|
24
24
|
|
|
25
25
|
[Quick start](#quick-start) · [Workflow](#mission-workflow) · [Models](#default-models) ·
|
|
26
26
|
[Measured results](#measured-results) · [Configuration](#configuration) · [Documentation](#documentation)
|
|
@@ -57,7 +57,7 @@ Use an existing Codex CLI signed in with **ChatGPT**. On Windows, PowerShell **7
|
|
|
57
57
|
available; POSIX uses bash. Sortie does not install Codex, start login or use a metered API fallback.
|
|
58
58
|
|
|
59
59
|
```sh
|
|
60
|
-
npm install --save-dev sortie-dogs@0.14.
|
|
60
|
+
npm install --save-dev sortie-dogs@0.14.6
|
|
61
61
|
npx --no-install sortie-dogs codex init .
|
|
62
62
|
```
|
|
63
63
|
|
|
@@ -86,7 +86,7 @@ bridge. [Codex guide: SDK, permissions, progress, resume and manifest route](doc
|
|
|
86
86
|
Use **OpenCode V2**. In the target project:
|
|
87
87
|
|
|
88
88
|
```sh
|
|
89
|
-
npm install --save-dev sortie-dogs@0.14.
|
|
89
|
+
npm install --save-dev sortie-dogs@0.14.6
|
|
90
90
|
npx --no-install sortie-dogs init .
|
|
91
91
|
```
|
|
92
92
|
|
|
@@ -144,9 +144,12 @@ one. Required success checks, missing commands and active/unstarted operations s
|
|
|
144
144
|
## Default models
|
|
145
145
|
|
|
146
146
|
- **Operator / Coordinator / Reviewer / Advisor:** GPT-6.1 Sol, `xhigh`.
|
|
147
|
-
- **Worker
|
|
148
|
-
- **
|
|
149
|
-
- **
|
|
147
|
+
- **Worker:** GPT-6.1 Terra Standard, `max` (no Fast/priority).
|
|
148
|
+
- **Scout / dedicated Luna Worker:** Luna Fast, `max`, unchanged.
|
|
149
|
+
- **OpenCode:** ordinary Worker `openai/gpt-6.1-terra#max`; management/review
|
|
150
|
+
`openai/gpt-6.1-sol#xhigh`.
|
|
151
|
+
- **Codex:** ordinary Worker native `gpt-6.1-terra` / `max`, Standard; management/review
|
|
152
|
+
`gpt-6.1-sol` / `xhigh`. The retained Luna-fast alias maps to native
|
|
150
153
|
`gpt-6-luna` / `max` with separate `serviceTier: "priority"` (Fast).
|
|
151
154
|
|
|
152
155
|
Explicit host model selections remain authoritative. OpenCode routing and Codex native settings
|
|
@@ -242,8 +245,8 @@ Install the desired package version and rerun **your host's** initializer:
|
|
|
242
245
|
|
|
243
246
|
An OpenCode config-local bridge may resolve a separate package; npm-global update alone does not
|
|
244
247
|
update it. [Global/update instructions](docs/configuration.md#global-availability).
|
|
245
|
-
The current Mission asset marker is `0.14.
|
|
246
|
-
`0.
|
|
248
|
+
The current Mission asset marker is `0.14.6-attachment-terra-v1`; the Codex skill marker is
|
|
249
|
+
`0.14.6-codex-skill-v1`. Installed markers alone do not prove a running host reloaded the new version.
|
|
247
250
|
|
|
248
251
|
There is no supported uninstall command. Remove the dependency and only known Sortie-owned paths;
|
|
249
252
|
follow the [manual removal guide](docs/uninstall.md), never delete the entire `.opencode` directory.
|
|
@@ -258,7 +261,7 @@ follow the [manual removal guide](docs/uninstall.md), never delete the entire `.
|
|
|
258
261
|
[SWE-bench history](docs/benchmarks/swebench-lite-history.md) · [Historical local case study](docs/benchmark-reference.md).
|
|
259
262
|
- **Development:** [Testing](docs/testing.md) · [CLI testing](docs/cli-testing.md) ·
|
|
260
263
|
[Windows tests](docs/windows-tests.md) · [Release routine](docs/release-batch.md).
|
|
261
|
-
- **Releases:** [v0.14.4](docs/release-v0.14.4.md) · [v0.14.3](docs/release-v0.14.3.md) · [v0.14.2](docs/release-v0.14.2.md) · [v0.14.1](docs/release-v0.14.1.md) · [v0.14.0](docs/release-v0.14.0.md) · [v0.13.22](docs/release-v0.13.22.md) · [v0.13.21](docs/release-v0.13.21.md) · [v0.13.20](docs/release-v0.13.20.md) · [v0.13.19](docs/release-v0.13.19.md) · [v0.13.18](docs/release-v0.13.18.md) · [v0.13.17](docs/release-v0.13.17.md) · [v0.13.16](docs/release-v0.13.16.md) · [v0.13.15](docs/release-v0.13.15.md) · [v0.13.14](docs/release-v0.13.14.md) · [v0.13.13](docs/release-v0.13.13.md) · [v0.13.12](docs/release-v0.13.12.md) · [v0.13.11](docs/release-v0.13.11.md) · [v0.13.10](docs/release-v0.13.10.md) ·
|
|
264
|
+
- **Releases:** [v0.14.6](docs/release-v0.14.6.md) · [v0.14.5](docs/release-v0.14.5.md) · [v0.14.4](docs/release-v0.14.4.md) · [v0.14.3](docs/release-v0.14.3.md) · [v0.14.2](docs/release-v0.14.2.md) · [v0.14.1](docs/release-v0.14.1.md) · [v0.14.0](docs/release-v0.14.0.md) · [v0.13.22](docs/release-v0.13.22.md) · [v0.13.21](docs/release-v0.13.21.md) · [v0.13.20](docs/release-v0.13.20.md) · [v0.13.19](docs/release-v0.13.19.md) · [v0.13.18](docs/release-v0.13.18.md) · [v0.13.17](docs/release-v0.13.17.md) · [v0.13.16](docs/release-v0.13.16.md) · [v0.13.15](docs/release-v0.13.15.md) · [v0.13.14](docs/release-v0.13.14.md) · [v0.13.13](docs/release-v0.13.13.md) · [v0.13.12](docs/release-v0.13.12.md) · [v0.13.11](docs/release-v0.13.11.md) · [v0.13.10](docs/release-v0.13.10.md) ·
|
|
262
265
|
[v0.13.9](docs/release-v0.13.9.md) · [All GitHub releases](https://github.com/zufall-upon/Sortie-dogs/releases).
|
|
263
266
|
|
|
264
267
|
## Community
|
package/dist/asset-version.d.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
* installed project marker without importing every asset body.
|
|
4
4
|
*/
|
|
5
5
|
export declare const RUNTIME_ASSET_VERSION = "0.3.89-completion-proof-v1";
|
|
6
|
-
export declare const V010_RUNTIME_ASSET_VERSION = "0.14.
|
|
7
|
-
export declare const CODEX_SKILL_ASSET_VERSION = "0.
|
|
6
|
+
export declare const V010_RUNTIME_ASSET_VERSION = "0.14.6-attachment-terra-v1";
|
|
7
|
+
export declare const CODEX_SKILL_ASSET_VERSION = "0.14.6-codex-skill-v1";
|
|
8
8
|
export type RuntimeAssetVersion = typeof RUNTIME_ASSET_VERSION | typeof V010_RUNTIME_ASSET_VERSION | typeof CODEX_SKILL_ASSET_VERSION;
|
package/dist/asset-version.js
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* installed project marker without importing every asset body.
|
|
4
4
|
*/
|
|
5
5
|
export const RUNTIME_ASSET_VERSION = "0.3.89-completion-proof-v1";
|
|
6
|
-
export const V010_RUNTIME_ASSET_VERSION = "0.14.
|
|
7
|
-
export const CODEX_SKILL_ASSET_VERSION = "0.
|
|
6
|
+
export const V010_RUNTIME_ASSET_VERSION = "0.14.6-attachment-terra-v1";
|
|
7
|
+
export const CODEX_SKILL_ASSET_VERSION = "0.14.6-codex-skill-v1";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CodexTurnEvent } from "../codex/app-server.js";
|
|
2
|
-
export declare const CODEX_MISSION_USAGE = "Usage: sortie-dogs codex mission --prompt <text>\n [--resume <root-thread-id>] [--project-root <path>] [--executable <codex>] [--model <model>] [--effort <effort>] [--permissions <native-profile>] [--trusted-pwsh <absolute-pwsh.exe>]\n\nRuns the existing Mission Operator, Coordinator, Worker and Reviewer through Codex.\n--model and --effort explicitly override all roles; otherwise packaged role defaults apply.\n--permissions explicitly selects an existing native profile; omission retains native defaults.\nWindows uses existing PowerShell 7; --trusted-pwsh pins its absolute executable path.\nThe packaged Luna-fast
|
|
2
|
+
export declare const CODEX_MISSION_USAGE = "Usage: sortie-dogs codex mission --prompt <text>\n [--resume <root-thread-id>] [--project-root <path>] [--executable <codex>] [--model <model>] [--effort <effort>] [--permissions <native-profile>] [--trusted-pwsh <absolute-pwsh.exe>]\n\nRuns the existing Mission Operator, Coordinator, Worker and Reviewer through Codex.\n--model and --effort explicitly override all roles; otherwise packaged role defaults apply.\n--permissions explicitly selects an existing native profile; omission retains native defaults.\nWindows uses existing PowerShell 7; --trusted-pwsh pins its absolute executable path.\nThe packaged ordinary worker uses native gpt-6.1-terra/max, Standard (no Fast/priority).\nThe retained Luna-fast alias maps to native gpt-6-luna with the priority (Fast) service tier.\nUses existing ChatGPT authentication and native Codex permissions.";
|
|
3
3
|
export declare function runCodexMissionCommand(argv: readonly string[]): Promise<number>;
|
|
4
4
|
/** Bounded user-facing progress; do not dump control packets or hidden reasoning. */
|
|
5
5
|
export declare function codexMissionProgress(event: CodexTurnEvent & {
|
|
@@ -6,7 +6,8 @@ Runs the existing Mission Operator, Coordinator, Worker and Reviewer through Cod
|
|
|
6
6
|
--model and --effort explicitly override all roles; otherwise packaged role defaults apply.
|
|
7
7
|
--permissions explicitly selects an existing native profile; omission retains native defaults.
|
|
8
8
|
Windows uses existing PowerShell 7; --trusted-pwsh pins its absolute executable path.
|
|
9
|
-
The packaged
|
|
9
|
+
The packaged ordinary worker uses native gpt-6.1-terra/max, Standard (no Fast/priority).
|
|
10
|
+
The retained Luna-fast alias maps to native gpt-6-luna with the priority (Fast) service tier.
|
|
10
11
|
Uses existing ChatGPT authentication and native Codex permissions.`;
|
|
11
12
|
export async function runCodexMissionCommand(argv) {
|
|
12
13
|
if (argv.length === 1 && argv[0] === "--help") {
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
export interface MissionAttachment {
|
|
2
|
+
index: number;
|
|
3
|
+
part_id?: string;
|
|
4
|
+
mime?: string;
|
|
5
|
+
filename?: string;
|
|
6
|
+
url: string;
|
|
7
|
+
path?: string;
|
|
8
|
+
sha256?: string;
|
|
9
|
+
}
|
|
1
10
|
export interface PublicMissionContext {
|
|
2
11
|
id: string;
|
|
3
12
|
role: "user" | "assistant";
|
|
@@ -12,6 +21,7 @@ export interface PublicMissionContext {
|
|
|
12
21
|
exit?: number;
|
|
13
22
|
time?: unknown;
|
|
14
23
|
}[];
|
|
24
|
+
attachments?: MissionAttachment[];
|
|
15
25
|
}
|
|
16
26
|
export interface MissionContextSource {
|
|
17
27
|
session_id: string;
|
|
@@ -20,6 +30,9 @@ export interface MissionContextSource {
|
|
|
20
30
|
entries: number;
|
|
21
31
|
observed_at: string;
|
|
22
32
|
history_available: boolean;
|
|
33
|
+
attachments?: (MissionAttachment & {
|
|
34
|
+
message_id: string;
|
|
35
|
+
})[];
|
|
23
36
|
}
|
|
24
37
|
export interface MissionContinuity {
|
|
25
38
|
sources: MissionContextSource[];
|
|
@@ -70,4 +83,7 @@ export declare function missionContextView(source: MissionContextSource, entries
|
|
|
70
83
|
entries: number;
|
|
71
84
|
observed_at: string;
|
|
72
85
|
history_available: boolean;
|
|
86
|
+
attachments?: (MissionAttachment & {
|
|
87
|
+
message_id: string;
|
|
88
|
+
})[];
|
|
73
89
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
5
|
const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
5
6
|
/** Public task data only. Keep exact text/results in a lazy snapshot, not private reasoning. */
|
|
6
7
|
export function publicMissionContext(messages) {
|
|
@@ -11,6 +12,11 @@ export function publicMissionContext(messages) {
|
|
|
11
12
|
const parts = message.parts.filter(record);
|
|
12
13
|
const text = parts.filter(part => part.type === "text" && part.synthetic !== true && typeof part.text === "string")
|
|
13
14
|
.map(part => part.text).join("\n");
|
|
15
|
+
const attachments = info.role === "user" ? parts.filter(part => part.type === "file" && typeof part.url === "string")
|
|
16
|
+
.map((part, index) => ({ index, url: part.url,
|
|
17
|
+
...(typeof part.id === "string" ? { part_id: part.id } : {}),
|
|
18
|
+
...(typeof part.mime === "string" ? { mime: part.mime } : {}),
|
|
19
|
+
...(typeof part.filename === "string" ? { filename: part.filename } : {}) })) : [];
|
|
14
20
|
const tools = parts.flatMap(part => {
|
|
15
21
|
if (part.type !== "tool" || typeof part.tool !== "string" || !record(part.state))
|
|
16
22
|
return [];
|
|
@@ -23,17 +29,47 @@ export function publicMissionContext(messages) {
|
|
|
23
29
|
...(typeof metadata.exit === "number" ? { exit: metadata.exit } : {}),
|
|
24
30
|
...(part.time !== undefined ? { time: part.time } : {}) }];
|
|
25
31
|
});
|
|
26
|
-
return text.trim() || tools.length ? [{ id: info.id, role: info.role, text, tools
|
|
32
|
+
return text.trim() || tools.length || attachments.length ? [{ id: info.id, role: info.role, text, tools,
|
|
33
|
+
...(attachments.length ? { attachments } : {}) }] : [];
|
|
27
34
|
});
|
|
28
35
|
}
|
|
36
|
+
/** Store inline bytes once, not megabytes of base64 in every prompt/contract. No network fetch or new permission. */
|
|
37
|
+
async function retainAttachment(directory, attachment) {
|
|
38
|
+
if (!attachment.url.startsWith("data:")) {
|
|
39
|
+
try {
|
|
40
|
+
return attachment.url.startsWith("file:") ? { ...attachment, path: fileURLToPath(attachment.url) } : attachment;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return attachment;
|
|
44
|
+
} // Keep a host-specific URI usable on its owning host, not a new admission gate.
|
|
45
|
+
}
|
|
46
|
+
const comma = attachment.url.indexOf(",");
|
|
47
|
+
if (comma < 0)
|
|
48
|
+
return attachment;
|
|
49
|
+
const header = attachment.url.slice(0, comma), data = attachment.url.slice(comma + 1);
|
|
50
|
+
const bytes = /;base64$/i.test(header) ? Buffer.from(data, "base64") : Buffer.from(decodeURIComponent(data));
|
|
51
|
+
const sha256 = createHash("sha256").update(bytes).digest("hex");
|
|
52
|
+
const extension = { "image/png": ".png", "image/jpeg": ".jpg", "image/gif": ".gif", "image/webp": ".webp",
|
|
53
|
+
"application/pdf": ".pdf", "text/plain": ".txt" }[attachment.mime ?? ""] ?? ".bin";
|
|
54
|
+
const path = join(directory, "attachments", `${sha256}${extension}`);
|
|
55
|
+
await mkdir(join(directory, "attachments"), { recursive: true });
|
|
56
|
+
await writeFile(path, bytes, { flag: "wx" }).catch(error => {
|
|
57
|
+
if (error.code !== "EEXIST")
|
|
58
|
+
throw error;
|
|
59
|
+
});
|
|
60
|
+
return { ...attachment, url: pathToFileURL(path).href, path, sha256 };
|
|
61
|
+
}
|
|
29
62
|
/** Preserve earlier available entries when the host later returns a compacted/partial history. */
|
|
30
63
|
export async function retainMissionContext(directory, sessionID, messages, previous) {
|
|
31
64
|
const current = publicMissionContext(messages);
|
|
32
65
|
const retained = previous ? await readFile(previous.path, "utf8")
|
|
33
66
|
.then(content => JSON.parse(content).entries).catch(() => undefined) : undefined;
|
|
34
67
|
const merged = new Map((retained ?? []).map(entry => [entry.id, entry]));
|
|
35
|
-
for (const entry of current)
|
|
36
|
-
|
|
68
|
+
for (const entry of current) {
|
|
69
|
+
const attachments = entry.attachments ? await Promise.all(entry.attachments.map(file => retainAttachment(directory, file)))
|
|
70
|
+
: merged.get(entry.id)?.attachments;
|
|
71
|
+
merged.set(entry.id, { ...entry, ...(attachments?.length ? { attachments } : {}) });
|
|
72
|
+
}
|
|
37
73
|
const entries = [...merged.values()];
|
|
38
74
|
const content = JSON.stringify({ session_id: sessionID, entries }, null, 2) + "\n";
|
|
39
75
|
const sha256 = createHash("sha256").update(content).digest("hex");
|
|
@@ -42,8 +78,10 @@ export async function retainMissionContext(directory, sessionID, messages, previ
|
|
|
42
78
|
await mkdir(directory, { recursive: true });
|
|
43
79
|
await writeFile(path, content);
|
|
44
80
|
}
|
|
81
|
+
const attachments = entries.flatMap(entry => (entry.attachments ?? []).map(file => ({ message_id: entry.id, ...file })));
|
|
45
82
|
return { source: { session_id: sessionID, path, sha256, entries: entries.length,
|
|
46
|
-
observed_at: new Date().toISOString(), history_available: current.length > 0
|
|
83
|
+
observed_at: new Date().toISOString(), history_available: current.length > 0,
|
|
84
|
+
...(attachments.length ? { attachments } : {}) }, entries };
|
|
47
85
|
}
|
|
48
86
|
/** Small inline view, with explicit pointers to every omitted byte in the exact snapshot. */
|
|
49
87
|
export function missionContextView(source, entries, suppliedRequestIDs = []) {
|
|
@@ -338,7 +338,7 @@ export class OperatorMissionRuntime {
|
|
|
338
338
|
corrections: (state.corrections ?? []).map(({ initialPrompt: _prompt, inlineReview: _inline, ...correction }) => correction),
|
|
339
339
|
retained_review: state.review ? { run_id: state.review.runID, verdict: state.review.verdict,
|
|
340
340
|
mode: state.review.mode, author: state.review.child, result: state.review.result, self_recheck: state.review.selfRecheck } : null,
|
|
341
|
-
guidance: "Current original_requests/requirements govern; older plans remain historical. Continue from known decisions, environment, completed work, retained findings and failures. A new plan or author does not resolve findings or turn self-recheck into independent approval. Read snapshot JSON entries by message/call IDs only for a relevant gap. Recheck mutable facts when needed or conflicting; do not repeat unchanged setup/investigation/checks merely because ownership changed. Successful evidence remains with its actual author/call and input bindings; historical results are not new authority." } };
|
|
341
|
+
guidance: "Current original_requests/requirements govern; older plans remain historical. Original attachments are in sources[].attachments, ordered within each message; read their path/URL when relevant, not a prose substitute. Message IDs and indices preserve provenance, not an inferred mapping to user-assigned image numbers. Continue from known decisions, environment, completed work, retained findings and failures. A new plan or author does not resolve findings or turn self-recheck into independent approval. Read snapshot JSON entries by message/call IDs only for a relevant gap. Recheck mutable facts when needed or conflicting; do not repeat unchanged setup/investigation/checks merely because ownership changed. Successful evidence remains with its actual author/call and input bindings; historical results are not new authority." } };
|
|
342
342
|
}
|
|
343
343
|
async load(file) {
|
|
344
344
|
try {
|
|
@@ -870,6 +870,7 @@ export async function missionAcceptanceSummary(mission, run, operators, observe)
|
|
|
870
870
|
}
|
|
871
871
|
})));
|
|
872
872
|
return { original_requests: mission.requests, requirements: mission.requirements,
|
|
873
|
+
original_attachments: (mission.continuity?.sources ?? []).flatMap(source => (source.attachments ?? []).map(file => ({ session_id: source.session_id, ...file }))),
|
|
873
874
|
operation: missionOperationSummary(mission),
|
|
874
875
|
history: { status: missingAnchors.length ? "unavailable" : history.status,
|
|
875
876
|
...(history.reason ? { reason: history.reason } : missingAnchors.length ? { reason: "accepted-handoff-anchor-unavailable" } : {}),
|
|
@@ -887,7 +888,7 @@ export async function missionAcceptanceSummary(mission, run, operators, observe)
|
|
|
887
888
|
observation: mission.deliveryObservation && mission.deliveryObservation.run_id === current?.runID ? mission.deliveryObservation : null,
|
|
888
889
|
observation_source: "persisted operator Git lifecycle and formal validation records; no new Git inspection",
|
|
889
890
|
clean: mission.deliveryObservation && mission.deliveryObservation.run_id === current?.runID ? mission.deliveryObservation.clean : "not independently observed by this projection" },
|
|
890
|
-
interpretation: "Compare original requests with the submitted candidate and actual evidence. Historical PASS is not current PASS. Inspect concrete gaps, not routine archive searches or full source rereads. Existing completion and Review guards still apply." };
|
|
891
|
+
interpretation: "Compare original requests (including relevant original attachments) with the submitted candidate and what the actual evidence exercises. Functional PASS, Review PASS, or an honestly recorded unverified limitation does not establish a required visual comparison. If a mandatory outcome remains unmet, continue authorized retrieval, inspection or correction without waiting for the user. Optional caveats, valid alternative checks and reusable evidence need not block acceptance; do not reject on the word unverified alone or repeat all checks yourself. No new approval, proof file, extra Reviewer, universal screenshots or pixel-exact matching is required. Historical PASS is not current PASS. Inspect concrete gaps, not routine archive searches or full source rereads. Existing completion and Review guards still apply." };
|
|
891
892
|
}
|
|
892
893
|
export function missionReviewIndependent(mission, child) {
|
|
893
894
|
return child !== undefined && !mission.sourceAuthors?.includes(child) &&
|
|
@@ -83,10 +83,19 @@ const SNAPSHOT_COMMAND = [
|
|
|
83
83
|
"actual_cwd=$(pwd -P)",
|
|
84
84
|
"root=$(git rev-parse --show-toplevel)",
|
|
85
85
|
"cd \"$root\"",
|
|
86
|
-
|
|
86
|
+
// Only a missing symbolic target is an unborn repository. An existing/broken
|
|
87
|
+
// ref target or failed observation must not become an invented empty base.
|
|
88
|
+
"if tree=$(git rev-parse --verify 'HEAD^{tree}' 2>/dev/null); then",
|
|
87
89
|
// Capture successful producer output before hashing: POSIX pipelines otherwise
|
|
88
90
|
// hide failed Git/file reads behind a successful hash of empty/partial data.
|
|
89
91
|
"tracked=$(git diff --binary HEAD -- && printf '.')",
|
|
92
|
+
"else",
|
|
93
|
+
"ref=$(git symbolic-ref -q HEAD) || exit 1",
|
|
94
|
+
"if git show-ref --verify --quiet \"$ref\"; then exit 1; else [ \"$?\" = 1 ] || exit 1; fi",
|
|
95
|
+
// hash-object without -w computes the repository-format empty tree, no writes.
|
|
96
|
+
"tree=$(git hash-object -t tree --stdin </dev/null)",
|
|
97
|
+
"tracked=$(git diff --binary \"$tree\" -- && printf '.')",
|
|
98
|
+
"fi",
|
|
90
99
|
"tracked=${tracked%.}",
|
|
91
100
|
"tracked=$(printf '%s' \"$tracked\" | sha256sum)",
|
|
92
101
|
"tracked=${tracked%% *}",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export declare const MODEL_COST_PRICING_SNAPSHOT: {
|
|
2
|
-
readonly checkedAt: "2026-
|
|
2
|
+
readonly checkedAt: "2026-10-27";
|
|
3
3
|
readonly currency: "USD";
|
|
4
4
|
readonly unit: "1M tokens";
|
|
5
|
-
readonly sources: readonly ["https://developers.openai.com/api/docs/pricing", "https://developers.openai.com/api/docs/models/gpt-6-astra", "https://developers.openai.com/api/docs/models/gpt-6-sol", "https://developers.openai.com/api/docs/models/gpt-6.1-sol", "https://developers.openai.com/api/docs/models/gpt-6-luna", "https://developers.openai.com/api/docs/guides/fast-mode", "https://developers.openai.com/api/docs/models/gpt-5.6-sol", "https://developers.openai.com/api/docs/models/gpt-5.6-terra", "https://developers.openai.com/api/docs/models/gpt-5.6-luna", "https://platform.claude.com/docs/en/about-claude/pricing"];
|
|
6
|
-
readonly assumptions: readonly ["OpenAI Standard pricing; requests above 272,000 total input/cache tokens use 2x input/cache and 1.5x output pricing.", "Anthropic Standard pricing with the 5-minute cache-write rate; Batch, Flex, regional, tool, and subscription charges are excluded.", "variant and serviceTier are separate; model variants do not alter the selected Standard token price.", "GPT-6 Sol, GPT-6.1 Sol, and GPT-6 Luna use their official Standard schedules; the OpenCode gpt-6-luna-fast selector sends API model gpt-6-luna with priority service tier.", "For GPT-6 Sol, GPT-6.1 Sol, and GPT-6 Luna, Fast mode (service_tier fast or priority, including the gpt-6.1-sol-fast selector) multiplies applicable Standard rates by 2, including cache and long-context multipliers.", "gpt-5.6-luna-fast is retained only as a compatibility price for historical host catalog entries; it has no published model page and is exactly twice the GPT-5.6 Luna Standard schedule."];
|
|
5
|
+
readonly sources: readonly ["https://developers.openai.com/api/docs/pricing", "https://developers.openai.com/api/docs/models/gpt-6-astra", "https://developers.openai.com/api/docs/models/gpt-6-sol", "https://developers.openai.com/api/docs/models/gpt-6.1-sol", "https://developers.openai.com/api/docs/models/gpt-6.1-terra", "https://developers.openai.com/api/docs/models/gpt-6-luna", "https://developers.openai.com/api/docs/guides/fast-mode", "https://developers.openai.com/api/docs/models/gpt-5.6-sol", "https://developers.openai.com/api/docs/models/gpt-5.6-terra", "https://developers.openai.com/api/docs/models/gpt-5.6-luna", "https://platform.claude.com/docs/en/about-claude/pricing"];
|
|
6
|
+
readonly assumptions: readonly ["OpenAI Standard pricing; requests above 272,000 total input/cache tokens use 2x input/cache and 1.5x output pricing.", "Anthropic Standard pricing with the 5-minute cache-write rate; Batch, Flex, regional, tool, and subscription charges are excluded.", "variant and serviceTier are separate; model variants do not alter the selected Standard token price.", "GPT-6.1 Terra Standard uses $1 input, $0.05 cache read, $1.25 30-minute cache write and $5 output per 1M tokens; subscription usage/limits are separate from this API-equivalent estimate.", "GPT-6 Sol, GPT-6.1 Sol, and GPT-6 Luna use their official Standard schedules; the OpenCode gpt-6-luna-fast selector sends API model gpt-6-luna with priority service tier.", "For GPT-6 Sol, GPT-6.1 Sol, GPT-6.1 Terra, and GPT-6 Luna, Fast mode (service_tier fast or priority, including the gpt-6.1-sol-fast selector) multiplies applicable Standard rates by 2, including cache and long-context multipliers.", "gpt-5.6-luna-fast is retained only as a compatibility price for historical host catalog entries; it has no published model page and is exactly twice the GPT-5.6 Luna Standard schedule."];
|
|
7
7
|
};
|
|
8
8
|
export interface ModelCostUsage {
|
|
9
9
|
readonly providerID: string | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const MODEL_COST_PRICING_SNAPSHOT = {
|
|
2
|
-
checkedAt: "2026-
|
|
2
|
+
checkedAt: "2026-10-27",
|
|
3
3
|
currency: "USD",
|
|
4
4
|
unit: "1M tokens",
|
|
5
5
|
sources: [
|
|
@@ -7,6 +7,7 @@ export const MODEL_COST_PRICING_SNAPSHOT = {
|
|
|
7
7
|
"https://developers.openai.com/api/docs/models/gpt-6-astra",
|
|
8
8
|
"https://developers.openai.com/api/docs/models/gpt-6-sol",
|
|
9
9
|
"https://developers.openai.com/api/docs/models/gpt-6.1-sol",
|
|
10
|
+
"https://developers.openai.com/api/docs/models/gpt-6.1-terra",
|
|
10
11
|
"https://developers.openai.com/api/docs/models/gpt-6-luna",
|
|
11
12
|
"https://developers.openai.com/api/docs/guides/fast-mode",
|
|
12
13
|
"https://developers.openai.com/api/docs/models/gpt-5.6-sol",
|
|
@@ -18,8 +19,9 @@ export const MODEL_COST_PRICING_SNAPSHOT = {
|
|
|
18
19
|
"OpenAI Standard pricing; requests above 272,000 total input/cache tokens use 2x input/cache and 1.5x output pricing.",
|
|
19
20
|
"Anthropic Standard pricing with the 5-minute cache-write rate; Batch, Flex, regional, tool, and subscription charges are excluded.",
|
|
20
21
|
"variant and serviceTier are separate; model variants do not alter the selected Standard token price.",
|
|
22
|
+
"GPT-6.1 Terra Standard uses $1 input, $0.05 cache read, $1.25 30-minute cache write and $5 output per 1M tokens; subscription usage/limits are separate from this API-equivalent estimate.",
|
|
21
23
|
"GPT-6 Sol, GPT-6.1 Sol, and GPT-6 Luna use their official Standard schedules; the OpenCode gpt-6-luna-fast selector sends API model gpt-6-luna with priority service tier.",
|
|
22
|
-
"For GPT-6 Sol, GPT-6.1 Sol, and GPT-6 Luna, Fast mode (service_tier fast or priority, including the gpt-6.1-sol-fast selector) multiplies applicable Standard rates by 2, including cache and long-context multipliers.",
|
|
24
|
+
"For GPT-6 Sol, GPT-6.1 Sol, GPT-6.1 Terra, and GPT-6 Luna, Fast mode (service_tier fast or priority, including the gpt-6.1-sol-fast selector) multiplies applicable Standard rates by 2, including cache and long-context multipliers.",
|
|
23
25
|
"gpt-5.6-luna-fast is retained only as a compatibility price for historical host catalog entries; it has no published model page and is exactly twice the GPT-5.6 Luna Standard schedule.",
|
|
24
26
|
],
|
|
25
27
|
};
|
|
@@ -27,6 +29,7 @@ const OPENAI = {
|
|
|
27
29
|
"gpt-6-astra": { input: 10, cacheRead: 1, cacheWrite: 12.5, output: 50 },
|
|
28
30
|
"gpt-6-sol": { input: 2, cacheRead: 0.2, cacheWrite: 2.5, output: 10 },
|
|
29
31
|
"gpt-6.1-sol": { input: 2, cacheRead: 0.1, cacheWrite: 2.5, output: 10 },
|
|
32
|
+
"gpt-6.1-terra": { input: 1, cacheRead: 0.05, cacheWrite: 1.25, output: 5 },
|
|
30
33
|
"gpt-6-luna": { input: 0.1, cacheRead: 0.01, cacheWrite: 0.125, output: 0.5 },
|
|
31
34
|
"gpt-5.6-sol": { input: 4, cacheRead: 0.4, cacheWrite: 5, output: 20 },
|
|
32
35
|
"gpt-5.6": { input: 4, cacheRead: 0.4, cacheWrite: 5, output: 20 },
|
|
@@ -49,7 +52,7 @@ export function estimateModelUsageCost(usage) {
|
|
|
49
52
|
const sol61FastAlias = usage.providerID?.toLowerCase() === "openai" && usage.modelID === "gpt-6.1-sol-fast";
|
|
50
53
|
const alias = lunaFastAlias || sol61FastAlias;
|
|
51
54
|
const fast = alias || (["fast", "priority"].includes(usage.serviceTier?.toLowerCase() ?? "") &&
|
|
52
|
-
usage.providerID?.toLowerCase() === "openai" && ["gpt-6-sol", "gpt-6.1-sol", "gpt-6-luna"].includes(usage.modelID ?? ""));
|
|
55
|
+
usage.providerID?.toLowerCase() === "openai" && ["gpt-6-sol", "gpt-6.1-sol", "gpt-6.1-terra", "gpt-6-luna"].includes(usage.modelID ?? ""));
|
|
53
56
|
if (usage.serviceTier !== undefined && !(fast ? ["standard", "default", "fast", "priority"] : ["standard", "default"]).includes(usage.serviceTier.toLowerCase())) {
|
|
54
57
|
return { status: "unpriced", reason: "unsupported-service-tier" };
|
|
55
58
|
}
|
package/dist/plugin/profiled.js
CHANGED
|
@@ -36,7 +36,8 @@ const SERIAL_OPTIONAL_ARGUMENTS = new Map([
|
|
|
36
36
|
"scope", "trigger", "cause", "prevention", "evidence", "evidenceRef", "id", "promotedRef", "confirmation",
|
|
37
37
|
])],
|
|
38
38
|
]);
|
|
39
|
-
const PREVIEW_WORKER_ROUTE = Object.freeze({ model: "openai/gpt-6-
|
|
39
|
+
const PREVIEW_WORKER_ROUTE = Object.freeze({ model: "openai/gpt-6.1-terra", variant: "max" });
|
|
40
|
+
const PREVIEW_LUNA_WORKER_ROUTE = Object.freeze({ model: "openai/gpt-6-luna-fast", variant: "max" });
|
|
40
41
|
const PREVIEW_SCOUT_ROUTE = Object.freeze({ model: "openai/gpt-6-luna-fast", variant: "max" });
|
|
41
42
|
/**
|
|
42
43
|
* Contract authorship, not throughput. Qualification observed a cheaper operations model emit
|
|
@@ -49,7 +50,7 @@ const PREVIEW_PRIMARY_ROUTE = Object.freeze({ model: "openai/gpt-6.1-sol", varia
|
|
|
49
50
|
const PREVIEW_REVIEW_ROUTE = Object.freeze({ model: "openai/gpt-6.1-sol", variant: "xhigh" });
|
|
50
51
|
/** Every preview route the profile can bind a role to. Catalog declaration reads this one list. */
|
|
51
52
|
const PREVIEW_ROUTES = Object.freeze([
|
|
52
|
-
PREVIEW_PRIMARY_ROUTE, PREVIEW_WORKER_ROUTE, PREVIEW_SCOUT_ROUTE, PREVIEW_OPERATIONS_ROUTE,
|
|
53
|
+
PREVIEW_PRIMARY_ROUTE, PREVIEW_WORKER_ROUTE, PREVIEW_LUNA_WORKER_ROUTE, PREVIEW_SCOUT_ROUTE, PREVIEW_OPERATIONS_ROUTE,
|
|
53
54
|
PREVIEW_REVIEW_ROUTE,
|
|
54
55
|
]);
|
|
55
56
|
function missionReportReview(mission, runID) {
|
|
@@ -3811,7 +3812,7 @@ export function createProfiledPlugin(profile, assetVersion) {
|
|
|
3811
3812
|
const agent = record(agents[name]) ? agents[name] : undefined;
|
|
3812
3813
|
if (!agent)
|
|
3813
3814
|
continue;
|
|
3814
|
-
const route = role === "dog-scout" ? PREVIEW_SCOUT_ROUTE :
|
|
3815
|
+
const route = role === "dog-scout" ? PREVIEW_SCOUT_ROUTE : PREVIEW_LUNA_WORKER_ROUTE;
|
|
3815
3816
|
agent.model ??= route.model;
|
|
3816
3817
|
if (agent.variant === undefined && agent.model === route.model)
|
|
3817
3818
|
agent.variant = route.variant;
|
package/dist/plugin/v2.js
CHANGED
|
@@ -90,6 +90,22 @@ function legacyPart(value, session, message) {
|
|
|
90
90
|
...(time ? { time: { start: time.ran ?? time.created, end: time.completed } } : {}),
|
|
91
91
|
...(output === undefined ? {} : { output }) } };
|
|
92
92
|
}
|
|
93
|
+
/** Resolved V2 files carry the original bytes, even when their source URI is no longer readable. */
|
|
94
|
+
function legacyUserParts(text, files, session, message) {
|
|
95
|
+
return [{ id: `${message}-text`, sessionID: session, messageID: message, type: "text", text },
|
|
96
|
+
...array(files).flatMap((file, index) => {
|
|
97
|
+
if (!record(file))
|
|
98
|
+
return [];
|
|
99
|
+
const mime = string(file.mime) ?? "application/octet-stream";
|
|
100
|
+
const url = typeof file.data === "string" ? `data:${mime};base64,${file.data}`
|
|
101
|
+
: string(file.uri); // The prompt hook runs before URI resolution.
|
|
102
|
+
if (!url)
|
|
103
|
+
return [];
|
|
104
|
+
return [{ id: `${message}-file-${index}`, sessionID: session, messageID: message, type: "file", mime, url,
|
|
105
|
+
...(typeof file.name === "string" ? { filename: file.name } : {}),
|
|
106
|
+
...(record(file.source) ? { source: file.source } : {}) }];
|
|
107
|
+
})];
|
|
108
|
+
}
|
|
93
109
|
function legacyMessage(value, session, agent) {
|
|
94
110
|
if (!record(value) || typeof value.id !== "string" || typeof value.type !== "string")
|
|
95
111
|
return undefined;
|
|
@@ -97,7 +113,7 @@ function legacyMessage(value, session, agent) {
|
|
|
97
113
|
const originalAgent = record(value.metadata) ? string(value.metadata.agent) ?? agent : agent;
|
|
98
114
|
if (value.type === "user") {
|
|
99
115
|
return { info: { id, sessionID: session, role: "user", agent: originalAgent, time: value.time },
|
|
100
|
-
parts:
|
|
116
|
+
parts: legacyUserParts(String(value.text ?? ""), value.files, session, id) };
|
|
101
117
|
}
|
|
102
118
|
if (value.type !== "assistant") {
|
|
103
119
|
if (value.type === "synthetic")
|
|
@@ -289,8 +305,22 @@ function toolContentText(content) {
|
|
|
289
305
|
return values.length === 0 ? undefined : values.join("\n");
|
|
290
306
|
}
|
|
291
307
|
function replaceToolContent(result, text) {
|
|
292
|
-
|
|
293
|
-
|
|
308
|
+
if (toolContentText(result.content) === text)
|
|
309
|
+
return result;
|
|
310
|
+
if (typeof result.content === "string")
|
|
311
|
+
return { ...result, content: text };
|
|
312
|
+
let replaced = false;
|
|
313
|
+
const content = array(result.content).flatMap(item => {
|
|
314
|
+
if (!record(item) || item.type !== "text" || typeof item.text !== "string")
|
|
315
|
+
return [item];
|
|
316
|
+
if (replaced)
|
|
317
|
+
return [];
|
|
318
|
+
replaced = true;
|
|
319
|
+
return [{ ...item, text }];
|
|
320
|
+
});
|
|
321
|
+
// Only the legacy textual projection changed. Native file/image blocks must still reach
|
|
322
|
+
// the host's model-input lowering, including images returned through Code Mode.
|
|
323
|
+
return { ...result, content: replaced ? content : [...content, { type: "text", text }] };
|
|
294
324
|
}
|
|
295
325
|
function assistantText(message) {
|
|
296
326
|
if (!record(message) || message.type !== "assistant" || message.finish !== "stop" || typeof message.id !== "string")
|
|
@@ -542,7 +572,7 @@ async function registerV2Hooks(context, hooks, background, liveState) {
|
|
|
542
572
|
["dog-reviewer-v010", "gpt-6.1-sol", "xhigh"],
|
|
543
573
|
["dog-scout-v010", "gpt-6-luna-fast", "max"],
|
|
544
574
|
["dog-luna-worker-v010", "gpt-6-luna-fast", "max"],
|
|
545
|
-
["dog-worker-v010", "gpt-6-
|
|
575
|
+
["dog-worker-v010", "gpt-6.1-terra", "max"],
|
|
546
576
|
])
|
|
547
577
|
editor.update(name, agent => { agent.model ??= { providerID: "openai", id, variant }; });
|
|
548
578
|
editor.update("dog-reviewer-v010", agent => {
|
|
@@ -784,7 +814,7 @@ async function registerV2Hooks(context, hooks, background, liveState) {
|
|
|
784
814
|
selectedChildModels.add(String(event.sessionID));
|
|
785
815
|
}
|
|
786
816
|
const output = { message: { id: String(event.messageID ?? ""), agent: string(info.agent), model },
|
|
787
|
-
parts:
|
|
817
|
+
parts: legacyUserParts(legacyText, event.prompt.files, String(event.sessionID), String(event.messageID ?? "")) };
|
|
788
818
|
await hooks["chat.message"]({ sessionID: String(event.sessionID), messageID: String(event.messageID ?? ""),
|
|
789
819
|
...(typeof info.agent === "string" ? { agent: info.agent } : {}), model }, output);
|
|
790
820
|
await reconcileCorrectionPermissions(String(event.sessionID));
|
|
@@ -427,7 +427,8 @@ export const runtimeAssets = Object.freeze([
|
|
|
427
427
|
content = content.replace("mode: subagent\n", "mode: subagent\nhidden: true\n");
|
|
428
428
|
}
|
|
429
429
|
if (["dog-worker", "dog-luna-worker", "dog-scout"].includes(asset.name)) {
|
|
430
|
-
|
|
430
|
+
const model = asset.name === "dog-worker" ? "openai/gpt-6.1-terra#max" : "openai/gpt-6-luna-fast#max";
|
|
431
|
+
content = content.replace("mode: subagent\n", `mode: subagent\nmodel: ${model}\n`);
|
|
431
432
|
}
|
|
432
433
|
if (["dog-reviewer", "dog-advisor"].includes(asset.name)) {
|
|
433
434
|
content = content.replace("mode: subagent\n", "mode: subagent\nmodel: openai/gpt-6.1-sol#xhigh\n");
|
|
@@ -216,7 +216,17 @@ ${MISSION_DEPENDENCY_WORKFLOW}
|
|
|
216
216
|
and cumulative budget. Use its Coordinator Task only for real coordination, contract discovery or
|
|
217
217
|
correction that cannot be handled directly. Never replace an active Worker or ask for routine approval.
|
|
218
218
|
4. After the review decision (including a justified low-risk skip), compare the completion candidate
|
|
219
|
-
|
|
219
|
+
against the original request, real source and observed evidence before final acceptance.
|
|
220
|
+
Include relevant original attachments: continuity sources retain ordered, message-linked read references
|
|
221
|
+
to the original bytes, not a descriptive substitute. Retrieve/inspect those references when needed.
|
|
222
|
+
Judge what each existing check actually exercises. Functional PASS, Review PASS, or honestly retaining
|
|
223
|
+
an unverified caveat does not establish a required visual comparison. If a mandatory outcome is unmet,
|
|
224
|
+
continue authorized retrieval, inspection or correction without waiting for a user reminder or approval.
|
|
225
|
+
Choose the effective method/author; reuse applicable evidence rather than repeat every check yourself.
|
|
226
|
+
Optional caveats and valid alternative verification can permit acceptance: the word unverified alone
|
|
227
|
+
is not a stop rule. This adds no approval gate, proof file, extra Reviewer, universal screenshot duty
|
|
228
|
+
or pixel-exact matching requirement. Keep autonomy, efficiency and visibility: report the actual gap
|
|
229
|
+
and next action, not an unsupported completion claim or a new restriction on ordinary work.
|
|
220
230
|
For a Coordinator ready candidate, use operator_status's acceptance_summary: verbatim original
|
|
221
231
|
requests, anchored cumulative formal validation, current review disposition (author self-recheck
|
|
222
232
|
is not independent approval) and recorded delivery state.
|