@lucascouts/claude-agent-acp-plus 0.26.0 → 0.28.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/acp-agent.d.ts +99 -23
- package/dist/acp-agent.d.ts.map +1 -1
- package/dist/acp-agent.js +264 -85
- package/dist/ultracode.d.ts +138 -72
- package/dist/ultracode.d.ts.map +1 -1
- package/dist/ultracode.js +208 -75
- package/package.json +1 -1
package/dist/ultracode.d.ts
CHANGED
|
@@ -1,100 +1,166 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Ultracode — an independent, session-scoped boolean option.
|
|
3
3
|
*
|
|
4
|
-
* **
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* **What it is.** The SDK's `Settings.ultracode` is *"standing
|
|
5
|
+
* dynamic-workflow orchestration at any effort level"*, session-scoped and
|
|
6
|
+
* applied through `apply_flag_settings`. It is not an effort level and it does
|
|
7
|
+
* not imply one: the CLI (`/effort ultracode on|off`, "any effort level, this
|
|
8
|
+
* session only") and the VS Code extension (a switch in the effort popover)
|
|
9
|
+
* both model it as a toggle beside effort. An earlier version of this module
|
|
10
|
+
* followed an older extension tooltip ("xhigh + workflows") and drew it as a
|
|
11
|
+
* notch in the effort select that forced `xhigh`; that silently raised the
|
|
12
|
+
* effort of a session started with `ultracode: true`, cleared it on any effort
|
|
13
|
+
* pick, and lost it on a model switch (PARITY-REPORT §21.2).
|
|
11
14
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
15
|
+
* **The wire contract** (`applyFlagSettings`, unchanged SDK 0.3.285..0.3.299):
|
|
16
|
+
* - `ultracode: true|false` turns it on or off and leaves effort alone;
|
|
17
|
+
* - an `effortLevel` change sent WITHOUT the key turns it off;
|
|
18
|
+
* - `null` resets it to off.
|
|
19
|
+
* Hence the two payload rules below: the toggle sends `{ultracode:true}` or
|
|
20
|
+
* `{ultracode:null}`, and every effort change re-sends `ultracode:true` while
|
|
21
|
+
* the intent is on — and never `null`.
|
|
16
22
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
23
|
+
* **Intent is not availability.** The CLI keeps the request and computes "in
|
|
24
|
+
* effect = requested and available", where available means workflows are
|
|
25
|
+
* enabled and the model supports `xhigh`. The adapter mirrors that: the
|
|
26
|
+
* session holds the intent, the option is shown only while available, and a
|
|
27
|
+
* model switch never drops the intent. The CLI reports both through the
|
|
28
|
+
* `get_settings` control request (`applied.{ultracode, ultracodeRequested,
|
|
29
|
+
* ultracodeAvailable}`), which the SDK runtime exposes as `Query.getSettings()`
|
|
30
|
+
* but `sdk.d.ts` does not declare — {@link readUltracodeState} wraps it.
|
|
22
31
|
*
|
|
23
32
|
* Kept self-contained — no import from `acp-agent.ts` — for the reason
|
|
24
|
-
* `thinking-option.ts` and `rewind-command.ts` state: that file is ~
|
|
25
|
-
* and moves upstream almost daily, so every coupling to it is paid again
|
|
26
|
-
* each sync.
|
|
33
|
+
* `thinking-option.ts` and `rewind-command.ts` state: that file is ~10,000
|
|
34
|
+
* lines and moves upstream almost daily, so every coupling to it is paid again
|
|
35
|
+
* at each sync.
|
|
27
36
|
*/
|
|
37
|
+
import type { SessionConfigOption, SetSessionConfigOptionRequest } from "@agentclientprotocol/sdk";
|
|
28
38
|
import type { EffortLevel, Settings } from "@anthropic-ai/claude-agent-sdk";
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
export declare const ULTRACODE_OPTION_VALUE = "ultracode";
|
|
33
|
-
/** Display name of that entry, matching the extension's own label. */
|
|
39
|
+
/** Config option id. */
|
|
40
|
+
export declare const ULTRACODE_CONFIG_ID = "ultracode";
|
|
41
|
+
/** Display name, matching the CLI's and the extension's label. */
|
|
34
42
|
export declare const ULTRACODE_OPTION_NAME = "Ultracode";
|
|
35
|
-
/**
|
|
36
|
-
*
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
/** Select-fallback values for clients without boolean config options. The
|
|
44
|
+
* same spelling Fast mode uses, so one client-side mapping serves both. */
|
|
45
|
+
export declare const ULTRACODE_ON = "on";
|
|
46
|
+
export declare const ULTRACODE_OFF = "off";
|
|
47
|
+
/** The effort level the model must support for Ultracode to be available.
|
|
48
|
+
* Availability only: Ultracode never SETS this level. */
|
|
39
49
|
export declare const ULTRACODE_EFFORT_LEVEL: EffortLevel;
|
|
40
|
-
/**
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
50
|
+
/** The value the old effort-select notch carried. Accepted for one release
|
|
51
|
+
* from clients that still send it (see {@link isLegacyUltracodeEffort}). */
|
|
52
|
+
export declare const LEGACY_ULTRACODE_EFFORT_VALUE = "ultracode";
|
|
53
|
+
/** Display state for the option, resolved by the caller. Mirrors
|
|
54
|
+
* `FastModeOptionState`: availability and value are different questions. */
|
|
44
55
|
export interface UltracodeOptionState {
|
|
45
|
-
/** Whether the
|
|
56
|
+
/** Whether the option is shown at all. */
|
|
46
57
|
available: boolean;
|
|
47
|
-
/**
|
|
48
|
-
|
|
58
|
+
/** The session's intent — shown as the option's value. */
|
|
59
|
+
requested: boolean;
|
|
60
|
+
/** Whether the client opted into boolean config options. */
|
|
61
|
+
useBooleanOption: boolean;
|
|
49
62
|
}
|
|
50
63
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
64
|
+
* The fallback availability check, used until (or instead of) the CLI's own
|
|
65
|
+
* `applied.ultracodeAvailable`:
|
|
53
66
|
*
|
|
54
|
-
* 1. workflows are not disabled — Ultracode *is*
|
|
55
|
-
*
|
|
56
|
-
* happen;
|
|
57
|
-
* 2. the current model supports `xhigh` — Ultracode has no meaning on a model
|
|
58
|
-
* that cannot reach the level it implies.
|
|
67
|
+
* 1. workflows are not disabled — Ultracode *is* workflow orchestration;
|
|
68
|
+
* 2. the current model supports `xhigh`.
|
|
59
69
|
*
|
|
60
|
-
*
|
|
61
|
-
* `
|
|
62
|
-
* same direction the extension's
|
|
70
|
+
* Partial by nature: the CLI also checks managed settings, org policy,
|
|
71
|
+
* `enableWorkflows` and `CLAUDE_CODE_DISABLE_WORKFLOWS`. An absent
|
|
72
|
+
* `disableWorkflows` opens the gate, the same direction the extension's
|
|
73
|
+
* `=== !0` comparison takes.
|
|
63
74
|
*/
|
|
64
75
|
export declare function isUltracodeAvailable(supportedEffortLevels: readonly string[], settings: Pick<Settings, "disableWorkflows"> | undefined): boolean;
|
|
65
|
-
/**
|
|
66
|
-
|
|
76
|
+
/** Build the option: a native boolean for clients that opted in, an on/off
|
|
77
|
+
* select otherwise (the ACP boolean-config-option RFD makes that a MUST). */
|
|
78
|
+
export declare function createUltracodeConfigOption(requested: boolean, useBooleanOption: boolean): SessionConfigOption;
|
|
79
|
+
/** The option for a resolved state, or `undefined` while unavailable. */
|
|
80
|
+
export declare function ultracodeConfigOption(state: UltracodeOptionState | undefined): SessionConfigOption | undefined;
|
|
67
81
|
/**
|
|
68
|
-
*
|
|
82
|
+
* Put the option where it belongs in an existing list — right after `effort`
|
|
83
|
+
* (after `model` when the model has no effort option), before `fast` — or
|
|
84
|
+
* remove it when `next` is undefined. Used when a background readback changes
|
|
85
|
+
* availability without a full rebuild.
|
|
86
|
+
*/
|
|
87
|
+
export declare function placeUltracodeOption(options: SessionConfigOption[], next: SessionConfigOption | undefined): SessionConfigOption[];
|
|
88
|
+
/** Resolve the requested value from `session/set_config_option`: a native
|
|
89
|
+
* boolean, or the on/off select-fallback strings. */
|
|
90
|
+
export declare function resolveUltracodeRequested(params: SetSessionConfigOptionRequest): boolean;
|
|
91
|
+
/** The toggle's payload. Off is an explicit `null`: `undefined` is dropped by
|
|
92
|
+
* JSON transport, and the SDK only clears a flag on `null`. */
|
|
93
|
+
export declare function ultracodeTogglePayload(requested: boolean): {
|
|
94
|
+
ultracode: true | null;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* The `apply_flag_settings` payload for an effort change — a user pick, the
|
|
98
|
+
* model-switch fallback, the initial effort, or a recreate's replay.
|
|
69
99
|
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* has to say something about `ultracode`, not just the one that turns it on:
|
|
74
|
-
* without the clear, picking `High` after Ultracode would lower the effort and
|
|
75
|
-
* leave workflow orchestration running, which is a state no picker entry names.
|
|
76
|
-
* The same reasoning applies to `effortLevel` — this function absorbed the older
|
|
77
|
-
* `toSdkEffortLevel` helper for exactly that reason: both keys are decided in
|
|
78
|
-
* one place, so neither can be forgotten on a path the other takes.
|
|
100
|
+
* An `effortLevel` change sent without `ultracode` turns Ultracode off, so the
|
|
101
|
+
* key rides along whenever the intent is on. It is never sent as `null` here:
|
|
102
|
+
* an effort change is not a request to turn Ultracode off.
|
|
79
103
|
*
|
|
80
|
-
* @param value the
|
|
81
|
-
*
|
|
104
|
+
* @param value the effort select's value — `"default"`, an `EffortLevel`, or
|
|
105
|
+
* `undefined` when the model has no effort option.
|
|
82
106
|
*/
|
|
83
|
-
export declare function
|
|
107
|
+
export declare function effortFlagSettings(value: string | undefined, ultracodeRequested: boolean): {
|
|
84
108
|
effortLevel: EffortLevel | null;
|
|
85
|
-
ultracode
|
|
109
|
+
ultracode?: true;
|
|
86
110
|
};
|
|
111
|
+
/** Whether an effort value is the retired Ultracode notch. Clients that saved
|
|
112
|
+
* it get `{effortLevel:'xhigh', ultracode:true}` for one release. */
|
|
113
|
+
export declare function isLegacyUltracodeEffort(value: unknown): boolean;
|
|
114
|
+
/** What the CLI reported. Each field is absent when the CLI did not say. */
|
|
115
|
+
export interface UltracodeReadback {
|
|
116
|
+
requested?: boolean;
|
|
117
|
+
available?: boolean;
|
|
118
|
+
}
|
|
87
119
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
120
|
+
* Read `applied.{ultracodeRequested, ultracodeAvailable}` through the SDK's
|
|
121
|
+
* untyped `Query.getSettings()`.
|
|
122
|
+
*
|
|
123
|
+
* Structural, never trusting: an SDK without the method, a rejected request,
|
|
124
|
+
* or a response without `applied` all resolve to `undefined`, and the caller
|
|
125
|
+
* keeps the heuristic. Never rejects.
|
|
90
126
|
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
*
|
|
127
|
+
* **Call it in the background, never inline.** Control requests are
|
|
128
|
+
* serialized and queue ahead of interrupt and close (upstream #1216), and on a
|
|
129
|
+
* fresh session the CLI does not service them until the first turn.
|
|
130
|
+
*/
|
|
131
|
+
export declare function readUltracodeState(query: unknown, onError?: (error: unknown) => void): Promise<UltracodeReadback | undefined>;
|
|
132
|
+
/**
|
|
133
|
+
* The slice of a session these helpers read and write. Structural, so this
|
|
134
|
+
* module does not import the `Session` type from `acp-agent.ts`.
|
|
135
|
+
*/
|
|
136
|
+
export interface UltracodeSession {
|
|
137
|
+
query: {
|
|
138
|
+
applyFlagSettings(settings: Record<string, unknown>): Promise<void>;
|
|
139
|
+
};
|
|
140
|
+
configOptions: SessionConfigOption[];
|
|
141
|
+
/** The intent: what the user (or settings, or the CLI's readback) asked for. */
|
|
142
|
+
ultracodeRequested: boolean;
|
|
143
|
+
/** Whether the option is shown: the CLI's `applied.ultracodeAvailable` when
|
|
144
|
+
* read, else {@link isUltracodeAvailable}'s heuristic. */
|
|
145
|
+
ultracodeAvailable: boolean;
|
|
146
|
+
}
|
|
147
|
+
/** Rebuild the option in place from the session's state. */
|
|
148
|
+
export declare function refreshUltracodeOption(session: UltracodeSession, useBooleanOption: boolean): void;
|
|
149
|
+
/** Toggle the intent. Applies first, then records — a rejected control
|
|
150
|
+
* request leaves the session and its option untouched, as Fast mode does. */
|
|
151
|
+
export declare function applyUltracodeToggle(session: UltracodeSession, requested: boolean, useBooleanOption: boolean): Promise<void>;
|
|
152
|
+
/**
|
|
153
|
+
* The one-release migration for clients that still send the retired notch:
|
|
154
|
+
* `effort = "ultracode"` becomes `{effortLevel:'xhigh', ultracode:true}`.
|
|
155
|
+
* Returns `false`, sending nothing, when this model's effort select does not
|
|
156
|
+
* offer `xhigh` — the caller then rejects the value like any other.
|
|
157
|
+
*/
|
|
158
|
+
export declare function applyLegacyUltracodeEffort(session: UltracodeSession, useBooleanOption: boolean): Promise<boolean>;
|
|
159
|
+
/**
|
|
160
|
+
* Fold a CLI readback into the session. Availability is always taken; the
|
|
161
|
+
* intent only when `seedIntent` (session start — a model switch keeps the
|
|
162
|
+
* intent it has). Returns whether the option the client sees changed, i.e.
|
|
163
|
+
* whether a `config_option_update` is owed.
|
|
98
164
|
*/
|
|
99
|
-
export declare function
|
|
165
|
+
export declare function applyUltracodeReadback(session: UltracodeSession, readback: UltracodeReadback, seedIntent: boolean, useBooleanOption: boolean): boolean;
|
|
100
166
|
//# sourceMappingURL=ultracode.d.ts.map
|
package/dist/ultracode.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ultracode.d.ts","sourceRoot":"","sources":["../src/ultracode.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ultracode.d.ts","sourceRoot":"","sources":["../src/ultracode.ts"],"names":[],"mappings":"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"}
|
package/dist/ultracode.js
CHANGED
|
@@ -1,103 +1,236 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Ultracode — an independent, session-scoped boolean option.
|
|
3
3
|
*
|
|
4
|
-
* **
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* **What it is.** The SDK's `Settings.ultracode` is *"standing
|
|
5
|
+
* dynamic-workflow orchestration at any effort level"*, session-scoped and
|
|
6
|
+
* applied through `apply_flag_settings`. It is not an effort level and it does
|
|
7
|
+
* not imply one: the CLI (`/effort ultracode on|off`, "any effort level, this
|
|
8
|
+
* session only") and the VS Code extension (a switch in the effort popover)
|
|
9
|
+
* both model it as a toggle beside effort. An earlier version of this module
|
|
10
|
+
* followed an older extension tooltip ("xhigh + workflows") and drew it as a
|
|
11
|
+
* notch in the effort select that forced `xhigh`; that silently raised the
|
|
12
|
+
* effort of a session started with `ultracode: true`, cleared it on any effort
|
|
13
|
+
* pick, and lost it on a model switch (PARITY-REPORT §21.2).
|
|
11
14
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
15
|
+
* **The wire contract** (`applyFlagSettings`, unchanged SDK 0.3.285..0.3.299):
|
|
16
|
+
* - `ultracode: true|false` turns it on or off and leaves effort alone;
|
|
17
|
+
* - an `effortLevel` change sent WITHOUT the key turns it off;
|
|
18
|
+
* - `null` resets it to off.
|
|
19
|
+
* Hence the two payload rules below: the toggle sends `{ultracode:true}` or
|
|
20
|
+
* `{ultracode:null}`, and every effort change re-sends `ultracode:true` while
|
|
21
|
+
* the intent is on — and never `null`.
|
|
16
22
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
23
|
+
* **Intent is not availability.** The CLI keeps the request and computes "in
|
|
24
|
+
* effect = requested and available", where available means workflows are
|
|
25
|
+
* enabled and the model supports `xhigh`. The adapter mirrors that: the
|
|
26
|
+
* session holds the intent, the option is shown only while available, and a
|
|
27
|
+
* model switch never drops the intent. The CLI reports both through the
|
|
28
|
+
* `get_settings` control request (`applied.{ultracode, ultracodeRequested,
|
|
29
|
+
* ultracodeAvailable}`), which the SDK runtime exposes as `Query.getSettings()`
|
|
30
|
+
* but `sdk.d.ts` does not declare — {@link readUltracodeState} wraps it.
|
|
22
31
|
*
|
|
23
32
|
* Kept self-contained — no import from `acp-agent.ts` — for the reason
|
|
24
|
-
* `thinking-option.ts` and `rewind-command.ts` state: that file is ~
|
|
25
|
-
* and moves upstream almost daily, so every coupling to it is paid again
|
|
26
|
-
* each sync.
|
|
33
|
+
* `thinking-option.ts` and `rewind-command.ts` state: that file is ~10,000
|
|
34
|
+
* lines and moves upstream almost daily, so every coupling to it is paid again
|
|
35
|
+
* at each sync.
|
|
27
36
|
*/
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
export const ULTRACODE_OPTION_VALUE = "ultracode";
|
|
32
|
-
/** Display name of that entry, matching the extension's own label. */
|
|
37
|
+
/** Config option id. */
|
|
38
|
+
export const ULTRACODE_CONFIG_ID = "ultracode";
|
|
39
|
+
/** Display name, matching the CLI's and the extension's label. */
|
|
33
40
|
export const ULTRACODE_OPTION_NAME = "Ultracode";
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
*
|
|
37
|
-
|
|
41
|
+
const ULTRACODE_DESCRIPTION = "Run dynamic workflows on every task";
|
|
42
|
+
/** Select-fallback values for clients without boolean config options. The
|
|
43
|
+
* same spelling Fast mode uses, so one client-side mapping serves both. */
|
|
44
|
+
export const ULTRACODE_ON = "on";
|
|
45
|
+
export const ULTRACODE_OFF = "off";
|
|
46
|
+
/** The effort level the model must support for Ultracode to be available.
|
|
47
|
+
* Availability only: Ultracode never SETS this level. */
|
|
38
48
|
export const ULTRACODE_EFFORT_LEVEL = "xhigh";
|
|
49
|
+
/** The value the old effort-select notch carried. Accepted for one release
|
|
50
|
+
* from clients that still send it (see {@link isLegacyUltracodeEffort}). */
|
|
51
|
+
export const LEGACY_ULTRACODE_EFFORT_VALUE = "ultracode";
|
|
39
52
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
53
|
+
* The fallback availability check, used until (or instead of) the CLI's own
|
|
54
|
+
* `applied.ultracodeAvailable`:
|
|
42
55
|
*
|
|
43
|
-
* 1. workflows are not disabled — Ultracode *is*
|
|
44
|
-
*
|
|
45
|
-
* happen;
|
|
46
|
-
* 2. the current model supports `xhigh` — Ultracode has no meaning on a model
|
|
47
|
-
* that cannot reach the level it implies.
|
|
56
|
+
* 1. workflows are not disabled — Ultracode *is* workflow orchestration;
|
|
57
|
+
* 2. the current model supports `xhigh`.
|
|
48
58
|
*
|
|
49
|
-
*
|
|
50
|
-
* `
|
|
51
|
-
* same direction the extension's
|
|
59
|
+
* Partial by nature: the CLI also checks managed settings, org policy,
|
|
60
|
+
* `enableWorkflows` and `CLAUDE_CODE_DISABLE_WORKFLOWS`. An absent
|
|
61
|
+
* `disableWorkflows` opens the gate, the same direction the extension's
|
|
62
|
+
* `=== !0` comparison takes.
|
|
52
63
|
*/
|
|
53
64
|
export function isUltracodeAvailable(supportedEffortLevels, settings) {
|
|
54
65
|
if (settings?.disableWorkflows === true)
|
|
55
66
|
return false;
|
|
56
67
|
return supportedEffortLevels.includes(ULTRACODE_EFFORT_LEVEL);
|
|
57
68
|
}
|
|
58
|
-
/**
|
|
59
|
-
|
|
60
|
-
|
|
69
|
+
/** Build the option: a native boolean for clients that opted in, an on/off
|
|
70
|
+
* select otherwise (the ACP boolean-config-option RFD makes that a MUST). */
|
|
71
|
+
export function createUltracodeConfigOption(requested, useBooleanOption) {
|
|
72
|
+
const base = {
|
|
73
|
+
id: ULTRACODE_CONFIG_ID,
|
|
74
|
+
name: ULTRACODE_OPTION_NAME,
|
|
75
|
+
description: ULTRACODE_DESCRIPTION,
|
|
76
|
+
category: "model_config",
|
|
77
|
+
};
|
|
78
|
+
if (useBooleanOption) {
|
|
79
|
+
return { ...base, type: "boolean", currentValue: requested };
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
...base,
|
|
83
|
+
type: "select",
|
|
84
|
+
currentValue: requested ? ULTRACODE_ON : ULTRACODE_OFF,
|
|
85
|
+
options: [
|
|
86
|
+
{ value: ULTRACODE_ON, name: "On" },
|
|
87
|
+
{ value: ULTRACODE_OFF, name: "Off" },
|
|
88
|
+
],
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/** The option for a resolved state, or `undefined` while unavailable. */
|
|
92
|
+
export function ultracodeConfigOption(state) {
|
|
93
|
+
if (!state?.available)
|
|
94
|
+
return undefined;
|
|
95
|
+
return createUltracodeConfigOption(state.requested, state.useBooleanOption);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Put the option where it belongs in an existing list — right after `effort`
|
|
99
|
+
* (after `model` when the model has no effort option), before `fast` — or
|
|
100
|
+
* remove it when `next` is undefined. Used when a background readback changes
|
|
101
|
+
* availability without a full rebuild.
|
|
102
|
+
*/
|
|
103
|
+
export function placeUltracodeOption(options, next) {
|
|
104
|
+
const rest = options.filter((o) => o.id !== ULTRACODE_CONFIG_ID);
|
|
105
|
+
if (!next)
|
|
106
|
+
return rest;
|
|
107
|
+
let anchor = rest.findIndex((o) => o.id === "effort");
|
|
108
|
+
if (anchor < 0)
|
|
109
|
+
anchor = rest.findIndex((o) => o.id === "model");
|
|
110
|
+
const at = anchor < 0 ? rest.length : anchor + 1;
|
|
111
|
+
return [...rest.slice(0, at), next, ...rest.slice(at)];
|
|
112
|
+
}
|
|
113
|
+
/** Resolve the requested value from `session/set_config_option`: a native
|
|
114
|
+
* boolean, or the on/off select-fallback strings. */
|
|
115
|
+
export function resolveUltracodeRequested(params) {
|
|
116
|
+
const value = params.value;
|
|
117
|
+
if (typeof value === "boolean")
|
|
118
|
+
return value;
|
|
119
|
+
if (value === ULTRACODE_ON)
|
|
120
|
+
return true;
|
|
121
|
+
if (value === ULTRACODE_OFF)
|
|
122
|
+
return false;
|
|
123
|
+
throw new Error(`Invalid value for config option ${ULTRACODE_CONFIG_ID}: ${String(value)}`);
|
|
124
|
+
}
|
|
125
|
+
/** The toggle's payload. Off is an explicit `null`: `undefined` is dropped by
|
|
126
|
+
* JSON transport, and the SDK only clears a flag on `null`. */
|
|
127
|
+
export function ultracodeTogglePayload(requested) {
|
|
128
|
+
return { ultracode: requested ? true : null };
|
|
61
129
|
}
|
|
62
130
|
/**
|
|
63
|
-
* The `apply_flag_settings` payload for an effort
|
|
131
|
+
* The `apply_flag_settings` payload for an effort change — a user pick, the
|
|
132
|
+
* model-switch fallback, the initial effort, or a recreate's replay.
|
|
64
133
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* has to say something about `ultracode`, not just the one that turns it on:
|
|
69
|
-
* without the clear, picking `High` after Ultracode would lower the effort and
|
|
70
|
-
* leave workflow orchestration running, which is a state no picker entry names.
|
|
71
|
-
* The same reasoning applies to `effortLevel` — this function absorbed the older
|
|
72
|
-
* `toSdkEffortLevel` helper for exactly that reason: both keys are decided in
|
|
73
|
-
* one place, so neither can be forgotten on a path the other takes.
|
|
134
|
+
* An `effortLevel` change sent without `ultracode` turns Ultracode off, so the
|
|
135
|
+
* key rides along whenever the intent is on. It is never sent as `null` here:
|
|
136
|
+
* an effort change is not a request to turn Ultracode off.
|
|
74
137
|
*
|
|
75
|
-
* @param value the
|
|
76
|
-
*
|
|
138
|
+
* @param value the effort select's value — `"default"`, an `EffortLevel`, or
|
|
139
|
+
* `undefined` when the model has no effort option.
|
|
77
140
|
*/
|
|
78
|
-
export function
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
141
|
+
export function effortFlagSettings(value, ultracodeRequested) {
|
|
142
|
+
const effortLevel = value === undefined || value === "default" ? null : value;
|
|
143
|
+
return ultracodeRequested ? { effortLevel, ultracode: true } : { effortLevel };
|
|
144
|
+
}
|
|
145
|
+
/** Whether an effort value is the retired Ultracode notch. Clients that saved
|
|
146
|
+
* it get `{effortLevel:'xhigh', ultracode:true}` for one release. */
|
|
147
|
+
export function isLegacyUltracodeEffort(value) {
|
|
148
|
+
return value === LEGACY_ULTRACODE_EFFORT_VALUE;
|
|
86
149
|
}
|
|
87
150
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
151
|
+
* Read `applied.{ultracodeRequested, ultracodeAvailable}` through the SDK's
|
|
152
|
+
* untyped `Query.getSettings()`.
|
|
153
|
+
*
|
|
154
|
+
* Structural, never trusting: an SDK without the method, a rejected request,
|
|
155
|
+
* or a response without `applied` all resolve to `undefined`, and the caller
|
|
156
|
+
* keeps the heuristic. Never rejects.
|
|
90
157
|
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
158
|
+
* **Call it in the background, never inline.** Control requests are
|
|
159
|
+
* serialized and queue ahead of interrupt and close (upstream #1216), and on a
|
|
160
|
+
* fresh session the CLI does not service them until the first turn.
|
|
161
|
+
*/
|
|
162
|
+
export async function readUltracodeState(query, onError) {
|
|
163
|
+
const getSettings = query?.getSettings;
|
|
164
|
+
if (typeof getSettings !== "function")
|
|
165
|
+
return undefined;
|
|
166
|
+
let response;
|
|
167
|
+
try {
|
|
168
|
+
response = await getSettings.call(query);
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
onError?.(error);
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
const applied = response?.applied;
|
|
175
|
+
if (typeof applied !== "object" || applied === null)
|
|
176
|
+
return undefined;
|
|
177
|
+
const { ultracodeRequested, ultracodeAvailable } = applied;
|
|
178
|
+
const readback = {};
|
|
179
|
+
if (typeof ultracodeRequested === "boolean")
|
|
180
|
+
readback.requested = ultracodeRequested;
|
|
181
|
+
if (typeof ultracodeAvailable === "boolean")
|
|
182
|
+
readback.available = ultracodeAvailable;
|
|
183
|
+
return readback.requested === undefined && readback.available === undefined
|
|
184
|
+
? undefined
|
|
185
|
+
: readback;
|
|
186
|
+
}
|
|
187
|
+
/** Rebuild the option in place from the session's state. */
|
|
188
|
+
export function refreshUltracodeOption(session, useBooleanOption) {
|
|
189
|
+
session.configOptions = placeUltracodeOption(session.configOptions, ultracodeConfigOption({
|
|
190
|
+
available: session.ultracodeAvailable,
|
|
191
|
+
requested: session.ultracodeRequested,
|
|
192
|
+
useBooleanOption,
|
|
193
|
+
}));
|
|
194
|
+
}
|
|
195
|
+
/** Toggle the intent. Applies first, then records — a rejected control
|
|
196
|
+
* request leaves the session and its option untouched, as Fast mode does. */
|
|
197
|
+
export async function applyUltracodeToggle(session, requested, useBooleanOption) {
|
|
198
|
+
await session.query.applyFlagSettings(ultracodeTogglePayload(requested));
|
|
199
|
+
session.ultracodeRequested = requested;
|
|
200
|
+
refreshUltracodeOption(session, useBooleanOption);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* The one-release migration for clients that still send the retired notch:
|
|
204
|
+
* `effort = "ultracode"` becomes `{effortLevel:'xhigh', ultracode:true}`.
|
|
205
|
+
* Returns `false`, sending nothing, when this model's effort select does not
|
|
206
|
+
* offer `xhigh` — the caller then rejects the value like any other.
|
|
98
207
|
*/
|
|
99
|
-
export function
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
208
|
+
export async function applyLegacyUltracodeEffort(session, useBooleanOption) {
|
|
209
|
+
const effort = session.configOptions.find((o) => o.id === "effort");
|
|
210
|
+
const offersXhigh = effort?.type === "select" &&
|
|
211
|
+
effort.options.some((o) => "value" in o && o.value === ULTRACODE_EFFORT_LEVEL);
|
|
212
|
+
if (!offersXhigh)
|
|
213
|
+
return false;
|
|
214
|
+
await session.query.applyFlagSettings(effortFlagSettings(ULTRACODE_EFFORT_LEVEL, true));
|
|
215
|
+
session.ultracodeRequested = true;
|
|
216
|
+
session.configOptions = session.configOptions.map((o) => o.id === "effort" && o.type === "select" ? { ...o, currentValue: ULTRACODE_EFFORT_LEVEL } : o);
|
|
217
|
+
refreshUltracodeOption(session, useBooleanOption);
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Fold a CLI readback into the session. Availability is always taken; the
|
|
222
|
+
* intent only when `seedIntent` (session start — a model switch keeps the
|
|
223
|
+
* intent it has). Returns whether the option the client sees changed, i.e.
|
|
224
|
+
* whether a `config_option_update` is owed.
|
|
225
|
+
*/
|
|
226
|
+
export function applyUltracodeReadback(session, readback, seedIntent, useBooleanOption) {
|
|
227
|
+
const before = JSON.stringify(session.configOptions.find((o) => o.id === ULTRACODE_CONFIG_ID));
|
|
228
|
+
if (readback.available !== undefined)
|
|
229
|
+
session.ultracodeAvailable = readback.available;
|
|
230
|
+
if (seedIntent && readback.requested !== undefined) {
|
|
231
|
+
session.ultracodeRequested = readback.requested;
|
|
232
|
+
}
|
|
233
|
+
refreshUltracodeOption(session, useBooleanOption);
|
|
234
|
+
const after = JSON.stringify(session.configOptions.find((o) => o.id === ULTRACODE_CONFIG_ID));
|
|
235
|
+
return before !== after;
|
|
103
236
|
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.28.0",
|
|
7
7
|
"description": "Claude Code in Zed and other ACP clients with the VS Code extension's UX — multi-select questions, refusal consent, live quota windows, background tasks, Ultracode effort and session notices. Fork of claude-agent-acp.",
|
|
8
8
|
"main": "dist/lib.js",
|
|
9
9
|
"types": "dist/lib.d.ts",
|