devframe 0.9.13 → 0.9.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/{_shared-DEAMiPfH.d.mts → _shared-Bf2FcfJ4.d.mts} +1 -1
  2. package/dist/adapters/build.d.mts +1 -1
  3. package/dist/adapters/cac.d.mts +1 -1
  4. package/dist/adapters/cac.mjs +1 -1
  5. package/dist/adapters/dev.d.mts +3 -3
  6. package/dist/adapters/dev.mjs +1 -1
  7. package/dist/adapters/embedded.d.mts +1 -1
  8. package/dist/adapters/initiate.d.mts +4 -4
  9. package/dist/adapters/initiate.mjs +1 -1
  10. package/dist/adapters/mcp.d.mts +1 -1
  11. package/dist/client/index.d.mts +11 -1
  12. package/dist/client/index.mjs +12 -0
  13. package/dist/{context-BBWPLDHh.d.mts → context-B7411Bem.d.mts} +25 -5
  14. package/dist/{context-_temOGDB.d.mts → context-CIsx_QnV.d.mts} +1 -1
  15. package/dist/{dev-SPZzBTrH.mjs → dev-DpfkCVqo.mjs} +1 -1
  16. package/dist/in-page-channel/index.d.mts +1 -1
  17. package/dist/{index-1ezCLThh.d.mts → index--pZ3fdAq.d.mts} +23 -3
  18. package/dist/index.d.mts +1 -1
  19. package/dist/{instance-shell-xuu6jg51.mjs → instance-shell-370Oee9K.mjs} +4 -12
  20. package/dist/{instance-shell-BUyYrKlu.d.mts → instance-shell-B-FE8NY5.d.mts} +5 -5
  21. package/dist/internal/index.d.mts +4 -4
  22. package/dist/internal/index.mjs +1 -1
  23. package/dist/node/auth.d.mts +3 -3
  24. package/dist/node/auth.mjs +2 -2
  25. package/dist/node/hub-internals.d.mts +2 -2
  26. package/dist/node/index.d.mts +1 -1
  27. package/dist/recipes/common-rpc-functions.d.mts +1 -1
  28. package/dist/recipes/interactive-auth.d.mts +26 -15
  29. package/dist/recipes/interactive-auth.mjs +58 -18
  30. package/dist/rpc/transports/ws-bun.d.mts +1 -1
  31. package/dist/rpc/transports/ws-deno.d.mts +1 -1
  32. package/dist/{rpc-core-DiCr5etS.d.mts → rpc-core-D7WvbvK0.d.mts} +2 -2
  33. package/dist/{state-Mwt6--el.mjs → state-W4wI6X5X.mjs} +14 -1
  34. package/dist/types/index.d.mts +1 -1
  35. package/dist/utils/events.d.mts +1 -1
  36. package/dist/utils/shared-state.d.mts +1 -1
  37. package/dist/utils/streaming-channel.d.mts +1 -1
  38. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { F as DevframeDefinition, G as McpAuthorization, I as DevframeDeploymentKind, q as McpSetting, t as ConnectionMeta, zt as DevframeAgentHost } from "./context-BBWPLDHh.mjs";
1
+ import { F as DevframeDefinition, G as McpAuthorization, I as DevframeDeploymentKind, q as McpSetting, t as ConnectionMeta, zt as DevframeAgentHost } from "./context-B7411Bem.mjs";
2
2
  //#region src/adapters/_shared.d.ts
3
3
  /**
4
4
  * Resolve the mount base path for a devframe's SPA. Hosted adapters
@@ -1,4 +1,4 @@
1
- import { F as DevframeDefinition, V as DevframeSnapshotRpcEntry, o as DevframeNodeContext } from "../context-BBWPLDHh.mjs";
1
+ import { F as DevframeDefinition, V as DevframeSnapshotRpcEntry, o as DevframeNodeContext } from "../context-B7411Bem.mjs";
2
2
  import { o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
3
3
  //#region src/adapters/build.d.ts
4
4
  export interface CreateBuildOptions {
@@ -1,4 +1,4 @@
1
- import { Dt as InferCliFlags, Et as CliFlagsSchema, F as DevframeDefinition, Ot as defineCliFlags, kt as parseCliFlags, q as McpSetting } from "../context-BBWPLDHh.mjs";
1
+ import { Dt as InferCliFlags, Et as CliFlagsSchema, F as DevframeDefinition, Ot as defineCliFlags, kt as parseCliFlags, q as McpSetting } from "../context-B7411Bem.mjs";
2
2
  import { CAC } from "cac";
3
3
  import { H3 } from "h3";
4
4
  //#region src/adapters/cac.d.ts
@@ -1,7 +1,7 @@
1
1
  import { s as colors } from "../nostics-D0PvLZsn.mjs";
2
2
  import { i as resolveDevServerPort, s as importRuntimeModule } from "../_shared-U8D-xzrp.mjs";
3
3
  import { createBuild } from "./build.mjs";
4
- import { t as createDevServer } from "../dev-SPZzBTrH.mjs";
4
+ import { t as createDevServer } from "../dev-DpfkCVqo.mjs";
5
5
  import process from "node:process";
6
6
  import cac$1 from "cac";
7
7
  //#region src/adapters/flags.ts
@@ -1,8 +1,8 @@
1
1
  import { c as DevframeNodeRpcSessionMeta, l as DevframeRpcConnection, n as WsOriginRegistry } from "../ws-server-D2nv68Hg.mjs";
2
- import { F as DevframeDefinition, Tt as DevframeAuthHandler, U as DevframeSseOptions, W as DevframeWsOptions, q as McpSetting, s as DevframeNodeRpcSession } from "../context-BBWPLDHh.mjs";
2
+ import { F as DevframeDefinition, Tt as DevframeAuthHandler, U as DevframeSseOptions, W as DevframeWsOptions, q as McpSetting, s as DevframeNodeRpcSession } from "../context-B7411Bem.mjs";
3
3
  import { o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
4
- import { c as StartedServer } from "../instance-shell-BUyYrKlu.mjs";
5
- import { c as resolveMcpConnectionMeta, o as resolveDevServerPort, t as ResolveDevServerPortOptions } from "../_shared-DEAMiPfH.mjs";
4
+ import { c as StartedServer } from "../instance-shell-B-FE8NY5.mjs";
5
+ import { c as resolveMcpConnectionMeta, o as resolveDevServerPort, t as ResolveDevServerPortOptions } from "../_shared-Bf2FcfJ4.mjs";
6
6
  import { H3 } from "h3";
7
7
  //#region src/adapters/dev.d.ts
8
8
  export interface CreateDevServerOptions {
@@ -1,3 +1,3 @@
1
1
  import { i as resolveDevServerPort, o as resolveMcpConnectionMeta } from "../_shared-U8D-xzrp.mjs";
2
- import { t as createDevServer } from "../dev-SPZzBTrH.mjs";
2
+ import { t as createDevServer } from "../dev-DpfkCVqo.mjs";
3
3
  export { createDevServer, resolveDevServerPort, resolveMcpConnectionMeta };
@@ -1,4 +1,4 @@
1
- import { F as DevframeDefinition, o as DevframeNodeContext } from "../context-BBWPLDHh.mjs";
1
+ import { F as DevframeDefinition, o as DevframeNodeContext } from "../context-B7411Bem.mjs";
2
2
  //#region src/adapters/embedded.d.ts
3
3
  export interface CreateEmbeddedOptions {
4
4
  /** Target context the devframe is registered into. Required. */
@@ -1,7 +1,7 @@
1
1
  import { c as DevframeNodeRpcSessionMeta, l as DevframeRpcConnection, n as WsOriginRegistry } from "../ws-server-D2nv68Hg.mjs";
