@recursiv/sdk 0.7.16 → 0.7.17

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/README.md CHANGED
@@ -78,6 +78,7 @@ for await (const chunk of r.agents.chatStream(agent.id, { message: 'Hello!' }))
78
78
  | `r.brain` | `sendMessage` |
79
79
  | `r.commands` | `execute`, `gatePrompt` |
80
80
  | `r.projectBrain` | `tasks`, `decisions`, `milestones`, `completeTask`, `usage` |
81
+ | `r.metrics` | `get`, `forOrg`, `forProject`, `children`, `definitions` — the KPI ledger per tier (platform, network, org, project): numbers with definitions, status, and confidence |
81
82
 
82
83
  ### Identity & Auth
83
84
  | Resource | Key methods |
package/dist/index.d.ts CHANGED
@@ -41,6 +41,7 @@ import { DispatcherResource } from './resources/dispatcher.js';
41
41
  import { GoalsResource } from './resources/goals.js';
42
42
  import { HumanAsksResource } from './resources/human-asks.js';
43
43
  import { BriefResource } from './resources/brief.js';
44
+ import { MetricsResource } from './resources/metrics.js';
44
45
  import { HumanInputResource } from './resources/human-input.js';
45
46
  import { SwarmsResource } from './resources/swarms.js';
46
47
  import { TemplatesResource } from './resources/templates.js';
