@sagmans/dsh-tui 0.1.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/LICENSE +21 -0
- package/README.md +266 -0
- package/cordis.patch.yml +123 -0
- package/lib/agent/fork.d.ts +24 -0
- package/lib/agent/fork.d.ts.map +1 -0
- package/lib/agent/fork.js +25 -0
- package/lib/agent/fork.js.map +1 -0
- package/lib/agent/history.d.ts +78 -0
- package/lib/agent/history.d.ts.map +1 -0
- package/lib/agent/history.js +179 -0
- package/lib/agent/history.js.map +1 -0
- package/lib/agent/host.d.ts +58 -0
- package/lib/agent/host.d.ts.map +1 -0
- package/lib/agent/host.js +59 -0
- package/lib/agent/host.js.map +1 -0
- package/lib/agent/model.d.ts +61 -0
- package/lib/agent/model.d.ts.map +1 -0
- package/lib/agent/model.js +92 -0
- package/lib/agent/model.js.map +1 -0
- package/lib/agent/present.d.ts +12 -0
- package/lib/agent/present.d.ts.map +1 -0
- package/lib/agent/present.js +52 -0
- package/lib/agent/present.js.map +1 -0
- package/lib/agent/presets.d.ts +75 -0
- package/lib/agent/presets.d.ts.map +1 -0
- package/lib/agent/presets.js +117 -0
- package/lib/agent/presets.js.map +1 -0
- package/lib/agent/projections.d.ts +16 -0
- package/lib/agent/projections.d.ts.map +1 -0
- package/lib/agent/projections.js +31 -0
- package/lib/agent/projections.js.map +1 -0
- package/lib/agent/status.d.ts +46 -0
- package/lib/agent/status.d.ts.map +1 -0
- package/lib/agent/status.js +67 -0
- package/lib/agent/status.js.map +1 -0
- package/lib/cards.d.ts +88 -0
- package/lib/cards.d.ts.map +1 -0
- package/lib/cards.js +218 -0
- package/lib/cards.js.map +1 -0
- package/lib/compat/probe.d.ts +33 -0
- package/lib/compat/probe.d.ts.map +1 -0
- package/lib/compat/probe.js +74 -0
- package/lib/compat/probe.js.map +1 -0
- package/lib/config.d.ts +13 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +49 -0
- package/lib/config.js.map +1 -0
- package/lib/contracts.d.ts +32 -0
- package/lib/contracts.d.ts.map +1 -0
- package/lib/contracts.js +2 -0
- package/lib/contracts.js.map +1 -0
- package/lib/export.d.ts +15 -0
- package/lib/export.d.ts.map +1 -0
- package/lib/export.js +52 -0
- package/lib/export.js.map +1 -0
- package/lib/gates.d.ts +85 -0
- package/lib/gates.d.ts.map +1 -0
- package/lib/gates.js +216 -0
- package/lib/gates.js.map +1 -0
- package/lib/identity.d.ts +33 -0
- package/lib/identity.d.ts.map +1 -0
- package/lib/identity.js +49 -0
- package/lib/identity.js.map +1 -0
- package/lib/index.d.ts +24 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +1196 -0
- package/lib/index.js.map +1 -0
- package/lib/input/completion.d.ts +22 -0
- package/lib/input/completion.d.ts.map +1 -0
- package/lib/input/completion.js +27 -0
- package/lib/input/completion.js.map +1 -0
- package/lib/input/submission.d.ts +62 -0
- package/lib/input/submission.d.ts.map +1 -0
- package/lib/input/submission.js +80 -0
- package/lib/input/submission.js.map +1 -0
- package/lib/jobs.d.ts +64 -0
- package/lib/jobs.d.ts.map +1 -0
- package/lib/jobs.js +123 -0
- package/lib/jobs.js.map +1 -0
- package/lib/startup.d.ts +17 -0
- package/lib/startup.d.ts.map +1 -0
- package/lib/startup.js +67 -0
- package/lib/startup.js.map +1 -0
- package/lib/subagents.d.ts +74 -0
- package/lib/subagents.d.ts.map +1 -0
- package/lib/subagents.js +141 -0
- package/lib/subagents.js.map +1 -0
- package/lib/terminal/bell.d.ts +18 -0
- package/lib/terminal/bell.d.ts.map +1 -0
- package/lib/terminal/bell.js +16 -0
- package/lib/terminal/bell.js.map +1 -0
- package/lib/terminal/clipboard.d.ts +11 -0
- package/lib/terminal/clipboard.d.ts.map +1 -0
- package/lib/terminal/clipboard.js +18 -0
- package/lib/terminal/clipboard.js.map +1 -0
- package/lib/terminal/restore.d.ts +17 -0
- package/lib/terminal/restore.d.ts.map +1 -0
- package/lib/terminal/restore.js +43 -0
- package/lib/terminal/restore.js.map +1 -0
- package/lib/terminal/title.d.ts +22 -0
- package/lib/terminal/title.d.ts.map +1 -0
- package/lib/terminal/title.js +34 -0
- package/lib/terminal/title.js.map +1 -0
- package/lib/text.d.ts +19 -0
- package/lib/text.d.ts.map +1 -0
- package/lib/text.js +61 -0
- package/lib/text.js.map +1 -0
- package/lib/theme.d.ts +47 -0
- package/lib/theme.d.ts.map +1 -0
- package/lib/theme.js +84 -0
- package/lib/theme.js.map +1 -0
- package/lib/transcript.d.ts +91 -0
- package/lib/transcript.d.ts.map +1 -0
- package/lib/transcript.js +315 -0
- package/lib/transcript.js.map +1 -0
- package/lib/ui/dock.d.ts +36 -0
- package/lib/ui/dock.d.ts.map +1 -0
- package/lib/ui/dock.js +110 -0
- package/lib/ui/dock.js.map +1 -0
- package/lib/ui/markdown.d.ts +17 -0
- package/lib/ui/markdown.d.ts.map +1 -0
- package/lib/ui/markdown.js +35 -0
- package/lib/ui/markdown.js.map +1 -0
- package/lib/ui/picker.d.ts +103 -0
- package/lib/ui/picker.d.ts.map +1 -0
- package/lib/ui/picker.js +165 -0
- package/lib/ui/picker.js.map +1 -0
- package/lib/ui/rows.d.ts +30 -0
- package/lib/ui/rows.d.ts.map +1 -0
- package/lib/ui/rows.js +49 -0
- package/lib/ui/rows.js.map +1 -0
- package/lib/ui/status.d.ts +49 -0
- package/lib/ui/status.d.ts.map +1 -0
- package/lib/ui/status.js +90 -0
- package/lib/ui/status.js.map +1 -0
- package/lib/ui/view.d.ts +56 -0
- package/lib/ui/view.d.ts.map +1 -0
- package/lib/ui/view.js +184 -0
- package/lib/ui/view.js.map +1 -0
- package/lib/work.d.ts +39 -0
- package/lib/work.d.ts.map +1 -0
- package/lib/work.js +97 -0
- package/lib/work.js.map +1 -0
- package/package.json +109 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability probe.
|
|
3
|
+
*
|
|
4
|
+
* The surface composes over whatever the profile already mounted, so a missing
|
|
5
|
+
* row shows up as a runtime failure somewhere deep in a turn. Naming the
|
|
6
|
+
* capability and the package that provides it turns that into a message the
|
|
7
|
+
* reader can act on.
|
|
8
|
+
*/
|
|
9
|
+
/** One capability the surface reads, and what to do when it is absent. */
|
|
10
|
+
export interface Capability {
|
|
11
|
+
/** Service name as it appears on the Cordis context. */
|
|
12
|
+
readonly service: string;
|
|
13
|
+
/** What the surface does with it. */
|
|
14
|
+
readonly use: string;
|
|
15
|
+
/** The row a composition must mount to provide it. */
|
|
16
|
+
readonly fix: string;
|
|
17
|
+
}
|
|
18
|
+
/** Without these the surface cannot run at all. */
|
|
19
|
+
export declare const REQUIRED_CAPABILITIES: readonly Capability[];
|
|
20
|
+
/** Without these the surface runs, with something switched off. */
|
|
21
|
+
export declare const OPTIONAL_CAPABILITIES: readonly Capability[];
|
|
22
|
+
/** What a composition provides, and what it does not. */
|
|
23
|
+
export interface ProbeReport {
|
|
24
|
+
readonly missingRequired: readonly Capability[];
|
|
25
|
+
readonly missingOptional: readonly Capability[];
|
|
26
|
+
}
|
|
27
|
+
/** Ask which capabilities a composition provides. */
|
|
28
|
+
export declare function probeComposition(has: (service: string) => boolean): ProbeReport;
|
|
29
|
+
/** The failure that stops activation, naming every missing requirement at once. */
|
|
30
|
+
export declare function describeMissingRequired(report: ProbeReport): string;
|
|
31
|
+
/** One line for the reader when the surface runs with something switched off. */
|
|
32
|
+
export declare function describeMissingOptional(report: ProbeReport): string | undefined;
|
|
33
|
+
//# sourceMappingURL=probe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../src/compat/probe.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,0EAA0E;AAC1E,MAAM,WAAW,UAAU;IACzB,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,qCAAqC;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,sDAAsD;IACtD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED,mDAAmD;AACnD,eAAO,MAAM,qBAAqB,EAAE,SAAS,UAAU,EAgBtD,CAAA;AAED,mEAAmE;AACnE,eAAO,MAAM,qBAAqB,EAAE,SAAS,UAAU,EA0BtD,CAAA;AAED,yDAAyD;AACzD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,eAAe,EAAE,SAAS,UAAU,EAAE,CAAA;IAC/C,QAAQ,CAAC,eAAe,EAAE,SAAS,UAAU,EAAE,CAAA;CAChD;AAED,qDAAqD;AACrD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,GAAG,WAAW,CAK/E;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAInE;AAED,iFAAiF;AACjF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAI/E"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability probe.
|
|
3
|
+
*
|
|
4
|
+
* The surface composes over whatever the profile already mounted, so a missing
|
|
5
|
+
* row shows up as a runtime failure somewhere deep in a turn. Naming the
|
|
6
|
+
* capability and the package that provides it turns that into a message the
|
|
7
|
+
* reader can act on.
|
|
8
|
+
*/
|
|
9
|
+
/** Without these the surface cannot run at all. */
|
|
10
|
+
export const REQUIRED_CAPABILITIES = [
|
|
11
|
+
{
|
|
12
|
+
service: 'agents',
|
|
13
|
+
use: 'creating and resuming the agent this terminal drives',
|
|
14
|
+
fix: 'mount @deepseek-ai/dsh-agent with an agent-loop implementation',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
service: 'agentPresets',
|
|
18
|
+
use: 'choosing the composition an agent runs, which owns its tools and prompt',
|
|
19
|
+
fix: 'mount @deepseek-ai/dsh-agent-presets, which this bundle inserts',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
service: 'appExit',
|
|
23
|
+
use: 'leaving with the exit code the launcher owns',
|
|
24
|
+
fix: 'start this surface with dsh --profile tui',
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
/** Without these the surface runs, with something switched off. */
|
|
28
|
+
export const OPTIONAL_CAPABILITIES = [
|
|
29
|
+
{
|
|
30
|
+
service: 'tools',
|
|
31
|
+
use: 'presenting each tool call through its own render intent',
|
|
32
|
+
fix: 'mount @deepseek-ai/dsh-tools',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
service: 'commands',
|
|
36
|
+
use: 'slash commands and their completion menu',
|
|
37
|
+
fix: 'mount @deepseek-ai/dsh-commands',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
service: 'sessionPersistence',
|
|
41
|
+
use: 'listing and replaying stored sessions',
|
|
42
|
+
fix: 'mount @deepseek-ai/dsh-session-persistence-jsonl',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
service: 'userQuestions',
|
|
46
|
+
use: 'answering the questions the model asks',
|
|
47
|
+
fix: 'mount @deepseek-ai/dsh-user-questions',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
service: 'approval',
|
|
51
|
+
use: 'pausing a gated tool for a decision',
|
|
52
|
+
fix: 'mount @deepseek-ai/dsh-user-approval',
|
|
53
|
+
},
|
|
54
|
+
];
|
|
55
|
+
/** Ask which capabilities a composition provides. */
|
|
56
|
+
export function probeComposition(has) {
|
|
57
|
+
return {
|
|
58
|
+
missingRequired: REQUIRED_CAPABILITIES.filter(capability => !has(capability.service)),
|
|
59
|
+
missingOptional: OPTIONAL_CAPABILITIES.filter(capability => !has(capability.service)),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/** The failure that stops activation, naming every missing requirement at once. */
|
|
63
|
+
export function describeMissingRequired(report) {
|
|
64
|
+
const lines = report.missingRequired.map(capability => ` ${capability.service}: needed for ${capability.use} — ${capability.fix}`);
|
|
65
|
+
return `dsh-tui: this profile is missing what the terminal surface needs\\n${lines.join('\\n')}`;
|
|
66
|
+
}
|
|
67
|
+
/** One line for the reader when the surface runs with something switched off. */
|
|
68
|
+
export function describeMissingOptional(report) {
|
|
69
|
+
if (report.missingOptional.length === 0)
|
|
70
|
+
return undefined;
|
|
71
|
+
const names = report.missingOptional.map(capability => capability.service);
|
|
72
|
+
return `running without ${names.join(', ')}; run /status after adding the rows this profile lacks`;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probe.js","sourceRoot":"","sources":["../../src/compat/probe.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH,mDAAmD;AACnD,MAAM,CAAC,MAAM,qBAAqB,GAA0B;IAC1D;QACE,OAAO,EAAE,QAAQ;QACjB,GAAG,EAAE,sDAAsD;QAC3D,GAAG,EAAE,gEAAgE;KACtE;IACD;QACE,OAAO,EAAE,cAAc;QACvB,GAAG,EAAE,yEAAyE;QAC9E,GAAG,EAAE,iEAAiE;KACvE;IACD;QACE,OAAO,EAAE,SAAS;QAClB,GAAG,EAAE,8CAA8C;QACnD,GAAG,EAAE,2CAA2C;KACjD;CACF,CAAA;AAED,mEAAmE;AACnE,MAAM,CAAC,MAAM,qBAAqB,GAA0B;IAC1D;QACE,OAAO,EAAE,OAAO;QAChB,GAAG,EAAE,yDAAyD;QAC9D,GAAG,EAAE,8BAA8B;KACpC;IACD;QACE,OAAO,EAAE,UAAU;QACnB,GAAG,EAAE,0CAA0C;QAC/C,GAAG,EAAE,iCAAiC;KACvC;IACD;QACE,OAAO,EAAE,oBAAoB;QAC7B,GAAG,EAAE,uCAAuC;QAC5C,GAAG,EAAE,kDAAkD;KACxD;IACD;QACE,OAAO,EAAE,eAAe;QACxB,GAAG,EAAE,wCAAwC;QAC7C,GAAG,EAAE,uCAAuC;KAC7C;IACD;QACE,OAAO,EAAE,UAAU;QACnB,GAAG,EAAE,qCAAqC;QAC1C,GAAG,EAAE,sCAAsC;KAC5C;CACF,CAAA;AAQD,qDAAqD;AACrD,MAAM,UAAU,gBAAgB,CAAC,GAAiC;IAChE,OAAO;QACL,eAAe,EAAE,qBAAqB,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACrF,eAAe,EAAE,qBAAqB,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;KACtF,CAAA;AACH,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,uBAAuB,CAAC,MAAmB;IACzD,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CACpD,KAAK,UAAU,CAAC,OAAO,gBAAgB,UAAU,CAAC,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,CAAC,CAAA;IAC9E,OAAO,sEAAsE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAA;AAClG,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,uBAAuB,CAAC,MAAmB;IACzD,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAA;IACzD,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;IAC1E,OAAO,mBAAmB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,wDAAwD,CAAA;AACpG,CAAC"}
|
package/lib/config.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TuiStartup } from './contracts.ts';
|
|
2
|
+
/** A composed row whose configuration cannot describe a runnable terminal surface. */
|
|
3
|
+
export declare class TuiConfigError extends Error {
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Validate the row's configuration into the runtime shape.
|
|
7
|
+
*
|
|
8
|
+
* The shipped patch derives every value from the startup service, but a user
|
|
9
|
+
* may hand-configure this row in a profile patch, so the row validates its own
|
|
10
|
+
* input instead of trusting the layer above it.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveConfig(raw: unknown): TuiStartup;
|
|
13
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAEhD,sFAAsF;AACtF,qBAAa,cAAe,SAAQ,KAAK;CAAG;AAsB5C;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAetD"}
|
package/lib/config.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { SessionId } from '@deepseek-ai/dsh-session';
|
|
2
|
+
/** A composed row whose configuration cannot describe a runnable terminal surface. */
|
|
3
|
+
export class TuiConfigError extends Error {
|
|
4
|
+
}
|
|
5
|
+
function requireString(value, field) {
|
|
6
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
7
|
+
throw new TuiConfigError(`${field} must be a non-empty string`);
|
|
8
|
+
}
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
function optionalString(value, field) {
|
|
12
|
+
if (value === undefined || value === null)
|
|
13
|
+
return undefined;
|
|
14
|
+
if (typeof value !== 'string')
|
|
15
|
+
throw new TuiConfigError(`${field} must be a string when present`);
|
|
16
|
+
const trimmed = value.trim();
|
|
17
|
+
return trimmed === '' ? undefined : trimmed;
|
|
18
|
+
}
|
|
19
|
+
function optionalBoolean(value, field, fallback) {
|
|
20
|
+
if (value === undefined || value === null)
|
|
21
|
+
return fallback;
|
|
22
|
+
if (typeof value !== 'boolean')
|
|
23
|
+
throw new TuiConfigError(`${field} must be a boolean when present`);
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Validate the row's configuration into the runtime shape.
|
|
28
|
+
*
|
|
29
|
+
* The shipped patch derives every value from the startup service, but a user
|
|
30
|
+
* may hand-configure this row in a profile patch, so the row validates its own
|
|
31
|
+
* input instead of trusting the layer above it.
|
|
32
|
+
*/
|
|
33
|
+
export function resolveConfig(raw) {
|
|
34
|
+
if (typeof raw !== 'object' || raw === null) {
|
|
35
|
+
throw new TuiConfigError('tui row configuration must be a mapping');
|
|
36
|
+
}
|
|
37
|
+
const record = raw;
|
|
38
|
+
return {
|
|
39
|
+
sessionId: SessionId(requireString(record.sessionId, 'sessionId')),
|
|
40
|
+
resume: optionalBoolean(record.resume, 'resume', false),
|
|
41
|
+
resumePicker: optionalBoolean(record.resumePicker, 'resumePicker', false),
|
|
42
|
+
model: optionalString(record.model, 'model'),
|
|
43
|
+
provider: optionalString(record.provider, 'provider'),
|
|
44
|
+
preset: optionalString(record.preset, 'preset'),
|
|
45
|
+
color: optionalBoolean(record.color, 'color', true),
|
|
46
|
+
bell: optionalBoolean(record.bell, 'bell', true),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAGpD,sFAAsF;AACtF,MAAM,OAAO,cAAe,SAAQ,KAAK;CAAG;AAE5C,SAAS,aAAa,CAAC,KAAc,EAAE,KAAa;IAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACrD,MAAM,IAAI,cAAc,CAAC,GAAG,KAAK,6BAA6B,CAAC,CAAA;IACjE,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,cAAc,CAAC,KAAc,EAAE,KAAa;IACnD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAA;IAC3D,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,MAAM,IAAI,cAAc,CAAC,GAAG,KAAK,gCAAgC,CAAC,CAAA;IACjG,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IAC5B,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAA;AAC7C,CAAC;AAED,SAAS,eAAe,CAAC,KAAc,EAAE,KAAa,EAAE,QAAiB;IACvE,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,QAAQ,CAAA;IAC1D,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,cAAc,CAAC,GAAG,KAAK,iCAAiC,CAAC,CAAA;IACnG,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,GAAY;IACxC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,MAAM,IAAI,cAAc,CAAC,yCAAyC,CAAC,CAAA;IACrE,CAAC;IACD,MAAM,MAAM,GAAG,GAA8B,CAAA;IAC7C,OAAO;QACL,SAAS,EAAE,SAAS,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAClE,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC;QACvD,YAAY,EAAE,eAAe,CAAC,MAAM,CAAC,YAAY,EAAE,cAAc,EAAE,KAAK,CAAC;QACzE,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC;QAC5C,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC;QACrD,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC;QAC/C,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC;QACnD,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC;KACjD,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
2
|
+
/**
|
|
3
|
+
* Launch identity and presentation options the app-owned command line row
|
|
4
|
+
* resolves before any row that depends on them activates. Absent on `--help`
|
|
5
|
+
* and on a usage error, which is how dependent rows stay unmounted.
|
|
6
|
+
*/
|
|
7
|
+
export interface TuiStartup {
|
|
8
|
+
/** Exact session this run owns: a fresh id or the one being resumed. */
|
|
9
|
+
readonly sessionId: SessionId;
|
|
10
|
+
/** Rehydrate persisted history instead of creating the session fresh. */
|
|
11
|
+
readonly resume: boolean;
|
|
12
|
+
/** Open the history picker before the first turn. */
|
|
13
|
+
readonly resumePicker: boolean;
|
|
14
|
+
/** Model override supplied on the command line. */
|
|
15
|
+
readonly model: string | undefined;
|
|
16
|
+
/** Provider-route override supplied on the command line. */
|
|
17
|
+
readonly provider: string | undefined;
|
|
18
|
+
/** Agent preset the new session runs; absent takes the roster's default. */
|
|
19
|
+
readonly preset: string | undefined;
|
|
20
|
+
/** Whether ANSI styling is enabled. */
|
|
21
|
+
readonly color: boolean;
|
|
22
|
+
/** Whether a long turn may ring the terminal bell when it finishes. */
|
|
23
|
+
readonly bell: boolean;
|
|
24
|
+
}
|
|
25
|
+
declare module '@deepseek-ai/cordis' {
|
|
26
|
+
interface Context {
|
|
27
|
+
tuiStartup?: TuiStartup;
|
|
28
|
+
/** Printed after the terminal is handed back, so the session stays recoverable. */
|
|
29
|
+
tuiGoodbyeMessage?: string;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=contracts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAEzD;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,qDAAqD;IACrD,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;IAC9B,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IACrC,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,uCAAuC;IACvC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CACvB;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,UAAU,CAAC,EAAE,UAAU,CAAA;QACvB,mFAAmF;QACnF,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAC3B;CACF"}
|
package/lib/contracts.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":""}
|
package/lib/export.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TranscriptEntry } from './transcript.ts';
|
|
2
|
+
/** Directory-relative default the reader can find without being told. */
|
|
3
|
+
export declare const DEFAULT_EXPORT_PREFIX = "dsh-session";
|
|
4
|
+
/** Default file for a dump: the session's own name, in the working directory. */
|
|
5
|
+
export declare function defaultExportFile(sessionId: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Render the visible transcript as markdown.
|
|
8
|
+
*
|
|
9
|
+
* The surface's own glyphs are kept so a pasted dump reads like the screen it
|
|
10
|
+
* came from, and every fragment is escaped for display for the same reason a
|
|
11
|
+
* rendered row is: the file may be opened in a terminal, and it is full of
|
|
12
|
+
* model and tool output.
|
|
13
|
+
*/
|
|
14
|
+
export declare function transcriptToText(entries: readonly TranscriptEntry[]): string;
|
|
15
|
+
//# sourceMappingURL=export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../src/export.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,yEAAyE;AACzE,eAAO,MAAM,qBAAqB,gBAAgB,CAAA;AAKlD,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,GAAG,MAAM,CAgC5E"}
|
package/lib/export.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { displayText } from "./text.js";
|
|
2
|
+
/** Directory-relative default the reader can find without being told. */
|
|
3
|
+
export const DEFAULT_EXPORT_PREFIX = 'dsh-session';
|
|
4
|
+
/** Id characters kept in a file name, so a session id cannot escape the directory. */
|
|
5
|
+
const UNSAFE_NAME = /[^A-Za-z0-9._-]/gu;
|
|
6
|
+
/** Default file for a dump: the session's own name, in the working directory. */
|
|
7
|
+
export function defaultExportFile(sessionId) {
|
|
8
|
+
return `${DEFAULT_EXPORT_PREFIX}-${sessionId.replace(UNSAFE_NAME, '_')}.md`;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Render the visible transcript as markdown.
|
|
12
|
+
*
|
|
13
|
+
* The surface's own glyphs are kept so a pasted dump reads like the screen it
|
|
14
|
+
* came from, and every fragment is escaped for display for the same reason a
|
|
15
|
+
* rendered row is: the file may be opened in a terminal, and it is full of
|
|
16
|
+
* model and tool output.
|
|
17
|
+
*/
|
|
18
|
+
export function transcriptToText(entries) {
|
|
19
|
+
const lines = [];
|
|
20
|
+
for (const entry of entries) {
|
|
21
|
+
switch (entry.kind) {
|
|
22
|
+
case 'user':
|
|
23
|
+
lines.push('', `> ${displayText(entry.text).replace(/\n/gu, '\n> ')}`);
|
|
24
|
+
break;
|
|
25
|
+
case 'assistant':
|
|
26
|
+
lines.push('', displayText(entry.text));
|
|
27
|
+
break;
|
|
28
|
+
case 'notice':
|
|
29
|
+
lines.push('', `<!-- ${displayText(entry.text)} -->`);
|
|
30
|
+
break;
|
|
31
|
+
case 'marker':
|
|
32
|
+
lines.push('', `--- ${displayText(entry.text)} ---`);
|
|
33
|
+
break;
|
|
34
|
+
case 'reasoning':
|
|
35
|
+
lines.push('', `<!-- ${displayText(entry.summary)} -->`);
|
|
36
|
+
break;
|
|
37
|
+
case 'tool': {
|
|
38
|
+
const mark = entry.card.failed ? 'ERROR' : 'tool';
|
|
39
|
+
lines.push('', `### ${mark}: ${displayText(entry.card.title)}`, '', '```');
|
|
40
|
+
for (const row of entry.card.detail)
|
|
41
|
+
lines.push(displayText(row));
|
|
42
|
+
if (entry.card.totalLines > entry.card.detail.length) {
|
|
43
|
+
lines.push(`… ${entry.card.totalLines - entry.card.detail.length} more lines`);
|
|
44
|
+
}
|
|
45
|
+
lines.push('```');
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return `${lines.join('\n').replace(/^\n+/u, '')}\n`;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../src/export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAGvC,yEAAyE;AACzE,MAAM,CAAC,MAAM,qBAAqB,GAAG,aAAa,CAAA;AAElD,sFAAsF;AACtF,MAAM,WAAW,GAAG,mBAAmB,CAAA;AAEvC,iFAAiF;AACjF,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO,GAAG,qBAAqB,IAAI,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,KAAK,CAAA;AAC7E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAmC;IAClE,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,MAAM;gBACT,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAA;gBACtE,MAAK;YACP,KAAK,WAAW;gBACd,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;gBACvC,MAAK;YACP,KAAK,QAAQ;gBACX,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBACrD,MAAK;YACP,KAAK,QAAQ;gBACX,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBACpD,MAAK;YACP,KAAK,WAAW;gBACd,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;gBACxD,MAAK;YACP,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAA;gBACjD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,IAAI,KAAK,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,CAAA;gBAC1E,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM;oBAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAA;gBACjE,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;oBACrD,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,aAAa,CAAC,CAAA;gBAChF,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBACjB,MAAK;YACP,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAA;AACrD,CAAC"}
|
package/lib/gates.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/** The outcome vocabulary the approval seam accepts from an answerer. */
|
|
2
|
+
export type ApprovalOutcome = 'allowed-once' | 'rejected' | 'cancelled';
|
|
3
|
+
/** How a pending gate presents itself, independent of how it is drawn. */
|
|
4
|
+
export interface GateCard {
|
|
5
|
+
readonly kind: 'approval' | 'question';
|
|
6
|
+
readonly title: string;
|
|
7
|
+
readonly detail: readonly string[];
|
|
8
|
+
readonly options: readonly GateOption[];
|
|
9
|
+
readonly hint: string;
|
|
10
|
+
}
|
|
11
|
+
/** One selectable row of a question gate. */
|
|
12
|
+
export interface GateOption {
|
|
13
|
+
readonly label: string;
|
|
14
|
+
readonly description: string | undefined;
|
|
15
|
+
readonly current: boolean;
|
|
16
|
+
readonly selected: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* One pending approval.
|
|
20
|
+
*
|
|
21
|
+
* The gate is a pure state machine: it turns key presses into the one outcome
|
|
22
|
+
* the seam accepts and never infers a durable grant, because a terminal key
|
|
23
|
+
* press is a single decision about a single call.
|
|
24
|
+
*/
|
|
25
|
+
export declare class ApprovalGate {
|
|
26
|
+
private readonly toolName;
|
|
27
|
+
private readonly reason;
|
|
28
|
+
private outcome;
|
|
29
|
+
constructor(toolName: string, reason: string | undefined);
|
|
30
|
+
get resolved(): boolean;
|
|
31
|
+
/** Apply one key press; returns the outcome the first time it settles. */
|
|
32
|
+
handleKey(data: string): ApprovalOutcome | undefined;
|
|
33
|
+
cancel(): void;
|
|
34
|
+
card(): GateCard;
|
|
35
|
+
}
|
|
36
|
+
/** One question as the seam describes it. */
|
|
37
|
+
export interface GateQuestion {
|
|
38
|
+
readonly id: string;
|
|
39
|
+
readonly question: string;
|
|
40
|
+
readonly detail: string | undefined;
|
|
41
|
+
readonly options: readonly {
|
|
42
|
+
readonly label: string;
|
|
43
|
+
readonly description: string | undefined;
|
|
44
|
+
}[];
|
|
45
|
+
readonly multiSelect: boolean;
|
|
46
|
+
}
|
|
47
|
+
/** One answered question in the batch result. */
|
|
48
|
+
export interface GateAnswer {
|
|
49
|
+
readonly id: string;
|
|
50
|
+
readonly selected: readonly string[];
|
|
51
|
+
readonly custom?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Read the seam's request into the gate's own vocabulary.
|
|
55
|
+
*
|
|
56
|
+
* A question without options is answered by typing, which is why it becomes an
|
|
57
|
+
* option-less gate rather than a rejected request: the model asked for text.
|
|
58
|
+
*/
|
|
59
|
+
export declare function toGateQuestions(request: unknown): GateQuestion[];
|
|
60
|
+
/**
|
|
61
|
+
* A pending batch of questions.
|
|
62
|
+
*
|
|
63
|
+
* Answers are collected per question and returned in the seam's shape. An
|
|
64
|
+
* escape skips the current question with an empty selection rather than
|
|
65
|
+
* aborting the batch, so a human who cannot answer one question still returns
|
|
66
|
+
* everything else they decided.
|
|
67
|
+
*/
|
|
68
|
+
export declare class QuestionGate {
|
|
69
|
+
private readonly questions;
|
|
70
|
+
private index;
|
|
71
|
+
private cursor;
|
|
72
|
+
private typed;
|
|
73
|
+
private readonly chosen;
|
|
74
|
+
private readonly custom;
|
|
75
|
+
private finished;
|
|
76
|
+
constructor(questions: readonly GateQuestion[]);
|
|
77
|
+
get resolved(): boolean;
|
|
78
|
+
private get current();
|
|
79
|
+
/** Apply one key press; returns the batch answer the first time it completes. */
|
|
80
|
+
handleKey(data: string): GateAnswer[] | undefined;
|
|
81
|
+
private confirm;
|
|
82
|
+
private result;
|
|
83
|
+
card(): GateCard;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=gates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gates.d.ts","sourceRoot":"","sources":["../src/gates.ts"],"names":[],"mappings":"AAEA,yEAAyE;AACzE,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,UAAU,GAAG,WAAW,CAAA;AAEvE,0EAA0E;AAC1E,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAAA;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,QAAQ,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAA;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,6CAA6C;AAC7C,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAC3B;AAMD;;;;;;GAMG;AACH,qBAAa,YAAY;IAIrB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJzB,OAAO,CAAC,OAAO,CAA6B;gBAGzB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS;IAG7C,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,0EAA0E;IAC1E,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAQpD,MAAM,IAAI,IAAI;IAId,IAAI,IAAI,QAAQ;CASjB;AAED,6CAA6C;AAC7C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,EAAE,CAAA;IACjG,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;CAC9B;AAED,iDAAiD;AACjD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAMD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,EAAE,CAwBhE;AAED;;;;;;;GAOG;AACH,qBAAa,YAAY;IAQX,OAAO,CAAC,QAAQ,CAAC,SAAS;IAPtC,OAAO,CAAC,KAAK,CAAI;IACjB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,QAAQ,CAAQ;gBAEK,SAAS,EAAE,SAAS,YAAY,EAAE;IAO/D,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,OAAO,KAAK,OAAO,GAElB;IAED,iFAAiF;IACjF,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,GAAG,SAAS;IAmDjD,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,MAAM;IAYd,IAAI,IAAI,QAAQ;CAuBjB"}
|
package/lib/gates.js
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { matchesKey } from '@earendil-works/pi-tui';
|
|
2
|
+
function lines(value) {
|
|
3
|
+
return value.split('\n').filter(line => line.trim() !== '');
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* One pending approval.
|
|
7
|
+
*
|
|
8
|
+
* The gate is a pure state machine: it turns key presses into the one outcome
|
|
9
|
+
* the seam accepts and never infers a durable grant, because a terminal key
|
|
10
|
+
* press is a single decision about a single call.
|
|
11
|
+
*/
|
|
12
|
+
export class ApprovalGate {
|
|
13
|
+
toolName;
|
|
14
|
+
reason;
|
|
15
|
+
outcome;
|
|
16
|
+
constructor(toolName, reason) {
|
|
17
|
+
this.toolName = toolName;
|
|
18
|
+
this.reason = reason;
|
|
19
|
+
}
|
|
20
|
+
get resolved() {
|
|
21
|
+
return this.outcome !== undefined;
|
|
22
|
+
}
|
|
23
|
+
/** Apply one key press; returns the outcome the first time it settles. */
|
|
24
|
+
handleKey(data) {
|
|
25
|
+
if (this.outcome !== undefined)
|
|
26
|
+
return undefined;
|
|
27
|
+
if (matchesKey(data, 'y'))
|
|
28
|
+
this.outcome = 'allowed-once';
|
|
29
|
+
else if (matchesKey(data, 'n'))
|
|
30
|
+
this.outcome = 'rejected';
|
|
31
|
+
else if (matchesKey(data, 'escape'))
|
|
32
|
+
this.outcome = 'cancelled';
|
|
33
|
+
return this.outcome;
|
|
34
|
+
}
|
|
35
|
+
cancel() {
|
|
36
|
+
this.outcome ??= 'cancelled';
|
|
37
|
+
}
|
|
38
|
+
card() {
|
|
39
|
+
return {
|
|
40
|
+
kind: 'approval',
|
|
41
|
+
title: `approval needed · ${this.toolName}`,
|
|
42
|
+
detail: this.reason === undefined ? [] : lines(this.reason),
|
|
43
|
+
options: [],
|
|
44
|
+
hint: this.outcome === undefined ? 'y allow once · n reject · esc cancel' : 'decided',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function asRecord(value) {
|
|
49
|
+
return typeof value === 'object' && value !== null ? value : undefined;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Read the seam's request into the gate's own vocabulary.
|
|
53
|
+
*
|
|
54
|
+
* A question without options is answered by typing, which is why it becomes an
|
|
55
|
+
* option-less gate rather than a rejected request: the model asked for text.
|
|
56
|
+
*/
|
|
57
|
+
export function toGateQuestions(request) {
|
|
58
|
+
const record = asRecord(request);
|
|
59
|
+
const raw = Array.isArray(record?.questions) ? record.questions : [];
|
|
60
|
+
const questions = [];
|
|
61
|
+
for (const item of raw) {
|
|
62
|
+
const entry = asRecord(item);
|
|
63
|
+
if (entry === undefined || typeof entry.id !== 'string')
|
|
64
|
+
continue;
|
|
65
|
+
const options = (Array.isArray(entry.options) ? entry.options : []).flatMap(option => {
|
|
66
|
+
const candidate = asRecord(option);
|
|
67
|
+
if (candidate === undefined || typeof candidate.label !== 'string')
|
|
68
|
+
return [];
|
|
69
|
+
return [{
|
|
70
|
+
label: candidate.label,
|
|
71
|
+
description: typeof candidate.description === 'string' ? candidate.description : undefined,
|
|
72
|
+
}];
|
|
73
|
+
});
|
|
74
|
+
questions.push({
|
|
75
|
+
id: entry.id,
|
|
76
|
+
question: typeof entry.question === 'string' ? entry.question : 'question',
|
|
77
|
+
detail: typeof entry.detail === 'string' ? entry.detail : undefined,
|
|
78
|
+
options,
|
|
79
|
+
multiSelect: entry.multiSelect === true,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return questions;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A pending batch of questions.
|
|
86
|
+
*
|
|
87
|
+
* Answers are collected per question and returned in the seam's shape. An
|
|
88
|
+
* escape skips the current question with an empty selection rather than
|
|
89
|
+
* aborting the batch, so a human who cannot answer one question still returns
|
|
90
|
+
* everything else they decided.
|
|
91
|
+
*/
|
|
92
|
+
export class QuestionGate {
|
|
93
|
+
questions;
|
|
94
|
+
index = 0;
|
|
95
|
+
cursor = 0;
|
|
96
|
+
typed = '';
|
|
97
|
+
chosen = [];
|
|
98
|
+
custom = [];
|
|
99
|
+
finished = false;
|
|
100
|
+
constructor(questions) {
|
|
101
|
+
this.questions = questions;
|
|
102
|
+
for (const _ of questions) {
|
|
103
|
+
this.chosen.push([]);
|
|
104
|
+
this.custom.push(undefined);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
get resolved() {
|
|
108
|
+
return this.finished;
|
|
109
|
+
}
|
|
110
|
+
get current() {
|
|
111
|
+
return this.questions[this.index];
|
|
112
|
+
}
|
|
113
|
+
/** Apply one key press; returns the batch answer the first time it completes. */
|
|
114
|
+
handleKey(data) {
|
|
115
|
+
const question = this.current;
|
|
116
|
+
if (this.finished || question === undefined)
|
|
117
|
+
return undefined;
|
|
118
|
+
if (matchesKey(data, 'up')) {
|
|
119
|
+
this.cursor = Math.max(0, this.cursor - 1);
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
if (matchesKey(data, 'down')) {
|
|
123
|
+
this.cursor = Math.min(Math.max(0, question.options.length - 1), this.cursor + 1);
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
if (question.options.length > 0 && matchesKey(data, 'space')) {
|
|
127
|
+
const option = question.options[this.cursor];
|
|
128
|
+
if (option !== undefined) {
|
|
129
|
+
const chosen = this.chosen[this.index] ?? [];
|
|
130
|
+
this.chosen[this.index] = chosen.includes(option.label)
|
|
131
|
+
? chosen.filter(label => label !== option.label)
|
|
132
|
+
: question.multiSelect ? [...chosen, option.label] : [option.label];
|
|
133
|
+
}
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
if (matchesKey(data, 'escape')) {
|
|
137
|
+
this.confirm();
|
|
138
|
+
return this.result();
|
|
139
|
+
}
|
|
140
|
+
if (matchesKey(data, 'enter')) {
|
|
141
|
+
this.confirm();
|
|
142
|
+
return this.result();
|
|
143
|
+
}
|
|
144
|
+
if (matchesKey(data, 'backspace')) {
|
|
145
|
+
this.typed = this.typed.slice(0, -1);
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
if (matchesKey(data, 'space')) {
|
|
149
|
+
this.typed += ' ';
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
if (/^[1-9]$/u.test(data)) {
|
|
153
|
+
const option = question.options[Number.parseInt(data, 10) - 1];
|
|
154
|
+
if (option !== undefined) {
|
|
155
|
+
const chosen = this.chosen[this.index] ?? [];
|
|
156
|
+
this.chosen[this.index] = chosen.includes(option.label)
|
|
157
|
+
? chosen.filter(label => label !== option.label)
|
|
158
|
+
: question.multiSelect ? [...chosen, option.label] : [option.label];
|
|
159
|
+
}
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
if (data.length === 1 && data >= ' ')
|
|
163
|
+
this.typed += data;
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
confirm() {
|
|
167
|
+
const question = this.current;
|
|
168
|
+
if (question === undefined)
|
|
169
|
+
return;
|
|
170
|
+
const typed = this.typed.trim();
|
|
171
|
+
if (typed !== '')
|
|
172
|
+
this.custom[this.index] = typed;
|
|
173
|
+
this.typed = '';
|
|
174
|
+
this.cursor = 0;
|
|
175
|
+
this.index += 1;
|
|
176
|
+
if (this.index >= this.questions.length)
|
|
177
|
+
this.finished = true;
|
|
178
|
+
}
|
|
179
|
+
result() {
|
|
180
|
+
if (!this.finished)
|
|
181
|
+
return undefined;
|
|
182
|
+
return this.questions.map((question, position) => {
|
|
183
|
+
const custom = this.custom[position];
|
|
184
|
+
return {
|
|
185
|
+
id: question.id,
|
|
186
|
+
selected: this.chosen[position] ?? [],
|
|
187
|
+
...(custom === undefined ? {} : { custom }),
|
|
188
|
+
};
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
card() {
|
|
192
|
+
const question = this.current;
|
|
193
|
+
if (question === undefined) {
|
|
194
|
+
return { kind: 'question', title: 'question', detail: [], options: [], hint: 'finishing' };
|
|
195
|
+
}
|
|
196
|
+
const chosen = this.chosen[this.index] ?? [];
|
|
197
|
+
const detail = question.detail === undefined ? [] : lines(question.detail);
|
|
198
|
+
if (this.typed !== '')
|
|
199
|
+
detail.push(`typed: ${this.typed}`);
|
|
200
|
+
return {
|
|
201
|
+
kind: 'question',
|
|
202
|
+
title: `${question.question}${this.questions.length > 1 ? ` (${this.index + 1}/${this.questions.length})` : ''}`,
|
|
203
|
+
detail,
|
|
204
|
+
options: question.options.map((option, position) => ({
|
|
205
|
+
label: option.label,
|
|
206
|
+
description: option.description,
|
|
207
|
+
current: position === this.cursor,
|
|
208
|
+
selected: chosen.includes(option.label),
|
|
209
|
+
})),
|
|
210
|
+
hint: question.options.length === 0
|
|
211
|
+
? 'type an answer · enter confirm · esc skip'
|
|
212
|
+
: `${question.multiSelect ? 'space toggle' : 'space select'} · digits pick · enter confirm · esc skip`,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=gates.js.map
|
package/lib/gates.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gates.js","sourceRoot":"","sources":["../src/gates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAsBnD,SAAS,KAAK,CAAC,KAAa;IAC1B,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;AAC7D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,YAAY;IAIJ;IACA;IAJX,OAAO,CAA6B;IAE5C,YACmB,QAAgB,EAChB,MAA0B;QAD1B,aAAQ,GAAR,QAAQ,CAAQ;QAChB,WAAM,GAAN,MAAM,CAAoB;IAC1C,CAAC;IAEJ,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,OAAO,KAAK,SAAS,CAAA;IACnC,CAAC;IAED,0EAA0E;IAC1E,SAAS,CAAC,IAAY;QACpB,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YAAE,OAAO,SAAS,CAAA;QAChD,IAAI,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC;YAAE,IAAI,CAAC,OAAO,GAAG,cAAc,CAAA;aACnD,IAAI,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC;YAAE,IAAI,CAAC,OAAO,GAAG,UAAU,CAAA;aACpD,IAAI,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC;YAAE,IAAI,CAAC,OAAO,GAAG,WAAW,CAAA;QAC/D,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,OAAO,KAAK,WAAW,CAAA;IAC9B,CAAC;IAED,IAAI;QACF,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,qBAAqB,IAAI,CAAC,QAAQ,EAAE;YAC3C,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;YAC3D,OAAO,EAAE,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,sCAAsC,CAAC,CAAC,CAAC,SAAS;SACtF,CAAA;IACH,CAAC;CACF;AAkBD,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAE,KAAiC,CAAC,CAAC,CAAC,SAAS,CAAA;AACrG,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IAChC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAA;IACpE,MAAM,SAAS,GAAmB,EAAE,CAAA;IACpC,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;QAC5B,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ;YAAE,SAAQ;QACjE,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;YACnF,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;YAClC,IAAI,SAAS,KAAK,SAAS,IAAI,OAAO,SAAS,CAAC,KAAK,KAAK,QAAQ;gBAAE,OAAO,EAAE,CAAA;YAC7E,OAAO,CAAC;oBACN,KAAK,EAAE,SAAS,CAAC,KAAK;oBACtB,WAAW,EAAE,OAAO,SAAS,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;iBAC3F,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;QACF,SAAS,CAAC,IAAI,CAAC;YACb,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,QAAQ,EAAE,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU;YAC1E,MAAM,EAAE,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;YACnE,OAAO;YACP,WAAW,EAAE,KAAK,CAAC,WAAW,KAAK,IAAI;SACxC,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,YAAY;IAQM;IAPrB,KAAK,GAAG,CAAC,CAAA;IACT,MAAM,GAAG,CAAC,CAAA;IACV,KAAK,GAAG,EAAE,CAAA;IACD,MAAM,GAAe,EAAE,CAAA;IACvB,MAAM,GAA2B,EAAE,CAAA;IAC5C,QAAQ,GAAG,KAAK,CAAA;IAExB,YAA6B,SAAkC;QAAlC,cAAS,GAAT,SAAS,CAAyB;QAC7D,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YACpB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC7B,CAAC;IACH,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED,IAAY,OAAO;QACjB,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACnC,CAAC;IAED,iFAAiF;IACjF,SAAS,CAAC,IAAY;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAA;QAC7B,IAAI,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,SAAS,CAAA;QAC7D,IAAI,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;YAC1C,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;YACjF,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YAC7D,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAC5C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;gBAC5C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;oBACrD,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,CAAC;oBAChD,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACvE,CAAC;YACD,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,IAAI,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,OAAO,EAAE,CAAA;YACd,OAAO,IAAI,CAAC,MAAM,EAAE,CAAA;QACtB,CAAC;QACD,IAAI,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,OAAO,EAAE,CAAA;YACd,OAAO,IAAI,CAAC,MAAM,EAAE,CAAA;QACtB,CAAC;QACD,IAAI,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;YACpC,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,IAAI,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,KAAK,IAAI,GAAG,CAAA;YACjB,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;YAC9D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;gBAC5C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;oBACrD,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,CAAC;oBAChD,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACvE,CAAC;YACD,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,IAAI,GAAG;YAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAA;QACxD,OAAO,SAAS,CAAA;IAClB,CAAC;IAEO,OAAO;QACb,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAA;QAC7B,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAM;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;QAC/B,IAAI,KAAK,KAAK,EAAE;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,CAAA;QACjD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;QACf,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;QACf,IAAI,CAAC,KAAK,IAAI,CAAC,CAAA;QACf,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM;YAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;IAC/D,CAAC;IAEO,MAAM;QACZ,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO,SAAS,CAAA;QACpC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE;YAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;YACpC,OAAO;gBACL,EAAE,EAAE,QAAQ,CAAC,EAAE;gBACf,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;gBACrC,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;aAC5C,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,IAAI;QACF,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAA;QAC7B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAA;QAC5F,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;QAC5C,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;QAC1E,IAAI,IAAI,CAAC,KAAK,KAAK,EAAE;YAAE,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;QAC1D,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,GAAG,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACjH,MAAM;YACN,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACnD,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,OAAO,EAAE,QAAQ,KAAK,IAAI,CAAC,MAAM;gBACjC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;aACxC,CAAC,CAAC;YACH,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;gBACjC,CAAC,CAAC,2CAA2C;gBAC7C,CAAC,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,cAAc,2CAA2C;SACzG,CAAA;IACH,CAAC;CACF"}
|