ankka 0.9.1 → 0.11.0

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 (78) hide show
  1. package/dist/_proto/ankka/protocol/v1/agent_pb.d.ts +35 -0
  2. package/dist/_proto/ankka/protocol/v1/agent_pb.js +8 -1
  3. package/dist/_proto/ankka/protocol/v1/client_pb.d.ts +542 -2
  4. package/dist/_proto/ankka/protocol/v1/client_pb.js +107 -6
  5. package/dist/_proto/ankka/protocol/v1/consumer_pb.d.ts +52 -1
  6. package/dist/_proto/ankka/protocol/v1/consumer_pb.js +11 -1
  7. package/dist/_proto/ankka/protocol/v1/discovery_pb.d.ts +330 -0
  8. package/dist/_proto/ankka/protocol/v1/discovery_pb.js +81 -16
  9. package/dist/_proto/ankka/protocol/v1/endpoint_pb.d.ts +184 -0
  10. package/dist/_proto/ankka/protocol/v1/endpoint_pb.js +26 -1
  11. package/dist/_proto/ankka/protocol/v1/view_pb.d.ts +63 -0
  12. package/dist/_proto/ankka/protocol/v1/view_pb.js +11 -1
  13. package/dist/_proto/ankka/protocol/v1/workflow_pb.d.ts +7 -0
  14. package/dist/_proto/ankka/protocol/v1/workflow_pb.js +1 -1
  15. package/dist/agent.d.ts +15 -1
  16. package/dist/agent.js +20 -0
  17. package/dist/approvals.d.ts +47 -0
  18. package/dist/approvals.js +57 -0
  19. package/dist/autonomous.d.ts +23 -1
  20. package/dist/autonomous.js +30 -1
  21. package/dist/client.d.ts +92 -4
  22. package/dist/client.js +262 -15
  23. package/dist/consumer.d.ts +40 -2
  24. package/dist/consumer.js +50 -0
  25. package/dist/context.d.ts +4 -0
  26. package/dist/contract.d.ts +36 -0
  27. package/dist/contract.js +58 -0
  28. package/dist/effects/keyed.d.ts +33 -0
  29. package/dist/effects/keyed.js +41 -0
  30. package/dist/effects/stateless.d.ts +21 -0
  31. package/dist/effects/stateless.js +19 -0
  32. package/dist/endpoint.d.ts +10 -1
  33. package/dist/endpoint.js +20 -0
  34. package/dist/graph.d.ts +171 -0
  35. package/dist/graph.js +446 -0
  36. package/dist/handlers.d.ts +10 -2
  37. package/dist/handlers.js +6 -2
  38. package/dist/index.d.ts +15 -6
  39. package/dist/index.js +13 -4
  40. package/dist/keyedView.d.ts +56 -0
  41. package/dist/keyedView.js +67 -0
  42. package/dist/mcp.d.ts +57 -0
  43. package/dist/mcp.js +64 -0
  44. package/dist/routes.d.ts +23 -3
  45. package/dist/routes.js +16 -3
  46. package/dist/server/agent.js +12 -4
  47. package/dist/server/discovery.d.ts +12 -1
  48. package/dist/server/discovery.js +95 -1
  49. package/dist/server/http.d.ts +2 -1
  50. package/dist/server/http.js +78 -4
  51. package/dist/server/stateless.js +104 -16
  52. package/dist/server/workflow.js +5 -1
  53. package/dist/service.d.ts +45 -3
  54. package/dist/service.js +234 -12
  55. package/dist/services.d.ts +137 -0
  56. package/dist/services.js +259 -0
  57. package/dist/socket.d.ts +15 -0
  58. package/dist/socket.js +25 -0
  59. package/dist/spec.d.ts +1 -1
  60. package/dist/spec.js +87 -14
  61. package/dist/startFrom.d.ts +32 -0
  62. package/dist/startFrom.js +44 -0
  63. package/dist/testkit/index.d.ts +2 -2
  64. package/dist/testkit/index.js +1 -1
  65. package/dist/testkit/integration.js +5 -0
  66. package/dist/testkit/kinds.d.ts +75 -5
  67. package/dist/testkit/kinds.js +264 -34
  68. package/dist/testkit/unit.d.ts +14 -1
  69. package/dist/testkit/unit.js +40 -3
  70. package/dist/timedAction.d.ts +17 -2
  71. package/dist/timedAction.js +33 -1
  72. package/dist/version.d.ts +1 -1
  73. package/dist/version.js +1 -1
  74. package/dist/view.d.ts +32 -0
  75. package/dist/view.js +8 -0
  76. package/dist/workflow.d.ts +18 -1
  77. package/dist/workflow.js +39 -0
  78. package/package.json +3 -2
