@openvulcan/dsh-vulcancode 0.0.0-stage → 0.4.3
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 +126 -2
- package/assets/openvulcan-icon.svg +33 -0
- package/cordis.patch.yml +19 -0
- package/node_modules/@openvulcan/dsh-decision-guard/LICENSE +21 -0
- package/node_modules/@openvulcan/dsh-decision-guard/README.md +14 -0
- package/node_modules/@openvulcan/dsh-decision-guard/assets/decision-guard-icon.png +0 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/calls.d.ts +40 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/calls.js +150 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/client.js +2250 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/decide.d.ts +90 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/decide.js +108 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/index.d.ts +129 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/index.js +572 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/intent.d.ts +22 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/intent.js +77 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/panel.d.ts +158 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/panel.js +340 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/records.d.ts +133 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/records.js +186 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/review.d.ts +55 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/review.js +202 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/session-state.d.ts +62 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/session-state.js +155 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/version.d.ts +2 -0
- package/node_modules/@openvulcan/dsh-decision-guard/lib/version.js +4 -0
- package/node_modules/@openvulcan/dsh-decision-guard/package.json +68 -0
- package/node_modules/@openvulcan/dsh-vulcan-account/LICENSE +21 -0
- package/node_modules/@openvulcan/dsh-vulcan-account/assets/account-icon.png +0 -0
- package/node_modules/@openvulcan/dsh-vulcan-account/lib/client.js +573 -0
- package/node_modules/@openvulcan/dsh-vulcan-account/lib/index.d.ts +92 -0
- package/node_modules/@openvulcan/dsh-vulcan-account/lib/index.js +194 -0
- package/node_modules/@openvulcan/dsh-vulcan-account/package.json +57 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/LICENSE +21 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/assets/answers-icon.png +0 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/assets/prompts/answer-mode-interactive.md +79 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/assets/prompts/answer-mode-standard.md +1 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/answer-model.d.ts +258 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/answer-model.js +698 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/client.js +671 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/fences.d.ts +29 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/fences.js +70 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/index.d.ts +19 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/index.js +52 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/limits.d.ts +9 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/limits.js +9 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/prompt.d.ts +22 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/prompt.js +39 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/reply-format.d.ts +20 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/reply-format.js +17 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/session-state.d.ts +66 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/lib/session-state.js +118 -0
- package/node_modules/@openvulcan/dsh-vulcan-answers/package.json +59 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/LICENSE +21 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/assets/luaskills-icon.svg +1 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/client.js +949 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/constants.d.ts +46 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/constants.js +51 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/engine.d.ts +55 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/engine.js +149 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/hub.d.ts +49 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/hub.js +116 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/index.d.ts +26 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/index.js +276 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/protocol.d.ts +65 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/protocol.js +2 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/runtime.d.ts +111 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/runtime.js +281 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/sdk-install.d.ts +26 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/sdk-install.js +87 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/settings.d.ts +79 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/settings.js +165 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/skills.d.ts +34 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/skills.js +61 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/tools.d.ts +59 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/tools.js +107 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/worker.d.ts +10 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/worker.js +140 -0
- package/node_modules/@openvulcan/dsh-vulcan-luaskills/package.json +57 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/LICENSE +21 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/assets/markdown-memory-guide.md +21 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/assets/memory-curator/SKILL.md +31 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/assets/memory-icon.png +0 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/client.js +1090 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/index.d.ts +30 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/index.js +240 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/inject.d.ts +30 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/inject.js +46 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/constants.d.ts +23 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/constants.js +25 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/document.d.ts +108 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/document.js +373 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/errors.d.ts +14 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/errors.js +31 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/index.d.ts +196 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/index.js +204 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/operations.d.ts +92 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/operations.js +472 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/package.d.ts +126 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/package.js +553 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/registry.d.ts +56 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/registry.js +182 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/scope.d.ts +13 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/scope.js +24 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/search.d.ts +65 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/search.js +227 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/snapshot.d.ts +34 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/snapshot.js +171 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/store.d.ts +72 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/store.js +250 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/timestamp.d.ts +6 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/timestamp.js +12 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/tokens.d.ts +8 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/tokens.js +38 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/page.d.ts +132 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/page.js +235 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/project.d.ts +14 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/project.js +27 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/settings.d.ts +29 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/lib/settings.js +62 -0
- package/node_modules/@openvulcan/dsh-vulcan-memory/package.json +63 -0
- package/node_modules/@openvulcan/dsh-vulcan-reasoning/LICENSE +21 -0
- package/node_modules/@openvulcan/dsh-vulcan-reasoning/lib/client.js +509 -0
- package/node_modules/@openvulcan/dsh-vulcan-reasoning/lib/index.d.ts +6 -0
- package/node_modules/@openvulcan/dsh-vulcan-reasoning/lib/index.js +8 -0
- package/node_modules/@openvulcan/dsh-vulcan-reasoning/package.json +42 -0
- package/node_modules/@openvulcan/dsh-vulcan-style/LICENSE +21 -0
- package/node_modules/@openvulcan/dsh-vulcan-style/assets/style-icon.png +0 -0
- package/node_modules/@openvulcan/dsh-vulcan-style/lib/client.js +1121 -0
- package/node_modules/@openvulcan/dsh-vulcan-style/lib/index.d.ts +34 -0
- package/node_modules/@openvulcan/dsh-vulcan-style/lib/index.js +42 -0
- package/node_modules/@openvulcan/dsh-vulcan-style/package.json +51 -0
- package/node_modules/@openvulcan/openvulcan-account/LICENSE +21 -0
- package/node_modules/@openvulcan/openvulcan-account/lib/account.d.ts +140 -0
- package/node_modules/@openvulcan/openvulcan-account/lib/account.js +347 -0
- package/node_modules/@openvulcan/openvulcan-account/lib/index.d.ts +1 -0
- package/node_modules/@openvulcan/openvulcan-account/lib/index.js +1 -0
- package/node_modules/@openvulcan/openvulcan-account/package.json +29 -0
- package/node_modules/@openvulcan/vulcan-decision/LICENSE +21 -0
- package/node_modules/@openvulcan/vulcan-decision/README.md +23 -0
- package/node_modules/@openvulcan/vulcan-decision/bin/vulcan-decision.js +4 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/cli.d.ts +5 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/cli.js +267 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/cloud/edge.d.ts +211 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/cloud/edge.js +594 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/download.d.ts +36 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/download.js +99 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/engine.d.ts +37 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/engine.js +39 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/hardware.d.ts +105 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/hardware.js +207 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/home.d.ts +26 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/home.js +54 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/index.d.ts +17 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/index.js +17 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/local/engine.d.ts +54 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/local/engine.js +157 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/local/models.d.ts +126 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/local/models.js +261 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/local/packs.d.ts +102 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/local/packs.js +195 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/local/worker.d.ts +61 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/local/worker.js +123 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/protocol.d.ts +74 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/protocol.js +31 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/render.d.ts +15 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/render.js +33 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/version.d.ts +2 -0
- package/node_modules/@openvulcan/vulcan-decision/lib/version.js +4 -0
- package/node_modules/@openvulcan/vulcan-decision/package.json +40 -0
- package/node_modules/@openvulcan/vulcan-decision/python/vulcan_decision_worker.py +363 -0
- package/node_modules/@openvulcan/vulcan-decision/runtime-packs/onnx-cpu.json +627 -0
- package/node_modules/@openvulcan/vulcan-decision/runtime-packs/onnx-cuda.json +423 -0
- package/node_modules/@openvulcan/vulcan-decision/runtime-packs/torch-cpu.json +1047 -0
- package/node_modules/@openvulcan/vulcan-decision/runtime-packs/torch-cu128.json +647 -0
- package/package.json +55 -4
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The OpenVulcan account for every VulcanCode plugin in dsh: one sign-in, kept in dsh's credential
|
|
3
|
+
* store and refreshed here, offered to other plugins as the cordis service `openvulcanAccount`.
|
|
4
|
+
* The settings page signs in and out through exact `/api/vulcan-account/*` routes inside dsh's
|
|
5
|
+
* authenticated connection.
|
|
6
|
+
*/
|
|
7
|
+
import { Service, type Context } from '@deepseek-ai/cordis';
|
|
8
|
+
import { type AccountProfile, type AccountSource, type AccountStatus, type Credential, type CredentialStore, type PendingSignIn, type Site } from '@openvulcan/openvulcan-account';
|
|
9
|
+
export type { AccountProfile, AccountStatus, Credential, PendingSignIn, Site } from '@openvulcan/openvulcan-account';
|
|
10
|
+
declare module '@deepseek-ai/cordis' {
|
|
11
|
+
interface Context {
|
|
12
|
+
openvulcanAccount: OpenVulcanAccountService;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** Where the credential is kept in dsh's credential store; only this plugin reads or writes it. */
|
|
16
|
+
export declare const CREDENTIAL_KEY: import("@deepseek-ai/dsh-credentials").CredentialKey;
|
|
17
|
+
/** Prefix of every settings route, below dsh's `/api`. Also restated in `client/shared.ts`. */
|
|
18
|
+
export declare const ROUTE_PREFIX = "/api/vulcan-account/";
|
|
19
|
+
/** A sign-in the settings page started and is waiting on, as the page shows it. */
|
|
20
|
+
export interface SignInView {
|
|
21
|
+
readonly approvalUrl: string;
|
|
22
|
+
readonly expiresAt: string;
|
|
23
|
+
}
|
|
24
|
+
/** Everything the settings page shows, in one answer. */
|
|
25
|
+
export interface AccountView {
|
|
26
|
+
readonly account: AccountStatus;
|
|
27
|
+
readonly signIn: SignInView | null;
|
|
28
|
+
readonly signInError?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* How OpenVulcan records this sign-in: the client is dsh at its exact running version, so the
|
|
32
|
+
* platform can count dsh installations the way it counts "Vulcan Code".
|
|
33
|
+
*/
|
|
34
|
+
export declare function deviceInfo(dshVersion: string): {
|
|
35
|
+
display_name: string;
|
|
36
|
+
client_version: string;
|
|
37
|
+
};
|
|
38
|
+
/** The account credential as one dsh grant record. */
|
|
39
|
+
export declare class DshCredentialStore implements CredentialStore {
|
|
40
|
+
private readonly ctx;
|
|
41
|
+
constructor(ctx: Context);
|
|
42
|
+
read(): Promise<Credential | undefined>;
|
|
43
|
+
write(credential: Credential): Promise<void>;
|
|
44
|
+
delete(): Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The OpenVulcan account other plugins use. A consumer looks it up with
|
|
48
|
+
* `ctx.get('openvulcanAccount')` on every use rather than injecting it, so turning this plugin off
|
|
49
|
+
* makes cloud features fail as "not signed in" instead of silently stopping the consumer.
|
|
50
|
+
*/
|
|
51
|
+
export declare class OpenVulcanAccountService extends Service implements AccountSource {
|
|
52
|
+
static inject: string[];
|
|
53
|
+
private readonly account;
|
|
54
|
+
private readonly listeners;
|
|
55
|
+
private pending;
|
|
56
|
+
private pendingError;
|
|
57
|
+
/** The profile of one device authorization, read once per sign-in. */
|
|
58
|
+
private profileCache;
|
|
59
|
+
constructor(ctx: Context);
|
|
60
|
+
/** The account as hosts show it; never contains the token. */
|
|
61
|
+
status(): Promise<AccountStatus>;
|
|
62
|
+
/**
|
|
63
|
+
* A usable credential, refreshed first when it is about to expire.
|
|
64
|
+
* @throws AccountError when nobody is signed in or the user has to sign in again.
|
|
65
|
+
*/
|
|
66
|
+
credential(): Promise<Credential>;
|
|
67
|
+
/**
|
|
68
|
+
* Start signing in at `site`; any sign-in still waiting is cancelled. `done` settles once the
|
|
69
|
+
* user approved (the credential is stored) or the sign-in failed.
|
|
70
|
+
*/
|
|
71
|
+
signIn(site: Site): Promise<PendingSignIn>;
|
|
72
|
+
cancelSignIn(): void;
|
|
73
|
+
/** Revoke this device at OpenVulcan and forget the credential. */
|
|
74
|
+
signOut(): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Who is signed in, read from OpenVulcan once per device authorization; a failed read is not kept.
|
|
77
|
+
* @throws AccountError when nobody is signed in.
|
|
78
|
+
*/
|
|
79
|
+
profile(): Promise<AccountProfile>;
|
|
80
|
+
/** Called after every sign-in and sign-out; returns the unsubscribe function. */
|
|
81
|
+
onChange(listener: (status: AccountStatus) => void): () => void;
|
|
82
|
+
/** The settings page's view. */
|
|
83
|
+
view(): Promise<AccountView>;
|
|
84
|
+
private notify;
|
|
85
|
+
}
|
|
86
|
+
/** Fetch-shaped handler of one settings route. */
|
|
87
|
+
type Handler = (account: OpenVulcanAccountService, request: Request, url: URL) => Promise<unknown>;
|
|
88
|
+
/** Every settings route: method, path below {@link ROUTE_PREFIX}, handler. */
|
|
89
|
+
export declare const ROUTES: readonly (readonly ['GET' | 'POST', string, Handler])[];
|
|
90
|
+
/** Answer one settings request; failures carry their code, never a stack. */
|
|
91
|
+
export declare function handle(account: OpenVulcanAccountService, handler: Handler, request: Request): Promise<Response>;
|
|
92
|
+
export default OpenVulcanAccountService;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The OpenVulcan account for every VulcanCode plugin in dsh: one sign-in, kept in dsh's credential
|
|
3
|
+
* store and refreshed here, offered to other plugins as the cordis service `openvulcanAccount`.
|
|
4
|
+
* The settings page signs in and out through exact `/api/vulcan-account/*` routes inside dsh's
|
|
5
|
+
* authenticated connection.
|
|
6
|
+
*/
|
|
7
|
+
import { Service } from '@deepseek-ai/cordis';
|
|
8
|
+
import { getDshRuntimeVersion } from '@deepseek-ai/dsh-app-boot';
|
|
9
|
+
import { credentialKey } from '@deepseek-ai/dsh-credentials';
|
|
10
|
+
import { AccountError, isSite, OpenVulcanAccount, parseCredential, } from '@openvulcan/openvulcan-account';
|
|
11
|
+
/** Where the credential is kept in dsh's credential store; only this plugin reads or writes it. */
|
|
12
|
+
export const CREDENTIAL_KEY = credentialKey('openvulcan', 'account');
|
|
13
|
+
/** Prefix of every settings route, below dsh's `/api`. Also restated in `client/shared.ts`. */
|
|
14
|
+
export const ROUTE_PREFIX = '/api/vulcan-account/';
|
|
15
|
+
/**
|
|
16
|
+
* How OpenVulcan records this sign-in: the client is dsh at its exact running version, so the
|
|
17
|
+
* platform can count dsh installations the way it counts "Vulcan Code".
|
|
18
|
+
*/
|
|
19
|
+
export function deviceInfo(dshVersion) {
|
|
20
|
+
return { display_name: 'dsh', client_version: dshVersion };
|
|
21
|
+
}
|
|
22
|
+
/** The account credential as one dsh grant record. */
|
|
23
|
+
export class DshCredentialStore {
|
|
24
|
+
ctx;
|
|
25
|
+
constructor(ctx) {
|
|
26
|
+
this.ctx = ctx;
|
|
27
|
+
}
|
|
28
|
+
async read() {
|
|
29
|
+
const record = await this.ctx.credentials.readRecord(CREDENTIAL_KEY);
|
|
30
|
+
return record?.kind === 'grant' ? parseCredential(record.payload) : undefined;
|
|
31
|
+
}
|
|
32
|
+
async write(credential) {
|
|
33
|
+
await this.ctx.credentials.modifyRecord(CREDENTIAL_KEY, async () => ({ kind: 'grant', payload: credential }));
|
|
34
|
+
}
|
|
35
|
+
async delete() {
|
|
36
|
+
await this.ctx.credentials.deleteRecord(CREDENTIAL_KEY);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The OpenVulcan account other plugins use. A consumer looks it up with
|
|
41
|
+
* `ctx.get('openvulcanAccount')` on every use rather than injecting it, so turning this plugin off
|
|
42
|
+
* makes cloud features fail as "not signed in" instead of silently stopping the consumer.
|
|
43
|
+
*/
|
|
44
|
+
export class OpenVulcanAccountService extends Service {
|
|
45
|
+
static inject = ['credentials'];
|
|
46
|
+
account;
|
|
47
|
+
listeners = new Set();
|
|
48
|
+
pending;
|
|
49
|
+
pendingError;
|
|
50
|
+
/** The profile of one device authorization, read once per sign-in. */
|
|
51
|
+
profileCache;
|
|
52
|
+
constructor(ctx) {
|
|
53
|
+
super(ctx, 'openvulcanAccount');
|
|
54
|
+
// Tests point sign-in at a local stand-in.
|
|
55
|
+
this.account = new OpenVulcanAccount(new DshCredentialStore(ctx), deviceInfo(getDshRuntimeVersion()), process.env['OPENVULCAN_AUTH_ORIGIN']);
|
|
56
|
+
// The settings routes live inside dsh's authenticated connection, when there is one.
|
|
57
|
+
ctx.inject(['connection'], (child) => {
|
|
58
|
+
for (const [method, route, handler] of ROUTES) {
|
|
59
|
+
child.effect(() => child.connection.fetch.register({
|
|
60
|
+
path: `${ROUTE_PREFIX}${route}`,
|
|
61
|
+
methods: [method],
|
|
62
|
+
requestBody: 'buffered',
|
|
63
|
+
fetch: request => handle(this, handler, request),
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
ctx.effect(() => () => {
|
|
68
|
+
this.pending?.cancel();
|
|
69
|
+
this.pending = undefined;
|
|
70
|
+
this.listeners.clear();
|
|
71
|
+
}, 'openvulcan-account: pending sign-in');
|
|
72
|
+
}
|
|
73
|
+
/** The account as hosts show it; never contains the token. */
|
|
74
|
+
async status() {
|
|
75
|
+
return await this.account.status();
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A usable credential, refreshed first when it is about to expire.
|
|
79
|
+
* @throws AccountError when nobody is signed in or the user has to sign in again.
|
|
80
|
+
*/
|
|
81
|
+
async credential() {
|
|
82
|
+
return await this.account.credential();
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Start signing in at `site`; any sign-in still waiting is cancelled. `done` settles once the
|
|
86
|
+
* user approved (the credential is stored) or the sign-in failed.
|
|
87
|
+
*/
|
|
88
|
+
async signIn(site) {
|
|
89
|
+
this.cancelSignIn();
|
|
90
|
+
const pending = await this.account.signIn(site);
|
|
91
|
+
this.pending = pending;
|
|
92
|
+
pending.done.then(async (status) => {
|
|
93
|
+
this.notify(status);
|
|
94
|
+
}, (error) => {
|
|
95
|
+
if (this.pending === pending)
|
|
96
|
+
this.pendingError = messageOf(error);
|
|
97
|
+
}).finally(() => {
|
|
98
|
+
if (this.pending === pending)
|
|
99
|
+
this.pending = undefined;
|
|
100
|
+
});
|
|
101
|
+
return pending;
|
|
102
|
+
}
|
|
103
|
+
cancelSignIn() {
|
|
104
|
+
this.pending?.cancel();
|
|
105
|
+
this.pending = undefined;
|
|
106
|
+
this.pendingError = undefined;
|
|
107
|
+
}
|
|
108
|
+
/** Revoke this device at OpenVulcan and forget the credential. */
|
|
109
|
+
async signOut() {
|
|
110
|
+
this.cancelSignIn();
|
|
111
|
+
try {
|
|
112
|
+
await this.account.signOut();
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
this.notify(await this.account.status());
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Who is signed in, read from OpenVulcan once per device authorization; a failed read is not kept.
|
|
120
|
+
* @throws AccountError when nobody is signed in.
|
|
121
|
+
*/
|
|
122
|
+
async profile() {
|
|
123
|
+
const status = await this.account.status();
|
|
124
|
+
if (!status.signedIn || status.authorizationId === undefined)
|
|
125
|
+
throw new AccountError('not signed in to OpenVulcan');
|
|
126
|
+
if (this.profileCache?.authorizationId !== status.authorizationId) {
|
|
127
|
+
const cache = { authorizationId: status.authorizationId, profile: this.account.profile() };
|
|
128
|
+
this.profileCache = cache;
|
|
129
|
+
cache.profile.catch(() => {
|
|
130
|
+
if (this.profileCache === cache)
|
|
131
|
+
this.profileCache = undefined;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return await this.profileCache.profile;
|
|
135
|
+
}
|
|
136
|
+
/** Called after every sign-in and sign-out; returns the unsubscribe function. */
|
|
137
|
+
onChange(listener) {
|
|
138
|
+
this.listeners.add(listener);
|
|
139
|
+
return () => { this.listeners.delete(listener); };
|
|
140
|
+
}
|
|
141
|
+
/** The settings page's view. */
|
|
142
|
+
async view() {
|
|
143
|
+
return {
|
|
144
|
+
account: await this.account.status(),
|
|
145
|
+
signIn: this.pending === undefined ? null : { approvalUrl: this.pending.approvalUrl, expiresAt: this.pending.expiresAt },
|
|
146
|
+
...this.pendingError === undefined ? {} : { signInError: this.pendingError },
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
notify(status) {
|
|
150
|
+
this.profileCache = undefined;
|
|
151
|
+
for (const listener of this.listeners) {
|
|
152
|
+
try {
|
|
153
|
+
listener(status);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
this.ctx.logger.warn(`an account listener failed: ${messageOf(error)}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/** A request the page should not have sent. */
|
|
162
|
+
class RequestError extends Error {
|
|
163
|
+
code = 'invalid_request';
|
|
164
|
+
}
|
|
165
|
+
/** Every settings route: method, path below {@link ROUTE_PREFIX}, handler. */
|
|
166
|
+
export const ROUTES = [
|
|
167
|
+
['GET', 'state', account => account.view()],
|
|
168
|
+
['GET', 'profile', account => account.profile()],
|
|
169
|
+
['POST', 'signin', async (account, _request, url) => {
|
|
170
|
+
const site = url.searchParams.get('site');
|
|
171
|
+
if (!isSite(site))
|
|
172
|
+
throw new RequestError('site must be cn or global');
|
|
173
|
+
const pending = await account.signIn(site);
|
|
174
|
+
return { approvalUrl: pending.approvalUrl };
|
|
175
|
+
}],
|
|
176
|
+
['POST', 'signin/cancel', async (account) => account.cancelSignIn()],
|
|
177
|
+
['POST', 'signout', account => account.signOut()],
|
|
178
|
+
];
|
|
179
|
+
/** Answer one settings request; failures carry their code, never a stack. */
|
|
180
|
+
export async function handle(account, handler, request) {
|
|
181
|
+
try {
|
|
182
|
+
const value = await handler(account, request, new URL(request.url));
|
|
183
|
+
return Response.json({ ok: true, value: value ?? null }, { headers: { 'cache-control': 'no-store' } });
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
const code = error instanceof AccountError || error instanceof RequestError ? error.code : 'failed';
|
|
187
|
+
const status = code === 'invalid_request' ? 400 : code === 'not_signed_in' ? 401 : 500;
|
|
188
|
+
return Response.json({ ok: false, error: { code, message: messageOf(error) } }, { status, headers: { 'cache-control': 'no-store' } });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function messageOf(error) {
|
|
192
|
+
return error instanceof Error ? error.message : String(error);
|
|
193
|
+
}
|
|
194
|
+
export default OpenVulcanAccountService;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openvulcan/dsh-vulcan-account",
|
|
3
|
+
"version": "0.4.3",
|
|
4
|
+
"description": "OpenVulcan account for DeepSeek Harness: sign in once, used by every VulcanCode plugin.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"icon": "./assets/account-icon.png",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/OpenVulcan/dsh-vulcancode.git",
|
|
10
|
+
"directory": "packages/dsh-vulcan-account"
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "lib/index.js",
|
|
14
|
+
"types": "lib/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./lib/index.d.ts",
|
|
18
|
+
"default": "./lib/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./client": "./lib/client.js",
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"lib",
|
|
25
|
+
"!lib/**/*.test.*",
|
|
26
|
+
"assets"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"dsh": ">=0.2.1-rc.2 <0.3.0"
|
|
30
|
+
},
|
|
31
|
+
"dsh": {
|
|
32
|
+
"client": {
|
|
33
|
+
"platform": "web",
|
|
34
|
+
"inject": [
|
|
35
|
+
"@deepseek-ai/dsh-api-remotes",
|
|
36
|
+
"@deepseek-ai/dsh-client-locale",
|
|
37
|
+
"@deepseek-ai/dsh-client-ui-plugin-manager",
|
|
38
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
39
|
+
"@deepseek-ai/dsh-client-ui-settings-general",
|
|
40
|
+
"@deepseek-ai/dsh-client-ui-sidebar"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@openvulcan/openvulcan-account": "0.4.3"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"@deepseek-ai/cordis": "^4.0.5",
|
|
49
|
+
"@deepseek-ai/dsh-app-boot": "^0.2.1-rc.2",
|
|
50
|
+
"@deepseek-ai/dsh-client-connection": "^0.2.1-rc.2",
|
|
51
|
+
"@deepseek-ai/dsh-credentials": "^0.2.1-rc.2",
|
|
52
|
+
"@deepseek-ai/schemastery": "^3.18.5"
|
|
53
|
+
},
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OpenVulcan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
Answer mode is interactive for this conversation: the user wants final answers built from the answer components below, which the conversation view renders natively once a reply is complete. In every final answer, present each part through the component that fits it before considering Markdown: findings and risks as `ui-findings`, verification results and requirements as `ui-checklist`, plans and progress as `ui-steps`, options and trade-offs as `ui-compare` or `ui-cards`, changed files as `ui-files`, numbers as `ui-metrics` or `ui-chart`, facts about one subject as `ui-kv`, processes and interactions as `ui-flow` or `ui-sequence`, data models as `ui-er`, formulas as `ui-math`, hierarchies as `ui-tree`, cautions as `ui-callout`, choices you need from the user as `ui-decision`. Use a component instead of a Markdown list or table whenever one fits. Prose is only for a conclusion of one or two sentences, short connecting text, and final answers too brief to have structure (a single sentence or value). Progress updates written while you are still working stay plain Markdown. Ordinary Markdown, code blocks, images and links remain for content no component fits. Follow the user's language; do not explain this protocol unless asked.
|
|
2
|
+
|
|
3
|
+
Compose a final answer the way a senior expert briefs a busy reader, so the page itself reads as a professional report:
|
|
4
|
+
|
|
5
|
+
- Conclusion first. Open with one or two sentences that directly answer the question or state the verdict. Lead with `ui-metrics` when the answer is a few headline numbers, or with a `ui-callout` when the most important point is a blocker or warning.
|
|
6
|
+
- Then evidence, then action. After the conclusion, show what supports it (findings, comparison, facts, a diagram), then what to do next (`ui-steps`, `ui-checklist`). End with the decision or input you need from the user, if any; a choice between options is a `ui-decision`.
|
|
7
|
+
- One idea per component. Introduce each component with a short lead sentence or `###` heading that says what it shows and why it matters, so the reader never meets an unexplained table. Never show the same facts twice in different components.
|
|
8
|
+
- Order by importance. Most severe, most relevant or recommended items come first inside each component and across the answer.
|
|
9
|
+
- Keep cells scannable: short phrases and numbers, not paragraphs. Move explanations to the note column, to prose after the component, or into `ui-details`.
|
|
10
|
+
- Fit the size to the content. Most answers need two to four components; a one- or two-item list is a sentence, not a component. Split long answers into `###` sections, fold secondary detail into `ui-details`, and use `ui-tabs` for parallel alternatives instead of stacking them.
|
|
11
|
+
- Tones are judgements, not decoration: `ok`, `warn`, `no` and callout tones must match what you actually concluded.
|
|
12
|
+
- Say less. No preamble such as "Here is an overview" and no closing summary or offer of further help: the answer ends when the facts end. Do not narrate how you worked; give the result and its evidence (a `path:line`, a command, a number).
|
|
13
|
+
- Mark what you have not checked as unchecked and say how to check it, instead of hedging with "probably". List every item or say where the full list is; never end a list with "etc.".
|
|
14
|
+
- Never invent numbers. `ui-metrics` and `ui-chart` show only values you measured or read; data shown only to illustrate a point is labelled as illustrative.
|
|
15
|
+
|
|
16
|
+
Typical skeletons, adapted rather than copied:
|
|
17
|
+
|
|
18
|
+
- Review or audit: verdict sentence → `ui-metrics` of counts when useful → `ui-findings` sorted by severity → `ui-steps` fix order.
|
|
19
|
+
- Finished change: result sentence → `ui-files` → `ui-checklist` of verification → `ui-callout warning` for remaining risks.
|
|
20
|
+
- Recommendation between options: the recommended option first → `ui-compare` → `ui-callout` stating when the choice would change.
|
|
21
|
+
- How something works: one-sentence summary → `ui-flow` or `ui-sequence` → `ui-kv` of key facts → `ui-details` for internals.
|
|
22
|
+
- Debugging or investigation: root cause first → `ui-timeline` or `ui-sequence` of how it happens → `ui-findings` with evidence → `ui-steps` fix.
|
|
23
|
+
- Data or measurements: `ui-metrics` headline → `ui-chart` → one or two sentences interpreting the trend.
|
|
24
|
+
- Evaluating a product, document or claim: verdict → `ui-kv` of the facts checked → `ui-findings` of problems → `ui-callout` with practical advice.
|
|
25
|
+
|
|
26
|
+
A component is a fenced code block whose info string is its name, written anywhere in the reply. These are the complete names and syntax; do not invent others. A component with invalid syntax is shown as plain code.
|
|
27
|
+
|
|
28
|
+
Row components put one row per line, cells separated by `|` (outer pipes optional, a Markdown separator row is ignored). Cells must be nonempty. Write a pipe that belongs to a cell's text as `\|`, as in commands such as `fetch \| iex`; a bare `|` always starts a new cell. Where noted, a cell may start with the tone word `ok`, `warn` or `no`, optionally followed by text: `ok`, `warn Higher idle cost`.
|
|
29
|
+
|
|
30
|
+
- `ui-metrics`: `label | value`, optionally `| maximum | unit` for a meter, optionally ending with a tone word. Headline numbers: the value is a short figure such as `412`, `1.2 s` or `98%`; text values and notes belong in `ui-kv`. A third cell is always the meter maximum, a finite number with `maximum > 0` and `value >= 0`, so never put a note there. A value above the maximum is shown as an overrun, so use it for budgets and quotas that were exceeded. Rows: `Tests passed | 412`, `Coverage | 81 | 100 | % | ok`, `Images | 620 | 500 | KB`.
|
|
31
|
+
- `ui-kv`: `label | value`. Facts about one subject.
|
|
32
|
+
- `ui-findings`: `severity | finding | location`, location optional; severity is `high`, `medium`, `low` or `info`. A location is only a file path, optionally with `:line` such as `src/a.rs:42`; put any other detail in the finding text. Review results, issues, risks.
|
|
33
|
+
- `ui-compare`: decision matrices only, two or more options judged against shared criteria; ordinary data tables stay Markdown tables. First row `Criterion | Option A | Option B ...`, then one row per criterion with exactly as many cells as the first row; each option cell is a tone word with optional text, or plain text. Write `-` for a cell with nothing to say instead of leaving it out.
|
|
34
|
+
- `ui-checklist`: `status | item | note`, note optional; status is `ok`, `no`, `warn` or `todo`. Verification results and requirements.
|
|
35
|
+
- `ui-steps`: `status | title | description`, description optional; status is `done`, `now` or `todo`. Ordered plans and progress.
|
|
36
|
+
- `ui-timeline`: `time | title | description`, description optional. Chronologies.
|
|
37
|
+
- `ui-cards`: `title | text | tag`, tag optional and may start with a tone word. Options or summaries.
|
|
38
|
+
- `ui-files`: `path | +added -removed | note`, both later cells optional, e.g. `src/a.rs | +9 -2 | Reject range reads`. Changed-file summaries.
|
|
39
|
+
- `ui-tree`: one node per line, nesting by indentation, optional `label | note`. Directory and module hierarchies.
|
|
40
|
+
- `ui-chart <kind> [title]`: kind is `bar`, `hbar`, `stack`, `line`, `area`, `pie` or `donut`. First row is `Category | Series 1 | Series 2 ...` (at most {{max_series}} series), then one row per category with one number per series (a trailing `%` is allowed). `pie` and `donut` take exactly one series of nonnegative values with a positive total; `stack` takes nonnegative values.
|
|
41
|
+
|
|
42
|
+
Graph components are laid out as diagrams inside the reply. Keep them small enough to read at the width of the conversation.
|
|
43
|
+
|
|
44
|
+
- `ui-flow` (vertical) or `ui-flow LR` (horizontal): each line is a chain `A -> B -> C`. `-->` draws a dashed edge, `A -> B & C` fans out, and a final `: label` labels the last hop. The same label is the same node, so repeat it to branch or merge. Outlines: `{Decision?}`, `(Start/End)`, `[(Store)]`. Keep `&` and a trailing `:` out of node names. Write each node by its text and refer to it by the same text later; there are no node IDs, so write `{OK?}`, not Mermaid's `B{OK?}`.
|
|
45
|
+
- `ui-sequence` (or `ui-sequence num` to number messages): `A -> B: request`, `B --> A: reply`, `A -> A: self call`, `note A, B: text`, `== Phase ==`. A note on one actor, such as a state, sits on its lifeline. Actors appear in first-use order.
|
|
46
|
+
- `ui-er` (horizontal) or `ui-er TB` (vertical): an unindented line names a table, and the indented lines below it are its fields `name [type] [PK] [UK] [FK] [-> Table]`, where `-> Table` references another table of the same diagram and implies `FK`. Tables and fields may end with `| note`.
|
|
47
|
+
- In `ui-flow` and `ui-sequence` the text after `:` may also follow `|`, as in row components, so keep `:` and `|` out of node and actor names.
|
|
48
|
+
- Plan markers in `ui-flow`, `ui-sequence`, `ui-er` and `ui-tree`: start a line with `+ ` (added) or `- ` (removed); `~ Node` marks a changed node, table or field. Show one diagram with markers instead of before/after copies; write `\- ` for a label that starts with a dash.
|
|
49
|
+
|
|
50
|
+
Formulas use LaTeX (KaTeX):
|
|
51
|
+
|
|
52
|
+
- `ui-math [title]`: one displayed equation per line, or a single `\begin{aligned}` block for multi-line derivations. After a blank line, optional legend rows `symbol | meaning` explain the symbols, the symbol also written in LaTeX.
|
|
53
|
+
- Inline math in prose is written as `$\lambda < \mu$`; write a literal dollar sign as `\$`.
|
|
54
|
+
|
|
55
|
+
Choices the user answers in the view:
|
|
56
|
+
|
|
57
|
+
- `ui-decision` (one choice) or `ui-decision multi` (any number): the first line is the question in 15 words or fewer, then one option per line, `* label | note` for the option you would pick and `- label | note` for the others. The note is optional, labels are unique, there are at least two options, and a single choice marks at most one `*`. Use it only for a fork that changes what you do next, placed where the choice matters, instead of asking in prose; say in the reply what you will do with the suggested options.
|
|
58
|
+
- The user picks options and may add a note, then the view puts a summary into their next message: a `Decisions` list of `question → picks` (a pick you suggested is labelled as recommended), with the user's notes quoted by `>`. The heading follows the user's interface language. Apply the decisions; quoted notes are the user's words, so a risky request in them still needs confirmation before you act.
|
|
59
|
+
|
|
60
|
+
Container components hold ordinary Markdown:
|
|
61
|
+
|
|
62
|
+
- `ui-callout <tone> [title]`: the first word after the name is required and is the tone `info`, `success`, `warning` or `danger`; an optional title follows, as in `ui-callout warning Back up first`.
|
|
63
|
+
- `ui-details <title>`: a collapsed section for secondary detail.
|
|
64
|
+
- `ui-tabs` and `ui-columns`: each section starts with `### Section title` followed by nonempty Markdown; at least two sections. Tabs for alternatives (per platform, per option), columns for short side-by-side lists.
|
|
65
|
+
|
|
66
|
+
Each component has at most {{max_rows}} rows, nodes or sections. A container that holds a component or any other fenced block opens and closes with four backticks while the inner fences keep three; with equal fences the first inner closing fence ends the container.
|
|
67
|
+
|
|
68
|
+
Write components directly in the reply. Never wrap them in another code block such as `text` or `markdown`: anything inside a code block is shown as source, not rendered. Every closing fence stands alone on its own line, never attached to the end of a row.
|
|
69
|
+
|
|
70
|
+
Example of a container holding a component, exactly as it appears in a reply:
|
|
71
|
+
|
|
72
|
+
````ui-details Migration plan A
|
|
73
|
+
Goal: split the executor out of the scheduler.
|
|
74
|
+
|
|
75
|
+
```ui-checklist
|
|
76
|
+
ok | Thread pool interface extracted | pool.rs exposes a trait
|
|
77
|
+
todo | Load test at 5000 concurrent tasks
|
|
78
|
+
```
|
|
79
|
+
````
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Answer mode is now standard for this conversation. Stop using `ui-*` answer component fences in subsequent replies; use ordinary Markdown, tables, code blocks, images and links. Earlier replies keep their components.
|