indusagi-coding-agent 0.2.3 → 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 +25 -0
- package/dist/entry.js +1733 -572
- package/dist/guardrails.js +21 -6
- package/dist/index.js +1687 -552
- package/dist/types/boot/heap.d.ts +31 -0
- package/dist/types/boot/runners/delegate-runner.d.ts +21 -1
- package/dist/types/boot/runners/server-mode.d.ts +71 -0
- package/dist/types/boot/runners/session.d.ts +24 -1
- 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/contract.d.ts +7 -6
- package/dist/types/conductor/conductor.d.ts +24 -0
- package/dist/types/conductor/contract.d.ts +71 -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/console/auth-status.d.ts +28 -0
- package/dist/types/console/components/TerminalConsole.d.ts +0 -5
- package/dist/types/console/contract.d.ts +13 -0
- package/dist/types/console/input/index.d.ts +1 -1
- package/dist/types/console/input/keymap.d.ts +1 -1
- package/dist/types/console/input/paste.d.ts +53 -1
- package/dist/types/console/overlays/approval-queue.d.ts +18 -1
- package/dist/types/console/overlays/index.d.ts +1 -1
- 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 +20 -1
- package/dist/types/workspace/brand.d.ts +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* quota-error.ts — maps the indus model-gateway's usage-limit response into a
|
|
3
|
+
* friendly, user-facing fault message.
|
|
4
|
+
*
|
|
5
|
+
* When a no-local-key, logged-in user runs a turn, the framework adapter is
|
|
6
|
+
* pointed at `${INDUS_SERVER_URL}/gateway/<provider>` (see the conductor's
|
|
7
|
+
* baseUrl rewrite). If that user is over their monthly token allowance, the
|
|
8
|
+
* server replies — *before* forwarding upstream — with:
|
|
9
|
+
*
|
|
10
|
+
* HTTP/1.1 429 Too Many Requests
|
|
11
|
+
* Content-Type: application/json
|
|
12
|
+
*
|
|
13
|
+
* { "error": "quota_exceeded", "used": <number>, "limit": <number> }
|
|
14
|
+
*
|
|
15
|
+
* The provider SDK / raw-fetch adapter turns that 429 into a thrown error. By
|
|
16
|
+
* the time it reaches the conductor it may be wrapped (an SDK `APIError`, a
|
|
17
|
+
* generic `Error`, a nested `cause` chain, or a plain string), so detection must
|
|
18
|
+
* be tolerant and walk the whole error chain rather than trust a single shape.
|
|
19
|
+
*
|
|
20
|
+
* This module is intentionally transport-agnostic and dependency-free so it can
|
|
21
|
+
* be unit-tested in isolation and imported from the conductor's retry chokepoint
|
|
22
|
+
* without pulling in any network/runtime modules.
|
|
23
|
+
*/
|
|
24
|
+
/** Detects the gateway's 429 quota body anywhere in the error chain. */
|
|
25
|
+
export declare function isQuotaFault(error: unknown): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Friendly user-facing text; `undefined` if `error` is not a quota fault.
|
|
28
|
+
*
|
|
29
|
+
* Includes the `<used>/<limit>` parenthetical when both numbers are parseable,
|
|
30
|
+
* and otherwise falls back to the same sentence without it. The `indus signin
|
|
31
|
+
* <provider>` hint steers the user toward supplying their own key (which takes
|
|
32
|
+
* the direct, un-metered local-key path), and the upgrade hint covers raising
|
|
33
|
+
* the server-side allowance.
|
|
34
|
+
*/
|
|
35
|
+
export declare function quotaErrorMessage(error: unknown): string | undefined;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared "does the user have a usable credential for this provider" probe.
|
|
3
|
+
*
|
|
4
|
+
* Used anywhere the console needs to know which providers are actually
|
|
5
|
+
* callable — the `/model` picker (only list authenticated providers) and the
|
|
6
|
+
* banner's Session panel (don't display an unauthenticated model as if it were
|
|
7
|
+
* ready to use) both need the exact same answer, so it lives here once.
|
|
8
|
+
*/
|
|
9
|
+
import type { OverlayServices } from "./contract";
|
|
10
|
+
/**
|
|
11
|
+
* Load the set of provider ids the user has USABLE credentials for, live, so a
|
|
12
|
+
* mid-session `/login` (either a local vault sign-in or the "Indus Server"
|
|
13
|
+
* server-tier device flow) is reflected without a restart.
|
|
14
|
+
*
|
|
15
|
+
* Two independent sources count: (1) any saved account in the local vault for a
|
|
16
|
+
* provider `listLoginProviders()` names, and (2) a valid server session token,
|
|
17
|
+
* which makes every gateway-eligible provider (`serverTierProviders()` —
|
|
18
|
+
* minimax, sarvam) usable even though the server tier never writes into the
|
|
19
|
+
* vault. Returns `null` until the asynchronous probe settles.
|
|
20
|
+
*
|
|
21
|
+
* `refreshKey` re-runs the probe whenever it changes by reference/value — a
|
|
22
|
+
* short-lived overlay (the `/model` picker) can leave it at its default since
|
|
23
|
+
* it remounts fresh on every open anyway, but a component mounted once for the
|
|
24
|
+
* whole session (the banner, the status bar) MUST pass something that changes
|
|
25
|
+
* right when a sign-in completes (e.g. the console's current status toast),
|
|
26
|
+
* otherwise this only ever reflects whatever was true at session start.
|
|
27
|
+
*/
|
|
28
|
+
export declare function useAuthenticatedProviders(services: OverlayServices | undefined, refreshKey?: unknown): Set<string> | null;
|
|
@@ -24,9 +24,4 @@
|
|
|
24
24
|
* `indusagi/react-ink`.
|
|
25
25
|
*/
|
|
26
26
|
import type { ConsoleProps } from "../contract";
|
|
27
|
-
/**
|
|
28
|
-
* The interactive console surface.
|
|
29
|
-
*
|
|
30
|
-
* @param props the conductor to drive, the resolved theme, and the slash registry
|
|
31
|
-
*/
|
|
32
27
|
export declare function TerminalConsole(props: ConsoleProps): JSX.Element;
|
|
@@ -359,6 +359,12 @@ export type ConsoleEvent = {
|
|
|
359
359
|
} | {
|
|
360
360
|
readonly type: "buffer:insert";
|
|
361
361
|
readonly text: string;
|
|
362
|
+
}
|
|
363
|
+
/** Swap the first occurrence of `find` for `replaceWith` (paste-marker growth). */
|
|
364
|
+
| {
|
|
365
|
+
readonly type: "buffer:replaceSpan";
|
|
366
|
+
readonly find: string;
|
|
367
|
+
readonly replaceWith: string;
|
|
362
368
|
} | {
|
|
363
369
|
readonly type: "buffer:erasePrev";
|
|
364
370
|
} | {
|
|
@@ -548,6 +554,13 @@ export interface OverlayServices {
|
|
|
548
554
|
readonly openLoginUrl: (url: string) => Promise<boolean>;
|
|
549
555
|
/** The credential store sign-in / sign-out overlays read and write. */
|
|
550
556
|
readonly vault: AuthVault;
|
|
557
|
+
/**
|
|
558
|
+
* Recompute the server-tier gateway routing map from current vault/token
|
|
559
|
+
* state and push it onto the live conductor, so a sign-in that happens
|
|
560
|
+
* mid-session (the "Indus Server" entry in `/login`) takes effect on the
|
|
561
|
+
* NEXT turn without needing a session restart.
|
|
562
|
+
*/
|
|
563
|
+
readonly refreshGatewayRouting: () => Promise<void>;
|
|
551
564
|
}
|
|
552
565
|
/**
|
|
553
566
|
* What the root `TerminalConsole` surface receives at mount.
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
export type { KeyChord, ConsoleVerb, ConsoleIntent, ChordOutcome, ChordLatch, ChordStep, } from "./keymap";
|
|
19
19
|
export { NO_INTENT, readKey, NO_CHORD, advanceChord } from "./keymap";
|
|
20
20
|
export type { PasteThresholds, PasteVault, PasteCapture, } from "./paste";
|
|
21
|
-
export { PASTE_THRESHOLDS, PASTE_BURST_GAP_MS, EMPTY_PASTE_VAULT, pasteMarker, classifyPaste, coalescePaste, expandMarkers, hasMarkers, } from "./paste";
|
|
21
|
+
export { PASTE_THRESHOLDS, PASTE_BURST_GAP_MS, PASTE_CONTINUATION_MS, PASTE_MARKER_LINE_CAP, EMPTY_PASTE_VAULT, pasteMarker, classifyPaste, coalescePaste, appendToPaste, pasteLines, expandMarkers, hasMarkers, } from "./paste";
|
|
22
22
|
export type { CompletionKind, Suggestion, TokenSpan, CompletionResult, DirEntry, DirReader, } from "./complete";
|
|
23
23
|
export { completeAt, applySuggestion } from "./complete";
|
|
24
24
|
export { createDirReader } from "./dir-reader";
|
|
@@ -115,7 +115,7 @@ export interface KeyChord {
|
|
|
115
115
|
* Inert
|
|
116
116
|
* - `none` — the keystroke carries no console meaning.
|
|
117
117
|
*/
|
|
118
|
-
export type ConsoleVerb = "text:type" | "text:newline" | "edit:erasePrev" | "edit:eraseNext" | "edit:clearLine" | "nav:left" | "nav:right" | "nav:home" | "nav:end" | "nav:up" | "nav:down" | "flow:submit" | "flow:dismiss" | "flow:accept" | "flow:interrupt" | "flow:suspend" | "flow:cycleModel" | "model:cycleThinking" | "mode:cyclePermission" | "mode:togglePlan" | "queue:dequeue" | "input:pasteImage" | "input:externalEditor" | "overlay:open" | "view:expandTools" | "view:toggleReasoning" | "none";
|
|
118
|
+
export type ConsoleVerb = "text:type" | "text:newline" | "edit:erasePrev" | "edit:eraseNext" | "edit:clearLine" | "nav:left" | "nav:right" | "nav:home" | "nav:end" | "nav:up" | "nav:down" | "flow:submit" | "flow:dismiss" | "flow:accept" | "flow:interrupt" | "flow:suspend" | "flow:cycleModel" | "model:cycleThinking" | "mode:cyclePermission" | "mode:togglePlan" | "queue:dequeue" | "queue:steer" | "input:pasteImage" | "input:externalEditor" | "overlay:open" | "view:expandTools" | "view:toggleReasoning" | "none";
|
|
119
119
|
/**
|
|
120
120
|
* A classified keystroke: a {@link ConsoleVerb} plus the small payload a verb
|
|
121
121
|
* may carry — the literal text for a `text:type` insert, or the target overlay
|
|
@@ -41,7 +41,14 @@ export interface PasteThresholds {
|
|
|
41
41
|
/** Minimum character count to treat a chunk as a large paste. */
|
|
42
42
|
readonly chars: number;
|
|
43
43
|
}
|
|
44
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* The default cut-offs above which a paste is coalesced into a marker.
|
|
46
|
+
*
|
|
47
|
+
* Matched to the reference agent: a paste of MORE than 10 lines (i.e. ≥10
|
|
48
|
+
* newlines) or more than 1000 characters hides behind a marker; anything
|
|
49
|
+
* smaller — including the common 8-line snippet — splices inline and renders
|
|
50
|
+
* as visible multi-line text in the composer.
|
|
51
|
+
*/
|
|
45
52
|
export declare const PASTE_THRESHOLDS: PasteThresholds;
|
|
46
53
|
/**
|
|
47
54
|
* The maximum gap, in milliseconds, between per-character events still treated
|
|
@@ -53,6 +60,30 @@ export declare const PASTE_THRESHOLDS: PasteThresholds;
|
|
|
53
60
|
* it. Exposed as data so the coalescing timer and any test share one value.
|
|
54
61
|
*/
|
|
55
62
|
export declare const PASTE_BURST_GAP_MS = 24;
|
|
63
|
+
/**
|
|
64
|
+
* How long, after a coalesced flush, a paste stays "active" — a further
|
|
65
|
+
* multi-character chunk landing within this window APPENDS to the active
|
|
66
|
+
* marker instead of minting a new one.
|
|
67
|
+
*
|
|
68
|
+
* Terminals deliver a big paste as a series of ~1KB stdin reads whose gaps can
|
|
69
|
+
* exceed any reasonable per-chunk debounce, so timing alone shreds one paste
|
|
70
|
+
* into many markers (`[Pasted #11][Pasted #12]…`, issue #18's second form).
|
|
71
|
+
* Sized GENEROUSLY: a very long paste (the spec case is 1000 lines) must
|
|
72
|
+
* survive mid-stream read hiccups as ONE marker, and the failure mode of a
|
|
73
|
+
* too-long window is mild — two lightning-fast deliberate pastes merge into
|
|
74
|
+
* one marker whose expansion is still the correct concatenated text — while a
|
|
75
|
+
* too-short window re-creates the shredding this exists to fix. Two human
|
|
76
|
+
* paste chords are >300ms apart in practice; single characters (real typing)
|
|
77
|
+
* never extend the window.
|
|
78
|
+
*/
|
|
79
|
+
export declare const PASTE_CONTINUATION_MS = 250;
|
|
80
|
+
/**
|
|
81
|
+
* Ceiling on the line count a single marker absorbs via continuation. One
|
|
82
|
+
* user paste stays ONE marker up to this many lines; a paste that keeps
|
|
83
|
+
* streaming past it rolls over into a fresh marker ("one more paste") so a
|
|
84
|
+
* runaway multi-megabyte paste can't grow a single unbounded vault body.
|
|
85
|
+
*/
|
|
86
|
+
export declare const PASTE_MARKER_LINE_CAP = 1000;
|
|
56
87
|
/** The console's own placeholder format for a hidden paste body. */
|
|
57
88
|
export declare function pasteMarker(ordinal: number, lineCount: number): string;
|
|
58
89
|
/**
|
|
@@ -106,6 +137,27 @@ export interface PasteCapture {
|
|
|
106
137
|
* @param body the full pasted text to hide
|
|
107
138
|
*/
|
|
108
139
|
export declare function coalescePaste(body: string, vault?: PasteVault): PasteCapture;
|
|
140
|
+
/**
|
|
141
|
+
* Grow an existing paste body with a follow-on chunk, reminting its marker.
|
|
142
|
+
*
|
|
143
|
+
* The continuation path for a paste the terminal split across reads: the extra
|
|
144
|
+
* text is appended to `ordinal`'s stored body and a fresh marker (same ordinal,
|
|
145
|
+
* updated line count) is returned so the surface can swap the token already
|
|
146
|
+
* spliced into the buffer. `minted` is unchanged — no new ordinal is consumed.
|
|
147
|
+
* An unknown ordinal starts from an empty body, so the call never throws.
|
|
148
|
+
*
|
|
149
|
+
* @param ordinal the marker ordinal to grow
|
|
150
|
+
* @param extra the follow-on pasted text to append
|
|
151
|
+
* @param vault the store holding the ordinal's current body
|
|
152
|
+
*/
|
|
153
|
+
export declare function appendToPaste(ordinal: number, extra: string, vault: PasteVault): PasteCapture;
|
|
154
|
+
/**
|
|
155
|
+
* The line count of an ordinal's stored body — the surface consults this
|
|
156
|
+
* against {@link PASTE_MARKER_LINE_CAP} to decide whether a continuation chunk
|
|
157
|
+
* may still append or must roll over into a fresh marker. Zero for an unknown
|
|
158
|
+
* ordinal or an empty body.
|
|
159
|
+
*/
|
|
160
|
+
export declare function pasteLines(vault: PasteVault, ordinal: number): number;
|
|
109
161
|
/**
|
|
110
162
|
* Rewrite every paste marker in a buffer back to the text it stands for.
|
|
111
163
|
*
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* abort/clear settles every outstanding entry with `"deny"` so a cancelled turn
|
|
16
16
|
* never hangs on a pending prompt.
|
|
17
17
|
*/
|
|
18
|
-
import type { ApprovalChoice } from "../../conductor";
|
|
18
|
+
import type { ApprovalChoice, PermissionMode } from "../../conductor";
|
|
19
19
|
import type { ApprovalRequest } from "./approval";
|
|
20
20
|
/** One parked approval request awaiting the user's choice. */
|
|
21
21
|
export interface ApprovalEntry {
|
|
@@ -69,3 +69,20 @@ export declare function approvalQueueReducer(state: ApprovalQueueState, event: A
|
|
|
69
69
|
* @param state the queue state
|
|
70
70
|
*/
|
|
71
71
|
export declare function activeApproval(state: ApprovalQueueState): ApprovalEntry | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Whether switching INTO `mode` mid-prompt should release (auto-allow) every
|
|
74
|
+
* PARKED approval request.
|
|
75
|
+
*
|
|
76
|
+
* Only `bypass` qualifies: a parked entry already passed the deny-rule and
|
|
77
|
+
* catastrophic-blocklist scans before it reached `ask`, and under bypass the
|
|
78
|
+
* engine allows everything not denied — so settling the parked prompts with
|
|
79
|
+
* `allow-once` matches exactly what the mode now means, and the run resumes
|
|
80
|
+
* instead of idling behind a prompt the user just declared moot. Every other
|
|
81
|
+
* mode keeps the prompts parked: `default`/`acceptEdits` still want the answer,
|
|
82
|
+
* and `plan` must not auto-ALLOW a mutating call (the user can still deny).
|
|
83
|
+
*
|
|
84
|
+
* Pure; the component wires it to the actual settle.
|
|
85
|
+
*
|
|
86
|
+
* @param mode the permission mode just switched into
|
|
87
|
+
*/
|
|
88
|
+
export declare function modeReleasesApprovals(mode: PermissionMode): boolean;
|
|
@@ -12,4 +12,4 @@ export { PickerOverlays, type OverlayGroupProps } from "./pickers";
|
|
|
12
12
|
export { SessionOverlays } from "./sessions";
|
|
13
13
|
export { AuthOverlays } from "./auth";
|
|
14
14
|
export { ApprovalOverlays, choiceFromId, readApprovalPayload, summarizeInput, APPROVAL_CHOICES, DISMISS_CHOICE, type ApprovalRequest, type ApprovalPayload, } from "./approval";
|
|
15
|
-
export { approvalQueueReducer, activeApproval, EMPTY_APPROVAL_QUEUE, type ApprovalEntry, type ApprovalQueueState, type ApprovalQueueEvent, } from "./approval-queue";
|
|
15
|
+
export { approvalQueueReducer, activeApproval, modeReleasesApprovals, EMPTY_APPROVAL_QUEUE, type ApprovalEntry, type ApprovalQueueState, type ApprovalQueueEvent, } from "./approval-queue";
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Login command — `runLogin`.
|
|
3
|
+
*
|
|
4
|
+
* The top-level `login` / `logout` / `whoami` surface that authenticates the CLI
|
|
5
|
+
* against the indus-server so a user with **no local provider key** can still run
|
|
6
|
+
* model turns through the server gateway (the session token is vended as the
|
|
7
|
+
* provider key downstream — see `src/boot/runners/server-mode.ts`).
|
|
8
|
+
*
|
|
9
|
+
* `login` drives the OAuth 2.0 **device-authorization** flow (RFC 8628) against
|
|
10
|
+
* the server's better-auth endpoints under `${INDUS_SERVER_URL}/api/auth`:
|
|
11
|
+
*
|
|
12
|
+
* 1. POST `/api/auth/device/code` → a `user_code` + verification URL.
|
|
13
|
+
* 2. The user opens the URL in a browser and approves the device.
|
|
14
|
+
* 3. We poll POST `/api/auth/device/token` until it returns an `access_token`.
|
|
15
|
+
* 4. The token is persisted via {@link storeServerToken} (A1's token store).
|
|
16
|
+
*
|
|
17
|
+
* This is a **pre-pipeline router**, not a runner: a no-key user cannot build a
|
|
18
|
+
* session, so login must short-circuit before the stage pipeline. {@link runLogin}
|
|
19
|
+
* therefore mirrors `runCredential` in `boot.ts` — it owns the first positional
|
|
20
|
+
* token only and returns `undefined` (fall through to a normal launch) when that
|
|
21
|
+
* token is not one of its verbs.
|
|
22
|
+
*
|
|
23
|
+
* The app does not depend on `better-auth/client`, `open`, or a spinner library,
|
|
24
|
+
* so the device flow is implemented over raw `fetch` and the console is driven
|
|
25
|
+
* with `chalk` to match the rest of the launch surface. `--server-url` and
|
|
26
|
+
* `--client-id` are parsed from the argv tail here (the declarative flag table is
|
|
27
|
+
* for the launch invocation, not these auth-only verbs).
|
|
28
|
+
*/
|
|
29
|
+
import type { OAuthLoginCallbacks } from "indusagi/ai";
|
|
30
|
+
import type { BootContext } from "../boot/contract";
|
|
31
|
+
/**
|
|
32
|
+
* The sign-in directory id for the indus-server session (as opposed to a
|
|
33
|
+
* per-model-provider credential). Used by `src/launch/oauth.ts` to special-case
|
|
34
|
+
* this entry in `listLoginProviders` / `startOAuthLogin` so the interactive
|
|
35
|
+
* `/login` picker can drive the same device-authorization flow as the `indus
|
|
36
|
+
* login` CLI verb.
|
|
37
|
+
*/
|
|
38
|
+
export declare const SERVER_TIER_PROVIDER_ID = "indus-server";
|
|
39
|
+
/**
|
|
40
|
+
* Drive the indus-server device-authorization flow through the framework's
|
|
41
|
+
* generic {@link OAuthLoginCallbacks} shape, so the interactive `/login` picker
|
|
42
|
+
* (`src/console/overlays/auth.tsx`'s `OAuthFlowDialog`) can establish a
|
|
43
|
+
* server-tier session the same way the `indus login` CLI verb does.
|
|
44
|
+
*
|
|
45
|
+
* Reuses the private {@link requestDeviceCode} / {@link pollForToken} helpers
|
|
46
|
+
* above rather than duplicating the request+poll sequence, and reports the
|
|
47
|
+
* verification URL / code through `callbacks.onAuth` exactly once, mirroring
|
|
48
|
+
* how `doLogin` renders them to the console. On success the token is persisted
|
|
49
|
+
* via {@link storeServerToken}; any thrown error (network failure, denial,
|
|
50
|
+
* expiry, timeout) propagates to the caller unchanged — `startOAuthLogin`'s
|
|
51
|
+
* caller (the dialog's try/catch) already renders a generic failure state.
|
|
52
|
+
*
|
|
53
|
+
* @param callbacks the framework's OAuth login callbacks (url + progress)
|
|
54
|
+
* @param serverUrl the indus-server base url (defaults to {@link INDUS_SERVER_URL})
|
|
55
|
+
* @param clientId the device-flow client id (defaults to {@link INDUS_CLIENT_ID})
|
|
56
|
+
*/
|
|
57
|
+
export declare function runServerTierLogin(callbacks: OAuthLoginCallbacks, serverUrl?: string, clientId?: string): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Route a `login` / `logout` / `whoami` verb, if this invocation is one.
|
|
60
|
+
*
|
|
61
|
+
* Inspects `ctx.argv[0]`: returns a numeric exit code when it handled one of the
|
|
62
|
+
* auth verbs, or `undefined` when the leading token is something else so the
|
|
63
|
+
* caller falls through to a normal launch. Modeled on `runCredential` in
|
|
64
|
+
* `boot.ts`; `--server-url` / `--client-id` are parsed from the argv tail.
|
|
65
|
+
*
|
|
66
|
+
* @param ctx the seeded boot context (carries the raw argv)
|
|
67
|
+
*/
|
|
68
|
+
export declare function runLogin(ctx: BootContext): Promise<number | undefined>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `src/launch/oauth.ts` — unit tests for the indus-server bridge added to the
|
|
3
|
+
* merged sign-in directory and `startOAuthLogin`.
|
|
4
|
+
*
|
|
5
|
+
* Covers:
|
|
6
|
+
* 1. {@link listLoginProviders} includes the `indus-server` entry
|
|
7
|
+
* (`SERVER_TIER_PROVIDER_ID`, `authKind: "oauth"`).
|
|
8
|
+
* 2. {@link startOAuthLogin} for `SERVER_TIER_PROVIDER_ID` drives the device
|
|
9
|
+
* flow over a mocked `fetch`, reports `onAuth` exactly once with the right
|
|
10
|
+
* shape, reports progress, never touches the vault, and resolves.
|
|
11
|
+
* 3. {@link startOAuthLogin} for an unregistered id still throws the
|
|
12
|
+
* pre-existing "No browser sign-in is available" error (regression check).
|
|
13
|
+
* 4. A device/token failure (`access_denied`) propagates out of
|
|
14
|
+
* `startOAuthLogin` unchanged rather than being swallowed.
|
|
15
|
+
*
|
|
16
|
+
* `storeServerToken` is mocked (partial mock of `../boot/server-token`) so the
|
|
17
|
+
* success-path test never touches the real `~/.indusagi/agent/server-token.json`
|
|
18
|
+
* file on the machine running the suite.
|
|
19
|
+
*/
|
|
20
|
+
export {};
|
|
@@ -38,6 +38,12 @@ export interface SummarizeDeps {
|
|
|
38
38
|
readonly priorDigest?: string;
|
|
39
39
|
/** Cancellation signal forwarded to the completer. */
|
|
40
40
|
readonly signal?: AbortSignal;
|
|
41
|
+
/**
|
|
42
|
+
* Credential for the summarization model's provider, forwarded to the
|
|
43
|
+
* completer. Required in practice for sessions whose key is resolved
|
|
44
|
+
* per-call (server tier) rather than from an environment variable.
|
|
45
|
+
*/
|
|
46
|
+
readonly apiKey?: string;
|
|
41
47
|
/**
|
|
42
48
|
* Optional cap on the digest size, in tokens, forwarded to the completer's
|
|
43
49
|
* `maxTokens`. A modest ceiling keeps the summary itself from eating the
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
* test seam — a unit test drives the runner with an in-memory fake instead of a
|
|
35
35
|
* real network round-trip.
|
|
36
36
|
*/
|
|
37
|
-
import { type AgentMessage } from "../conductor";
|
|
37
|
+
import { type AgentMessage, type SessionPermissionPolicy } from "../conductor";
|
|
38
38
|
import { type AgentTool } from "../capability-deck";
|
|
39
39
|
import { type AgentEvent } from "indusagi/agent";
|
|
40
40
|
import type { WorkflowAgentRunner } from "./engine";
|
|
@@ -89,6 +89,25 @@ export interface WorkflowAgentRunnerOptions {
|
|
|
89
89
|
* `Agent`. When omitted the runner uses `new Agent`.
|
|
90
90
|
*/
|
|
91
91
|
readonly spawn?: (prompt: string, context: WorkflowSpawnContext) => WorkflowSubAgent;
|
|
92
|
+
/**
|
|
93
|
+
* Resolve the current server-tier gateway routing map (provider -> gateway
|
|
94
|
+
* base url). Called FRESH on every `run()` — never cached — so a mid-session
|
|
95
|
+
* `/login` (to "Indus Server") is always picked up on the very next subagent
|
|
96
|
+
* call. Mirrors {@link getApiKey}, which is likewise invoked per-request
|
|
97
|
+
* rather than resolved once at construction.
|
|
98
|
+
*/
|
|
99
|
+
readonly getGatewayBaseUrls?: () => Promise<Record<string, string>>;
|
|
100
|
+
/**
|
|
101
|
+
* The parent session's live permission policy: the SAME mutable rule list the
|
|
102
|
+
* parent gate reads plus a live getter onto the conductor's current mode. When
|
|
103
|
+
* present, every spawned workflow subagent runs under a RESOLVER-LESS gate
|
|
104
|
+
* built from it — deny/ask rules, plan-mode enforcement, and the
|
|
105
|
+
* catastrophic-bash blocklist apply per inner tool call, and a mid-run mode
|
|
106
|
+
* switch (Shift+Tab) retargets the very next subagent tool call. A subagent
|
|
107
|
+
* cannot prompt, so an `ask` decision deterministically denies. Absent (a bare
|
|
108
|
+
* test construction), the subagent runs ungated as before.
|
|
109
|
+
*/
|
|
110
|
+
readonly permissionPolicy?: SessionPermissionPolicy;
|
|
92
111
|
}
|
|
93
112
|
/**
|
|
94
113
|
* Build a live {@link WorkflowAgentRunner} the host wires into the deck context.
|
|
@@ -23,4 +23,4 @@ export declare const BRAND: Brand;
|
|
|
23
23
|
* Single source of truth: bump this one line per release. Co-located with the
|
|
24
24
|
* brand so `boot` reads it without importing the index barrel.
|
|
25
25
|
*/
|
|
26
|
-
export declare const VERSION = "0.2.
|
|
26
|
+
export declare const VERSION = "0.2.4";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "indusagi-coding-agent",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Indusagi coding agent — a terminal-first AI coding agent, built from scratch on the indusagi framework.",
|
|
5
5
|
"author": "Varun Israni",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@sinclair/typebox": "^0.34.49",
|
|
58
58
|
"chalk": "^5.6.2",
|
|
59
59
|
"highlight.js": "^11.11.1",
|
|
60
|
-
"indusagi": "^0.13.
|
|
60
|
+
"indusagi": "^0.13.3",
|
|
61
61
|
"ink": "^5.2.1",
|
|
62
62
|
"jiti": "^2.7.0",
|
|
63
63
|
"marked": "^18.0.4",
|