@cortexkit/anthropic-auth-core 1.23.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/accounts.d.ts +3 -16
- package/dist/cachekeep.d.ts +9 -0
- package/dist/claude-code.d.ts +16 -0
- package/dist/claustrum-enrollment.d.ts +2 -0
- package/dist/claustrum-scoped-roster.d.ts +4 -0
- package/dist/claustrum-scoped-runtime.d.ts +3 -0
- package/dist/claustrum-scoped.d.ts +14 -0
- package/dist/claustrum.d.ts +0 -209
- package/dist/commands/account.d.ts +2 -3
- package/dist/index.d.ts +44 -1
- package/dist/index.js +29700 -38
- package/dist/internal-types/LICENSE +21 -0
- package/dist/internal-types/commands/builtins.d.ts +71 -0
- package/dist/internal-types/commands/index.d.ts +10 -0
- package/dist/internal-types/commands/menu.d.ts +61 -0
- package/dist/internal-types/commands/model.d.ts +238 -0
- package/dist/internal-types/commands/pi.d.ts +23 -0
- package/dist/internal-types/commands/seam.d.ts +72 -0
- package/dist/internal-types/fs/refresh-file-lock.d.ts +33 -0
- package/dist/internal-types/logger/capture-sink.d.ts +14 -0
- package/dist/internal-types/logger/engine.d.ts +100 -0
- package/dist/internal-types/logger/index.d.ts +6 -0
- package/dist/internal-types/logger/redact.d.ts +11 -0
- package/dist/internal-types/pi-slot/index.d.ts +3 -0
- package/dist/internal-types/pi-slot/slot.d.ts +49 -0
- package/dist/internal-types/quota/codec.d.ts +11 -0
- package/dist/internal-types/quota/format.d.ts +46 -0
- package/dist/internal-types/quota/index.d.ts +10 -0
- package/dist/internal-types/quota/map.d.ts +63 -0
- package/dist/internal-types/quota/merge.d.ts +48 -0
- package/dist/internal-types/quota/projection.d.ts +64 -0
- package/dist/internal-types/store/attribution.d.ts +28 -0
- package/dist/internal-types/store/errors.d.ts +55 -0
- package/dist/internal-types/store/hooks.d.ts +12 -0
- package/dist/internal-types/store/identity.d.ts +39 -0
- package/dist/internal-types/store/index.d.ts +21 -0
- package/dist/internal-types/store/mutate.d.ts +189 -0
- package/dist/internal-types/store/pool.d.ts +196 -0
- package/dist/internal-types/store/provider-state.d.ts +131 -0
- package/dist/internal-types/store/publication.d.ts +47 -0
- package/dist/internal-types/store/pull.d.ts +36 -0
- package/dist/internal-types/store/refresh-lock.d.ts +63 -0
- package/dist/internal-types/store/refresh.d.ts +72 -0
- package/dist/internal-types/store/rows.d.ts +313 -0
- package/dist/internal-types/store/runtime.d.ts +36 -0
- package/dist/internal-types/store/schema.d.ts +443 -0
- package/dist/internal-types/store/settings.d.ts +63 -0
- package/dist/internal-types/store/torn.d.ts +78 -0
- package/dist/migration-source.d.ts +33 -0
- package/dist/models.d.ts +41 -0
- package/dist/native-account-runtime.d.ts +121 -0
- package/dist/native-account-view.d.ts +126 -0
- package/dist/native-command-effects.d.ts +59 -0
- package/dist/native-credential-validation.d.ts +42 -0
- package/dist/native-custody-activation.d.ts +45 -0
- package/dist/native-custody.d.ts +114 -0
- package/dist/native-enrollment-authority.d.ts +2 -0
- package/dist/native-host-auth-read.d.ts +3 -0
- package/dist/native-host-auth-write.d.ts +51 -0
- package/dist/native-host-auth.d.ts +12 -0
- package/dist/native-local-credential-service.d.ts +76 -0
- package/dist/native-local-runtime-readers.d.ts +22 -0
- package/dist/native-lock-observer.d.ts +12 -0
- package/dist/native-menu-executor.d.ts +243 -0
- package/dist/native-menu-model.d.ts +142 -0
- package/dist/native-migration-proof.d.ts +28 -0
- package/dist/native-migration-source.d.ts +47 -0
- package/dist/native-migration.d.ts +66 -0
- package/dist/native-quota-codec.d.ts +32 -0
- package/dist/native-refresh-coordinator.d.ts +240 -0
- package/dist/native-roster-seed.d.ts +115 -0
- package/dist/native-runtime-registry.d.ts +19 -0
- package/dist/native-runtime.d.ts +204 -0
- package/dist/native-transient-account.d.ts +38 -0
- package/dist/native-ui.d.ts +45 -0
- package/dist/native-usage-publication.d.ts +11 -0
- package/dist/native-vault-admission.d.ts +8 -0
- package/dist/native-vault-connection.d.ts +33 -0
- package/dist/native-vault-paths.d.ts +13 -0
- package/dist/native-vault-runtime.d.ts +102 -0
- package/dist/native-vault-seed.d.ts +16 -0
- package/dist/pool-authority.d.ts +159 -0
- package/dist/pool-binding.d.ts +32 -0
- package/dist/pool-paths.d.ts +21 -0
- package/dist/pool-store.d.ts +32 -0
- package/dist/provider-error.d.ts +139 -0
- package/dist/quota-manager.d.ts +18 -7
- package/dist/relay.d.ts +14 -1
- package/dist/request-history.d.ts +34 -0
- package/dist/sse.d.ts +81 -0
- package/dist/sticky-routing.d.ts +27 -0
- package/package.json +9 -4
- package/dist/accounts.js +0 -3881
- package/dist/auth.js +0 -185
- package/dist/cache1h.js +0 -97
- package/dist/cachekeep-registry.js +0 -124
- package/dist/cachekeep.js +0 -604
- package/dist/cch.js +0 -172
- package/dist/claude-code.js +0 -403
- package/dist/claustrum-enrollment-registry.d.ts +0 -17
- package/dist/claustrum-enrollment-registry.js +0 -194
- package/dist/claustrum-enrollment.js +0 -485
- package/dist/claustrum-scoped-roster.js +0 -194
- package/dist/claustrum-scoped-runtime.js +0 -230
- package/dist/claustrum-scoped.js +0 -193
- package/dist/claustrum.js +0 -1471
- package/dist/commands/account.js +0 -368
- package/dist/constants.js +0 -83
- package/dist/custom-headers.js +0 -102
- package/dist/dump.js +0 -616
- package/dist/fast.js +0 -66
- package/dist/json.js +0 -10
- package/dist/killswitch.js +0 -132
- package/dist/logger.js +0 -288
- package/dist/logging.js +0 -59
- package/dist/mid-conversation-output-config.js +0 -89
- package/dist/model-remap.js +0 -72
- package/dist/models.js +0 -177
- package/dist/network-errors.js +0 -27
- package/dist/oauth-profile.js +0 -60
- package/dist/pkce.js +0 -17
- package/dist/prime.js +0 -841
- package/dist/provider.js +0 -0
- package/dist/quota-header-feed.js +0 -331
- package/dist/quota-headers.js +0 -121
- package/dist/quota-manager.js +0 -856
- package/dist/quotas.js +0 -141
- package/dist/relay.js +0 -1303
- package/dist/routing.js +0 -94
- package/dist/start.js +0 -29
- package/dist/sticky-routing.js +0 -541
- package/dist/thinking-binding.js +0 -54
- package/dist/token-fingerprint.js +0 -8
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ex Machina
|
|
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,71 @@
|
|
|
1
|
+
import type { AddInput, PoolLockSpec, PoolRow, PoolStore, RemoveOptions } from '../store/index.js';
|
|
2
|
+
import type { CommandInvocation, KnobValues, MenuChoice, MenuKnob } from './model.js';
|
|
3
|
+
import { type ResolvedSection } from './seam.js';
|
|
4
|
+
/**
|
|
5
|
+
* What a plugin's login hands back. `ready` adds the account now. `pending`
|
|
6
|
+
* means the user must finish somewhere else (a browser, a device code):
|
|
7
|
+
* `message` tells them how, and the account is added when `completion`
|
|
8
|
+
* settles, with the result sent to the invocation that started it.
|
|
9
|
+
*/
|
|
10
|
+
export type LoginOutcome = {
|
|
11
|
+
status: 'ready';
|
|
12
|
+
account: AddInput;
|
|
13
|
+
} | {
|
|
14
|
+
status: 'pending';
|
|
15
|
+
message: string;
|
|
16
|
+
/** Resolves with the account to add, or undefined when the user gave up. */
|
|
17
|
+
completion: Promise<AddInput | undefined>;
|
|
18
|
+
} | {
|
|
19
|
+
status: 'cancelled';
|
|
20
|
+
message?: string;
|
|
21
|
+
};
|
|
22
|
+
export interface AccountsSectionOptions {
|
|
23
|
+
/** What to show as an account's identity; defaults to its recorded identity. */
|
|
24
|
+
describeIdentity?(row: PoolRow): string | undefined;
|
|
25
|
+
/** The plugin's login; without it the section offers no add action. */
|
|
26
|
+
login?: {
|
|
27
|
+
label?: string;
|
|
28
|
+
knobs?: MenuKnob[];
|
|
29
|
+
run(values: KnobValues, invocation: CommandInvocation): Promise<LoginOutcome>;
|
|
30
|
+
};
|
|
31
|
+
/** Passed to `store.remove`: a reason refuses removing that id. */
|
|
32
|
+
protect?: RemoveOptions['protect'];
|
|
33
|
+
}
|
|
34
|
+
export interface QuotaSectionOptions {
|
|
35
|
+
/** The quota scope to show (`all` or a model family); defaults to `all`. */
|
|
36
|
+
scope?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Checks quota now for the named rows. Without it, the menu asks the store
|
|
39
|
+
* for a reading of each row and waits for the pulls to settle.
|
|
40
|
+
*/
|
|
41
|
+
check?(ids: readonly string[], invocation: CommandInvocation): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
export interface RoutingSectionOptions {
|
|
44
|
+
/**
|
|
45
|
+
* Further `routing.mode` values the plugin routes as `ordered` with the
|
|
46
|
+
* former main row moved (`main-first`, `fallback-first`), offered between
|
|
47
|
+
* `ordered` and `sticky-balanced`.
|
|
48
|
+
*/
|
|
49
|
+
orderedVariants?: MenuChoice[];
|
|
50
|
+
formerMainId?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface LimitsSectionOptions {
|
|
53
|
+
/**
|
|
54
|
+
* The quota window labels a floor can be set for. Defaults to every label
|
|
55
|
+
* the pool's quota readings carry, or `primary` when there are none.
|
|
56
|
+
*/
|
|
57
|
+
labels?: readonly string[];
|
|
58
|
+
}
|
|
59
|
+
export interface BuiltinOptions {
|
|
60
|
+
store: PoolStore;
|
|
61
|
+
extraLocks?: readonly PoolLockSpec[];
|
|
62
|
+
now: () => number;
|
|
63
|
+
accounts?: AccountsSectionOptions;
|
|
64
|
+
quota?: QuotaSectionOptions;
|
|
65
|
+
routing?: RoutingSectionOptions;
|
|
66
|
+
limits?: LimitsSectionOptions;
|
|
67
|
+
}
|
|
68
|
+
/** `disabledReason` recorded when the user disables an account from the menu. */
|
|
69
|
+
export declare const MENU_DISABLED_REASON = "disabled from the command menu";
|
|
70
|
+
/** The four built-in sections, in their fixed order, from one read of the store. */
|
|
71
|
+
export declare function builtinSections(options: BuiltinOptions): Promise<ResolvedSection[]>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type { AccountsSectionOptions, LimitsSectionOptions, LoginOutcome, QuotaSectionOptions, RoutingSectionOptions, } from './builtins.js';
|
|
2
|
+
export { MENU_DISABLED_REASON } from './builtins.js';
|
|
3
|
+
export type { CommandMenu, CommandMenuOptions, StoreSectionSlot, } from './menu.js';
|
|
4
|
+
export { createCommandMenu, parseApplyRequest } from './menu.js';
|
|
5
|
+
export type { ActionDefinition, ActionInput, ActionOutcome, CommandApplyRequest, CommandApplyResult, CommandDialogPayload, CommandInvocation, CommandMenuModel, ItemDefinition, KnobValue, KnobValues, MenuAccount, MenuAction, MenuChoice, MenuConfirmation, MenuItem, MenuKnob, MenuSection, NotifyKind, PluginExtraSection, PluginSection, SectionContent, SectionSlot, } from './model.js';
|
|
6
|
+
export { SECTION_SLOTS } from './model.js';
|
|
7
|
+
export type { PiMenuOptions, PiMenuUi } from './pi.js';
|
|
8
|
+
export { runPiCommandMenu } from './pi.js';
|
|
9
|
+
export type { ProjectedFailure, SeamLogger, TextRedactor } from './seam.js';
|
|
10
|
+
export { ACTION_FAILED, CommandError, createTextRedactor, DEFAULT_IRREVERSIBLE_CONFIRMATION, projectFailure, } from './seam.js';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type RedactionOptions } from '../logger/index.js';
|
|
2
|
+
import type { PoolLockSpec, PoolStore } from '../store/index.js';
|
|
3
|
+
import { type AccountsSectionOptions, type LimitsSectionOptions, type QuotaSectionOptions, type RoutingSectionOptions } from './builtins.js';
|
|
4
|
+
import type { CommandApplyRequest, CommandApplyResult, CommandDialogPayload, CommandInvocation, PluginExtraSection, PluginSection } from './model.js';
|
|
5
|
+
import { type SeamLogger } from './seam.js';
|
|
6
|
+
/** The four slots the library can build from a pool store. */
|
|
7
|
+
export type StoreSectionSlot = 'accounts' | 'quota' | 'routing' | 'limits';
|
|
8
|
+
export interface CommandMenuOptions {
|
|
9
|
+
/** The slash command's name without the slash (`openai`, `claude`). */
|
|
10
|
+
command: string;
|
|
11
|
+
/** The dialog title. */
|
|
12
|
+
title: string;
|
|
13
|
+
/**
|
|
14
|
+
* The pool store the built-in Accounts, Quota, Routing and Limits sections
|
|
15
|
+
* read and write. Required unless `replace` supplies all four.
|
|
16
|
+
*/
|
|
17
|
+
store?: PoolStore;
|
|
18
|
+
/**
|
|
19
|
+
* Plugin sections that take the place of built-in ones, keeping their slot
|
|
20
|
+
* and the fixed order. For a plugin whose accounts are not pool rows (a
|
|
21
|
+
* single host login, or rows it must not expose by id), so it renders its
|
|
22
|
+
* own items and actions without a store. A replaced slot's built-in
|
|
23
|
+
* options (`accounts`, `quota`, ...) must not be given.
|
|
24
|
+
*/
|
|
25
|
+
replace?: Partial<Record<StoreSectionSlot, PluginSection>>;
|
|
26
|
+
/** The plugin's legacy locks, passed to every store write the menu makes. */
|
|
27
|
+
extraLocks?: readonly PoolLockSpec[];
|
|
28
|
+
accounts?: AccountsSectionOptions;
|
|
29
|
+
quota?: QuotaSectionOptions;
|
|
30
|
+
routing?: RoutingSectionOptions;
|
|
31
|
+
limits?: LimitsSectionOptions;
|
|
32
|
+
/** The Cache section; omitted when the plugin has none. */
|
|
33
|
+
cache?: PluginSection;
|
|
34
|
+
/** The Diagnostics section (dumps, logging); omitted when the plugin has none. */
|
|
35
|
+
diagnostics?: PluginSection;
|
|
36
|
+
/** Provider extras, shown after every fixed section in this order. */
|
|
37
|
+
extras?: readonly PluginExtraSection[];
|
|
38
|
+
/** Receives the seam's warnings and failed actions; defaults to the library logger. */
|
|
39
|
+
logger?: SeamLogger;
|
|
40
|
+
/**
|
|
41
|
+
* The provider's secret shapes, added to the redactor every string that
|
|
42
|
+
* leaves the menu goes through (payloads and notifications). Without a
|
|
43
|
+
* pattern for its key format, a plugin's API key quoted in an outcome's
|
|
44
|
+
* text is not recognised.
|
|
45
|
+
*/
|
|
46
|
+
redaction?: RedactionOptions;
|
|
47
|
+
now?: () => number;
|
|
48
|
+
}
|
|
49
|
+
export interface CommandMenu {
|
|
50
|
+
readonly command: string;
|
|
51
|
+
/** The dialog payload for one invocation of the slash command. */
|
|
52
|
+
open(invocation: CommandInvocation): Promise<CommandDialogPayload>;
|
|
53
|
+
/** Applies one action and returns its message and the refreshed menu. */
|
|
54
|
+
apply(request: CommandApplyRequest, invocation: CommandInvocation): Promise<CommandApplyResult>;
|
|
55
|
+
}
|
|
56
|
+
export declare function createCommandMenu(options: CommandMenuOptions): CommandMenu;
|
|
57
|
+
/**
|
|
58
|
+
* Checks an apply request that arrived over the loopback RPC; undefined when
|
|
59
|
+
* it is not one. Only the request's own fields are kept.
|
|
60
|
+
*/
|
|
61
|
+
export declare function parseApplyRequest(value: unknown): CommandApplyRequest | undefined;
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/** The section slots, in the one order every renderer shows them. */
|
|
2
|
+
export declare const SECTION_SLOTS: readonly ['accounts', 'quota', 'routing', 'limits', 'cache', 'diagnostics', 'extra'];
|
|
3
|
+
export type SectionSlot = (typeof SECTION_SLOTS)[number];
|
|
4
|
+
/** One choice of a `choice` input. */
|
|
5
|
+
export interface MenuChoice {
|
|
6
|
+
value: string;
|
|
7
|
+
label: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A typed input an action collects before it runs. `value` is the current
|
|
11
|
+
* setting, shown as the default. A `number` or `text` input that is not
|
|
12
|
+
* `required` may be left empty, which the action receives as `null`.
|
|
13
|
+
*/
|
|
14
|
+
export type MenuKnob = {
|
|
15
|
+
kind: 'choice';
|
|
16
|
+
id: string;
|
|
17
|
+
label: string;
|
|
18
|
+
choices: MenuChoice[];
|
|
19
|
+
value?: string;
|
|
20
|
+
} | {
|
|
21
|
+
kind: 'toggle';
|
|
22
|
+
id: string;
|
|
23
|
+
label: string;
|
|
24
|
+
value: boolean;
|
|
25
|
+
} | {
|
|
26
|
+
kind: 'number';
|
|
27
|
+
id: string;
|
|
28
|
+
label: string;
|
|
29
|
+
value?: number;
|
|
30
|
+
min?: number;
|
|
31
|
+
max?: number;
|
|
32
|
+
required?: boolean;
|
|
33
|
+
} | {
|
|
34
|
+
kind: 'text';
|
|
35
|
+
id: string;
|
|
36
|
+
label: string;
|
|
37
|
+
value?: string;
|
|
38
|
+
placeholder?: string;
|
|
39
|
+
/** Hide what is typed (a pasted secret, for example). */
|
|
40
|
+
masked?: boolean;
|
|
41
|
+
required?: boolean;
|
|
42
|
+
};
|
|
43
|
+
export type KnobValue = string | number | boolean | null;
|
|
44
|
+
export type KnobValues = Readonly<Record<string, KnobValue>>;
|
|
45
|
+
export interface MenuConfirmation {
|
|
46
|
+
message: string;
|
|
47
|
+
/** Irreversible actions always carry a confirmation. */
|
|
48
|
+
irreversible: boolean;
|
|
49
|
+
}
|
|
50
|
+
export interface MenuAction {
|
|
51
|
+
id: string;
|
|
52
|
+
label: string;
|
|
53
|
+
description?: string;
|
|
54
|
+
/**
|
|
55
|
+
* The header a section-level action is listed under (`Actions`). See
|
|
56
|
+
* `MenuSection` for how renderers draw groups.
|
|
57
|
+
*/
|
|
58
|
+
group?: string;
|
|
59
|
+
knobs: MenuKnob[];
|
|
60
|
+
/** Present when the action must be confirmed before it is applied. */
|
|
61
|
+
confirm?: MenuConfirmation;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The account fields a renderer may show, and nothing else: an account is
|
|
65
|
+
* always projected field by field, never spread, so a credential the store
|
|
66
|
+
* row carries cannot reach a payload.
|
|
67
|
+
*/
|
|
68
|
+
export interface MenuAccount {
|
|
69
|
+
id: string;
|
|
70
|
+
label?: string;
|
|
71
|
+
enabled: boolean;
|
|
72
|
+
type: 'oauth' | 'api';
|
|
73
|
+
/** What the plugin chose to show for the account's identity. */
|
|
74
|
+
identity?: string;
|
|
75
|
+
}
|
|
76
|
+
export interface MenuItem {
|
|
77
|
+
id: string;
|
|
78
|
+
label: string;
|
|
79
|
+
detail?: string;
|
|
80
|
+
/** The header the item is listed under (`Accounts`); see `MenuSection`. */
|
|
81
|
+
group?: string;
|
|
82
|
+
/**
|
|
83
|
+
* A short value shown right-aligned beside the label (`enabled`,
|
|
84
|
+
* `5h 58% left`): an OpenCode dialog option's `footer`.
|
|
85
|
+
*/
|
|
86
|
+
status?: string;
|
|
87
|
+
account?: MenuAccount;
|
|
88
|
+
/**
|
|
89
|
+
* Extra name/value pairs a drawer may list under the item. Plugin data
|
|
90
|
+
* passes through here, so it is scrubbed of credential-shaped names.
|
|
91
|
+
*/
|
|
92
|
+
facts?: Record<string, unknown>;
|
|
93
|
+
actions: MenuAction[];
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* One section of the menu. How every renderer draws it:
|
|
97
|
+
*
|
|
98
|
+
* - Every option a renderer shows can be selected and does something: it is
|
|
99
|
+
* an item with at least one action, or a section-level action. Text that
|
|
100
|
+
* does nothing is never an option; it is a group header or a line.
|
|
101
|
+
* - `lines` are read-only text. On OpenCode they are drawn as header text
|
|
102
|
+
* (a `category`) above the first group; on Pi they are part of the select
|
|
103
|
+
* title.
|
|
104
|
+
* - The options are the items, then the section-level actions, in that
|
|
105
|
+
* order. When an option's `group` differs from the previous one's, a
|
|
106
|
+
* header naming the group is drawn first. A header is never selectable
|
|
107
|
+
* (on OpenCode it is the option's `category`).
|
|
108
|
+
* - An item's `status` is drawn right-aligned beside its label (on
|
|
109
|
+
* OpenCode, `footer`); its `detail` and an action's `description` are
|
|
110
|
+
* the secondary text (`description`).
|
|
111
|
+
*
|
|
112
|
+
* The built-in sections never emit an item without actions, and a plugin
|
|
113
|
+
* section should not either. A renderer that meets one must not offer it as
|
|
114
|
+
* an option: on OpenCode a `disabled` option is hidden altogether, so the
|
|
115
|
+
* item is written as header text instead, and Pi writes it into the title.
|
|
116
|
+
*/
|
|
117
|
+
export interface MenuSection {
|
|
118
|
+
id: string;
|
|
119
|
+
slot: SectionSlot;
|
|
120
|
+
title: string;
|
|
121
|
+
/** Read-only text shown above the rows; never a selectable option. */
|
|
122
|
+
lines: string[];
|
|
123
|
+
items: MenuItem[];
|
|
124
|
+
actions: MenuAction[];
|
|
125
|
+
facts?: Record<string, unknown>;
|
|
126
|
+
}
|
|
127
|
+
export interface CommandMenuModel {
|
|
128
|
+
/** The slash command's name, without the slash. */
|
|
129
|
+
command: string;
|
|
130
|
+
title: string;
|
|
131
|
+
sections: MenuSection[];
|
|
132
|
+
}
|
|
133
|
+
/** What a host's TUI receives when the slash command opens the dialog. */
|
|
134
|
+
export interface CommandDialogPayload {
|
|
135
|
+
command: string;
|
|
136
|
+
menu: CommandMenuModel;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* One applied action, as a renderer sends it back. `itemId` names the item
|
|
140
|
+
* the action sits on; absent for a section-level action.
|
|
141
|
+
*/
|
|
142
|
+
export interface CommandApplyRequest {
|
|
143
|
+
command: string;
|
|
144
|
+
sectionId: string;
|
|
145
|
+
itemId?: string;
|
|
146
|
+
actionId: string;
|
|
147
|
+
values?: KnobValues;
|
|
148
|
+
/** True once the user confirmed an action that carries a confirmation. */
|
|
149
|
+
confirmed?: boolean;
|
|
150
|
+
sessionId?: string;
|
|
151
|
+
}
|
|
152
|
+
/** The outcome of an apply: a message for the user and the refreshed menu. */
|
|
153
|
+
export interface CommandApplyResult {
|
|
154
|
+
command: string;
|
|
155
|
+
ok: boolean;
|
|
156
|
+
text: string;
|
|
157
|
+
/**
|
|
158
|
+
* A stable code naming why the apply failed; present on every failure.
|
|
159
|
+
* The library's own codes are `unavailable`, `needs-confirmation`,
|
|
160
|
+
* `invalid-input`, `refused`, `action-failed` and `pool-<store failure
|
|
161
|
+
* kind>`; a plugin's `CommandError` or `ActionOutcome` names its own.
|
|
162
|
+
*/
|
|
163
|
+
code?: string;
|
|
164
|
+
/** True when the action was refused only for want of a confirmation. */
|
|
165
|
+
needsConfirmation?: boolean;
|
|
166
|
+
menu: CommandMenuModel;
|
|
167
|
+
}
|
|
168
|
+
export type NotifyKind = 'info' | 'warning' | 'error';
|
|
169
|
+
/**
|
|
170
|
+
* The per-invocation context of one slash-command call. The library reads
|
|
171
|
+
* both fields once, when the call starts, and keeps that copy for any work
|
|
172
|
+
* the call leaves running (a login completing later, for example), so a host
|
|
173
|
+
* that reuses one context object across sessions cannot reroute feedback.
|
|
174
|
+
*/
|
|
175
|
+
export interface CommandInvocation {
|
|
176
|
+
sessionId?: string;
|
|
177
|
+
notify(message: string, kind?: NotifyKind): void;
|
|
178
|
+
}
|
|
179
|
+
export interface ActionOutcome {
|
|
180
|
+
ok: boolean;
|
|
181
|
+
text: string;
|
|
182
|
+
/** The failure's stable code; a failure without one is `refused`. */
|
|
183
|
+
code?: string;
|
|
184
|
+
}
|
|
185
|
+
export interface ActionInput {
|
|
186
|
+
values: KnobValues;
|
|
187
|
+
/** The item the action sits on; absent for a section-level action. */
|
|
188
|
+
itemId?: string;
|
|
189
|
+
invocation: CommandInvocation;
|
|
190
|
+
}
|
|
191
|
+
type ActionBase = {
|
|
192
|
+
id: string;
|
|
193
|
+
label: string;
|
|
194
|
+
description?: string;
|
|
195
|
+
/** The header a section-level action is listed under; see `MenuSection`. */
|
|
196
|
+
group?: string;
|
|
197
|
+
knobs?: MenuKnob[];
|
|
198
|
+
run(input: ActionInput): Promise<string | ActionOutcome>;
|
|
199
|
+
};
|
|
200
|
+
/**
|
|
201
|
+
* An action and its body. An irreversible action must name its
|
|
202
|
+
* confirmation; a reversible one may.
|
|
203
|
+
*/
|
|
204
|
+
export type ActionDefinition = ActionBase & ({
|
|
205
|
+
irreversible: true;
|
|
206
|
+
confirm: string;
|
|
207
|
+
} | {
|
|
208
|
+
irreversible?: false;
|
|
209
|
+
confirm?: string;
|
|
210
|
+
});
|
|
211
|
+
export interface ItemDefinition {
|
|
212
|
+
id: string;
|
|
213
|
+
label: string;
|
|
214
|
+
detail?: string;
|
|
215
|
+
/** The header the item is listed under; see `MenuSection`. */
|
|
216
|
+
group?: string;
|
|
217
|
+
/** A short value shown right-aligned beside the label. */
|
|
218
|
+
status?: string;
|
|
219
|
+
facts?: Record<string, unknown>;
|
|
220
|
+
actions?: ActionDefinition[];
|
|
221
|
+
}
|
|
222
|
+
export interface SectionContent {
|
|
223
|
+
/** Read-only text; renderers never make a line selectable. */
|
|
224
|
+
lines?: string[];
|
|
225
|
+
items?: ItemDefinition[];
|
|
226
|
+
actions?: ActionDefinition[];
|
|
227
|
+
facts?: Record<string, unknown>;
|
|
228
|
+
}
|
|
229
|
+
/** A section a plugin supplies for one of its slots. */
|
|
230
|
+
export interface PluginSection {
|
|
231
|
+
title: string;
|
|
232
|
+
build(invocation: CommandInvocation): SectionContent | Promise<SectionContent>;
|
|
233
|
+
}
|
|
234
|
+
/** A provider extra: a plugin section shown after the fixed slots. */
|
|
235
|
+
export interface PluginExtraSection extends PluginSection {
|
|
236
|
+
id: string;
|
|
237
|
+
}
|
|
238
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CommandMenu } from './menu.js';
|
|
2
|
+
import type { NotifyKind } from './model.js';
|
|
3
|
+
/**
|
|
4
|
+
* The part of Pi's `ExtensionUIContext` the renderer uses. `select` and
|
|
5
|
+
* `input` resolve undefined when the user backs out.
|
|
6
|
+
*/
|
|
7
|
+
export interface PiMenuUi {
|
|
8
|
+
select(title: string, options: string[]): Promise<string | undefined>;
|
|
9
|
+
confirm(title: string, message: string): Promise<boolean>;
|
|
10
|
+
input(title: string, placeholder?: string): Promise<string | undefined>;
|
|
11
|
+
notify(message: string, type?: NotifyKind): void;
|
|
12
|
+
}
|
|
13
|
+
export interface PiMenuOptions {
|
|
14
|
+
sessionId?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Runs one invocation of the slash command on Pi: sections, then an item or
|
|
18
|
+
* a section action, then the action's inputs and confirmation; after each
|
|
19
|
+
* apply the user is back in the same section with the refreshed menu. Each
|
|
20
|
+
* section's list ends with Back, which returns to the section list; backing
|
|
21
|
+
* out of the section list ends the invocation.
|
|
22
|
+
*/
|
|
23
|
+
export declare function runPiCommandMenu(menu: CommandMenu, ui: PiMenuUi, options?: PiMenuOptions): Promise<void>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { type RedactionOptions } from '../logger/index.js';
|
|
2
|
+
import type { ActionDefinition, CommandApplyResult, CommandDialogPayload, ItemDefinition, MenuAccount, MenuConfirmation, SectionContent, SectionSlot } from './model.js';
|
|
3
|
+
/** Where a dropped field is reported. Names only, never values. */
|
|
4
|
+
export interface SeamLogger {
|
|
5
|
+
warn(message: string, data?: unknown): void;
|
|
6
|
+
}
|
|
7
|
+
/** Masks the secret-shaped parts of one string. */
|
|
8
|
+
export type TextRedactor = (text: string) => string;
|
|
9
|
+
/** The string redactor every value crossing the seam goes through. */
|
|
10
|
+
export declare function createTextRedactor(options?: RedactionOptions): TextRedactor;
|
|
11
|
+
/**
|
|
12
|
+
* A failure whose message was written for the user. An action throws it to
|
|
13
|
+
* show `message` with the stable `code`; any other thrown value is shown only
|
|
14
|
+
* as a generic message, because its text may quote a request, a response or
|
|
15
|
+
* a credential. `code` is lowercase letters, digits and dashes; anything else
|
|
16
|
+
* is reported as `action-failed`.
|
|
17
|
+
*/
|
|
18
|
+
export declare class CommandError extends Error {
|
|
19
|
+
readonly code: string;
|
|
20
|
+
constructor(code: string, message: string, options?: {
|
|
21
|
+
cause?: unknown;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/** What a failed action shows: a stable code and a message safe to display. */
|
|
25
|
+
export interface ProjectedFailure {
|
|
26
|
+
code: string;
|
|
27
|
+
text: string;
|
|
28
|
+
}
|
|
29
|
+
/** The code and message shown for an exception the seam cannot vouch for. */
|
|
30
|
+
export declare const ACTION_FAILED: ProjectedFailure;
|
|
31
|
+
/** The code and display text for a thrown value; never its raw text. */
|
|
32
|
+
export declare function projectFailure(error: unknown): ProjectedFailure;
|
|
33
|
+
/** A built-in item may carry the account it shows; plugin items cannot. */
|
|
34
|
+
export interface ResolvedItem extends ItemDefinition {
|
|
35
|
+
account?: MenuAccount;
|
|
36
|
+
}
|
|
37
|
+
/** A section with its bodies, as the menu holds it between builds. */
|
|
38
|
+
export interface ResolvedSection {
|
|
39
|
+
id: string;
|
|
40
|
+
slot: SectionSlot;
|
|
41
|
+
title: string;
|
|
42
|
+
content: Omit<SectionContent, 'items'> & {
|
|
43
|
+
items?: ResolvedItem[];
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** The confirmation shown when an irreversible action names none. */
|
|
47
|
+
export declare const DEFAULT_IRREVERSIBLE_CONFIRMATION = "This cannot be undone. Continue?";
|
|
48
|
+
/** What every payload builder needs besides the payload itself. */
|
|
49
|
+
export interface SeamContext {
|
|
50
|
+
logger: SeamLogger;
|
|
51
|
+
redact: TextRedactor;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The confirmation an action must pass before it runs, or undefined. An
|
|
55
|
+
* irreversible action always has one, even when its definition (built
|
|
56
|
+
* outside the type checker) names none.
|
|
57
|
+
*/
|
|
58
|
+
export declare function confirmationOf(action: ActionDefinition): MenuConfirmation | undefined;
|
|
59
|
+
/** The account fields a renderer may show; see `MenuAccount`. */
|
|
60
|
+
export declare function projectAccount(account: MenuAccount): MenuAccount;
|
|
61
|
+
/** The payload a host's TUI receives when the slash command opens. */
|
|
62
|
+
export declare function dialogPayload(command: string, title: string, sections: readonly ResolvedSection[], seam: SeamContext): CommandDialogPayload;
|
|
63
|
+
/** How an apply ended, before the seam turns it into a payload. */
|
|
64
|
+
export interface ApplyOutcome {
|
|
65
|
+
ok: boolean;
|
|
66
|
+
text: string;
|
|
67
|
+
/** Present on every failure. */
|
|
68
|
+
code?: string;
|
|
69
|
+
needsConfirmation?: boolean;
|
|
70
|
+
}
|
|
71
|
+
/** An apply's result: the message and the refreshed menu. */
|
|
72
|
+
export declare function applyResult(command: string, title: string, sections: readonly ResolvedSection[], outcome: ApplyOutcome, seam: SeamContext): CommandApplyResult;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare function isLostMarkerRaceError(error: unknown): boolean;
|
|
2
|
+
export interface LockLoss {
|
|
3
|
+
readonly reason: 'taken-over' | 'expired' | 'unreadable' | 'renewal-failed' | 'marker-lost';
|
|
4
|
+
readonly expectedOwnerId: string;
|
|
5
|
+
readonly observedOwnerId?: string;
|
|
6
|
+
readonly observedExpiresAt?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface RefreshFileLock {
|
|
9
|
+
readonly ownerId: string;
|
|
10
|
+
assertOwned(): Promise<void>;
|
|
11
|
+
release(): Promise<void>;
|
|
12
|
+
/** Resolves once on detected loss; remains pending after an owner's release. */
|
|
13
|
+
whenLost(): Promise<LockLoss>;
|
|
14
|
+
hasLost(): boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function acquireRefreshFileLock(options: {
|
|
17
|
+
name: string;
|
|
18
|
+
ttlMs: number;
|
|
19
|
+
/**
|
|
20
|
+
* File the lock is named after. Required: the lock and the write it guards
|
|
21
|
+
* must target the same file, and a default resolved in here could only ever
|
|
22
|
+
* be one host's path.
|
|
23
|
+
*/
|
|
24
|
+
path: string;
|
|
25
|
+
now?: () => number;
|
|
26
|
+
renew?: boolean;
|
|
27
|
+
renewIntervalMs?: number;
|
|
28
|
+
/** Notifies a live-owner refusal without awaiting; observer failures are ignored. */
|
|
29
|
+
onContended?: () => void;
|
|
30
|
+
/** Synchronous, never awaited; throws and returned promise/thenable rejections are isolated. */
|
|
31
|
+
onRenewalTimer?: (event: 'scheduled' | 'cancelled') => void;
|
|
32
|
+
onStep?: (step: 'stale-marker-stat' | 'stale-marker-claimed' | 'stale-lock-observed' | 'stale-lock-confirmed' | 'stale-lock-removed' | 'stale-lock-recreated' | 'eviction-marker-acquired' | 'renewal-owner-confirmed' | 'renewal-marker-unavailable' | 'renewal-write-fenced' | 'renewal-write-ready' | 'relinquish-read' | 'renewal-finished' | 'release-owner-confirmed') => void | Promise<void>;
|
|
33
|
+
}): Promise<RefreshFileLock | null>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Level } from './engine.js';
|
|
2
|
+
export interface LogTestRecord {
|
|
3
|
+
channel: string;
|
|
4
|
+
level: Level;
|
|
5
|
+
message: string;
|
|
6
|
+
data?: unknown;
|
|
7
|
+
}
|
|
8
|
+
/** The engine delivers scrubbed records only; this sink never sees raw credentials. */
|
|
9
|
+
export type CaptureSink = (record: LogTestRecord) => void;
|
|
10
|
+
export declare function createCaptureSink(): {
|
|
11
|
+
records: LogTestRecord[];
|
|
12
|
+
sink: CaptureSink;
|
|
13
|
+
clear: () => void;
|
|
14
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { CaptureSink } from './capture-sink.js';
|
|
2
|
+
import { type RedactionOptions } from './redact.js';
|
|
3
|
+
export type Level = 'error' | 'warn' | 'info' | 'debug' | 'trace';
|
|
4
|
+
/** A logger that writes to a file, and to a capture sink when one is given. */
|
|
5
|
+
export interface InitLoggerOptions extends RedactionOptions {
|
|
6
|
+
/** Receives every emitted record, scrubbed, alongside the file. */
|
|
7
|
+
captureSink?: CaptureSink;
|
|
8
|
+
/**
|
|
9
|
+
* Path of the file lines are appended to, or a function returning it.
|
|
10
|
+
*
|
|
11
|
+
* A function is what a host passes when its destination can move while the
|
|
12
|
+
* process runs — an operator or a test changing the variable that names the
|
|
13
|
+
* log file expects the next line to land in the new file, and a value
|
|
14
|
+
* captured once at init would keep writing to the old one.
|
|
15
|
+
*/
|
|
16
|
+
file: string | (() => string);
|
|
17
|
+
/** Level floor applied when no `setLogLevel` call has overridden it. */
|
|
18
|
+
level?: Level | (() => Level | undefined);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A logger with no file: the capture sink is its only destination. Nothing
|
|
22
|
+
* is written to disk or printed, for a host that forwards records to its own
|
|
23
|
+
* log.
|
|
24
|
+
*/
|
|
25
|
+
export interface SinkOnlyLoggerOptions extends RedactionOptions {
|
|
26
|
+
/** Receives every emitted record, scrubbed. */
|
|
27
|
+
captureSink: CaptureSink;
|
|
28
|
+
file?: undefined;
|
|
29
|
+
/** Level floor applied when no `setLogLevel` call has overridden it. */
|
|
30
|
+
level?: Level | (() => Level | undefined);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* What a logger is configured with: a file (`InitLoggerOptions`, the shape
|
|
34
|
+
* every release before this one accepted, kept as its own interface so a
|
|
35
|
+
* caller deriving a type from it with `Pick` or `extends` keeps compiling) or
|
|
36
|
+
* a capture sink alone.
|
|
37
|
+
*/
|
|
38
|
+
export type LoggerOptions = InitLoggerOptions | SinkOnlyLoggerOptions;
|
|
39
|
+
export interface ChannelLogger {
|
|
40
|
+
error(message: string, data?: unknown): void;
|
|
41
|
+
warn(message: string, data?: unknown): void;
|
|
42
|
+
info(message: string, data?: unknown): void;
|
|
43
|
+
debug(message: string, data?: unknown): void;
|
|
44
|
+
trace(message: string, data?: unknown): void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A logger with its own file, level, redaction, capture sink and buffer.
|
|
48
|
+
* Two instances in one process never touch each other's settings or lines,
|
|
49
|
+
* so two plugins that load one shared copy of this module each keep their own
|
|
50
|
+
* log by holding their own instance.
|
|
51
|
+
*/
|
|
52
|
+
export interface LoggerInstance {
|
|
53
|
+
/** A logger whose lines carry `channel` and go to this instance's file. */
|
|
54
|
+
createLogger(channel: string): ChannelLogger;
|
|
55
|
+
/**
|
|
56
|
+
* Point this instance at a host's file and level. Idempotent: calling it
|
|
57
|
+
* again replaces both. A runtime level installed by `setLogLevel` is left
|
|
58
|
+
* alone, because it is the operator's explicit choice and outranks the
|
|
59
|
+
* floor a host computed at start-up.
|
|
60
|
+
*/
|
|
61
|
+
configure(options: LoggerOptions): void;
|
|
62
|
+
/** Operator override of the level floor; undefined removes it. */
|
|
63
|
+
setLogLevel(level: Level | undefined): void;
|
|
64
|
+
/**
|
|
65
|
+
* Write whatever is buffered. Safe to call synchronously from a
|
|
66
|
+
* process-exit handler, which is how each host drains the buffer on
|
|
67
|
+
* shutdown.
|
|
68
|
+
*/
|
|
69
|
+
flushLogs(): void;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* A logger instance of its own, configured with `options`. A plugin whose
|
|
73
|
+
* copy of this module may be shared with another plugin in the same process
|
|
74
|
+
* uses this instead of `initLogger`, so neither replaces the other's file,
|
|
75
|
+
* level, redaction or capture sink.
|
|
76
|
+
*/
|
|
77
|
+
export declare function createLoggerInstance(options: LoggerOptions): LoggerInstance;
|
|
78
|
+
/**
|
|
79
|
+
* Point the module's default logger at a host's file and level, and return
|
|
80
|
+
* it. Idempotent: calling it again replaces both. A runtime level installed
|
|
81
|
+
* by `setLogLevel` is deliberately left alone, because it is the operator's
|
|
82
|
+
* explicit choice and outranks the floor a host computed at start-up.
|
|
83
|
+
*/
|
|
84
|
+
export declare function initLogger(options: LoggerOptions): LoggerInstance;
|
|
85
|
+
export declare function setLogLevel(l: Level | undefined): void;
|
|
86
|
+
/**
|
|
87
|
+
* Write whatever the default logger has buffered. Safe to call synchronously
|
|
88
|
+
* from a process-exit handler, which is how each host drains the buffer on
|
|
89
|
+
* shutdown.
|
|
90
|
+
*/
|
|
91
|
+
export declare function flushLogs(): void;
|
|
92
|
+
export declare function createLogger(channel: string): ChannelLogger;
|
|
93
|
+
export declare function flushForTest(): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Return the default logger to its uninitialised state. Only a test needs
|
|
96
|
+
* this: a single process runs every test file, so a file path left over from
|
|
97
|
+
* one test would keep a later "logger was never initialised" case writing
|
|
98
|
+
* lines.
|
|
99
|
+
*/
|
|
100
|
+
export declare function resetLoggerForTest(): void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { CaptureSink, LogTestRecord } from './capture-sink.js';
|
|
2
|
+
export { createCaptureSink } from './capture-sink.js';
|
|
3
|
+
export type { ChannelLogger, InitLoggerOptions, Level, LoggerInstance, LoggerOptions, SinkOnlyLoggerOptions, } from './engine.js';
|
|
4
|
+
export { createLogger, createLoggerInstance, flushForTest, flushLogs, initLogger, resetLoggerForTest, setLogLevel, } from './engine.js';
|
|
5
|
+
export type { RedactionOptions, Redactor } from './redact.js';
|
|
6
|
+
export { createRedactor, redact, redactStrings } from './redact.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface RedactionOptions {
|
|
2
|
+
extraSecretKeys?: (normalizedKey: string) => boolean;
|
|
3
|
+
extraValuePatterns?: RegExp[];
|
|
4
|
+
}
|
|
5
|
+
export declare function createRedactor(options?: RedactionOptions): {
|
|
6
|
+
redact: (value: unknown) => unknown;
|
|
7
|
+
redactStrings: (value: unknown) => unknown;
|
|
8
|
+
};
|
|
9
|
+
export type Redactor = ReturnType<typeof createRedactor>;
|
|
10
|
+
export declare const redact: (value: unknown) => unknown;
|
|
11
|
+
export declare const redactStrings: (value: unknown) => unknown;
|