@@ -101,6 +102,7 @@ export declare class Recursiv {
101
102
  readonly goals: GoalsResource;
102
103
  readonly humanAsks: HumanAsksResource;
103
104
  readonly brief: BriefResource;
105
+ readonly metrics: MetricsResource;
104
106
  readonly humanInput: HumanInputResource;
105
107
  readonly swarms: SwarmsResource;
106
108
  readonly templates: TemplatesResource;
@@ -158,6 +160,7 @@ export { EnvVarsResource } from './resources/env-vars.js';
158
160
  export type { QueryDatabaseInput, QueryResult } from './resources/databases.js';
159
161
  export { GitHubResource } from './resources/github.js';
160
162
  export { DeploymentsResource } from './resources/deployments.js';
163
+ export type { PrepareProtocolServersInput, PreparedProtocolServers, ProtocolServerPreparation } from './resources/deployments.js';
161
164
  export { IntegrationsResource } from './resources/integrations.js';
162
165
  export type { ExecuteToolInput, ExecuteToolResult } from './resources/integrations.js';
163
166
  export { ProjectBrainResource } from './resources/project-brain.js';
@@ -186,7 +189,7 @@ export type { UploadMediaInput, UploadUrlInput, UploadUrlResult } from './resour
186
189
  export { WalletResource } from './resources/wallet.js';
187
190
  export { ProtocolsResource } from './resources/protocols.js';
188
191
  export { PROTOCOL_ADAPTER_MATURITIES, PROTOCOL_CAPABILITY_OPERATIONS, PROTOCOL_CAPABILITY_STATUSES, } from './resources/protocols.js';
189
- export type { ListProtocolCandidatesParams, ProtocolAdapterMaturity, ProtocolAdapterMetadata, ProtocolCandidateListResponse, ProtocolCandidatePageMeta, ProtocolCapabilityOperation, ProtocolCapabilityStatus, ProtocolCollectionStatus, ProtocolQuarantinedCandidate, ProtocolRefreshResult, ProtocolSettings, ProtocolSettingsUpdateResult, UpdateSettingsInput as UpdateProtocolSettingsInput, } from './resources/protocols.js';
192
+ export type { HostedProtocolConnections, ListProtocolCandidatesParams, ProtocolAdapterMaturity, ProtocolAdapterMetadata, ProtocolCandidateListResponse, ProtocolCandidatePageMeta, ProtocolCapabilityOperation, ProtocolCapabilityStatus, ProtocolCollectionStatus, ProtocolQuarantinedCandidate, ProtocolRefreshResult, ProtocolSettings, ProtocolSettingsUpdateResult, UpdateSettingsInput as UpdateProtocolSettingsInput, } from './resources/protocols.js';
190
193
  export { InboxResource } from './resources/inbox.js';
191
194
  export { NetworkResource } from './resources/network.js';
192
195
  export { SimulatorResource } from './resources/simulator.js';
@@ -198,6 +201,8 @@ export { DispatcherResource } from './resources/dispatcher.js';
198
201
  export { GoalsResource } from './resources/goals.js';
199
202
  export { HumanAsksResource } from './resources/human-asks.js';
200
203
  export { BriefResource } from './resources/brief.js';
204
+ export { MetricsResource } from './resources/metrics.js';
205
+ export type { KpiTier, KpiStatus, KpiConfidence, KpiUnit, KpiNumber, KpiSeriesPoint, KpiRead, KpiChild, KpiChildren, KpiDefinition, KpiReadParams, KpiEvidence, EvidenceReceipt, EvidenceReceiptKind, EvidenceCompute, KpiPresence } from './resources/metrics.js';
201
206
  export type { Brief, BriefEmail, MyBrief, MyBriefEntry, BriefParams, BriefShipped, BriefNext, BriefStuckItem, BriefNumbers } from './resources/brief.js';
202
207
  export type { HumanAsk, HumanAskStatus, CreateHumanAskInput, ListHumanAsksParams } from './resources/human-asks.js';
203
208
  export { HumanInputResource } from './resources/human-input.js';
@@ -213,3 +218,4 @@ export { RecursivError, AuthenticationError, AuthorizationError, NotFoundError,
213
218
  export { parseSSE } from './lib/sse.js';
214
219
  export * from './lib/webhooks.js';
215
220
  export type * from './types.js';
221
+ export type { PrepareHostedServiceInput, HostedServiceScope, HostedServiceOperation, HostedServiceReservation, HostedServiceObservation } from './resources/deployments.js';
package/dist/index.js CHANGED
@@ -42,6 +42,7 @@ import { DispatcherResource } from './resources/dispatcher.js';
42
42
  import { GoalsResource } from './resources/goals.js';
43
43
  import { HumanAsksResource } from './resources/human-asks.js';
44
44
  import { BriefResource } from './resources/brief.js';
45
+ import { MetricsResource } from './resources/metrics.js';
45
46
  import { HumanInputResource } from './resources/human-input.js';
46
47
  import { SwarmsResource } from './resources/swarms.js';
47
48
  import { TemplatesResource } from './resources/templates.js';
@@ -102,6 +103,7 @@ export class Recursiv {
102
103
  goals;
103
104
  humanAsks;
104
105
  brief;
106
+ metrics;
105
107
  humanInput;
106
108
  swarms;
107
109
  templates;
@@ -161,6 +163,7 @@ export class Recursiv {
161
163
  this.goals = new GoalsResource(client);
162
164
  this.humanAsks = new HumanAsksResource(client);
163
165
  this.brief = new BriefResource(client);
166
+ this.metrics = new MetricsResource(client);
164
167
  this.humanInput = new HumanInputResource(client);
165
168
  this.swarms = new SwarmsResource(client);
166
169
  this.templates = new TemplatesResource(client);
@@ -245,6 +248,7 @@ export { DispatcherResource } from './resources/dispatcher.js';
245
248
  export { GoalsResource } from './resources/goals.js';
246
249
  export { HumanAsksResource } from './resources/human-asks.js';
247
250
  export { BriefResource } from './resources/brief.js';
251
+ export { MetricsResource } from './resources/metrics.js';
248
252
  export { HumanInputResource } from './resources/human-input.js';
249
253
  export { SwarmsResource } from './resources/swarms.js';
250
254
  export { TemplatesResource } from './resources/templates.js';
@@ -92,16 +92,31 @@ export interface BriefStuckItem {
92
92
  }
93
93
  export interface BriefMetricNumber {
94
94
  label: string;
95
- value: number;
95
+ /** Null when the ledger could not count; `status` says so. */
96
+ value: number | null;
96
97
  unit: string;
97
98
  windowDays: number | null;
99
+ /** `ok` is a full count, `partial` a floor, `failed` no number. */
100
+ status?: 'ok' | 'partial' | 'failed';
101
+ /** ISO instant the number's windows end at. */
102
+ asOf?: string;
103
+ /** One sentence saying what the number counts. */
104
+ definition?: string;
105
+ definitionVersion?: number;
106
+ detail?: Record<string, unknown> | null;
98
107
  }
99
108
  export interface BriefNumbers {
100
109
  asOf: string;
110
+ /** The ledger day (YYYY-MM-DD) the numbers come from; null when there is none yet. */
111
+ bucket?: string | null;
112
+ /** True when the ledger missed a day: the numbers are older than yesterday. */
113
+ stale?: boolean;
114
+ /** The newest instant a recount agreed with the stored values, or null. */
115
+ verifiedAt?: string | null;
101
116
  source: 'platform' | 'postgres';
102
117
  querySetKey: string | null;
103
118
  numbers: Record<string, BriefMetricNumber>;
104
- /** The weekly numbers as of `since`, when available. */
119
+ /** The same numbers seven days before `bucket`, for every source, when the ledger has them. */
105
120
  weekBefore: Record<string, number> | null;
106
121
  }
107
122
  export type BriefBlockName = 'shipped' | 'next' | 'stuck' | 'numbers';
@@ -38,9 +38,106 @@ export interface GetLogsParams {
38
38
  export interface DeleteDeploymentParams {
39
39
  project_id: string;
40
40
  }
41
+ export interface PrepareProtocolServersInput {
42
+ project_id: string;
43
+ network_id: string;
44
+ hosts: {
45
+ pds: string;
46
+ activitypub: string;
47
+ nostr: string;
48
+ };
49
+ /** Immutable upstream image references including @sha256 digest. */
50
+ images: {
51
+ pds: string;
52
+ activitypub: string;
53
+ nostr: string;
54
+ };
55
+ test_plc_url: string;
56
+ test_publisher_pubkeys: string[];
57
+ }
58
+ export interface PreparedProtocolServers {
59
+ id: string;
60
+ provider_service_uuid: string;
61
+ state: 'prepared';
62
+ runtime_status: 'unverified';
63
+ }
64
+ export interface ProtocolServerPreparation {
65
+ /** Provider process observation only; protocol interoperability remains unverified. */
66
+ provider_status: 'running' | 'stopped' | 'transitioning' | 'unhealthy' | 'unknown';
67
+ id: string;
68
+ provider_service_uuid: string | null;
69
+ service_name: string;
70
+ request_hash: string;
71
+ state: 'provisioning' | 'prepared' | 'starting' | 'uncertain';
72
+ updated_at: string;
73
+ runtime_status: 'unverified';
74
+ }
75
+ /** Server-maintained recipes; new service integrations extend this union. */
76
+ export interface PrepareHostedServiceInput {
77
+ project_id: string;
78
+ network_id: string;
79
+ database_id: string;
80
+ recipe: 'plc-directory-v1';
81
+ hostname: string;
82
+ }
83
+ export interface HostedServiceScope {
84
+ project_id: string;
85
+ network_id: string;
86
+ }
87
+ export interface HostedServiceOperation extends HostedServiceScope {
88
+ request_hash: string;
89
+ }
90
+ export interface HostedServiceReservation {
91
+ id: string;
92
+ provider_service_uuid: string | null;
93
+ request_hash: string;
94
+ state: 'provisioning' | 'prepared' | 'starting' | 'uncertain';
95
+ /** Preparation and provider process state do not establish interoperability. */
96
+ runtime_status: 'unverified';
97
+ }
98
+ export interface HostedServiceObservation extends HostedServiceReservation {
99
+ provider_status: 'running' | 'stopped' | 'transitioning' | 'unhealthy' | 'unknown';
100
+ }
41
101
  export declare class DeploymentsResource {
42
102
  private client;
43
103
  constructor(client: HttpClient);
104
+ /** Prepare a stopped staging service from a maintained recipe. Requires an unbound owner key. */
105
+ prepareHostedService(input: PrepareHostedServiceInput): Promise<SingleResponse<HostedServiceReservation>>;
106
+ getHostedService(scope: HostedServiceScope): Promise<SingleResponse<HostedServiceObservation | null>>;
107
+ /** Recover the existing stopped service without creating another service or rotating credentials. */
108
+ reconcileHostedService(input: HostedServiceOperation): Promise<SingleResponse<HostedServiceReservation>>;
109
+ /** Queue activation once; acceptance is not live health or interoperability proof. */
110
+ startHostedService(input: HostedServiceOperation): Promise<SingleResponse<HostedServiceReservation>>;
111
+ /** Reserve and prepare stopped staging servers. Requires an unbound platform operator key. */
112
+ prepareProtocolServers(input: PrepareProtocolServersInput): Promise<SingleResponse<PreparedProtocolServers>>;
113
+ /** Read operator-only reservation metadata. This does not probe runtime health. */
114
+ getProtocolServerPreparation(scope: {
115
+ project_id: string;
116
+ network_id: string;
117
+ }): Promise<SingleResponse<ProtocolServerPreparation>>;
118
+ /** Queue a single activation after verifying the saved provider configuration and secrets.
119
+ * A 202 response is not evidence of live runtime health. */
120
+ startProtocolServers(input: {
121
+ project_id: string;
122
+ network_id: string;
123
+ request_hash: string;
124
+ }): Promise<SingleResponse<{
125
+ id: string;
126
+ provider_service_uuid: string;
127
+ state: 'starting';
128
+ runtime_status: 'unverified';
129
+ }>>;
130
+ /** Reconcile an existing stopped reservation; never creates or starts a service. */
131
+ reconcileProtocolServers(input: {
132
+ project_id: string;
133
+ network_id: string;
134
+ request_hash: string;
135
+ }): Promise<SingleResponse<{
136
+ id: string;
137
+ provider_service_uuid: string;
138
+ state: 'prepared';
139
+ runtime_status: 'unverified';
140
+ }>>;
44
141
  /** List deployments for a project */
45
142
  list(params: ListDeploymentsParams): Promise<SingleResponse<unknown[]>>;
46
143
  /** Trigger a production deployment */
@@ -3,6 +3,38 @@ export class DeploymentsResource {
3
3
  constructor(client) {
4
4
  this.client = client;
5
5
  }
6
+ /** Prepare a stopped staging service from a maintained recipe. Requires an unbound owner key. */
7
+ prepareHostedService(input) {
8
+ return this.client.post('/deployments/hosted-services/prepare', input);
9
+ }
10
+ getHostedService(scope) {
11
+ return this.client.get('/deployments/hosted-services', { ...scope });
12
+ }
13
+ /** Recover the existing stopped service without creating another service or rotating credentials. */
14
+ reconcileHostedService(input) {
15
+ return this.client.post('/deployments/hosted-services/reconcile', input);
16
+ }
17
+ /** Queue activation once; acceptance is not live health or interoperability proof. */
18
+ startHostedService(input) {
19
+ return this.client.post('/deployments/hosted-services/start', input);
20
+ }
21
+ /** Reserve and prepare stopped staging servers. Requires an unbound platform operator key. */
22
+ prepareProtocolServers(input) {
23
+ return this.client.post('/deployments/protocol-servers/prepare', input);
24
+ }
25
+ /** Read operator-only reservation metadata. This does not probe runtime health. */
26
+ getProtocolServerPreparation(scope) {
27
+ return this.client.get('/deployments/protocol-servers', { project_id: scope.project_id, network_id: scope.network_id });
28
+ }
29
+ /** Queue a single activation after verifying the saved provider configuration and secrets.
30
+ * A 202 response is not evidence of live runtime health. */
31
+ startProtocolServers(input) {
32
+ return this.client.post('/deployments/protocol-servers/start', input);
33
+ }
34
+ /** Reconcile an existing stopped reservation; never creates or starts a service. */
35
+ reconcileProtocolServers(input) {
36
+ return this.client.post('/deployments/protocol-servers/reconcile', input);
37
+ }
6
38
  /** List deployments for a project */
7
39
  list(params) {
8
40
  return this.client.get('/deployments', { ...params });
@@ -0,0 +1,169 @@
1
+ import type { HttpClient } from '../client.js';
2
+ import type { SingleResponse } from '../types.js';
3
+ /** The platform's four tiers, top down. */
4
+ export type KpiTier = 'platform' | 'network' | 'org' | 'project';
5
+ export type KpiStatus = 'ok' | 'partial' | 'failed';
6
+ /** One word for a whole read, worst case wins. */
7
+ export type KpiConfidence = 'ok' | 'partial' | 'stale' | 'unverified' | 'missing';
8
+ export type KpiUnit = 'count' | 'minor_units' | 'microcents' | 'basis_points';
9
+ export interface KpiNumber {
10
+ key: string;
11
+ label: string;
12
+ /** Null when the ledger could not count; `status` says so. */
13
+ value: number | null;
14
+ unit: KpiUnit;
15
+ windowDays: number | null;
16
+ /** One sentence saying what the number counts. */
17
+ definition: string;
18
+ definitionVersion: number;
19
+ status: KpiStatus;
20
+ asOf: string | null;
21
+ bucket: string | null;
22
+ weekBefore: number | null;
23
+ delta: number | null;
24
+ verifiedAt: string | null;
25
+ source: 'platform' | 'postgres' | 'posthog' | null;
26
+ detail: Record<string, unknown> | null;
27
+ }
28
+ export interface KpiSeriesPoint {
29
+ bucket: string;
30
+ value: number | null;
31
+ status: KpiStatus;
32
+ }
33
+ export interface KpiRead {
34
+ tier: KpiTier;
35
+ scopeId: string;
36
+ asOf: string;
37
+ bucket: string | null;
38
+ stale: boolean;
39
+ verifiedAt: string | null;
40
+ confidence: KpiConfidence;
41
+ /** The three keys this tier leads with. */
42
+ headline: string[];
43
+ metrics: Record<string, KpiNumber>;
44
+ series?: Record<string, KpiSeriesPoint[]>;
45
+ }
46
+ export interface KpiChild {
47
+ tier: KpiTier;
48
+ scopeId: string;
49
+ name: string;
50
+ slug: string | null;
51
+ headline: {
52
+ key: string;
53
+ value: number | null;
54
+ status: KpiStatus | null;
55
+ bucket: string | null;
56
+ };
57
+ }
58
+ export interface KpiChildren {
59
+ tier: KpiTier;
60
+ scopeId: string;
61
+ childTier: KpiTier | null;
62
+ children: KpiChild[];
63
+ }
64
+ export type EvidenceReceiptKind = 'pull_request' | 'deploy' | 'task' | 'invoice' | 'stuck';
65
+ export interface EvidenceReceipt {
66
+ kind: EvidenceReceiptKind;
67
+ title: string;
68
+ where: string | null;
69
+ at: string | null;
70
+ amountMinorUnits: number | null;
71
+ url: string | null;
72
+ }
73
+ export type EvidenceCompute = {
74
+ kind: 'sql';
75
+ sql: string;
76
+ params: unknown[];
77
+ } | {
78
+ kind: 'resolver';
79
+ name: string;
80
+ } | {
81
+ kind: 'external';
82
+ querySetKey: string;
83
+ sql: string | null;
84
+ };
85
+ /** The proof behind one number on one day. */
86
+ export interface KpiEvidence {
87
+ tier: KpiTier;
88
+ scopeId: string;
89
+ metric: string;
90
+ label: string;
91
+ definition: string;
92
+ definitionVersion: number;
93
+ unit: string;
94
+ windowDays: number | null;
95
+ bucket: string | null;
96
+ snapshot: {
97
+ value: number | null;
98
+ status: KpiStatus;
99
+ detail: Record<string, unknown> | null;
100
+ asOf: string;
101
+ computedAt: string;
102
+ computeMs: number | null;
103
+ verifiedAt: string | null;
104
+ source: string;
105
+ definitionVersion: number;
106
+ } | null;
107
+ compute: EvidenceCompute | null;
108
+ window: {
109
+ since: string;
110
+ until: string;
111
+ } | null;
112
+ receipts: EvidenceReceipt[];
113
+ receiptsStatus: 'ok' | 'partial' | 'sql' | 'none';
114
+ receiptsDetail: Record<string, unknown> | null;
115
+ }
116
+ /** Who is here now: a five-minute pulse, never a KPI. */
117
+ export interface KpiPresence {
118
+ tier: KpiTier;
119
+ scopeId: string;
120
+ /** Null when the presence store is not configured. */
121
+ activeNow: number | null;
122
+ /** Sixty per-minute counts, oldest first. */
123
+ minute: number[];
124
+ asOf: string;
125
+ }
126
+ export interface KpiDefinition {
127
+ tier: KpiTier;
128
+ key: string;
129
+ label: string;
130
+ unit: KpiUnit;
131
+ windowDays: number | null;
132
+ definition: string;
133
+ definitionVersion: number;
134
+ backfillable: boolean;
135
+ }
136
+ export interface KpiReadParams {
137
+ /** Subset of keys; every key of the tier when absent. */
138
+ keys?: string[];
139
+ /** ISO instant the windows end at. Default: now. */
140
+ asOf?: string;
141
+ /** Add daily series over this many days ending at asOf (1..400). */
142
+ seriesDays?: number;
143
+ }
144
+ /**
145
+ * The KPI ledger. Every number a person sees on a KPI screen, an agent
146
+ * reads here: the same rows, definitions, and confidence.
147
+ *
148
+ * Access follows the tier: platform owners, network admins, organization
149
+ * members, project admins or the owning organization.
150
+ */
151
+ export declare class MetricsResource {
152
+ private client;
153
+ constructor(client: HttpClient);
154
+ private query;
155
+ /** One tier, one scope: every number with its definition, status, week-before, and one confidence word. */
156
+ get(tier: KpiTier, scopeId: string, params?: KpiReadParams): Promise<SingleResponse<KpiRead>>;
157
+ /** One organization's numbers. */
158
+ forOrg(organizationId: string, params?: KpiReadParams): Promise<SingleResponse<KpiRead>>;
159
+ /** One project's numbers. */
160
+ forProject(projectId: string, params?: KpiReadParams): Promise<SingleResponse<KpiRead>>;
161
+ /** The tier below, one row per child with its headline number. */
162
+ children(tier: KpiTier, scopeId: string): Promise<SingleResponse<KpiChildren>>;
163
+ /** The proof behind one number on one day: audit fields, the statement, the receipts. */
164
+ evidence(tier: KpiTier, scopeId: string, metric: string, day?: string): Promise<SingleResponse<KpiEvidence>>;
165
+ /** Who is here now. A pulse from the last five minutes, not a ledger number. */
166
+ presence(tier: KpiTier, scopeId: string): Promise<SingleResponse<KpiPresence>>;
167
+ /** Every definition, the words not the numbers. */
168
+ definitions(tier?: KpiTier): Promise<SingleResponse<KpiDefinition[]>>;
169
+ }
@@ -0,0 +1,49 @@
1
+ // ── Resource ──
2
+ /**
3
+ * The KPI ledger. Every number a person sees on a KPI screen, an agent
4
+ * reads here: the same rows, definitions, and confidence.
5
+ *
6
+ * Access follows the tier: platform owners, network admins, organization
7
+ * members, project admins or the owning organization.
8
+ */
9
+ export class MetricsResource {
10
+ client;
11
+ constructor(client) {
12
+ this.client = client;
13
+ }
14
+ query(params) {
15
+ return {
16
+ ...(params.keys?.length ? { keys: params.keys.join(',') } : {}),
17
+ ...(params.asOf ? { as_of: params.asOf } : {}),
18
+ ...(params.seriesDays ? { series_days: params.seriesDays } : {}),
19
+ };
20
+ }
21
+ /** One tier, one scope: every number with its definition, status, week-before, and one confidence word. */
22
+ async get(tier, scopeId, params = {}) {
23
+ return this.client.get('/metrics', { tier, scope_id: scopeId, ...this.query(params) });
24
+ }
25
+ /** One organization's numbers. */
26
+ async forOrg(organizationId, params = {}) {
27
+ return this.client.get(`/organizations/${organizationId}/metrics`, this.query(params));
28
+ }
29
+ /** One project's numbers. */
30
+ async forProject(projectId, params = {}) {
31
+ return this.client.get(`/projects/${projectId}/metrics`, this.query(params));
32
+ }
33
+ /** The tier below, one row per child with its headline number. */
34
+ async children(tier, scopeId) {
35
+ return this.client.get('/metrics/children', { tier, scope_id: scopeId });
36
+ }
37
+ /** The proof behind one number on one day: audit fields, the statement, the receipts. */
38
+ async evidence(tier, scopeId, metric, day) {
39
+ return this.client.get('/metrics/evidence', { tier, scope_id: scopeId, metric, ...(day ? { day } : {}) });
40
+ }
41
+ /** Who is here now. A pulse from the last five minutes, not a ledger number. */
42
+ async presence(tier, scopeId) {
43
+ return this.client.get('/metrics/presence', { tier, scope_id: scopeId });
44
+ }
45
+ /** Every definition, the words not the numbers. */
46
+ async definitions(tier) {
47
+ return this.client.get('/metrics/definitions', tier ? { tier } : undefined);
48
+ }
49
+ }
@@ -121,11 +121,21 @@ export interface ProtocolSettingsUpdateResult {
121
121
  success: true;
122
122
  protocol_settings: Omit<ProtocolSettings, 'available_protocols'>;
123
123
  }
124
+ export interface HostedProtocolConnections {
125
+ state: 'not_configured' | 'provisioning' | 'prepared' | 'starting' | 'uncertain';
126
+ interoperability: 'unverified';
127
+ servers: {
128
+ protocol: 'atproto' | 'activitypub' | 'nostr';
129
+ url: string;
130
+ }[];
131
+ }
124
132
  export declare class ProtocolsResource {
125
133
  private client;
126
134
  constructor(client: HttpClient);
127
135
  /** List adapters with truthful capability, maturity, and limitation metadata. */
128
136
  list(): Promise<SingleResponse<ProtocolAdapterMetadata[]>>;
137
+ /** Configured addresses for the current app. Does not attest runtime or account readiness. */
138
+ hostedServers(): Promise<SingleResponse<HostedProtocolConnections>>;
129
139
  /** Get project-scoped unpublished candidate status (admin) */
130
140
  status(): Promise<SingleResponse<ProtocolCollectionStatus[]>>;
131
141
  /**
@@ -37,6 +37,10 @@ export class ProtocolsResource {
37
37
  list() {
38
38
  return this.client.get('/protocols');
39
39
  }
40
+ /** Configured addresses for the current app. Does not attest runtime or account readiness. */
41
+ hostedServers() {
42
+ return this.client.get('/protocols/servers');
43
+ }
40
44
  /** Get project-scoped unpublished candidate status (admin) */
41
45
  status() {
42
46
  return this.client.get('/protocols/status');
package/llm.md CHANGED
@@ -652,6 +652,27 @@ await r.dispatcher.deleteWebhook(id)
652
652
 
653
653
  ---
654
654
 
655
+ ## KPIs (the metric ledger)
656
+
657
+ Every KPI a person sees, an agent reads from the same daily snapshots. Numbers carry a one-sentence definition, a status (`ok`, `partial`, `failed`), the value seven days earlier, and one `confidence` word for the whole read. A number that could not be counted is `null`, never `0`.
658
+
659
+ ```typescript
660
+ // One tier, one scope. Access follows the tier: platform owners, network admins,
661
+ // organization members, project admins or the owning organization.
662
+ const { data } = await r.metrics.forOrg(orgId, { keys: ['activeIn28Days', 'revenueIn28Days'], seriesDays: 28 });
663
+ data.confidence; // 'ok' | 'partial' | 'stale' | 'unverified' | 'missing'
664
+ data.metrics.activeIn28Days.value; // 312
665
+ data.metrics.activeIn28Days.weekBefore; // 288
666
+ data.metrics.activeIn28Days.definition; // 'Distinct product users who opened an app ... ending at as_of.'
667
+
668
+ await r.metrics.forProject(projectId); // members, signups, active, posts, API health
669
+ await r.metrics.get('network', networkId); // admins: users, retention, MRR, waitlist
670
+ await r.metrics.children('org', orgId); // the org's projects with their headline number
671
+ await r.metrics.definitions('project'); // every key with its sentence, for a success metric
672
+ ```
673
+
674
+ A task's `success_metric` can name a ledger key: `internal.project.activeIn7Days > 100`.
675
+
655
676
  ## Golden paths
656
677
 
657
678
  ### AI-native app (database + agent + storage + auth)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@recursiv/sdk",
3
- "version": "0.7.16",
3
+ "version": "0.7.17",
4
4
  "description": "TypeScript SDK for the Recursiv API",
5
5
  "license": "FSL-1.1-ALv2",
6
6
  "type": "module",