@parlor/core 0.4.0 → 0.4.2

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/dist/action.d.ts CHANGED
@@ -53,10 +53,11 @@ export interface ActionConfig<TInput extends z.ZodType, TOutput> {
53
53
  readonly reads?: ReadTags<z.output<TInput>> | undefined;
54
54
  readonly writes?: readonly TagSource[] | undefined;
55
55
  /**
56
- * Whose clients its `writes` wake: everyone in the scope (the default), or only the
57
- * caller's own user, with their tabs and computers, when the scope is shared.
56
+ * Whose clients its `writes` wake: everyone in the scope (the default), only the caller's
57
+ * own user, with their tabs and computers, when the scope is shared, or that user in every
58
+ * scope (`account`), for what belongs to the person rather than the scope.
58
59
  */
59
- readonly notifies?: "scope" | "user" | undefined;
60
+ readonly notifies?: "scope" | "user" | "account" | undefined;
60
61
  /**
61
62
  * Ask the user to approve each call from an agent (source `mcp` or `agent`) in the app
62
63
  * before it runs. Calls from the app's own UI and plain HTTP never ask, and a call with an
@@ -1 +1 @@
1
- {"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"action.js","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"AAyFA,MAAM,OAAO,GAAkB,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAYvD,MAAM,UAAU,YAAY,CAC1B,MAAqC;IAErC,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAiB;IAC1C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,iBAAiB,GAA8B,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAE/E,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,MAAoB;IACvE,OAAO,MAAM,CAAC,OAAO,KAAK,IAAI,IAAI,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,cAAc,GAAG;IACrB,SAAS,EAAE,MAAM;IACjB,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,KAAK;IACZ,IAAI,EAAE,MAAM;IACZ,GAAG,EAAE,MAAM;CAC2C,CAAC;AAEzD,MAAM,UAAU,iBAAiB,CAAC,SAAoB;IACpD,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,IAAI,SAAS,CAAC,IAAI;QAAE,OAAO,OAAO,CAAC;IACjE,OAAO,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAiB,EAAE,SAAkB;IAClE,OAAO,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC;AAC7C,CAAC","sourcesContent":["import type { z } from \"zod\";\n\nimport type { Principal, PrincipalKind } from \"./principal.js\";\n\nexport type ActionSource = \"ui\" | \"agent\" | \"http\" | \"mcp\";\n\nexport interface DataRegister {}\n\nexport type ParlorDatabase = DataRegister extends { database: infer D } ? D : unknown;\n\nexport type Unlisten = () => Promise<void>;\n\nexport interface ListenOptions {\n /**\n * The connection behind this listener dropped. It is gone for good, and notifications\n * sent until a new `listen` call succeeds are lost, so a listener must listen again and\n * reload whatever it derived from them.\n */\n readonly onLost?: (() => void) | undefined;\n}\n\nexport interface DataProvider<TDb = unknown> {\n /**\n * Work deferred to the server's first request, such as migrations on runtimes that allow\n * no I/O while the app loads. The server awaits it before anything else touches the data.\n */\n prepare?(): Promise<void>;\n read(): TDb;\n transaction<T>(run: (tx: TDb) => Promise<T>): Promise<T>;\n listen?(\n channel: string,\n handler: (payload: string) => void,\n options?: ListenOptions,\n ): Promise<Unlisten>;\n close?(): Promise<void>;\n}\n\nexport interface ActionContext {\n readonly scope: string;\n readonly source: ActionSource;\n readonly principal: Principal;\n readonly db: ParlorDatabase;\n readonly signal?: AbortSignal | undefined;\n /**\n * The HTTP request that made the call, whichever surface it came through; undefined for\n * an in-process call. For what the request carries besides identity, such as a cookie\n * the app set; who is calling is `principal`.\n */\n readonly request?: Request | undefined;\n}\n\nexport interface TableLike {\n readonly _: { readonly name: string };\n}\n\nexport type TagSource = string | TableLike;\nexport type Tag = readonly (string | number)[];\nexport type ReadTags<TInput> = readonly TagSource[] | ((input: TInput) => readonly Tag[]);\n\nexport interface ActionConfig<TInput extends z.ZodType, TOutput> {\n readonly description: string;\n readonly input: TInput;\n readonly reads?: ReadTags<z.output<TInput>> | undefined;\n readonly writes?: readonly TagSource[] | undefined;\n /**\n * Whose clients its `writes` wake: everyone in the scope (the default), or only the\n * caller's own user, with their tabs and computers, when the scope is shared.\n */\n readonly notifies?: \"scope\" | \"user\" | undefined;\n /**\n * Ask the user to approve each call from an agent (source `mcp` or `agent`) in the app\n * before it runs. Calls from the app's own UI and plain HTTP never ask, and a call with an\n * API key is refused, as nobody can approve for it. The server's `confirmation` policy can\n * change both. With an enforcing auth provider the source comes from the caller's\n * credential, so this is a boundary; without one it stays a UX guard over a\n * self-declared header.\n */\n readonly confirm?: boolean | undefined;\n /**\n * Callable without signing in. Only read when the server has an enforcing auth provider,\n * which otherwise answers an anonymous caller with `unauthenticated`.\n */\n readonly public?: boolean | undefined;\n readonly run: (\n input: z.output<TInput>,\n ctx: ActionContext,\n ) => Promise<TOutput> | TOutput;\n}\n\nconst kAction: unique symbol = Symbol.for(\"fw.action\");\n\nexport interface ActionDefinition<\n TInput extends z.ZodType = z.ZodType,\n TOutput = unknown,\n> extends ActionConfig<TInput, TOutput> {\n readonly [kAction]: true;\n}\n\nexport type AnyAction = ActionDefinition<z.ZodType, unknown>;\nexport type ActionMap = Record<string, AnyAction>;\n\nexport function defineAction<TInput extends z.ZodType, TOutput>(\n config: ActionConfig<TInput, TOutput>,\n): ActionDefinition<TInput, TOutput> {\n return { ...config, [kAction]: true };\n}\n\nexport function isAction(value: unknown): value is AnyAction {\n return typeof value === \"object\" && value !== null && kAction in value;\n}\n\nexport function isMutating(action: AnyAction): boolean {\n return (action.writes?.length ?? 0) > 0;\n}\n\nconst CONFIRMED_SOURCES: ReadonlySet<ActionSource> = new Set([\"mcp\", \"agent\"]);\n\nexport function needsConfirmation(action: AnyAction, source: ActionSource): boolean {\n return action.confirm === true && CONFIRMED_SOURCES.has(source);\n}\n\nconst SOURCE_BY_KIND = {\n anonymous: \"http\",\n user: \"ui\",\n agent: \"mcp\",\n host: \"http\",\n key: \"http\",\n} as const satisfies Record<PrincipalKind, ActionSource>;\n\nexport function sourceOfPrincipal(principal: Principal): ActionSource {\n if (principal.kind === \"agent\" && principal.turn) return \"agent\";\n return SOURCE_BY_KIND[principal.kind];\n}\n\nexport function needsPrincipal(action: AnyAction, enforcing: boolean): boolean {\n return enforcing && action.public !== true;\n}\n\nexport type ActionInput<A> =\n A extends ActionDefinition<infer I, unknown> ? z.input<I> : never;\nexport type ActionOutput<A> = A extends ActionDefinition<z.ZodType, infer O> ? O : never;\n"]}
1
+ {"version":3,"file":"action.js","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"AA0FA,MAAM,OAAO,GAAkB,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAYvD,MAAM,UAAU,YAAY,CAC1B,MAAqC;IAErC,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAiB;IAC1C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,iBAAiB,GAA8B,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAE/E,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,MAAoB;IACvE,OAAO,MAAM,CAAC,OAAO,KAAK,IAAI,IAAI,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,cAAc,GAAG;IACrB,SAAS,EAAE,MAAM;IACjB,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,KAAK;IACZ,IAAI,EAAE,MAAM;IACZ,GAAG,EAAE,MAAM;CAC2C,CAAC;AAEzD,MAAM,UAAU,iBAAiB,CAAC,SAAoB;IACpD,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,IAAI,SAAS,CAAC,IAAI;QAAE,OAAO,OAAO,CAAC;IACjE,OAAO,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAiB,EAAE,SAAkB;IAClE,OAAO,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC;AAC7C,CAAC","sourcesContent":["import type { z } from \"zod\";\n\nimport type { Principal, PrincipalKind } from \"./principal.js\";\n\nexport type ActionSource = \"ui\" | \"agent\" | \"http\" | \"mcp\";\n\nexport interface DataRegister {}\n\nexport type ParlorDatabase = DataRegister extends { database: infer D } ? D : unknown;\n\nexport type Unlisten = () => Promise<void>;\n\nexport interface ListenOptions {\n /**\n * The connection behind this listener dropped. It is gone for good, and notifications\n * sent until a new `listen` call succeeds are lost, so a listener must listen again and\n * reload whatever it derived from them.\n */\n readonly onLost?: (() => void) | undefined;\n}\n\nexport interface DataProvider<TDb = unknown> {\n /**\n * Work deferred to the server's first request, such as migrations on runtimes that allow\n * no I/O while the app loads. The server awaits it before anything else touches the data.\n */\n prepare?(): Promise<void>;\n read(): TDb;\n transaction<T>(run: (tx: TDb) => Promise<T>): Promise<T>;\n listen?(\n channel: string,\n handler: (payload: string) => void,\n options?: ListenOptions,\n ): Promise<Unlisten>;\n close?(): Promise<void>;\n}\n\nexport interface ActionContext {\n readonly scope: string;\n readonly source: ActionSource;\n readonly principal: Principal;\n readonly db: ParlorDatabase;\n readonly signal?: AbortSignal | undefined;\n /**\n * The HTTP request that made the call, whichever surface it came through; undefined for\n * an in-process call. For what the request carries besides identity, such as a cookie\n * the app set; who is calling is `principal`.\n */\n readonly request?: Request | undefined;\n}\n\nexport interface TableLike {\n readonly _: { readonly name: string };\n}\n\nexport type TagSource = string | TableLike;\nexport type Tag = readonly (string | number)[];\nexport type ReadTags<TInput> = readonly TagSource[] | ((input: TInput) => readonly Tag[]);\n\nexport interface ActionConfig<TInput extends z.ZodType, TOutput> {\n readonly description: string;\n readonly input: TInput;\n readonly reads?: ReadTags<z.output<TInput>> | undefined;\n readonly writes?: readonly TagSource[] | undefined;\n /**\n * Whose clients its `writes` wake: everyone in the scope (the default), only the caller's\n * own user, with their tabs and computers, when the scope is shared, or that user in every\n * scope (`account`), for what belongs to the person rather than the scope.\n */\n readonly notifies?: \"scope\" | \"user\" | \"account\" | undefined;\n /**\n * Ask the user to approve each call from an agent (source `mcp` or `agent`) in the app\n * before it runs. Calls from the app's own UI and plain HTTP never ask, and a call with an\n * API key is refused, as nobody can approve for it. The server's `confirmation` policy can\n * change both. With an enforcing auth provider the source comes from the caller's\n * credential, so this is a boundary; without one it stays a UX guard over a\n * self-declared header.\n */\n readonly confirm?: boolean | undefined;\n /**\n * Callable without signing in. Only read when the server has an enforcing auth provider,\n * which otherwise answers an anonymous caller with `unauthenticated`.\n */\n readonly public?: boolean | undefined;\n readonly run: (\n input: z.output<TInput>,\n ctx: ActionContext,\n ) => Promise<TOutput> | TOutput;\n}\n\nconst kAction: unique symbol = Symbol.for(\"fw.action\");\n\nexport interface ActionDefinition<\n TInput extends z.ZodType = z.ZodType,\n TOutput = unknown,\n> extends ActionConfig<TInput, TOutput> {\n readonly [kAction]: true;\n}\n\nexport type AnyAction = ActionDefinition<z.ZodType, unknown>;\nexport type ActionMap = Record<string, AnyAction>;\n\nexport function defineAction<TInput extends z.ZodType, TOutput>(\n config: ActionConfig<TInput, TOutput>,\n): ActionDefinition<TInput, TOutput> {\n return { ...config, [kAction]: true };\n}\n\nexport function isAction(value: unknown): value is AnyAction {\n return typeof value === \"object\" && value !== null && kAction in value;\n}\n\nexport function isMutating(action: AnyAction): boolean {\n return (action.writes?.length ?? 0) > 0;\n}\n\nconst CONFIRMED_SOURCES: ReadonlySet<ActionSource> = new Set([\"mcp\", \"agent\"]);\n\nexport function needsConfirmation(action: AnyAction, source: ActionSource): boolean {\n return action.confirm === true && CONFIRMED_SOURCES.has(source);\n}\n\nconst SOURCE_BY_KIND = {\n anonymous: \"http\",\n user: \"ui\",\n agent: \"mcp\",\n host: \"http\",\n key: \"http\",\n} as const satisfies Record<PrincipalKind, ActionSource>;\n\nexport function sourceOfPrincipal(principal: Principal): ActionSource {\n if (principal.kind === \"agent\" && principal.turn) return \"agent\";\n return SOURCE_BY_KIND[principal.kind];\n}\n\nexport function needsPrincipal(action: AnyAction, enforcing: boolean): boolean {\n return enforcing && action.public !== true;\n}\n\nexport type ActionInput<A> =\n A extends ActionDefinition<infer I, unknown> ? z.input<I> : never;\nexport type ActionOutput<A> = A extends ActionDefinition<z.ZodType, infer O> ? O : never;\n"]}
@@ -58,6 +58,11 @@ export interface TurnBinding {
58
58
  readonly turnId: TurnId;
59
59
  readonly hostId: HostId;
60
60
  readonly clientId: string;
61
+ /**
62
+ * The scope of the conversation the turn answers, the only one its agent acts in: the
63
+ * server refuses a scope resolver that answers another. Absent on a token minted before it.
64
+ */
65
+ readonly scope?: string | undefined;
61
66
  }
