@sidequest-007/dsh-atlas 1.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +269 -0
  2. package/CONTRIBUTING.md +50 -0
  3. package/LICENSE +21 -0
  4. package/LICENSE-ORIGINAL +21 -0
  5. package/NOTICE +29 -0
  6. package/README.md +297 -0
  7. package/README.zh.md +289 -0
  8. package/assets/diagrams/atlas-overview.svg +53 -0
  9. package/assets/diagrams/atlas-seam.svg +32 -0
  10. package/assets/screenshots/file-mention-composer.png +0 -0
  11. package/assets/screenshots/file-mention-settings.png +0 -0
  12. package/assets/screenshots/menu-mixed.png +0 -0
  13. package/cordis.patch.yml +14 -0
  14. package/dsh.plugin.json +12 -0
  15. package/lib/client.js +20615 -0
  16. package/lib/index.js +17458 -0
  17. package/lib/invariant.js +13 -0
  18. package/lib/types/abort.d.ts +22 -0
  19. package/lib/types/atlas.d.ts +181 -0
  20. package/lib/types/client/DraftLinks.d.ts +21 -0
  21. package/lib/types/client/FilesDock.d.ts +75 -0
  22. package/lib/types/client/FolderPicker.d.ts +66 -0
  23. package/lib/types/client/FolderTab.d.ts +50 -0
  24. package/lib/types/client/MentionNavigator.d.ts +96 -0
  25. package/lib/types/client/MenuIcons.d.ts +16 -0
  26. package/lib/types/client/ReferenceLinks.d.ts +85 -0
  27. package/lib/types/client/SettingsSection.d.ts +31 -0
  28. package/lib/types/client/draft-links.d.ts +205 -0
  29. package/lib/types/client/draft-scope.d.ts +22 -0
  30. package/lib/types/client/git-provider.d.ts +45 -0
  31. package/lib/types/client/icons.d.ts +48 -0
  32. package/lib/types/client/index.d.ts +8 -0
  33. package/lib/types/client/locales.d.ts +267 -0
  34. package/lib/types/client/model.d.ts +38 -0
  35. package/lib/types/client/reference-links.d.ts +100 -0
  36. package/lib/types/client/remote.d.ts +54 -0
  37. package/lib/types/client/search.d.ts +9 -0
  38. package/lib/types/client/source.d.ts +325 -0
  39. package/lib/types/client/styles.d.ts +15 -0
  40. package/lib/types/contract.d.ts +512 -0
  41. package/lib/types/defaults.d.ts +115 -0
  42. package/lib/types/external.d.ts +58 -0
  43. package/lib/types/files.d.ts +76 -0
  44. package/lib/types/git.d.ts +44 -0
  45. package/lib/types/index.d.ts +88 -0
  46. package/lib/types/invariant.d.ts +15 -0
  47. package/lib/types/mention.d.ts +80 -0
  48. package/lib/types/paste.d.ts +13 -0
  49. package/lib/types/reference.d.ts +16 -0
  50. package/lib/types/references.d.ts +126 -0
  51. package/lib/types/runtime-info.d.ts +30 -0
  52. package/lib/types/runtime.d.ts +180 -0
  53. package/lib/types/settings.d.ts +25 -0
  54. package/lib/types/tokens.d.ts +35 -0
  55. package/lib/types/tools.d.ts +94 -0
  56. package/lib/types/typert.d.ts +13 -0
  57. package/lib/types/types.d.ts +12 -0
  58. package/package.json +208 -0
