/** * JIT layer-2 tools — runtime assembly. * * `createTmTools(input)` is called ONCE per server() invocation and returns * the runtime the plugin merges into its hooks: * * const tm = await createTmTools(input) * return { config, "tool.execute.before", tool: tm.tools } * * It generates the run identity (run id + store-persisted HMAC key), resolves * the env config, sweeps expired run payloads (startup-only TTL reclamation) * and assembles the governed tool surface (tm_fetch + tm_memory / tm_search / * tm_webfetch / tm_join / tm_stats / tm_board_write / tm_ledger; * T0.4-verified shape: `{ tool: { tm_fetch: { description, args, * execute(args, ctx) } } }`). */ import type { HostEvent, PluginInput, ToolDefinition } from "../types.js"; import { type EnvProtectMode } from "../envprotect.js"; import { type TmConfig } from "./config.js"; import { type ConfigFileRoots } from "./config-files.js"; import { RunStore } from "./store.js"; import type { CapabilityRow } from "../capabilities.js"; import { rmForceSafe } from "../fs-safe.js"; export { rmForceSafe }; export { buildTmMemoryTool, MEMORY_CATEGORIES, MEMORY_CONTENT_MAX, MEMORY_TITLE_MAX, projectSlug, scoreMemory, parseMemoryMarkdown, renderMemoryMarkdown, } from "./memory.js"; export { buildLedgerTool, createStorageLedgerStore, normalizeLedger, emptyLedger, addItem, markItem, openItems, renderLedger, ledgerGoalLine, LEDGER_STATUSES, type Ledger, type LedgerItem, type LedgerStore, } from "./ledger.js"; export { buildDispatchTools, DISPATCH_TARGETS, lastAssistantText, renderChildLine, sessionApiOf, summarizeStates, } from "./dispatch.js"; export type { ChildRecord, DispatchDeps } from "./dispatch.js"; export interface TmRuntime { runId: string; config: TmConfig; store: RunStore; /** The ONE main pipeline instance (exposed for tests + tool builders). */ pipelines: ReturnType; tools: Record; /** Kill any long-lived session the tools own. ASYNC because the host's * dispose hook awaits it. No tool owns a child process any more (the * self-built browser is gone), so this is a no-op kept for the contract. */ dispose: () => Promise; /** Host event bus slice the async dispatcher needs (session.idle / * .error / .status settle the lead's children). */ observeDispatchEvent: (event: HostEvent) => void; /** v2: open a tm_join row for a child the HOST's own `subagent` tool created, so a * background dispatch is collectable instead of invisible. */ registerHostChild: (child: { sessionID: string; parentSessionID: string; agent: string; label: string; }) => boolean; /** v2: the registered host children (the retry governor tells a child's failures * apart from the lead's by this table — sub-agent vs main-agent chains). */ hostChildren: () => Array<{ sessionID: string; parentSessionID: string; agent: string; state: string; }>; /** Settle a registered child from the host's own completion envelope; false when this * process does not know the id. See `applyV2CompletionWatch`. */ settleHostChild: (sessionID: string, state: string) => boolean; /** Any child still running? Gates the per-request completion scan. */ hasOpenHostChild: () => boolean; /** Open async dispatches this plugin started (tests + observability). `adopted` / * `startedAt` ride along because the sub-agent concurrency cap leaves out the rows * nothing will ever settle (see `RunningChildLike`). */ dispatches: () => Array<{ sessionID: string; agent: string; label: string; state: string; adopted?: boolean; startedAt: number; }>; } export interface CreateTmToolsOptions { /** R6 mode — pass the plugin-level resolved value to keep ONE source. */ mode?: EnvProtectMode; /** R6 extra deny rules — same single-source rule. */ extra?: RegExp[]; /** A sub-agent child session entered our registry (adopted from the host's * session tree, or claimed by an id the lead named) — let the approval gate * register it so the sub-agent's own protected read opens the official * dialog instead of hard-throwing in an unregistered session. */ onChildSession?: (sessionID: string, agent: string) => void; /** Live host-capability matrix, rendered by tm_stats (the probe itself * lives at the plugin entry because that is where the host surfaces are * handed to us). */ capabilities?: () => CapabilityRow[]; /** Environment to resolve the tool config from. Defaults to `process.env`, * and exists so the two personalities can fork a DEFAULT without mutating the * host process's env (v1 keeps its shipped behaviour byte-exactly while v2 * opens the domain allowlist, which is a personality decision, not a global * one). Anything the user actually set always wins. */ env?: Record; /** Lowest-priority default overrides (BELOW the file layers): v2 uses it to * default `webfetchAllowedDomains` to `["*"]` when no file sets it. */ configDefaults?: Record; /** Test injection: skip the file layers entirely. */ envOnly?: boolean; /** Auto-generate the global config file at boot (default true). */ autoCreate?: boolean; /** Where the lead's LEDGER lives. v2 passes a `ctx.storage` adapter because * that host has no `todowrite` for the mandate to attach to; v1 passes nothing * and therefore registers no `tm_ledger` at all — its tool surface stays the * one the v1 personality was frozen with. */ ledgerStore?: import("./ledger.js").LedgerStore; /** What the v2 `ctx.session` bridge saw (attempted shapes, last host error), so * `tm_join` can report WHY a named id could not be claimed. */ sessionReaderReport?: () => { attempted: number; resolved: number; usedShape?: string; failedShapes: string[]; lastError?: string; }; /** Roots for the layered `team-mode.jsonc` reader. Injectable so tests point * at a temp dir and never read the user's real `~/.config/opencode`. */ configRoots?: ConfigFileRoots; } /** Collision-free shard key for a workspace path. It is a HASH rather than a * sanitized basename because the CJK paths this plugin actually meets strip * to nothing useful — `D:\扒取数据` and `D:\文档` both slug to "d", and a store * shard that collides is the exact bug this exists to kill. */ export declare function workspaceStoreKey(directory: string): string; /** The shard dir is created lazily, one per non-git workspace — so a machine * that runs this plugin's own test suite a hundred times grows a `w-*` * directory per throwaway temp dir (64 after a single dev session). Prune * the siblings that have produced nothing inside the TTL, never the live * one, and never with a bare rmSync (win32 silently no-ops on non-ASCII * paths, which would leave the directory in place and the loop lying about * what it removed). */ export declare function pruneStaleStoreShards(base: string, /** the live shard to protect; `null` when this workspace has no shard (a git * workspace stores at the base itself), which means every stale sibling is fair * game — the TTL, not the identity of the current workspace, is what keeps a * session's data alive */ keep: string | null, ttlMs: number, now?: number): string[]; /** A layout nothing reads is still a layout the user paid disk for. Sharding * moved the run/trajectory trees under `w-/`, which silently orphaned * the pre-shard `blackboard/` (runs + webcache) and `trajectory/` at the * shared tmpdir base — measured 503 MB and 2654 run dirs on one machine, and * no sweeper points there any more, so an upgrade would never reclaim it. * Drain them under the SAME TTL rule the live store uses: expired is * deletable, fresh is not (a session started before the upgrade may still be * writing there), and the empty shells go last. `memories/` and the team * blackboard's date-named dirs are still live at that base and are not * touched here. */ export declare function reclaimLegacyStoreBuckets(base: string, ttlMs: number, now?: number): string[]; export declare function createTmTools(input: PluginInput, opts?: CreateTmToolsOptions): Promise; export { DEFAULT_BASH_READONLY_ALLOWED, DEFAULT_WEBFETCH_DOMAINS, estimateTokens, parseAllowlistEnv, parseWebfetchAllowlistEnv, parseWeightsEnv, resolveConfig, resolveOnOff, coerceValue, shouldOffload, shorten, TM_CONFIG_DEFAULTS, } from "./config.js"; export { CONFIG_FILE_NAME, readConfigFiles, resolveGlobalDir, resolveLayeredTmConfig, renderConfigSection, type ConfigFileRoots, type ConfigFileRead, type LayeredTmConfig, } from "./config-files.js"; export { renderConfigTemplate, ensureGlobalConfig, type AutoCreateState } from "./config-template.js"; export { buildRef, hmacToken, isExpired, loadOrCreateHandleKey, newRunId, parseRef, REF_PATTERN, verifyToken, HANDLE_KEY_FILE, } from "./refs.js"; export { RunStore, USAGE_JSONL_RELPATH } from "./store.js"; export { buildPreview, buildStructureSummary, capTokens, contentTypeForPath, detectContentType, sniffContentType, } from "./preview.js"; export { assertReadablePath, classifyReadonlyCommand, isInsideDir, } from "./guard.js"; export { buildTmTools } from "./tools.js"; export { buildPipelines } from "./pipelines.js"; export type { TmDeps, TmPipelines } from "./pipelines.js"; export { buildWebfetchArgsSchema, buildSearchArgsSchema } from "./args-schema.js"; export { toToolResult, HANDLE_INVALID_MESSAGE, tmError } from "./result.js"; export type { TmPhase } from "./result.js"; export { runShellCommand, spawnShellFallback, cleanShellError } from "./shell-bridge.js"; export { buildTmWebfetchTool, checkWebUrl, extractWebResponse, extractSearchHits, renderSearchHits, fetchWebText, hitDomainBlacklist, setHitBlacklist, setPrivateSpacePolicy, HIT_DOMAIN_BLACKLIST_DEFAULT, hostAllowed, htmlToText, } from "./webfetch.js"; export type { SearchHit } from "./webfetch.js"; export { buildTmSearchTool, SEARCH_ENGINES, SEARCH_ENGINE_NAMES, renderNpmResults, renderGithubResults, renderWikiResults, } from "./search.js"; //# sourceMappingURL=index.d.ts.map