62
67
  /** A signed-in principal backed by a user: everything but anonymous and a key. */
63
68
  export type AuthenticatedPrincipal = UserPrincipal | AgentPrincipal | HostPrincipal;
@@ -1 +1 @@
1
- {"version":3,"file":"principal.d.ts","sourceRoot":"","sources":["../src/principal.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,MAAM,EACX,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,KAAK,MAAM,EACX,KAAK,MAAM,EACZ,MAAM,UAAU,CAAC;AAElB;;;;GAIG;AACH,MAAM,MAAM,SAAS,GACjB,kBAAkB,GAClB,aAAa,GACb,cAAc,GACd,aAAa,GACb,YAAY,CAAC;AAEjB,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAE9C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;CAC5B;AAED,6DAA6D;AAC7D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC1C;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CACzC;AAED,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,2FAA2F;IAC3F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAC7D;AAED,6FAA6F;AAC7F,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,kFAAkF;AAClF,MAAM,MAAM,sBAAsB,GAAG,aAAa,GAAG,cAAc,GAAG,aAAa,CAAC;AAEpF,eAAO,MAAM,SAAS,EAAE,kBAA0C,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,MAAgC,CAAC;AAE3D,wBAAgB,OAAO,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,IAAI,sBAAsB,CAIjF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,SAAS,GACnB,SAAS,IAAI,sBAAsB,CAErC;AAED,wBAAgB,MAAM,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAE3E"}
1
+ {"version":3,"file":"principal.d.ts","sourceRoot":"","sources":["../src/principal.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,MAAM,EACX,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,KAAK,MAAM,EACX,KAAK,MAAM,EACZ,MAAM,UAAU,CAAC;AAElB;;;;GAIG;AACH,MAAM,MAAM,SAAS,GACjB,kBAAkB,GAClB,aAAa,GACb,cAAc,GACd,aAAa,GACb,YAAY,CAAC;AAEjB,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAE9C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;CAC5B;AAED,6DAA6D;AAC7D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC1C;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CACzC;AAED,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,2FAA2F;IAC3F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAC7D;AAED,6FAA6F;AAC7F,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,kFAAkF;AAClF,MAAM,MAAM,sBAAsB,GAAG,aAAa,GAAG,cAAc,GAAG,aAAa,CAAC;AAEpF,eAAO,MAAM,SAAS,EAAE,kBAA0C,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,MAAgC,CAAC;AAE3D,wBAAgB,OAAO,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,IAAI,sBAAsB,CAIjF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,SAAS,GACnB,SAAS,IAAI,sBAAsB,CAErC;AAED,wBAAgB,MAAM,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAE3E"}
@@ -1 +1 @@
1
- {"version":3,"file":"principal.js","sourceRoot":"","sources":["../src/principal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,GAQL,MAAM,UAAU,CAAC;AA+ElB,MAAM,CAAC,MAAM,SAAS,GAAuB,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAEnE;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAW,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAE3D,MAAM,UAAU,OAAO,CAAC,SAAoB;IAC1C,OAAO,CACL,SAAS,CAAC,IAAI,KAAK,MAAM,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,CACrF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,SAAoB;IAEpB,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,SAAgC;IACrD,OAAO,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACtF,CAAC","sourcesContent":["import {\n asId,\n type DeviceId,\n type GrantId,\n type HostId,\n type KeyId,\n type ThreadId,\n type TurnId,\n type UserId,\n} from \"./ids.js\";\n\n/**\n * Who is calling, resolved once per request from its credential by the server's auth\n * provider. Never built from a header: `x-parlor-source` and `x-parlor-client` are\n * routing hints at most.\n */\nexport type Principal =\n | AnonymousPrincipal\n | UserPrincipal\n | AgentPrincipal\n | HostPrincipal\n | KeyPrincipal;\n\nexport type PrincipalKind = Principal[\"kind\"];\n\nexport interface AnonymousPrincipal {\n readonly kind: \"anonymous\";\n}\n\n/** A person in the app's own UI: a session on one device. */\nexport interface UserPrincipal {\n readonly kind: \"user\";\n readonly userId: UserId;\n readonly sessionId: string;\n readonly deviceId?: DeviceId | undefined;\n}\n\n/**\n * An agent acting for a user. `turn` is set only for an inline agent inside a chat turn;\n * an external MCP client has none.\n */\nexport interface AgentPrincipal {\n readonly kind: \"agent\";\n readonly userId: UserId;\n readonly grantId: GrantId;\n readonly agent: AgentIdentity;\n readonly turn?: TurnBinding | undefined;\n}\n\n/** A user's computer running Parlor Host, holding a grant for one app. */\nexport interface HostPrincipal {\n readonly kind: \"host\";\n readonly userId: UserId;\n readonly grantId: GrantId;\n readonly hostId: HostId;\n}\n\n/**\n * A program holding an API key the app issued, bound to one scope. No person stands behind\n * its calls: it has no user, nobody can approve for it, and it reaches no screen.\n */\nexport interface KeyPrincipal {\n readonly kind: \"key\";\n readonly keyId: KeyId;\n /** The only scope it acts in; the server refuses a scope resolver that answers another. */\n readonly scope: string;\n /** How audit records and approvals name it, such as `API key \"CI exporter\"`. */\n readonly name: string;\n /** The app's own claims, such as a role. The framework never reads them. */\n readonly claims: Readonly<Record<string, string | boolean>>;\n}\n\n/** `verified` is false when the name is the MCP client's self-declared `clientInfo.name`. */\nexport interface AgentIdentity {\n readonly name: string;\n readonly verified: boolean;\n}\n\nexport interface TurnBinding {\n readonly threadId: ThreadId;\n readonly turnId: TurnId;\n readonly hostId: HostId;\n readonly clientId: string;\n}\n\n/** A signed-in principal backed by a user: everything but anonymous and a key. */\nexport type AuthenticatedPrincipal = UserPrincipal | AgentPrincipal | HostPrincipal;\n\nexport const ANONYMOUS: AnonymousPrincipal = { kind: \"anonymous\" };\n\n/**\n * Who everyone is when no provider tells people apart: the anonymous browser and the\n * `parlor dev` host and turns. Equal to the default scope, so they share one audience.\n */\nexport const DEV_USER_ID: UserId = asId(\"user\", \"default\");\n\nexport function hasUser(principal: Principal): principal is AuthenticatedPrincipal {\n return (\n principal.kind === \"user\" || principal.kind === \"agent\" || principal.kind === \"host\"\n );\n}\n\n/**\n * @deprecated Use `hasUser`, or `principal.kind !== \"anonymous\"` to include a key. Same as\n * `hasUser`: false for a key, which is signed in but has no user.\n */\nexport function isAuthenticated(\n principal: Principal,\n): principal is AuthenticatedPrincipal {\n return hasUser(principal);\n}\n\nexport function userOf(principal: Principal | undefined): UserId | undefined {\n return principal !== undefined && hasUser(principal) ? principal.userId : undefined;\n}\n"]}
1
+ {"version":3,"file":"principal.js","sourceRoot":"","sources":["../src/principal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,GAQL,MAAM,UAAU,CAAC;AAoFlB,MAAM,CAAC,MAAM,SAAS,GAAuB,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAEnE;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAW,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAE3D,MAAM,UAAU,OAAO,CAAC,SAAoB;IAC1C,OAAO,CACL,SAAS,CAAC,IAAI,KAAK,MAAM,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,CACrF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,SAAoB;IAEpB,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,SAAgC;IACrD,OAAO,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACtF,CAAC","sourcesContent":["import {\n asId,\n type DeviceId,\n type GrantId,\n type HostId,\n type KeyId,\n type ThreadId,\n type TurnId,\n type UserId,\n} from \"./ids.js\";\n\n/**\n * Who is calling, resolved once per request from its credential by the server's auth\n * provider. Never built from a header: `x-parlor-source` and `x-parlor-client` are\n * routing hints at most.\n */\nexport type Principal =\n | AnonymousPrincipal\n | UserPrincipal\n | AgentPrincipal\n | HostPrincipal\n | KeyPrincipal;\n\nexport type PrincipalKind = Principal[\"kind\"];\n\nexport interface AnonymousPrincipal {\n readonly kind: \"anonymous\";\n}\n\n/** A person in the app's own UI: a session on one device. */\nexport interface UserPrincipal {\n readonly kind: \"user\";\n readonly userId: UserId;\n readonly sessionId: string;\n readonly deviceId?: DeviceId | undefined;\n}\n\n/**\n * An agent acting for a user. `turn` is set only for an inline agent inside a chat turn;\n * an external MCP client has none.\n */\nexport interface AgentPrincipal {\n readonly kind: \"agent\";\n readonly userId: UserId;\n readonly grantId: GrantId;\n readonly agent: AgentIdentity;\n readonly turn?: TurnBinding | undefined;\n}\n\n/** A user's computer running Parlor Host, holding a grant for one app. */\nexport interface HostPrincipal {\n readonly kind: \"host\";\n readonly userId: UserId;\n readonly grantId: GrantId;\n readonly hostId: HostId;\n}\n\n/**\n * A program holding an API key the app issued, bound to one scope. No person stands behind\n * its calls: it has no user, nobody can approve for it, and it reaches no screen.\n */\nexport interface KeyPrincipal {\n readonly kind: \"key\";\n readonly keyId: KeyId;\n /** The only scope it acts in; the server refuses a scope resolver that answers another. */\n readonly scope: string;\n /** How audit records and approvals name it, such as `API key \"CI exporter\"`. */\n readonly name: string;\n /** The app's own claims, such as a role. The framework never reads them. */\n readonly claims: Readonly<Record<string, string | boolean>>;\n}\n\n/** `verified` is false when the name is the MCP client's self-declared `clientInfo.name`. */\nexport interface AgentIdentity {\n readonly name: string;\n readonly verified: boolean;\n}\n\nexport interface TurnBinding {\n readonly threadId: ThreadId;\n readonly turnId: TurnId;\n readonly hostId: HostId;\n readonly clientId: string;\n /**\n * The scope of the conversation the turn answers, the only one its agent acts in: the\n * server refuses a scope resolver that answers another. Absent on a token minted before it.\n */\n readonly scope?: string | undefined;\n}\n\n/** A signed-in principal backed by a user: everything but anonymous and a key. */\nexport type AuthenticatedPrincipal = UserPrincipal | AgentPrincipal | HostPrincipal;\n\nexport const ANONYMOUS: AnonymousPrincipal = { kind: \"anonymous\" };\n\n/**\n * Who everyone is when no provider tells people apart: the anonymous browser and the\n * `parlor dev` host and turns. Equal to the default scope, so they share one audience.\n */\nexport const DEV_USER_ID: UserId = asId(\"user\", \"default\");\n\nexport function hasUser(principal: Principal): principal is AuthenticatedPrincipal {\n return (\n principal.kind === \"user\" || principal.kind === \"agent\" || principal.kind === \"host\"\n );\n}\n\n/**\n * @deprecated Use `hasUser`, or `principal.kind !== \"anonymous\"` to include a key. Same as\n * `hasUser`: false for a key, which is signed in but has no user.\n */\nexport function isAuthenticated(\n principal: Principal,\n): principal is AuthenticatedPrincipal {\n return hasUser(principal);\n}\n\nexport function userOf(principal: Principal | undefined): UserId | undefined {\n return principal !== undefined && hasUser(principal) ? principal.userId : undefined;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parlor/core",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "homepage": "https://cychien.github.io/parlor",
5
5
  "bugs": "https://github.com/cychien/parlor/issues",
6
6
  "license": "MIT",