2
- import { F as DevframeDefinition, St as DevframeStorageScope, Tt as DevframeAuthHandler, U as DevframeSseOptions, W as DevframeWsOptions, o as DevframeNodeContext, q as McpSetting, s as DevframeNodeRpcSession, t as ConnectionMeta } from "../context-BBWPLDHh.mjs";
2
+ import { F as DevframeDefinition, St as DevframeStorageScope, Tt as DevframeAuthHandler, U as DevframeSseOptions, W as DevframeWsOptions, o as DevframeNodeContext, q as McpSetting, s as DevframeNodeRpcSession, t as ConnectionMeta } from "../context-B7411Bem.mjs";
3
3
  import { o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
4
- import { c as StartedServer, f as DevframeInstanceRecord } from "../instance-shell-BUyYrKlu.mjs";
4
+ import { c as StartedServer, f as DevframeInstanceRecord } from "../instance-shell-B-FE8NY5.mjs";
5
5
  import { Buffer } from "node:buffer";
6
6
  import { IncomingMessage, Server, ServerResponse } from "node:http";
7
7
  import { Duplex } from "node:stream";
@@ -63,8 +63,8 @@ export interface InitDevframeOptions {
63
63
  * Authentication for the RPC endpoint. A handler mounted inside an app
64
64
  * server is reachable by anything that can open its socket, so it **gates
65
65
  * by default**: when unset (or `true`), devframe's interactive OTP handler
66
- * is wired and its code/link banner prints once the public origin is known
67
- * (derived from the first request, or `origin`). Pass a
66
+ * is wired and its code/link banner prints when an untrusted client asks
67
+ * for a code (the client's `requestAuthCode()`). Pass a
68
68
  * {@link DevframeAuthHandler} for a custom scheme, or `false` to opt out
69
69
  * for a single-user localhost setup that owns the trust boundary another
70
70
  * way. Ignored for the `ws.url` tier, since the server behind that URL owns auth.
@@ -1,2 +1,2 @@
1
- import { n as getInstanceInternals, r as initDevframe } from "../dev-SPZzBTrH.mjs";
1
+ import { n as getInstanceInternals, r as initDevframe } from "../dev-DpfkCVqo.mjs";
2
2
  export { getInstanceInternals, initDevframe };
@@ -1,4 +1,4 @@
1
- import { F as DevframeDefinition, G as McpAuthorization, o as DevframeNodeContext } from "../context-BBWPLDHh.mjs";
1
+ import { F as DevframeDefinition, G as McpAuthorization, o as DevframeNodeContext } from "../context-B7411Bem.mjs";
2
2
  import { H3 } from "h3";
3
3
  import "@modelcontextprotocol/server";
4
4
  //#region src/adapters/mcp/build-server.d.ts
@@ -1,6 +1,6 @@
1
1
  import { f as RpcCacheManager, p as RpcCacheOptions } from "../index-pIVt92jP.mjs";
2
2
  import { _ as RpcFunctionDefinition, w as RpcFunctionsCollector } from "../types-Dq4i156u.mjs";
3
- import { Q as DevframeServiceMeta, Vt as EventEmitter, b as StreamSink, ct as DevframeSettings, d as RpcSharedStateHost, et as DevframeServiceScopeOf, gt as SettingsForNamespace, ht as ScopedSharedStates, it as DevframeServicesState, k as SharedState, mt as ScopedServerFunctions, pt as ScopedRpcFn, t as ConnectionMeta, u as RpcSharedStateGetOptions, vt as DevframeRpcClientFunctions, y as StreamReader, yt as DevframeRpcServerFunctions } from "../context-BBWPLDHh.mjs";
3
+ import { Q as DevframeServiceMeta, Vt as EventEmitter, b as StreamSink, ct as DevframeSettings, d as RpcSharedStateHost, et as DevframeServiceScopeOf, gt as SettingsForNamespace, ht as ScopedSharedStates, it as DevframeServicesState, k as SharedState, mt as ScopedServerFunctions, pt as ScopedRpcFn, t as ConnectionMeta, u as RpcSharedStateGetOptions, vt as DevframeRpcClientFunctions, y as StreamReader, yt as DevframeRpcServerFunctions } from "../context-B7411Bem.mjs";
4
4
  import { t as SseRpcChannelOptions } from "../sse-client-BQ4jS3eO.mjs";
5
5
  import { t as WsRpcChannelOptions } from "../ws-client-Xpxt0oPA.mjs";
6
6
  import { BirpcOptions, BirpcReturn } from "birpc";
@@ -394,6 +394,15 @@ export interface DevframeRpcClient {
394
394
  * authenticated.
395
395
  */
396
396
  requestTrustWithCode: (code: string) => Promise<boolean>;
397
+ /**
398
+ * Ask the server to print its one-time code banner in the terminal, e.g.
399
+ * when a custom auth UI is shown. Pass `reissue: true` to rotate the code
400
+ * first (a "re-issue" button), guaranteeing a freshly-valid code; without
401
+ * it the server prints each code at most once.
402
+ */
403
+ requestAuthCode: (options?: {
404
+ reissue?: boolean;
405
+ }) => Promise<void>;
397
406
  /**
398
407
  * Call a RPC function on the server
399
408
  */
@@ -476,6 +485,7 @@ export interface DevframeRpcClientMode {
476
485
  * token on success (for the caller to persist), or `null` on failure.
477
486
  */
478
487
  requestTrustWithCode: (code: string) => Promise<string | null>;
488
+ requestAuthCode: DevframeRpcClient['requestAuthCode'];
479
489
  call: DevframeRpcClient['call'];
480
490
  callEvent: DevframeRpcClient['callEvent'];
481
491
  callOptional: DevframeRpcClient['callOptional'];
@@ -1075,6 +1075,13 @@ function createLiveRpcClientMode(options) {
1075
1075
  }
1076
1076
  return token;
1077
1077
  }
1078
+ async function requestAuthCode(options = {}) {
1079
+ await serverRpc.$call("anonymous:devframe:auth:request-code", {
1080
+ ua: navigator.userAgent,
1081
+ origin: location.origin,
1082
+ ...options.reissue ? { reissue: true } : {}
1083
+ });
1084
+ }
1078
1085
  async function requestTrust() {
1079
1086
  if (isTrusted) return true;
1080
1087
  return requestTrustWithToken(currentAuthToken ?? "");
@@ -1105,6 +1112,7 @@ function createLiveRpcClientMode(options) {
1105
1112
  requestTrust,
1106
1113
  requestTrustWithToken,
1107
1114
  requestTrustWithCode,
1115
+ requestAuthCode,
1108
1116
  ensureTrusted,
1109
1117
  call: (...args) => {
1110
1118
  const method = String(args[0]);
@@ -1305,6 +1313,8 @@ async function createStaticRpcClientMode(options) {
1305
1313
  requestTrustWithToken: async () => true,
1306
1314
  /** Static backends are always trusted, so there's nothing to exchange. */
1307
1315
  requestTrustWithCode: async () => null,
1316
+ /** No server terminal to print a code in. */
1317
+ requestAuthCode: async () => {},
1308
1318
  ensureTrusted: async () => true,
1309
1319
  call: (...args) => staticCaller.call(args[0], args.slice(1)),
1310
1320
  callEvent: (...args) => staticCaller.callEvent(args[0], args.slice(1)),
@@ -1986,6 +1996,7 @@ async function getDevframeRpcClient(options = {}) {
1986
1996
  } catch {}
1987
1997
  return true;
1988
1998
  },
1999
+ requestAuthCode: (options) => mode.requestAuthCode(options),
1989
2000
  call: gateOnBootstrapAuth(mode.call),
1990
2001
  callEvent: gateOnBootstrapAuth(mode.callEvent),
1991
2002
  callOptional: gateOnBootstrapAuth(mode.callOptional),
@@ -2024,6 +2035,7 @@ async function getDevframeRpcClient(options = {}) {
2024
2035
  async function runSimpleAuthPrompt() {
2025
2036
  if (options.simpleAuth === false || !isTopLevelUnframed()) return;
2026
2037
  if (typeof globalThis.prompt !== "function") return;
2038
+ await rpc.requestAuthCode().catch(() => {});
2027
2039
  while (!rpc.isTrusted) {
2028
2040
  const code = globalThis.prompt("devframe: enter the authentication code shown in your terminal");
2029
2041
  if (code == null) return;
@@ -335,8 +335,9 @@ declare function parseCliFlags(schema: CliFlagsSchema, raw: Record<string, unkno
335
335
  interface DevframeAuthHandler {
336
336
  /**
337
337
  * `anonymous:devframe:auth` + `anonymous:devframe:auth:exchange` (the
338
- * handshake) and `devframe:auth:revoke` (self-revoke); register these on
339
- * the RPC host (e.g. `rpcHost.register(fn)` for each).
338
+ * handshake), `anonymous:devframe:auth:request-code` (client-requested
339
+ * banner print), and `devframe:auth:revoke` (self-revoke); register these
340
+ * on the RPC host (e.g. `rpcHost.register(fn)` for each).
340
341
  */
341
342
  rpcFunctions: RpcFunctionDefinitionAny[];
342
343
  /**
@@ -354,9 +355,11 @@ interface DevframeAuthHandler {
354
355
  */
355
356
  onConnect: (connection: DevframeRpcConnection, session: DevframeNodeRpcSession) => void;
356
357
  /**
357
- * Print the current one-time code and its magic-link URL. Devframe stays
358
- * headless, so call this yourself once the server is listening. Safe to
359
- * call repeatedly; it only prints once per code.
358
+ * Print the current one-time code and its magic-link URL. An untrusted
359
+ * browser client triggers this itself over
360
+ * `anonymous:devframe:auth:request-code`; call it directly when the host
361
+ * wants the code on screen without waiting for a client. Safe to call
362
+ * repeatedly; it only prints once per code.
360
363
  */
361
364
  printBanner: () => void;
362
365
  /**
@@ -589,6 +592,23 @@ interface DevframeRpcServerFunctions {
589
592
  }) => Promise<{
590
593
  authToken: string | null;
591
594
  }>;
595
+ /**
596
+ * Ask the server to print its auth banner (code + magic link) for this
597
+ * client, e.g. when an auth UI first shows; `reissue: true` rotates the code
598
+ * first (the manual "re-issue" action). Registered by
599
+ * `recipes/interactive-auth`; a repeat request for an already-printed code
600
+ * is a no-op.
601
+ *
602
+ * Named with the `anonymous:` prefix (see `isAnonymousRpcMethod`) so it is
603
+ * reachable before the connection is trusted.
604
+ *
605
+ * @internal
606
+ */
607
+ 'anonymous:devframe:auth:request-code': (params: {
608
+ ua: string;
609
+ origin: string;
610
+ reissue?: boolean;
611
+ }) => Promise<void>;
592
612
  /**
593
613
  * Self-revoke: the caller asks the server to revoke its own bearer token
594
614
  * (if any) and drop to untrusted. Requires an already-trusted caller, so
@@ -1,4 +1,4 @@
1
- import { k as SharedState, o as DevframeNodeContext } from "./context-BBWPLDHh.mjs";
1
+ import { k as SharedState, o as DevframeNodeContext } from "./context-B7411Bem.mjs";
2
2
  //#region src/node/hub-internals/context.d.ts
3
3
  interface InternalAnonymousAuthStorage {
4
4
  trusted: Record<string, {
@@ -5,7 +5,7 @@ import { t as createHostContext } from "./context-Cdj9z9m2.mjs";
5
5
  import { t as resolveStaticAssetsSource } from "./remote-assets-DMFzLSoH.mjs";
6
6
  import { a as resolveMcpConfig, i as resolveDevServerPort, n as normalizeBasePath, r as resolveBasePath, s as importRuntimeModule, t as loadAutoMcpAdapter } from "./_shared-U8D-xzrp.mjs";
7
7
  import { t as createH3DevframeHost } from "./host-h3-BROI6SQ4.mjs";
8
- import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, t as createInstanceShell } from "./instance-shell-xuu6jg51.mjs";
8
+ import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, t as createInstanceShell } from "./instance-shell-370Oee9K.mjs";
9
9
  import { open } from "./utils/open.mjs";
10
10
  import { mountStaticHandler } from "./utils/serve-static.mjs";
11
11
  import { resolve } from "pathe";
@@ -1,5 +1,5 @@
1
1
  import { D as InferArgsType, E as Thenable, O as InferReturnType, T as RpcReturnSchema, i as RpcArgsSchema } from "../types-Dq4i156u.mjs";
2
- import { Vt as EventEmitter, k as SharedState } from "../context-BBWPLDHh.mjs";
2
+ import { Vt as EventEmitter, k as SharedState } from "../context-B7411Bem.mjs";
3
3
  import { BirpcReturn } from "birpc";
4
4
  //#region src/in-page-channel/types.d.ts
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { k as SharedState, o as DevframeNodeContext, s as DevframeNodeRpcSession } from "./context-BBWPLDHh.mjs";
2
- import { n as InternalAnonymousAuthStorage } from "./context-_temOGDB.mjs";
1
+ import { k as SharedState, o as DevframeNodeContext, s as DevframeNodeRpcSession } from "./context-B7411Bem.mjs";
2
+ import { n as InternalAnonymousAuthStorage } from "./context-CIsx_QnV.mjs";
3
3
  //#region src/node/auth/revoke.d.ts
4
4
  /**
5
5
  * Flip `isTrusted` to false on any live WS clients connected with `token`
@@ -15,11 +15,31 @@ declare function revokeActiveConnectionsForToken(context: DevframeNodeContext, t
15
15
  declare function revokeAuthToken(context: DevframeNodeContext, storage: SharedState<InternalAnonymousAuthStorage>, token: string): Promise<void>;
16
16
  //#endregion
17
17
  //#region src/node/auth/state.d.ts
18
+ /**
19
+ * Format a raw `navigator.userAgent` string into the short display label
20
+ * shown for a trusted device (e.g. "Chrome 120 | macOS 14 desktop").
21
+ *
22
+ * The client used to parse+format this itself, but that pulled
23
+ * `ua-parser-modern` into the browser bundle for a label nothing else on
24
+ * the client needs; the client now sends the raw string and parsing
25
+ * happens here, at the server ingress, keeping the persisted label format
26
+ * identical.
27
+ */
28
+ declare function describeUA(userAgent: string): string;
18
29
  /**
19
30
  * The current one-time authentication code. Display this to the user (e.g. in
20
31
  * the dev-server terminal) so they can type it into the browser to authenticate.
21
32
  */
22
33
  declare function getTempAuthCode(): string;
34
+ /**
35
+ * The current code plus its expiry timestamp, for display (e.g. the auth
36
+ * banner). An already-expired code is rotated first, so the returned code is
37
+ * always redeemable for its remaining lifetime.
38
+ */
39
+ declare function getTempAuthCodeInfo(): {
40
+ code: string;
41
+ expireAt: number;
42
+ };
23
43
  /**
24
44
  * Rotate the authentication code, resetting its expiry window and failed-attempt
25
45
  * counter. Call this when a new authentication flow begins (e.g. when an
@@ -65,4 +85,4 @@ declare function exchangeTempAuthCode(code: string, session: DevframeNodeRpcSess
65
85
  origin: string;
66
86
  }, storage: SharedState<InternalAnonymousAuthStorage>): string | null;
67
87
  //#endregion
68
- export { verifyAuthToken as a, refreshTempAuthCode as i, exchangeTempAuthCode as n, revokeActiveConnectionsForToken as o, getTempAuthCode as r, revokeAuthToken as s, buildOtpAuthUrl as t };
88
+ export { getTempAuthCodeInfo as a, revokeActiveConnectionsForToken as c, getTempAuthCode as i, revokeAuthToken as l, describeUA as n, refreshTempAuthCode as o, exchangeTempAuthCode as r, verifyAuthToken as s, buildOtpAuthUrl as t };
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import "./index-pIVt92jP.mjs";
2
2
  import { C as RpcFunctionType, T as RpcReturnSchema, _ as RpcFunctionDefinition, g as RpcFunctionAgentOptions, i as RpcArgsSchema } from "./types-Dq4i156u.mjs";
3
3
  import { c as DevframeNodeRpcSessionMeta, d as DevframeRpcTransportKind, l as DevframeRpcConnection, u as DevframeRpcConnectionRequest } from "./ws-server-D2nv68Hg.mjs";
4
- import { $ as DevframeServiceOf, At as AgentHandle, B as DevframeSetupInfo, Bt as DevframeAgentHostEvents, Ct as DevframeDiagnosticsHost, F as DevframeDefinition, Ft as AgentTool, G as McpAuthorization, H as DevframeSnapshotRpcInputs, Ht as EventUnsubscribe, I as DevframeDeploymentKind, It as AgentToolInput, J as DevframeServiceDefinition, K as McpRouteOptions, L as DevframeDockDefaults, Lt as AgentToolProvider, Mt as AgentResource, Nt as AgentResourceContent, P as DevframeCliOptions, Pt as AgentResourceInput, Q as DevframeServiceMeta, R as DevframeDuplicationStrategy, Rt as AgentToolProviderHandle, St as DevframeStorageScope, U as DevframeSseOptions, Ut as EventsMap, V as DevframeSnapshotRpcEntry, Vt as EventEmitter, W as DevframeWsOptions, X as DevframeServiceId, Y as DevframeServiceDescriptor, Z as DevframeServiceInput, _t as DevframeViewHost, a as DevframeConnectionConfigsRegistry, at as DevframeScopedNodeContext, bt as DevframeRpcSharedStates, c as RpcBroadcastOptions, ct as DevframeSettings, d as RpcSharedStateHost, dt as ScopedBroadcastOptions, et as DevframeServiceScopeOf, f as RpcStreamingChannel, ft as ScopedClientFunctions, gt as SettingsForNamespace, ht as ScopedSharedStates, i as DevframeCapabilities, it as DevframeServicesState, jt as AgentManifest, l as RpcFunctionsHost, lt as DevframeSettingsRegistry, m as RpcStreamingHost, mt as ScopedServerFunctions, n as ConnectionMetaSse, nt as DevframeServicesRegistry, o as DevframeNodeContext, ot as DevframeScopedNodeRpc, p as RpcStreamingChannelOptions, pt as ScopedRpcFn, q as McpSetting, r as ConnectionMetaWebsocket, rt as DevframeServicesScopeRegistry, s as DevframeNodeRpcSession, st as DevframeScopedStreamingHost, t as ConnectionMeta, tt as DevframeServicesHost, u as RpcSharedStateGetOptions, ut as DevframeSettingsStore, vt as DevframeRpcClientFunctions, wt as DevframeDiagnosticsLogger, xt as DevframeHost, yt as DevframeRpcServerFunctions, z as DevframeRpcOptions, zt as DevframeAgentHost } from "./context-BBWPLDHh.mjs";
4
+ import { $ as DevframeServiceOf, At as AgentHandle, B as DevframeSetupInfo, Bt as DevframeAgentHostEvents, Ct as DevframeDiagnosticsHost, F as DevframeDefinition, Ft as AgentTool, G as McpAuthorization, H as DevframeSnapshotRpcInputs, Ht as EventUnsubscribe, I as DevframeDeploymentKind, It as AgentToolInput, J as DevframeServiceDefinition, K as McpRouteOptions, L as DevframeDockDefaults, Lt as AgentToolProvider, Mt as AgentResource, Nt as AgentResourceContent, P as DevframeCliOptions, Pt as AgentResourceInput, Q as DevframeServiceMeta, R as DevframeDuplicationStrategy, Rt as AgentToolProviderHandle, St as DevframeStorageScope, U as DevframeSseOptions, Ut as EventsMap, V as DevframeSnapshotRpcEntry, Vt as EventEmitter, W as DevframeWsOptions, X as DevframeServiceId, Y as DevframeServiceDescriptor, Z as DevframeServiceInput, _t as DevframeViewHost, a as DevframeConnectionConfigsRegistry, at as DevframeScopedNodeContext, bt as DevframeRpcSharedStates, c as RpcBroadcastOptions, ct as DevframeSettings, d as RpcSharedStateHost, dt as ScopedBroadcastOptions, et as DevframeServiceScopeOf, f as RpcStreamingChannel, ft as ScopedClientFunctions, gt as SettingsForNamespace, ht as ScopedSharedStates, i as DevframeCapabilities, it as DevframeServicesState, jt as AgentManifest, l as RpcFunctionsHost, lt as DevframeSettingsRegistry, m as RpcStreamingHost, mt as ScopedServerFunctions, n as ConnectionMetaSse, nt as DevframeServicesRegistry, o as DevframeNodeContext, ot as DevframeScopedNodeRpc, p as RpcStreamingChannelOptions, pt as ScopedRpcFn, q as McpSetting, r as ConnectionMetaWebsocket, rt as DevframeServicesScopeRegistry, s as DevframeNodeRpcSession, st as DevframeScopedStreamingHost, t as ConnectionMeta, tt as DevframeServicesHost, u as RpcSharedStateGetOptions, ut as DevframeSettingsStore, vt as DevframeRpcClientFunctions, wt as DevframeDiagnosticsLogger, xt as DevframeHost, yt as DevframeRpcServerFunctions, z as DevframeRpcOptions, zt as DevframeAgentHost } from "./context-B7411Bem.mjs";
5
5
  import { a as RemoteAssetsStore, i as RemoteAssetsProviderCustom, n as RemoteAssetsErrorMessage, o as StaticAssetsSource, r as RemoteAssetsProvider, t as RemoteAssets } from "./remote-assets-eBvSKZMS.mjs";
6
6
  import { i as DevframeDefineDiagnosticsOptions } from "./nostics-0sKe5HIj.mjs";
7
7
  //#region src/define.d.ts
@@ -258,9 +258,9 @@ function respondWith(event, response) {
258
258
  }
259
259
  /**
260
260
  * The shared machinery behind `initDevframe` and `initHub`: one mount base,
261
- * one h3 app, one lazily-derived public origin (and the auth banner that waits
262
- * for it), one WebSocket binding, and the fetch / connect-middleware pair that
263
- * serves them. Each factory supplies only what makes it itself (its context,
261
+ * one h3 app, one lazily-derived public origin (which backs the auth
262
+ * banner's magic link), one WebSocket binding, and the fetch /
263
+ * connect-middleware pair that serves them. Each factory supplies only what makes it itself (its context,
264
264
  * its routes, its diagnostics) through `init` / `mount`.
265
265
  *
266
266
  * Nothing here listens on a port unless a side-car was explicitly requested:
@@ -297,12 +297,6 @@ function createInstanceShell(options) {
297
297
  return explicitOrigin() || derivedOrigin;
298
298
  }
299
299
  let authHandler;
300
- let bannerPrinted = false;
301
- function maybePrintBanner() {
302
- if (bannerPrinted || !authHandler || !currentOrigin()) return;
303
- bannerPrinted = true;
304
- authHandler.printBanner();
305
- }
306
300
  let meta;
307
301
  let registration;
308
302
  let registerPromise;
@@ -343,7 +337,7 @@ function createInstanceShell(options) {
343
337
  * adopts only a loopback host or an exact `allowedOrigins` match, so a raw
344
338
  * inbound `Host`/URL authority never redirects the credential-bearing link.
345
339
  * First-valid-origin wins: an invalid candidate leaves `derivedOrigin` unset
346
- * (printing/registering nothing) so a later valid one can still be adopted.
340
+ * (registering nothing) so a later valid one can still be adopted.
347
341
  */
348
342
  function noteOrigin(candidate) {
349
343
  if (derivedOrigin === void 0 && !explicitOrigin()) {
@@ -351,7 +345,6 @@ function createInstanceShell(options) {
351
345
  const accepted = validateOriginCandidate(candidate, Array.isArray(allowed) ? allowed : void 0);
352
346
  if (accepted !== void 0) derivedOrigin = accepted;
353
347
  }
354
- maybePrintBanner();
355
348
  maybeRegister();
356
349
  }
357
350
  let started;
@@ -522,7 +515,6 @@ function createInstanceShell(options) {
522
515
  };
523
516
  if (Object.keys(ctx.staticConfig).length > 0) meta.configs = ctx.staticConfig;
524
517
  await options.mount?.(ctx, meta, api);
525
- maybePrintBanner();
526
518
  maybeRegister();
527
519
  }
528
520
  const initPromise = init();
@@ -1,6 +1,6 @@
1
1
  import { c as DevframeNodeRpcSessionMeta, l as DevframeRpcConnection, n as WsOriginRegistry } from "./ws-server-D2nv68Hg.mjs";
2
- import { Tt as DevframeAuthHandler, U as DevframeSseOptions, W as DevframeWsOptions, o as DevframeNodeContext, s as DevframeNodeRpcSession, t as ConnectionMeta, vt as DevframeRpcClientFunctions, yt as DevframeRpcServerFunctions } from "./context-BBWPLDHh.mjs";
3
- import "./index-1ezCLThh.mjs";
2
+ import { Tt as DevframeAuthHandler, U as DevframeSseOptions, W as DevframeWsOptions, o as DevframeNodeContext, s as DevframeNodeRpcSession, t as ConnectionMeta, vt as DevframeRpcClientFunctions, yt as DevframeRpcServerFunctions } from "./context-B7411Bem.mjs";
3
+ import "./index--pZ3fdAq.mjs";
4
4
  import { BirpcGroup } from "birpc";
5
5
  import { NodeAdapter } from "crossws/adapters/node";
6
6
  import { Buffer } from "node:buffer";
@@ -245,9 +245,9 @@ interface InstanceShell<TContext extends DevframeNodeContext> {
245
245
  declare function samePath(a: string, b: string): boolean;
246
246
  /**
247
247
  * The shared machinery behind `initDevframe` and `initHub`: one mount base,
248
- * one h3 app, one lazily-derived public origin (and the auth banner that waits
249
- * for it), one WebSocket binding, and the fetch / connect-middleware pair that
250
- * serves them. Each factory supplies only what makes it itself (its context,
248
+ * one h3 app, one lazily-derived public origin (which backs the auth
249
+ * banner's magic link), one WebSocket binding, and the fetch /
250
+ * connect-middleware pair that serves them. Each factory supplies only what makes it itself (its context,
251
251
  * its routes, its diagnostics) through `init` / `mount`.
252
252
  *
253
253
  * Nothing here listens on a port unless a side-car was explicitly requested:
@@ -1,9 +1,9 @@
1
1
  import { v as RpcFunctionDefinitionAny } from "../types-Dq4i156u.mjs";
2
- import { At as AgentHandle, Bt as DevframeAgentHostEvents, F as DevframeDefinition, Ft as AgentTool, It as AgentToolInput, Lt as AgentToolProvider, Mt as AgentResource, Nt as AgentResourceContent, Pt as AgentResourceInput, Rt as AgentToolProviderHandle, Vt as EventEmitter, jt as AgentManifest, o as DevframeNodeContext, xt as DevframeHost, zt as DevframeAgentHost$1 } from "../context-BBWPLDHh.mjs";
2
+ import { At as AgentHandle, Bt as DevframeAgentHostEvents, F as DevframeDefinition, Ft as AgentTool, It as AgentToolInput, Lt as AgentToolProvider, Mt as AgentResource, Nt as AgentResourceContent, Pt as AgentResourceInput, Rt as AgentToolProviderHandle, Vt as EventEmitter, jt as AgentManifest, o as DevframeNodeContext, xt as DevframeHost, zt as DevframeAgentHost$1 } from "../context-B7411Bem.mjs";
3
3
  import { a as RemoteAssetsStore, o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
4
- import { a as InstanceShellInit, c as StartedServer, d as samePath, f as DevframeInstanceRecord, h as registerDevframeInstance, i as InstanceShellApi, l as createInstanceShell, m as listLiveDevframeInstances, n as InstanceRegisterConfig, o as InstanceShellInternals, p as DevframeInstanceRegistration, r as InstanceShell, s as InstanceWsTier, t as CreateInstanceShellOptions, u as resolveInstanceRegister } from "../instance-shell-BUyYrKlu.mjs";
5
- import { a as resolveBasePath, i as normalizeBasePath, n as ResolvedMcpConfig, r as loadAutoMcpAdapter, s as resolveMcpConfig } from "../_shared-DEAMiPfH.mjs";
6
- import { n as CreateContextRpcServerOptions, r as createContextRpcServer, t as ContextRpcServer } from "../rpc-core-DiCr5etS.mjs";
4
+ import { a as InstanceShellInit, c as StartedServer, d as samePath, f as DevframeInstanceRecord, h as registerDevframeInstance, i as InstanceShellApi, l as createInstanceShell, m as listLiveDevframeInstances, n as InstanceRegisterConfig, o as InstanceShellInternals, p as DevframeInstanceRegistration, r as InstanceShell, s as InstanceWsTier, t as CreateInstanceShellOptions, u as resolveInstanceRegister } from "../instance-shell-B-FE8NY5.mjs";
5
+ import { a as resolveBasePath, i as normalizeBasePath, n as ResolvedMcpConfig, r as loadAutoMcpAdapter, s as resolveMcpConfig } from "../_shared-Bf2FcfJ4.mjs";
6
+ import { n as CreateContextRpcServerOptions, r as createContextRpcServer, t as ContextRpcServer } from "../rpc-core-D7WvbvK0.mjs";
7
7
  //#region src/client-assets.d.ts
8
8
  /**
9
9
  * Resolve a definition's client assets source: the built SPA served as its
@@ -5,6 +5,6 @@ import { n as coerceAgentPositionalArgs, t as DevframeAgentHost } from "../host-
5
5
  import { a as resolveMcpConfig, n as normalizeBasePath, r as resolveBasePath, s as importRuntimeModule, t as loadAutoMcpAdapter } from "../_shared-U8D-xzrp.mjs";
6
6
  import { t as createH3DevframeHost } from "../host-h3-BROI6SQ4.mjs";
7
7
  import { i as registerDevframeInstance, n as listLiveDevframeInstances } from "../instance-registry-DCq762YJ.mjs";
8
- import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, r as samePath, t as createInstanceShell } from "../instance-shell-xuu6jg51.mjs";
8
+ import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, r as samePath, t as createInstanceShell } from "../instance-shell-370Oee9K.mjs";
9
9
  import { t as createContextRpcServer } from "../rpc-core-CvkU23bQ.mjs";
10
10
  export { DevframeAgentHost, coerceAgentPositionalArgs, createContextRpcServer, createH3DevframeHost, createInstanceShell, createRpcWireCodec, diagnostics, importRuntimeModule, listLiveDevframeInstances, loadAutoMcpAdapter, normalizeBasePath, normalizeHttpServerUrl, peekRpcWireFrame, registerDevframeInstance, resolveBasePath, resolveClientAssets, resolveInstanceRegister, resolveMcpConfig, samePath };
@@ -1,3 +1,3 @@
1
- import { Tt as DevframeAuthHandler } from "../context-BBWPLDHh.mjs";
2
- import { a as verifyAuthToken, i as refreshTempAuthCode, n as exchangeTempAuthCode, o as revokeActiveConnectionsForToken, r as getTempAuthCode, s as revokeAuthToken, t as buildOtpAuthUrl } from "../index-1ezCLThh.mjs";
3
- export { DevframeAuthHandler, buildOtpAuthUrl, exchangeTempAuthCode, getTempAuthCode, refreshTempAuthCode, revokeActiveConnectionsForToken, revokeAuthToken, verifyAuthToken };
1
+ import { Tt as DevframeAuthHandler } from "../context-B7411Bem.mjs";
2
+ import { a as getTempAuthCodeInfo, c as revokeActiveConnectionsForToken, i as getTempAuthCode, l as revokeAuthToken, n as describeUA, o as refreshTempAuthCode, r as exchangeTempAuthCode, s as verifyAuthToken, t as buildOtpAuthUrl } from "../index--pZ3fdAq.mjs";
3
+ export { DevframeAuthHandler, buildOtpAuthUrl, describeUA, exchangeTempAuthCode, getTempAuthCode, getTempAuthCodeInfo, refreshTempAuthCode, revokeActiveConnectionsForToken, revokeAuthToken, verifyAuthToken };
@@ -1,3 +1,3 @@
1
1
  import { n as revokeAuthToken, t as revokeActiveConnectionsForToken } from "../revoke-cqztiCX4.mjs";
2
- import { a as verifyAuthToken, i as refreshTempAuthCode, n as exchangeTempAuthCode, r as getTempAuthCode, t as buildOtpAuthUrl } from "../state-Mwt6--el.mjs";
3
- export { buildOtpAuthUrl, exchangeTempAuthCode, getTempAuthCode, refreshTempAuthCode, revokeActiveConnectionsForToken, revokeAuthToken, verifyAuthToken };
2
+ import { a as getTempAuthCodeInfo, i as getTempAuthCode, n as describeUA, o as refreshTempAuthCode, r as exchangeTempAuthCode, s as verifyAuthToken, t as buildOtpAuthUrl } from "../state-W4wI6X5X.mjs";
3
+ export { buildOtpAuthUrl, describeUA, exchangeTempAuthCode, getTempAuthCode, getTempAuthCodeInfo, refreshTempAuthCode, revokeActiveConnectionsForToken, revokeAuthToken, verifyAuthToken };
@@ -1,3 +1,3 @@
1
- import { a as internalContextMap, i as getInternalContext, n as InternalAnonymousAuthStorage, r as RemoteTokenRecord, t as DevframeInternalContext } from "../context-_temOGDB.mjs";
2
- import { a as resolveBasePath, i as normalizeBasePath } from "../_shared-DEAMiPfH.mjs";
1
+ import { a as internalContextMap, i as getInternalContext, n as InternalAnonymousAuthStorage, r as RemoteTokenRecord, t as DevframeInternalContext } from "../context-CIsx_QnV.mjs";
2
+ import { a as resolveBasePath, i as normalizeBasePath } from "../_shared-Bf2FcfJ4.mjs";
3
3
  export { type DevframeInternalContext, type InternalAnonymousAuthStorage, type RemoteTokenRecord, getInternalContext, internalContextMap, normalizeBasePath, resolveBasePath };
@@ -1,6 +1,6 @@
1
1
  import "../index-pIVt92jP.mjs";
2
2
  import { v as RpcFunctionDefinitionAny } from "../types-Dq4i156u.mjs";
3
- import { k as SharedState, l as RpcFunctionsHost, o as DevframeNodeContext, xt as DevframeHost } from "../context-BBWPLDHh.mjs";
3
+ import { k as SharedState, l as RpcFunctionsHost, o as DevframeNodeContext, xt as DevframeHost } from "../context-B7411Bem.mjs";
4
4
  import { BirpcGroup } from "birpc";
5
5
  //#region src/node/context.d.ts
6
6
  export interface CreateHostContextOptions {
@@ -1,6 +1,6 @@
1
1
  import "../index-pIVt92jP.mjs";
2
2
  import { E as Thenable, S as RpcFunctionSetupResult, c as RpcDump, g as RpcFunctionAgentOptions } from "../types-Dq4i156u.mjs";
3
- import "../context-BBWPLDHh.mjs";
3
+ import "../context-B7411Bem.mjs";
4
4
  import { SimpleSchema } from "../utils/simple-schema.mjs";
5
5
  //#region src/recipes/common-rpc-functions.d.ts
6
6
  /**
@@ -1,5 +1,5 @@
1
- import { Tt as DevframeAuthHandler, o as DevframeNodeContext, s as DevframeNodeRpcSession } from "../context-BBWPLDHh.mjs";
2
- import "../index-1ezCLThh.mjs";
1
+ import { Tt as DevframeAuthHandler, o as DevframeNodeContext, s as DevframeNodeRpcSession } from "../context-B7411Bem.mjs";
2
+ import "../index--pZ3fdAq.mjs";
3
3
  import { ColorFn } from "../utils/colors.mjs";
4
4
  //#region src/recipes/interactive-auth.d.ts
5
5
  export interface CreateInteractiveAuthOptions {
@@ -11,20 +11,18 @@ export interface CreateInteractiveAuthOptions {
11
11
  */
12
12
  clientAuthTokens?: string[];
13
13
  /**
14
- * Print the current code + magic-link URL. Devframe stays headless, so
15
- * there is no default banner printed automatically; call
16
- * `auth.printBanner()` yourself once the server is listening. Defaults to
17
- * {@link createAuthBanner}'s output; pass its result here directly to
18
- * rebrand the box (title / colors), or your own function to replace the
19
- * format outright.
14
+ * Print the current code + magic-link URL. Runs when an untrusted browser
15
+ * client asks for a code (`anonymous:devframe:auth:request-code`, sent by
16
+ * the client's `requestAuthCode()`) or when the host calls
17
+ * `auth.printBanner()` itself. Defaults to {@link createAuthBanner}'s
18
+ * output; pass its result here directly to rebrand the box (title /
19
+ * colors), or your own function to replace the format outright.
20
20
  */
21
21
  banner?: AuthBannerFunction;
22
22
  /**
23
23
  * Called once a code exchange succeeds, so a host rendering its own
24
- * banner can retract it. Fires after the rotated code is printed, so
25
- * such a host drops that follow-up too and calls `auth.printBanner()`
26
- * when it next wants a code on screen. Connect-time trust from a static
27
- * or remote-dock token doesn't call this.
24
+ * banner can retract it. Connect-time trust from a static or
25
+ * remote-dock token doesn't call this.
28
26
  */
29
27
  onTrusted?: (info: {
30
28
  session: DevframeNodeRpcSession;
@@ -36,11 +34,24 @@ export interface CreateInteractiveAuthOptions {
36
34
  */
37
35
  serverUrl?: () => string;
38
36
  }
39
- /** Signature of `options.banner`: render the current auth code + magic-link URL. */
40
- export type AuthBannerFunction = (info: {
37
+ /** The browser client whose `anonymous:devframe:auth:request-code` call triggered a banner print. */
38
+ export interface AuthBannerRequester {
39
+ /** Short display label parsed from the client's user agent (e.g. `Chrome 120 | macOS 14 desktop`). */
40
+ ua: string;
41
+ /** The requesting page's `location.origin`. */
42
+ origin: string;
43
+ }
44
+ /** What `options.banner` receives on each print. */
45
+ export interface AuthBannerInfo {
41
46
  code: string;
42
47
  url: string;
43
- }) => void;
48
+ /** Epoch-ms timestamp the code stops being redeemable at. */
49
+ expireAt: number;
50
+ /** Present when a browser client requested the print; absent for a host's own `printBanner()` call. */
51
+ requester?: AuthBannerRequester;
52
+ }
53
+ /** Signature of `options.banner`: render the current auth code + magic-link URL. */
54
+ export type AuthBannerFunction = (info: AuthBannerInfo) => void;
44
55
  /** Palette for {@link createAuthBanner}'s box - one color per part, so a host can rebrand a subset. */
45
56
  export interface CreateAuthBannerColorsOptions {
46
57
  border: ColorFn;
@@ -1,7 +1,7 @@
1
1
  import { s as colors } from "../nostics-D0PvLZsn.mjs";
2
2
  import { n as defineRpcFunction } from "../define-BLWPsH6y.mjs";
3
3
  import { isAnonymousRpcMethod } from "../constants.mjs";
4
- import { a as verifyAuthToken, n as exchangeTempAuthCode, r as getTempAuthCode, t as buildOtpAuthUrl } from "../state-Mwt6--el.mjs";
4
+ import { a as getTempAuthCodeInfo, n as describeUA, o as refreshTempAuthCode, r as exchangeTempAuthCode, s as verifyAuthToken, t as buildOtpAuthUrl } from "../state-W4wI6X5X.mjs";
5
5
  import { t as getInternalContext } from "../context-jXO5vzjH.mjs";
6
6
  import { t as s } from "../simple-schema-Bi40l-P6.mjs";
7
7
  //#region src/recipes/interactive-auth.ts
@@ -16,28 +16,48 @@ function createAuthBanner(options = {}) {
16
16
  const title = options.title ?? "Devframe";
17
17
  const palette = {
18
18
  border: colors.dim,
19
- title: colors.bold,
19
+ title: (x) => colors.gray(colors.bold(x)),
20
20
  label: colors.dim,
21
- code: colors.bold,
21
+ code: (f) => colors.green(colors.bold(f)),
22
22
  url: colors.cyan,
23
23
  ...options.colors
24
24
  };
25
25
  return (info) => {
26
- const rows = [[
27
- "auth code",
28
- info.code,
29
- palette.code
30
- ], [
31
- "or open",
32
- info.url,
33
- palette.url
34
- ]];
26
+ const rows = [
27
+ [
28
+ "auth code",
29
+ info.code,
30
+ palette.code
31
+ ],
32
+ [
33
+ "or open",
34
+ info.url,
35
+ palette.url
36
+ ],
37
+ [
38
+ "expires at",
39
+ new Date(info.expireAt).toLocaleTimeString(),
40
+ palette.label
41
+ ]
42
+ ];
43
+ if (info.requester) {
44
+ rows.push([
45
+ "ua",
46
+ info.requester.ua,
47
+ palette.label
48
+ ]);
49
+ rows.push([
50
+ "origin",
51
+ info.requester.origin,
52
+ palette.label
53
+ ]);
54
+ }
35
55
  const labelWidth = Math.max(...rows.map(([label]) => label.length));
36
56
  const contentWidth = Math.max(...rows.map(([, value]) => labelWidth + 2 + value.length));
37
- const titleBarLength = title.length + 3;
57
+ const titleBarLength = title.length + 2;
38
58
  const lineWidth = Math.max(contentWidth, titleBarLength - 2);
39
59
  const top = [
40
- palette.border(`╭─`),
60
+ palette.border(`╭`),
41
61
  palette.title(title),
42
62
  palette.border(`${"─".repeat(Math.max(lineWidth + 2 - titleBarLength, 0))}╮`)
43
63
  ].join(" ");
@@ -83,14 +103,16 @@ function createInteractiveAuth(context, options = {}) {
83
103
  }
84
104
  const banner = options.banner ?? createAuthBanner();
85
105
  let bannerPrintedForCode;
86
- function printBanner() {
87
- const code = getTempAuthCode();
106
+ function printBanner(info) {
107
+ const { code, expireAt } = getTempAuthCodeInfo();
88
108
  if (code === bannerPrintedForCode) return;
89
109
  bannerPrintedForCode = code;
90
110
  const url = buildOtpAuthUrl(resolveServerUrl(), code);
91
111
  banner({
92
112
  code,
93
- url
113
+ url,
114
+ expireAt,
115
+ ...info?.requester ? { requester: info.requester } : {}
94
116
  });
95
117
  }
96
118
  const anonymousAuth = defineRpcFunction({
@@ -129,7 +151,6 @@ function createInteractiveAuth(context, options = {}) {
129
151
  const session = context.rpc.getCurrentRpcSession();
130
152
  if (!session) return { authToken: null };
131
153
  const authToken = exchangeTempAuthCode(params.code, session, params, storage);
132
- printBanner();
133
154
  if (authToken) options.onTrusted?.({
134
155
  session,
135
156
  authToken
@@ -137,6 +158,24 @@ function createInteractiveAuth(context, options = {}) {
137
158
  return { authToken };
138
159
  }
139
160
  });
161
+ const anonymousAuthRequestCode = defineRpcFunction({
162
+ name: "anonymous:devframe:auth:request-code",
163
+ type: "action",
164
+ jsonSerializable: true,
165
+ args: [s.object({
166
+ ua: s.string(),
167
+ origin: s.string(),
168
+ reissue: s.optional(s.boolean())
169
+ })],
170
+ returns: s.void(),
171
+ handler(params) {
172
+ if (params.reissue) refreshTempAuthCode();
173
+ printBanner({ requester: {
174
+ ua: describeUA(params.ua),
175
+ origin: params.origin
176
+ } });
177
+ }
178
+ });
140
179
  const revoke = defineRpcFunction({
141
180
  name: "devframe:auth:revoke",
142
181
  type: "action",
@@ -180,6 +219,7 @@ function createInteractiveAuth(context, options = {}) {
180
219
  rpcFunctions: [
181
220
  anonymousAuth,
182
221
  anonymousAuthExchange,
222
+ anonymousAuthRequestCode,
183
223
  revoke
184
224
  ],
185
225
  authorize,
@@ -1,5 +1,5 @@
1
1
  import { n as WsOriginRegistry } from "../../ws-server-D2nv68Hg.mjs";
2
- import { t as ContextRpcServer } from "../../rpc-core-DiCr5etS.mjs";
2
+ import { t as ContextRpcServer } from "../../rpc-core-D7WvbvK0.mjs";
3
3
  //#region src/rpc/transports/ws-bun.d.ts
4
4
  export interface AttachBunWsTransportOptions {
5
5
  /** Same contract as `WsRpcTransportOptions.allowedOrigins`. */
@@ -1,5 +1,5 @@
1
1
  import { n as WsOriginRegistry } from "../../ws-server-D2nv68Hg.mjs";
2
- import { t as ContextRpcServer } from "../../rpc-core-DiCr5etS.mjs";
2
+ import { t as ContextRpcServer } from "../../rpc-core-D7WvbvK0.mjs";
3
3
  //#region src/rpc/transports/ws-deno.d.ts
4
4
  export interface AttachDenoWsTransportOptions {
5
5
  /** Same contract as `WsRpcTransportOptions.allowedOrigins`. */
@@ -1,6 +1,6 @@
1
1
  import { c as DevframeNodeRpcSessionMeta, l as DevframeRpcConnection } from "./ws-server-D2nv68Hg.mjs";
2
- import { Tt as DevframeAuthHandler, o as DevframeNodeContext, s as DevframeNodeRpcSession, vt as DevframeRpcClientFunctions, yt as DevframeRpcServerFunctions } from "./context-BBWPLDHh.mjs";
3
- import "./index-1ezCLThh.mjs";
2
+ import { Tt as DevframeAuthHandler, o as DevframeNodeContext, s as DevframeNodeRpcSession, vt as DevframeRpcClientFunctions, yt as DevframeRpcServerFunctions } from "./context-B7411Bem.mjs";
3
+ import "./index--pZ3fdAq.mjs";
4
4
  import { BirpcGroup, EventOptions } from "birpc";
5
5
  //#region src/node/rpc-core.d.ts
6
6
  interface CreateContextRpcServerOptions {
@@ -1215,6 +1215,19 @@ function getTempAuthCode() {
1215
1215
  return ensureTempAuthCode();
1216
1216
  }
1217
1217
  /**
1218
+ * The current code plus its expiry timestamp, for display (e.g. the auth
1219
+ * banner). An already-expired code is rotated first, so the returned code is
1220
+ * always redeemable for its remaining lifetime.
1221
+ */
1222
+ function getTempAuthCodeInfo() {
1223
+ ensureTempAuthCode();
1224
+ if (Date.now() > tempAuthCodeExpiresAt) refreshTempAuthCode();
1225
+ return {
1226
+ code: tempAuthCode,
1227
+ expireAt: tempAuthCodeExpiresAt
1228
+ };
1229
+ }
1230
+ /**
1218
1231
  * Rotate the authentication code, resetting its expiry window and failed-attempt
1219
1232
  * counter. Call this when a new authentication flow begins (e.g. when an
1220
1233
  * untrusted client starts authenticating) so the displayed code is freshly
@@ -1296,4 +1309,4 @@ function exchangeTempAuthCode(code, session, info, storage) {
1296
1309
  return authToken;
1297
1310
  }
1298
1311
  //#endregion
1299
- export { verifyAuthToken as a, refreshTempAuthCode as i, exchangeTempAuthCode as n, getTempAuthCode as r, buildOtpAuthUrl as t };
1312
+ export { getTempAuthCodeInfo as a, getTempAuthCode as i, describeUA as n, refreshTempAuthCode as o, exchangeTempAuthCode as r, verifyAuthToken as s, buildOtpAuthUrl as t };
@@ -1,6 +1,6 @@
1
1
  import { g as RpcFunctionAgentOptions } from "../types-Dq4i156u.mjs";
2
2
  import { c as DevframeNodeRpcSessionMeta, d as DevframeRpcTransportKind, l as DevframeRpcConnection, u as DevframeRpcConnectionRequest } from "../ws-server-D2nv68Hg.mjs";
3
- import { $ as DevframeServiceOf, At as AgentHandle, B as DevframeSetupInfo, Bt as DevframeAgentHostEvents, Ct as DevframeDiagnosticsHost, F as DevframeDefinition, Ft as AgentTool, G as McpAuthorization, H as DevframeSnapshotRpcInputs, Ht as EventUnsubscribe, I as DevframeDeploymentKind, It as AgentToolInput, J as DevframeServiceDefinition, K as McpRouteOptions, L as DevframeDockDefaults, Lt as AgentToolProvider, Mt as AgentResource, Nt as AgentResourceContent, P as DevframeCliOptions, Pt as AgentResourceInput, Q as DevframeServiceMeta, R as DevframeDuplicationStrategy, Rt as AgentToolProviderHandle, St as DevframeStorageScope, U as DevframeSseOptions, Ut as EventsMap, V as DevframeSnapshotRpcEntry, Vt as EventEmitter, W as DevframeWsOptions, X as DevframeServiceId, Y as DevframeServiceDescriptor, Z as DevframeServiceInput, _t as DevframeViewHost, a as DevframeConnectionConfigsRegistry, at as DevframeScopedNodeContext, bt as DevframeRpcSharedStates, c as RpcBroadcastOptions, ct as DevframeSettings, d as RpcSharedStateHost, dt as ScopedBroadcastOptions, et as DevframeServiceScopeOf, f as RpcStreamingChannel, ft as ScopedClientFunctions, gt as SettingsForNamespace, ht as ScopedSharedStates, i as DevframeCapabilities, it as DevframeServicesState, jt as AgentManifest, l as RpcFunctionsHost, lt as DevframeSettingsRegistry, m as RpcStreamingHost, mt as ScopedServerFunctions, n as ConnectionMetaSse, nt as DevframeServicesRegistry, o as DevframeNodeContext, ot as DevframeScopedNodeRpc, p as RpcStreamingChannelOptions, pt as ScopedRpcFn, q as McpSetting, r as ConnectionMetaWebsocket, rt as DevframeServicesScopeRegistry, s as DevframeNodeRpcSession, st as DevframeScopedStreamingHost, t as ConnectionMeta, tt as DevframeServicesHost, u as RpcSharedStateGetOptions, ut as DevframeSettingsStore, vt as DevframeRpcClientFunctions, wt as DevframeDiagnosticsLogger, xt as DevframeHost, yt as DevframeRpcServerFunctions, z as DevframeRpcOptions, zt as DevframeAgentHost } from "../context-BBWPLDHh.mjs";
3
+ import { $ as DevframeServiceOf, At as AgentHandle, B as DevframeSetupInfo, Bt as DevframeAgentHostEvents, Ct as DevframeDiagnosticsHost, F as DevframeDefinition, Ft as AgentTool, G as McpAuthorization, H as DevframeSnapshotRpcInputs, Ht as EventUnsubscribe, I as DevframeDeploymentKind, It as AgentToolInput, J as DevframeServiceDefinition, K as McpRouteOptions, L as DevframeDockDefaults, Lt as AgentToolProvider, Mt as AgentResource, Nt as AgentResourceContent, P as DevframeCliOptions, Pt as AgentResourceInput, Q as DevframeServiceMeta, R as DevframeDuplicationStrategy, Rt as AgentToolProviderHandle, St as DevframeStorageScope, U as DevframeSseOptions, Ut as EventsMap, V as DevframeSnapshotRpcEntry, Vt as EventEmitter, W as DevframeWsOptions, X as DevframeServiceId, Y as DevframeServiceDescriptor, Z as DevframeServiceInput, _t as DevframeViewHost, a as DevframeConnectionConfigsRegistry, at as DevframeScopedNodeContext, bt as DevframeRpcSharedStates, c as RpcBroadcastOptions, ct as DevframeSettings, d as RpcSharedStateHost, dt as ScopedBroadcastOptions, et as DevframeServiceScopeOf, f as RpcStreamingChannel, ft as ScopedClientFunctions, gt as SettingsForNamespace, ht as ScopedSharedStates, i as DevframeCapabilities, it as DevframeServicesState, jt as AgentManifest, l as RpcFunctionsHost, lt as DevframeSettingsRegistry, m as RpcStreamingHost, mt as ScopedServerFunctions, n as ConnectionMetaSse, nt as DevframeServicesRegistry, o as DevframeNodeContext, ot as DevframeScopedNodeRpc, p as RpcStreamingChannelOptions, pt as ScopedRpcFn, q as McpSetting, r as ConnectionMetaWebsocket, rt as DevframeServicesScopeRegistry, s as DevframeNodeRpcSession, st as DevframeScopedStreamingHost, t as ConnectionMeta, tt as DevframeServicesHost, u as RpcSharedStateGetOptions, ut as DevframeSettingsStore, vt as DevframeRpcClientFunctions, wt as DevframeDiagnosticsLogger, xt as DevframeHost, yt as DevframeRpcServerFunctions, z as DevframeRpcOptions, zt as DevframeAgentHost } from "../context-B7411Bem.mjs";
4
4
  import { a as RemoteAssetsStore, i as RemoteAssetsProviderCustom, n as RemoteAssetsErrorMessage, o as StaticAssetsSource, r as RemoteAssetsProvider, t as RemoteAssets } from "../remote-assets-eBvSKZMS.mjs";
5
5
  import { i as DevframeDefineDiagnosticsOptions } from "../nostics-0sKe5HIj.mjs";
6
6
  export { AgentHandle, AgentManifest, AgentResource, AgentResourceContent, AgentResourceInput, AgentTool, AgentToolInput, AgentToolProvider, AgentToolProviderHandle, ConnectionMeta, ConnectionMetaSse, ConnectionMetaWebsocket, DevframeAgentHost, DevframeAgentHostEvents, DevframeCapabilities, DevframeCliOptions, DevframeConnectionConfigsRegistry, type DevframeDefineDiagnosticsOptions, DevframeDefinition, DevframeDeploymentKind, DevframeDiagnosticsHost, DevframeDiagnosticsLogger, DevframeDockDefaults, DevframeDuplicationStrategy, DevframeHost, DevframeNodeContext, DevframeNodeRpcSession, type DevframeNodeRpcSessionMeta, DevframeRpcClientFunctions, type DevframeRpcConnection, type DevframeRpcConnectionRequest, DevframeRpcOptions, DevframeRpcServerFunctions, DevframeRpcSharedStates, type DevframeRpcTransportKind, DevframeScopedNodeContext, DevframeScopedNodeRpc, DevframeScopedStreamingHost, DevframeServiceDefinition, DevframeServiceDescriptor, DevframeServiceId, DevframeServiceInput, DevframeServiceMeta, DevframeServiceOf, DevframeServiceScopeOf, DevframeServicesHost, DevframeServicesRegistry, DevframeServicesScopeRegistry, DevframeServicesState, DevframeSettings, DevframeSettingsRegistry, DevframeSettingsStore, DevframeSetupInfo, DevframeSnapshotRpcEntry, DevframeSnapshotRpcInputs, DevframeSseOptions, DevframeStorageScope, DevframeViewHost, DevframeWsOptions, EventEmitter, EventUnsubscribe, EventsMap, McpAuthorization, McpRouteOptions, McpSetting, RemoteAssets, RemoteAssetsErrorMessage, RemoteAssetsProvider, RemoteAssetsProviderCustom, RemoteAssetsStore, RpcBroadcastOptions, type RpcFunctionAgentOptions, RpcFunctionsHost, RpcSharedStateGetOptions, RpcSharedStateHost, RpcStreamingChannel, RpcStreamingChannelOptions, RpcStreamingHost, ScopedBroadcastOptions, ScopedClientFunctions, ScopedRpcFn, ScopedServerFunctions, ScopedSharedStates, SettingsForNamespace, StaticAssetsSource };
@@ -1,4 +1,4 @@
1
- import { Ut as EventsMap, Vt as EventEmitter } from "../context-BBWPLDHh.mjs";
1
+ import { Ut as EventsMap, Vt as EventEmitter } from "../context-B7411Bem.mjs";
2
2
  //#region src/utils/events.d.ts
3
3
  /**
4
4
  * Create event emitter.
@@ -1,2 +1,2 @@
1
- import { A as SharedStateEvents, D as ImmutableObject, E as ImmutableMap, M as SharedStatePatch, N as createSharedState, O as ImmutableSet, T as ImmutableArray, j as SharedStateOptions, k as SharedState, w as Immutable } from "../context-BBWPLDHh.mjs";
1
+ import { A as SharedStateEvents, D as ImmutableObject, E as ImmutableMap, M as SharedStatePatch, N as createSharedState, O as ImmutableSet, T as ImmutableArray, j as SharedStateOptions, k as SharedState, w as Immutable } from "../context-B7411Bem.mjs";
2
2
  export { Immutable, ImmutableArray, ImmutableMap, ImmutableObject, ImmutableSet, SharedState, SharedStateEvents, SharedStateOptions, SharedStatePatch, createSharedState };
@@ -1,2 +1,2 @@
1
- import { C as createStreamSink, S as createStreamReader, _ as CreateStreamSinkOptions, b as StreamSink, g as CreateStreamReaderOptions, h as BufferedChunk, v as StreamErrorPayload, x as StreamSinkEvents, y as StreamReader } from "../context-BBWPLDHh.mjs";
1
+ import { C as createStreamSink, S as createStreamReader, _ as CreateStreamSinkOptions, b as StreamSink, g as CreateStreamReaderOptions, h as BufferedChunk, v as StreamErrorPayload, x as StreamSinkEvents, y as StreamReader } from "../context-B7411Bem.mjs";
2
2
  export { BufferedChunk, CreateStreamReaderOptions, CreateStreamSinkOptions, StreamErrorPayload, StreamReader, StreamSink, StreamSinkEvents, createStreamReader, createStreamSink };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "devframe",
3
3
  "type": "module",
4
- "version": "0.9.13",
4
+ "version": "0.9.15",
5
5
  "description": "Framework for building one portable devtool integration that runs in any viewer.",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",