@2kw/ai 7.0.0-dev.9 → 7.1.0-dev.1
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 +1 -1
- package/dist/commands/analytics.js +1 -3
- package/dist/commands/responses.d.ts +3 -0
- package/dist/commands/responses.js +46 -0
- package/dist/index.js +2 -0
- package/dist/lib/client.js +2 -0
- package/dist/lib/errors.d.ts +3 -0
- package/dist/lib/errors.js +6 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -110,7 +110,7 @@ kubectl-style contexts switch between organizations and environments:
|
|
|
110
110
|
| `tracing` | Inspect request traces and tracing settings |
|
|
111
111
|
| `memory` | Your agent memory files (list, read, write, delete, forget); member totals and erasure for admins |
|
|
112
112
|
| `providers` | Manage BYOK AI providers |
|
|
113
|
-
| `analytics` | Usage analytics:
|
|
113
|
+
| `analytics` | Usage analytics: operations, tokens, quality, providers, errors |
|
|
114
114
|
| `billing` | Check subscription tier and usage limits |
|
|
115
115
|
| `agents` | Run agents and answer paused runs (approvals and relayed tool calls); apply, export and scaffold agent.yaml; manage versions, labels, approvals and tool catalogs |
|
|
116
116
|
| `skills` | Import and export SKILL.md bundles; manage skill versions and labels |
|
|
@@ -8,7 +8,7 @@ function addDateOptions(cmd) {
|
|
|
8
8
|
}
|
|
9
9
|
export function makeAnalyticsCommand() {
|
|
10
10
|
const cmd = new Command("analytics").description("Organization analytics");
|
|
11
|
-
const summary = new Command("summary").description("Cross-surface summary (total ops,
|
|
11
|
+
const summary = new Command("summary").description("Cross-surface summary (total ops, tokens, p95, per-surface breakdown)");
|
|
12
12
|
addDateOptions(summary);
|
|
13
13
|
summary.action(async (opts, command) => {
|
|
14
14
|
await runAction(command, async () => {
|
|
@@ -66,7 +66,6 @@ export function makeAnalyticsCommand() {
|
|
|
66
66
|
"successfulExtractions",
|
|
67
67
|
"successRate",
|
|
68
68
|
"totalTokens",
|
|
69
|
-
"totalCost",
|
|
70
69
|
"avgDurationMs",
|
|
71
70
|
]);
|
|
72
71
|
});
|
|
@@ -89,7 +88,6 @@ export function makeAnalyticsCommand() {
|
|
|
89
88
|
"successfulExtractions",
|
|
90
89
|
"successRate",
|
|
91
90
|
"totalTokens",
|
|
92
|
-
"totalCost",
|
|
93
91
|
"avgDurationMs",
|
|
94
92
|
]);
|
|
95
93
|
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { getClient, runAction } from "../lib/client.js";
|
|
3
|
+
import { isJsonOutput } from "../lib/config.js";
|
|
4
|
+
import { formatDetail, formatSuccess } from "../lib/output.js";
|
|
5
|
+
export function makeResponsesCommand() {
|
|
6
|
+
const cmd = new Command("responses").description("Read and cancel background responses (agent runs started with background: true)");
|
|
7
|
+
cmd
|
|
8
|
+
.command("get")
|
|
9
|
+
.description("Read a background response as it stands now: queued, in_progress, requires_action, completed, " +
|
|
10
|
+
"incomplete, failed or cancelled. Only background responses can be read by id.")
|
|
11
|
+
.argument("<responseId>", "Response ID")
|
|
12
|
+
.action(async (responseId, _opts, command) => {
|
|
13
|
+
await runAction(command, async () => {
|
|
14
|
+
const client = getClient(command);
|
|
15
|
+
const { data } = await client.GET("/v1/responses/{responseId}", {
|
|
16
|
+
params: { path: { responseId } },
|
|
17
|
+
});
|
|
18
|
+
formatDetail(data, command);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
cmd
|
|
22
|
+
.command("cancel")
|
|
23
|
+
.description("Cancel the background run whose newest response this is. A queued or paused run is cancelled at " +
|
|
24
|
+
"once; a running one stops at its next step. Only the caller that started the run can cancel it; " +
|
|
25
|
+
"an older response of the run is refused with a conflict that names the newest one.")
|
|
26
|
+
.argument("<responseId>", "Response ID")
|
|
27
|
+
.action(async (responseId, _opts, command) => {
|
|
28
|
+
await runAction(command, async () => {
|
|
29
|
+
const client = getClient(command);
|
|
30
|
+
const { data } = await client.POST("/v1/responses/{responseId}/cancel", {
|
|
31
|
+
params: { path: { responseId } },
|
|
32
|
+
});
|
|
33
|
+
const response = data;
|
|
34
|
+
if (isJsonOutput(command)) {
|
|
35
|
+
formatDetail(response, command);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const status = typeof response?.status === "string" ? response.status : undefined;
|
|
39
|
+
formatSuccess(status === "cancelled"
|
|
40
|
+
? `Response ${responseId} cancelled.`
|
|
41
|
+
: `Cancel requested for response ${responseId}; it stops at its next step (status: ${status ?? "unknown"}).`, command);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
return cmd;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=responses.js.map
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,7 @@ import { makeScoresCommand } from "./commands/scores.js";
|
|
|
28
28
|
import { makeQueuesCommand } from "./commands/queues.js";
|
|
29
29
|
import { makeAgentsCommand } from "./commands/agents.js";
|
|
30
30
|
import { makeConversationsCommand } from "./commands/conversations.js";
|
|
31
|
+
import { makeResponsesCommand } from "./commands/responses.js";
|
|
31
32
|
import { makeKnowledgeCommand } from "./commands/knowledge.js";
|
|
32
33
|
import { makeFilesCommand } from "./commands/files.js";
|
|
33
34
|
import { makeInstallationsCommand } from "./commands/installations.js";
|
|
@@ -68,6 +69,7 @@ program.addCommand(makeSettingsCommand());
|
|
|
68
69
|
program.addCommand(makeMemoryCommand());
|
|
69
70
|
program.addCommand(makeAgentsCommand());
|
|
70
71
|
program.addCommand(makeConversationsCommand());
|
|
72
|
+
program.addCommand(makeResponsesCommand());
|
|
71
73
|
program.addCommand(makeKnowledgeCommand());
|
|
72
74
|
program.addCommand(makeFilesCommand());
|
|
73
75
|
program.addCommand(makeInstallationsCommand());
|
package/dist/lib/client.js
CHANGED
|
@@ -39,6 +39,8 @@ export const errorMiddleware = {
|
|
|
39
39
|
code: typeof nested?.code === "string" ? nested.code : undefined,
|
|
40
40
|
// A problem detail names its cause in `errorCode` (GlobalExceptionHandler).
|
|
41
41
|
errorCode: typeof body.errorCode === "string" ? body.errorCode : undefined,
|
|
42
|
+
// A background run's 409 names its newest response, so the caller can poll it.
|
|
43
|
+
headResponseId: typeof nested?.head_response_id === "string" ? nested.head_response_id : undefined,
|
|
42
44
|
});
|
|
43
45
|
},
|
|
44
46
|
};
|
package/dist/lib/errors.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface ApiErrorBody {
|
|
|
15
15
|
* Kept apart from {@link code}: that one holds lowercase gateway codes and is printed by `--json`.
|
|
16
16
|
*/
|
|
17
17
|
errorCode?: string;
|
|
18
|
+
/** The background run's newest response, named by a 409 the run's state answers. */
|
|
19
|
+
headResponseId?: string;
|
|
18
20
|
}
|
|
19
21
|
export declare class BackboneApiError extends Error {
|
|
20
22
|
readonly status: number;
|
|
@@ -22,6 +24,7 @@ export declare class BackboneApiError extends Error {
|
|
|
22
24
|
readonly timestamp: string;
|
|
23
25
|
readonly code?: string;
|
|
24
26
|
readonly errorCode?: string;
|
|
27
|
+
readonly headResponseId?: string;
|
|
25
28
|
constructor(body: Omit<ApiErrorBody, "error"> & {
|
|
26
29
|
error: string;
|
|
27
30
|
});
|
package/dist/lib/errors.js
CHANGED
|
@@ -8,6 +8,7 @@ export class BackboneApiError extends Error {
|
|
|
8
8
|
timestamp;
|
|
9
9
|
code;
|
|
10
10
|
errorCode;
|
|
11
|
+
headResponseId;
|
|
11
12
|
constructor(body) {
|
|
12
13
|
super(body.message);
|
|
13
14
|
this.name = "BackboneApiError";
|
|
@@ -16,6 +17,7 @@ export class BackboneApiError extends Error {
|
|
|
16
17
|
this.timestamp = body.timestamp;
|
|
17
18
|
this.code = body.code;
|
|
18
19
|
this.errorCode = body.errorCode;
|
|
20
|
+
this.headResponseId = body.headResponseId;
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
23
|
/**
|
|
@@ -108,6 +110,9 @@ export function hintFor(err) {
|
|
|
108
110
|
if (err.code === "invalid_approval_decision" && /decided by a conversation grant/.test(err.message)) {
|
|
109
111
|
return "This request was already approved by a conversation grant; nothing to decide.";
|
|
110
112
|
}
|
|
113
|
+
if (err.headResponseId) {
|
|
114
|
+
return `The run's newest response is ${err.headResponseId}. Check it: 2kw responses get ${err.headResponseId}`;
|
|
115
|
+
}
|
|
111
116
|
if (err.code && CODE_HINTS[err.code])
|
|
112
117
|
return CODE_HINTS[err.code];
|
|
113
118
|
// The 403 whose cause is the credential, not the role (#805). Without this the
|
|
@@ -169,6 +174,7 @@ export function handleError(err, json) {
|
|
|
169
174
|
error: err.errorType,
|
|
170
175
|
status: err.status,
|
|
171
176
|
...(err.code ? { code: err.code } : {}),
|
|
177
|
+
...(err.headResponseId ? { head_response_id: err.headResponseId } : {}),
|
|
172
178
|
message: err.message,
|
|
173
179
|
timestamp: err.timestamp,
|
|
174
180
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@2kw/ai",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.1.0-dev.1",
|
|
4
4
|
"description": "CLI for 2kw.ai — schema-driven document extraction, an OpenAI-compatible EU LLM gateway, transcription, prompts, datasets, and experiments from your terminal or agentic workflows. Ships as 2kw, backbone, and bb.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|