@@ -0,0 +1,58 @@
1
+ /** The one sandbox mode that may DISCOVER new external paths. */
2
+ export declare const EXTERNAL_ADDING_MODE = "danger-full-access";
3
+ /** The sandbox modes this plugin understands; anything else is treated as narrow. */
4
+ export type SandboxModeName = 'read-only' | 'workspace-write' | 'danger-full-access';
5
+ /** What one session may do with out-of-workspace paths right now. */
6
+ export interface ExternalAccess {
7
+ /** Whether this session may reference and search paths the ledger does not know yet. */
8
+ readonly canDiscover: boolean;
9
+ /** Ledger directories this session may reference INTO, as canonical paths. */
10
+ readonly roots: readonly string[];
11
+ /** Ledger paths this session may reference EXACTLY (files included). */
12
+ readonly known: readonly string[];
13
+ }
14
+ /** The access a session with no resolved policy gets: ledger paths only. */
15
+ export declare const NO_EXTERNAL_DISCOVERY: ExternalAccess;
16
+ /**
17
+ * Build one session's access from its resolved sandbox mode and the ledger.
18
+ * @param mode - the resolved sandbox mode, or undefined when the host has no policy service.
19
+ * @param roots - ledger directories associated with this workspace.
20
+ * @param known - every ledger path associated with this workspace, files included.
21
+ * @returns the access verdict for this session.
22
+ */
23
+ export declare function externalAccess(mode: string | undefined, roots: readonly string[], known?: readonly string[]): ExternalAccess;
24
+ /**
25
+ * Whether one absolute path may be referenced under this access.
26
+ *
27
+ * A discovering session may reference anything that exists; a narrow one only
28
+ * what the ledger already holds — the exact paths the user referenced before
29
+ * (files included) and anything inside the ledger's directories.
30
+ * @param access - the session's access verdict.
31
+ * @param absolute - an absolute candidate path.
32
+ * @returns true when the path is allowed.
33
+ */
34
+ export declare function allowsExternal(access: ExternalAccess, absolute: string): boolean;
35
+ /**
36
+ * Whether a path lies inside a directory (the directory itself counts).
37
+ *
38
+ * Compares canonical keys and requires a separator boundary, so a sibling whose
39
+ * name merely starts the same (`…/b` vs `…/bc`) is never treated as inside.
40
+ * @param root - the containing directory.
41
+ * @param target - the candidate path.
42
+ * @returns true when target is root or below it.
43
+ */
44
+ export declare function isUnder(root: string, target: string): boolean;
45
+ /** The canonical spelling of one external path, as tokens and the ledger carry it. */
46
+ export declare function externalPath(absolute: string): string;
47
+ /**
48
+ * Whether one path is absolute rather than workspace-relative.
49
+ *
50
+ * Both halves need this: the host decides whether a reference escapes the
51
+ * workspace at all, and the browser half must not look an absolute path up in a
52
+ * workspace-relative index (it would never be there). A drive-relative spelling
53
+ * (`E:foo`) is NOT absolute — it names nothing stable, so it stays a relative
54
+ * path and is refused by the host's own confinement test.
55
+ * @param value - a path as typed, picked, or recorded.
56
+ * @returns true for `E:/…`, `E:\…`, `/…`, or a UNC `\\server\share`.
57
+ */
58
+ export declare function isAbsoluteReference(value: string): boolean;
@@ -0,0 +1,76 @@
1
+ import type { Dir } from 'node:fs';
2
+ import type { FileEntry, FileIgnoreRuleInput } from './contract.ts';
3
+ /** Options for one bounded index pass. */
4
+ export interface IndexOptions {
5
+ /** Hard cap on collected files. */
6
+ readonly maxFiles: number;
7
+ /** Directory basenames the walk skips (children never enqueue). */
8
+ readonly ignoreDirs: readonly string[];
9
+ /** Exact and Regex basename filters applied before files enter the index. */
10
+ readonly ignoreFiles: readonly FileIgnoreRuleInput[];
11
+ }
12
+ /** One index pass result: the sorted file list plus the honest truncation flag. */
13
+ export interface WorkspaceIndex {
14
+ readonly files: readonly FileEntry[];
15
+ /** True when the walk hit `maxFiles` before the tree was exhausted. */
16
+ readonly truncated: boolean;
17
+ }
18
+ /** Directory opener seam used by the real filesystem and deterministic tests. */
19
+ export type OpenWorkspaceDirectory = (path: string) => Promise<Dir>;
20
+ /**
21
+ * Collect every regular file under `root` (bounded, name-sorted).
22
+ * @param root - workspace root to walk.
23
+ * @param options - cap and ignore list.
24
+ * @param signal - caller lifetime; every filesystem await races it.
25
+ * @param openDirectory - directory opener; defaults to node:fs.
26
+ * @returns the sorted file list and the truncation flag.
27
+ */
28
+ export declare function indexWorkspace(root: string, options: IndexOptions, signal?: AbortSignal, openDirectory?: OpenWorkspaceDirectory): Promise<WorkspaceIndex>;
29
+ /**
30
+ * List the DIRECT subdirectories of one directory (one level, never recursive).
31
+ *
32
+ * Used to offer the folders around a session workspace — the sibling checkouts
33
+ * a plugin author routinely needs, e.g. the DSH source tree beside the workspace
34
+ * — without walking anything: one `opendir` of one directory. Symlinks are
35
+ * skipped exactly like the workspace walk skips them (a link cycle can never
36
+ * strand this), ignore-listed directory names are skipped by basename, and the
37
+ * bounded result is name-sorted.
38
+ * @param dir - absolute directory to list.
39
+ * @param options - cap and the ignored directory basenames.
40
+ * @param signal - caller lifetime; the filesystem awaits race it.
41
+ * @param openDirectory - directory opener; defaults to node:fs.
42
+ * @returns absolute child directory paths, name-sorted and capped.
43
+ */
44
+ export declare function listSubdirectories(dir: string, options: {
45
+ readonly limit: number;
46
+ readonly ignoreDirs: readonly string[];
47
+ readonly skipHidden?: boolean;
48
+ readonly followLinks?: boolean;
49
+ }, signal?: AbortSignal, openDirectory?: OpenWorkspaceDirectory): Promise<readonly string[]>;
50
+ /** One row of a one-level directory listing: a name and what it is. */
51
+ export interface DirectoryEntryInfo {
52
+ readonly name: string;
53
+ readonly kind: 'file' | 'dir';
54
+ }
55
+ /** One directory's direct children, name-sorted with directories first. */
56
+ export interface DirectoryContents {
57
+ readonly entries: readonly DirectoryEntryInfo[];
58
+ /** True when the entry cap cut the listing short. */
59
+ readonly truncated: boolean;
60
+ }
61
+ /**
62
+ * List ONE directory's direct children, files included.
63
+ *
64
+ * The folder browser and the folder tab need what a file manager shows — both
65
+ * kinds, in one level — where {@link listSubdirectories} answers "which folders
66
+ * are next to this one". A link (junction or symlink) is reported as what it
67
+ * POINTS AT and dropped when it points at nothing, because a row the user cannot
68
+ * enter is worse than no row. Directories come first, then names, so the shape of
69
+ * the tree reads before its contents do.
70
+ * @param dir - absolute directory to list.
71
+ * @param limit - hard cap on returned entries.
72
+ * @param signal - caller lifetime; the filesystem awaits race it.
73
+ * @param openDirectory - directory opener; defaults to node:fs.
74
+ * @returns the entries and whether the cap was reached.
75
+ */
76
+ export declare function readDirectory(dir: string, limit: number, signal?: AbortSignal, openDirectory?: OpenWorkspaceDirectory): Promise<DirectoryContents>;
@@ -0,0 +1,44 @@
1
+ import type { AtlasProvider } from './atlas.ts';
2
+ import { type GitChange } from './contract.ts';
3
+ /**
4
+ * Parse porcelain v1 output into changes, dropping ignored directories.
5
+ * @param output - the raw `git status --porcelain=v1` text.
6
+ * @returns one entry per changed path, in git's order.
7
+ */
8
+ export declare function parseGitStatus(output: string): readonly GitChange[];
9
+ /**
10
+ * Parse `git diff --numstat` output into per-path line counts.
11
+ * @param output - the raw numstat text.
12
+ * @returns a path-keyed count map; binary files have no counts and are absent.
13
+ */
14
+ export declare function parseGitNumstat(output: string): ReadonlyMap<string, {
15
+ added: number;
16
+ removed: number;
17
+ }>;
18
+ /**
19
+ * The workspace's changed paths, with line counts where Git can count them.
20
+ * @param cwd - the workspace directory.
21
+ * @param signal - caller lifetime.
22
+ * @returns the changes, or an empty list outside a Git workspace.
23
+ */
24
+ export declare function readGitChanges(cwd: string, signal: AbortSignal): Promise<readonly GitChange[]>;
25
+ /**
26
+ * The diff for one changed path. A path Git sees as unchanged against HEAD is
27
+ * retried against the empty file, so an untracked path's content arrives as
28
+ * Git's own "new file" hunk rather than as a file read.
29
+ * @param cwd - the workspace directory.
30
+ * @param path - the repository-relative path being committed.
31
+ * @param signal - caller lifetime.
32
+ * @returns the diff text, or undefined when Git produced none.
33
+ */
34
+ export declare function readGitDiff(cwd: string, path: string, signal: AbortSignal): Promise<string | undefined>;
35
+ /**
36
+ * The built-in `@git` provider's injection half.
37
+ *
38
+ * This is the seam's worked example, and it is deliberately not privileged: it
39
+ * declares `scopes`/`testedOn` and goes through the same registry and the same
40
+ * version gate as a third-party provider. Its menu half is registered in the
41
+ * browser (see `client/git-provider.ts`) because the candidates must be filtered
42
+ * per keystroke while the repository lives on the Host.
43
+ */
44
+ export declare const GIT_RESOLVE_PROVIDER: AtlasProvider;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * dsh-atlas host plugin: mounts the `atFile` and `atMention` Typert
3
+ * Remote services (workspace search + category pickers), registers their
4
+ * strict Typert manifests and the settings namespace, mounts the official
5
+ * cross-session snapshot service when the profile has not, and marks every
6
+ * @ mention category (path, skill, past chat, plugin) at each agent's
7
+ * pre-step boundary. The plugin never reads mentioned file contents. The
8
+ * client half ships in the same package (`./client`); the web server serves
9
+ * it under /plugins/dsh-atlas/client.js.
10
+ */
11
+ import type { Context } from '@deepseek-ai/cordis';
12
+ import type { SessionId } from '@deepseek-ai/dsh-session/types';
13
+ import z from '@deepseek-ai/schemastery';
14
+ import { type ReferenceExpansion } from './mention.ts';
15
+ import type { AtFileSettings, SkillTier } from './contract.ts';
16
+ import type { ResolvedConfig } from './types.ts';
17
+ /** Cordis plugin name (the Loader entry and client bundle id). */
18
+ export declare const name = "dsh-atlas";
19
+ /** Services required before load: the Typert registry, the settings provider, and the agent registry. */
20
+ export declare const inject: string[];
21
+ export { DEFAULT_IGNORE_DIRS, DEFAULT_IGNORE_FILES } from './defaults.ts';
22
+ /**
23
+ * The public `@` seam surface, for a plugin that wants to register a source.
24
+ *
25
+ * `ctx.get('atlas')` is the handle; `AtlasSeam` is the shape to cast it to. A
26
+ * provider's declaration uses `AtlasProvider`/`AtlasItem`, and both halves type
27
+ * against the same `AtlasCallContext`.
28
+ */
29
+ export type { AtlasCallContext, AtlasItem, AtlasProvider, AtlasRegistration, AtlasSeam } from './atlas.ts';
30
+ /** Host plugin configuration, validated at load by the Loader. */
31
+ export interface Config {
32
+ /** Hard cap on indexed files per workspace; the walk stops and reports truncation. */
33
+ maxIndexedFiles: number;
34
+ /** Directory basenames the index walk skips entirely. */
35
+ ignoreDirs: string[];
36
+ /** When true, a recognized @skill mention also injects the skill body. */
37
+ injectSkillBody: boolean;
38
+ }
39
+ /**
40
+ * Configuration schema: deployment-varying bounds stay tunable from
41
+ * the profile patch. The inferred schema type keeps the callable form accepting
42
+ * partial input, so `Config({})` yields the defaults (what the Loader does
43
+ * for Loader compositions).
44
+ */
45
+ export declare const Config: z<Schemastery.ObjectS<{
46
+ maxIndexedFiles: z<number, number>;
47
+ ignoreDirs: z<string[], string[]>;
48
+ injectSkillBody: z<boolean, boolean>;
49
+ }>, Schemastery.ObjectT<{
50
+ maxIndexedFiles: z<number, number>;
51
+ ignoreDirs: z<string[], string[]>;
52
+ injectSkillBody: z<boolean, boolean>;
53
+ }>>;
54
+ /** Providers whose bundled skills are system skills (same set as the sidebar Skill Manager). */
55
+ export declare const SYSTEM_BUNDLED_PROVIDERS: Set<string>;
56
+ /**
57
+ * Map a skill registry source (and its owning provider) onto the management
58
+ * tiers shown by the sidebar Skill Manager: system / user / project / custom /
59
+ * plugin. Bundled skills from the filesystem/badge providers are system;
60
+ * bundled skills from any other provider come from a plugin's own tree.
61
+ */
62
+ export declare function skillTier(source: string | undefined, provider: string | undefined): SkillTier;
63
+ /**
64
+ * Build the settings-gated category expansions for one agent. Pure wiring:
65
+ * the expansion behavior lives in src/references.ts (unit-tested).
66
+ * @param ctx - the plugin context (service access).
67
+ * @param agent - the addressed live agent.
68
+ * @param resolved - resolved plugin configuration.
69
+ * @param readSettings - live settings read.
70
+ */
71
+ export declare function buildReferenceExpansion(ctx: Context, agent: {
72
+ readonly id: unknown;
73
+ } & {
74
+ readonly session: {
75
+ readonly id: SessionId;
76
+ readonly header: {
77
+ readonly cwd?: string;
78
+ };
79
+ };
80
+ }, resolved: ResolvedConfig & {
81
+ injectSkillBody: boolean;
82
+ }, readSettings: () => AtFileSettings): ReferenceExpansion;
83
+ /**
84
+ * Mount the atFile/atMention services and the pre-step reference markers.
85
+ * @param ctx - host cordis context.
86
+ * @param config - validated plugin configuration (schema defaults applied).
87
+ */
88
+ export declare function apply(ctx: Context, config?: Config): void;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Package-owned invariant companion for `@sidequest-007/dsh-atlas`.
3
+ * @module @sidequest-007/dsh-atlas/invariant
4
+ */
5
+ import type { Context } from '@deepseek-ai/cordis';
6
+ /** Cordis companion plugin name. */
7
+ export declare const name = "dsh-atlas-invariant";
8
+ /** Service required before the companion can reserve package ownership. */
9
+ export declare const inject: string[];
10
+ /**
11
+ * Register this package's invariant companion.
12
+ * @param ctx - Cordis context carrying the invariant service.
13
+ * @returns the installed registration's disposer after setup succeeds.
14
+ */
15
+ export declare const apply: (ctx: Context) => Promise<() => void>;
@@ -0,0 +1,80 @@
1
+ import type { UserMessage } from '@deepseek-ai/dsh-llm';
2
+ import type { PreStepDecision } from '@deepseek-ai/dsh-agent';
3
+ import { type LineRange } from './tokens.ts';
4
+ import { type ExternalAccess } from './external.ts';
5
+ /** One recognized mention: its workspace-relative token and resolved kind. */
6
+ export interface Mention {
7
+ /** Workspace-relative path (no leading @, no trailing slash, no line range). */
8
+ readonly relative: string;
9
+ readonly kind: 'file' | 'dir';
10
+ /** Inclusive 1-based line range, present only for `path:start-end` tokens. */
11
+ readonly lines?: LineRange;
12
+ /** True when `relative` is an absolute path outside the session workspace. */
13
+ readonly outside?: true;
14
+ }
15
+ /** The source tag the injected reference carries (transcript consumers use it). */
16
+ declare module '@deepseek-ai/dsh-llm' {
17
+ interface MessageSourceMap {
18
+ 'at-file-mention': {
19
+ kind: 'at-file-mention';
20
+ relative: string;
21
+ lines?: string;
22
+ };
23
+ }
24
+ }
25
+ /**
26
+ * Scan one text block for `@path` tokens, deduplicated in first-seen order.
27
+ * A trailing slash (the directory chip form) is stripped from the path.
28
+ * @param text - the message text block.
29
+ * @returns unique workspace-relative tokens.
30
+ */
31
+ export declare function scanMentions(text: string, ignorePastedMentions?: boolean): readonly string[];
32
+ /**
33
+ * Expand every `@path` mention into a validated existence-only reference, in
34
+ * first-seen order. Unknown paths stay plain prose.
35
+ * @param messages - the assembled step messages.
36
+ * @param cwd - the session's workspace directory.
37
+ * @param signal - caller lifetime.
38
+ * @param ignorePastedMentions - live pasted-@ policy.
39
+ * @param access - the session's out-of-workspace access, or undefined to refuse external paths.
40
+ * @param onExternal - called with each accepted external reference, for the ledger.
41
+ * @returns the injected user messages (empty when nothing matched or disabled).
42
+ */
43
+ export declare function expandMentions(messages: readonly UserMessage[], cwd: string | undefined, signal: AbortSignal, ignorePastedMentions?: boolean, access?: ExternalAccess, onExternal?: (mention: Mention) => void): Promise<UserMessage[]>;
44
+ /** The minimal agent face the pre-step handler reads. */
45
+ export interface MentionAgent {
46
+ session: {
47
+ header: {
48
+ cwd?: string;
49
+ };
50
+ };
51
+ }
52
+ /** The `agent/pre-step` listener body: expand mentions in the claimed user
53
+ * messages and append the injections to the downstream decision. Extracted so
54
+ * the boundary logic is unit-testable without an assembled agent scope.
55
+ * @param agent - the addressed agent (its session header owns the cwd).
56
+ * @param isEnabled - live settings read.
57
+ * @param messages - the claimed messages (the user's own words).
58
+ * @param signal - caller lifetime.
59
+ * @param next - the downstream waterfall.
60
+ * @param ignorePastedMentions - live pasted-@ policy.
61
+ * @param references - optional category expansions (chats, skills, plugins).
62
+ * @param access - the session's out-of-workspace access, or undefined to refuse external paths.
63
+ * @param onExternal - called with each accepted external reference, for the ledger.
64
+ * @returns the decision with injections appended, or the downstream decision.
65
+ */
66
+ export declare function mentionPreStep(agent: MentionAgent, isEnabled: () => boolean, messages: readonly UserMessage[], signal: AbortSignal, next: () => Promise<PreStepDecision>, ignorePastedMentions?: () => boolean, references?: ReferenceExpansion, access?: ExternalAccess, onExternal?: (mention: Mention) => void): Promise<PreStepDecision>;
67
+ /** Live category expansions wired by the host entry; each is settings-gated. */
68
+ export interface ReferenceExpansion {
69
+ /** Aggregate past-chat snapshot context, or undefined when none/disabled. */
70
+ expandChats(messages: readonly UserMessage[], signal: AbortSignal): Promise<UserMessage | undefined>;
71
+ /** `<skill-reference>` markers for recognized `@skill:` tokens. */
72
+ expandSkills(messages: readonly UserMessage[], signal: AbortSignal): Promise<readonly UserMessage[]>;
73
+ /** `<plugin-reference>` markers for recognized `@plugin:` tokens. */
74
+ expandPlugins(messages: readonly UserMessage[], signal: AbortSignal): Promise<readonly UserMessage[]>;
75
+ /**
76
+ * `<atlas-reference>` blocks for recognized `@atlas:<provider>/<item>` tokens,
77
+ * carrying the body the provider's own `resolve` returned.
78
+ */
79
+ expandAtlas?(messages: readonly UserMessage[], signal: AbortSignal): Promise<readonly UserMessage[]>;
80
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Internal marker used to distinguish pasted @ tokens from text the user
3
+ * typed. It is removed at the Host boundary before the prompt reaches the
4
+ * model. Word joiner has no visible glyph and keeps the displayed draft
5
+ * unchanged while making the token unambiguous to the plugin.
6
+ */
7
+ export declare const PASTED_MENTION_MARKER = "\u2060";
8
+ /** Add the internal marker after every @ that starts a pasted token. */
9
+ export declare function protectPastedMentions(text: string): string;
10
+ /** Whether a parsed token contains the internal pasted-text marker. */
11
+ export declare function isProtectedMentionToken(token: string): boolean;
12
+ /** Restore pasted text before it is shown to the model or another consumer. */
13
+ export declare function stripPastedMentionMarkers(text: string): string;
@@ -0,0 +1,16 @@
1
+ import type { ReferenceInfo } from './contract.ts';
2
+ import { type ExternalAccess } from './external.ts';
3
+ /**
4
+ * Inspect reference paths: workspace-relative ones, plus the absolute
5
+ * out-of-workspace ones this session is allowed to reference.
6
+ *
7
+ * Paths that escape the workspace, are external without access, or do not exist
8
+ * come back with `exists: false` rather than being dropped, so the dock can
9
+ * attribute the failure to the exact token the user typed.
10
+ * @param cwd - the session workspace root (absolute).
11
+ * @param targets - paths as typed, already stripped of line ranges.
12
+ * @param signal - caller lifetime.
13
+ * @param access - the session's out-of-workspace access, or undefined to refuse external paths.
14
+ * @returns one row per target, in request order.
15
+ */
16
+ export declare function inspectReferences(cwd: string, targets: readonly string[], signal: AbortSignal, access?: ExternalAccess): Promise<readonly ReferenceInfo[]>;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Host-side expansion for the non-path @ mention categories: past chats
3
+ * (official `dsh-session:` snapshot references), skills (`@skill:name`),
4
+ * and plugins (`@plugin:name`). Each expansion validates the token against a
5
+ * live capability (session reference resolver, skill registry, plugin
6
+ * inventory) and injects a sourced user message — never raw content bytes
7
+ * from the Host side unless the skill body injection config is enabled.
8
+ * Chat mentions are stripped to readable `@label` text in the user's own
9
+ * message, and the official `prepare()` snapshot is appended as a separate,
10
+ * replayable context message.
11
+ */
12
+ import type { Agent } from '@deepseek-ai/dsh-agent';
13
+ import type { ContentBlock, UserMessage } from '@deepseek-ai/dsh-llm';
14
+ import type { AtlasCallContext, AtlasRegistration } from './atlas.ts';
15
+ import { type SessionReferenceInput } from '@deepseek-ai/dsh-session-reference';
16
+ /** The `@skill:name` mention token: `@skill:` then a whitespace/@-free name. */
17
+ export declare const SKILL_MENTION_PATTERN: RegExp;
18
+ /** The `@plugin:name` mention token: `@plugin:` then a whitespace/@-free module name. */
19
+ export declare const PLUGIN_MENTION_PATTERN: RegExp;
20
+ /** The source tag skill reference messages carry (transcript consumers use it). */
21
+ declare module '@deepseek-ai/dsh-llm' {
22
+ interface MessageSourceMap {
23
+ 'atlas-skill': {
24
+ kind: 'atlas-skill';
25
+ name: string;
26
+ };
27
+ 'atlas-plugin': {
28
+ kind: 'atlas-plugin';
29
+ moduleName: string;
30
+ };
31
+ 'atlas-provider': {
32
+ kind: 'atlas-provider';
33
+ provider: string;
34
+ item: string;
35
+ };
36
+ }
37
+ }
38
+ /** Escape one value for an XML-like reference attribute without altering it. */
39
+ export declare function escapeReferenceAttribute(value: string): string;
40
+ /** The session-reference resolver face this boundary needs (unit-test stub). */
41
+ export interface ChatResolver {
42
+ prepare(agent: Agent, content: readonly ContentBlock[], references: readonly SessionReferenceInput[], signal: AbortSignal): Promise<{
43
+ readonly additionalContext?: UserMessage;
44
+ }>;
45
+ }
46
+ /**
47
+ * Scan the claimed user messages for `@skill:name` tokens in first-seen
48
+ * order. Known skills get a `<skill-reference>` marker; when `loadBody` is
49
+ * provided (config `injectSkillBody`) the skill body is appended in a
50
+ * `<skill-body>` block so the model can act on the full instructions.
51
+ * Unknown names stay plain prose.
52
+ * @param messages - the claimed user messages.
53
+ * @param isKnown - live lookup: is this skill currently discoverable?
54
+ * @param signal - caller lifetime.
55
+ * @param loadBody - optional full-body loader (skill registry `get`).
56
+ * @returns the injected user messages.
57
+ */
58
+ export declare function expandSkillMentions(messages: readonly UserMessage[], isKnown: (name: string) => boolean | Promise<boolean>, signal: AbortSignal, loadBody?: (name: string) => Promise<string | undefined>): Promise<UserMessage[]>;
59
+ /**
60
+ * Scan the claimed user messages for `@plugin:name` tokens in first-seen
61
+ * order. Enabled plugin modules get a `<plugin-reference>` marker; unknown
62
+ * or disabled modules stay plain prose.
63
+ * @param messages - the claimed user messages.
64
+ * @param isEnabled - live lookup: is this module an enabled plugin?
65
+ * @param signal - caller lifetime.
66
+ * @returns the injected user messages.
67
+ */
68
+ export declare function expandPluginMentions(messages: readonly UserMessage[], isEnabled: (moduleName: string) => boolean | Promise<boolean>, signal: AbortSignal): Promise<UserMessage[]>;
69
+ /** The `@atlas:<provider>/<item>` token: a provider handle, then its own item id. */
70
+ export declare const ATLAS_MENTION_PATTERN: RegExp;
71
+ /** How much one provider body may add to a single step. */
72
+ export declare const ATLAS_BODY_LIMIT = 16384;
73
+ /** How much every provider body may add to a single step in total. */
74
+ export declare const ATLAS_TOTAL_LIMIT = 49152;
75
+ /** One `@atlas:` mention, split into the handle and the provider's own item id. */
76
+ export interface AtlasMentionTarget {
77
+ readonly providerId: string;
78
+ readonly item: string;
79
+ }
80
+ /**
81
+ * Scan the claimed user messages for `@atlas:<provider>/<item>` tokens and inject
82
+ * one reference per token, carrying the body the provider's own `resolve` returns.
83
+ *
84
+ * ATLAS never reads a provider's data: the body arrives through the provider's
85
+ * callback, is bounded here, and is never persisted — the usage counter records
86
+ * only the `provider/item` handle. A provider that is not registered, or whose
87
+ * `resolve` fails, contributes nothing rather than blocking the send.
88
+ * @param messages - the claimed user messages.
89
+ * @param context - the answered session, its workspace, and caller lifetime,
90
+ * handed to the provider verbatim.
91
+ * @param lookup - the live injection-side registrations.
92
+ * @returns the injected user messages, in first-seen order.
93
+ */
94
+ export declare function expandAtlasMentions(messages: readonly UserMessage[], context: AtlasCallContext, lookup: (providerId: string) => AtlasRegistration | undefined): Promise<readonly UserMessage[]>;
95
+ /**
96
+ * Extract `dsh-session:` references from the claimed user messages in
97
+ * first-mention order and return the messages with the markdown mentions
98
+ * normalized to readable `@label` text.
99
+ * @param messages - the claimed user messages.
100
+ * @returns structured references plus the cleaned message copy.
101
+ */
102
+ export declare function collectChatReferences(messages: readonly UserMessage[]): {
103
+ readonly references: readonly SessionReferenceInput[];
104
+ readonly cleaned: readonly UserMessage[];
105
+ };
106
+ /**
107
+ * Normalize `dsh-session:` markdown mentions in the user messages to
108
+ * readable `@label` text without preparing any context. Applied by the
109
+ * pre-step wrapper whenever chat references are enabled so the raw URI never
110
+ * reaches the model; unknown labels stay as parsed.
111
+ * @param messages - the assembled step messages.
112
+ * @returns the cleaned message copy.
113
+ */
114
+ export declare function cleanChatMentions(messages: readonly UserMessage[]): readonly UserMessage[];
115
+ /**
116
+ * Prepare one aggregated past-chat snapshot for the claimed user messages.
117
+ * Returns the official `additionalContext` user message, or undefined when
118
+ * the claim has no `dsh-session:` references or the resolver produced none.
119
+ * Errors are surfaced to the caller (the pre-step wrapper logs and continues).
120
+ * @param agent - the live agent whose session is the reference target.
121
+ * @param resolver - `ctx.sessionReferenceResolver` (official service).
122
+ * @param messages - the claimed user messages.
123
+ * @param signal - caller lifetime.
124
+ * @returns the context message to place before the user's own words.
125
+ */
126
+ export declare function expandChatMentions(agent: Agent, resolver: ChatResolver, messages: readonly UserMessage[], signal: AbortSignal): Promise<UserMessage | undefined>;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The anchors to try, in order, when locating the running Harness manifest.
3
+ *
4
+ * `entry` — the process's own entry point — is the Harness that is actually up,
5
+ * and it is the only anchor whose answer can be trusted when the plugin's own
6
+ * module graph reaches a *different* Harness build. That is the normal shape of
7
+ * a linked development install: the profile loads the plugin from the checkout
8
+ * while the running CLI comes from the global install, so a plugin-anchored
9
+ * lookup resolves the checkout (or nothing at all) and every `testedOn` claim
10
+ * would be judged against the wrong version. `self` stays as the fallback for
11
+ * launches where the entry point is a loader rather than the Harness.
12
+ * @param entry - `process.argv[1]`, or undefined when the process has none.
13
+ * @param self - this module's own URL.
14
+ * @returns the anchors, most trustworthy first.
15
+ */
16
+ export declare function versionAnchors(entry: string | undefined, self: string): readonly string[];
17
+ /**
18
+ * Read the first anchor that yields a manifest, or rethrow the last failure.
19
+ * @param anchors - candidate anchors, most trustworthy first.
20
+ * @param read - how to read the manifest at one anchor.
21
+ * @returns the manifest text from the first anchor that had one.
22
+ */
23
+ export declare function readFirstAvailable(anchors: readonly string[], read: (anchor: string) => string): string;
24
+ /**
25
+ * Read the installed DSH version.
26
+ * @param resolvePackageJson - how to locate the package manifest; injectable so
27
+ * the failure paths are testable without a broken install.
28
+ * @returns the version string, or undefined when it cannot be established.
29
+ */
30
+ export declare function readDshVersion(resolvePackageJson?: () => string): string | undefined;