agl 40.5.1 → 41.0.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/changelog.md +43 -0
- package/dist_serve/bundle.js +3514 -3357
- package/dist_serve/bundle.js.map +2 -2
- package/dist_serve/bundle.js.third-party-notices.json +58 -32
- package/dist_serve/bundle.js.third-party-notices.txt +108 -33
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/aglapi/aglapisurface.document.js +64 -37
- package/dist_ts/classes.aglhome.d.ts +5 -0
- package/dist_ts/classes.aglhome.js +2 -1
- package/dist_ts/classes.authstore.js +5 -1
- package/dist_ts/classes.controller.d.ts +8 -0
- package/dist_ts/classes.controller.js +119 -22
- package/dist_ts/classes.controllereventdelivery.d.ts +72 -0
- package/dist_ts/classes.controllereventdelivery.js +233 -0
- package/dist_ts/classes.flexmodels.public.js +4 -1
- package/dist_ts/classes.flexprojectionreader.d.ts +6 -0
- package/dist_ts/classes.flexprojectionreader.js +29 -5
- package/dist_ts/classes.flexservice.d.ts +2 -1
- package/dist_ts/classes.flexservice.js +34 -6
- package/dist_ts/classes.flexstore.d.ts +41 -4
- package/dist_ts/classes.flexstore.js +266 -203
- package/dist_ts/classes.inferencegateway.d.ts +35 -1
- package/dist_ts/classes.inferencegateway.js +86 -26
- package/dist_ts/classes.inferenceservice.d.ts +4 -2
- package/dist_ts/classes.inferenceservice.js +5 -4
- package/dist_ts/classes.proxycontrol.d.ts +58 -4
- package/dist_ts/classes.proxycontrol.js +23 -44
- package/dist_ts/classes.proxycontrolclient.d.ts +15 -5
- package/dist_ts/classes.proxycontrolclient.js +67 -17
- package/dist_ts/classes.proxydaemon.d.ts +22 -3
- package/dist_ts/classes.proxydaemon.js +73 -12
- package/dist_ts/classes.proxyleaseholder.d.ts +43 -14
- package/dist_ts/classes.proxyleaseholder.js +66 -22
- package/dist_ts/classes.proxystore.d.ts +9 -0
- package/dist_ts/classes.proxystore.js +15 -7
- package/dist_ts/classes.ticketnotifier.js +4 -2
- package/dist_ts/classes.ticketstore.d.ts +50 -2
- package/dist_ts/classes.ticketstore.js +195 -78
- package/dist_ts/classes.workercallerbindings.d.ts +66 -0
- package/dist_ts/classes.workercallerbindings.js +211 -0
- package/dist_ts/classes.workercallers.d.ts +63 -2
- package/dist_ts/classes.workercallers.js +430 -65
- package/dist_ts/driver/classes.drivereventrelay.d.ts +13 -1
- package/dist_ts/driver/classes.drivereventrelay.js +99 -6
- package/dist_ts/driver/functions.driverinstructions.d.ts +1 -1
- package/dist_ts/driver/functions.driverinstructions.js +1 -1
- package/dist_ts/driver/functions.drivertools.d.ts +11 -2
- package/dist_ts/driver/functions.drivertools.js +19 -9
- package/dist_ts/fleet/classes.boardpump.d.ts +8 -2
- package/dist_ts/fleet/classes.boardpump.js +38 -20
- package/dist_ts/fleet/classes.ticketeffects.d.ts +17 -2
- package/dist_ts/fleet/classes.ticketeffects.js +16 -10
- package/dist_ts/fleet/classes.workerlaunches.d.ts +12 -5
- package/dist_ts/fleet/classes.workerlaunches.js +25 -19
- package/dist_ts/fleet/classes.workers.d.ts +21 -0
- package/dist_ts/fleet/classes.workers.js +110 -17
- package/dist_ts/fleet/functions.workervalidation.js +2 -2
- package/dist_ts/functions.flexprivatesnapshot.d.ts +102 -0
- package/dist_ts/functions.flexprivatesnapshot.js +461 -0
- package/dist_ts/functions.inferencecli.d.ts +3 -2
- package/dist_ts/functions.inferencecli.js +67 -5
- package/dist_ts/functions.inferencecliarguments.d.ts +6 -2
- package/dist_ts/functions.inferencecliarguments.js +29 -2
- package/dist_ts/functions.inferencelaunch.d.ts +24 -0
- package/dist_ts/functions.inferencelaunch.js +42 -2
- package/dist_ts/functions.mcptickettools.d.ts +3 -0
- package/dist_ts/functions.mcptickettools.js +2 -2
- package/dist_ts/functions.proxycontract.d.ts +11 -0
- package/dist_ts/functions.proxycontract.js +12 -1
- package/dist_ts/functions.proxysocket.d.ts +6 -0
- package/dist_ts/functions.proxysocket.js +46 -0
- package/dist_ts/functions.ticketcli.d.ts +1 -1
- package/dist_ts/functions.ticketcli.js +8 -4
- package/dist_ts/functions.ticketvalidation.d.ts +3 -0
- package/dist_ts/functions.ticketvalidation.js +7 -4
- package/dist_ts/functions.workerprocessproof.d.ts +6 -0
- package/dist_ts/functions.workerprocessproof.js +28 -4
- package/dist_ts/interfaces.flexipc.d.ts +21 -2
- package/dist_ts/interfaces.flexipc.js +33 -16
- package/dist_ts_interfaces/fleetworkers.d.ts +6 -0
- package/dist_ts_interfaces/interfaces.d.ts +1 -1
- package/dist_ts_interfaces/interfaces.js +1 -1
- package/dist_ts_interfaces/requests.tickets.d.ts +8 -12
- package/dist_ts_interfaces/tickets.d.ts +37 -9
- package/dist_ts_interfaces/tickets.js +7 -1
- package/dist_ts_interfaces/workercallers.d.ts +43 -4
- package/package.json +7 -7
- package/readme.md +156 -23
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/aglapi/aglapisurface.document.ts +63 -36
- package/ts/classes.aglhome.ts +6 -0
- package/ts/classes.authstore.ts +4 -0
- package/ts/classes.controller.ts +141 -32
- package/ts/classes.controllereventdelivery.ts +289 -0
- package/ts/classes.flexmodels.public.ts +10 -0
- package/ts/classes.flexprojectionreader.ts +30 -3
- package/ts/classes.flexservice.ts +33 -5
- package/ts/classes.flexstore.ts +381 -246
- package/ts/classes.inferencegateway.ts +104 -23
- package/ts/classes.inferenceservice.ts +6 -3
- package/ts/classes.proxycontrol.ts +76 -39
- package/ts/classes.proxycontrolclient.ts +72 -20
- package/ts/classes.proxydaemon.ts +85 -15
- package/ts/classes.proxyleaseholder.ts +84 -28
- package/ts/classes.proxystore.ts +16 -5
- package/ts/classes.ticketnotifier.ts +3 -1
- package/ts/classes.ticketstore.ts +201 -75
- package/ts/classes.workercallerbindings.ts +147 -0
- package/ts/classes.workercallers.ts +410 -59
- package/ts/driver/classes.drivereventrelay.ts +89 -4
- package/ts/driver/functions.driverinstructions.ts +1 -1
- package/ts/driver/functions.drivertools.ts +22 -8
- package/ts/fleet/classes.boardpump.ts +51 -19
- package/ts/fleet/classes.ticketeffects.ts +25 -11
- package/ts/fleet/classes.workerlaunches.ts +23 -15
- package/ts/fleet/classes.workers.ts +79 -17
- package/ts/fleet/functions.workervalidation.ts +1 -1
- package/ts/functions.flexprivatesnapshot.ts +601 -0
- package/ts/functions.inferencecli.ts +61 -7
- package/ts/functions.inferencecliarguments.ts +32 -1
- package/ts/functions.inferencelaunch.ts +49 -2
- package/ts/functions.mcptickettools.ts +1 -1
- package/ts/functions.proxycontract.ts +12 -0
- package/ts/functions.proxysocket.ts +39 -0
- package/ts/functions.ticketcli.ts +7 -3
- package/ts/functions.ticketvalidation.ts +7 -3
- package/ts/functions.workerprocessproof.ts +27 -4
- package/ts/interfaces.flexipc.ts +50 -21
- package/ts_interfaces/fleetworkers.ts +6 -0
- package/ts_interfaces/interfaces.ts +1 -1
- package/ts_interfaces/requests.tickets.ts +9 -6
- package/ts_interfaces/tickets.ts +32 -1
- package/ts_interfaces/workercallers.ts +32 -4
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements.harnesscontrollerapp.ts +19 -8
- package/ts_web/elements.ticketboard.ts +16 -4
- package/ts_web/settings.general.ts +10 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type * as plugins from './plugins.js';
|
|
2
2
|
import type {
|
|
3
|
-
ITicket,
|
|
4
|
-
ITicketFilters, ITicketMove, ITicketQuestion, TTicketLink, TTicketOperation, TTicketReferenceContent, TTicketRequest,
|
|
3
|
+
ITicket, ITicketAnswer, ITicketAsk, ITicketBoard, ITicketChanges, ITicketComment, ITicketCreate,
|
|
4
|
+
ITicketDetail, ITicketFilters, ITicketGet, ITicketMove, ITicketQuestion, TTicketLink, TTicketOperation, TTicketReferenceContent, TTicketRequest,
|
|
5
5
|
TTicketResponse,
|
|
6
6
|
} from './tickets.js';
|
|
7
7
|
|
|
@@ -61,15 +61,18 @@ export interface IReq_ControllerMcpTicketSearch extends plugins.typedrequestInte
|
|
|
61
61
|
response: { tickets: ITicket[] };
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
|
-
* Reads a ticket by its `AGL-<n>` key
|
|
65
|
-
*
|
|
64
|
+
* Reads a ticket by its `AGL-<n>` key with its source, links, all its questions and their answers,
|
|
65
|
+
* and the newest page of its history (up to `limit` entries, default 50, at most 500, within 256 KiB), oldest first: the
|
|
66
|
+
* activity entries and the Markdown comments they name, a `commented` entry naming its comment by
|
|
67
|
+
* id. `historyBefore` is present while older history exists; pass it as `before` for the next page.
|
|
68
|
+
* `commentId` reads that one comment instead (`comments: [it]`, `activity: []`), without `before` or `limit`.
|
|
66
69
|
*/
|
|
67
70
|
export interface IReq_ControllerMcpTicketGet extends plugins.typedrequestInterfaces.implementsTR<
|
|
68
71
|
TControllerMcpTicketRequest<'get'>, IReq_ControllerMcpTicketGet
|
|
69
72
|
> {
|
|
70
73
|
method: 'agl.mcp.ticket.get';
|
|
71
|
-
request:
|
|
72
|
-
response:
|
|
74
|
+
request: ITicketGet & { ownerToken?: string };
|
|
75
|
+
response: ITicketDetail;
|
|
73
76
|
}
|
|
74
77
|
/** Reads a ticket's comments. */
|
|
75
78
|
export interface IReq_ControllerMcpTicketComments extends plugins.typedrequestInterfaces.implementsTR<
|
package/ts_interfaces/tickets.ts
CHANGED
|
@@ -200,6 +200,36 @@ export interface ITicketCreate {
|
|
|
200
200
|
attachments?: ITicketAttachment[];
|
|
201
201
|
}
|
|
202
202
|
export interface ITicketMove { ticketId: string; columnId: TTicketColumn; beforeTicketId?: string; }
|
|
203
|
+
/**
|
|
204
|
+
* How many history entries one `get` returns unless it names `limit`, the most it may name, and the bytes a page holds
|
|
205
|
+
* at most (its entries plus the comments they name, serialized; a page holds at least one entry). The budget wins over `limit`.
|
|
206
|
+
*/
|
|
207
|
+
export const ticketHistoryPage = { default: 50, maximum: 500, bytes: 256 * 1024 } as const;
|
|
208
|
+
/** A ticket and one page of its history: the newest entries, or those older than the entry `before` names, within `ticketHistoryPage`. */
|
|
209
|
+
export interface ITicketGet {
|
|
210
|
+
ticketId: string;
|
|
211
|
+
/** An activity id, as `historyBefore` returned it: the page holds only older entries. */
|
|
212
|
+
before?: string;
|
|
213
|
+
/** Entries on the page, 1 to 500 (`ticketHistoryPage.maximum`); 50 (`ticketHistoryPage.default`) when absent. */
|
|
214
|
+
limit?: number;
|
|
215
|
+
/**
|
|
216
|
+
* One comment of this ticket, by the id an activity entry or a fleet event names: the response holds the ticket, its
|
|
217
|
+
* questions and that comment alone (`comments: [it]`, `activity: []`, no `historyBefore`). Excludes `before` and `limit`.
|
|
218
|
+
*/
|
|
219
|
+
commentId?: string;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* A ticket, all its questions and one page of its history, oldest first. `activity` is the page; `comments` are the
|
|
223
|
+
* comments its `commented` entries name, whose `changes.comment` holds only `{ after: { id } }` here (the stored
|
|
224
|
+
* entry keeps the whole comment). `historyBefore` is present while older entries exist: pass it as `before`.
|
|
225
|
+
*/
|
|
226
|
+
export interface ITicketDetail {
|
|
227
|
+
ticket: ITicket;
|
|
228
|
+
comments: ITicketComment[];
|
|
229
|
+
activity: ITicketActivity[];
|
|
230
|
+
questions: ITicketQuestion[];
|
|
231
|
+
historyBefore?: string;
|
|
232
|
+
}
|
|
203
233
|
export interface ITicketBoard {
|
|
204
234
|
revision: number;
|
|
205
235
|
columns: { id: TTicketColumn; title: string; done?: boolean }[];
|
|
@@ -211,7 +241,7 @@ export interface ITicketOperations {
|
|
|
211
241
|
list: { request: ITicketFilters; response: { tickets: ITicket[] } };
|
|
212
242
|
board: { request: ITicketFilters; response: ITicketBoard };
|
|
213
243
|
search: { request: { query: string; label?: string }; response: { tickets: ITicket[] } };
|
|
214
|
-
get: { request:
|
|
244
|
+
get: { request: ITicketGet; response: ITicketDetail };
|
|
215
245
|
comments: { request: { ticketId: string }; response: { comments: ITicketComment[] } };
|
|
216
246
|
create: { request: ITicketCreate; response: { ticket: ITicket } };
|
|
217
247
|
update: { request: { ticketId: string; expectedRevision: number; changes: ITicketChanges }; response: { ticket: ITicket } };
|
|
@@ -259,6 +289,7 @@ export const ticketErrorMessages = {
|
|
|
259
289
|
ticket_ask_forbidden: 'Workers may ask questions only on tickets assigned to their verified session.',
|
|
260
290
|
ticket_answer_forbidden: 'Only the owner or the driver may answer ticket questions.',
|
|
261
291
|
ticket_question_not_found: 'The requested question does not exist on this ticket.',
|
|
292
|
+
ticket_comment_not_found: 'The requested comment does not exist on this ticket.',
|
|
262
293
|
ticket_question_answered: 'The question already has a different answer; a second answer is refused. Ask a new question instead.',
|
|
263
294
|
ticket_answer_invalid: 'An answer chooses existing option ids (one unless multiSelect) and/or gives free text where the question allows it.',
|
|
264
295
|
} as const;
|
|
@@ -6,6 +6,8 @@ export const workerCallerLaunchGenerationEnvironmentVariable = 'AGL_MCP_LAUNCH_G
|
|
|
6
6
|
export interface IFleetWorkerCallerLaunchBase {
|
|
7
7
|
launchId: string;
|
|
8
8
|
projectId: string;
|
|
9
|
+
/** The fleet worker the launch identifies, `${projectId}:${name}`: a worker holds one current launch. */
|
|
10
|
+
workerId: string;
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
/**
|
|
@@ -27,11 +29,15 @@ export interface IFleetClaudeProcess {
|
|
|
27
29
|
startTicks: string;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
export type TFleetWorkerCallerBinding = IFleetWorkerCallerLaunchBase & {
|
|
32
|
+
export type TFleetWorkerCallerBinding = Omit<IFleetWorkerCallerLaunchBase, 'workerId'> & {
|
|
31
33
|
nativeSessionId: string;
|
|
32
34
|
expectedBindingRevision: number;
|
|
33
35
|
} & (
|
|
34
|
-
|
|
36
|
+
/**
|
|
37
|
+
* A Claude launch binds to its background job and to the job's current process; a job whose process already exited
|
|
38
|
+
* binds without one, and the next process of the same job proves itself when its bridge enrolls.
|
|
39
|
+
*/
|
|
40
|
+
| { harnessId: 'claude'; claudeJobId: string; claudeProcess?: IFleetClaudeProcess }
|
|
35
41
|
| { harnessId: 'codex' }
|
|
36
42
|
);
|
|
37
43
|
|
|
@@ -53,12 +59,34 @@ export interface IFleetWorkerCallerHooks {
|
|
|
53
59
|
ticketSessionId: string;
|
|
54
60
|
}>;
|
|
55
61
|
getWorkerCallerStatus(launchId: string): IWorkerCallerReadiness;
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Revokes one launch, or the current launch of a worker, also one the controller kept from before a restart. Every
|
|
64
|
+
* reason but `generation_change` revokes it for good: its kept binding is deleted with it.
|
|
65
|
+
*/
|
|
66
|
+
revokeWorkerCaller(request: ({ launchId: string } | { workerId: string }) & {
|
|
58
67
|
reason: 'failure' | 'stop' | 'replacement' | 'generation_change' | 'cancelled';
|
|
59
68
|
}): Promise<void>;
|
|
60
69
|
}
|
|
61
70
|
|
|
71
|
+
/** The background job a Claude worker's launch is bound to, as the controller asks the fleet about it. */
|
|
72
|
+
export interface IWorkerClaudeJobRequest {
|
|
73
|
+
workerId: string;
|
|
74
|
+
projectId: string;
|
|
75
|
+
nativeSessionId: string;
|
|
76
|
+
jobId: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* What a fresh Claude inventory shows of that job: `running` in one process, `settled` without a process, `ended` for
|
|
81
|
+
* this worker (the worker is gone or archived, continues in another session, or the session continues as another job),
|
|
82
|
+
* or `unproven` when the registry or the inventory could not be read or did not list the session once.
|
|
83
|
+
*/
|
|
84
|
+
export type TWorkerClaudeJobObservation =
|
|
85
|
+
| { state: 'running'; process: IFleetClaudeProcess }
|
|
86
|
+
| { state: 'settled' }
|
|
87
|
+
| { state: 'ended'; reason: string }
|
|
88
|
+
| { state: 'unproven'; reason: string };
|
|
89
|
+
|
|
62
90
|
export interface IWorkerCallerSubject {
|
|
63
91
|
kind: 'worker_launch';
|
|
64
92
|
launchId: string;
|
|
@@ -941,10 +941,13 @@ const modelHarnessId = (choiceArg: interfaces.TControllerModelChoice): TBrowserS
|
|
|
941
941
|
/** How long after asking for a restart this page expects its connection to drop; still connected, AGL did not restart. */
|
|
942
942
|
const restartCheckMs = 20_000;
|
|
943
943
|
|
|
944
|
+
/** A model as a harness's own row names it, without the harness: "openai/gpt-5.6-sol". */
|
|
945
|
+
const modelChoiceName = (choiceArg: interfaces.TControllerModelChoice): string => `${choiceArg.providerID}/${choiceArg.modelID}`;
|
|
946
|
+
|
|
944
947
|
const modelOptionLabel = (choiceArg: interfaces.TControllerModelChoice): string => {
|
|
945
948
|
return [
|
|
946
949
|
sessionHarnessLabel(modelHarnessId(choiceArg)),
|
|
947
|
-
|
|
950
|
+
modelChoiceName(choiceArg),
|
|
948
951
|
].join(' · ');
|
|
949
952
|
};
|
|
950
953
|
|
|
@@ -18816,16 +18819,23 @@ ${entry.detail.stack}`}</pre>`}
|
|
|
18816
18819
|
|
|
18817
18820
|
/** General as the controller's confirmed settings and this browser's own choices have it. */
|
|
18818
18821
|
private generalSettingsView(): IGeneralSettingsView {
|
|
18822
|
+
// Each row belongs to one harness, so it names a model without the harness.
|
|
18823
|
+
const modelName = (modelStringArg: string): string => {
|
|
18824
|
+
const choice = this.modelChoicesByString.get(modelStringArg);
|
|
18825
|
+
return choice ? modelChoiceName(choice) : modelStringArg;
|
|
18826
|
+
};
|
|
18819
18827
|
return {
|
|
18820
18828
|
defaults: (['opencode', 'flex', 'codex', 'claude'] as const).map((harnessIdArg) => {
|
|
18821
18829
|
const name = sessionHarnessLabel(harnessIdArg);
|
|
18822
18830
|
const model = this.defaultModelStrings[harnessIdArg];
|
|
18823
18831
|
const unavailable = this.unavailableDefaultModels[harnessIdArg];
|
|
18824
18832
|
// Flex has no default of its own: without one AGL can name, its composer asks for a model.
|
|
18825
|
-
const
|
|
18826
|
-
|
|
18833
|
+
const composerDefault = this.composerDefaultModelStrings[harnessIdArg];
|
|
18834
|
+
const runningDefault = composerDefault
|
|
18835
|
+
? modelName(composerDefault)
|
|
18836
|
+
: harnessIdArg === 'flex' ? '' : `${name}'s own default`;
|
|
18827
18837
|
const note = unavailable
|
|
18828
|
-
? `The saved default ${
|
|
18838
|
+
? `The saved default ${modelChoiceName(unavailable)} is no longer offered. ${runningDefault
|
|
18829
18839
|
? `New conversations run on ${runningDefault}.`
|
|
18830
18840
|
: 'New Flex conversations need an account and model chosen in the composer.'}`
|
|
18831
18841
|
: harnessIdArg === 'flex' && !model ? 'Without a default, Flex\'s composer asks for an account and a model.' : '';
|
|
@@ -18834,7 +18844,7 @@ ${entry.detail.stack}`}</pre>`}
|
|
|
18834
18844
|
name,
|
|
18835
18845
|
models: [
|
|
18836
18846
|
{ key: '', label: harnessIdArg === 'flex' ? 'Ask in the composer' : `${name}'s own default` },
|
|
18837
|
-
...this.modelOptionsForHarness(harnessIdArg).map((optionArg) => ({ key: optionArg, label: optionArg })),
|
|
18847
|
+
...this.modelOptionsForHarness(harnessIdArg).map((optionArg) => ({ key: optionArg, label: modelName(optionArg) })),
|
|
18838
18848
|
],
|
|
18839
18849
|
model,
|
|
18840
18850
|
efforts: this.settingsEffortDropdownOptions(model)
|
|
@@ -18854,9 +18864,10 @@ ${entry.detail.stack}`}</pre>`}
|
|
|
18854
18864
|
gpu: this.browserGpu,
|
|
18855
18865
|
activeGpu: this.activeBrowserGpu,
|
|
18856
18866
|
presentation: this.browserPresentation,
|
|
18857
|
-
|
|
18858
|
-
|
|
18859
|
-
|
|
18867
|
+
// Said only while Paint cannot be used: an available Paint needs no sentence.
|
|
18868
|
+
paintState: !this.activeBrowserPaint
|
|
18869
|
+
? 'No browser runtime is running.'
|
|
18870
|
+
: this.activeBrowserPaint.state === 'available' ? '' : describeBrowserPaintAvailability(this.activeBrowserPaint),
|
|
18860
18871
|
paintRearm: this.activeBrowserPaint?.state === 'unavailable'
|
|
18861
18872
|
&& this.activeBrowserPaint.reason !== 'descriptor-missing'
|
|
18862
18873
|
&& this.activeBrowserPaint.reason !== 'unsupported-platform'
|
|
@@ -250,6 +250,20 @@ export class AglTicketBoard extends plugins.deesElement.DeesElement {
|
|
|
250
250
|
?? { id: personArg.id, name: personArg.name };
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
+
/** A ticket's whole history: `get` returns it a page at a time, newest first, so this reads back to the first entry. */
|
|
254
|
+
private async history(ticketIdArg: string, signalArg?: AbortSignal): Promise<Omit<interfaces.ITicketDetail, 'historyBefore'>> {
|
|
255
|
+
const pages: interfaces.ITicketDetail[] = [];
|
|
256
|
+
let before: string | undefined;
|
|
257
|
+
do {
|
|
258
|
+
const page = await this.fire('get', { ticketId: ticketIdArg, limit: interfaces.ticketHistoryPage.maximum,
|
|
259
|
+
...(before === undefined ? {} : { before }) }, signalArg);
|
|
260
|
+
pages.unshift(page);
|
|
261
|
+
before = page.historyBefore;
|
|
262
|
+
} while (before !== undefined);
|
|
263
|
+
const { ticket, questions } = pages.at(-1)!;
|
|
264
|
+
return { ticket, questions, comments: pages.flatMap((pageArg) => pageArg.comments), activity: pages.flatMap((pageArg) => pageArg.activity) };
|
|
265
|
+
}
|
|
266
|
+
|
|
253
267
|
/** Tickets as the kanban shows them, remembering whom they name. */
|
|
254
268
|
private shown(ticketsArg: interfaces.ITicket[]): IKanbanTicket[] {
|
|
255
269
|
for (const ticket of ticketsArg) {
|
|
@@ -274,12 +288,10 @@ export class AglTicketBoard extends plugins.deesElement.DeesElement {
|
|
|
274
288
|
searchTickets: async (queryArg, signalArg) => this.shown((await this.fire('search', { query: queryArg }, signalArg)).tickets),
|
|
275
289
|
// The discussion is the comments and the questions; the kanban orders them by when they were written.
|
|
276
290
|
loadComments: async (ticketIdArg, signalArg) => {
|
|
277
|
-
const { comments, questions } = await this.
|
|
291
|
+
const { comments, questions } = await this.history(ticketIdArg, signalArg);
|
|
278
292
|
return [...comments.map(kanbanComment), ...questions.map(kanbanQuestion)];
|
|
279
293
|
},
|
|
280
|
-
loadActivity: async (ticketIdArg, signalArg) => (
|
|
281
|
-
(await this.fire('get', { ticketId: ticketIdArg }, signalArg)).activity.map(kanbanActivity)
|
|
282
|
-
),
|
|
294
|
+
loadActivity: async (ticketIdArg, signalArg) => (await this.history(ticketIdArg, signalArg)).activity.map(kanbanActivity),
|
|
283
295
|
addComment: async (inputArg) => this.change(async () => (
|
|
284
296
|
kanbanComment((await this.fire('comment', { ticketId: inputArg.ticketId, body: inputArg.body })).comment)
|
|
285
297
|
)),
|
|
@@ -36,7 +36,7 @@ export interface IGeneralSettingsView {
|
|
|
36
36
|
gpu: 'enabled' | 'disabled';
|
|
37
37
|
activeGpu: 'enabled' | 'disabled';
|
|
38
38
|
presentation: interfaces.TControllerBrowserPresentation;
|
|
39
|
-
/**
|
|
39
|
+
/** Why Paint cannot be used now, or that no browser runtime runs; empty while Paint is available. */
|
|
40
40
|
paintState: string;
|
|
41
41
|
/** Paint's integrity retries stopped and can be started again. */
|
|
42
42
|
paintRearm: boolean;
|
|
@@ -90,10 +90,15 @@ export const renderGeneralSettings = (
|
|
|
90
90
|
leading: html`<mp-harness-mark .harness=${rowArg.harnessId}></mp-harness-mark>`,
|
|
91
91
|
label: rowArg.name,
|
|
92
92
|
...(rowArg.note ? { description: rowArg.note } : {}),
|
|
93
|
-
|
|
93
|
+
// One folded button per row (model · effort), as wide as it says and at most a share of a narrow screen;
|
|
94
|
+
// it opens the model and the effort in a speech bubble. A saved default no longer offered gives it the
|
|
95
|
+
// warning tone.
|
|
96
|
+
control: html`<mp-model-picker class="settingsDefault" data-harness=${rowArg.harnessId} fold="always"
|
|
97
|
+
style="max-width: min(360px, 45vw);" .label=${`Default model for ${rowArg.name}`}
|
|
98
|
+
.warning=${rowArg.noteIsWarning ? rowArg.note : ''}
|
|
94
99
|
.models=${rowArg.models} .model=${rowArg.model} .efforts=${rowArg.efforts} .effort=${rowArg.effort}
|
|
95
100
|
.effortDisabledReason=${rowArg.effortDisabledReason} .modelPlaceholder=${'Choose a model'}
|
|
96
|
-
.modelLabel=${
|
|
101
|
+
.modelLabel=${'Model'} .effortLabel=${'Reasoning effort'}
|
|
97
102
|
@mp-model-change=${(eventArg: CustomEvent<TMpModelChoice>) => actionsArg.setDefault(rowArg.harnessId, eventArg.detail)}
|
|
98
103
|
></mp-model-picker>`,
|
|
99
104
|
})),
|
|
@@ -161,7 +166,8 @@ export const renderGeneralSettings = (
|
|
|
161
166
|
{
|
|
162
167
|
key: 'presentation',
|
|
163
168
|
label: 'New browser views show',
|
|
164
|
-
description: `Paint draws the page as vector scenes in this tab; Video streams it. Each view can switch on its own
|
|
169
|
+
description: `Paint draws the page as vector scenes in this tab; Video streams it. Each view can switch on its own.${
|
|
170
|
+
viewArg.paintState ? ` ${viewArg.paintState}` : ''}`,
|
|
165
171
|
control: html`
|
|
166
172
|
${viewArg.paintRearm
|
|
167
173
|
? html`<dees-button class="settingsBrowserPaintRearm" size="sm" text="Retry Paint" @clicked=${() => actionsArg.rearmPaint()}></dees-button>`
|