@phaseo/agent-sdk 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +219 -0
- package/README.md +309 -2
- package/SKILL.md +24 -0
- package/dist/adapters/gateway-client.d.ts +24 -0
- package/dist/adapters/gateway-client.js +179 -0
- package/dist/agent.d.ts +7 -0
- package/dist/agent.js +11 -0
- package/dist/devtools.d.ts +26 -0
- package/dist/devtools.js +102 -0
- package/dist/errors.d.ts +60 -0
- package/dist/errors.js +161 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.js +4 -1
- package/dist/runtime/loop.d.ts +3 -0
- package/dist/runtime/loop.js +1070 -0
- package/dist/types.d.ts +215 -0
- package/dist/types.js +1 -0
- package/examples/coding-review-agent.ts +108 -0
- package/examples/parallel-tool-agent.ts +60 -0
- package/examples/research-brief-agent.ts +70 -0
- package/examples/support-triage-agent.ts +104 -0
- package/package.json +24 -6
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import type { AgentGatewayErrorDetails } from "./errors.js";
|
|
2
|
+
import type { AgentDevtoolsConfig } from "./devtools.js";
|
|
3
|
+
export type AgentToolCall = {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
input: unknown;
|
|
7
|
+
};
|
|
8
|
+
export type AgentMessage = {
|
|
9
|
+
role: "system" | "user";
|
|
10
|
+
content: string;
|
|
11
|
+
} | {
|
|
12
|
+
role: "assistant";
|
|
13
|
+
content: string;
|
|
14
|
+
toolCalls?: AgentToolCall[];
|
|
15
|
+
} | {
|
|
16
|
+
role: "tool";
|
|
17
|
+
content: string;
|
|
18
|
+
toolCallId: string;
|
|
19
|
+
name: string;
|
|
20
|
+
};
|
|
21
|
+
export type AgentTool<TInput = unknown, TOutput = unknown, TContext = unknown> = {
|
|
22
|
+
id: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
parameters?: Record<string, unknown>;
|
|
25
|
+
timeoutMs?: number;
|
|
26
|
+
execute: (input: TInput, context: AgentRuntimeContext<TContext>) => Promise<TOutput> | TOutput;
|
|
27
|
+
};
|
|
28
|
+
export type AgentRuntimeContext<TContext = unknown> = {
|
|
29
|
+
runId: string;
|
|
30
|
+
agentId: string;
|
|
31
|
+
stepIndex: number;
|
|
32
|
+
context: TContext | undefined;
|
|
33
|
+
signal?: AbortSignal;
|
|
34
|
+
};
|
|
35
|
+
export type AgentModelRequest<TContext = unknown> = {
|
|
36
|
+
agentId: string;
|
|
37
|
+
model?: string;
|
|
38
|
+
instructions?: string;
|
|
39
|
+
messages: AgentMessage[];
|
|
40
|
+
tools: Array<Pick<AgentTool, "id" | "description" | "parameters">>;
|
|
41
|
+
context: TContext | undefined;
|
|
42
|
+
signal?: AbortSignal;
|
|
43
|
+
};
|
|
44
|
+
export type AgentModelResponse = {
|
|
45
|
+
message: Extract<AgentMessage, {
|
|
46
|
+
role: "assistant";
|
|
47
|
+
}>;
|
|
48
|
+
usage?: Record<string, unknown>;
|
|
49
|
+
requestId?: string;
|
|
50
|
+
nativeResponseId?: string | null;
|
|
51
|
+
provider?: string;
|
|
52
|
+
model?: string;
|
|
53
|
+
responseMeta?: Record<string, unknown>;
|
|
54
|
+
};
|
|
55
|
+
export type AgentModelClient<TContext = unknown> = {
|
|
56
|
+
generate: (request: AgentModelRequest<TContext>) => Promise<AgentModelResponse>;
|
|
57
|
+
};
|
|
58
|
+
export type AgentModelRetryConfig = {
|
|
59
|
+
maxRetries?: number;
|
|
60
|
+
backoffMs?: number;
|
|
61
|
+
};
|
|
62
|
+
export type AgentToolExecutionConfig = {
|
|
63
|
+
toolConcurrency?: number;
|
|
64
|
+
};
|
|
65
|
+
export type AgentEvent = {
|
|
66
|
+
type: "run.started" | "run.completed" | "run.failed" | "run.cancelled";
|
|
67
|
+
runId: string;
|
|
68
|
+
agentId: string;
|
|
69
|
+
timestamp: string;
|
|
70
|
+
status: AgentRunStatus;
|
|
71
|
+
output?: unknown;
|
|
72
|
+
error?: string;
|
|
73
|
+
errorDetails?: AgentGatewayErrorDetails;
|
|
74
|
+
} | {
|
|
75
|
+
type: "run.resumed";
|
|
76
|
+
runId: string;
|
|
77
|
+
agentId: string;
|
|
78
|
+
timestamp: string;
|
|
79
|
+
status: AgentRunStatus;
|
|
80
|
+
previousStatus: AgentRunStatus;
|
|
81
|
+
} | {
|
|
82
|
+
type: "run.waiting_for_human";
|
|
83
|
+
runId: string;
|
|
84
|
+
agentId: string;
|
|
85
|
+
timestamp: string;
|
|
86
|
+
status: AgentRunStatus;
|
|
87
|
+
stepIndex: number;
|
|
88
|
+
pause: AgentHumanPause;
|
|
89
|
+
} | {
|
|
90
|
+
type: "step.started" | "step.completed" | "step.cancelled" | "step.failed" | "model.requested" | "model.failed" | "model.completed" | "checkpoint.saved";
|
|
91
|
+
runId: string;
|
|
92
|
+
agentId: string;
|
|
93
|
+
timestamp: string;
|
|
94
|
+
status: AgentRunStatus;
|
|
95
|
+
stepIndex: number;
|
|
96
|
+
attempt?: number;
|
|
97
|
+
requestId?: string;
|
|
98
|
+
nativeResponseId?: string | null;
|
|
99
|
+
provider?: string;
|
|
100
|
+
model?: string;
|
|
101
|
+
usage?: Record<string, unknown>;
|
|
102
|
+
responseMeta?: Record<string, unknown>;
|
|
103
|
+
error?: string;
|
|
104
|
+
errorDetails?: AgentGatewayErrorDetails;
|
|
105
|
+
} | {
|
|
106
|
+
type: "tool.started" | "tool.completed" | "tool.failed";
|
|
107
|
+
runId: string;
|
|
108
|
+
agentId: string;
|
|
109
|
+
timestamp: string;
|
|
110
|
+
status: AgentRunStatus;
|
|
111
|
+
stepIndex: number;
|
|
112
|
+
toolCallId: string;
|
|
113
|
+
toolName: string;
|
|
114
|
+
output?: unknown;
|
|
115
|
+
error?: string;
|
|
116
|
+
};
|
|
117
|
+
export type AgentEventHandler = (event: AgentEvent) => void | Promise<void>;
|
|
118
|
+
export type AgentHumanPause = {
|
|
119
|
+
reason: string;
|
|
120
|
+
payload?: unknown;
|
|
121
|
+
requestedAt: string;
|
|
122
|
+
};
|
|
123
|
+
export type AgentHumanReviewRequest = {
|
|
124
|
+
reason: string;
|
|
125
|
+
payload?: unknown;
|
|
126
|
+
};
|
|
127
|
+
export type AgentHumanReviewContext<TInput = unknown, TContext = unknown, TOutput = unknown> = {
|
|
128
|
+
runId: string;
|
|
129
|
+
agentId: string;
|
|
130
|
+
stepIndex: number;
|
|
131
|
+
input: TInput;
|
|
132
|
+
context: TContext | undefined;
|
|
133
|
+
messages: AgentMessage[];
|
|
134
|
+
response: AgentModelResponse;
|
|
135
|
+
parsedOutput?: TOutput;
|
|
136
|
+
};
|
|
137
|
+
export type AgentDefinition<TInput = unknown, TOutput = unknown, TContext = unknown> = {
|
|
138
|
+
id: string;
|
|
139
|
+
model?: string;
|
|
140
|
+
preset?: string;
|
|
141
|
+
instructions?: string;
|
|
142
|
+
tools?: AgentTool<any, any, TContext>[];
|
|
143
|
+
maxSteps?: number;
|
|
144
|
+
modelRetry?: AgentModelRetryConfig;
|
|
145
|
+
toolExecution?: AgentToolExecutionConfig;
|
|
146
|
+
parseOutput?: (text: string) => TOutput;
|
|
147
|
+
humanReview?: (context: AgentHumanReviewContext<TInput, TContext, TOutput>) => AgentHumanReviewRequest | null | Promise<AgentHumanReviewRequest | null>;
|
|
148
|
+
};
|
|
149
|
+
export type AgentRunStatus = "queued" | "running" | "waiting_for_tools" | "waiting_for_human" | "completed" | "failed" | "cancelled";
|
|
150
|
+
export type AgentStepStatus = "pending" | "executing_model" | "executing_tools" | "checkpointed" | "cancelled" | "failed";
|
|
151
|
+
export type AgentRunRecord<TInput = unknown, TContext = unknown, TOutput = unknown> = {
|
|
152
|
+
id: string;
|
|
153
|
+
agentId: string;
|
|
154
|
+
status: AgentRunStatus;
|
|
155
|
+
input: TInput;
|
|
156
|
+
context?: TContext;
|
|
157
|
+
messages: AgentMessage[];
|
|
158
|
+
result?: TOutput;
|
|
159
|
+
error?: string;
|
|
160
|
+
errorDetails?: AgentGatewayErrorDetails;
|
|
161
|
+
pause?: AgentHumanPause | null;
|
|
162
|
+
createdAt: string;
|
|
163
|
+
updatedAt: string;
|
|
164
|
+
stepCount: number;
|
|
165
|
+
};
|
|
166
|
+
export type AgentStepRecord = {
|
|
167
|
+
runId: string;
|
|
168
|
+
index: number;
|
|
169
|
+
status: AgentStepStatus;
|
|
170
|
+
requestId?: string;
|
|
171
|
+
nativeResponseId?: string | null;
|
|
172
|
+
provider?: string;
|
|
173
|
+
model?: string;
|
|
174
|
+
modelAttempts?: number;
|
|
175
|
+
usage?: Record<string, unknown>;
|
|
176
|
+
toolCalls?: AgentToolCall[];
|
|
177
|
+
responseMeta?: Record<string, unknown>;
|
|
178
|
+
error?: string;
|
|
179
|
+
errorDetails?: AgentGatewayErrorDetails;
|
|
180
|
+
createdAt: string;
|
|
181
|
+
updatedAt: string;
|
|
182
|
+
};
|
|
183
|
+
export type AgentRunOptions<TInput = unknown, TContext = unknown> = {
|
|
184
|
+
input: TInput;
|
|
185
|
+
client: AgentModelClient<TContext>;
|
|
186
|
+
context?: TContext;
|
|
187
|
+
model?: string;
|
|
188
|
+
preset?: string;
|
|
189
|
+
maxSteps?: number;
|
|
190
|
+
modelRetry?: AgentModelRetryConfig;
|
|
191
|
+
toolExecution?: AgentToolExecutionConfig;
|
|
192
|
+
signal?: AbortSignal;
|
|
193
|
+
onEvent?: AgentEventHandler;
|
|
194
|
+
devtools?: Partial<AgentDevtoolsConfig>;
|
|
195
|
+
};
|
|
196
|
+
export type AgentContinueOptions<TInput = unknown, TOutput = unknown, TContext = unknown> = {
|
|
197
|
+
run: AgentRunResult<TOutput, TInput, TContext>;
|
|
198
|
+
client: AgentModelClient<TContext>;
|
|
199
|
+
context?: TContext;
|
|
200
|
+
model?: string;
|
|
201
|
+
preset?: string;
|
|
202
|
+
maxSteps?: number;
|
|
203
|
+
modelRetry?: AgentModelRetryConfig;
|
|
204
|
+
toolExecution?: AgentToolExecutionConfig;
|
|
205
|
+
signal?: AbortSignal;
|
|
206
|
+
humanInput?: string;
|
|
207
|
+
onEvent?: AgentEventHandler;
|
|
208
|
+
devtools?: Partial<AgentDevtoolsConfig>;
|
|
209
|
+
};
|
|
210
|
+
export type AgentRunResult<TOutput = unknown, TInput = unknown, TContext = unknown> = {
|
|
211
|
+
run: AgentRunRecord<TInput, TContext, TOutput>;
|
|
212
|
+
steps: AgentStepRecord[];
|
|
213
|
+
output: TOutput | undefined;
|
|
214
|
+
messages: AgentMessage[];
|
|
215
|
+
};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAgent,
|
|
3
|
+
createGatewayAgentClient,
|
|
4
|
+
defineTool,
|
|
5
|
+
} from "@phaseo/agent-sdk";
|
|
6
|
+
|
|
7
|
+
type CodeReviewPlan = {
|
|
8
|
+
risk: "low" | "medium" | "high";
|
|
9
|
+
summary: string;
|
|
10
|
+
recommendedActions: string[];
|
|
11
|
+
needsApproval: boolean;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const lookupDiffSummary = defineTool({
|
|
15
|
+
id: "lookup-diff-summary",
|
|
16
|
+
description: "Return a short summary of the changed files in one pull request.",
|
|
17
|
+
async execute(input: { pullRequestId: string }) {
|
|
18
|
+
return {
|
|
19
|
+
pullRequestId: input.pullRequestId,
|
|
20
|
+
files: ["apps/api/src/pipeline/before/index.ts", "apps/web/src/lib/chat/formatRoomError.ts"],
|
|
21
|
+
summary:
|
|
22
|
+
"Changes touch request validation and request-detail rendering for gateway diagnostics.",
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const lookupFailingChecks = defineTool({
|
|
28
|
+
id: "lookup-failing-checks",
|
|
29
|
+
description: "Return the failing CI checks for one pull request.",
|
|
30
|
+
async execute(input: { pullRequestId: string }) {
|
|
31
|
+
return {
|
|
32
|
+
pullRequestId: input.pullRequestId,
|
|
33
|
+
failingChecks: ["web-typecheck"],
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const codingReviewAgent = createAgent<string, CodeReviewPlan>({
|
|
39
|
+
id: "coding-review-agent",
|
|
40
|
+
model: "phaseo/free",
|
|
41
|
+
instructions:
|
|
42
|
+
"Use the available tools to inspect the coding task, then return a strict JSON review plan with risk, summary, recommendedActions, and needsApproval.",
|
|
43
|
+
tools: [lookupDiffSummary, lookupFailingChecks],
|
|
44
|
+
parseOutput(text: string) {
|
|
45
|
+
return JSON.parse(text) as CodeReviewPlan;
|
|
46
|
+
},
|
|
47
|
+
humanReview: ({ parsedOutput }: { parsedOutput?: CodeReviewPlan }) =>
|
|
48
|
+
parsedOutput?.needsApproval
|
|
49
|
+
? {
|
|
50
|
+
reason: "coding_review_approval_required",
|
|
51
|
+
payload: parsedOutput,
|
|
52
|
+
}
|
|
53
|
+
: null,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
async function main() {
|
|
57
|
+
const client = createGatewayAgentClient({
|
|
58
|
+
clientOptions: {
|
|
59
|
+
apiKey: process.env.PHASEO_API_KEY!,
|
|
60
|
+
},
|
|
61
|
+
responseFormat: {
|
|
62
|
+
type: "json_schema",
|
|
63
|
+
name: "code_review_plan",
|
|
64
|
+
schema: {
|
|
65
|
+
type: "object",
|
|
66
|
+
properties: {
|
|
67
|
+
risk: {
|
|
68
|
+
type: "string",
|
|
69
|
+
enum: ["low", "medium", "high"],
|
|
70
|
+
},
|
|
71
|
+
summary: { type: "string" },
|
|
72
|
+
recommendedActions: {
|
|
73
|
+
type: "array",
|
|
74
|
+
items: { type: "string" },
|
|
75
|
+
minItems: 1,
|
|
76
|
+
},
|
|
77
|
+
needsApproval: { type: "boolean" },
|
|
78
|
+
},
|
|
79
|
+
required: ["risk", "summary", "recommendedActions", "needsApproval"],
|
|
80
|
+
additionalProperties: false,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
plugins: [{ id: "response-healing", mode: "strict" }],
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const result = await codingReviewAgent.run({
|
|
87
|
+
input: "Review pull request pr_482 and produce a remediation plan.",
|
|
88
|
+
client,
|
|
89
|
+
onEvent(event: { type: string; runId: string }) {
|
|
90
|
+
console.log(event.type, event.runId);
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
if (result.run.status === "waiting_for_human") {
|
|
95
|
+
console.log("Paused for approval:", result.run.pause);
|
|
96
|
+
const continued = await codingReviewAgent.continueRun({
|
|
97
|
+
run: result,
|
|
98
|
+
client,
|
|
99
|
+
humanInput: "Approved. Finalize the plan.",
|
|
100
|
+
});
|
|
101
|
+
console.log(continued.output);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
console.log(result.output);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
void main();
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { createAgent, createGatewayAgentClient, defineTool } from "@phaseo/agent-sdk";
|
|
2
|
+
|
|
3
|
+
const fetchDocs = defineTool({
|
|
4
|
+
id: "fetch-docs",
|
|
5
|
+
description: "Fetch one internal docs summary by slug.",
|
|
6
|
+
async execute(input: { slug: string }) {
|
|
7
|
+
return {
|
|
8
|
+
slug: input.slug,
|
|
9
|
+
summary: `Docs summary for ${input.slug}`,
|
|
10
|
+
};
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const fetchStatus = defineTool({
|
|
15
|
+
id: "fetch-status",
|
|
16
|
+
description: "Fetch one status summary by component id.",
|
|
17
|
+
async execute(input: { component: string }) {
|
|
18
|
+
return {
|
|
19
|
+
component: input.component,
|
|
20
|
+
status: "operational",
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const fetchIncidents = defineTool({
|
|
26
|
+
id: "fetch-incidents",
|
|
27
|
+
description: "Fetch one current incident digest by service id.",
|
|
28
|
+
async execute(input: { service: string }) {
|
|
29
|
+
return {
|
|
30
|
+
service: input.service,
|
|
31
|
+
openIncidents: 0,
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const agent = createAgent({
|
|
37
|
+
id: "parallel-tool-agent",
|
|
38
|
+
model: "phaseo/free",
|
|
39
|
+
instructions:
|
|
40
|
+
"Use the available tools to gather context, then return one concise operational summary.",
|
|
41
|
+
tools: [fetchDocs, fetchStatus, fetchIncidents],
|
|
42
|
+
toolExecution: {
|
|
43
|
+
toolConcurrency: 3,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const result = await agent.run({
|
|
48
|
+
input:
|
|
49
|
+
"Fetch the presets docs, the gateway status component, and the async-jobs incident digest, then summarize the current state.",
|
|
50
|
+
client: createGatewayAgentClient({
|
|
51
|
+
clientOptions: {
|
|
52
|
+
apiKey: process.env.PHASEO_API_KEY!,
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
onEvent(event) {
|
|
56
|
+
console.log(event.type, event.runId);
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
console.log(result.output);
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { createAgent, createGatewayAgentClient } from "@phaseo/agent-sdk";
|
|
2
|
+
|
|
3
|
+
type ResearchBrief = {
|
|
4
|
+
topic: string;
|
|
5
|
+
summary: string;
|
|
6
|
+
sources: Array<{
|
|
7
|
+
title: string;
|
|
8
|
+
url: string;
|
|
9
|
+
}>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const researchBriefAgent = createAgent<string, ResearchBrief>({
|
|
13
|
+
id: "research-brief-agent",
|
|
14
|
+
model: "phaseo/free",
|
|
15
|
+
instructions:
|
|
16
|
+
"Research the user's topic with web search when needed and return a concise JSON brief with cited sources.",
|
|
17
|
+
parseOutput(text) {
|
|
18
|
+
return JSON.parse(text) as ResearchBrief;
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const client = createGatewayAgentClient({
|
|
23
|
+
clientOptions: {
|
|
24
|
+
apiKey: process.env.PHASEO_API_KEY!,
|
|
25
|
+
},
|
|
26
|
+
responseFormat: {
|
|
27
|
+
type: "json_schema",
|
|
28
|
+
name: "research_brief",
|
|
29
|
+
schema: {
|
|
30
|
+
type: "object",
|
|
31
|
+
properties: {
|
|
32
|
+
topic: { type: "string" },
|
|
33
|
+
summary: { type: "string" },
|
|
34
|
+
sources: {
|
|
35
|
+
type: "array",
|
|
36
|
+
items: {
|
|
37
|
+
type: "object",
|
|
38
|
+
properties: {
|
|
39
|
+
title: { type: "string" },
|
|
40
|
+
url: { type: "string" },
|
|
41
|
+
},
|
|
42
|
+
required: ["title", "url"],
|
|
43
|
+
additionalProperties: false,
|
|
44
|
+
},
|
|
45
|
+
minItems: 1,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
required: ["topic", "summary", "sources"],
|
|
49
|
+
additionalProperties: false,
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
plugins: [{ id: "response-healing" }],
|
|
53
|
+
gatewayTools: [{ type: "gateway:web_search", parameters: { max_results: 5 } }] as any,
|
|
54
|
+
toolChoice: "gateway:web_search" as any,
|
|
55
|
+
webSearchOptions: {
|
|
56
|
+
search_context_size: "high",
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export async function runResearchBrief(topic: string) {
|
|
61
|
+
const result = await researchBriefAgent.run({
|
|
62
|
+
input: topic,
|
|
63
|
+
client,
|
|
64
|
+
onEvent(event) {
|
|
65
|
+
console.log(event.type, event.runId);
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return result.output;
|
|
70
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentGatewayError,
|
|
3
|
+
createAgent,
|
|
4
|
+
createGatewayAgentClient,
|
|
5
|
+
} from "@phaseo/agent-sdk";
|
|
6
|
+
|
|
7
|
+
type SupportTriageDecision = {
|
|
8
|
+
queue: "billing" | "reliability" | "product" | "security";
|
|
9
|
+
severity: "low" | "medium" | "high";
|
|
10
|
+
needsHumanReview: boolean;
|
|
11
|
+
summary: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const supportTriageAgent = createAgent<string, SupportTriageDecision>({
|
|
15
|
+
id: "support-triage-agent",
|
|
16
|
+
preset: "support-triage",
|
|
17
|
+
parseOutput(text: string) {
|
|
18
|
+
return JSON.parse(text) as SupportTriageDecision;
|
|
19
|
+
},
|
|
20
|
+
humanReview: ({ parsedOutput }: { parsedOutput?: SupportTriageDecision }) =>
|
|
21
|
+
parsedOutput?.needsHumanReview
|
|
22
|
+
? {
|
|
23
|
+
reason: "support_triage_review_required",
|
|
24
|
+
payload: parsedOutput,
|
|
25
|
+
}
|
|
26
|
+
: null,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
async function main() {
|
|
30
|
+
try {
|
|
31
|
+
const client = createGatewayAgentClient({
|
|
32
|
+
clientOptions: {
|
|
33
|
+
apiKey: process.env.PHASEO_API_KEY!,
|
|
34
|
+
},
|
|
35
|
+
responseFormat: {
|
|
36
|
+
type: "json_schema",
|
|
37
|
+
name: "support_triage_decision",
|
|
38
|
+
schema: {
|
|
39
|
+
type: "object",
|
|
40
|
+
properties: {
|
|
41
|
+
queue: {
|
|
42
|
+
type: "string",
|
|
43
|
+
enum: ["billing", "reliability", "product", "security"],
|
|
44
|
+
},
|
|
45
|
+
severity: {
|
|
46
|
+
type: "string",
|
|
47
|
+
enum: ["low", "medium", "high"],
|
|
48
|
+
},
|
|
49
|
+
needsHumanReview: {
|
|
50
|
+
type: "boolean",
|
|
51
|
+
},
|
|
52
|
+
summary: {
|
|
53
|
+
type: "string",
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
required: ["queue", "severity", "needsHumanReview", "summary"],
|
|
57
|
+
additionalProperties: false,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
plugins: [{ id: "response-healing", mode: "strict" }],
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const result = await supportTriageAgent.run({
|
|
64
|
+
input: "Customer says webhook deliveries failed overnight and asks whether data was lost.",
|
|
65
|
+
client,
|
|
66
|
+
modelRetry: {
|
|
67
|
+
maxRetries: 2,
|
|
68
|
+
backoffMs: 250,
|
|
69
|
+
},
|
|
70
|
+
onEvent(event: { type: string; runId: string }) {
|
|
71
|
+
console.log(event.type, event.runId);
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
if (result.run.status === "waiting_for_human") {
|
|
76
|
+
console.log("Paused for approval:", result.run.pause);
|
|
77
|
+
|
|
78
|
+
const continued = await supportTriageAgent.continueRun({
|
|
79
|
+
run: result,
|
|
80
|
+
client,
|
|
81
|
+
humanInput: "Approved. Finalize the triage decision.",
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
console.log(continued.output);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log(result.output);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error instanceof AgentGatewayError) {
|
|
91
|
+
console.error("Gateway request failed", {
|
|
92
|
+
status: error.status,
|
|
93
|
+
requestId: error.requestId,
|
|
94
|
+
generationId: error.generationId,
|
|
95
|
+
reason: error.reason,
|
|
96
|
+
providerFailureDiagnostics: error.providerFailureDiagnostics,
|
|
97
|
+
routingDiagnostics: error.routingDiagnostics,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
void main();
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phaseo/agent-sdk",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
3
|
+
"description": "TypeScript SDK for building agentic applications on top of Phaseo Gateway",
|
|
4
|
+
"version": "0.1.2",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"private": false,
|
|
6
7
|
"license": "MIT",
|
|
7
8
|
"main": "./dist/index.js",
|
|
8
9
|
"module": "./dist/index.js",
|
|
@@ -15,16 +16,33 @@
|
|
|
15
16
|
},
|
|
16
17
|
"files": [
|
|
17
18
|
"dist",
|
|
18
|
-
"
|
|
19
|
+
"examples",
|
|
20
|
+
"README.md",
|
|
21
|
+
"SKILL.md"
|
|
19
22
|
],
|
|
23
|
+
"sideEffects": false,
|
|
20
24
|
"dependencies": {
|
|
21
|
-
"@
|
|
25
|
+
"@phaseo/sdk": "2.1.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^25.6.0",
|
|
29
|
+
"rimraf": "^6.0.0",
|
|
30
|
+
"typescript": "^6.0.2",
|
|
31
|
+
"vitest": "^4.1.7"
|
|
22
32
|
},
|
|
23
33
|
"repository": {
|
|
24
34
|
"type": "git",
|
|
25
|
-
"url": "
|
|
35
|
+
"url": "https://github.com/phaseoteam/Phaseo",
|
|
36
|
+
"directory": "packages/sdk/agent-sdk-ts"
|
|
26
37
|
},
|
|
27
38
|
"publishConfig": {
|
|
28
39
|
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
43
|
+
"build": "pnpm run clean && node ../sdk-ts/node_modules/typescript/bin/tsc -p tsconfig.build.json",
|
|
44
|
+
"typecheck": "node ../sdk-ts/node_modules/typescript/bin/tsc -p tsconfig.json --noEmit",
|
|
45
|
+
"test": "pnpm exec vitest run",
|
|
46
|
+
"pack:dry": "pnpm publish --dry-run --no-git-checks"
|
|
29
47
|
}
|
|
30
|
-
}
|
|
48
|
+
}
|