thoth-agents 0.12.0 → 0.13.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 +11 -2
- package/dist/{chunk-SEF6PFM6.js → chunk-5MYXVRZZ.js} +132 -157
- package/dist/chunk-6O4GKDS7.js +207 -0
- package/dist/{chunk-QOA2AETX.js → chunk-NOLDFT7O.js} +3 -3
- package/dist/{chunk-7F33WUSD.js → chunk-VVYAQTYE.js} +2 -2
- package/dist/{chunk-NY2IPJ7V.js → chunk-YCWGTDFE.js} +531 -233
- package/dist/cli/index.js +6 -6
- package/dist/cli/opencode-profiles.d.ts +10 -0
- package/dist/cli/tui/index.js +3 -3
- package/dist/config/loader.d.ts +1 -4
- package/dist/config/schema.d.ts +0 -22
- package/dist/index.js +824 -30
- package/dist/opencode/context.d.ts +16 -0
- package/dist/opencode/profile-rpc-handlers.d.ts +3 -0
- package/dist/opencode/profile-rpc.d.ts +688 -0
- package/dist/opencode/profile-runtime.d.ts +3 -0
- package/dist/opencode/profile-sessions.d.ts +18 -0
- package/dist/opencode/profiles/editor.d.ts +44 -0
- package/dist/opencode/profiles/index.d.ts +18 -0
- package/dist/opencode/profiles/resolver.d.ts +12 -0
- package/dist/opencode/profiles/store.d.ts +63 -0
- package/dist/opencode/profiles/types.d.ts +26 -0
- package/dist/opencode/tool-overrides/evaluator.d.ts +13 -0
- package/dist/opencode/tool-overrides/index.d.ts +5 -0
- package/dist/opencode/tool-overrides/store.d.ts +38 -0
- package/dist/opencode/tool-overrides/types.d.ts +32 -0
- package/dist/opencode/tool-overrides/validation.d.ts +5 -0
- package/dist/opencode/tool-overrides/wildcard.d.ts +3 -0
- package/dist/opencode/tool-rpc-handlers.d.ts +3 -0
- package/dist/opencode/tool-rpc.d.ts +428 -0
- package/dist/pi.js +2 -2
- package/dist/tui/fixtures.d.ts +2 -0
- package/dist/tui/flow.d.ts +16 -0
- package/dist/tui/index.d.ts +7 -0
- package/dist/tui/index.js +1384 -0
- package/dist/tui/model.d.ts +84 -0
- package/dist/tui/tools/fixtures.d.ts +3 -0
- package/dist/tui/tools/flow.d.ts +11 -0
- package/dist/tui/tools/model.d.ts +97 -0
- package/package.json +5 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/thoth-agents.schema.json +0 -70
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Plugin } from '@opencode/plugin';
|
|
2
|
+
export type SessionProfileSelection = {
|
|
3
|
+
name: string;
|
|
4
|
+
projectDir: string;
|
|
5
|
+
};
|
|
6
|
+
/** Plugin-global storage; selections retain the owning project's identity. */
|
|
7
|
+
export declare class SessionProfileSelections {
|
|
8
|
+
private readonly storage;
|
|
9
|
+
private readonly projectDir;
|
|
10
|
+
constructor(storage: Plugin.Context['storage'], projectDir: string);
|
|
11
|
+
private parse;
|
|
12
|
+
set(sessionID: string, name: string | undefined, projectDir?: string): Promise<void>;
|
|
13
|
+
/** Collect before mutating storage so pagination remains stable. */
|
|
14
|
+
all(): Promise<Array<SessionProfileSelection & {
|
|
15
|
+
sessionID: string;
|
|
16
|
+
}>>;
|
|
17
|
+
get(sessionID: string): Promise<SessionProfileSelection | undefined>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type ModelProfileStore } from './store.js';
|
|
2
|
+
import { type NamedModelProfile, type ProfileRole, type ProfileScope, type RoleProfile } from './types.js';
|
|
3
|
+
export type ProfileEntry = {
|
|
4
|
+
key: string;
|
|
5
|
+
name: string;
|
|
6
|
+
/** Undefined only for the read-only virtual default. */
|
|
7
|
+
scope?: ProfileScope;
|
|
8
|
+
agents: NamedModelProfile['agents'];
|
|
9
|
+
/** Original persisted snapshot; undefined for an unsaved draft. */
|
|
10
|
+
base?: NamedModelProfile;
|
|
11
|
+
shadowed: boolean;
|
|
12
|
+
};
|
|
13
|
+
/** null removes an override, restoring effective config inheritance. */
|
|
14
|
+
export type RoleEdit = {
|
|
15
|
+
model?: string | null;
|
|
16
|
+
variant?: string | null;
|
|
17
|
+
};
|
|
18
|
+
export declare const isDraft: (entry: ProfileEntry) => boolean;
|
|
19
|
+
export declare const isEntryDirty: (entry: ProfileEntry) => boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Draft-until-save editor. Use entries() again after reload/save/discard/rename/delete.
|
|
22
|
+
* Entries are working copies; file operations re-read and save rejects stale baselines.
|
|
23
|
+
* Session selection remains caller-owned, not persisted by this host-neutral editor.
|
|
24
|
+
*/
|
|
25
|
+
export declare class ModelProfileWorkspace {
|
|
26
|
+
readonly store: ModelProfileStore;
|
|
27
|
+
private current;
|
|
28
|
+
constructor(store: ModelProfileStore);
|
|
29
|
+
/** Refresh disk state while retaining dirty working copies and their original baselines. */
|
|
30
|
+
reload(): void;
|
|
31
|
+
entries(): ProfileEntry[];
|
|
32
|
+
pendingCount(): number;
|
|
33
|
+
valuesFor(entry: ProfileEntry, role: ProfileRole): RoleProfile;
|
|
34
|
+
private assertEditable;
|
|
35
|
+
private newName;
|
|
36
|
+
createDraft(source: ProfileEntry, name: string, scope: ProfileScope): ProfileEntry;
|
|
37
|
+
edit(entry: ProfileEntry, role: ProfileRole, edit: RoleEdit): void;
|
|
38
|
+
/** Materialize all effective roles. A concurrent same-profile edit requires reload. */
|
|
39
|
+
save(entry: ProfileEntry): string;
|
|
40
|
+
/** Drop a draft or revert an edit to the latest persisted value. */
|
|
41
|
+
discard(entry: ProfileEntry): void;
|
|
42
|
+
rename(entry: ProfileEntry, name: string): void;
|
|
43
|
+
delete(entry: ProfileEntry): void;
|
|
44
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-neutral OpenCode model profiles.
|
|
3
|
+
*
|
|
4
|
+
* Inject the effective role roster into ModelProfileStore; use resolve(sessionName)
|
|
5
|
+
* for selection and resolveRoleProfile for field-level inheritance. Persisted files
|
|
6
|
+
* never contain the virtual `default`. Warnings are returned by resolve, collected
|
|
7
|
+
* by read(scope, warnings), and optionally forwarded to the store's warn callback.
|
|
8
|
+
* Runtime reads tolerate bad files; mutations reject invalid files to avoid data loss.
|
|
9
|
+
*
|
|
10
|
+
* ModelProfileWorkspace owns drafts until save. Same-profile concurrent saves raise
|
|
11
|
+
* ProfileConflictError (code PROFILE_CONFLICT); discard then reload entries to retry.
|
|
12
|
+
* Store mutations re-read files and atomically replace each individual file, not a
|
|
13
|
+
* transaction across global/project files or a cross-process compare-and-swap lock.
|
|
14
|
+
*/
|
|
15
|
+
export * from './editor.js';
|
|
16
|
+
export * from './resolver.js';
|
|
17
|
+
export * from './store.js';
|
|
18
|
+
export * from './types.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type EffectiveRoster, type ModelEntry, type NamedModelProfile, type ProfileRole, type RoleProfile } from './types.js';
|
|
2
|
+
/** Normalize the effective config's scalar/array models without changing fallback order. */
|
|
3
|
+
export declare function configuredModelChain(config: EffectiveRoster[ProfileRole]): ModelEntry[];
|
|
4
|
+
/** Resolve one layer as a pair, matching runtime scalar/array model semantics. */
|
|
5
|
+
export declare function resolveModelPair(config: EffectiveRoster[ProfileRole], inherited?: RoleProfile): RoleProfile;
|
|
6
|
+
/** Model overrides own their variant; variant-only overrides inherit the model. */
|
|
7
|
+
export declare function resolveRoleProfile(role: ProfileRole, profile: NamedModelProfile, roster: EffectiveRoster): RoleProfile;
|
|
8
|
+
export declare function defaultModelProfile(roster: EffectiveRoster): NamedModelProfile;
|
|
9
|
+
/** Profile first; a model ID occurs at most once, even if its variant differs. */
|
|
10
|
+
export declare function mergeProfileModelChain(profile: RoleProfile, configured: readonly ModelEntry[]): ModelEntry[];
|
|
11
|
+
/** Native subagent input format. Undefined means no model could be resolved. */
|
|
12
|
+
export declare function formatModelString(profile: RoleProfile): string | undefined;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type EffectiveRoster, type ModelProfileSelection, type ModelProfilesDocument, type NamedModelProfile, type ProfileScope, type RoleProfile } from './types.js';
|
|
2
|
+
export declare const DEFAULT_PROFILE = "default";
|
|
3
|
+
export type ModelProfileStoreOptions = {
|
|
4
|
+
cwd: string;
|
|
5
|
+
configDir?: string;
|
|
6
|
+
homeDir?: string;
|
|
7
|
+
env?: Record<string, string | undefined>;
|
|
8
|
+
/** Injected effective thoth-agents.json roster, including shipped defaults. */
|
|
9
|
+
roster?: EffectiveRoster;
|
|
10
|
+
warn?: (message: string) => void;
|
|
11
|
+
paths?: {
|
|
12
|
+
global: string;
|
|
13
|
+
project: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export declare function modelProfilePaths(options: ModelProfileStoreOptions): {
|
|
17
|
+
global: string;
|
|
18
|
+
project: string;
|
|
19
|
+
};
|
|
20
|
+
export declare function validateProfileName(value: unknown, writable?: boolean): string;
|
|
21
|
+
export declare function parseRoleProfile(value: unknown): RoleProfile;
|
|
22
|
+
export declare function parseNamedModelProfile(value: unknown): NamedModelProfile;
|
|
23
|
+
/** Strict parser for editors; runtime readers catch errors and warn instead. */
|
|
24
|
+
export declare function parseModelProfilesDocument(raw: unknown): ModelProfilesDocument;
|
|
25
|
+
/** Identifiable optimistic-concurrency failure for RPC/TUI reload prompts. */
|
|
26
|
+
export declare class ProfileConflictError extends Error {
|
|
27
|
+
readonly scope: ProfileScope;
|
|
28
|
+
readonly profileName: string;
|
|
29
|
+
readonly code = "PROFILE_CONFLICT";
|
|
30
|
+
constructor(scope: ProfileScope, profileName: string);
|
|
31
|
+
}
|
|
32
|
+
/** Synchronous, host-neutral file store. Runtime reads never throw for bad files. */
|
|
33
|
+
export declare class ModelProfileStore {
|
|
34
|
+
private readonly options;
|
|
35
|
+
readonly paths: {
|
|
36
|
+
global: string;
|
|
37
|
+
project: string;
|
|
38
|
+
};
|
|
39
|
+
constructor(options: ModelProfileStoreOptions);
|
|
40
|
+
defaultProfile(): NamedModelProfile;
|
|
41
|
+
private load;
|
|
42
|
+
read(scope: ProfileScope, warnings?: string[]): ModelProfilesDocument;
|
|
43
|
+
lookup(name: string, scope?: ProfileScope): {
|
|
44
|
+
profile: NamedModelProfile;
|
|
45
|
+
scope?: ProfileScope;
|
|
46
|
+
} | undefined;
|
|
47
|
+
private write;
|
|
48
|
+
/** Re-read before writing. An expected baseline enables same-profile conflict detection. */
|
|
49
|
+
save(scope: ProfileScope, name: string, value: unknown, options?: {
|
|
50
|
+
expected?: NamedModelProfile | null;
|
|
51
|
+
}): void;
|
|
52
|
+
create(scope: ProfileScope, name: string, value: unknown): void;
|
|
53
|
+
/** Pins that actually resolved to a global profile follow rename/delete. */
|
|
54
|
+
private projectPointsToGlobal;
|
|
55
|
+
rename(scope: ProfileScope, source: string, target: string): void;
|
|
56
|
+
delete(scope: ProfileScope, name: string): {
|
|
57
|
+
clearedActive: boolean;
|
|
58
|
+
};
|
|
59
|
+
setActive(scope: ProfileScope, name?: string): void;
|
|
60
|
+
setGlobalActive(name?: string): void;
|
|
61
|
+
setProjectPin(name?: string): void;
|
|
62
|
+
resolve(sessionSelection?: string): ModelProfileSelection;
|
|
63
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AgentOverrideConfig, ModelEntry } from '../../config/schema.js';
|
|
2
|
+
/** Shared canonical roster; never maintain a second role list here. */
|
|
3
|
+
export declare const PROFILE_ROLES: ("orchestrator" | "explorer" | "librarian" | "oracle" | "designer" | "worker")[];
|
|
4
|
+
export type ProfileRole = (typeof PROFILE_ROLES)[number];
|
|
5
|
+
export type ProfileScope = 'global' | 'project';
|
|
6
|
+
export type RoleProfile = {
|
|
7
|
+
model?: string;
|
|
8
|
+
variant?: string;
|
|
9
|
+
};
|
|
10
|
+
export type NamedModelProfile = {
|
|
11
|
+
agents: Partial<Record<ProfileRole, RoleProfile>>;
|
|
12
|
+
};
|
|
13
|
+
export type ModelProfilesDocument = {
|
|
14
|
+
version: 1;
|
|
15
|
+
active?: string;
|
|
16
|
+
profiles: Record<string, NamedModelProfile>;
|
|
17
|
+
};
|
|
18
|
+
/** Already includes shipped defaults. No runtime or host objects are required. */
|
|
19
|
+
export type EffectiveRoster = Partial<Record<ProfileRole, Pick<AgentOverrideConfig, 'model' | 'variant'>>>;
|
|
20
|
+
export type ModelProfileSelection = {
|
|
21
|
+
name: string;
|
|
22
|
+
scope?: ProfileScope;
|
|
23
|
+
profile: NamedModelProfile;
|
|
24
|
+
warnings: string[];
|
|
25
|
+
};
|
|
26
|
+
export type { ModelEntry };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PermissionRule } from '../permission-rules.js';
|
|
2
|
+
import type { ActionOverride, EffectiveToolOverrides, ToolEffect, ToolScope } from './types.js';
|
|
3
|
+
/** Rules to append to the shipped array; an empty override list is a no-op. */
|
|
4
|
+
export declare function appendOverrideRules(overrides: readonly ActionOverride[]): PermissionRule[];
|
|
5
|
+
/** Role-level preview at resource '*'; session rules are intentionally not involved. */
|
|
6
|
+
export declare function evaluateAction(base: readonly PermissionRule[], effective: EffectiveToolOverrides | undefined, action: string, platform?: string): {
|
|
7
|
+
effect: ToolEffect;
|
|
8
|
+
origin: 'default' | ToolScope;
|
|
9
|
+
};
|
|
10
|
+
/** Inherit removes every exact entry, leaving broader patterns intact. */
|
|
11
|
+
export declare function removeActionOverride(overrides: readonly ActionOverride[], action: string): ActionOverride[];
|
|
12
|
+
/** Explicit choices go last so broader patterns cannot supersede the edit. */
|
|
13
|
+
export declare function setActionOverride(overrides: readonly ActionOverride[], value: ActionOverride): ActionOverride[];
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { appendOverrideRules, evaluateAction, removeActionOverride, setActionOverride, } from './evaluator.js';
|
|
2
|
+
export { ToolsConflictError, ToolsOverrideStore, type ToolsOverrideStoreOptions, toolsOverridePaths, } from './store.js';
|
|
3
|
+
export * from './types.js';
|
|
4
|
+
export { parseActionOverrides, parseToolsDocument, validateSpecialistRole, } from './validation.js';
|
|
5
|
+
export { countActionMatches, matchAction } from './wildcard.js';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type SpecialistRole, type ToolScope, type ToolsRevision, type ToolsSnapshot, type ToolsState } from './types.js';
|
|
2
|
+
export type ToolsOverrideStoreOptions = {
|
|
3
|
+
cwd: string;
|
|
4
|
+
configDir?: string;
|
|
5
|
+
homeDir?: string;
|
|
6
|
+
env?: Record<string, string | undefined>;
|
|
7
|
+
paths?: {
|
|
8
|
+
global: string;
|
|
9
|
+
project: string;
|
|
10
|
+
};
|
|
11
|
+
warn?: (message: string) => void;
|
|
12
|
+
};
|
|
13
|
+
export declare function toolsOverridePaths(options: ToolsOverrideStoreOptions): {
|
|
14
|
+
global: string;
|
|
15
|
+
project: string;
|
|
16
|
+
};
|
|
17
|
+
export declare class ToolsConflictError extends Error {
|
|
18
|
+
readonly scope: ToolScope;
|
|
19
|
+
readonly code = "TOOLS_CONFLICT";
|
|
20
|
+
constructor(scope: ToolScope);
|
|
21
|
+
}
|
|
22
|
+
/** Synchronous host-neutral store with per-file optimistic revisions. */
|
|
23
|
+
export declare class ToolsOverrideStore {
|
|
24
|
+
private readonly options;
|
|
25
|
+
readonly paths: {
|
|
26
|
+
global: string;
|
|
27
|
+
project: string;
|
|
28
|
+
};
|
|
29
|
+
constructor(options: ToolsOverrideStoreOptions);
|
|
30
|
+
private raw;
|
|
31
|
+
read(scope: ToolScope): ToolsSnapshot;
|
|
32
|
+
resolve(): ToolsState;
|
|
33
|
+
private mutate;
|
|
34
|
+
/** Save ordered rules losslessly, including duplicates; other roles survive. */
|
|
35
|
+
save(scope: ToolScope, role: SpecialistRole, overrides: unknown, baseRevision: ToolsRevision): ToolsSnapshot;
|
|
36
|
+
/** Remove a scope's role entry (project reset resumes global inheritance). */
|
|
37
|
+
reset(scope: ToolScope, role: SpecialistRole, baseRevision: ToolsRevision): ToolsSnapshot;
|
|
38
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type ProfileRole } from '../profiles/types.js';
|
|
2
|
+
export type SpecialistRole = Exclude<ProfileRole, 'orchestrator'>;
|
|
3
|
+
export declare const SPECIALIST_ROLES: SpecialistRole[];
|
|
4
|
+
export type ToolScope = 'global' | 'project';
|
|
5
|
+
export type ToolEffect = 'allow' | 'ask' | 'deny';
|
|
6
|
+
export type ActionOverride = {
|
|
7
|
+
action: string;
|
|
8
|
+
effect: ToolEffect;
|
|
9
|
+
};
|
|
10
|
+
export type RoleToolOverrides = {
|
|
11
|
+
overrides: ActionOverride[];
|
|
12
|
+
};
|
|
13
|
+
export type ToolsDocument = {
|
|
14
|
+
version: 1;
|
|
15
|
+
roles: Partial<Record<SpecialistRole, RoleToolOverrides>>;
|
|
16
|
+
};
|
|
17
|
+
export type EffectiveToolOverrides = RoleToolOverrides & {
|
|
18
|
+
origin: ToolScope;
|
|
19
|
+
};
|
|
20
|
+
/** Opaque token for the entire on-disk file, including invalid content. */
|
|
21
|
+
export type ToolsRevision = string;
|
|
22
|
+
export type ToolsSnapshot = {
|
|
23
|
+
document: ToolsDocument;
|
|
24
|
+
revision: ToolsRevision;
|
|
25
|
+
warnings: string[];
|
|
26
|
+
};
|
|
27
|
+
export type ToolsState = {
|
|
28
|
+
global: ToolsSnapshot;
|
|
29
|
+
project: ToolsSnapshot;
|
|
30
|
+
effective: Partial<Record<SpecialistRole, EffectiveToolOverrides>>;
|
|
31
|
+
warnings: string[];
|
|
32
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type ActionOverride, type SpecialistRole, type ToolsDocument } from './types.js';
|
|
2
|
+
export declare function parseActionOverrides(value: unknown): ActionOverride[];
|
|
3
|
+
export declare function validateSpecialistRole(role: string): SpecialistRole;
|
|
4
|
+
/** Unknown roles warn and are ignored; malformed known roles invalidate the file. */
|
|
5
|
+
export declare function parseToolsDocument(value: unknown, warnings?: string[]): ToolsDocument;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** Mirrors OpenCode 2.2.5 wildcard.ts at 9bbb8ce18c80f099e0e448775f59d965ead40a21. */
|
|
2
|
+
export declare function matchAction(input: string, pattern: string, platform?: string): boolean;
|
|
3
|
+
export declare function countActionMatches(pattern: string, actions: readonly string[], platform?: string): number;
|