@agentforge-io/sdk-server 4.6.0 → 4.7.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.
- package/dist/client.d.ts +2 -0
- package/dist/client.js +2 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +3 -1
- package/dist/resources/analytics.d.ts +21 -54
- package/dist/resources/analytics.js +31 -39
- package/dist/resources/apps.d.ts +17 -1
- package/dist/resources/apps.js +18 -0
- package/dist/resources/inbox.d.ts +65 -107
- package/dist/resources/inbox.js +67 -105
- package/dist/resources/provisioning.d.ts +31 -0
- package/dist/resources/provisioning.js +25 -0
- package/dist/resources/teams.d.ts +12 -0
- package/dist/resources/teams.js +40 -0
- package/dist/types.d.ts +162 -0
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { ConnectorsResource } from './resources/connectors';
|
|
|
6
6
|
import { InboxResource } from './resources/inbox';
|
|
7
7
|
import { ProvisioningResource } from './resources/provisioning';
|
|
8
8
|
import { SecretsResource } from './resources/secrets';
|
|
9
|
+
import { TeamsResource } from './resources/teams';
|
|
9
10
|
import { ToolsResource } from './resources/tools';
|
|
10
11
|
export interface AgentForgeClientOptions {
|
|
11
12
|
/** Platform base URL — e.g. http://localhost:3032 in dev. */
|
|
@@ -68,6 +69,7 @@ export declare class AgentForgeClient {
|
|
|
68
69
|
readonly provisioning: ProvisioningResource;
|
|
69
70
|
readonly secrets: SecretsResource;
|
|
70
71
|
readonly tools: ToolsResource;
|
|
72
|
+
readonly teams: TeamsResource;
|
|
71
73
|
constructor(opts: AgentForgeClientOptions);
|
|
72
74
|
authHeaders(): Record<string, string>;
|
|
73
75
|
getAppSecret(): string | undefined;
|
package/dist/client.js
CHANGED
|
@@ -28,6 +28,7 @@ const connectors_1 = require("./resources/connectors");
|
|
|
28
28
|
const inbox_1 = require("./resources/inbox");
|
|
29
29
|
const provisioning_1 = require("./resources/provisioning");
|
|
30
30
|
const secrets_1 = require("./resources/secrets");
|
|
31
|
+
const teams_1 = require("./resources/teams");
|
|
31
32
|
const tools_1 = require("./resources/tools");
|
|
32
33
|
class AgentForgeClient {
|
|
33
34
|
constructor(opts) {
|
|
@@ -57,6 +58,7 @@ class AgentForgeClient {
|
|
|
57
58
|
this.provisioning = new provisioning_1.ProvisioningResource(this);
|
|
58
59
|
this.secrets = new secrets_1.SecretsResource(this);
|
|
59
60
|
this.tools = new tools_1.ToolsResource(this);
|
|
61
|
+
this.teams = new teams_1.TeamsResource(this);
|
|
60
62
|
}
|
|
61
63
|
// Auth headers derivados del modo. ChatToken gana si ambos están presentes;
|
|
62
64
|
// luego apiKey (ak_live_); luego appSecret (sk_live_) — ambos secrets viajan
|
package/dist/index.d.ts
CHANGED
|
@@ -2,19 +2,20 @@ export { AgentForgeClient } from './client';
|
|
|
2
2
|
export type { AgentForgeClientOptions, RequestOptions } from './client';
|
|
3
3
|
export { AgentForgeError, AgentForgeAuthError, AgentForgeNotFoundError, AgentForgeNetworkError, } from './errors';
|
|
4
4
|
export { TOOL_CALLBACK_HEADERS, ToolCallbackSignatureError, signToolCallbackPayload, verifyToolCallbackSignature, } from './webhooks';
|
|
5
|
-
export type { AgentMe, AgentSummary, AppUserConnectorStatus, ApprovalCopyBundle, ChannelContext, ChatStreamChunk, ChatStreamEvent, ChatTokenRecord, ConnectorDefaultsResult, ConnectorDefaultsSource, ConnectorResourceItem, ConnectorStatus, ConnectorToolInfo, ConversationHistory, ConversationStatus, CreateAgentInput, CreateClickupTaskInput, CreateClickupTaskResult, ExternalToolSummary, IssueChatTokenInput, ListAgentsResult, ListConnectorResourcesResult, McpServerConfig, MessageRecord, MessageRole, PublicAppBranding, AppSelf, AppSelfConnector, AppSelfConnectors, RegisterToolInput, RegisterToolsInput, RegisterToolsResult, ToolCallbackPayload, ToolCallRecord, ToolPermission, ToolPermissionMode, TokenUsage, TenantSecretEntry, UpdateAgentInput, } from './types';
|
|
5
|
+
export type { AgentMe, AgentSummary, AppUserConnectorStatus, ApprovalCopyBundle, ChannelContext, ChatStreamChunk, ChatStreamEvent, ChatTokenRecord, ConnectorDefaultsResult, ConnectorDefaultsSource, ConnectorResourceItem, ConnectorStatus, ConnectorToolInfo, ConversationHistory, ConversationStatus, CreateAgentInput, CreateClickupTaskInput, CreateClickupTaskResult, ExternalToolSummary, IssueChatTokenInput, ListAgentsResult, ListConnectorResourcesResult, McpServerConfig, MessageRecord, MessageRole, PublicAppBranding, PublicProfileBlock, PublicProfileTemplate, PublicTeamLanding, CreateTeamInput, TeamSummary, AppSelf, AppSelfConnector, AppSelfConnectors, AppSelfConnectorTools, AppSelfConnectorToolsResponse, RegisterToolInput, RegisterToolsInput, RegisterToolsResult, ToolCallbackPayload, ToolCallRecord, ToolPermission, ToolPermissionMode, TokenUsage, TenantSecretEntry, UpdateAgentInput, InboxThreadMode, InboxMessageDirection, InboxMessageSource, InboxMessageType, InboxThreadCustomerProfileView, InboxThreadView, InboxMessageView, SupportKpiTotals, SupportKpiResponse, AgentAttentionLogRow, } from './types';
|
|
6
6
|
export { AgentsResource } from './resources/agents';
|
|
7
7
|
export { AnalyticsResource } from './resources/analytics';
|
|
8
|
-
export type {
|
|
8
|
+
export type { GetSupportKpisInput, GetAgentAttentionLogInput, } from './resources/analytics';
|
|
9
9
|
export { AppsResource } from './resources/apps';
|
|
10
10
|
export { ChatResource } from './resources/chat';
|
|
11
11
|
export type { AnthropicClientOptions, StreamMessageInput } from './resources/chat';
|
|
12
12
|
export { ConnectorsResource } from './resources/connectors';
|
|
13
13
|
export type { InboxChannelView } from './resources/connectors';
|
|
14
14
|
export { InboxResource } from './resources/inbox';
|
|
15
|
-
export type {
|
|
15
|
+
export type { ListThreadsOptions, SendMessageInput, AssignThreadInput, UnassignThreadInput, SetThreadModeInput, CloseThreadInput, } from './resources/inbox';
|
|
16
16
|
export { ProvisioningResource } from './resources/provisioning';
|
|
17
|
-
export type { ProvisionedTenant, ProvisionedApp, } from './resources/provisioning';
|
|
17
|
+
export type { ProvisionedTenant, ProvisionedApp, ProvisionedTeam, } from './resources/provisioning';
|
|
18
18
|
export { SecretsResource } from './resources/secrets';
|
|
19
|
+
export { TeamsResource } from './resources/teams';
|
|
19
20
|
export { ToolsResource } from './resources/tools';
|
|
20
21
|
export type { RespondToCallbackInput, VerifyCallbackInput } from './resources/tools';
|
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
// const payload = af.tools.verifyCallback({ rawBody, signatureHeader, secretPlaintext });
|
|
29
29
|
// await af.tools.respondToCallback({ resultUrl: payload.resultUrl, tenantId: payload.tenantId, secret, result });
|
|
30
30
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
-
exports.ToolsResource = exports.SecretsResource = exports.ProvisioningResource = exports.InboxResource = exports.ConnectorsResource = exports.ChatResource = exports.AppsResource = exports.AnalyticsResource = exports.AgentsResource = exports.verifyToolCallbackSignature = exports.signToolCallbackPayload = exports.ToolCallbackSignatureError = exports.TOOL_CALLBACK_HEADERS = exports.AgentForgeNetworkError = exports.AgentForgeNotFoundError = exports.AgentForgeAuthError = exports.AgentForgeError = exports.AgentForgeClient = void 0;
|
|
31
|
+
exports.ToolsResource = exports.TeamsResource = exports.SecretsResource = exports.ProvisioningResource = exports.InboxResource = exports.ConnectorsResource = exports.ChatResource = exports.AppsResource = exports.AnalyticsResource = exports.AgentsResource = exports.verifyToolCallbackSignature = exports.signToolCallbackPayload = exports.ToolCallbackSignatureError = exports.TOOL_CALLBACK_HEADERS = exports.AgentForgeNetworkError = exports.AgentForgeNotFoundError = exports.AgentForgeAuthError = exports.AgentForgeError = exports.AgentForgeClient = void 0;
|
|
32
32
|
var client_1 = require("./client");
|
|
33
33
|
Object.defineProperty(exports, "AgentForgeClient", { enumerable: true, get: function () { return client_1.AgentForgeClient; } });
|
|
34
34
|
var errors_1 = require("./errors");
|
|
@@ -57,5 +57,7 @@ var provisioning_1 = require("./resources/provisioning");
|
|
|
57
57
|
Object.defineProperty(exports, "ProvisioningResource", { enumerable: true, get: function () { return provisioning_1.ProvisioningResource; } });
|
|
58
58
|
var secrets_1 = require("./resources/secrets");
|
|
59
59
|
Object.defineProperty(exports, "SecretsResource", { enumerable: true, get: function () { return secrets_1.SecretsResource; } });
|
|
60
|
+
var teams_1 = require("./resources/teams");
|
|
61
|
+
Object.defineProperty(exports, "TeamsResource", { enumerable: true, get: function () { return teams_1.TeamsResource; } });
|
|
60
62
|
var tools_1 = require("./resources/tools");
|
|
61
63
|
Object.defineProperty(exports, "ToolsResource", { enumerable: true, get: function () { return tools_1.ToolsResource; } });
|
|
@@ -1,72 +1,39 @@
|
|
|
1
1
|
import type { AgentForgeClient } from '../client';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
avgResolutionMs: number | null;
|
|
11
|
-
avgFrtMs: number | null;
|
|
12
|
-
avgTimeToAssignMs: number | null;
|
|
13
|
-
}
|
|
14
|
-
export interface SupportKpiResponse {
|
|
15
|
-
tenantId: string;
|
|
16
|
-
from: string;
|
|
17
|
-
to: string;
|
|
18
|
-
totals: SupportKpiTotals;
|
|
19
|
-
byDimension: Array<SupportKpiTotals & {
|
|
20
|
-
dimensionType: 'agent' | 'operator';
|
|
21
|
-
dimensionKey: string;
|
|
22
|
-
}>;
|
|
23
|
-
}
|
|
24
|
-
export interface AgentAttentionLogRow {
|
|
25
|
-
dimensionType: 'agent' | 'operator';
|
|
26
|
-
dimensionKey: string;
|
|
27
|
-
metricDate: string;
|
|
28
|
-
receivedCount: number;
|
|
29
|
-
aiResponsesCount: number;
|
|
30
|
-
humanMessagesCount: number;
|
|
31
|
-
escalationsCount: number;
|
|
32
|
-
aiResolvedCount: number;
|
|
33
|
-
humanHandledCount: number;
|
|
34
|
-
assignmentsCount: number;
|
|
35
|
-
avgResolutionMs: number | null;
|
|
36
|
-
avgFrtMs: number | null;
|
|
37
|
-
avgTimeToAssignMs: number | null;
|
|
2
|
+
import type { SupportKpiResponse, AgentAttentionLogRow } from '../types';
|
|
3
|
+
export interface GetSupportKpisInput {
|
|
4
|
+
/** Window start (inclusive). ISO 8601 or Date. */
|
|
5
|
+
from: string | Date;
|
|
6
|
+
/** Window end (exclusive). ISO 8601 or Date. */
|
|
7
|
+
to: string | Date;
|
|
8
|
+
agentId?: string;
|
|
9
|
+
operatorUserId?: string;
|
|
38
10
|
}
|
|
39
|
-
export interface
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
/** ISO date string. Required. */
|
|
43
|
-
to: string;
|
|
44
|
-
/** Narrow to one agent's rows (`byDimension`/`items` filtered to
|
|
45
|
-
* `dimensionType: 'agent', dimensionKey: agentId`). */
|
|
11
|
+
export interface GetAgentAttentionLogInput {
|
|
12
|
+
from: string | Date;
|
|
13
|
+
to: string | Date;
|
|
46
14
|
agentId?: string;
|
|
47
|
-
/** Narrow to one operator's rows. */
|
|
48
15
|
operatorUserId?: string;
|
|
49
16
|
}
|
|
50
17
|
export declare class AnalyticsResource {
|
|
51
18
|
private readonly client;
|
|
52
19
|
constructor(client: AgentForgeClient);
|
|
53
20
|
/**
|
|
54
|
-
* `GET /apps/me/support-kpis` — totals + per-agent
|
|
55
|
-
* the
|
|
21
|
+
* `GET /apps/me/support-kpis` — totals + per-(agent|operator)
|
|
22
|
+
* breakdown for the App's tenant, in the given window.
|
|
56
23
|
*
|
|
57
24
|
* @example
|
|
58
|
-
* const
|
|
59
|
-
* from: '2026-08-01T00:00:
|
|
60
|
-
* to:
|
|
25
|
+
* const { totals, byDimension } = await af.analytics.getSupportKpis({
|
|
26
|
+
* from: '2026-08-01T00:00:00Z',
|
|
27
|
+
* to: '2026-08-08T00:00:00Z',
|
|
61
28
|
* });
|
|
62
29
|
*/
|
|
63
|
-
getSupportKpis(
|
|
30
|
+
getSupportKpis(input: GetSupportKpisInput): Promise<SupportKpiResponse>;
|
|
64
31
|
/**
|
|
65
|
-
* `GET /apps/me/support-attention-log` —
|
|
66
|
-
*
|
|
32
|
+
* `GET /apps/me/support-attention-log` — per-day rows for
|
|
33
|
+
* the "atención por agente" table/chart (SD-11).
|
|
67
34
|
*/
|
|
68
|
-
getAgentAttentionLog(
|
|
35
|
+
getAgentAttentionLog(input: GetAgentAttentionLogInput): Promise<{
|
|
69
36
|
items: AgentAttentionLogRow[];
|
|
70
37
|
}>;
|
|
71
|
-
private
|
|
38
|
+
private buildQuery;
|
|
72
39
|
}
|
|
@@ -1,26 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// analytics resource (AGF-SD-
|
|
3
|
-
//
|
|
4
|
-
// `GET /apps/me/support
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// narrowing.
|
|
2
|
+
// analytics resource (AGF-SD-5) — App-scoped read surface for the support
|
|
3
|
+
// KPIs materialized by SD-3 (`af_support_metrics`). Wraps SD-3b's
|
|
4
|
+
// `AppSupportAnalyticsController` (`GET /apps/me/support-*`), which follows
|
|
5
|
+
// the `me/*` precedent of `AppsController`: the `sk_live_` IS the identity,
|
|
6
|
+
// so there is no `:agentId` in the path and no `tenantId` in the query.
|
|
8
7
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// appSecret-only client; see `connectors.ts`'s file header for the same
|
|
14
|
-
// gotcha on the App-user scope methods there), so `authHeaders()` can pick
|
|
15
|
-
// either credential for the `Authorization: Bearer` header. `tenantId` is
|
|
16
|
-
// NEVER a param here (SDD §4.5) — the server resolves it exclusively from
|
|
17
|
-
// the credential.
|
|
18
|
-
//
|
|
19
|
-
// `from`/`to` are REQUIRED on both methods — the platform rejects a
|
|
20
|
-
// missing/malformed/inverted/too-wide range with 400 (no implicit default
|
|
21
|
-
// window). This wrapper does no validation of its own; it forwards
|
|
22
|
-
// whatever `Date` the caller passes as an ISO string and lets the server
|
|
23
|
-
// be the single source of truth for what's a valid range.
|
|
8
|
+
// Both methods are single-tenant reads: `tenantId` is resolved from the
|
|
9
|
+
// caller's auth context on the server (never from input), so the SDK
|
|
10
|
+
// signature only takes the query knobs. `agentId`/`operatorUserId` are
|
|
11
|
+
// optional filters within that tenant.
|
|
24
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
13
|
exports.AnalyticsResource = void 0;
|
|
26
14
|
class AnalyticsResource {
|
|
@@ -28,32 +16,36 @@ class AnalyticsResource {
|
|
|
28
16
|
this.client = client;
|
|
29
17
|
}
|
|
30
18
|
/**
|
|
31
|
-
* `GET /apps/me/support-kpis` — totals + per-agent
|
|
32
|
-
* the
|
|
19
|
+
* `GET /apps/me/support-kpis` — totals + per-(agent|operator)
|
|
20
|
+
* breakdown for the App's tenant, in the given window.
|
|
33
21
|
*
|
|
34
22
|
* @example
|
|
35
|
-
* const
|
|
36
|
-
* from: '2026-08-01T00:00:
|
|
37
|
-
* to:
|
|
23
|
+
* const { totals, byDimension } = await af.analytics.getSupportKpis({
|
|
24
|
+
* from: '2026-08-01T00:00:00Z',
|
|
25
|
+
* to: '2026-08-08T00:00:00Z',
|
|
38
26
|
* });
|
|
39
27
|
*/
|
|
40
|
-
async getSupportKpis(
|
|
41
|
-
|
|
28
|
+
async getSupportKpis(input) {
|
|
29
|
+
const qs = this.buildQuery(input);
|
|
30
|
+
return this.client.request('GET', `/apps/me/support-kpis?${qs}`);
|
|
42
31
|
}
|
|
43
32
|
/**
|
|
44
|
-
* `GET /apps/me/support-attention-log` —
|
|
45
|
-
*
|
|
33
|
+
* `GET /apps/me/support-attention-log` — per-day rows for
|
|
34
|
+
* the "atención por agente" table/chart (SD-11).
|
|
46
35
|
*/
|
|
47
|
-
async getAgentAttentionLog(
|
|
48
|
-
|
|
36
|
+
async getAgentAttentionLog(input) {
|
|
37
|
+
const qs = this.buildQuery(input);
|
|
38
|
+
return this.client.request('GET', `/apps/me/support-attention-log?${qs}`);
|
|
49
39
|
}
|
|
50
|
-
|
|
51
|
-
const params = new URLSearchParams(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
params.set('
|
|
56
|
-
|
|
40
|
+
buildQuery(input) {
|
|
41
|
+
const params = new URLSearchParams();
|
|
42
|
+
params.set('from', input.from instanceof Date ? input.from.toISOString() : input.from);
|
|
43
|
+
params.set('to', input.to instanceof Date ? input.to.toISOString() : input.to);
|
|
44
|
+
if (input.agentId)
|
|
45
|
+
params.set('agentId', input.agentId);
|
|
46
|
+
if (input.operatorUserId)
|
|
47
|
+
params.set('operatorUserId', input.operatorUserId);
|
|
48
|
+
return params.toString();
|
|
57
49
|
}
|
|
58
50
|
}
|
|
59
51
|
exports.AnalyticsResource = AnalyticsResource;
|
package/dist/resources/apps.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentForgeClient } from '../client';
|
|
2
|
-
import type { PublicAppBranding, AppSelf, AppSelfConnectors } from '../types';
|
|
2
|
+
import type { PublicAppBranding, AppSelf, AppSelfConnectors, AppSelfConnectorToolsResponse } from '../types';
|
|
3
3
|
export declare class AppsResource {
|
|
4
4
|
private readonly client;
|
|
5
5
|
constructor(client: AgentForgeClient);
|
|
@@ -41,5 +41,21 @@ export declare class AppsResource {
|
|
|
41
41
|
* by the App at runtime.
|
|
42
42
|
*/
|
|
43
43
|
list: () => Promise<AppSelfConnectors>;
|
|
44
|
+
/**
|
|
45
|
+
* `GET /apps/me/connector-tools` (AGF-CTG-1) — flat tool-name catalog
|
|
46
|
+
* contributed by the connectors ENABLED for the App this client
|
|
47
|
+
* authenticated AS. App-level granularity ONLY: this is NOT narrowed
|
|
48
|
+
* per-end-user — that narrowing already happens downstream at runtime
|
|
49
|
+
* via `toolsForAppUser ∩ agent.tools[]`.
|
|
50
|
+
*
|
|
51
|
+
* Use it to build a whitelist of tool names an App may reference (e.g.
|
|
52
|
+
* the SOP Architect's bootstrap), so a prompt cannot name a connector
|
|
53
|
+
* tool the App has no connector enabled for.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* const { toolNames } = await af.apps.connectors.tools();
|
|
57
|
+
* const allowed = new Set(toolNames);
|
|
58
|
+
*/
|
|
59
|
+
tools: () => Promise<AppSelfConnectorToolsResponse>;
|
|
44
60
|
};
|
|
45
61
|
}
|
package/dist/resources/apps.js
CHANGED
|
@@ -35,6 +35,24 @@ class AppsResource {
|
|
|
35
35
|
list: async () => {
|
|
36
36
|
return this.client.request('GET', '/apps/me/connectors');
|
|
37
37
|
},
|
|
38
|
+
/**
|
|
39
|
+
* `GET /apps/me/connector-tools` (AGF-CTG-1) — flat tool-name catalog
|
|
40
|
+
* contributed by the connectors ENABLED for the App this client
|
|
41
|
+
* authenticated AS. App-level granularity ONLY: this is NOT narrowed
|
|
42
|
+
* per-end-user — that narrowing already happens downstream at runtime
|
|
43
|
+
* via `toolsForAppUser ∩ agent.tools[]`.
|
|
44
|
+
*
|
|
45
|
+
* Use it to build a whitelist of tool names an App may reference (e.g.
|
|
46
|
+
* the SOP Architect's bootstrap), so a prompt cannot name a connector
|
|
47
|
+
* tool the App has no connector enabled for.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* const { toolNames } = await af.apps.connectors.tools();
|
|
51
|
+
* const allowed = new Set(toolNames);
|
|
52
|
+
*/
|
|
53
|
+
tools: async () => {
|
|
54
|
+
return this.client.request('GET', '/apps/me/connector-tools');
|
|
55
|
+
},
|
|
38
56
|
};
|
|
39
57
|
}
|
|
40
58
|
/**
|
|
@@ -1,113 +1,71 @@
|
|
|
1
1
|
import type { AgentForgeClient } from '../client';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* `GET /connectors/inbox/agents/:agentId/inbox/threads` — threads for this
|
|
7
|
-
* agent's support inbox. Optional `channelId` narrows to one channel.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* const { items } = await af.inbox.listThreads(agentId);
|
|
11
|
-
*/
|
|
12
|
-
listThreads(agentId: string, opts?: {
|
|
13
|
-
channelId?: string;
|
|
14
|
-
}): Promise<{
|
|
15
|
-
items: InboxThreadView[];
|
|
16
|
-
}>;
|
|
17
|
-
/**
|
|
18
|
-
* `GET /connectors/inbox/agents/:agentId/inbox/threads/:threadId` — a
|
|
19
|
-
* single thread.
|
|
20
|
-
*/
|
|
21
|
-
getThread(agentId: string, threadId: string): Promise<InboxThreadView>;
|
|
22
|
-
/**
|
|
23
|
-
* `GET /connectors/inbox/agents/:agentId/inbox/threads/:threadId/messages`
|
|
24
|
-
* — full message history for a thread.
|
|
25
|
-
*/
|
|
26
|
-
listMessages(agentId: string, threadId: string): Promise<{
|
|
27
|
-
items: InboxMessageView[];
|
|
28
|
-
}>;
|
|
29
|
-
/**
|
|
30
|
-
* `POST .../threads/:threadId/messages` — send a message as the operator.
|
|
31
|
-
* `pauseAgent` defaults `true` server-side (pass `false` to reply without
|
|
32
|
-
* taking the thread away from the agent). `operatorId` is the App's own
|
|
33
|
-
* opaque identifier for the acting human rep — see file header.
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* await af.inbox.sendOperatorMessage(agentId, threadId, {
|
|
37
|
-
* text: 'Un momento, reviso tu caso.',
|
|
38
|
-
* operatorId: 'scrappydoc-rep-42',
|
|
39
|
-
* });
|
|
40
|
-
*/
|
|
41
|
-
sendOperatorMessage(agentId: string, threadId: string, input: {
|
|
42
|
-
text: string;
|
|
43
|
-
pauseAgent?: boolean;
|
|
44
|
-
operatorId?: string;
|
|
45
|
-
}): Promise<void>;
|
|
46
|
-
/**
|
|
47
|
-
* `POST .../threads/:threadId/assign` — claim a thread for an operator.
|
|
48
|
-
* `operatorId` is required (the server rejects a missing one with 401).
|
|
49
|
-
*/
|
|
50
|
-
assignThread(agentId: string, threadId: string, input: {
|
|
51
|
-
operatorId: string;
|
|
52
|
-
}): Promise<void>;
|
|
53
|
-
/**
|
|
54
|
-
* `DELETE .../threads/:threadId/assign` — release a thread claim
|
|
55
|
-
* (handback). `operatorId`, when given, must match the current assignee
|
|
56
|
-
* server-side.
|
|
57
|
-
*/
|
|
58
|
-
handback(agentId: string, threadId: string, opts?: {
|
|
59
|
-
operatorId?: string;
|
|
60
|
-
}): Promise<void>;
|
|
61
|
-
/**
|
|
62
|
-
* `POST .../threads/:threadId/mode` — switch a thread between agent/human
|
|
63
|
-
* mode.
|
|
64
|
-
*/
|
|
65
|
-
setThreadMode(agentId: string, threadId: string, mode: InboxThreadMode): Promise<void>;
|
|
66
|
-
/**
|
|
67
|
-
* `POST .../threads/:threadId/close` — close a human-mode thread.
|
|
68
|
-
*/
|
|
69
|
-
closeThread(agentId: string, threadId: string, opts?: {
|
|
70
|
-
notes?: string;
|
|
71
|
-
operatorId?: string;
|
|
72
|
-
}): Promise<void>;
|
|
2
|
+
import type { InboxThreadView, InboxMessageView, InboxThreadMode } from '../types';
|
|
3
|
+
export interface ListThreadsOptions {
|
|
4
|
+
/** Optional filter to threads on a single channel of the agent. */
|
|
5
|
+
channelId?: string;
|
|
73
6
|
}
|
|
74
|
-
export
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
7
|
+
export interface SendMessageInput {
|
|
8
|
+
/** The operator's text. */
|
|
9
|
+
text: string;
|
|
10
|
+
/** Default true. Toggle off when the operator wants to chime in
|
|
11
|
+
* without taking the thread away from the agent. */
|
|
12
|
+
pauseAgent?: boolean;
|
|
13
|
+
/** App-minted operator identity (see file header). */
|
|
14
|
+
operatorId?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface AssignThreadInput {
|
|
17
|
+
/** App-minted operator identity — required for assign. Same string
|
|
18
|
+
* re-sent proves ownership of a prior claim. */
|
|
19
|
+
operatorId: string;
|
|
20
|
+
}
|
|
21
|
+
export interface UnassignThreadInput {
|
|
22
|
+
/** App-minted operator identity — must match the current assignee. */
|
|
23
|
+
operatorId: string;
|
|
83
24
|
}
|
|
84
|
-
export interface
|
|
85
|
-
id: string;
|
|
86
|
-
channelId: string;
|
|
87
|
-
externalId: string;
|
|
88
|
-
displayName?: string;
|
|
25
|
+
export interface SetThreadModeInput {
|
|
89
26
|
mode: InboxThreadMode;
|
|
90
|
-
unreadCount: number;
|
|
91
|
-
lastMessageAt?: string;
|
|
92
|
-
lastMessagePreview?: string;
|
|
93
|
-
assignedHumanUserId?: string;
|
|
94
|
-
closedAt?: string;
|
|
95
|
-
closeNotes?: string;
|
|
96
|
-
closedByUserId?: string;
|
|
97
|
-
customerProfileId?: string;
|
|
98
|
-
customerProfile?: InboxThreadCustomerProfileView;
|
|
99
|
-
createdAt: string;
|
|
100
|
-
updatedAt: string;
|
|
101
27
|
}
|
|
102
|
-
export interface
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
28
|
+
export interface CloseThreadInput {
|
|
29
|
+
/** Free-text notes the operator leaves on close. Persisted as
|
|
30
|
+
* `af_inbox_threads.close_notes` — later consumed by AGF-BRAIN as
|
|
31
|
+
* institutional knowledge. */
|
|
32
|
+
notes?: string;
|
|
33
|
+
/** App-minted operator identity — recorded on `closed_by_user_id`. */
|
|
34
|
+
operatorId?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Agent-scoped inbox operator surface. Every method takes the `agentId`
|
|
38
|
+
* whose threads the App is operating; the App-ownership boundary is
|
|
39
|
+
* enforced server-side (404 on mismatch, mirroring
|
|
40
|
+
* `assertAgentOwnedByApp` in the identity-side controllers).
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* const inbox = af.inbox.forAgent(agentId);
|
|
44
|
+
* const { items: threads } = await inbox.listThreads();
|
|
45
|
+
* const { items: messages } = await inbox.listMessages(threads[0].id);
|
|
46
|
+
* await inbox.sendMessage(threads[0].id, {
|
|
47
|
+
* text: 'Hi, jumping in to help',
|
|
48
|
+
* operatorId: 'rep_alice',
|
|
49
|
+
* });
|
|
50
|
+
*/
|
|
51
|
+
export declare class InboxResource {
|
|
52
|
+
private readonly client;
|
|
53
|
+
constructor(client: AgentForgeClient);
|
|
54
|
+
/** Bind an agent id and return a helper with one method per
|
|
55
|
+
* `AppInboxController` route. Avoids threading `agentId` through
|
|
56
|
+
* every call. */
|
|
57
|
+
forAgent(agentId: string): {
|
|
58
|
+
listThreads: (opts?: ListThreadsOptions) => Promise<{
|
|
59
|
+
items: InboxThreadView[];
|
|
60
|
+
}>;
|
|
61
|
+
getThread: (threadId: string) => Promise<InboxThreadView>;
|
|
62
|
+
listMessages: (threadId: string) => Promise<{
|
|
63
|
+
items: InboxMessageView[];
|
|
64
|
+
}>;
|
|
65
|
+
sendMessage: (threadId: string, input: SendMessageInput) => Promise<void>;
|
|
66
|
+
assign: (threadId: string, input: AssignThreadInput) => Promise<void>;
|
|
67
|
+
unassign: (threadId: string, input: UnassignThreadInput) => Promise<void>;
|
|
68
|
+
setMode: (threadId: string, input: SetThreadModeInput) => Promise<void>;
|
|
69
|
+
close: (threadId: string, input?: CloseThreadInput) => Promise<void>;
|
|
70
|
+
};
|
|
113
71
|
}
|
package/dist/resources/inbox.js
CHANGED
|
@@ -1,118 +1,80 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// inbox resource (AGF-SD-
|
|
3
|
-
// `AppInboxController` (`connectors/inbox/agents/:agentId
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// agent-scoped `ak_live_` — never a human dashboard session.
|
|
2
|
+
// inbox resource (AGF-SD-5) — App-scoped operator surface. Wraps the
|
|
3
|
+
// platform's `AppInboxController` (AGF-SD-1, `connectors/inbox/agents/:agentId`),
|
|
4
|
+
// exposing list/read/reply/assign/close for the threads of an agent the
|
|
5
|
+
// calling App owns.
|
|
7
6
|
//
|
|
8
|
-
// Auth: `
|
|
9
|
-
// `
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// that file's header), inbox operator routes are meant to be called by an
|
|
13
|
-
// App itself. So this resource uses plain `this.client.request()`, whose
|
|
14
|
-
// `authHeaders()` picks `apiKey` OR `appSecret` for the `Authorization:
|
|
15
|
-
// Bearer` header (chatToken, if present instead, is rejected server-side
|
|
16
|
-
// with 401 since the route requires `auth.isApiKey`). Every method takes
|
|
17
|
-
// `agentId` explicitly (unlike `af.agents.me()`) because the platform
|
|
18
|
-
// route itself is per-agent and validates ownership server-side
|
|
19
|
-
// (`assertOwnedAgent` — 404, not 403, on a foreign agent).
|
|
7
|
+
// Auth: `ApiKeyGuard` on the server accepts BOTH `ak_live_` and `sk_live_`.
|
|
8
|
+
// The SDK's `authHeaders()` already sends whichever the client was
|
|
9
|
+
// constructed with on the `Authorization: Bearer` header — no per-call
|
|
10
|
+
// wiring needed here.
|
|
20
11
|
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
12
|
+
// `operatorId` semantics: SD-1's header comment flags this explicitly — an
|
|
13
|
+
// App has no `af_users.id`, so `operatorId` is whatever stable string the
|
|
14
|
+
// App mints for its own end of the conversation. The SDK exposes it as an
|
|
15
|
+
// optional param on `send()`, `assign()`, `unassign()`, `close()` and
|
|
16
|
+
// passes it through verbatim. The server's assignment guard still enforces
|
|
17
|
+
// "same operatorId re-sent = same claimant".
|
|
23
18
|
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
// `userId`. See `AppInboxController`'s file header on the platform for the
|
|
29
|
-
// full rationale.
|
|
30
|
-
//
|
|
31
|
-
// NOT covered here (left for a future extension — see file bottom for
|
|
32
|
-
// what's deliberately excluded and why):
|
|
33
|
-
// - `af.inbox.channels.get`/`update` — no App-scoped single-channel-read
|
|
34
|
-
// or update route exists on the platform today (`ApiKeyInboxController`
|
|
35
|
-
// only has list/create/delete). `list`/`create`/`destroy` already live
|
|
36
|
-
// on `af.connectors.*` (see `connectors.ts`) — not duplicated here.
|
|
37
|
-
// - operator online/offline status (`PUT teams/:teamId/operator/status`)
|
|
38
|
-
// — lives on `OperatorStatusController`, gated by the GLOBAL
|
|
39
|
-
// `JwtAuthGuard` (human dashboard session), not `ApiKeyGuard`. No
|
|
40
|
-
// `@Public()`, not reachable with `sk_live_`/`ak_live_` at all.
|
|
19
|
+
// NOTE — chip AGF-INBOX-OPERATORID-UUID: SD-1's free-string `operatorId`
|
|
20
|
+
// collides with UUID columns on assign/close (open follow-up on the
|
|
21
|
+
// platform side). Callers passing arbitrary strings should not be
|
|
22
|
+
// surprised by a 500 today; the shape convergence lands separately.
|
|
41
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
24
|
exports.InboxResource = void 0;
|
|
25
|
+
/**
|
|
26
|
+
* Agent-scoped inbox operator surface. Every method takes the `agentId`
|
|
27
|
+
* whose threads the App is operating; the App-ownership boundary is
|
|
28
|
+
* enforced server-side (404 on mismatch, mirroring
|
|
29
|
+
* `assertAgentOwnedByApp` in the identity-side controllers).
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* const inbox = af.inbox.forAgent(agentId);
|
|
33
|
+
* const { items: threads } = await inbox.listThreads();
|
|
34
|
+
* const { items: messages } = await inbox.listMessages(threads[0].id);
|
|
35
|
+
* await inbox.sendMessage(threads[0].id, {
|
|
36
|
+
* text: 'Hi, jumping in to help',
|
|
37
|
+
* operatorId: 'rep_alice',
|
|
38
|
+
* });
|
|
39
|
+
*/
|
|
43
40
|
class InboxResource {
|
|
44
41
|
constructor(client) {
|
|
45
42
|
this.client = client;
|
|
46
43
|
}
|
|
47
|
-
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
* await af.inbox.sendOperatorMessage(agentId, threadId, {
|
|
82
|
-
* text: 'Un momento, reviso tu caso.',
|
|
83
|
-
* operatorId: 'scrappydoc-rep-42',
|
|
84
|
-
* });
|
|
85
|
-
*/
|
|
86
|
-
async sendOperatorMessage(agentId, threadId, input) {
|
|
87
|
-
await this.client.request('POST', `/connectors/inbox/agents/${encodeURIComponent(agentId)}/inbox/threads/${encodeURIComponent(threadId)}/messages`, input);
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* `POST .../threads/:threadId/assign` — claim a thread for an operator.
|
|
91
|
-
* `operatorId` is required (the server rejects a missing one with 401).
|
|
92
|
-
*/
|
|
93
|
-
async assignThread(agentId, threadId, input) {
|
|
94
|
-
await this.client.request('POST', `/connectors/inbox/agents/${encodeURIComponent(agentId)}/inbox/threads/${encodeURIComponent(threadId)}/assign`, input);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* `DELETE .../threads/:threadId/assign` — release a thread claim
|
|
98
|
-
* (handback). `operatorId`, when given, must match the current assignee
|
|
99
|
-
* server-side.
|
|
100
|
-
*/
|
|
101
|
-
async handback(agentId, threadId, opts) {
|
|
102
|
-
await this.client.request('DELETE', `/connectors/inbox/agents/${encodeURIComponent(agentId)}/inbox/threads/${encodeURIComponent(threadId)}/assign`, opts);
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* `POST .../threads/:threadId/mode` — switch a thread between agent/human
|
|
106
|
-
* mode.
|
|
107
|
-
*/
|
|
108
|
-
async setThreadMode(agentId, threadId, mode) {
|
|
109
|
-
await this.client.request('POST', `/connectors/inbox/agents/${encodeURIComponent(agentId)}/inbox/threads/${encodeURIComponent(threadId)}/mode`, { mode });
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* `POST .../threads/:threadId/close` — close a human-mode thread.
|
|
113
|
-
*/
|
|
114
|
-
async closeThread(agentId, threadId, opts) {
|
|
115
|
-
await this.client.request('POST', `/connectors/inbox/agents/${encodeURIComponent(agentId)}/inbox/threads/${encodeURIComponent(threadId)}/close`, opts);
|
|
44
|
+
/** Bind an agent id and return a helper with one method per
|
|
45
|
+
* `AppInboxController` route. Avoids threading `agentId` through
|
|
46
|
+
* every call. */
|
|
47
|
+
forAgent(agentId) {
|
|
48
|
+
const base = `/connectors/inbox/agents/${encodeURIComponent(agentId)}/inbox`;
|
|
49
|
+
return {
|
|
50
|
+
listThreads: async (opts = {}) => {
|
|
51
|
+
const qs = opts.channelId
|
|
52
|
+
? `?channelId=${encodeURIComponent(opts.channelId)}`
|
|
53
|
+
: '';
|
|
54
|
+
return this.client.request('GET', `${base}/threads${qs}`);
|
|
55
|
+
},
|
|
56
|
+
getThread: async (threadId) => {
|
|
57
|
+
return this.client.request('GET', `${base}/threads/${encodeURIComponent(threadId)}`);
|
|
58
|
+
},
|
|
59
|
+
listMessages: async (threadId) => {
|
|
60
|
+
return this.client.request('GET', `${base}/threads/${encodeURIComponent(threadId)}/messages`);
|
|
61
|
+
},
|
|
62
|
+
sendMessage: async (threadId, input) => {
|
|
63
|
+
await this.client.request('POST', `${base}/threads/${encodeURIComponent(threadId)}/messages`, input);
|
|
64
|
+
},
|
|
65
|
+
assign: async (threadId, input) => {
|
|
66
|
+
await this.client.request('POST', `${base}/threads/${encodeURIComponent(threadId)}/assign`, input);
|
|
67
|
+
},
|
|
68
|
+
unassign: async (threadId, input) => {
|
|
69
|
+
await this.client.request('DELETE', `${base}/threads/${encodeURIComponent(threadId)}/assign`, input);
|
|
70
|
+
},
|
|
71
|
+
setMode: async (threadId, input) => {
|
|
72
|
+
await this.client.request('POST', `${base}/threads/${encodeURIComponent(threadId)}/mode`, input);
|
|
73
|
+
},
|
|
74
|
+
close: async (threadId, input = {}) => {
|
|
75
|
+
await this.client.request('POST', `${base}/threads/${encodeURIComponent(threadId)}/close`, input);
|
|
76
|
+
},
|
|
77
|
+
};
|
|
116
78
|
}
|
|
117
79
|
}
|
|
118
80
|
exports.InboxResource = InboxResource;
|
|
@@ -11,6 +11,14 @@ export interface ProvisionedApp {
|
|
|
11
11
|
publicKey: string;
|
|
12
12
|
appSecret: string;
|
|
13
13
|
}
|
|
14
|
+
/** `POST /platform/host-teams` result — a team-orchestrator's identity
|
|
15
|
+
* (AGF-SD-6a). No secret to reveal here (unlike `tenant()`/`app()`) — a
|
|
16
|
+
* team has no credential of its own, it's addressed through the
|
|
17
|
+
* tenant's `ak_live_` / App's `sk_live_`. */
|
|
18
|
+
export interface ProvisionedTeam {
|
|
19
|
+
teamId: string;
|
|
20
|
+
orchestratorAgentId: string;
|
|
21
|
+
}
|
|
14
22
|
export declare class ProvisioningResource {
|
|
15
23
|
private readonly client;
|
|
16
24
|
constructor(client: AgentForgeClient);
|
|
@@ -49,4 +57,27 @@ export declare class ProvisioningResource {
|
|
|
49
57
|
hostApp: string;
|
|
50
58
|
hostRef?: string;
|
|
51
59
|
}): Promise<ProvisionedApp>;
|
|
60
|
+
/**
|
|
61
|
+
* `POST /platform/host-teams` (AGF-SD-6a) — find-or-create a
|
|
62
|
+
* team-orchestrator for an EXISTING tenant on behalf of a trusted host
|
|
63
|
+
* app. Idempotent by `(tenantId, hostRef)`: a re-provision returns the
|
|
64
|
+
* SAME `teamId`/`orchestratorAgentId`, never a duplicate orchestrator.
|
|
65
|
+
*
|
|
66
|
+
* @param input.tenantId the tenant the team belongs to (host provisions
|
|
67
|
+
* it first via `tenant()`)
|
|
68
|
+
* @param input.hostApp short host id (e.g. "scrappydoc") — recorded
|
|
69
|
+
* for parity with `tenant()`/`app()`, not part of
|
|
70
|
+
* the idempotency key here (a team already lives
|
|
71
|
+
* under one tenant, so `(tenantId, hostRef)`
|
|
72
|
+
* alone is unambiguous)
|
|
73
|
+
* @param input.hostRef host reference (e.g. the workspaceId) — the
|
|
74
|
+
* idempotency key together with `tenantId`
|
|
75
|
+
* @param input.name display name, only used on first provision
|
|
76
|
+
*/
|
|
77
|
+
team(input: {
|
|
78
|
+
tenantId: string;
|
|
79
|
+
hostApp: string;
|
|
80
|
+
hostRef: string;
|
|
81
|
+
name?: string;
|
|
82
|
+
}): Promise<ProvisionedTeam>;
|
|
52
83
|
}
|
|
@@ -51,5 +51,30 @@ class ProvisioningResource {
|
|
|
51
51
|
async app(input) {
|
|
52
52
|
return this.client.request('POST', '/platform/host-apps', { tenantId: input.tenantId, hostApp: input.hostApp, hostRef: input.hostRef }, { headers: this.headers() });
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* `POST /platform/host-teams` (AGF-SD-6a) — find-or-create a
|
|
56
|
+
* team-orchestrator for an EXISTING tenant on behalf of a trusted host
|
|
57
|
+
* app. Idempotent by `(tenantId, hostRef)`: a re-provision returns the
|
|
58
|
+
* SAME `teamId`/`orchestratorAgentId`, never a duplicate orchestrator.
|
|
59
|
+
*
|
|
60
|
+
* @param input.tenantId the tenant the team belongs to (host provisions
|
|
61
|
+
* it first via `tenant()`)
|
|
62
|
+
* @param input.hostApp short host id (e.g. "scrappydoc") — recorded
|
|
63
|
+
* for parity with `tenant()`/`app()`, not part of
|
|
64
|
+
* the idempotency key here (a team already lives
|
|
65
|
+
* under one tenant, so `(tenantId, hostRef)`
|
|
66
|
+
* alone is unambiguous)
|
|
67
|
+
* @param input.hostRef host reference (e.g. the workspaceId) — the
|
|
68
|
+
* idempotency key together with `tenantId`
|
|
69
|
+
* @param input.name display name, only used on first provision
|
|
70
|
+
*/
|
|
71
|
+
async team(input) {
|
|
72
|
+
return this.client.request('POST', '/platform/host-teams', {
|
|
73
|
+
tenantId: input.tenantId,
|
|
74
|
+
hostApp: input.hostApp,
|
|
75
|
+
hostRef: input.hostRef,
|
|
76
|
+
name: input.name,
|
|
77
|
+
}, { headers: this.headers() });
|
|
78
|
+
}
|
|
54
79
|
}
|
|
55
80
|
exports.ProvisioningResource = ProvisioningResource;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AgentForgeClient } from '../client';
|
|
2
|
+
import type { CreateTeamInput, PublicTeamLanding, TeamSummary } from '../types';
|
|
3
|
+
export declare class TeamsResource {
|
|
4
|
+
private readonly client;
|
|
5
|
+
constructor(client: AgentForgeClient);
|
|
6
|
+
/** `GET /team/:slug` — public landing payload of a public team. 404 → `AgentForgeNotFoundError`. */
|
|
7
|
+
getPublic(slug: string): Promise<PublicTeamLanding>;
|
|
8
|
+
/** `POST /api/v1/teams` — create a team (and its orchestrator) in the caller's tenant. */
|
|
9
|
+
create(input: CreateTeamInput): Promise<TeamSummary>;
|
|
10
|
+
/** `DELETE /api/v1/teams/:teamId` — delete a team of the caller's tenant. */
|
|
11
|
+
delete(teamId: string): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// teams resource — public read of a team's landing payload, so a host App
|
|
3
|
+
// (PoodleDeck, ScrappyDoc, …) can render its own public page for a team
|
|
4
|
+
// without hand-rolling a fetch against the platform (SDK-first rule).
|
|
5
|
+
//
|
|
6
|
+
// - `getPublic(slug)` — `GET /team/:slug`. The platform's anonymous team
|
|
7
|
+
// landing surface: team metadata + profile template/blocks/theme, the
|
|
8
|
+
// orchestrator identity and the member roster. Private teams 404 to
|
|
9
|
+
// anonymous callers; this client never sends a user JWT, so it only
|
|
10
|
+
// ever sees public teams.
|
|
11
|
+
//
|
|
12
|
+
// - `create(input)` / `delete(teamId)` — `POST` / `DELETE /api/v1/teams`.
|
|
13
|
+
// A host App builds a team for one of its end customers (members are
|
|
14
|
+
// agents it created with `agents.create`). With `sk_live_` the team is
|
|
15
|
+
// owned by the App. `delete` is the compensation when a later step of
|
|
16
|
+
// the host's own onboarding fails.
|
|
17
|
+
//
|
|
18
|
+
// The response also carries a `chatToken` (`aft_…`) for the platform's own
|
|
19
|
+
// public page. A host that runs the chat server-side with its `sk_live_`
|
|
20
|
+
// (`chat.streamMessageForAppUser`) must NOT forward it to browsers.
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.TeamsResource = void 0;
|
|
23
|
+
class TeamsResource {
|
|
24
|
+
constructor(client) {
|
|
25
|
+
this.client = client;
|
|
26
|
+
}
|
|
27
|
+
/** `GET /team/:slug` — public landing payload of a public team. 404 → `AgentForgeNotFoundError`. */
|
|
28
|
+
async getPublic(slug) {
|
|
29
|
+
return this.client.request('GET', `/team/${encodeURIComponent(slug)}`);
|
|
30
|
+
}
|
|
31
|
+
/** `POST /api/v1/teams` — create a team (and its orchestrator) in the caller's tenant. */
|
|
32
|
+
async create(input) {
|
|
33
|
+
return this.client.request('POST', '/api/v1/teams', input);
|
|
34
|
+
}
|
|
35
|
+
/** `DELETE /api/v1/teams/:teamId` — delete a team of the caller's tenant. */
|
|
36
|
+
async delete(teamId) {
|
|
37
|
+
await this.client.request('DELETE', `/api/v1/teams/${encodeURIComponent(teamId)}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.TeamsResource = TeamsResource;
|
package/dist/types.d.ts
CHANGED
|
@@ -84,6 +84,16 @@ export interface AppSelfConnectors {
|
|
|
84
84
|
mode: 'whitelist' | 'legacy';
|
|
85
85
|
connectors: AppSelfConnector[];
|
|
86
86
|
}
|
|
87
|
+
export interface AppSelfConnectorTools {
|
|
88
|
+
connectorId: string;
|
|
89
|
+
toolNames: string[];
|
|
90
|
+
}
|
|
91
|
+
export interface AppSelfConnectorToolsResponse {
|
|
92
|
+
connectors: AppSelfConnectorTools[];
|
|
93
|
+
/** Flat, de-duplicated union of every `toolNames` entry above — this is
|
|
94
|
+
* what a whitelist consumer actually wants. */
|
|
95
|
+
toolNames: string[];
|
|
96
|
+
}
|
|
87
97
|
export interface RegisterToolInput {
|
|
88
98
|
name: string;
|
|
89
99
|
description: string;
|
|
@@ -488,4 +498,156 @@ export interface TenantSecretEntry {
|
|
|
488
498
|
* Ausente si nunca se configuró. */
|
|
489
499
|
updatedAt?: string;
|
|
490
500
|
}
|
|
501
|
+
export type InboxThreadMode = 'agent' | 'human';
|
|
502
|
+
export type InboxMessageDirection = 'inbound' | 'outbound';
|
|
503
|
+
export type InboxMessageSource = 'customer' | 'agent' | 'operator';
|
|
504
|
+
export type InboxMessageType = 'text' | 'image' | 'video' | 'audio' | 'document' | 'sticker' | 'location' | 'unsupported';
|
|
505
|
+
/** Read-through customer profile snapshot embedded on every thread — saves
|
|
506
|
+
* the UI a round-trip per thread. NULL on threads whose customerProfileId
|
|
507
|
+
* hasn't been linked yet (very brief window on first inbound). */
|
|
508
|
+
export interface InboxThreadCustomerProfileView {
|
|
509
|
+
id: string;
|
|
510
|
+
displayName?: string;
|
|
511
|
+
/** Provider handle without the leading `@`. */
|
|
512
|
+
username?: string;
|
|
513
|
+
avatarUrl?: string;
|
|
514
|
+
providerId?: string;
|
|
515
|
+
tags?: string[];
|
|
516
|
+
notes?: string;
|
|
517
|
+
}
|
|
518
|
+
export interface InboxThreadView {
|
|
519
|
+
id: string;
|
|
520
|
+
channelId: string;
|
|
521
|
+
externalId: string;
|
|
522
|
+
displayName?: string;
|
|
523
|
+
mode: InboxThreadMode;
|
|
524
|
+
unreadCount: number;
|
|
525
|
+
lastMessageAt?: string;
|
|
526
|
+
lastMessagePreview?: string;
|
|
527
|
+
/** Workspace user currently responsible for the thread. */
|
|
528
|
+
assignedHumanUserId?: string;
|
|
529
|
+
/** AGF-ASSIGN-P1-CLOSE. ISO timestamp when the human conversation was
|
|
530
|
+
* formally closed. Undefined = open / never escalated. */
|
|
531
|
+
closedAt?: string;
|
|
532
|
+
closeNotes?: string;
|
|
533
|
+
closedByUserId?: string;
|
|
534
|
+
customerProfileId?: string;
|
|
535
|
+
customerProfile?: InboxThreadCustomerProfileView;
|
|
536
|
+
createdAt: string;
|
|
537
|
+
updatedAt: string;
|
|
538
|
+
}
|
|
539
|
+
export interface InboxMessageView {
|
|
540
|
+
id: string;
|
|
541
|
+
threadId: string;
|
|
542
|
+
direction: InboxMessageDirection;
|
|
543
|
+
source: InboxMessageSource;
|
|
544
|
+
type: InboxMessageType;
|
|
545
|
+
body: string;
|
|
546
|
+
externalMessageId?: string;
|
|
547
|
+
payload?: Record<string, unknown>;
|
|
548
|
+
sentAt: string;
|
|
549
|
+
recordedAt: string;
|
|
550
|
+
}
|
|
551
|
+
export interface SupportKpiTotals {
|
|
552
|
+
receivedCount: number;
|
|
553
|
+
aiResponsesCount: number;
|
|
554
|
+
humanMessagesCount: number;
|
|
555
|
+
escalationsCount: number;
|
|
556
|
+
aiResolvedCount: number;
|
|
557
|
+
humanHandledCount: number;
|
|
558
|
+
assignmentsCount: number;
|
|
559
|
+
avgResolutionMs: number | null;
|
|
560
|
+
avgFrtMs: number | null;
|
|
561
|
+
avgTimeToAssignMs: number | null;
|
|
562
|
+
}
|
|
563
|
+
export interface SupportKpiResponse {
|
|
564
|
+
tenantId: string;
|
|
565
|
+
from: string;
|
|
566
|
+
to: string;
|
|
567
|
+
totals: SupportKpiTotals;
|
|
568
|
+
/** One entry per (dimensionType, dimensionKey) in range. */
|
|
569
|
+
byDimension: Array<SupportKpiTotals & {
|
|
570
|
+
dimensionType: 'agent' | 'operator';
|
|
571
|
+
dimensionKey: string;
|
|
572
|
+
}>;
|
|
573
|
+
}
|
|
574
|
+
export interface AgentAttentionLogRow {
|
|
575
|
+
dimensionType: 'agent' | 'operator';
|
|
576
|
+
dimensionKey: string;
|
|
577
|
+
/** YYYY-MM-DD */
|
|
578
|
+
metricDate: string;
|
|
579
|
+
receivedCount: number;
|
|
580
|
+
aiResponsesCount: number;
|
|
581
|
+
humanMessagesCount: number;
|
|
582
|
+
escalationsCount: number;
|
|
583
|
+
aiResolvedCount: number;
|
|
584
|
+
humanHandledCount: number;
|
|
585
|
+
assignmentsCount: number;
|
|
586
|
+
avgResolutionMs: number | null;
|
|
587
|
+
avgFrtMs: number | null;
|
|
588
|
+
avgTimeToAssignMs: number | null;
|
|
589
|
+
}
|
|
590
|
+
export type PublicProfileTemplate = 'minimal' | 'brand' | 'beacons';
|
|
591
|
+
export interface PublicProfileBlock {
|
|
592
|
+
id: string;
|
|
593
|
+
kind: string;
|
|
594
|
+
enabled: boolean;
|
|
595
|
+
title?: string;
|
|
596
|
+
[field: string]: unknown;
|
|
597
|
+
}
|
|
598
|
+
export interface PublicTeamLanding {
|
|
599
|
+
team: {
|
|
600
|
+
id: string;
|
|
601
|
+
name: string;
|
|
602
|
+
publicSlug?: string;
|
|
603
|
+
description?: string;
|
|
604
|
+
theme: Record<string, unknown> | null;
|
|
605
|
+
profileTemplate: PublicProfileTemplate;
|
|
606
|
+
profileBlocks: PublicProfileBlock[] | null;
|
|
607
|
+
orchestrationMode: 'flat' | 'hierarchical';
|
|
608
|
+
};
|
|
609
|
+
orchestrator: {
|
|
610
|
+
id: string;
|
|
611
|
+
name: string;
|
|
612
|
+
avatarUrl?: string;
|
|
613
|
+
};
|
|
614
|
+
members: Array<{
|
|
615
|
+
id: string;
|
|
616
|
+
name: string;
|
|
617
|
+
avatarUrl?: string;
|
|
618
|
+
description?: string;
|
|
619
|
+
roleHint?: string;
|
|
620
|
+
}>;
|
|
621
|
+
/** Platform-page ChatToken. Hosts that chat through `sk_live_` must not expose it. */
|
|
622
|
+
chatToken: string | null;
|
|
623
|
+
}
|
|
624
|
+
/** `POST /api/v1/teams` body. The team's hidden orchestrator agent is created with it. */
|
|
625
|
+
export interface CreateTeamInput {
|
|
626
|
+
name: string;
|
|
627
|
+
/** Tenant-unique slug; derived from `name` when omitted. */
|
|
628
|
+
slug?: string;
|
|
629
|
+
description?: string;
|
|
630
|
+
/** Standalone agents of the same tenant that become the team's members. */
|
|
631
|
+
memberAgentIds?: string[];
|
|
632
|
+
/** agentId → what that member is for (the orchestrator reads it to delegate). */
|
|
633
|
+
roleHints?: Record<string, string>;
|
|
634
|
+
/** Globally unique handle of the public page (`/team/:publicSlug`). Minted when omitted. */
|
|
635
|
+
publicSlug?: string;
|
|
636
|
+
visibility?: 'private' | 'public';
|
|
637
|
+
orchestrationMode?: 'flat' | 'hierarchical';
|
|
638
|
+
}
|
|
639
|
+
/** A team as the admin surface returns it (`/api/v1/teams`). */
|
|
640
|
+
export interface TeamSummary {
|
|
641
|
+
id: string;
|
|
642
|
+
tenantId: string;
|
|
643
|
+
appId?: string | null;
|
|
644
|
+
name: string;
|
|
645
|
+
slug: string;
|
|
646
|
+
description?: string | null;
|
|
647
|
+
publicSlug?: string | null;
|
|
648
|
+
visibility: 'private' | 'public';
|
|
649
|
+
orchestratorAgentId: string;
|
|
650
|
+
orchestrationMode: 'flat' | 'hierarchical';
|
|
651
|
+
[field: string]: unknown;
|
|
652
|
+
}
|
|
491
653
|
export {};
|
package/package.json
CHANGED