akanjs 3.0.0-alpha.54 → 3.0.0-alpha.55
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/local/apps/serverLifecycle/serverLifecycle-local.db-shm +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-shm +0 -0
- package/package.json +1 -1
- package/server/rscWorker.tsx +5 -13
- package/server/webRouter.ts +3 -5
- package/store/agent/StoreSurfaceSource.ts +9 -1
- package/types/store/agent/StoreSurfaceSource.d.ts +9 -1
- package/types/ui/Agent/Chat.d.ts +25 -4
- package/types/ui/Agent/Zone.d.ts +23 -4
- package/types/ui/Agent/agentSessionOf.d.ts +12 -3
- package/types/ui/Agent/index.d.ts +1 -1
- package/types/ui/Agent/sessionHistory.d.ts +1 -1
- package/types/ui/Agent/sessionView.d.ts +15 -0
- package/types/ui/RecentTime.d.ts +18 -1
- package/types/ui/index.d.ts +5 -3
- package/types/vendor/use-agentic/AgentProvider.d.ts +1 -2
- package/types/vendor/use-agentic/AgentSession.d.ts +33 -6
- package/types/vendor/use-agentic/AgenticSurface.d.ts +5 -0
- package/ui/Agent/Chat.tsx +76 -36
- package/ui/Agent/Zone.tsx +44 -12
- package/ui/Agent/agentSessionOf.ts +23 -4
- package/ui/Agent/sessionHistory.ts +10 -3
- package/ui/Agent/sessionView.ts +38 -0
- package/ui/RecentTime.tsx +83 -35
- package/ui/System/Client.tsx +19 -7
- package/ui/System/ThemeToggle.tsx +14 -5
- package/ui/index.ts +29 -3
- package/vendor/use-agentic/AgentProvider.tsx +1 -1
- package/vendor/use-agentic/AgentSession.ts +84 -19
- package/vendor/use-agentic/AgenticSurface.ts +9 -0
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/server/rscWorker.tsx
CHANGED
|
@@ -547,7 +547,6 @@ export class RscRenderer {
|
|
|
547
547
|
});
|
|
548
548
|
return;
|
|
549
549
|
}
|
|
550
|
-
const theme = untrackedCookies().get("theme")?.value;
|
|
551
550
|
let element: ReactNode;
|
|
552
551
|
let effectivePatchDecision = safePatchDecision;
|
|
553
552
|
if (match && safePatchDecision.status === "patch" && safePatchDecision.patch) {
|
|
@@ -563,9 +562,9 @@ export class RscRenderer {
|
|
|
563
562
|
reason: "suffix-compose-fallback",
|
|
564
563
|
commonPrefixLength: safePatchDecision.commonPrefixLength,
|
|
565
564
|
};
|
|
566
|
-
element = await this.#renderMatched(urlObj, match,
|
|
565
|
+
element = await this.#renderMatched(urlObj, match, searchParams);
|
|
567
566
|
} else element = suffixElement;
|
|
568
|
-
} else if (match) element = await this.#renderMatched(urlObj, match,
|
|
567
|
+
} else if (match) element = await this.#renderMatched(urlObj, match, searchParams);
|
|
569
568
|
else element = await this.#renderNotFound(urlObj);
|
|
570
569
|
const traceCacheKey =
|
|
571
570
|
effectivePatchDecision.status === "patch" ? (patchCacheEntry?.key ?? cacheEntry?.key) : cacheEntry?.key;
|
|
@@ -1236,12 +1235,8 @@ export class RscRenderer {
|
|
|
1236
1235
|
const routeHeadSnapshot = this.#createRouteHeadSnapshot(url, routeHead, {
|
|
1237
1236
|
hasExplicitLanguageAlternates: routeHead.hasExplicitLanguageAlternates,
|
|
1238
1237
|
});
|
|
1239
|
-
const theme = untrackedCookies().get("theme")?.value;
|
|
1240
1238
|
return (
|
|
1241
|
-
<html
|
|
1242
|
-
lang={params.lang ?? RscRenderer.#getLocale(pathname, this.#i18n)}
|
|
1243
|
-
{...(theme ? { "data-theme": theme } : { suppressHydrationWarning: true })}
|
|
1244
|
-
>
|
|
1239
|
+
<html lang={params.lang ?? RscRenderer.#getLocale(pathname, this.#i18n)} suppressHydrationWarning>
|
|
1245
1240
|
<head key="head">
|
|
1246
1241
|
<meta key="charset" charSet="utf-8" />
|
|
1247
1242
|
<meta key="viewport" name="viewport" content="width=device-width, initial-scale=1" />
|
|
@@ -1263,7 +1258,6 @@ export class RscRenderer {
|
|
|
1263
1258
|
async #renderMatched(
|
|
1264
1259
|
url: URL,
|
|
1265
1260
|
match: { pathRoute: PathRoute; params: Record<string, string> },
|
|
1266
|
-
theme?: string,
|
|
1267
1261
|
searchParams = RouteTreeBuilder.parseSearchParams(url.search),
|
|
1268
1262
|
): Promise<ReactNode> {
|
|
1269
1263
|
this.#logger.verbose(
|
|
@@ -1289,11 +1283,9 @@ export class RscRenderer {
|
|
|
1289
1283
|
searchParams,
|
|
1290
1284
|
navKey: url.pathname + url.search,
|
|
1291
1285
|
});
|
|
1286
|
+
|
|
1292
1287
|
return (
|
|
1293
|
-
<html
|
|
1294
|
-
lang={match.params.lang ?? this.#i18n.defaultLocale}
|
|
1295
|
-
{...(theme ? { "data-theme": theme } : { suppressHydrationWarning: true })}
|
|
1296
|
-
>
|
|
1288
|
+
<html lang={match.params.lang ?? this.#i18n.defaultLocale} suppressHydrationWarning>
|
|
1297
1289
|
<head key="head">
|
|
1298
1290
|
<meta key="charset" charSet="utf-8" />
|
|
1299
1291
|
<meta key="viewport" name="viewport" content="width=device-width, initial-scale=1" />
|
package/server/webRouter.ts
CHANGED
|
@@ -610,7 +610,8 @@ export class WebRouter {
|
|
|
610
610
|
if (rscResult.type === "redirect")
|
|
611
611
|
return Response.redirect(new URL(rscResult.location, url.origin), rscResult.status);
|
|
612
612
|
if (rscResult.type === "not-found") return this.#renderSystemNotFoundFallbackResponse(req, url);
|
|
613
|
-
|
|
613
|
+
|
|
614
|
+
const cookieTheme = WebRouter.#cookieValue(req, "theme");
|
|
614
615
|
const hostRequestStore = createRequestStore(req);
|
|
615
616
|
const extraBootstrapInline = [
|
|
616
617
|
rscResult.trace?.routeState
|
|
@@ -628,7 +629,7 @@ export class WebRouter {
|
|
|
628
629
|
bootstrapModules: [this.#artifact.rscClientUrl],
|
|
629
630
|
extraBootstrapInline: extraBootstrapInline || undefined,
|
|
630
631
|
importmap: this.#artifact.vendorMap,
|
|
631
|
-
theme:
|
|
632
|
+
theme: cookieTheme ?? rscResult.theme ?? "system",
|
|
632
633
|
lateControl: rscResult.lateControl,
|
|
633
634
|
waitForAllReady: rscResult.trace?.ssrBlocking ?? false,
|
|
634
635
|
onCancel: (reason: unknown) => {
|
|
@@ -797,9 +798,6 @@ export class WebRouter {
|
|
|
797
798
|
}
|
|
798
799
|
}
|
|
799
800
|
|
|
800
|
-
static #hasCookie(req: Request, name: string): boolean {
|
|
801
|
-
return parseCookieHeader(req.headers.get("cookie") ?? "").has(name);
|
|
802
|
-
}
|
|
803
801
|
#getHtmlCacheEntry(req: Request, url: URL): { entry: RouteCacheEntry | null; reason?: string } {
|
|
804
802
|
const decision = resolvePublicRouteCacheEntryDecision({
|
|
805
803
|
request: req,
|
|
@@ -13,13 +13,21 @@ import { ScreenTarget } from "./ScreenTarget";
|
|
|
13
13
|
*
|
|
14
14
|
* Per zone view: a zone's `readState` reaches the keys its own subtree subscribes, and its `readScreen` and
|
|
15
15
|
* `highlight` reach into its own `data-agent-zone` container rather than the whole document. A page can shadow any
|
|
16
|
-
* of them by registering a hook tool of the same name — hook entries win over a source's.
|
|
16
|
+
* of them by registering a hook tool of the same name — hook entries win over a source's. **That is a root-scope
|
|
17
|
+
* move only**: inside a zone the hook entry is registered under its scope-prefixed name, which can never collide
|
|
18
|
+
* with the bare name a source publishes, so a zone drops a built-in with the session's `builtins` option instead.
|
|
17
19
|
*/
|
|
18
20
|
export class StoreSurfaceSource implements SurfaceSource {
|
|
19
21
|
/** Defined in `akanjs/ui/styles.css`, so the flash follows the app's own theme tokens. */
|
|
20
22
|
static readonly highlightClass = "akan-agent-highlight";
|
|
21
23
|
/** Mirrors the animation in that stylesheet: the class outlives the ring by nothing. */
|
|
22
24
|
static readonly highlightMs = 2400;
|
|
25
|
+
/**
|
|
26
|
+
* What `tools()` contributes, in the order it builds them — the list a session's `builtins` option selects from.
|
|
27
|
+
* A screen that declares a hook tool of one of these names is not in it: that entry is the screen's, not this
|
|
28
|
+
* source's, so withholding the built-ins never withholds a tool a component published on purpose.
|
|
29
|
+
*/
|
|
30
|
+
static readonly builtins = ["navigate", "goBack", "readScreen", "readState", "highlight"] as const;
|
|
23
31
|
|
|
24
32
|
#bridge: AgentBridge | null;
|
|
25
33
|
readonly #builtins = new Map<string, ToolEntry[]>();
|
|
@@ -8,7 +8,9 @@ import { AgentBridge } from "./AgentBridge.d.ts";
|
|
|
8
8
|
*
|
|
9
9
|
* Per zone view: a zone's `readState` reaches the keys its own subtree subscribes, and its `readScreen` and
|
|
10
10
|
* `highlight` reach into its own `data-agent-zone` container rather than the whole document. A page can shadow any
|
|
11
|
-
* of them by registering a hook tool of the same name — hook entries win over a source's.
|
|
11
|
+
* of them by registering a hook tool of the same name — hook entries win over a source's. **That is a root-scope
|
|
12
|
+
* move only**: inside a zone the hook entry is registered under its scope-prefixed name, which can never collide
|
|
13
|
+
* with the bare name a source publishes, so a zone drops a built-in with the session's `builtins` option instead.
|
|
12
14
|
*/
|
|
13
15
|
export declare class StoreSurfaceSource implements SurfaceSource {
|
|
14
16
|
#private;
|
|
@@ -16,6 +18,12 @@ export declare class StoreSurfaceSource implements SurfaceSource {
|
|
|
16
18
|
static readonly highlightClass = "akan-agent-highlight";
|
|
17
19
|
/** Mirrors the animation in that stylesheet: the class outlives the ring by nothing. */
|
|
18
20
|
static readonly highlightMs = 2400;
|
|
21
|
+
/**
|
|
22
|
+
* What `tools()` contributes, in the order it builds them — the list a session's `builtins` option selects from.
|
|
23
|
+
* A screen that declares a hook tool of one of these names is not in it: that entry is the screen's, not this
|
|
24
|
+
* source's, so withholding the built-ins never withholds a tool a component published on purpose.
|
|
25
|
+
*/
|
|
26
|
+
static readonly builtins: readonly ["navigate", "goBack", "readScreen", "readState", "highlight"];
|
|
19
27
|
/** Lazy by default: `AgentBridge.of()` walks the whole store, so it waits for the first enumeration. */
|
|
20
28
|
constructor(bridge?: AgentBridge);
|
|
21
29
|
tools: (view?: string[]) => ToolEntry[];
|
package/types/ui/Agent/Chat.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
import { type AgentRunner, type CompactOptions } from "../../vendor/use-agentic.d.ts";
|
|
2
|
+
import { type AgentRunner, type AgentSessionOptions, type CompactOptions, type SessionHistory } from "../../vendor/use-agentic.d.ts";
|
|
3
3
|
import type { AttachReader } from "./attachment.d.ts";
|
|
4
4
|
import type { PersistOption } from "./sessionHistory.d.ts";
|
|
5
|
+
import type { BuiltinOption } from "./sessionView.d.ts";
|
|
5
6
|
import type { VoiceEngine } from "./voice.d.ts";
|
|
6
7
|
export interface ChatProps {
|
|
7
8
|
/** Reaches whichever surface is showing — the launcher while closed, the panel while open. */
|
|
@@ -17,6 +18,13 @@ export interface ChatProps {
|
|
|
17
18
|
* messages left verbatim below the summary. Tune it per provider; `{ at: 0 }` turns it off.
|
|
18
19
|
*/
|
|
19
20
|
compact?: CompactOptions;
|
|
21
|
+
/**
|
|
22
|
+
* Which of the runtime's own tools this chat's agent gets — all of them by default, `false` none, an array
|
|
23
|
+
* exactly the ones it names. A chat that must not leave the screen it is on drops `navigate` and `goBack`.
|
|
24
|
+
*/
|
|
25
|
+
builtins?: BuiltinOption;
|
|
26
|
+
/** Called after a compaction replaced messages with one summary — where a host syncs its own watermark. */
|
|
27
|
+
onCompact?: AgentSessionOptions["onCompact"];
|
|
20
28
|
defaultOpen?: boolean;
|
|
21
29
|
/**
|
|
22
30
|
* Controlled open state. Pass it with `onOpenChange` to drive the panel from the app's own control — a header
|
|
@@ -26,8 +34,14 @@ export interface ChatProps {
|
|
|
26
34
|
onOpenChange?: (open: boolean) => void;
|
|
27
35
|
/** `false` draws no launcher, for an app that opens the panel from a control of its own. */
|
|
28
36
|
launcher?: boolean;
|
|
29
|
-
/**
|
|
30
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Keeps the transcript across reloads — sessionStorage by default, `{ storage: "local" }` to outlive the tab, or
|
|
39
|
+
* a `SessionHistory` of the app's own to keep it anywhere else, a server included.
|
|
40
|
+
*
|
|
41
|
+
* Ignored, like every session option above it, when an enclosing `Agent.Zone` or `AgentProvider` already holds a
|
|
42
|
+
* session: this chat then binds to that one, and the options belong to whoever built it.
|
|
43
|
+
*/
|
|
44
|
+
persist?: PersistOption | SessionHistory;
|
|
31
45
|
/** Renders in the page flow instead of floating above it — a zone chat that lives inside its own section. */
|
|
32
46
|
inline?: boolean;
|
|
33
47
|
/** `false` gives the browser its own Cmd/Ctrl+L back, for an app whose shell already spends that chord. */
|
|
@@ -39,6 +53,13 @@ export interface ChatProps {
|
|
|
39
53
|
intro?: ReactNode;
|
|
40
54
|
/** Extra header controls, left of the built-in clear and close buttons. */
|
|
41
55
|
header?: ReactNode;
|
|
56
|
+
/**
|
|
57
|
+
* `false` draws no header bar at all — for an `inline` chat inside a panel the app already titles. The extra
|
|
58
|
+
* `header` controls go with it, and the clear action stays reachable as the `/new` command.
|
|
59
|
+
*/
|
|
60
|
+
chrome?: boolean;
|
|
61
|
+
/** The composer's opening text, read once at mount — where a `?prompt=` lands without sending it. */
|
|
62
|
+
defaultDraft?: string;
|
|
42
63
|
/**
|
|
43
64
|
* Reads a file the user attached into an attachment, or answers `null` to leave it to the built-in reader
|
|
44
65
|
* (images as bytes, text as text). This is where an app puts what needs a parser — a PDF's text, a spreadsheet's
|
|
@@ -60,6 +81,6 @@ export interface ChatProps {
|
|
|
60
81
|
* `persist` keeps it. An enclosing AgentProvider's session wins, which is how an app isolates a surface or swaps
|
|
61
82
|
* the loop while keeping this UI.
|
|
62
83
|
*/
|
|
63
|
-
export declare const DefaultChat: ({ className, title, instructions, runner, maxTurns, compact, defaultOpen, open: openProp, onOpenChange, launcher, persist, inline, shortcut, launcherClassName, panelClassName, intro, header, attach, voice, }: ChatProps) => ReactNode;
|
|
84
|
+
export declare const DefaultChat: ({ className, title, instructions, runner, maxTurns, compact, builtins, onCompact, defaultOpen, open: openProp, onOpenChange, launcher, persist, inline, shortcut, launcherClassName, panelClassName, intro, header, chrome, defaultDraft, attach, voice, }: ChatProps) => ReactNode;
|
|
64
85
|
declare const _default: import("react").ComponentType<ChatProps>;
|
|
65
86
|
export default _default;
|
package/types/ui/Agent/Zone.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
import { type AgentRunner, type CompactOptions } from "../../vendor/use-agentic.d.ts";
|
|
2
|
+
import { type AgentRunner, type AgentSession, type AgentSessionOptions, type CompactOptions, type SessionHistory } from "../../vendor/use-agentic.d.ts";
|
|
3
3
|
import type { PersistOption } from "./sessionHistory.d.ts";
|
|
4
|
+
import type { BuiltinOption } from "./sessionView.d.ts";
|
|
4
5
|
export interface ZoneProps {
|
|
5
6
|
className?: string;
|
|
6
7
|
/** Names the zone; the scope id and the `data-agent-zone` container both derive from it. */
|
|
@@ -12,8 +13,26 @@ export interface ZoneProps {
|
|
|
12
13
|
maxTurns?: number;
|
|
13
14
|
/** When this zone's conversation summarizes itself — same contract as the chat's own `compact`. */
|
|
14
15
|
compact?: CompactOptions;
|
|
15
|
-
/**
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Which of the runtime's own tools this zone's agent gets — all of them by default, `false` none, an array
|
|
18
|
+
* exactly the ones it names. `builtins={["readScreen", "readState"]}` is how a zone that must not leave the
|
|
19
|
+
* screen stops being able to: the tools are withheld, not discouraged, so a prompt cannot talk the model past it.
|
|
20
|
+
*/
|
|
21
|
+
builtins?: BuiltinOption;
|
|
22
|
+
/**
|
|
23
|
+
* Keeps this zone's transcript across reloads, keyed by the zone's scope path — web storage by default, or a
|
|
24
|
+
* `SessionHistory` of the app's own to keep it anywhere else, a server included.
|
|
25
|
+
*/
|
|
26
|
+
persist?: PersistOption | SessionHistory;
|
|
27
|
+
/** Called after a compaction replaced messages with one summary — where a host syncs its own watermark. */
|
|
28
|
+
onCompact?: AgentSessionOptions["onCompact"];
|
|
29
|
+
/**
|
|
30
|
+
* Runs this zone on a session the app built instead of one of its own, and the app then owns it: unmounting the
|
|
31
|
+
* zone leaves it running. Read once at mount, like every other session option here.
|
|
32
|
+
*/
|
|
33
|
+
session?: AgentSession;
|
|
34
|
+
/** Hands the session out once it exists, for a page or store that wants to send into it or watch it. */
|
|
35
|
+
onSession?: (session: AgentSession) => void;
|
|
17
36
|
children: ReactNode;
|
|
18
37
|
}
|
|
19
38
|
/**
|
|
@@ -22,4 +41,4 @@ export interface ZoneProps {
|
|
|
22
41
|
* zones are views, never walls. An `Agent.Chat` mounted inside binds to this session automatically, so two zones
|
|
23
42
|
* on one screen run two conversations in parallel, each seeing only its own subtree.
|
|
24
43
|
*/
|
|
25
|
-
export declare const Zone: ({ className, id, label, instructions, runner, maxTurns, compact, persist, children, }: ZoneProps) => import("react/jsx-runtime").JSX.Element;
|
|
44
|
+
export declare const Zone: ({ className, id, label, instructions, runner, maxTurns, compact, builtins, persist, onCompact, session: provided, onSession, children, }: ZoneProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type AgentRunner, AgentSession, type CompactOptions } from "../../vendor/use-agentic.d.ts";
|
|
1
|
+
import { type AgentRunner, AgentSession, type AgentSessionOptions, type CompactOptions, type SessionHistory } from "../../vendor/use-agentic.d.ts";
|
|
2
2
|
import { type PersistOption } from "./sessionHistory.d.ts";
|
|
3
|
+
import { type BuiltinOption } from "./sessionView.d.ts";
|
|
3
4
|
export interface AgentSessionSetup {
|
|
4
5
|
/** Read per call rather than captured, so text the session builds follows a language switched mid-conversation. */
|
|
5
6
|
l: (key: string) => string;
|
|
@@ -9,10 +10,18 @@ export interface AgentSessionSetup {
|
|
|
9
10
|
instructions?: string;
|
|
10
11
|
maxTurns?: number;
|
|
11
12
|
compact?: CompactOptions;
|
|
12
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Which of the runtime's own tools this session gets: all of them by default, none with `false`, exactly the
|
|
15
|
+
* ones an array names. A zone whose conversation must stay on one screen takes `navigate` and `goBack` off it.
|
|
16
|
+
*/
|
|
17
|
+
builtins?: BuiltinOption;
|
|
18
|
+
/** Web storage by default; a `SessionHistory` puts the transcript wherever the app keeps it, including a server. */
|
|
19
|
+
persist?: PersistOption | SessionHistory;
|
|
20
|
+
/** Called after a compaction replaced messages with one summary — where a host syncs its own watermark. */
|
|
21
|
+
onCompact?: AgentSessionOptions["onCompact"];
|
|
13
22
|
}
|
|
14
23
|
/**
|
|
15
24
|
* The one place a chat session is wired to the akan runtime. Chat and Zone both build one, and building it twice
|
|
16
25
|
* is how a zone came to be the only surface with no `compact` option — an option added on one side of a copy.
|
|
17
26
|
*/
|
|
18
|
-
export declare const agentSessionOf: ({ l, view, runner, instructions, maxTurns, compact, persist, }: AgentSessionSetup) => AgentSession;
|
|
27
|
+
export declare const agentSessionOf: ({ l, view, runner, instructions, maxTurns, compact, builtins, persist, onCompact, }: AgentSessionSetup) => AgentSession;
|
|
@@ -14,5 +14,5 @@ export declare const Agent: {
|
|
|
14
14
|
StateKey: typeof StateKey;
|
|
15
15
|
Tool: typeof Tool;
|
|
16
16
|
Transcript: typeof Transcript;
|
|
17
|
-
Zone: ({ className, id, label, instructions, runner, maxTurns, compact, persist, children, }: import("./Zone.d.ts").ZoneProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
Zone: ({ className, id, label, instructions, runner, maxTurns, compact, builtins, persist, onCompact, session: provided, onSession, children, }: import("./Zone.d.ts").ZoneProps) => import("react/jsx-runtime").JSX.Element;
|
|
18
18
|
};
|
|
@@ -11,4 +11,4 @@ export type PersistOption = boolean | {
|
|
|
11
11
|
* why the cap is applied *before* the pairing repair: the window it keeps can start between a tool call and the
|
|
12
12
|
* result answering it, and a transcript restored in that state is refused by the provider on its first turn.
|
|
13
13
|
*/
|
|
14
|
-
export declare const sessionHistoryOf: (persist: PersistOption | undefined, pathKey?: string) => SessionHistory | undefined;
|
|
14
|
+
export declare const sessionHistoryOf: (persist: PersistOption | SessionHistory | undefined, pathKey?: string) => SessionHistory | undefined;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { StoreSurfaceSource } from "akanjs/store";
|
|
2
|
+
import type { AgenticSurface, SurfaceView } from "../../vendor/use-agentic.d.ts";
|
|
3
|
+
/** One of the tools the akan runtime contributes to every screen, whatever that screen declares. */
|
|
4
|
+
export type AgentBuiltin = (typeof StoreSurfaceSource.builtins)[number];
|
|
5
|
+
/** `true` (the default) takes all of them, `false` none, an array exactly the ones it names. */
|
|
6
|
+
export type BuiltinOption = boolean | AgentBuiltin[];
|
|
7
|
+
/**
|
|
8
|
+
* The half of the surface one session reads: scoped to its zone, and narrowed to the built-ins it was given.
|
|
9
|
+
*
|
|
10
|
+
* Narrowing happens here rather than on the source because the source is shared — two sessions read one registry,
|
|
11
|
+
* and a zone that must not navigate away cannot take `navigate` off the screen for the root agent too. A withheld
|
|
12
|
+
* tool is withheld from `call` as well as from the listing, answering the same "unknown tool" a name that was
|
|
13
|
+
* never registered gets: a tool the model can still reach by guessing its name is not withheld.
|
|
14
|
+
*/
|
|
15
|
+
export declare const sessionView: (surface: AgenticSurface, path: string[], builtins?: BuiltinOption) => SurfaceView;
|
package/types/ui/RecentTime.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import { type Dayjs } from "akanjs/base";
|
|
2
|
+
export type RecentTimeRelativeUnit = "second" | "minute" | "hour" | "day" | "week" | "month" | "year";
|
|
3
|
+
export type RecentTimeRelativeStyle = "fromNow" | "always" | "auto";
|
|
4
|
+
export interface RecentTimeRelative {
|
|
5
|
+
unit: RecentTimeRelativeUnit;
|
|
6
|
+
/** Signed count in `unit`. Negative is past, positive is future, `0` is now. */
|
|
7
|
+
count: number;
|
|
8
|
+
date: Dayjs;
|
|
9
|
+
now: Dayjs;
|
|
10
|
+
defaultLabel: string;
|
|
11
|
+
}
|
|
12
|
+
export type RecentTimeRelativeFormat = RecentTimeRelativeStyle | ((relative: RecentTimeRelative) => string);
|
|
2
13
|
export interface RecentTimeProps {
|
|
3
14
|
/** Date value to render. Null renders nothing, and epoch placeholder values render --:--. */
|
|
4
15
|
date: Date | Dayjs | null;
|
|
@@ -6,7 +17,13 @@ export interface RecentTimeProps {
|
|
|
6
17
|
breakUnit?: Intl.RelativeTimeFormatUnit;
|
|
7
18
|
/** Use compact automatic formatting or always include date and time. */
|
|
8
19
|
format?: "full" | "auto";
|
|
20
|
+
/**
|
|
21
|
+
* Relative phrasing. `"fromNow"` (default) keeps dayjs locale strings (`하루 전`).
|
|
22
|
+
* `"always"` / `"auto"` use `Intl.RelativeTimeFormat` — `1일 전` vs `어제`.
|
|
23
|
+
* A function replaces the relative label; return `defaultLabel` to keep the default.
|
|
24
|
+
*/
|
|
25
|
+
relative?: RecentTimeRelativeFormat;
|
|
9
26
|
/** Additional classes for the trigger span. */
|
|
10
27
|
className?: string;
|
|
11
28
|
}
|
|
12
|
-
export declare const RecentTime: ({ date, breakUnit, format, className }: RecentTimeProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
29
|
+
export declare const RecentTime: ({ date, breakUnit, format, relative, className }: RecentTimeProps) => import("react/jsx-runtime").JSX.Element | null;
|
package/types/ui/index.d.ts
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
export { SessionContext, useAgent } from "../vendor/use-agentic.d.ts";
|
|
1
|
+
export { AgentProvider, type AgentProviderProps, type AgentRunner, AgentSession, type AgentSessionOptions, type ChatMessage, type CompactOptions, type ContextBlock, httpRunner, type PublishedTool, type RunnerEvent, type RunnerRequest, SessionContext, type SessionHistory, type SurfaceView, useAgent, } from "../vendor/use-agentic.d.ts";
|
|
2
2
|
export { Agent } from "./Agent.d.ts";
|
|
3
3
|
export { type ApprovalProps, DefaultApproval } from "./Agent/Approval.d.ts";
|
|
4
|
-
export { agentSessionOf } from "./Agent/agentSessionOf.d.ts";
|
|
4
|
+
export { type AgentSessionSetup, agentSessionOf } from "./Agent/agentSessionOf.d.ts";
|
|
5
5
|
export { type AttachReader, maxAttachmentBytes } from "./Agent/attachment.d.ts";
|
|
6
6
|
export { type BubbleProps, DefaultBubble } from "./Agent/Bubble.d.ts";
|
|
7
7
|
export type { ChatProps } from "./Agent/Chat.d.ts";
|
|
8
8
|
export { type ChatCommand, ChatCommands } from "./Agent/ChatCommands.d.ts";
|
|
9
9
|
export { type ComposerProps, DefaultComposer } from "./Agent/Composer.d.ts";
|
|
10
|
+
export { fetchRunner } from "./Agent/fetchRunner.d.ts";
|
|
10
11
|
export { DefaultLauncher, type LauncherProps } from "./Agent/Launcher.d.ts";
|
|
11
12
|
export { type CodeProps, DefaultCode, DefaultMarkdown, type MarkdownProps } from "./Agent/Markdown.d.ts";
|
|
12
13
|
export { DefaultMenu, type MenuProps as AgentMenuProps, type MenuRow } from "./Agent/Menu.d.ts";
|
|
13
14
|
export { DefaultQuestion, type QuestionProps } from "./Agent/Question.d.ts";
|
|
14
15
|
export type { PersistOption } from "./Agent/sessionHistory.d.ts";
|
|
16
|
+
export type { AgentBuiltin, BuiltinOption } from "./Agent/sessionView.d.ts";
|
|
15
17
|
export { tokenCount } from "./Agent/tokenCount.d.ts";
|
|
16
18
|
export type { VoiceEngine, VoiceHandlers, VoiceListener, VoiceSpeech } from "./Agent/voice.d.ts";
|
|
17
19
|
export { agentAttrs } from "./agentAttrs.d.ts";
|
|
@@ -52,7 +54,7 @@ export { Pagination } from "./Pagination.d.ts";
|
|
|
52
54
|
export { Popconfirm } from "./Popconfirm.d.ts";
|
|
53
55
|
export { Portal } from "./Portal.d.ts";
|
|
54
56
|
export { Radio } from "./Radio.d.ts";
|
|
55
|
-
export { RecentTime } from "./RecentTime.d.ts";
|
|
57
|
+
export { RecentTime, type RecentTimeProps, type RecentTimeRelative, type RecentTimeRelativeFormat, type RecentTimeRelativeStyle, type RecentTimeRelativeUnit, } from "./RecentTime.d.ts";
|
|
56
58
|
export { Refresh } from "./Refresh.d.ts";
|
|
57
59
|
export { type BadgeVariants, type ButtonVariants, badgeRecipe, buttonRecipe, type InputSurfaceVariants, inputRecipe, recipe, tv, } from "./recipe.d.ts";
|
|
58
60
|
export { ScreenNavigator } from "./ScreenNavigator.d.ts";
|
|
@@ -2,7 +2,7 @@ import { type ReactNode } from "react";
|
|
|
2
2
|
import { AgenticSurface } from "./AgenticSurface.d.ts";
|
|
3
3
|
import { AgentSession, type AgentSessionOptions } from "./AgentSession.d.ts";
|
|
4
4
|
import type { AgentRunner } from "./types.d.ts";
|
|
5
|
-
interface AgentProviderProps extends AgentSessionOptions {
|
|
5
|
+
export interface AgentProviderProps extends AgentSessionOptions {
|
|
6
6
|
surface?: AgenticSurface;
|
|
7
7
|
session?: AgentSession;
|
|
8
8
|
runner?: AgentRunner;
|
|
@@ -15,4 +15,3 @@ interface AgentProviderProps extends AgentSessionOptions {
|
|
|
15
15
|
* `useAgent` reads.
|
|
16
16
|
*/
|
|
17
17
|
export declare const AgentProvider: ({ surface, session, runner, children, ...options }: AgentProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
18
|
-
export {};
|
|
@@ -21,18 +21,31 @@ export interface PendingQuestion {
|
|
|
21
21
|
answer: (value: string | string[]) => void;
|
|
22
22
|
dismiss: (reason?: string) => void;
|
|
23
23
|
}
|
|
24
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Where a session keeps its transcript across page loads. Storage-neutral: the host decides what backs it, so a
|
|
26
|
+
* server-side transcript is as legal as web storage — which is why every method may answer asynchronously. A
|
|
27
|
+
* `load` still in flight when the user sends the first message is dropped rather than merged: the conversation
|
|
28
|
+
* on screen is the one they are having, and splicing a restored one under it would rewrite what they just said.
|
|
29
|
+
*
|
|
30
|
+
* Which makes **sending on mount a race the restore loses** — an opening prompt fired from an effect beats the
|
|
31
|
+
* fetch, and the user watches the conversation they came back to never arrive. Wait for `isRestoring` to clear,
|
|
32
|
+
* or write the prompt into the composer and leave the send to them.
|
|
33
|
+
*/
|
|
25
34
|
export interface SessionHistory {
|
|
26
|
-
load(): ChatMessage[] | null
|
|
27
|
-
save(messages: readonly ChatMessage[]): void
|
|
28
|
-
clear(): void
|
|
35
|
+
load(): ChatMessage[] | null | Promise<ChatMessage[] | null>;
|
|
36
|
+
save(messages: readonly ChatMessage[]): void | Promise<void>;
|
|
37
|
+
clear(): void | Promise<void>;
|
|
29
38
|
}
|
|
30
39
|
export interface AgentSessionOptions {
|
|
31
40
|
instructions?: string;
|
|
32
41
|
buildContext?: (surface: SurfaceView) => ContextBlock[];
|
|
33
42
|
/** Assistant turns per send before the session asks whether to keep going, or stops. */
|
|
34
43
|
maxTurns?: number;
|
|
35
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* Restores settled messages at construction and saves after every change, debounced. Failures are silent, and
|
|
46
|
+
* saves are chained rather than issued in parallel — an async host would otherwise land them out of order and
|
|
47
|
+
* persist an older transcript last.
|
|
48
|
+
*/
|
|
36
49
|
history?: SessionHistory;
|
|
37
50
|
/**
|
|
38
51
|
* Awaited after a tool that changed something and before its change report is taken. A surface is read
|
|
@@ -54,6 +67,15 @@ export interface AgentSessionOptions {
|
|
|
54
67
|
* few messages is replaced by one summary of itself, before the turn that would have overflowed is sent.
|
|
55
68
|
*/
|
|
56
69
|
compact?: CompactOptions;
|
|
70
|
+
/**
|
|
71
|
+
* Fires after a compaction replaced `replaced` with `summary`. A host that keeps its own server-side summary
|
|
72
|
+
* uses it to move its watermark to the same cut, so the two do not summarize the same messages twice.
|
|
73
|
+
*
|
|
74
|
+
* It matters most to a host whose watermark is a *position*: compaction shrinks the transcript in place, so a
|
|
75
|
+
* "sync everything past index N" scheme silently stops syncing once N is past the shortened array — no
|
|
76
|
+
* duplicate, no error, just messages that never reach the server. Reset the mark here.
|
|
77
|
+
*/
|
|
78
|
+
onCompact?: (replaced: readonly ChatMessage[], summary: ChatMessage) => void;
|
|
57
79
|
}
|
|
58
80
|
/**
|
|
59
81
|
* The client-side conversation loop: send → model turn → tool calls → approval gate → execute → report diffs → next
|
|
@@ -73,6 +95,11 @@ export declare class AgentSession {
|
|
|
73
95
|
*/
|
|
74
96
|
static readonly askUserTool: PublishedTool;
|
|
75
97
|
constructor(surface: SurfaceView, runner: AgentRunner, options?: AgentSessionOptions);
|
|
98
|
+
/**
|
|
99
|
+
* True while an async `history.load()` is still in flight — the transcript is empty but not yet known to be.
|
|
100
|
+
* A host that opens with a prompt of its own waits for this before sending, or the restore loses the race.
|
|
101
|
+
*/
|
|
102
|
+
get isRestoring(): boolean;
|
|
76
103
|
get surface(): SurfaceView;
|
|
77
104
|
get messages(): readonly ChatMessage[];
|
|
78
105
|
get isRunning(): boolean;
|
|
@@ -97,7 +124,7 @@ export declare class AgentSession {
|
|
|
97
124
|
/**
|
|
98
125
|
* Empties the transcript and the persisted history, ending a turn that is still running. Awaiting the abort
|
|
99
126
|
* matters: the loop settles in its own `finally`, a microtask later, and a transcript emptied before that lands
|
|
100
|
-
* is one the winding-down turn appends onto.
|
|
127
|
+
* is one the winding-down turn appends onto. The returned promise waits for the history to clear too.
|
|
101
128
|
*/
|
|
102
129
|
reset: () => Promise<void>;
|
|
103
130
|
/**
|
|
@@ -39,6 +39,11 @@ export declare class AgenticSurface {
|
|
|
39
39
|
*/
|
|
40
40
|
view(path: string[]): SurfaceView;
|
|
41
41
|
tool(name: string, view?: string[]): ToolEntry | null;
|
|
42
|
+
/**
|
|
43
|
+
* Whether a *mounted component* declares this name — a source's contribution answers `false`. The distinction is
|
|
44
|
+
* what lets a host drop the built-in tools without dropping a screen's own tool that deliberately shadows one.
|
|
45
|
+
*/
|
|
46
|
+
declares(name: string, view?: string[]): boolean;
|
|
42
47
|
/** Every call made through this surface, oldest first. What the dock shows the user to check against the screen. */
|
|
43
48
|
get transcript(): readonly AgentCall[];
|
|
44
49
|
call(name: string, args?: Record<string, unknown>, view?: string[]): Promise<unknown>;
|