@cat-factory/kernel 0.283.0 → 0.285.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/dist/domain/design-image-delivery.d.ts +128 -0
- package/dist/domain/design-image-delivery.d.ts.map +1 -0
- package/dist/domain/design-image-delivery.js +83 -0
- package/dist/domain/design-image-delivery.js.map +1 -0
- package/dist/domain/harness-capabilities.d.ts +7 -5
- package/dist/domain/harness-capabilities.d.ts.map +1 -1
- package/dist/domain/harness-capabilities.js +28 -8
- package/dist/domain/harness-capabilities.js.map +1 -1
- package/dist/domain/models.d.ts +2 -0
- package/dist/domain/models.d.ts.map +1 -1
- package/dist/domain/models.js +68 -11
- package/dist/domain/models.js.map +1 -1
- package/dist/domain/types.d.ts +40 -0
- package/dist/domain/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/ports/agent-executor.d.ts +39 -8
- package/dist/ports/agent-executor.d.ts.map +1 -1
- package/dist/ports/agent-executor.js.map +1 -1
- package/dist/ports/model-provider.d.ts +14 -0
- package/dist/ports/model-provider.d.ts.map +1 -1
- package/dist/ports/model-provider.js.map +1 -1
- package/dist/ports/pr-mergeability.d.ts +9 -1
- package/dist/ports/pr-mergeability.d.ts.map +1 -1
- package/dist/ports/pr-merger.d.ts +5 -2
- package/dist/ports/pr-merger.d.ts.map +1 -1
- package/dist/ports/pr-report.d.ts +10 -3
- package/dist/ports/pr-report.d.ts.map +1 -1
- package/dist/ports/runner-transport.d.ts +5 -1
- package/dist/ports/runner-transport.d.ts.map +1 -1
- package/dist/shared/redact-image-payloads.logic.d.ts +14 -0
- package/dist/shared/redact-image-payloads.logic.d.ts.map +1 -0
- package/dist/shared/redact-image-payloads.logic.js +100 -0
- package/dist/shared/redact-image-payloads.logic.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { HarnessKind, ModelRef } from '../ports/model-provider.js';
|
|
2
|
+
/**
|
|
3
|
+
* Which harnesses can put an IMAGE in front of their model, as an exhaustive `Record` over
|
|
4
|
+
* `HarnessKind` so a new harness cannot be added without stating its answer (an omitted entry
|
|
5
|
+
* would read as `false` and silently drop every render on that harness).
|
|
6
|
+
*
|
|
7
|
+
* `false` is a statement about THIS repo's pinned CLI, not a claim about the vendor's product. The
|
|
8
|
+
* bar for `true` is that the image has a verified way to get bytes into a turn, because the cost of
|
|
9
|
+
* guessing is asymmetric: a harness wrongly marked `true` is handed a manifest, downloads the
|
|
10
|
+
* frames, tells the agent they are there, and the agent then reports it cannot see them, which
|
|
11
|
+
* reads to everyone as a platform bug rather than as a missing capability. A harness wrongly marked
|
|
12
|
+
* `false` costs a run the pictures and SAYS SO, which is the disposition the whole vocabulary
|
|
13
|
+
* below exists to give.
|
|
14
|
+
*
|
|
15
|
+
* - `claude-code` reads an image file with its own file-reading tool, which is why the container
|
|
16
|
+
* half of this feature is files on disk plus a prompt that names them: the CLI composes the
|
|
17
|
+
* image content part, exactly as it does for a screenshot a human pastes at it.
|
|
18
|
+
* - `codex` and `pi` are `false` today. Codex's pinned CLI has no verified file-to-turn path in
|
|
19
|
+
* this image, and Pi has no image input at all (the same reason it has no MCP client). Flip an
|
|
20
|
+
* entry here in the change that teaches the image to carry the bytes, never ahead of it.
|
|
21
|
+
*/
|
|
22
|
+
export declare const HARNESS_IMAGE_INPUT: Record<HarnessKind, boolean>;
|
|
23
|
+
/**
|
|
24
|
+
* Whether this harness can open an image file the platform wrote into the checkout.
|
|
25
|
+
*
|
|
26
|
+
* TOTAL over `HarnessKind`, with no "no harness" case: an inline call has no CLI to ask about, and
|
|
27
|
+
* letting `undefined` answer `true` here is what once let the ambient inline path (a harness CLI
|
|
28
|
+
* fed one-shot text) inherit the container answer and promise files nothing wrote. Which channel a
|
|
29
|
+
* site has is {@link DesignImageCarrier}'s job to state, not this table's to guess.
|
|
30
|
+
*/
|
|
31
|
+
export declare function harnessAcceptsImages(harness: HarnessKind): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Why a run's design renders were NOT put in front of its model.
|
|
34
|
+
*
|
|
35
|
+
* Each member names a DIFFERENT fix, which is why they are not folded into one "unavailable":
|
|
36
|
+
*
|
|
37
|
+
* - `harness_no_image_input` is the CLI: this kind runs in a container on a harness with no way to
|
|
38
|
+
* read an image into a turn. Switching the step's model to another image-capable one changes
|
|
39
|
+
* nothing; the fix is a different harness (or an image that teaches this one).
|
|
40
|
+
* - `model_no_image_input` is the model: the harness could carry an image and the resolved model
|
|
41
|
+
* does not take one. Here the fix IS the model, which is why it must not read as the harness's
|
|
42
|
+
* limitation.
|
|
43
|
+
* - `unknown_model_image_input` is the honest third answer, and the commonest: the catalog does not
|
|
44
|
+
* declare whether this flavour accepts images. It is kept apart from `model_no_image_input`
|
|
45
|
+
* because they send a reader to opposite places (declare the capability, versus pick a different
|
|
46
|
+
* model), and collapsing them would let an undeclared multimodal model read as a text-only one
|
|
47
|
+
* forever, with nothing anywhere saying the platform simply never asked.
|
|
48
|
+
* - `transfer_failed` is the store: the pair CAN carry an image and the bytes did not arrive. The
|
|
49
|
+
* only transient member, and the only one worth retrying.
|
|
50
|
+
*
|
|
51
|
+
* Two more name a SEAM that carries no picture whatever the harness and the model could do, so
|
|
52
|
+
* neither comes out of {@link resolveDesignImageDelivery}: there is no pair to join, and the site
|
|
53
|
+
* that knows which seam it is states it directly, exactly as the store's own failure does.
|
|
54
|
+
*
|
|
55
|
+
* - `inline_harness_text_only` is the ambient inline path: the deployment serves a subscription ref
|
|
56
|
+
* by driving its CLI as a host subprocess with one-shot text on stdin. It names a harness whose
|
|
57
|
+
* container dispatch reads image files perfectly well, and has neither a checkout to write one
|
|
58
|
+
* into nor a message part to attach. The fix is a deployment's, not a run's: serve this kind
|
|
59
|
+
* somewhere that has one.
|
|
60
|
+
* - `consensus_panel` is a diverted step: its participants share ONE composed prompt string across
|
|
61
|
+
* models that need not agree about image input, so there is nothing to attach a picture to. Named
|
|
62
|
+
* for the surface rather than for a capability, and spelled to match the `UnavailableToolServer`
|
|
63
|
+
* reason a panel already reports for the same reason on the same surface.
|
|
64
|
+
*
|
|
65
|
+
* There is deliberately no member for "the task has no design": that is an absent set, not a
|
|
66
|
+
* refused delivery, and a run with nothing to show must not tell its agent that something was
|
|
67
|
+
* withheld.
|
|
68
|
+
*/
|
|
69
|
+
export type DesignImageUnavailableReason = 'harness_no_image_input' | 'model_no_image_input' | 'unknown_model_image_input' | 'inline_harness_text_only' | 'consensus_panel' | 'transfer_failed';
|
|
70
|
+
/**
|
|
71
|
+
* HOW the pictures reached the model, when they did.
|
|
72
|
+
*
|
|
73
|
+
* Carried rather than re-derived at each prompt site, because the two channels put the images in
|
|
74
|
+
* different places and a prompt that names the wrong one is worse than one that names neither: a
|
|
75
|
+
* container agent told its designs are "attached below" goes looking through a message that has
|
|
76
|
+
* none, and an inline model pointed at a checkout directory has no filesystem to look in.
|
|
77
|
+
*
|
|
78
|
+
* - `files` — the harness wrote them into the checkout and the CLI reads them with its own
|
|
79
|
+
* image-reading tool, which is what composes the image content part.
|
|
80
|
+
* - `message` — the caller put them in the model request itself, as image parts (an inline call:
|
|
81
|
+
* there is no CLI in between and no disk to write to).
|
|
82
|
+
*/
|
|
83
|
+
export type DesignImageChannel = 'files' | 'message';
|
|
84
|
+
/**
|
|
85
|
+
* What a dispatch decided about its renders: a discriminated result rather than a nullable one, so
|
|
86
|
+
* "not attached" always arrives WITH its cause and the prompt can state it.
|
|
87
|
+
*/
|
|
88
|
+
export type DesignImageDelivery = {
|
|
89
|
+
attached: true;
|
|
90
|
+
channel: DesignImageChannel;
|
|
91
|
+
} | {
|
|
92
|
+
attached: false;
|
|
93
|
+
reason: DesignImageUnavailableReason;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* The route a dispatch site has for putting bytes in front of its model: the half of the decision
|
|
97
|
+
* that is a property of the SEAM rather than of the model.
|
|
98
|
+
*
|
|
99
|
+
* Declared by the site because only the site knows it. "Is a harness named" does not answer it (the
|
|
100
|
+
* ambient inline path names one and can carry nothing), and neither does "is this call inline" (a
|
|
101
|
+
* consensus panel is inline and can carry nothing either). A site with no route at all does not
|
|
102
|
+
* build a carrier: it states its own refusal from the two seam reasons above.
|
|
103
|
+
*/
|
|
104
|
+
export type DesignImageCarrier =
|
|
105
|
+
/** A container dispatch: the harness downloads the files and its CLI opens them. */
|
|
106
|
+
{
|
|
107
|
+
channel: 'files';
|
|
108
|
+
harness: HarnessKind;
|
|
109
|
+
}
|
|
110
|
+
/** An inline model call composing its own request, so it can add image parts itself. */
|
|
111
|
+
| {
|
|
112
|
+
channel: 'message';
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Join the two halves for one dispatch: the carrier's ability to carry an image and the resolved
|
|
116
|
+
* model's ability to take one.
|
|
117
|
+
*
|
|
118
|
+
* The carrier is asked FIRST, and the order is load-bearing rather than stylistic. A subscription
|
|
119
|
+
* harness pins its own model, so a Codex run reporting `model_no_image_input` would send someone to
|
|
120
|
+
* change a model they cannot change without also changing the harness; the CLI is the outer
|
|
121
|
+
* constraint and the honest one to name.
|
|
122
|
+
*
|
|
123
|
+
* `acceptsImages` is a tri-state on purpose (see {@link DesignImageUnavailableReason}): `true`
|
|
124
|
+
* attaches, `false` refuses as the model's limitation, and ABSENT refuses as the platform's own
|
|
125
|
+
* silence about this flavour.
|
|
126
|
+
*/
|
|
127
|
+
export declare function resolveDesignImageDelivery(carrier: DesignImageCarrier, ref: Pick<ModelRef, 'acceptsImages'>): DesignImageDelivery;
|
|
128
|
+
//# sourceMappingURL=design-image-delivery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-image-delivery.d.ts","sourceRoot":"","sources":["../../src/domain/design-image-delivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAyBvE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,OAAO,CAI5D,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAElE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,MAAM,4BAA4B,GACpC,wBAAwB,GACxB,sBAAsB,GACtB,2BAA2B,GAC3B,0BAA0B,GAC1B,iBAAiB,GACjB,iBAAiB,CAAA;AAErB;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,CAAA;AAEpD;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,GAC/C;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,4BAA4B,CAAA;CAAE,CAAA;AAE7D;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB;AAC5B,oFAAoF;AAClF;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE;AAC5C,wFAAwF;GACtF;IAAE,OAAO,EAAE,SAAS,CAAA;CAAE,CAAA;AAE1B;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,kBAAkB,EAC3B,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,GACnC,mBAAmB,CASrB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Whether a dispatch can put a design RENDER in front of its model, and the reason when it
|
|
3
|
+
// cannot.
|
|
4
|
+
//
|
|
5
|
+
// The platform holds pictures of a task's linked designs (the frames an import retained, plus the
|
|
6
|
+
// images a person attached), and until now they reached a model on no path at all: a container
|
|
7
|
+
// agent got the textual `.cat-context/` description and an explicit instruction NOT to fetch the
|
|
8
|
+
// preview URL, and an inline caller got the same text. What a designer actually cares about, what
|
|
9
|
+
// the screen looks like, was invisible to every agent building it.
|
|
10
|
+
//
|
|
11
|
+
// Delivery is a PAIR fact, and both halves have to be true: the dispatch site must have a CHANNEL
|
|
12
|
+
// that can carry bytes to the model, and the model must accept them. Neither half implies the
|
|
13
|
+
// other, so they are declared separately and joined here, once, rather than re-derived at each
|
|
14
|
+
// delivery site.
|
|
15
|
+
//
|
|
16
|
+
// The channel is stated BY the call site rather than inferred from "is there a harness", because
|
|
17
|
+
// the two are not the same question and the sites where they disagree are exactly the ones that
|
|
18
|
+
// break silently. An ambient inline run drives a harness CLI with one-shot text on stdin: it names
|
|
19
|
+
// a harness, has no checkout to write a file into, and flattens its message to a string, so it can
|
|
20
|
+
// carry a picture by neither route. A consensus panel is inline with no harness at all and still
|
|
21
|
+
// cannot carry one, because its participants share a single composed prompt string.
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
/**
|
|
24
|
+
* Which harnesses can put an IMAGE in front of their model, as an exhaustive `Record` over
|
|
25
|
+
* `HarnessKind` so a new harness cannot be added without stating its answer (an omitted entry
|
|
26
|
+
* would read as `false` and silently drop every render on that harness).
|
|
27
|
+
*
|
|
28
|
+
* `false` is a statement about THIS repo's pinned CLI, not a claim about the vendor's product. The
|
|
29
|
+
* bar for `true` is that the image has a verified way to get bytes into a turn, because the cost of
|
|
30
|
+
* guessing is asymmetric: a harness wrongly marked `true` is handed a manifest, downloads the
|
|
31
|
+
* frames, tells the agent they are there, and the agent then reports it cannot see them, which
|
|
32
|
+
* reads to everyone as a platform bug rather than as a missing capability. A harness wrongly marked
|
|
33
|
+
* `false` costs a run the pictures and SAYS SO, which is the disposition the whole vocabulary
|
|
34
|
+
* below exists to give.
|
|
35
|
+
*
|
|
36
|
+
* - `claude-code` reads an image file with its own file-reading tool, which is why the container
|
|
37
|
+
* half of this feature is files on disk plus a prompt that names them: the CLI composes the
|
|
38
|
+
* image content part, exactly as it does for a screenshot a human pastes at it.
|
|
39
|
+
* - `codex` and `pi` are `false` today. Codex's pinned CLI has no verified file-to-turn path in
|
|
40
|
+
* this image, and Pi has no image input at all (the same reason it has no MCP client). Flip an
|
|
41
|
+
* entry here in the change that teaches the image to carry the bytes, never ahead of it.
|
|
42
|
+
*/
|
|
43
|
+
export const HARNESS_IMAGE_INPUT = {
|
|
44
|
+
pi: false,
|
|
45
|
+
'claude-code': true,
|
|
46
|
+
codex: false,
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Whether this harness can open an image file the platform wrote into the checkout.
|
|
50
|
+
*
|
|
51
|
+
* TOTAL over `HarnessKind`, with no "no harness" case: an inline call has no CLI to ask about, and
|
|
52
|
+
* letting `undefined` answer `true` here is what once let the ambient inline path (a harness CLI
|
|
53
|
+
* fed one-shot text) inherit the container answer and promise files nothing wrote. Which channel a
|
|
54
|
+
* site has is {@link DesignImageCarrier}'s job to state, not this table's to guess.
|
|
55
|
+
*/
|
|
56
|
+
export function harnessAcceptsImages(harness) {
|
|
57
|
+
return HARNESS_IMAGE_INPUT[harness];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Join the two halves for one dispatch: the carrier's ability to carry an image and the resolved
|
|
61
|
+
* model's ability to take one.
|
|
62
|
+
*
|
|
63
|
+
* The carrier is asked FIRST, and the order is load-bearing rather than stylistic. A subscription
|
|
64
|
+
* harness pins its own model, so a Codex run reporting `model_no_image_input` would send someone to
|
|
65
|
+
* change a model they cannot change without also changing the harness; the CLI is the outer
|
|
66
|
+
* constraint and the honest one to name.
|
|
67
|
+
*
|
|
68
|
+
* `acceptsImages` is a tri-state on purpose (see {@link DesignImageUnavailableReason}): `true`
|
|
69
|
+
* attaches, `false` refuses as the model's limitation, and ABSENT refuses as the platform's own
|
|
70
|
+
* silence about this flavour.
|
|
71
|
+
*/
|
|
72
|
+
export function resolveDesignImageDelivery(carrier, ref) {
|
|
73
|
+
if (carrier.channel === 'files' && !harnessAcceptsImages(carrier.harness)) {
|
|
74
|
+
return { attached: false, reason: 'harness_no_image_input' };
|
|
75
|
+
}
|
|
76
|
+
if (ref.acceptsImages === undefined) {
|
|
77
|
+
return { attached: false, reason: 'unknown_model_image_input' };
|
|
78
|
+
}
|
|
79
|
+
if (!ref.acceptsImages)
|
|
80
|
+
return { attached: false, reason: 'model_no_image_input' };
|
|
81
|
+
return { attached: true, channel: carrier.channel };
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=design-image-delivery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-image-delivery.js","sourceRoot":"","sources":["../../src/domain/design-image-delivery.ts"],"names":[],"mappings":"AAEA,8EAA8E;AAC9E,2FAA2F;AAC3F,UAAU;AACV,EAAE;AACF,kGAAkG;AAClG,+FAA+F;AAC/F,iGAAiG;AACjG,kGAAkG;AAClG,mEAAmE;AACnE,EAAE;AACF,kGAAkG;AAClG,8FAA8F;AAC9F,+FAA+F;AAC/F,iBAAiB;AACjB,EAAE;AACF,iGAAiG;AACjG,gGAAgG;AAChG,mGAAmG;AACnG,mGAAmG;AACnG,iGAAiG;AACjG,oFAAoF;AACpF,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAiC;IAC/D,EAAE,EAAE,KAAK;IACT,aAAa,EAAE,IAAI;IACnB,KAAK,EAAE,KAAK;CACb,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAoB;IACvD,OAAO,mBAAmB,CAAC,OAAO,CAAC,CAAA;AACrC,CAAC;AAqFD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAA2B,EAC3B,GAAoC;IAEpC,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1E,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAA;IAC9D,CAAC;IACD,IAAI,GAAG,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAA;IACjE,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,aAAa;QAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAA;IAClF,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAA;AACrD,CAAC"}
|
|
@@ -7,13 +7,19 @@ import type { RunnerDispatchAck, RunnerJobStopOutcome } from '../ports/runner-tr
|
|
|
7
7
|
* (`packageRegistries`, `validation`) needs no handshake, because an older image simply does less and
|
|
8
8
|
* the run reports what it did. Adding a member here is a claim that the PROMPT would lie.
|
|
9
9
|
*
|
|
10
|
+
* That is also why `designImages` is a member and `referenceScreenshots` is not, though they are the
|
|
11
|
+
* same wire shape: the capture block is composed BY the harness out of what actually landed, so an
|
|
12
|
+
* image that ignores the field simply says nothing, while the design block is composed by the
|
|
13
|
+
* BACKEND (only it knows the delivery verdict and the views no container was sent) and would name a
|
|
14
|
+
* directory an older image never wrote.
|
|
15
|
+
*
|
|
10
16
|
* Keyed as an exhaustive `Record` so the list below cannot drift from the union, and mirrored
|
|
11
17
|
* byte-for-byte by the harness's own `HARNESS_BODY_CAPABILITIES` (the image is built from `src/`
|
|
12
18
|
* plus typescript alone, so it can depend on no workspace package). The pairing is pinned by the
|
|
13
19
|
* harness's `test/agent-capabilities.conformity.test.ts`, the same copy-plus-pin arrangement the
|
|
14
20
|
* id/tool-name patterns use.
|
|
15
21
|
*/
|
|
16
|
-
export type HarnessBodyCapability = 'mcpServers' | 'skills';
|
|
22
|
+
export type HarnessBodyCapability = 'mcpServers' | 'skills' | 'designImages';
|
|
17
23
|
/** Every capability the handshake covers. Derived, so it cannot drift from the union. */
|
|
18
24
|
export declare const HARNESS_BODY_CAPABILITIES: HarnessBodyCapability[];
|
|
19
25
|
/** What a capability is, for an operator-facing message. */
|
|
@@ -41,10 +47,6 @@ export declare function parseHarnessBodyCapabilities(value: unknown): HarnessBod
|
|
|
41
47
|
* dropped every tool server for its own reasons (an unsupported harness, a missing credential)
|
|
42
48
|
* promised the agent nothing and has nothing to verify. What must line up is the body and the
|
|
43
49
|
* PROMPT, and the prompt is composed from the same resolution the body is.
|
|
44
|
-
*
|
|
45
|
-
* A capability's name IS its body field name, deliberately. That is what lets this stay one
|
|
46
|
-
* filter instead of a second mapping to keep in step, and it is why the harness's own list is a
|
|
47
|
-
* list of field names too.
|
|
48
50
|
*/
|
|
49
51
|
export declare function requiredHarnessCapabilities(body: Readonly<Record<string, unknown>>): HarnessBodyCapability[];
|
|
50
52
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-capabilities.d.ts","sourceRoot":"","sources":["../../src/domain/harness-capabilities.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAE3F
|
|
1
|
+
{"version":3,"file":"harness-capabilities.d.ts","sourceRoot":"","sources":["../../src/domain/harness-capabilities.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAE3F;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,qBAAqB,GAAG,YAAY,GAAG,QAAQ,GAAG,cAAc,CAAA;AAS5E,yFAAyF;AACzF,eAAO,MAAM,yBAAyB,EAEjC,qBAAqB,EAAE,CAAA;AAE5B,4DAA4D;AAC5D,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,qBAAqB,GAAG,MAAM,CAEvF;AAED,kEAAkE;AAClE,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,qBAAqB,CAItF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,qBAAqB,EAAE,GAAG,SAAS,CAGhG;AAgCD;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACtC,qBAAqB,EAAE,CAIzB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,iBAAiB,GAAG,SAAS,CAMlF;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,wBAAwB,GAChC;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,qBAAqB,EAAE,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,qBAAqB,EAAE,CAAA;CAAE,CAAA;AAE7D,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,SAAS,qBAAqB,EAAE,EAC1C,QAAQ,EAAE,SAAS,qBAAqB,EAAE,GAAG,SAAS,GACrD,wBAAwB,CAK1B;AAED;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,GAAG,QAAQ,CAAA;AAmCjE;;;;;GAKG;AACH,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,SAAS,qBAAqB,EAAE,EACzC,IAAI,EAAE,mBAAmB,GACxB,MAAM,CAQR"}
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
const HARNESS_BODY_CAPABILITY_LABELS = {
|
|
20
20
|
mcpServers: 'tool servers (MCP)',
|
|
21
21
|
skills: 'skills',
|
|
22
|
+
designImages: 'design pictures',
|
|
22
23
|
};
|
|
23
24
|
/** Every capability the handshake covers. Derived, so it cannot drift from the union. */
|
|
24
25
|
export const HARNESS_BODY_CAPABILITIES = Object.keys(HARNESS_BODY_CAPABILITY_LABELS);
|
|
@@ -48,6 +49,32 @@ export function parseHarnessBodyCapabilities(value) {
|
|
|
48
49
|
return undefined;
|
|
49
50
|
return value.filter(isHarnessBodyCapability);
|
|
50
51
|
}
|
|
52
|
+
/** A non-empty array: the wire shape of every capability that is simply a list. */
|
|
53
|
+
function isPopulatedList(value) {
|
|
54
|
+
return Array.isArray(value) && value.length > 0;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* What "the body carries this capability" means for each one, as an exhaustive `Record` so a new
|
|
58
|
+
* member cannot be added without stating its own answer.
|
|
59
|
+
*
|
|
60
|
+
* A predicate per capability rather than one shape test over all of them, because the field shapes
|
|
61
|
+
* genuinely differ and the wrong generalisation is SILENT in the worst direction: `designImages` is
|
|
62
|
+
* an object (`{ url, token, files }`), so the populated-list test every list-shaped capability
|
|
63
|
+
* shares reads it as absent, the handshake never fires for it, and an image that predates the field
|
|
64
|
+
* ignores the manifest while the backend's prompt names a directory nothing wrote. That is
|
|
65
|
+
* precisely the blind run this whole handshake exists to refuse.
|
|
66
|
+
*
|
|
67
|
+
* The KEY is still the body field name, which is what keeps the harness's own list a list of field
|
|
68
|
+
* names and needs no second mapping there; only the emptiness test lives here.
|
|
69
|
+
*/
|
|
70
|
+
const HARNESS_BODY_CAPABILITY_CARRIED = {
|
|
71
|
+
mcpServers: isPopulatedList,
|
|
72
|
+
skills: isPopulatedList,
|
|
73
|
+
// A manifest with no files promises the agent nothing, exactly as an empty server list does.
|
|
74
|
+
designImages: (value) => typeof value === 'object' &&
|
|
75
|
+
value !== null &&
|
|
76
|
+
isPopulatedList(value.files),
|
|
77
|
+
};
|
|
51
78
|
/**
|
|
52
79
|
* Which capabilities a job body actually CARRIES, which is what the handshake is checked against.
|
|
53
80
|
*
|
|
@@ -55,16 +82,9 @@ export function parseHarnessBodyCapabilities(value) {
|
|
|
55
82
|
* dropped every tool server for its own reasons (an unsupported harness, a missing credential)
|
|
56
83
|
* promised the agent nothing and has nothing to verify. What must line up is the body and the
|
|
57
84
|
* PROMPT, and the prompt is composed from the same resolution the body is.
|
|
58
|
-
*
|
|
59
|
-
* A capability's name IS its body field name, deliberately. That is what lets this stay one
|
|
60
|
-
* filter instead of a second mapping to keep in step, and it is why the harness's own list is a
|
|
61
|
-
* list of field names too.
|
|
62
85
|
*/
|
|
63
86
|
export function requiredHarnessCapabilities(body) {
|
|
64
|
-
return HARNESS_BODY_CAPABILITIES.filter((capability) =>
|
|
65
|
-
const value = body[capability];
|
|
66
|
-
return Array.isArray(value) && value.length > 0;
|
|
67
|
-
});
|
|
87
|
+
return HARNESS_BODY_CAPABILITIES.filter((capability) => HARNESS_BODY_CAPABILITY_CARRIED[capability](body[capability]));
|
|
68
88
|
}
|
|
69
89
|
/**
|
|
70
90
|
* Read a harness's `POST /jobs` acceptance body into a {@link RunnerDispatchAck}.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-capabilities.js","sourceRoot":"","sources":["../../src/domain/harness-capabilities.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,iGAAiG;AACjG,EAAE;AACF,6FAA6F;AAC7F,gGAAgG;AAChG,kGAAkG;AAClG,4FAA4F;AAC5F,kGAAkG;AAClG,kGAAkG;AAClG,0FAA0F;AAC1F,EAAE;AACF,4FAA4F;AAC5F,6FAA6F;AAC7F,8FAA8F;AAC9F,wFAAwF;AACxF,6FAA6F;AAC7F,4FAA4F;
|
|
1
|
+
{"version":3,"file":"harness-capabilities.js","sourceRoot":"","sources":["../../src/domain/harness-capabilities.ts"],"names":[],"mappings":"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"}
|
package/dist/domain/models.d.ts
CHANGED
|
@@ -87,6 +87,8 @@ export interface BedrockVariant {
|
|
|
87
87
|
baseModelId: string;
|
|
88
88
|
/** Context window at Bedrock, when known (often differs from the vendor's own API). */
|
|
89
89
|
contextTokens?: number;
|
|
90
|
+
/** Whether Bedrock serves this model with image input. See {@link ModelRef.acceptsImages}. */
|
|
91
|
+
acceptsImages?: boolean;
|
|
90
92
|
}
|
|
91
93
|
/**
|
|
92
94
|
* A subscription-only variant: the model runs in the Claude Code / Codex harness
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/domain/models.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EAEvB,4BAA4B,EAC7B,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAGvE;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,4EAMiB,CAAA;AAE3C;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,2BAA2B,EAAE,SAAS,WAAW,EAAkB,CAAA;AAEhF;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,qCAA+B,CAAA;AASrE,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAC,WAAW,EAAE,aAAa,GAAG,OAAO,CAAC,CAAA;IACtD,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,kBAAkB,EAAE,wBAAwB,CAmBrF,CAAA;AAiBD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,QAAQ,CAAA;IACb,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAA;IACd,kEAAkE;IAClE,aAAa,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAA;IACnB,uFAAuF;IACvF,aAAa,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/domain/models.ts"],"names":[],"mappings":"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"}
|
package/dist/domain/models.js
CHANGED
|
@@ -72,6 +72,7 @@ export const MODEL_CATALOG = [
|
|
|
72
72
|
provider: 'workers-ai',
|
|
73
73
|
model: '@cf/meta/llama-4-scout-17b-16e-instruct',
|
|
74
74
|
contextTokens: 131_072,
|
|
75
|
+
acceptsImages: true,
|
|
75
76
|
},
|
|
76
77
|
},
|
|
77
78
|
{
|
|
@@ -284,7 +285,12 @@ export const MODEL_CATALOG = [
|
|
|
284
285
|
description: "Anthropic's most capable model — run via Claude Code on your Claude subscription, " +
|
|
285
286
|
'or pay-as-you-go through OpenRouter (billed at Anthropic rates).',
|
|
286
287
|
openrouter: {
|
|
287
|
-
ref: {
|
|
288
|
+
ref: {
|
|
289
|
+
provider: 'openrouter',
|
|
290
|
+
model: 'anthropic/claude-fable-5',
|
|
291
|
+
contextTokens: 1_000_000,
|
|
292
|
+
acceptsImages: true,
|
|
293
|
+
},
|
|
288
294
|
keyEnv: 'OPENROUTER_API_KEY',
|
|
289
295
|
providerLabel: 'OpenRouter',
|
|
290
296
|
},
|
|
@@ -294,6 +300,7 @@ export const MODEL_CATALOG = [
|
|
|
294
300
|
model: 'claude-fable-5',
|
|
295
301
|
harness: 'claude-code',
|
|
296
302
|
contextTokens: 1_000_000,
|
|
303
|
+
acceptsImages: true,
|
|
297
304
|
},
|
|
298
305
|
vendor: 'claude',
|
|
299
306
|
},
|
|
@@ -306,7 +313,12 @@ export const MODEL_CATALOG = [
|
|
|
306
313
|
'same price, run via Claude Code on your Claude subscription, or pay-as-you-go ' +
|
|
307
314
|
'through OpenRouter (billed at Anthropic rates).',
|
|
308
315
|
openrouter: {
|
|
309
|
-
ref: {
|
|
316
|
+
ref: {
|
|
317
|
+
provider: 'openrouter',
|
|
318
|
+
model: 'anthropic/claude-opus-5',
|
|
319
|
+
contextTokens: 1_000_000,
|
|
320
|
+
acceptsImages: true,
|
|
321
|
+
},
|
|
310
322
|
keyEnv: 'OPENROUTER_API_KEY',
|
|
311
323
|
providerLabel: 'OpenRouter',
|
|
312
324
|
},
|
|
@@ -316,6 +328,7 @@ export const MODEL_CATALOG = [
|
|
|
316
328
|
model: 'claude-opus-5',
|
|
317
329
|
harness: 'claude-code',
|
|
318
330
|
contextTokens: 1_000_000,
|
|
331
|
+
acceptsImages: true,
|
|
319
332
|
},
|
|
320
333
|
vendor: 'claude',
|
|
321
334
|
},
|
|
@@ -332,6 +345,7 @@ export const MODEL_CATALOG = [
|
|
|
332
345
|
model: 'claude-sonnet-5',
|
|
333
346
|
harness: 'claude-code',
|
|
334
347
|
contextTokens: 1_000_000,
|
|
348
|
+
acceptsImages: true,
|
|
335
349
|
},
|
|
336
350
|
vendor: 'claude',
|
|
337
351
|
},
|
|
@@ -348,7 +362,7 @@ export const MODEL_CATALOG = [
|
|
|
348
362
|
// would silently run 4.8 for a block pinned to 5. No `contextTokens`: Bedrock's window
|
|
349
363
|
// for this model is per-account and we have none verified, and an invented number would
|
|
350
364
|
// cap the proxy's output budget against a limit nobody measured.
|
|
351
|
-
bedrock: { baseModelId: 'anthropic.claude-opus-4-8' },
|
|
365
|
+
bedrock: { baseModelId: 'anthropic.claude-opus-4-8', acceptsImages: true },
|
|
352
366
|
},
|
|
353
367
|
// The GPT-5.6 tiers are what Codex actually serves today: `sol` (flagship), `terra`
|
|
354
368
|
// (balanced everyday) and `luna` (cheapest). The model id IS the Codex `--model` slug —
|
|
@@ -361,12 +375,23 @@ export const MODEL_CATALOG = [
|
|
|
361
375
|
description: "OpenAI's flagship for complex coding and research — run via Codex on your ChatGPT " +
|
|
362
376
|
'subscription, or pay-as-you-go through OpenRouter (billed at OpenAI rates).',
|
|
363
377
|
openrouter: {
|
|
364
|
-
ref: {
|
|
378
|
+
ref: {
|
|
379
|
+
provider: 'openrouter',
|
|
380
|
+
model: 'openai/gpt-5.6-sol',
|
|
381
|
+
contextTokens: 1_050_000,
|
|
382
|
+
acceptsImages: true,
|
|
383
|
+
},
|
|
365
384
|
keyEnv: 'OPENROUTER_API_KEY',
|
|
366
385
|
providerLabel: 'OpenRouter',
|
|
367
386
|
},
|
|
368
387
|
subscription: {
|
|
369
|
-
ref: {
|
|
388
|
+
ref: {
|
|
389
|
+
provider: 'openai',
|
|
390
|
+
model: 'gpt-5.6-sol',
|
|
391
|
+
harness: 'codex',
|
|
392
|
+
contextTokens: 1_050_000,
|
|
393
|
+
acceptsImages: true,
|
|
394
|
+
},
|
|
370
395
|
vendor: 'codex',
|
|
371
396
|
},
|
|
372
397
|
},
|
|
@@ -377,7 +402,12 @@ export const MODEL_CATALOG = [
|
|
|
377
402
|
description: "OpenAI's balanced everyday model — GPT-5.5-class capability at a fraction of the cost. " +
|
|
378
403
|
'The migration target for GPT-5.4, which Codex retires on 31 Aug 2026.',
|
|
379
404
|
openrouter: {
|
|
380
|
-
ref: {
|
|
405
|
+
ref: {
|
|
406
|
+
provider: 'openrouter',
|
|
407
|
+
model: 'openai/gpt-5.6-terra',
|
|
408
|
+
contextTokens: 1_050_000,
|
|
409
|
+
acceptsImages: true,
|
|
410
|
+
},
|
|
381
411
|
keyEnv: 'OPENROUTER_API_KEY',
|
|
382
412
|
providerLabel: 'OpenRouter',
|
|
383
413
|
},
|
|
@@ -387,6 +417,7 @@ export const MODEL_CATALOG = [
|
|
|
387
417
|
model: 'gpt-5.6-terra',
|
|
388
418
|
harness: 'codex',
|
|
389
419
|
contextTokens: 1_050_000,
|
|
420
|
+
acceptsImages: true,
|
|
390
421
|
},
|
|
391
422
|
vendor: 'codex',
|
|
392
423
|
},
|
|
@@ -398,7 +429,12 @@ export const MODEL_CATALOG = [
|
|
|
398
429
|
description: "OpenAI's fastest, cheapest GPT-5.6 tier — for clear, repeatable tasks. The migration " +
|
|
399
430
|
'target for GPT-5.4 mini.',
|
|
400
431
|
openrouter: {
|
|
401
|
-
ref: {
|
|
432
|
+
ref: {
|
|
433
|
+
provider: 'openrouter',
|
|
434
|
+
model: 'openai/gpt-5.6-luna',
|
|
435
|
+
contextTokens: 1_050_000,
|
|
436
|
+
acceptsImages: true,
|
|
437
|
+
},
|
|
402
438
|
keyEnv: 'OPENROUTER_API_KEY',
|
|
403
439
|
providerLabel: 'OpenRouter',
|
|
404
440
|
},
|
|
@@ -408,6 +444,7 @@ export const MODEL_CATALOG = [
|
|
|
408
444
|
model: 'gpt-5.6-luna',
|
|
409
445
|
harness: 'codex',
|
|
410
446
|
contextTokens: 1_050_000,
|
|
447
|
+
acceptsImages: true,
|
|
411
448
|
},
|
|
412
449
|
vendor: 'codex',
|
|
413
450
|
},
|
|
@@ -420,14 +457,25 @@ export const MODEL_CATALOG = [
|
|
|
420
457
|
'ChatGPT subscription, pay-as-you-go through OpenRouter (billed at OpenAI rates), or ' +
|
|
421
458
|
'on AWS Bedrock. The newest OpenAI generation Bedrock serves: the GPT-5.6 tiers are ' +
|
|
422
459
|
'Codex/OpenRouter only.',
|
|
423
|
-
bedrock: { baseModelId: 'openai.gpt-5.5', contextTokens: 1_050_000 },
|
|
460
|
+
bedrock: { baseModelId: 'openai.gpt-5.5', contextTokens: 1_050_000, acceptsImages: true },
|
|
424
461
|
openrouter: {
|
|
425
|
-
ref: {
|
|
462
|
+
ref: {
|
|
463
|
+
provider: 'openrouter',
|
|
464
|
+
model: 'openai/gpt-5.5',
|
|
465
|
+
contextTokens: 1_050_000,
|
|
466
|
+
acceptsImages: true,
|
|
467
|
+
},
|
|
426
468
|
keyEnv: 'OPENROUTER_API_KEY',
|
|
427
469
|
providerLabel: 'OpenRouter',
|
|
428
470
|
},
|
|
429
471
|
subscription: {
|
|
430
|
-
ref: {
|
|
472
|
+
ref: {
|
|
473
|
+
provider: 'openai',
|
|
474
|
+
model: 'gpt-5.5',
|
|
475
|
+
harness: 'codex',
|
|
476
|
+
contextTokens: 1_050_000,
|
|
477
|
+
acceptsImages: true,
|
|
478
|
+
},
|
|
431
479
|
vendor: 'codex',
|
|
432
480
|
},
|
|
433
481
|
},
|
|
@@ -455,6 +503,7 @@ export const MODEL_CATALOG = [
|
|
|
455
503
|
provider: 'openrouter',
|
|
456
504
|
model: 'google/gemini-3.1-pro-preview',
|
|
457
505
|
contextTokens: 1_048_576,
|
|
506
|
+
acceptsImages: true,
|
|
458
507
|
},
|
|
459
508
|
keyEnv: 'OPENROUTER_API_KEY',
|
|
460
509
|
providerLabel: 'OpenRouter',
|
|
@@ -467,7 +516,12 @@ export const MODEL_CATALOG = [
|
|
|
467
516
|
description: "Google's newest model and its positioned workhorse — 1M-token context at a fraction of " +
|
|
468
517
|
'Pro pricing. Via OpenRouter, billed at Google rates.',
|
|
469
518
|
openrouter: {
|
|
470
|
-
ref: {
|
|
519
|
+
ref: {
|
|
520
|
+
provider: 'openrouter',
|
|
521
|
+
model: 'google/gemini-3.6-flash',
|
|
522
|
+
contextTokens: 1_048_576,
|
|
523
|
+
acceptsImages: true,
|
|
524
|
+
},
|
|
471
525
|
keyEnv: 'OPENROUTER_API_KEY',
|
|
472
526
|
providerLabel: 'OpenRouter',
|
|
473
527
|
},
|
|
@@ -667,6 +721,9 @@ const FLAVOR_HANDLERS = {
|
|
|
667
721
|
// deployment that hasn't configured Bedrock, which is most of them.
|
|
668
722
|
model: resolveBedrockModelId(m.bedrock.baseModelId, caps) ?? m.bedrock.baseModelId,
|
|
669
723
|
...(m.bedrock.contextTokens ? { contextTokens: m.bedrock.contextTokens } : {}),
|
|
724
|
+
...(m.bedrock.acceptsImages === undefined
|
|
725
|
+
? {}
|
|
726
|
+
: { acceptsImages: m.bedrock.acceptsImages }),
|
|
670
727
|
},
|
|
671
728
|
flavor: 'bedrock',
|
|
672
729
|
providerLabel: 'AWS Bedrock',
|