indusagi-coding-agent 0.2.2 → 0.2.4
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/CHANGELOG.md +46 -0
- package/dist/entry.js +12434 -9445
- package/dist/guardrails.js +897 -37
- package/dist/index.js +14081 -11111
- package/dist/types/boot/heap.d.ts +31 -0
- package/dist/types/boot/runners/delegate-runner.d.ts +27 -1
- package/dist/types/boot/runners/server-mode.d.ts +71 -0
- package/dist/types/boot/runners/session.d.ts +26 -18
- package/dist/types/boot/runners/session.test.d.ts +6 -1
- package/dist/types/boot/server-token.d.ts +97 -0
- package/dist/types/capability-deck/cards/index.d.ts +1 -0
- package/dist/types/capability-deck/cards/task-card.d.ts +26 -2
- package/dist/types/capability-deck/cards/workflow-card.d.ts +55 -0
- package/dist/types/capability-deck/cards/workflow-card.test.d.ts +12 -0
- package/dist/types/capability-deck/contract.d.ts +7 -6
- package/dist/types/capability-deck/index.d.ts +1 -1
- package/dist/types/conductor/conductor.d.ts +24 -0
- package/dist/types/conductor/contract.d.ts +79 -7
- package/dist/types/conductor/index.d.ts +3 -3
- package/dist/types/conductor/permissions.d.ts +74 -4
- package/dist/types/conductor/post-edit-diagnostics.test.d.ts +8 -3
- package/dist/types/conductor/quota-error.d.ts +35 -0
- package/dist/types/conductor/signal-hub/translate.d.ts +4 -1
- package/dist/types/console/auth-status.d.ts +28 -0
- package/dist/types/console/components/AgentsView.d.ts +41 -0
- package/dist/types/console/components/BackgroundAgents.d.ts +63 -0
- package/dist/types/console/components/BackgroundAgents.test.d.ts +8 -0
- package/dist/types/console/components/Banner.d.ts +67 -33
- package/dist/types/console/components/TerminalConsole.d.ts +0 -5
- package/dist/types/console/components/welcome.d.ts +115 -0
- package/dist/types/console/components/welcome.test.d.ts +9 -0
- package/dist/types/console/contract.d.ts +16 -1
- package/dist/types/console/index.d.ts +3 -0
- package/dist/types/console/input/index.d.ts +1 -1
- package/dist/types/console/input/keymap.d.ts +2 -2
- package/dist/types/console/input/paste.d.ts +58 -6
- package/dist/types/console/overlays/approval-queue.d.ts +18 -1
- package/dist/types/console/overlays/boards.d.ts +55 -0
- package/dist/types/console/overlays/index.d.ts +1 -1
- package/dist/types/console/theme/adapter.d.ts +1 -1
- package/dist/types/console/theme/index.d.ts +1 -1
- package/dist/types/console/theme/palette.d.ts +10 -0
- package/dist/types/launch/login.d.ts +68 -0
- package/dist/types/launch/oauth.test.d.ts +20 -0
- package/dist/types/window-budget/summarize/condense.d.ts +6 -0
- package/dist/types/workflow-engine/agent-runner.d.ts +124 -0
- package/dist/types/workflow-engine/agent-runner.test.d.ts +8 -0
- package/dist/types/workflow-engine/display.d.ts +148 -0
- package/dist/types/workflow-engine/display.test.d.ts +1 -0
- package/dist/types/workflow-engine/engine.d.ts +183 -0
- package/dist/types/workflow-engine/engine.test.d.ts +1 -0
- package/dist/types/workflow-engine/index.d.ts +21 -0
- package/dist/types/workflow-engine/parse.d.ts +64 -0
- package/dist/types/workflow-engine/parse.test.d.ts +1 -0
- package/dist/types/workflow-engine/structured-output.d.ts +51 -0
- package/dist/types/workflow-engine/structured-output.test.d.ts +1 -0
- package/dist/types/workspace/brand.d.ts +1 -1
- package/package.json +2 -2
- package/dist/types/console/components/Emblem.d.ts +0 -49
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heap headroom guard.
|
|
3
|
+
*
|
|
4
|
+
* Node's default old-space cap (~2 GB on 64-bit builds) is too small for heavy
|
|
5
|
+
* runs — most acutely a burst of parallel sub-agents whose combined transcripts
|
|
6
|
+
* push the resident heap past the default and abort the whole process with a V8
|
|
7
|
+
* "JavaScript heap out of memory" fatal (the exact crash this guards against).
|
|
8
|
+
*
|
|
9
|
+
* `--max-old-space-size` can only be set at process launch, so before any real
|
|
10
|
+
* work begins we re-exec the *same* program once with a raised cap, inherit its
|
|
11
|
+
* stdio (so the interactive TUI runs unchanged in the child), and adopt its exit
|
|
12
|
+
* code. The re-exec is one level deep: the child carries `INDUS_HEAP_BOOSTED=1`
|
|
13
|
+
* so it skips the guard and runs the agent directly.
|
|
14
|
+
*
|
|
15
|
+
* Controlled by env:
|
|
16
|
+
* INDUS_MAX_HEAP_MB target old-space size in MB (default 4096; 0 disables
|
|
17
|
+
* the guard entirely and runs in-process).
|
|
18
|
+
* INDUS_HEAP_BOOSTED set internally on the child; never set this yourself.
|
|
19
|
+
*
|
|
20
|
+
* If the re-exec cannot spawn (a locked-down sandbox, a missing argv[1]) the
|
|
21
|
+
* guard silently falls back to running in the current, un-boosted process rather
|
|
22
|
+
* than failing to start.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Ensure the process has heap headroom, re-execing once if it does not.
|
|
26
|
+
*
|
|
27
|
+
* Returns normally in three cases: the guard is disabled, the cap is already
|
|
28
|
+
* raised, or the re-exec could not be spawned. Otherwise it does NOT return —
|
|
29
|
+
* it runs the boosted child to completion and exits with the child's status.
|
|
30
|
+
*/
|
|
31
|
+
export declare function ensureHeapHeadroom(): void;
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* The `spawn`/`tools` options are pure test seams — they let a unit test drive
|
|
26
26
|
* the runner with an in-memory fake instead of a real network round-trip.
|
|
27
27
|
*/
|
|
28
|
-
import { type AgentMessage } from "../../conductor";
|
|
28
|
+
import { type AgentMessage, type SessionPermissionPolicy } from "../../conductor";
|
|
29
29
|
import { type AgentTool } from "../../capability-deck";
|
|
30
30
|
import type { DelegateRunner } from "../../capability-deck/cards/task-card";
|
|
31
31
|
/**
|
|
@@ -43,6 +43,12 @@ export interface DelegateSubAgent {
|
|
|
43
43
|
messages: readonly AgentMessage[];
|
|
44
44
|
error?: string;
|
|
45
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* Optional event subscription (the real framework `Agent` provides it). The
|
|
48
|
+
* runner uses it to recompute live token spend as the sub-agent works; a test
|
|
49
|
+
* fake may omit it, in which case no progress is reported.
|
|
50
|
+
*/
|
|
51
|
+
subscribe?(listener: () => void): () => void;
|
|
46
52
|
}
|
|
47
53
|
/** Configuration for {@link createDelegateRunner}. */
|
|
48
54
|
export interface DelegateRunnerOptions {
|
|
@@ -69,6 +75,26 @@ export interface DelegateRunnerOptions {
|
|
|
69
75
|
* `task` card — the recursion guard).
|
|
70
76
|
*/
|
|
71
77
|
readonly tools?: () => AgentTool[];
|
|
78
|
+
/**
|
|
79
|
+
* Resolve the current server-tier gateway routing map (provider -> gateway
|
|
80
|
+
* base url). Called FRESH on every `run()` — never cached — so a mid-session
|
|
81
|
+
* `/login` (to "Indus Server"), including one that lands after this runner was
|
|
82
|
+
* constructed but before a given delegated call, is always picked up. This
|
|
83
|
+
* mirrors {@link getApiKey}, which is likewise invoked per-request rather than
|
|
84
|
+
* resolved once at construction.
|
|
85
|
+
*/
|
|
86
|
+
readonly getGatewayBaseUrls?: () => Promise<Record<string, string>>;
|
|
87
|
+
/**
|
|
88
|
+
* The parent session's live permission policy: the SAME mutable rule list the
|
|
89
|
+
* parent gate reads plus a live getter onto the conductor's current mode. When
|
|
90
|
+
* present, every spawned sub-agent runs under a RESOLVER-LESS gate built from
|
|
91
|
+
* it — deny/ask rules, plan-mode enforcement, and the catastrophic-bash
|
|
92
|
+
* blocklist apply per inner tool call, and a mid-run mode switch (Shift+Tab)
|
|
93
|
+
* retargets the very next delegated tool call. A sub-agent cannot prompt, so
|
|
94
|
+
* an `ask` decision deterministically denies with an actionable message.
|
|
95
|
+
* Absent (a bare test construction), the sub-agent runs ungated as before.
|
|
96
|
+
*/
|
|
97
|
+
readonly permissionPolicy?: SessionPermissionPolicy;
|
|
72
98
|
}
|
|
73
99
|
/**
|
|
74
100
|
* Build a live {@link DelegateRunner} the host wires into the deck context.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boot helper: decide whether a provider runs in **server mode** (Case B).
|
|
3
|
+
*
|
|
4
|
+
* A model turn takes one of three paths (see LOGIN_GATEWAY_PLAN.md §1):
|
|
5
|
+
* - **A. Local key** — a usable key for the provider is stored in the on-disk
|
|
6
|
+
* auth vault (or exported in the environment). The framework calls the
|
|
7
|
+
* provider directly; behaviour is unchanged and this module returns
|
|
8
|
+
* `{ serverMode: false }`.
|
|
9
|
+
* - **B. Server tier** — the provider is gateway-eligible, the user has **no**
|
|
10
|
+
* usable local key, and they hold a **valid server token**. The session token
|
|
11
|
+
* is vended as the provider "key" and the model is re-routed through the indus
|
|
12
|
+
* gateway. This module returns `{ serverMode: true, token }`.
|
|
13
|
+
* - **C. Blocked** — no local key and no valid token: `{ serverMode: false }`
|
|
14
|
+
* (the resolver then falls through to the framework's own env lookup, which
|
|
15
|
+
* surfaces the usual "no API key" guidance pointing at `indus login`).
|
|
16
|
+
*
|
|
17
|
+
* The two consumers in {@link file://./session.ts} call this with the SAME
|
|
18
|
+
* `(ctx, provider, vault)` triple so the key-resolver fallback and the
|
|
19
|
+
* gateway-base-url computation always agree on whether server mode is active.
|
|
20
|
+
*/
|
|
21
|
+
import type { BootContext } from "../contract";
|
|
22
|
+
import type { AuthVault } from "../../launch/contract";
|
|
23
|
+
/**
|
|
24
|
+
* The outcome of {@link resolveServerMode}: whether the provider should route
|
|
25
|
+
* through the gateway this run, and (when so) the session token to hand back as
|
|
26
|
+
* the provider api key.
|
|
27
|
+
*/
|
|
28
|
+
export interface ServerModeResult {
|
|
29
|
+
/** `true` => bind the gateway base url and use {@link token} as the key. */
|
|
30
|
+
serverMode: boolean;
|
|
31
|
+
/** The session token (`access_token`) to vend as the key, when `serverMode`. */
|
|
32
|
+
token?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Whether `provider` may be routed through the indus gateway. Excludes the
|
|
36
|
+
* non-portable providers (vertex / bedrock / codex) and the deferred opencode
|
|
37
|
+
* `anthropic-messages` api per the §B.4 caveat.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isGatewayEligibleProvider(provider: string): boolean;
|
|
40
|
+
/** The server-tier provider slugs (for default-model selection / listing). */
|
|
41
|
+
export declare function serverTierProviders(): readonly string[];
|
|
42
|
+
/**
|
|
43
|
+
* Decide whether `provider` runs in server mode for this session.
|
|
44
|
+
*
|
|
45
|
+
* Server mode is active when ALL hold:
|
|
46
|
+
* 1. {@link isGatewayEligibleProvider}(provider) — excludes vertex/bedrock/codex
|
|
47
|
+
* and the deferred opencode `anthropic-messages` api (§B.4);
|
|
48
|
+
* 2. no EXPLICIT local key — the vault holds no usable key for the provider
|
|
49
|
+
* (an ambient env var is intentionally ignored for server-tier providers);
|
|
50
|
+
* 3. {@link hasValidServerToken}() — a stored, non-expired server token exists.
|
|
51
|
+
*
|
|
52
|
+
* Returns `{ serverMode: false }` whenever any condition fails, so the
|
|
53
|
+
* local-key (Case A) path is preserved byte-for-byte: the resolver then returns
|
|
54
|
+
* `undefined` and no gateway base url is bound.
|
|
55
|
+
*
|
|
56
|
+
* @param _ctx the boot context (reserved for future per-run policy; the vault is
|
|
57
|
+
* passed explicitly so callers share one instance)
|
|
58
|
+
* @param provider the framework provider slug to evaluate
|
|
59
|
+
* @param vault the on-disk credential vault to probe for a local key
|
|
60
|
+
*/
|
|
61
|
+
export declare function resolveServerMode(_ctx: BootContext, provider: string, vault: AuthVault): Promise<ServerModeResult>;
|
|
62
|
+
/**
|
|
63
|
+
* Build the per-provider gateway base-url map for THIS session: for every
|
|
64
|
+
* gateway-eligible provider currently in server mode (no explicit local key +
|
|
65
|
+
* valid token), map `provider -> ${INDUS_SERVER_URL}/gateway/${provider}`.
|
|
66
|
+
*
|
|
67
|
+
* The conductor consults this map at EVERY model bind — including a runtime
|
|
68
|
+
* `/model` switch — so selecting ANY server-tier model (not just the one the
|
|
69
|
+
* session launched on) routes through the gateway. Empty when nothing qualifies.
|
|
70
|
+
*/
|
|
71
|
+
export declare function resolveServerGatewayUrls(ctx: BootContext, vault: AuthVault): Promise<Record<string, string>>;
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
* {@link ModelMatcher}; the conductor itself is built lazily so no framework agent
|
|
9
9
|
* is constructed until the first turn runs.
|
|
10
10
|
*/
|
|
11
|
-
import { type AgentTool, type SessionConductor } from "../../conductor";
|
|
11
|
+
import { type AgentTool, type ApprovalResolver, type CanUseToolFn, type PermissionMode, type PermissionRule, type SessionConductor } from "../../conductor";
|
|
12
12
|
import { type MemoryStore } from "../../capability-deck";
|
|
13
13
|
import { type DelegateRunner } from "../../capability-deck/cards/task-card";
|
|
14
|
+
import type { WorkflowAgentRunner } from "../../workflow-engine";
|
|
14
15
|
import { type CheckpointStore } from "./checkpoint";
|
|
15
16
|
import { type ContextDoc, type SkillCard } from "../../briefing";
|
|
16
17
|
import type { BootContext, Invocation } from "../contract";
|
|
@@ -33,23 +34,7 @@ export declare function resolveModelId(ctx: BootContext): string;
|
|
|
33
34
|
* bad/unreadable skills dir never sinks the session.
|
|
34
35
|
*/
|
|
35
36
|
export declare function gatherModelSkills(cwd: string): SkillCard[];
|
|
36
|
-
|
|
37
|
-
* Select the tool deck for the run, honouring `--no-tools` (empty) and `--tools`
|
|
38
|
-
* (allow-list). Tool ids are matched case-insensitively with `_`/`-` stripped, so
|
|
39
|
-
* a `--tools web_fetch,todo_read` request lines up with the deck's `webfetch` /
|
|
40
|
-
* `todoread` ids.
|
|
41
|
-
*/
|
|
42
|
-
/**
|
|
43
|
-
* @param runner an optional live sub-agent {@link DelegateRunner}; when present it
|
|
44
|
-
* is injected under {@link DELEGATE_HANDLE_KEY} so the `task` card delegates for
|
|
45
|
-
* real instead of returning its `STUB_NOTE`. Omitted by callers that only need
|
|
46
|
-
* a deck (the card then degrades gracefully).
|
|
47
|
-
* @param checkpoint an optional per-session {@link CheckpointStore}; when present
|
|
48
|
-
* it is injected under {@link CHECKPOINT_HANDLE_KEY} so the framework's
|
|
49
|
-
* write/edit tools snapshot a file's pre-mutation content (rewind, #24). Omitted
|
|
50
|
-
* callers get no checkpointing (the tools no-op the snapshot).
|
|
51
|
-
*/
|
|
52
|
-
export declare function selectTools(cwd: string, inv: Invocation, runner?: DelegateRunner, memoryStore?: MemoryStore, checkpoint?: CheckpointStore): AgentTool[];
|
|
37
|
+
export declare function selectTools(cwd: string, inv: Invocation, runner?: DelegateRunner, memoryStore?: MemoryStore, checkpoint?: CheckpointStore, workflowRunner?: WorkflowAgentRunner): AgentTool[];
|
|
53
38
|
/**
|
|
54
39
|
* Compose the run's system prompt: `--system` replaces the built-in briefing,
|
|
55
40
|
* `--append-system` adds a trailing block, and both compose (override then
|
|
@@ -69,6 +54,29 @@ export declare function composeSystem(tools: AgentTool[], inv: Invocation, cwd:
|
|
|
69
54
|
* @param cwd the run's working directory
|
|
70
55
|
*/
|
|
71
56
|
export declare function sessionScopeDir(sessionsRoot: string, cwd: string): string;
|
|
57
|
+
/**
|
|
58
|
+
* Build the `canUseTool` gate factory for a boot run.
|
|
59
|
+
*
|
|
60
|
+
* The factory receives a getter onto the conductor's LIVE permission mode plus the
|
|
61
|
+
* conductor's stable approval delegate, and returns the gate that reads them. The
|
|
62
|
+
* delegate is threaded straight into `requestApproval`: on a NON-interactive boot
|
|
63
|
+
* (oneshot / link) no resolver is ever installed, so the delegate denies and an
|
|
64
|
+
* `ask` decision deterministically denies with an actionable message. The
|
|
65
|
+
* interactive (React) console installs its overlay resolver via the conductor's
|
|
66
|
+
* `setApprovalResolver` AFTER mount, at which point the SAME delegate begins
|
|
67
|
+
* routing `ask` decisions to the overlay — no rebuild, fully additive.
|
|
68
|
+
*
|
|
69
|
+
* `rules` is the session's LIVE mutable rule list: the gate re-scans it on every
|
|
70
|
+
* call, and an `allow-always` approval appends into it (via `appendAllowRule`
|
|
71
|
+
* below), so the approval is remembered for the remainder of the session — and
|
|
72
|
+
* ONLY the session; nothing is ever written back to settings. Every gate the
|
|
73
|
+
* factory mints (and every sub-agent gate built over the same array) sees the
|
|
74
|
+
* appended rules immediately.
|
|
75
|
+
*
|
|
76
|
+
* Exported for the boot tests; product callers go through
|
|
77
|
+
* {@link buildSessionConductor}.
|
|
78
|
+
*/
|
|
79
|
+
export declare function buildPermissionGate(rules: PermissionRule[], mode: PermissionMode, tools: readonly AgentTool[], planReachable?: boolean): ((currentMode: () => PermissionMode, requestApproval?: ApprovalResolver) => CanUseToolFn) | undefined;
|
|
72
80
|
export declare function buildSessionConductor(ctx: BootContext): Promise<SessionConductor>;
|
|
73
81
|
/**
|
|
74
82
|
* The prompts a oneshot run submits: the positional first prompt when present,
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Skills-surface wiring (#7 / fixes #11).
|
|
2
|
+
* Skills-surface wiring (#7 / fixes #11) + the boot permission-gate factory.
|
|
3
3
|
*
|
|
4
4
|
* Proves the chain that makes on-disk `SKILL.md` cards visible to the model:
|
|
5
5
|
* `gatherModelSkills` walks `cwd/.indusagi/skills`, drops any card flagged
|
|
6
6
|
* `disable-model-invocation`, and the survivors render into the briefing's
|
|
7
7
|
* `<available_skills>` block via `composeSystem`. A `--system` override must NOT
|
|
8
8
|
* carry the skills block (it replaces the whole prompt).
|
|
9
|
+
*
|
|
10
|
+
* `buildPermissionGate` is pinned here too: default mode ALWAYS builds a gate
|
|
11
|
+
* (only a rule-less bypass boot with plan unreachable goes gate-free), and the
|
|
12
|
+
* factory wires `appendAllowRule` into the live rule list so an `allow-always`
|
|
13
|
+
* approval is remembered for the remainder of the session (B2).
|
|
9
14
|
*/
|
|
10
15
|
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-token store — the boot-layer persistence for the indus device-login
|
|
3
|
+
* session token. This is the app side of the login + model-gateway contract: a
|
|
4
|
+
* successful `indus login` device flow writes the better-auth session token
|
|
5
|
+
* here, and the key resolver later reads it back to drive "server mode" (Case B
|
|
6
|
+
* — no local provider key, but a valid server session, so requests are routed
|
|
7
|
+
* through the indus-server gateway with the session token as the api key).
|
|
8
|
+
*
|
|
9
|
+
* The token lives in a single JSON file under the app's profile directory
|
|
10
|
+
* (`~/.indusagi/agent/server-token.json`) — deliberately NOT the framework's
|
|
11
|
+
* `~/.better-auth` location, so the CLI session is isolated from any other
|
|
12
|
+
* tooling. As with the credential vault, the file is tiny and access is
|
|
13
|
+
* interactive, so we read / write the whole file each time and tolerate a
|
|
14
|
+
* missing or malformed file as "no token".
|
|
15
|
+
*
|
|
16
|
+
* Ported from supercli `server/src/lib/token.ts`; the load-bearing detail is the
|
|
17
|
+
* `expires_in` (seconds, from the device-flow response) → `expires_at` (absolute
|
|
18
|
+
* ISO timestamp, on disk) conversion, which lets {@link isServerTokenExpired}
|
|
19
|
+
* decide freshness without re-deriving the clock offset.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Root of the indus-server. Used to build the gateway base URL and the
|
|
23
|
+
* device-login endpoints. Any trailing slash(es) are stripped so callers can
|
|
24
|
+
* append paths with a single separator.
|
|
25
|
+
*/
|
|
26
|
+
export declare const INDUS_SERVER_URL: string;
|
|
27
|
+
/** The app profile directory that holds the server session token. */
|
|
28
|
+
export declare const CONFIG_DIR: string;
|
|
29
|
+
/** Absolute path of the JSON file the session token is persisted to. */
|
|
30
|
+
export declare const TOKEN_FILE: string;
|
|
31
|
+
/** On-disk token shape (what {@link storeServerToken} writes / {@link getServerToken} returns). */
|
|
32
|
+
export interface TokenData {
|
|
33
|
+
/** The better-auth session token, used as the gateway api key in server mode. */
|
|
34
|
+
access_token: string;
|
|
35
|
+
/** Optional refresh token, when the device flow returns one. */
|
|
36
|
+
refresh_token?: string;
|
|
37
|
+
/** Token scheme; defaults to `"Bearer"`. */
|
|
38
|
+
token_type: string;
|
|
39
|
+
/** Optional granted scope string. */
|
|
40
|
+
scope?: string;
|
|
41
|
+
/** Absolute expiry as an ISO string, or null when the token has no expiry. */
|
|
42
|
+
expires_at: string | null;
|
|
43
|
+
/** When this record was written, as an ISO string. */
|
|
44
|
+
created_at: string;
|
|
45
|
+
}
|
|
46
|
+
/** Device-flow response shape accepted by {@link storeServerToken} (`expires_in` → `expires_at`). */
|
|
47
|
+
export interface ServerTokenInput {
|
|
48
|
+
/** The better-auth session token. */
|
|
49
|
+
access_token: string;
|
|
50
|
+
/** Optional refresh token. */
|
|
51
|
+
refresh_token?: string;
|
|
52
|
+
/** Token scheme; defaults to `"Bearer"` when omitted. */
|
|
53
|
+
token_type?: string;
|
|
54
|
+
/** Optional granted scope string. */
|
|
55
|
+
scope?: string;
|
|
56
|
+
/** Lifetime in seconds, relative to now; converted to an absolute `expires_at`. */
|
|
57
|
+
expires_in?: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Read the stored session token, tolerating a missing or malformed file as
|
|
61
|
+
* "no token".
|
|
62
|
+
*
|
|
63
|
+
* @returns the parsed {@link TokenData}, or `null` when nothing is stored.
|
|
64
|
+
*/
|
|
65
|
+
export declare function getServerToken(): Promise<TokenData | null>;
|
|
66
|
+
/**
|
|
67
|
+
* Persist a session token from a device-flow response, converting the relative
|
|
68
|
+
* `expires_in` (seconds) into an absolute `expires_at` ISO timestamp and
|
|
69
|
+
* defaulting `token_type` to `"Bearer"`. Creates the profile directory if
|
|
70
|
+
* needed and writes the file with owner-only permissions.
|
|
71
|
+
*
|
|
72
|
+
* @param token the device-flow token payload.
|
|
73
|
+
* @returns `true` on success, `false` if the write failed.
|
|
74
|
+
*/
|
|
75
|
+
export declare function storeServerToken(token: ServerTokenInput): Promise<boolean>;
|
|
76
|
+
/**
|
|
77
|
+
* Remove the stored session token (used by `indus logout`). A missing file is
|
|
78
|
+
* treated as nothing-to-do.
|
|
79
|
+
*
|
|
80
|
+
* @returns `true` when a file was deleted, `false` when none existed / removal failed.
|
|
81
|
+
*/
|
|
82
|
+
export declare function clearServerToken(): Promise<boolean>;
|
|
83
|
+
/**
|
|
84
|
+
* Decide whether a token is expired. A token counts as expired when it is
|
|
85
|
+
* absent, has no `expires_at`, or has under 5 minutes of life remaining (the
|
|
86
|
+
* margin keeps a long turn from racing the expiry boundary).
|
|
87
|
+
*
|
|
88
|
+
* @param token the token to inspect (or `null`).
|
|
89
|
+
* @returns `true` when the token is missing or stale.
|
|
90
|
+
*/
|
|
91
|
+
export declare function isServerTokenExpired(token: TokenData | null): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Convenience predicate: there is a stored token and it is not expired.
|
|
94
|
+
*
|
|
95
|
+
* @returns `true` when a usable (fresh) session token is on disk.
|
|
96
|
+
*/
|
|
97
|
+
export declare function hasValidServerToken(): Promise<boolean>;
|
|
@@ -21,6 +21,7 @@ import type { CapabilityCard } from "../contract";
|
|
|
21
21
|
export { todoCard, buildTodoCapability, TodoLedger, type TodoItem, type TodoState, type TodoWeight, type TodoParamsType, type TodoDetails, } from "./todo-card";
|
|
22
22
|
export { daemonCard, buildDaemonCapability, DaemonTable, type DaemonState, type DaemonParamsType, type DaemonDetails, } from "./bg-process-card";
|
|
23
23
|
export { taskCard, buildTaskCapability, DELEGATE_HANDLE_KEY, type DelegateRunner, type DelegateRequest, type DelegateResult, type TaskParamsType, type TaskDetails, } from "./task-card";
|
|
24
|
+
export { workflowCard, buildWorkflowCapability, WORKFLOW_HANDLE_KEY, type WorkflowParamsType, type WorkflowDetails, } from "./workflow-card";
|
|
24
25
|
export { saasCard, buildSaasCapability, SAAS_GATEWAY_KEY, type SaasGatewayPort, type RemoteToolSummary, type RemoteExecution, type SaasParamsType, type SaasDetails, } from "./saas-card";
|
|
25
26
|
export { memoryCard, buildMemoryCapability, InMemoryStore, MEMORY_HANDLE_KEY, type MemoryStore, type MemoryParamsType, type MemoryDetails, } from "./memory-card";
|
|
26
27
|
export { enterPlanModeCard, exitPlanModeCard, buildEnterPlanModeCapability, buildExitPlanModeCapability, PLAN_HANDLE_KEY, type PlanController, type EnterPlanParamsType, type EnterPlanDetails, type ExitPlanParamsType, type ExitPlanDetails, } from "./plan-tools";
|
|
@@ -37,6 +37,20 @@ export interface DelegateResult {
|
|
|
37
37
|
/** The sub-agent's final report, surfaced to the parent agent verbatim. */
|
|
38
38
|
readonly report: string;
|
|
39
39
|
}
|
|
40
|
+
/** One line of a sub-agent's live activity stream (for the drill-in view). */
|
|
41
|
+
export interface ActivityLine {
|
|
42
|
+
/** What kind of step this is, used to colour it. */
|
|
43
|
+
readonly tone: "reason" | "tool" | "result";
|
|
44
|
+
/** The display text (already shortened to a single line). */
|
|
45
|
+
readonly text: string;
|
|
46
|
+
}
|
|
47
|
+
/** Live progress a running sub-agent streams back while it works. */
|
|
48
|
+
export interface DelegateProgress {
|
|
49
|
+
/** Cumulative tokens the sub-agent has spent so far (input + output). */
|
|
50
|
+
readonly tokens: number;
|
|
51
|
+
/** The sub-agent's recent activity (reasoning + tool steps), newest last. */
|
|
52
|
+
readonly activity: readonly ActivityLine[];
|
|
53
|
+
}
|
|
40
54
|
/**
|
|
41
55
|
* The contract a host's sub-agent runner must satisfy to be wired in.
|
|
42
56
|
*
|
|
@@ -47,8 +61,14 @@ export interface DelegateResult {
|
|
|
47
61
|
export interface DelegateRunner {
|
|
48
62
|
/** Optional roster of named agent profiles, surfaced in the tool description. */
|
|
49
63
|
listAgents?(): readonly string[];
|
|
50
|
-
/**
|
|
51
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Run one delegated objective and resolve with the sub-agent's report.
|
|
66
|
+
*
|
|
67
|
+
* When an `onProgress` callback is supplied the runner streams live metrics
|
|
68
|
+
* (token spend) as the sub-agent works, so the host can surface them (the
|
|
69
|
+
* background-agents panel). Optional — a runner may ignore it.
|
|
70
|
+
*/
|
|
71
|
+
run(request: DelegateRequest, signal?: AbortSignal, onProgress?: (progress: DelegateProgress) => void): Promise<DelegateResult>;
|
|
52
72
|
}
|
|
53
73
|
declare const TaskParams: import("@sinclair/typebox").TObject<{
|
|
54
74
|
objective: import("@sinclair/typebox").TString;
|
|
@@ -65,6 +85,10 @@ export interface TaskDetails {
|
|
|
65
85
|
readonly ok: boolean;
|
|
66
86
|
/** The agent profile that ran, if one was named. */
|
|
67
87
|
readonly agent?: string;
|
|
88
|
+
/** Cumulative tokens the sub-agent spent — streamed live on progress updates. */
|
|
89
|
+
readonly tokens?: number;
|
|
90
|
+
/** The sub-agent's recent activity — streamed live for the drill-in view. */
|
|
91
|
+
readonly activity?: readonly ActivityLine[];
|
|
68
92
|
}
|
|
69
93
|
/**
|
|
70
94
|
* Build the task/delegate capability.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow capability — orchestrate a deterministic fan-out of subagents.
|
|
3
|
+
*
|
|
4
|
+
* App-novel wiring, sibling to (and UNRELATED to) the {@link "./task-card"}
|
|
5
|
+
* delegate card. The `workflow` tool runs a deterministic JavaScript workflow
|
|
6
|
+
* script that calls `agent()`, `parallel()`, and `pipeline()` to fan work out
|
|
7
|
+
* across many fresh subagents and fan their results back in, all under a live
|
|
8
|
+
* `◆ Workflow:` progress tree streamed into the tool result.
|
|
9
|
+
*
|
|
10
|
+
* The actual subagent runner is NOT owned by this card — it is a framework /
|
|
11
|
+
* boot concern injected through {@link DeckContext.framework} under the
|
|
12
|
+
* {@link WORKFLOW_HANDLE_KEY} key. When that handle is present the capability
|
|
13
|
+
* really runs the workflow (via the pure {@link runWorkflow} engine); when it is
|
|
14
|
+
* absent (tests, headless tooling, a host that has not wired the runner) the
|
|
15
|
+
* capability degrades gracefully to a clearly-typed {@link STUB_NOTE} result
|
|
16
|
+
* rather than throwing, exactly like the task card's `readDelegateRunner` path.
|
|
17
|
+
*
|
|
18
|
+
* Recursion guard: this card is registered all-profile-only in
|
|
19
|
+
* {@link "../cards/index"} (`APP_NOVEL_CARDS`), so the `'authoring'` deck a
|
|
20
|
+
* workflow subagent runs against EXCLUDES it — a subagent cannot call `workflow`.
|
|
21
|
+
*
|
|
22
|
+
* Live UI: each engine lifecycle callback mutates a {@link WorkflowSnapshot} and
|
|
23
|
+
* calls the framework `onUpdate` with the snapshot rendered through
|
|
24
|
+
* {@link renderWorkflowText} (the v1 string renderer). Updates are coalesced to
|
|
25
|
+
* status transitions (phase / agent start / agent end), not every log line, to
|
|
26
|
+
* avoid render thrash. The conductor re-projects the framework
|
|
27
|
+
* `tool_execution_update` event to a `tool_update` product signal (stage 3).
|
|
28
|
+
*/
|
|
29
|
+
import { type Static } from "@sinclair/typebox";
|
|
30
|
+
import type { Capability, CapabilityCard, DeckContext } from "../contract";
|
|
31
|
+
import { type WorkflowSnapshot } from "../../workflow-engine";
|
|
32
|
+
/** Key under which a host wires a live workflow agent runner into the context. */
|
|
33
|
+
export declare const WORKFLOW_HANDLE_KEY: "workflow";
|
|
34
|
+
declare const WorkflowParams: import("@sinclair/typebox").TObject<{
|
|
35
|
+
script: import("@sinclair/typebox").TString;
|
|
36
|
+
args: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TAny>;
|
|
37
|
+
}>;
|
|
38
|
+
/** Statically-inferred parameter type the capability's `execute` receives. */
|
|
39
|
+
export type WorkflowParamsType = Static<typeof WorkflowParams>;
|
|
40
|
+
/** Structured detail returned alongside the model-facing content (the snapshot). */
|
|
41
|
+
export type WorkflowDetails = WorkflowSnapshot;
|
|
42
|
+
/**
|
|
43
|
+
* Build the workflow capability.
|
|
44
|
+
*
|
|
45
|
+
* If a {@link WorkflowAgentRunner} is present on the context it is bound and the
|
|
46
|
+
* tool truly orchestrates; otherwise the tool builds anyway and returns a typed,
|
|
47
|
+
* non-throwing stub so the deck stays assemblable in every environment.
|
|
48
|
+
*
|
|
49
|
+
* @param ctx the deck context; an optional runner is read from
|
|
50
|
+
* `ctx.framework[WORKFLOW_HANDLE_KEY]`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildWorkflowCapability(ctx: DeckContext): Capability<typeof WorkflowParams, WorkflowDetails>;
|
|
53
|
+
/** Catalog row for the workflow capability. */
|
|
54
|
+
export declare const workflowCard: CapabilityCard;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow card — focused unit tests.
|
|
3
|
+
*
|
|
4
|
+
* The card is a pure capability builder over the pure {@link runWorkflow} engine
|
|
5
|
+
* (an injected {@link WorkflowAgentRunner} does the spawning). These tests cover:
|
|
6
|
+
* - the STUB_NOTE degrade when no runner handle is wired (no throw),
|
|
7
|
+
* - a real run with an in-memory fake runner: lifecycle → snapshot,
|
|
8
|
+
* - abort flips running agents to skipped,
|
|
9
|
+
* - and the deck-assembly guarantee: workflow appears in the `all` profile but
|
|
10
|
+
* NOT in the `authoring` subagent profile (the recursion guard).
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
@@ -124,12 +124,13 @@ export type CardProfiles = readonly DeckProfile[];
|
|
|
124
124
|
* The named capability sets a session can be provisioned with — the profile
|
|
125
125
|
* table that replaces a trio of near-identical build functions.
|
|
126
126
|
*
|
|
127
|
-
* - `authoring` — the
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* - `all` — every registered capability, nothing withheld.
|
|
127
|
+
* - `authoring` — the READ-ONLY built-in subset: read/ls/search/web/
|
|
128
|
+
* checklist-read. No filesystem mutation, no shell, no app-novel cards —
|
|
129
|
+
* the deck sub-agents (task/workflow) are provisioned with (see
|
|
130
|
+
* {@link "./provision"}'s PROFILE_TABLE, the authoritative mapping).
|
|
131
|
+
* - `survey` — every built-in (mutating ones included), no app-novel cards.
|
|
132
|
+
* - `all` — every registered capability, nothing withheld. What an
|
|
133
|
+
* interactive coding session runs with.
|
|
133
134
|
*/
|
|
134
135
|
export type DeckProfile = "authoring" | "survey" | "all";
|
|
135
136
|
/**
|
|
@@ -31,7 +31,7 @@ export { CAPABILITY_CARDS, CAPABILITY_INDEX, CARD_PROFILES, capabilityIds, hasCa
|
|
|
31
31
|
* (checklist, background-process proxy, delegate/sub-agent, SaaS connector,
|
|
32
32
|
* working memory) plus their builders, stores, and injection-handle types.
|
|
33
33
|
*/
|
|
34
|
-
export { APP_NOVEL_CARDS, todoCard, buildTodoCapability, TodoLedger, type TodoItem, type TodoState, type TodoWeight, type TodoParamsType, type TodoDetails, daemonCard, buildDaemonCapability, DaemonTable, type DaemonState, type DaemonParamsType, type DaemonDetails, taskCard, buildTaskCapability, DELEGATE_HANDLE_KEY, type DelegateRunner, type DelegateRequest, type DelegateResult, type TaskParamsType, type TaskDetails, saasCard, buildSaasCapability, SAAS_GATEWAY_KEY, type SaasGatewayPort, type RemoteToolSummary, type RemoteExecution, type SaasParamsType, type SaasDetails, memoryCard, buildMemoryCapability, InMemoryStore, MEMORY_HANDLE_KEY, type MemoryStore, type MemoryParamsType, type MemoryDetails, enterPlanModeCard, exitPlanModeCard, buildEnterPlanModeCapability, buildExitPlanModeCapability, PLAN_HANDLE_KEY, planSlug, planFilePath, writePlan, readPlan, PLANS_DIRNAME, type PlanController, type EnterPlanParamsType, type EnterPlanDetails, type ExitPlanParamsType, type ExitPlanDetails, } from "./cards/index";
|
|
34
|
+
export { APP_NOVEL_CARDS, todoCard, buildTodoCapability, TodoLedger, type TodoItem, type TodoState, type TodoWeight, type TodoParamsType, type TodoDetails, daemonCard, buildDaemonCapability, DaemonTable, type DaemonState, type DaemonParamsType, type DaemonDetails, taskCard, buildTaskCapability, DELEGATE_HANDLE_KEY, type DelegateRunner, type DelegateRequest, type DelegateResult, type TaskParamsType, type TaskDetails, workflowCard, buildWorkflowCapability, WORKFLOW_HANDLE_KEY, type WorkflowParamsType, type WorkflowDetails, saasCard, buildSaasCapability, SAAS_GATEWAY_KEY, type SaasGatewayPort, type RemoteToolSummary, type RemoteExecution, type SaasParamsType, type SaasDetails, memoryCard, buildMemoryCapability, InMemoryStore, MEMORY_HANDLE_KEY, type MemoryStore, type MemoryParamsType, type MemoryDetails, enterPlanModeCard, exitPlanModeCard, buildEnterPlanModeCapability, buildExitPlanModeCapability, PLAN_HANDLE_KEY, planSlug, planFilePath, writePlan, readPlan, PLANS_DIRNAME, type PlanController, type EnterPlanParamsType, type EnterPlanDetails, type ExitPlanParamsType, type ExitPlanDetails, } from "./cards/index";
|
|
35
35
|
/**
|
|
36
36
|
* Bridge ledger — event-sourced enrollment of dynamically grafted MCP tools:
|
|
37
37
|
* content-hash / ULID key minting, the immutable {@link BridgeLedger} value with
|
|
@@ -89,6 +89,18 @@ export interface CondenseOpts {
|
|
|
89
89
|
readonly force?: boolean;
|
|
90
90
|
readonly model?: Model<any>;
|
|
91
91
|
readonly contextTokens?: number;
|
|
92
|
+
/**
|
|
93
|
+
* Cancellation for a manual `/compact`. A hook MAY honor it mid-summarization;
|
|
94
|
+
* the conductor always checks it after the hook returns and discards the
|
|
95
|
+
* result when aborted, so even a hook that ignores the signal cancels cleanly.
|
|
96
|
+
*/
|
|
97
|
+
readonly signal?: AbortSignal;
|
|
98
|
+
/**
|
|
99
|
+
* The bound model's credential, resolved through the session's per-call key
|
|
100
|
+
* resolver. Forwarded so the summarizer authenticates exactly like a turn —
|
|
101
|
+
* server-tier sessions have no env-var fallback for this.
|
|
102
|
+
*/
|
|
103
|
+
readonly apiKey?: string;
|
|
92
104
|
}
|
|
93
105
|
/**
|
|
94
106
|
* The pluggable condense hook. Given the active branch's messages (and an options
|
|
@@ -186,4 +198,16 @@ export declare function reduceState(prev: ConductorState, action: StateAction):
|
|
|
186
198
|
* @param deps injectable collaborators; all optional, live defaults supplied
|
|
187
199
|
*/
|
|
188
200
|
export declare function createSessionConductor(options: SessionConductorOptions, deps?: ConductorDeps): SessionConductor;
|
|
201
|
+
/**
|
|
202
|
+
* Return the framework model unchanged, or — when a gateway base URL is set
|
|
203
|
+
* ("server mode") — a CLONE with its `baseUrl` swapped to the gateway so the
|
|
204
|
+
* request flows through the quota-enforcing indus-server. Never mutates the
|
|
205
|
+
* shared catalog card (always spreads into a fresh object). When
|
|
206
|
+
* `gatewayBaseUrl` is `undefined` the model is returned by reference, keeping
|
|
207
|
+
* the local-key path byte-for-byte unchanged.
|
|
208
|
+
*/
|
|
209
|
+
export declare function withGatewayBaseUrl<M extends {
|
|
210
|
+
baseUrl: string;
|
|
211
|
+
provider: string;
|
|
212
|
+
}>(model: M, gatewayBaseUrls: Record<string, string> | undefined): M;
|
|
189
213
|
export {};
|