@hydraharness/harness-client-ui-agent-preset 0.1.1-rc.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +73 -0
- package/lib/client.js +1693 -0
- package/lib/index.js +11 -0
- package/lib/invariant.js +23 -0
- package/lib/types/client/AgentPresetLabel.d.ts +30 -0
- package/lib/types/client/AgentPresetRow.d.ts +35 -0
- package/lib/types/client/AgentPresetSeat.d.ts +38 -0
- package/lib/types/client/AgentPresetSection.d.ts +61 -0
- package/lib/types/client/PresetMenu.d.ts +42 -0
- package/lib/types/client/index.d.ts +29 -0
- package/lib/types/client/locales.d.ts +31 -0
- package/lib/types/client/seat-store.d.ts +105 -0
- package/lib/types/client/section-store.d.ts +191 -0
- package/lib/types/client/settings-store.d.ts +165 -0
- package/lib/types/index.d.ts +9 -0
- package/lib/types/invariant.d.ts +16 -0
- package/package.json +84 -0
package/lib/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region lib/types/index.js
|
|
2
|
+
/**
|
|
3
|
+
* Agent-preset surface plugin, node half. The empty apply exists so the plugin
|
|
4
|
+
* appears in the host cordis.yml / Loader; the browser half ships the
|
|
5
|
+
* General-settings row through exports["./client"], discovered from the
|
|
6
|
+
* package.json hydra.client declaration.
|
|
7
|
+
*/
|
|
8
|
+
/** Host plugin body — no host-side behavior for this surface plugin. */
|
|
9
|
+
function apply() {}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { apply };
|
package/lib/invariant.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region lib/types/invariant.js
|
|
2
|
+
/**
|
|
3
|
+
* Package-owned invariant companion for `@hydraharness/harness-client-ui-agent-preset`.
|
|
4
|
+
* @module @hydraharness/harness-client-ui-agent-preset/invariant
|
|
5
|
+
*/
|
|
6
|
+
const PACKAGE_NAME = "@hydraharness/harness-client-ui-agent-preset";
|
|
7
|
+
/** Cordis companion plugin name. */
|
|
8
|
+
const name = "client-ui-agent-preset-invariant";
|
|
9
|
+
/** Service required before the companion can reserve package ownership. */
|
|
10
|
+
const inject = ["invariants"];
|
|
11
|
+
/**
|
|
12
|
+
* No runtime invariant: this is a browser-side surface plugin whose node half owns no event stream
|
|
13
|
+
* or mutable runtime data; the roster and the settings write are host contracts covered there.
|
|
14
|
+
*/
|
|
15
|
+
const install = () => {};
|
|
16
|
+
/**
|
|
17
|
+
* Register this package's invariant companion.
|
|
18
|
+
* @param ctx - Cordis context carrying the invariant service.
|
|
19
|
+
* @returns the installed registration's disposer after setup succeeds.
|
|
20
|
+
*/
|
|
21
|
+
const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
22
|
+
//#endregion
|
|
23
|
+
export { apply, inject, name };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The session header's agent-preset label.
|
|
3
|
+
*
|
|
4
|
+
* Read-only by construction: a session's composition is fixed once its
|
|
5
|
+
* conversation starts, and a header is only worth reading after that. Offering
|
|
6
|
+
* a control here would promise a switch the host refuses; naming what the
|
|
7
|
+
* session runs is the honest affordance, and the choice itself lives on the
|
|
8
|
+
* new-session screen ({@link AgentPresetSeat}).
|
|
9
|
+
*/
|
|
10
|
+
import type { SnapshotStore } from '@hydraharness/harness-client-runtime/client';
|
|
11
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@hydraharness/harness-client-ui-slots';
|
|
12
|
+
import type { AgentPresetSettingsState } from './settings-store.ts';
|
|
13
|
+
/** Registration-side business face for the header label. */
|
|
14
|
+
export interface AgentPresetLabelInjected {
|
|
15
|
+
hooks: {
|
|
16
|
+
/** Roster snapshot bound by the renderer as useAgentPresets. */
|
|
17
|
+
agentPresets: SnapshotStore<AgentPresetSettingsState>;
|
|
18
|
+
};
|
|
19
|
+
/** Read the roster, so the label can show a name rather than an id. */
|
|
20
|
+
load: () => Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
/** Full component props. */
|
|
23
|
+
export type AgentPresetLabelProps = PropsRuntime<'conversation.session.header.actions'> & PropsLocale<'settings.agentPreset'> & InjectFace<AgentPresetLabelInjected>;
|
|
24
|
+
/**
|
|
25
|
+
* Render this session's agent-preset name beside its title.
|
|
26
|
+
* @param props - composed slot props.
|
|
27
|
+
* @returns the label, or null when the session records no preset.
|
|
28
|
+
*/
|
|
29
|
+
export declare function AgentPresetLabel({ sessionId, useSessions, useAgentPresets, load, t, }: AgentPresetLabelProps): import("react").JSX.Element | null;
|
|
30
|
+
//# sourceMappingURL=AgentPresetLabel.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-preset preference row: the preset new sessions are composed from.
|
|
3
|
+
* A running session keeps the composition it began with, so this row never
|
|
4
|
+
* disturbs work in progress.
|
|
5
|
+
*/
|
|
6
|
+
import type { SnapshotStore } from '@hydraharness/harness-client-runtime/client';
|
|
7
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@hydraharness/harness-client-ui-slots';
|
|
8
|
+
import type { AgentPresetSettingsState } from './settings-store.ts';
|
|
9
|
+
import { type AgentPresetSettingsKey } from './locales.ts';
|
|
10
|
+
/** Registration-side business face for the host-backed preference. */
|
|
11
|
+
export interface AgentPresetRowInjected {
|
|
12
|
+
hooks: {
|
|
13
|
+
/** Agent-preset settings snapshot bound by the renderer as useAgentPreset. */
|
|
14
|
+
agentPreset: SnapshotStore<AgentPresetSettingsState>;
|
|
15
|
+
};
|
|
16
|
+
/** Load the roster when the row first renders. */
|
|
17
|
+
load: () => Promise<void>;
|
|
18
|
+
/** Persist one preset as the default for later sessions. */
|
|
19
|
+
select: (id: string) => Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
/** Full component props. */
|
|
22
|
+
export type AgentPresetRowProps = PropsRuntime<'settings.general.item'> & PropsLocale<'settings.agentPreset'> & InjectFace<AgentPresetRowInjected>;
|
|
23
|
+
/**
|
|
24
|
+
* Render the new-session agent-preset selector.
|
|
25
|
+
* @param props - composed slot props.
|
|
26
|
+
* @returns the row, or null when the deployment composes no presets.
|
|
27
|
+
*/
|
|
28
|
+
export declare function AgentPresetRow({ load, select, useAgentPreset, t }: AgentPresetRowProps): import("react").JSX.Element | null;
|
|
29
|
+
declare module '@hydraharness/harness-client-ui-slots' {
|
|
30
|
+
interface LocaleNamespaceMap {
|
|
31
|
+
/** Agent-preset row copy. */
|
|
32
|
+
'settings.agentPreset': AgentPresetSettingsKey;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=AgentPresetRow.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The agent-preset chip on the new-session screen, beside the workspace
|
|
3
|
+
* picker.
|
|
4
|
+
*
|
|
5
|
+
* It lives here rather than in the composer because the choice is only
|
|
6
|
+
* available before a conversation starts: once a turn has run, the session's
|
|
7
|
+
* history was produced under that preset's tools and the host refuses to swap
|
|
8
|
+
* them. A control that spends most of its life disabled belongs on the screen
|
|
9
|
+
* where it still works.
|
|
10
|
+
*
|
|
11
|
+
* The menu opens on the staged choice, which starts as the deployment default.
|
|
12
|
+
* Picking stages; the choice reaches a session when one becomes current.
|
|
13
|
+
*/
|
|
14
|
+
import type { SnapshotStore } from '@hydraharness/harness-client-runtime/client';
|
|
15
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@hydraharness/harness-client-ui-slots';
|
|
16
|
+
import type { AgentPresetSeatState } from './seat-store.ts';
|
|
17
|
+
/** Registration-side business face for the hero chip. */
|
|
18
|
+
export interface AgentPresetSeatInjected {
|
|
19
|
+
hooks: {
|
|
20
|
+
/** Seat snapshot bound by the renderer as useAgentPresetSeat. */
|
|
21
|
+
agentPresetSeat: SnapshotStore<AgentPresetSeatState>;
|
|
22
|
+
};
|
|
23
|
+
/** Read the roster when the chip first renders. */
|
|
24
|
+
load: () => Promise<void>;
|
|
25
|
+
/** Stage one preset for the next session. */
|
|
26
|
+
select: (id: string) => Promise<void>;
|
|
27
|
+
/** Clear the one-shot introduce cue once the chip has played it. */
|
|
28
|
+
introduced: () => void;
|
|
29
|
+
}
|
|
30
|
+
/** Full component props. */
|
|
31
|
+
export type AgentPresetSeatProps = PropsRuntime<'conversation.hero.agentPreset'> & PropsLocale<'settings.agentPreset'> & InjectFace<AgentPresetSeatInjected>;
|
|
32
|
+
/**
|
|
33
|
+
* Render the new-session agent-preset chip.
|
|
34
|
+
* @param props - composed slot props.
|
|
35
|
+
* @returns the chip, or null when the deployment composes no presets.
|
|
36
|
+
*/
|
|
37
|
+
export declare function AgentPresetSeat({ load, select, introduced, useAgentPresetSeat, t }: AgentPresetSeatProps): import("react").JSX.Element | null;
|
|
38
|
+
//# sourceMappingURL=AgentPresetSeat.d.ts.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-presets settings section: the roster as cards, a copy dialog as the
|
|
3
|
+
* only way a preset is created, and a read-only viewer over the shipped
|
|
4
|
+
* compositions.
|
|
5
|
+
*
|
|
6
|
+
* The browser edits no composition text — a shipped preset opens read-only to
|
|
7
|
+
* be READ (it is the known-good composition a copy starts from), and a custom
|
|
8
|
+
* preset is edited in its own files, which is what the location action leads
|
|
9
|
+
* to. Deleting a preset leaves running sessions alone: a composition is
|
|
10
|
+
* mounted once at session creation and nothing re-reads the file.
|
|
11
|
+
*/
|
|
12
|
+
import type { ReactNode } from 'react';
|
|
13
|
+
import type { SnapshotStore } from '@hydraharness/harness-client-runtime/client';
|
|
14
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@hydraharness/harness-client-ui-slots';
|
|
15
|
+
import { type AgentPresetSectionState } from './section-store.ts';
|
|
16
|
+
/** Registration-side business face for the management section. */
|
|
17
|
+
export interface AgentPresetSectionInjected {
|
|
18
|
+
hooks: {
|
|
19
|
+
/** Page snapshot bound by the renderer as useAgentPresetSection. */
|
|
20
|
+
agentPresetSection: SnapshotStore<AgentPresetSectionState>;
|
|
21
|
+
};
|
|
22
|
+
/** Read the roster; called once when the section first renders. */
|
|
23
|
+
load: () => Promise<void>;
|
|
24
|
+
/** Open one shipped preset's composition in the read-only viewer. */
|
|
25
|
+
view: (id: string) => Promise<void>;
|
|
26
|
+
/** Close the read-only viewer. */
|
|
27
|
+
closeView: () => void;
|
|
28
|
+
/** Open the copy dialog over one preset. */
|
|
29
|
+
beginCopy: (from: string) => void;
|
|
30
|
+
/** Close the copy dialog, discarding the draft. */
|
|
31
|
+
cancelCopy: () => void;
|
|
32
|
+
/** Name the preset the copy creates. */
|
|
33
|
+
setCopyId: (id: string) => void;
|
|
34
|
+
/** Name the copy's display name. */
|
|
35
|
+
setCopyName: (name: string) => void;
|
|
36
|
+
/** Submit the copy. */
|
|
37
|
+
confirmCopy: () => Promise<void>;
|
|
38
|
+
/** Open one preset's directory, or reveal its path where there is no desktop. */
|
|
39
|
+
openLocation: (id: string) => Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Stage the self-referential preset and start a new session on it — the
|
|
42
|
+
* guided way to author a preset, beside copying. Absent when the surface
|
|
43
|
+
* is composed without the conversation flow to land the session in.
|
|
44
|
+
*/
|
|
45
|
+
startCreatorDraft?: () => void;
|
|
46
|
+
/** Ask for delete confirmation, or dismiss it with null. */
|
|
47
|
+
confirmDelete: (id: string | null) => void;
|
|
48
|
+
/** Delete the preset awaiting confirmation. */
|
|
49
|
+
remove: () => Promise<void>;
|
|
50
|
+
/** Make one preset the default for sessions created later. */
|
|
51
|
+
makeDefault: (id: string) => Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
/** Full component props. */
|
|
54
|
+
export type AgentPresetSectionProps = PropsRuntime<'settings.section'> & PropsLocale<'settings.agentPreset'> & InjectFace<AgentPresetSectionInjected>;
|
|
55
|
+
/**
|
|
56
|
+
* Render the Agent presets section content column.
|
|
57
|
+
* @param props - composed slot props.
|
|
58
|
+
* @returns the section, or null when the deployment composes no presets.
|
|
59
|
+
*/
|
|
60
|
+
export declare function AgentPresetSection(props: AgentPresetSectionProps): ReactNode;
|
|
61
|
+
//# sourceMappingURL=AgentPresetSection.d.ts.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The preset picker both surfaces render: a menu of presets over a button
|
|
3
|
+
* naming the current one.
|
|
4
|
+
*
|
|
5
|
+
* The settings row and the composer seat differ in where they sit, what they
|
|
6
|
+
* call the current value, and when they refuse a pick — not in how the picker
|
|
7
|
+
* itself behaves. Trust is the one thing the list always says: a locally
|
|
8
|
+
* authored preset is exactly as privileged as the plugins it names, so the
|
|
9
|
+
* label marks it rather than presenting every preset as shipped and vetted.
|
|
10
|
+
*/
|
|
11
|
+
import type { AgentPresetOption } from './settings-store.ts';
|
|
12
|
+
import { type AgentPresetSettingsKey } from './locales.ts';
|
|
13
|
+
/** What one surface passes to the shared picker. */
|
|
14
|
+
export interface PresetMenuProps {
|
|
15
|
+
/** Presets to offer, in roster order. */
|
|
16
|
+
options: readonly AgentPresetOption[];
|
|
17
|
+
/** The preset the button names and the menu marks selected. */
|
|
18
|
+
selectedId: string;
|
|
19
|
+
/** Text on the button; the surfaces word a pending roster differently. */
|
|
20
|
+
label: string;
|
|
21
|
+
/** Active Web locale lookup. */
|
|
22
|
+
t: (key: AgentPresetSettingsKey) => string;
|
|
23
|
+
/** Class for the trigger button, owned by the calling surface. */
|
|
24
|
+
buttonClassName: string | undefined;
|
|
25
|
+
/** Class for the chevron, owned by the calling surface. */
|
|
26
|
+
chevronClassName: string | undefined;
|
|
27
|
+
/** Whether the trigger refuses interaction. */
|
|
28
|
+
disabled: boolean;
|
|
29
|
+
/** Whether the menu is open — the surface owns this so it can force it shut. */
|
|
30
|
+
open: boolean;
|
|
31
|
+
/** Report the menu's next open state. */
|
|
32
|
+
onOpenChange: (open: boolean) => void;
|
|
33
|
+
/** Called with the picked preset once the menu has closed. */
|
|
34
|
+
onSelect: (id: string) => void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Render the preset picker.
|
|
38
|
+
* @param props - the calling surface's copy, styling, and handlers.
|
|
39
|
+
* @returns the menu and its trigger.
|
|
40
|
+
*/
|
|
41
|
+
export declare function PresetMenu({ options, selectedId, label, t, buttonClassName, chevronClassName, disabled, open, onOpenChange, onSelect, }: PresetMenuProps): import("react").JSX.Element;
|
|
42
|
+
//# sourceMappingURL=PresetMenu.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-preset surface plugin, browser half — four surfaces over one roster:
|
|
3
|
+
* a General-settings row for the default preset, a chip on the new-session
|
|
4
|
+
* screen for the session about to start, a read-only label in the session
|
|
5
|
+
* header, and a settings section that manages the roster (copy, delete,
|
|
6
|
+
* default, and the way into a preset's own files).
|
|
7
|
+
*
|
|
8
|
+
* A running session keeps the composition it began with (the host refuses to
|
|
9
|
+
* adopt an existing session under a different preset). That is what splits
|
|
10
|
+
* the choice from the display: the General row and the hero chip are both
|
|
11
|
+
* before-the-fact, while the header only reports what a session already runs.
|
|
12
|
+
*/
|
|
13
|
+
import type { ClientContext } from '@hydraharness/harness-client-runtime/client';
|
|
14
|
+
export type { AgentPresetLabelInjected, AgentPresetLabelProps } from './AgentPresetLabel.tsx';
|
|
15
|
+
export type { AgentPresetRowInjected, AgentPresetRowProps } from './AgentPresetRow.tsx';
|
|
16
|
+
export type { AgentPresetSeatInjected, AgentPresetSeatProps } from './AgentPresetSeat.tsx';
|
|
17
|
+
export type { AgentPresetSectionInjected, AgentPresetSectionProps } from './AgentPresetSection.tsx';
|
|
18
|
+
export type { AgentPresetSeatState, SeatSessionSummary } from './seat-store.ts';
|
|
19
|
+
export { draftBlocker, type AgentPresetSectionState, type CopyDraft, type PresetRow, type PresetView, } from './section-store.ts';
|
|
20
|
+
export type { AgentPresetOption, AgentPresetSettingsState } from './settings-store.ts';
|
|
21
|
+
export { AGENT_PRESET_SETTINGS_NS, writeDefaultPreset } from './settings-store.ts';
|
|
22
|
+
/** Required services (cordis fiber inject). */
|
|
23
|
+
export declare const inject: string[];
|
|
24
|
+
/**
|
|
25
|
+
* Mount the General-settings row.
|
|
26
|
+
* @param ctx - the browser plugin context.
|
|
27
|
+
*/
|
|
28
|
+
export declare function apply(ctx: ClientContext): void;
|
|
29
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Locale bundles for the agent-preset settings row, hero chip, header label, and management section. */
|
|
2
|
+
/** Locale keys these surfaces render. */
|
|
3
|
+
export type AgentPresetSettingsKey = 'title' | 'description' | 'loading' | 'error' | 'userTrust' | 'seatHint' | 'headerHint' | 'nav' | 'sectionIntro' | 'builtIn' | 'setDefault' | 'view' | 'presetStandardName' | 'presetStandardDescription' | 'presetCodeName' | 'presetCodeDescription' | 'presetMinimalName' | 'presetMinimalDescription' | 'presetCordisName' | 'presetCordisDescription' | 'duplicate' | 'duplicateUnavailable' | 'delete' | 'presetId' | 'presetIdPlaceholder' | 'copyOf' | 'displayName' | 'displayNamePlaceholder' | 'inUse' | 'noDescription' | 'builtInGroup' | 'customGroup' | 'brokenBadge' | 'brokenNoCopy' | 'composition' | 'cancel' | 'close' | 'retry' | 'copyTitle' | 'copyIntro' | 'create' | 'creating' | 'creatorDraft' | 'openLocation' | 'showLocation' | 'revealedPathLabel' | 'idRequired' | 'idInvalid' | 'idTaken' | 'deleteTitle' | 'deleteDescription' | 'deleteConfirm' | 'deleting';
|
|
4
|
+
/** English copy. */
|
|
5
|
+
export declare const en: Record<AgentPresetSettingsKey, string>;
|
|
6
|
+
/** Preset roster fields needed to resolve Web display copy. */
|
|
7
|
+
export interface PresetDisplaySource {
|
|
8
|
+
/** Stable preset id. */
|
|
9
|
+
readonly id: string;
|
|
10
|
+
/** Whether the deployment ships the preset or the user owns it. */
|
|
11
|
+
readonly trust: 'system' | 'user';
|
|
12
|
+
/** Unlocalized name published by the preset. */
|
|
13
|
+
readonly name?: string;
|
|
14
|
+
/** Unlocalized description published by the preset. */
|
|
15
|
+
readonly description?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Display copy resolved for the active Web locale. */
|
|
18
|
+
export interface PresetDisplayText {
|
|
19
|
+
/** Localized built-in name or the preset's own fallback name. */
|
|
20
|
+
readonly name: string;
|
|
21
|
+
/** Localized built-in description or the preset's own description. */
|
|
22
|
+
readonly description?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Resolve preset display copy without making user-authored metadata translatable.
|
|
26
|
+
* @param preset - roster row whose copy is being rendered.
|
|
27
|
+
* @param t - active Web locale lookup.
|
|
28
|
+
* @returns localized copy for a known shipped preset, otherwise file metadata.
|
|
29
|
+
*/
|
|
30
|
+
export declare function presetDisplayText(preset: PresetDisplaySource, t: (key: AgentPresetSettingsKey) => string): PresetDisplayText;
|
|
31
|
+
//# sourceMappingURL=locales.d.ts.map
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hero-chip controller: which preset the NEXT session gets.
|
|
3
|
+
*
|
|
4
|
+
* The new-session screen has no session, so a pick is staged rather than
|
|
5
|
+
* applied. It reaches a session when one becomes current and is still blank —
|
|
6
|
+
* whether the workspace connect created it or reused an existing blank one,
|
|
7
|
+
* which is why staging cannot simply ride along on `sessions.create`.
|
|
8
|
+
*
|
|
9
|
+
* The stage is forgotten once applied: the next new session starts from the
|
|
10
|
+
* deployment default again, matching the workspace picker beside it.
|
|
11
|
+
*/
|
|
12
|
+
import type { IApiClient } from '@hydraharness/harness-api-remotes/client';
|
|
13
|
+
import { type SessionId, type SnapshotStore } from '@hydraharness/harness-client-runtime/client';
|
|
14
|
+
import type { AgentPresetOption } from './settings-store.ts';
|
|
15
|
+
/** Hero-chip snapshot. */
|
|
16
|
+
export interface AgentPresetSeatState {
|
|
17
|
+
/** Presets the deployment supplies; empty means the chip renders nothing. */
|
|
18
|
+
options: readonly AgentPresetOption[];
|
|
19
|
+
/** The staged choice, empty until the roster loads. */
|
|
20
|
+
current: string;
|
|
21
|
+
/** A rejected apply's message, cleared by the next attempt. */
|
|
22
|
+
error: string | null;
|
|
23
|
+
busy: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* One-shot cue that the chip should introduce itself (the creator-draft
|
|
26
|
+
* entry staged the pick from another screen, so the user never touched the
|
|
27
|
+
* chip); the renderer clears it via `introduced()` once played.
|
|
28
|
+
*/
|
|
29
|
+
introduce: boolean;
|
|
30
|
+
}
|
|
31
|
+
/** One session's identity and whether it has started. */
|
|
32
|
+
export interface SeatSessionSummary {
|
|
33
|
+
/** The session the chip would apply its staged choice to. */
|
|
34
|
+
id: SessionId;
|
|
35
|
+
/** False once a turn has run — applying is refused from then on. */
|
|
36
|
+
blank: boolean;
|
|
37
|
+
/** The preset the session already runs, when the summary reports one. */
|
|
38
|
+
agentPreset?: string;
|
|
39
|
+
}
|
|
40
|
+
/** Stages the next session's preset and applies it when one appears. */
|
|
41
|
+
export declare class AgentPresetSeatController {
|
|
42
|
+
private readonly api;
|
|
43
|
+
/** The session the hero is about to hand over to, when there is one. */
|
|
44
|
+
private readonly currentSession;
|
|
45
|
+
/**
|
|
46
|
+
* Publish an applied switch into the session list, so the header label
|
|
47
|
+
* moves with the composition instead of waiting for the next full list
|
|
48
|
+
* refresh. Optional: a harness that renders no list omits it.
|
|
49
|
+
*/
|
|
50
|
+
private readonly onApplied?;
|
|
51
|
+
/** Chip snapshot the renderer subscribes to. */
|
|
52
|
+
readonly store: SnapshotStore<AgentPresetSeatState>;
|
|
53
|
+
/**
|
|
54
|
+
* The deployment default, so a consumed stage can fall back to it without
|
|
55
|
+
* re-reading the roster.
|
|
56
|
+
*/
|
|
57
|
+
private fallback;
|
|
58
|
+
/** Set while a pick is waiting for a session; cleared once applied. */
|
|
59
|
+
private staged;
|
|
60
|
+
constructor(api: Pick<IApiClient, 'agentPresets'>,
|
|
61
|
+
/** The session the hero is about to hand over to, when there is one. */
|
|
62
|
+
currentSession: () => SeatSessionSummary | undefined,
|
|
63
|
+
/**
|
|
64
|
+
* Publish an applied switch into the session list, so the header label
|
|
65
|
+
* moves with the composition instead of waiting for the next full list
|
|
66
|
+
* refresh. Optional: a harness that renders no list omits it.
|
|
67
|
+
*/
|
|
68
|
+
onApplied?: ((sessionId: string, agentPreset: string) => void) | undefined);
|
|
69
|
+
private set;
|
|
70
|
+
/**
|
|
71
|
+
* Read the roster and open the chip on the deployment default.
|
|
72
|
+
* @returns once the snapshot reflects the host.
|
|
73
|
+
*/
|
|
74
|
+
load(): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Stage one preset for the next session, applying it immediately when a
|
|
77
|
+
* blank session is already current.
|
|
78
|
+
* @param id - the preset to stage.
|
|
79
|
+
* @returns once the stage settled, and the apply too when one happened.
|
|
80
|
+
*/
|
|
81
|
+
select(id: string): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Stage a pick WITHOUT the immediate apply, for a flow that starts the
|
|
84
|
+
* receiving session after the pick (the settings section's creator entry).
|
|
85
|
+
* `select()`'s immediate apply would meet the still-current running session
|
|
86
|
+
* and drop the stage as unservable; staging alone leaves it for the
|
|
87
|
+
* list-change applier, which fires when the started session becomes
|
|
88
|
+
* current.
|
|
89
|
+
* @param id - the preset to stage.
|
|
90
|
+
* @param introduce - true when the stage came from another screen and the
|
|
91
|
+
* chip should announce itself on the session it lands on.
|
|
92
|
+
*/
|
|
93
|
+
stage(id: string, introduce?: boolean): void;
|
|
94
|
+
/** Acknowledge the introduction cue once the chip has played it. */
|
|
95
|
+
introduced(): void;
|
|
96
|
+
/**
|
|
97
|
+
* Hand the staged choice to the current session, if there is one to take it.
|
|
98
|
+
*
|
|
99
|
+
* Called both by `select()` and by whoever observes the current session
|
|
100
|
+
* changing, because the session may appear either before or after the pick.
|
|
101
|
+
* @returns once the switch settled, or immediately when there is nothing to do.
|
|
102
|
+
*/
|
|
103
|
+
apply(): Promise<void>;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=seat-store.d.ts.map
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-preset management controller: the roster as a list, a copy dialog as
|
|
3
|
+
* the only way a preset is created, and a read-only viewer over the shipped
|
|
4
|
+
* compositions.
|
|
5
|
+
*
|
|
6
|
+
* The browser edits no composition text. A new preset is a host-side copy of
|
|
7
|
+
* an existing one (`{ from, id, name? }` is all that crosses the wire), and
|
|
8
|
+
* everything after creation happens in the preset's own files — which is why
|
|
9
|
+
* the page's other job is getting the user TO those files: open the directory
|
|
10
|
+
* where the host has a desktop, show its path where it does not.
|
|
11
|
+
*
|
|
12
|
+
* The host stays the single fact source. Every mutation writes through the
|
|
13
|
+
* wire and the page re-reads the roster afterwards, because a copy changes
|
|
14
|
+
* more than the row it targeted.
|
|
15
|
+
*/
|
|
16
|
+
import type { IApiClient } from '@hydraharness/harness-api-remotes/client';
|
|
17
|
+
import { type SnapshotStore } from '@hydraharness/harness-client-runtime/client';
|
|
18
|
+
/** One preset row the page renders. */
|
|
19
|
+
export interface PresetRow {
|
|
20
|
+
/** Preset id and directory name; the display name falls back to it. */
|
|
21
|
+
id: string;
|
|
22
|
+
/** Display name the preset published, absent when it published none. */
|
|
23
|
+
name?: string;
|
|
24
|
+
/** One sentence on what the preset is for. */
|
|
25
|
+
description?: string;
|
|
26
|
+
/** Whether the preset ships with the deployment or was authored locally. */
|
|
27
|
+
trust: 'system' | 'user';
|
|
28
|
+
/** Whether a session that names no preset gets this one. */
|
|
29
|
+
isDefault: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Why the preset cannot compose a session, absent when it can. A broken
|
|
32
|
+
* row renders marked and unselectable — its directory still occupies the
|
|
33
|
+
* id, so deleting it (or fixing the files) is the way out, and this page
|
|
34
|
+
* is where both of those live.
|
|
35
|
+
*/
|
|
36
|
+
broken?: string;
|
|
37
|
+
}
|
|
38
|
+
/** The copy dialog: a new id and optional display name over a fixed source. */
|
|
39
|
+
export interface CopyDraft {
|
|
40
|
+
/** The preset being copied. */
|
|
41
|
+
from: string;
|
|
42
|
+
/** Display name of the source, for the dialog title. */
|
|
43
|
+
fromTitle: string;
|
|
44
|
+
/** New preset id being typed; the directory name, so it is required. */
|
|
45
|
+
id: string;
|
|
46
|
+
/** Display name being typed; empty falls back to the id. */
|
|
47
|
+
name: string;
|
|
48
|
+
/** Whether the copy is in flight. */
|
|
49
|
+
saving: boolean;
|
|
50
|
+
/** The last copy failure, cleared by the next edit. */
|
|
51
|
+
error: string | null;
|
|
52
|
+
}
|
|
53
|
+
/** The read-only composition viewer over one shipped preset. */
|
|
54
|
+
export interface PresetView {
|
|
55
|
+
/** The preset whose composition is shown. */
|
|
56
|
+
id: string;
|
|
57
|
+
/** Display name, for the dialog title. */
|
|
58
|
+
title: string;
|
|
59
|
+
/** Composition text exactly as stored. */
|
|
60
|
+
content: string;
|
|
61
|
+
}
|
|
62
|
+
/** Page snapshot. */
|
|
63
|
+
export interface AgentPresetSectionState {
|
|
64
|
+
status: 'idle' | 'loading' | 'ready' | 'unavailable' | 'error';
|
|
65
|
+
/** Whole-load failure text; a copy failure stays on the dialog. */
|
|
66
|
+
error: string | null;
|
|
67
|
+
/** Whether the deployment configures a root new presets can be written to. */
|
|
68
|
+
authorable: boolean;
|
|
69
|
+
/** Whether the host can open a preset directory on a native desktop. */
|
|
70
|
+
hasDocument: boolean;
|
|
71
|
+
/** Every preset the deployment currently supplies. */
|
|
72
|
+
rows: readonly PresetRow[];
|
|
73
|
+
/** The open copy dialog, or null. */
|
|
74
|
+
copy: CopyDraft | null;
|
|
75
|
+
/** The open read-only viewer, or null. */
|
|
76
|
+
view: PresetView | null;
|
|
77
|
+
/** The preset awaiting delete confirmation. */
|
|
78
|
+
pendingDelete: string | null;
|
|
79
|
+
/** Whether a delete is in flight. */
|
|
80
|
+
deleting: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Preset directories shown as text because the host has no desktop opener
|
|
83
|
+
* — the answer `openDocument` gives instead of opening.
|
|
84
|
+
*/
|
|
85
|
+
revealedPaths: Readonly<Record<string, string>>;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Why this copy cannot be submitted yet, as a locale key, or undefined when
|
|
89
|
+
* it can. Client-side only: the host re-checks the id and its answer is what
|
|
90
|
+
* the dialog reports on failure.
|
|
91
|
+
* @param draft - the open copy dialog.
|
|
92
|
+
* @param rows - the roster, for the collision check.
|
|
93
|
+
* @returns the blocking reason's locale key, or undefined when submittable.
|
|
94
|
+
*/
|
|
95
|
+
export declare function draftBlocker(draft: CopyDraft, rows: readonly PresetRow[]): 'idRequired' | 'idInvalid' | 'idTaken' | undefined;
|
|
96
|
+
/** Reads the roster and drives the copy dialog, viewer, and location reveals. */
|
|
97
|
+
export declare class AgentPresetSectionController {
|
|
98
|
+
private readonly api;
|
|
99
|
+
/**
|
|
100
|
+
* Called after this page changes the roster DIRECTORY, so the other
|
|
101
|
+
* surfaces reading the same roster re-read it. A settings field moving is
|
|
102
|
+
* already announced by the host through the forwarded
|
|
103
|
+
* `settings/document-updated`; a directory copied or deleted here is not,
|
|
104
|
+
* and the new-session chip has no other way to learn a preset it should
|
|
105
|
+
* offer now exists.
|
|
106
|
+
*/
|
|
107
|
+
private readonly rosterChanged;
|
|
108
|
+
/** Page snapshot the renderer subscribes to. */
|
|
109
|
+
readonly store: SnapshotStore<AgentPresetSectionState>;
|
|
110
|
+
private readonly refresh;
|
|
111
|
+
constructor(api: Pick<IApiClient, 'agentPresets' | 'settings'>,
|
|
112
|
+
/**
|
|
113
|
+
* Called after this page changes the roster DIRECTORY, so the other
|
|
114
|
+
* surfaces reading the same roster re-read it. A settings field moving is
|
|
115
|
+
* already announced by the host through the forwarded
|
|
116
|
+
* `settings/document-updated`; a directory copied or deleted here is not,
|
|
117
|
+
* and the new-session chip has no other way to learn a preset it should
|
|
118
|
+
* offer now exists.
|
|
119
|
+
*/
|
|
120
|
+
rosterChanged?: () => void);
|
|
121
|
+
private set;
|
|
122
|
+
private patchCopy;
|
|
123
|
+
/**
|
|
124
|
+
* Load the roster. An empty roster means the deployment composes no
|
|
125
|
+
* presets, which is a valid deployment rather than a failure — the section
|
|
126
|
+
* reports `unavailable` and renders nothing.
|
|
127
|
+
* @returns once the snapshot reflects the host.
|
|
128
|
+
*/
|
|
129
|
+
load(): Promise<void>;
|
|
130
|
+
private acceptRoster;
|
|
131
|
+
/**
|
|
132
|
+
* Open one shipped preset's composition in the read-only viewer.
|
|
133
|
+
* @param id - the preset to view.
|
|
134
|
+
* @returns once the composition loaded or the failure is on the page.
|
|
135
|
+
*/
|
|
136
|
+
view(id: string): Promise<void>;
|
|
137
|
+
/** Close the read-only viewer. */
|
|
138
|
+
closeView(): void;
|
|
139
|
+
/**
|
|
140
|
+
* Open the copy dialog over one preset.
|
|
141
|
+
* @param from - the preset the copy will start from.
|
|
142
|
+
*/
|
|
143
|
+
beginCopy(from: string): void;
|
|
144
|
+
/** Close the copy dialog, discarding whatever was typed. */
|
|
145
|
+
cancelCopy(): void;
|
|
146
|
+
/**
|
|
147
|
+
* Name the preset the copy creates.
|
|
148
|
+
* @param id - the id typed into the dialog.
|
|
149
|
+
*/
|
|
150
|
+
setCopyId(id: string): void;
|
|
151
|
+
/**
|
|
152
|
+
* Name the copy's display name.
|
|
153
|
+
* @param name - the display name typed into the dialog.
|
|
154
|
+
*/
|
|
155
|
+
setCopyName(name: string): void;
|
|
156
|
+
/**
|
|
157
|
+
* Submit the copy, re-read the roster, then take the user to the new
|
|
158
|
+
* preset's files — the directory opens where the host has a desktop, and
|
|
159
|
+
* its path appears on the new row where it does not.
|
|
160
|
+
* @returns once the copy settled and the page reflects it.
|
|
161
|
+
*/
|
|
162
|
+
confirmCopy(): Promise<void>;
|
|
163
|
+
/**
|
|
164
|
+
* Open one preset's directory on the host desktop, or reveal its path on
|
|
165
|
+
* the row where the deployment has no opener to hand it to.
|
|
166
|
+
* @param id - the preset whose files the user wants.
|
|
167
|
+
* @returns once the host answered and the page reflects it.
|
|
168
|
+
*/
|
|
169
|
+
openLocation(id: string): Promise<void>;
|
|
170
|
+
/**
|
|
171
|
+
* Ask for confirmation before deleting one preset.
|
|
172
|
+
* @param id - the preset to delete, or null to dismiss the confirmation.
|
|
173
|
+
*/
|
|
174
|
+
confirmDelete(id: string | null): void;
|
|
175
|
+
/**
|
|
176
|
+
* Delete the preset awaiting confirmation, then re-read the roster.
|
|
177
|
+
*
|
|
178
|
+
* A session already composed from it keeps running: its composition was
|
|
179
|
+
* mounted at creation and nothing re-reads the file.
|
|
180
|
+
* @returns once the delete settled and the page reflects it.
|
|
181
|
+
*/
|
|
182
|
+
remove(): Promise<void>;
|
|
183
|
+
/**
|
|
184
|
+
* Make one preset the default for sessions created later. Running sessions
|
|
185
|
+
* keep the composition they began with, so this never disturbs work.
|
|
186
|
+
* @param id - the preset to make default.
|
|
187
|
+
* @returns once the write settled and the roster was re-read.
|
|
188
|
+
*/
|
|
189
|
+
makeDefault(id: string): Promise<void>;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=section-store.d.ts.map
|