package/dist/agent.js CHANGED
@@ -5,7 +5,9 @@
5
5
  // static readonly tools = { lookup: tool("lookup", "Looks up a cart by id.", CartLookup, (a: Assistant, input) => a.lookup(input.cartId)) }
6
6
  // static readonly guardrails = { noSecrets: guardrail("no-secrets", (stage, text) => text.includes("sk-") ? "a key leaked" : null) }
7
7
  // static readonly handlers = { ask: command("ask", s.string, s.string, (a: Assistant, q) => a.ask(q)), chat: stream("chat", s.string, (a: Assistant, q) => a.ask(q)) }
8
+ import { secretsFor } from "./client.js";
8
9
  import { AgentEffects } from "./effects/agent.js";
10
+ import { servicesFor } from "./services.js";
9
11
  export class Agent {
10
12
  effects = new AgentEffects();
11
13
  #sessionId = "";
@@ -23,6 +25,24 @@ export class Agent {
23
25
  throw new Error("client is only available inside a handler, a tool or a guardrail");
24
26
  return this.#client;
25
27
  }
28
+ #secrets;
29
+ /** The service's secret store: values kept encrypted in the service's own database, never in a journal or a view. */
30
+ get secrets() {
31
+ return this.#secrets ?? secretsFor(this.client);
32
+ }
33
+ /** A unit test's store in place of the runtime's: `component.secrets = new InMemorySecrets()`. */
34
+ set secrets(store) {
35
+ this.#secrets = store;
36
+ }
37
+ #services;
38
+ /** Other services, called as this one, through the runtime: `this.services.service("orders")`. */
39
+ get services() {
40
+ return this.#services ?? servicesFor(this.client);
41
+ }
42
+ /** A unit test's in place of the runtime's: `component.services = new ScriptedServices()`. */
43
+ set services(services) {
44
+ this.#services = services;
45
+ }
26
46
  /** @internal */
27
47
  get _kind() {
28
48
  return "agent";
@@ -0,0 +1,47 @@
1
+ import type { ApprovalAwaited as ApprovalAwaitedProto, ApprovalRequest as ApprovalRequestProto } from "./_proto/ankka/protocol/v1/client_pb.ts";
2
+ /** The protocol version that carries approvals: a runtime before it cannot record a decision. */
3
+ export declare const APPROVALS_SINCE = "1.11";
4
+ /** That a tool, or every tool of an MCP server, waits for a person; with `withinMs`, the platform refuses it when that much time passes undecided. */
5
+ export type Approval = true | {
6
+ readonly withinMs: number;
7
+ };
8
+ /** A problem with an approval as declared, or undefined. */
9
+ export declare function approvalProblem(approval: Approval | undefined): string | undefined;
10
+ /** The discovery form: absent for none, empty for no time limit. */
11
+ export declare function approvalToProto(approval: Approval | undefined): {
12
+ withinMillis?: bigint;
13
+ } | undefined;
14
+ /** What an agent records when the model calls a tool that requires approval: the id a decision names, the tool and the model's arguments. */
15
+ export interface ApprovalRequest {
16
+ readonly id: string;
17
+ readonly tool: string;
18
+ readonly arguments: unknown;
19
+ readonly requestedAt: number;
20
+ readonly expiresAt?: number;
21
+ }
22
+ export declare function requestFromProto(pb: ApprovalRequestProto): ApprovalRequest;
23
+ /** A request as an autonomous agent's record holds it. */
24
+ export declare function requestFromJson(body: Record<string, any>): ApprovalRequest;
25
+ /** What a turn that may wait came to: the model's answer, or the requests it waits on. */
26
+ export type AgentOutcome<R> = {
27
+ readonly kind: "answered";
28
+ readonly value: R;
29
+ } | {
30
+ readonly kind: "awaiting-approval";
31
+ readonly requests: readonly ApprovalRequest[];
32
+ };
33
+ export declare function awaitingOf(pb: ApprovalAwaitedProto): AgentOutcome<never>;
34
+ /**
35
+ * Thrown by the calls that answer only with a value — `invoke` and `stream` — when the turn waits. Use
36
+ * `ask`, `streamParts` or `decide` to be answered with the requests instead.
37
+ */
38
+ export declare class ApprovalAwaited extends Error {
39
+ readonly requests: readonly ApprovalRequest[];
40
+ constructor(requests: readonly ApprovalRequest[]);
41
+ }
42
+ /** A person's decision: `by` names who decided and is required; a refusal may carry a note the model is told. */
43
+ export interface DecisionInput {
44
+ readonly approved: boolean;
45
+ readonly by: string;
46
+ readonly note?: string;
47
+ }
@@ -0,0 +1,57 @@
1
+ // Approvals: a tool that waits for a person's decision before it runs.
2
+ //
3
+ // A tool declared with `approval` is never run when the model calls it. The sidecar records an approval
4
+ // request and answers the caller with it instead of an answer; the turn goes on when a person decides,
5
+ // through `decide`. Approved, the tool runs once and the model is told its result; refused, the model is
6
+ // told who refused it and why, and the tool never runs. Who decided is required and recorded; who *may*
7
+ // decide is the ACL of whatever route sends the decision.
8
+ /** The protocol version that carries approvals: a runtime before it cannot record a decision. */
9
+ export const APPROVALS_SINCE = "1.11";
10
+ /** A problem with an approval as declared, or undefined. */
11
+ export function approvalProblem(approval) {
12
+ if (approval === undefined || approval === true)
13
+ return undefined;
14
+ if (!Number.isFinite(approval.withinMs) || approval.withinMs <= 0)
15
+ return `a time limit for approval must be positive, not ${approval.withinMs}ms`;
16
+ return undefined;
17
+ }
18
+ /** The discovery form: absent for none, empty for no time limit. */
19
+ export function approvalToProto(approval) {
20
+ if (approval === undefined)
21
+ return undefined;
22
+ return approval === true ? {} : { withinMillis: BigInt(Math.trunc(approval.withinMs)) };
23
+ }
24
+ export function requestFromProto(pb) {
25
+ return Object.freeze({
26
+ id: pb.id,
27
+ tool: pb.tool,
28
+ arguments: pb.argumentsJson ? JSON.parse(pb.argumentsJson) : {},
29
+ requestedAt: Number(pb.requestedAtMillis),
30
+ ...(pb.expiresAtMillis !== undefined ? { expiresAt: Number(pb.expiresAtMillis) } : {}),
31
+ });
32
+ }
33
+ /** A request as an autonomous agent's record holds it. */
34
+ export function requestFromJson(body) {
35
+ return Object.freeze({
36
+ id: String(body.id),
37
+ tool: String(body.tool),
38
+ arguments: body.arguments ?? {},
39
+ requestedAt: Number(body.requestedAt ?? 0),
40
+ ...(body.expiresAt !== undefined ? { expiresAt: Number(body.expiresAt) } : {}),
41
+ });
42
+ }
43
+ export function awaitingOf(pb) {
44
+ return Object.freeze({ kind: "awaiting-approval", requests: pb.requests.map(requestFromProto) });
45
+ }
46
+ /**
47
+ * Thrown by the calls that answer only with a value — `invoke` and `stream` — when the turn waits. Use
48
+ * `ask`, `streamParts` or `decide` to be answered with the requests instead.
49
+ */
50
+ export class ApprovalAwaited extends Error {
51
+ requests;
52
+ constructor(requests) {
53
+ super(`approval awaited for ${requests.map((r) => `'${r.tool}' (${r.id})`).join(", ")}`);
54
+ this.name = "ApprovalAwaited";
55
+ this.requests = requests;
56
+ }
57
+ }
@@ -1,6 +1,9 @@
1
- import type { ComponentClient } from "./client.ts";
1
+ import { type ApprovalRequest, type DecisionInput } from "./approvals.ts";
2
+ import type { McpServerRef, ResultGuardrailRef } from "./mcp.ts";
3
+ import { type ComponentClient, type Secrets } from "./client.ts";
2
4
  import type { GuardrailRef, ToolRef } from "./handlers.ts";
3
5
  import type { Schema } from "./schema.ts";
6
+ import { type Services } from "./services.ts";
4
7
  type MaybePromise<T> = T | Promise<T>;
5
8
  export declare const COMPLETE_TASK = "complete_task";
6
9
  export declare const FAIL_TASK = "fail_task";
@@ -51,6 +54,14 @@ export declare abstract class AutonomousAgent {
51
54
  /** The task a tool, a guardrail or a rule is running for. */
52
55
  get taskId(): string;
53
56
  get client(): ComponentClient;
57
+ /** The service's secret store: values kept encrypted in the service's own database, never in a journal or a view. */
58
+ get secrets(): Secrets;
59
+ /** A unit test's store in place of the runtime's: `component.secrets = new InMemorySecrets()`. */
60
+ set secrets(store: Secrets);
61
+ /** Other services, called as this one, through the runtime: `this.services.service("orders")`. */
62
+ get services(): Services;
63
+ /** A unit test's in place of the runtime's: `component.services = new ScriptedServices()`. */
64
+ set services(services: Services);
54
65
  /** @internal */
55
66
  get _kind(): "autonomous-agent";
56
67
  /** @internal */
@@ -67,6 +78,10 @@ export interface AutonomousAgentClass<C extends AutonomousAgent = AutonomousAgen
67
78
  readonly guardrails?: Readonly<Record<string, GuardrailRef>>;
68
79
  readonly accepts: readonly TaskAcceptance[];
69
80
  readonly settings?: AutonomousSettings;
81
+ /** MCP servers whose tools are offered beside the agent's own, as `mcp__<server>__<tool>`. */
82
+ readonly mcpServers?: Readonly<Record<string, McpServerRef>>;
83
+ /** Checks on what an MCP server's tool answered, before the model is told it. */
84
+ readonly resultGuardrails?: Readonly<Record<string, ResultGuardrailRef>>;
70
85
  }
71
86
  /** The discovery form of a result schema. */
72
87
  export declare function resultSchemaJson(type: TaskType<any>): string | undefined;
@@ -94,6 +109,8 @@ export interface AgentState {
94
109
  readonly currentTask: string | undefined;
95
110
  readonly iteration: number;
96
111
  readonly queued: readonly string[];
112
+ /** The approval requests the current task's tool calls await; while any does, the instance calls no model. */
113
+ readonly awaiting: readonly ApprovalRequest[];
97
114
  }
98
115
  /** One thing an instance did: `type` names it, and the rest of its fields are as sent. */
99
116
  export interface Notification {
@@ -148,6 +165,11 @@ export declare class AutonomousAgentCalls {
148
165
  /** Stops the instance for good; its tasks go back to pending for another to take. */
149
166
  terminate(): Promise<void>;
150
167
  state(): Promise<AgentState>;
168
+ /**
169
+ * Decides one of the instance's approval requests. `by` names who decided and is required. Approved, the
170
+ * tool runs and the task goes on; refused, the model is told so. A request already decided is a conflict.
171
+ */
172
+ decide(approvalId: string, decision: DecisionInput): Promise<void>;
151
173
  /** What the instance does from now on, as it happens. Nothing is replayed. */
152
174
  notifications(): AsyncIterable<Notification>;
153
175
  }
@@ -14,8 +14,11 @@
14
14
  //
15
15
  // A tool may run more than once for one request of the model — after a crash, the last recorded
16
16
  // request's tools run again — so a tool with a side effect should tolerate a repeat.
17
+ import { requestFromJson } from "./approvals.js";
18
+ import { secretsFor } from "./client.js";
17
19
  import { decodeJsonValue, reviver } from "./json.js";
18
20
  import { toJsonSchema } from "./schema.js";
21
+ import { servicesFor } from "./services.js";
19
22
  export const COMPLETE_TASK = "complete_task";
20
23
  export const FAIL_TASK = "fail_task";
21
24
  export const accepted = () => Object.freeze({ verdict: "accepted" });
@@ -56,6 +59,24 @@ export class AutonomousAgent {
56
59
  throw new Error("client is only available inside a tool, a guardrail or a rule");
57
60
  return this.#client;
58
61
  }
62
+ #secrets;
63
+ /** The service's secret store: values kept encrypted in the service's own database, never in a journal or a view. */
64
+ get secrets() {
65
+ return this.#secrets ?? secretsFor(this.client);
66
+ }
67
+ /** A unit test's store in place of the runtime's: `component.secrets = new InMemorySecrets()`. */
68
+ set secrets(store) {
69
+ this.#secrets = store;
70
+ }
71
+ #services;
72
+ /** Other services, called as this one, through the runtime: `this.services.service("orders")`. */
73
+ get services() {
74
+ return this.#services ?? servicesFor(this.client);
75
+ }
76
+ /** A unit test's in place of the runtime's: `component.services = new ScriptedServices()`. */
77
+ set services(services) {
78
+ this.#services = services;
79
+ }
59
80
  /** @internal */
60
81
  get _kind() {
61
82
  return "autonomous-agent";
@@ -188,7 +209,15 @@ export class AutonomousAgentCalls {
188
209
  const r = (await this.#client._raw("event-sourced", INSTANCE, `${this.componentId}/${this.#instance()}`, "get"));
189
210
  const current = r.current;
190
211
  const phase = r.terminated ? "terminated" : r.suspended ? "suspended" : current ? "working" : (r.queue ?? []).length > 0 ? "waiting" : "idle";
191
- return Object.freeze({ phase, currentTask: current?.taskId, iteration: current?.iteration ?? 0, queued: [...(r.queue ?? [])] });
212
+ const awaiting = (current?.approvals ?? []).filter((a) => a.decision === undefined || a.decision === null).map(requestFromJson);
213
+ return Object.freeze({ phase, currentTask: current?.taskId, iteration: current?.iteration ?? 0, queued: [...(r.queue ?? [])], awaiting });
214
+ }
215
+ /**
216
+ * Decides one of the instance's approval requests. `by` names who decided and is required. Approved, the
217
+ * tool runs and the task goes on; refused, the model is told so. A request already decided is a conflict.
218
+ */
219
+ async decide(approvalId, decision) {
220
+ await this.#client._decide("autonomous-agent", this.componentId, this.#instance(), "", approvalId, decision);
192
221
  }
193
222
  /** What the instance does from now on, as it happens. Nothing is replayed. */
194
223
  async *notifications() {
package/dist/client.d.ts CHANGED
@@ -4,8 +4,9 @@ import { jsonCodec, type Shape } from "./codec.ts";
4
4
  import { type Metadata } from "./effects/common.ts";
5
5
  import type { HandlerRef } from "./handlers.ts";
6
6
  import { type ComponentKind } from "./kinds.ts";
7
- import type { Duration } from "./time.ts";
7
+ import { Duration } from "./time.ts";
8
8
  import { AutonomousAgentCalls, TaskCalls, Tasks } from "./autonomous.ts";
9
+ import { type AgentOutcome, type DecisionInput } from "./approvals.ts";
9
10
  /** A component class as the typed client sees it: an id and, on its prototype, its kind. */
10
11
  export interface ComponentRef {
11
12
  readonly componentId: string;
@@ -22,10 +23,25 @@ interface Connection {
22
23
  export declare class Invocation<I, R> {
23
24
  #private;
24
25
  constructor(connection: Connection, metadata: Metadata, kind: ComponentKind, componentId: string, entityId: string, name: string, input: Shape<I> | undefined, reply: Shape<R> | undefined);
25
- /** Invokes and decodes the reply; a refusal rejects with `CommandError`. */
26
+ /**
27
+ * Invokes and decodes the reply; a refusal rejects with `CommandError`. An agent's turn that waits for a
28
+ * person rejects with `ApprovalAwaited`; `ask` answers it instead.
29
+ */
26
30
  invoke(input?: I): Promise<R>;
27
- /** Invokes a streaming handler; yields tokens in order; a failure rejects with `CommandError`. */
31
+ /** Calls an agent's handler for its outcome: the model's answer, or the approval requests the turn waits on. */
32
+ ask(input?: I): Promise<AgentOutcome<R>>;
33
+ /**
34
+ * Decides one of the session's approval requests; this invocation names the handler whose turn waits.
35
+ * `by` names who decided and is required. When it was the turn's last awaited decision the turn goes on,
36
+ * and this answers as `ask` would have. A request already decided is a conflict.
37
+ */
38
+ decide(approvalId: string, decision: DecisionInput): Promise<AgentOutcome<R>>;
39
+ /** Invokes a streaming handler; yields tokens in order; a failure rejects with `CommandError`, a turn that waits with `ApprovalAwaited`. */
28
40
  stream(input?: I): AsyncIterable<string>;
41
+ /** As `stream`, ending with one awaiting part when the turn waits for a person. */
42
+ streamParts(input?: I): AsyncIterable<string | Extract<AgentOutcome<never>, {
43
+ kind: "awaiting-approval";
44
+ }>>;
29
45
  }
30
46
  /** Calls on one component instance, by wire name. */
31
47
  export declare class Calls {
@@ -44,10 +60,15 @@ export declare class TypedCalls<C> {
44
60
  /** View queries: rows come back as a JSON array decoded with the row shape. */
45
61
  export declare class Views {
46
62
  #private;
47
- constructor(connection: Connection);
63
+ constructor(connection: Connection, metadata?: Metadata);
48
64
  get<Row>(viewId: string, key: string, row: Shape<Row>): Promise<Row | null>;
49
65
  all<Row>(viewId: string, row: Shape<Row>): Promise<Row[]>;
50
66
  query<Row>(viewId: string, name: string, key: string | null, row: Shape<Row>): Promise<Row[]>;
67
+ /**
68
+ * The rows of one of a view's declared queries, asked by name with the values it takes. At most
69
+ * `limit` rows, 1000 when it is not given, in the statement's own order.
70
+ */
71
+ ask<Row>(viewId: string, name: string, values: Readonly<Record<string, string>>, row: Shape<Row>, limit?: number): Promise<Row[]>;
51
72
  }
52
73
  /** What a timer fires: a component class and one of its handlers, or the same by name. */
53
74
  export type TimerTarget = {
@@ -61,13 +82,78 @@ export type TimerTarget = {
61
82
  readonly input?: Shape<any>;
62
83
  readonly entityId?: string;
63
84
  };
85
+ /** What a recurring timer fires: a timed action's class and one of its handlers, or the same by name. */
86
+ export type TimedActionTarget = {
87
+ readonly component: ComponentRef;
88
+ readonly handler: HandlerRef<any, any, any, any>;
89
+ } | {
90
+ readonly componentId: string;
91
+ readonly name: string;
92
+ readonly input?: Shape<any>;
93
+ };
64
94
  export declare class Timers {
65
95
  #private;
66
96
  constructor(connection: Connection);
67
97
  /** Schedules `target` after `delay`. Scheduling twice under one id replaces the earlier schedule. */
68
98
  schedule(timerId: string, delay: Duration, target: TimerTarget, input?: unknown): Promise<void>;
99
+ /**
100
+ * Schedules `target`, a timed action's handler, first after `delay` (zero or less is due at once) and
101
+ * then every `period` until it is cancelled or replaced. Setting it again with the same handler and
102
+ * period keeps its next due time, so a service may set its recurring timers every time it starts.
103
+ * A period outside 1 millisecond to 36,500 days is refused with `BAD_REQUEST` before anything is sent.
104
+ */
105
+ scheduleRecurring(timerId: string, delay: Duration, period: Duration, target: TimedActionTarget, input?: unknown): Promise<void>;
106
+ /** Cancels the timer under `timerId`, whether it fires once or recurs. */
69
107
  cancel(timerId: string): Promise<void>;
70
108
  }
109
+ export declare const MAX_SECRET_NAME_LENGTH = 253;
110
+ export declare const MAX_SECRET_VALUE_BYTES = 65536;
111
+ /** What is wrong with a secret's name, if anything: the runtime's own rule. */
112
+ export declare function secretNameProblem(name: string): string | undefined;
113
+ /** What is wrong with a secret's value, if anything. Never quotes the value. */
114
+ export declare function secretValueProblem(value: string): string | undefined;
115
+ /**
116
+ * The service's secret store: named text values the runtime keeps in the service's own database,
117
+ * encrypted with a key this process never sees. Offered to endpoints, workflow steps, consumers,
118
+ * timed actions and agents; an entity and a view have no `secrets` at all.
119
+ *
120
+ * Every refusal is a `CommandError` with the runtime's code: `BAD_REQUEST` for a name or a value that
121
+ * breaks its rule, `INTERNAL` when the service has no secret key or a value was kept with another
122
+ * one, `UNAVAILABLE` when the database cannot be reached.
123
+ */
124
+ export declare class Secrets {
125
+ #private;
126
+ /** The store reached through `client`'s sidecar; with none, every call throws. */
127
+ constructor(client?: ComponentClient);
128
+ /** Keeps `value` under `name`, replacing what was there. */
129
+ put(name: string, value: string): Promise<void>;
130
+ /** The value kept under `name`, or `undefined` when there is none. Never an empty string. */
131
+ get(name: string): Promise<string | undefined>;
132
+ /** Removes what is kept under `name`. Removing nothing is not an error. */
133
+ delete(name: string): Promise<void>;
134
+ }
135
+ /** A secret store for unit tests: a map, applying the runtime's rules with its words. */
136
+ export declare class InMemorySecrets extends Secrets {
137
+ readonly values: Map<string, string>;
138
+ put(name: string, value: string): Promise<void>;
139
+ get(name: string): Promise<string | undefined>;
140
+ delete(name: string): Promise<void>;
141
+ }
142
+ /** A store for unit tests whose every call throws: the unit kit's default, beside `noClient()`. */
143
+ export declare function noSecrets(): Secrets;
144
+ /**
145
+ * @internal What a call to another service is sent through: `client`'s sidecar, and the metadata of
146
+ * the handler `client` was scoped to. Not a member of the client, which an entity holds too.
147
+ */
148
+ export declare function channelOf(client: ComponentClient): {
149
+ stub(): ConnectClient<typeof Client>;
150
+ metadata: Metadata;
151
+ } | undefined;
152
+ /**
153
+ * @internal The secret store reached through `client`'s sidecar. Not a member of the client, which
154
+ * an entity holds too: only the component kinds that may have a store call this.
155
+ */
156
+ export declare function secretsFor(client: ComponentClient): Secrets;
71
157
  export declare class ComponentClient {
72
158
  #private;
73
159
  readonly views: Views;
@@ -93,6 +179,8 @@ export declare class ComponentClient {
93
179
  } | string, instanceId?: string): AutonomousAgentCalls;
94
180
  /** @internal A call with a JSON body and a JSON reply, as the platform's own components take them. */
95
181
  _raw(kind: ComponentKind, componentId: string, entityId: string, name: string, body?: unknown): Promise<unknown>;
182
+ /** @internal A decision on an approval request; a refusal rejects with `CommandError`. */
183
+ _decide(kind: ComponentKind, componentId: string, entityId: string, name: string, approvalId: string, decision: DecisionInput): Promise<void>;
96
184
  /** @internal A streaming call whose tokens are text. */
97
185
  _rawStream(kind: ComponentKind, componentId: string, entityId: string, name: string): AsyncIterable<string>;
98
186
  /** Typed calls through a component class's handler table: `client.of(ShoppingCartEntity, cartId).call(ShoppingCartEntity.handlers.addItem).invoke(item)`. */