@hasna/todos 0.15.52 → 0.17.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/CHANGELOG.md +1993 -0
- package/README.md +356 -42
- package/dist/ai-tools.d.ts.map +1 -1
- package/dist/ai.d.ts.map +1 -1
- package/dist/cli/cloud-router.d.ts +162 -72
- package/dist/cli/cloud-router.d.ts.map +1 -1
- package/dist/cli/commands/agent-commands.d.ts.map +1 -1
- package/dist/cli/commands/config-serve-commands.d.ts.map +1 -1
- package/dist/cli/commands/delegate.d.ts.map +1 -1
- package/dist/cli/commands/environment-snapshots.d.ts.map +1 -1
- package/dist/cli/commands/machines-api.d.ts +4 -0
- package/dist/cli/commands/machines-api.d.ts.map +1 -0
- package/dist/cli/commands/machines.d.ts.map +1 -1
- package/dist/cli/commands/mcp-hooks-commands.d.ts.map +1 -1
- package/dist/cli/commands/plan-commands.d.ts +3 -0
- package/dist/cli/commands/plan-commands.d.ts.map +1 -0
- package/dist/cli/commands/plan-template-commands.d.ts.map +1 -1
- package/dist/cli/commands/pr-group-commands.d.ts.map +1 -1
- package/dist/cli/commands/project-commands.d.ts.map +1 -1
- package/dist/cli/commands/query-commands.d.ts.map +1 -1
- package/dist/cli/commands/storage-commands.d.ts.map +1 -1
- package/dist/cli/commands/task-list-commands.d.ts +3 -0
- package/dist/cli/commands/task-list-commands.d.ts.map +1 -0
- package/dist/cli/commands/template-commands.d.ts +3 -0
- package/dist/cli/commands/template-commands.d.ts.map +1 -0
- package/dist/cli/helpers.d.ts.map +1 -1
- package/dist/cli/index.js +22072 -15949
- package/dist/cli/machine-api.d.ts +7 -0
- package/dist/cli/machine-api.d.ts.map +1 -0
- package/dist/cli/plan-read-api.d.ts +6 -0
- package/dist/cli/plan-read-api.d.ts.map +1 -0
- package/dist/cli/project-api.d.ts +119 -0
- package/dist/cli/project-api.d.ts.map +1 -0
- package/dist/cli/stage-a.d.ts +25 -5
- package/dist/cli/stage-a.d.ts.map +1 -1
- package/dist/cli/task-query-api.d.ts +21 -0
- package/dist/cli/task-query-api.d.ts.map +1 -0
- package/dist/cli/template-api.d.ts +7 -0
- package/dist/cli/template-api.d.ts.map +1 -0
- package/dist/cli/template-remote.d.ts +90 -0
- package/dist/cli/template-remote.d.ts.map +1 -0
- package/dist/cli-mcp-parity.d.ts.map +1 -1
- package/dist/contracts.js +908 -291
- package/dist/db/agents.d.ts +8 -0
- package/dist/db/agents.d.ts.map +1 -1
- package/dist/db/builtin-templates.d.ts +2 -33
- package/dist/db/builtin-templates.d.ts.map +1 -1
- package/dist/db/database.d.ts +6 -0
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/handoffs.d.ts.map +1 -1
- package/dist/db/identity-mapping.d.ts +25 -0
- package/dist/db/identity-mapping.d.ts.map +1 -1
- package/dist/db/machines.d.ts.map +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/plans.d.ts.map +1 -1
- package/dist/db/retrospectives.d.ts.map +1 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/task-crud.d.ts.map +1 -1
- package/dist/db/task-lists.d.ts.map +1 -1
- package/dist/db/task-runs.d.ts +2 -0
- package/dist/db/task-runs.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4341 -1756
- package/dist/lib/assignee-validation.d.ts.map +1 -1
- package/dist/lib/builtin-template-library.d.ts +32 -0
- package/dist/lib/builtin-template-library.d.ts.map +1 -0
- package/dist/lib/cli-reference.d.ts.map +1 -1
- package/dist/lib/config.d.ts +10 -13
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/db-backup.d.ts +1 -1
- package/dist/lib/db-backup.d.ts.map +1 -1
- package/dist/lib/env.d.ts +18 -0
- package/dist/lib/env.d.ts.map +1 -0
- package/dist/lib/environment-snapshots.d.ts.map +1 -1
- package/dist/lib/feature-manifest.d.ts.map +1 -1
- package/dist/lib/gatherer.d.ts.map +1 -1
- package/dist/lib/headless-boundaries.d.ts +4 -3
- package/dist/lib/headless-boundaries.d.ts.map +1 -1
- package/dist/lib/local-encryption.d.ts +12 -0
- package/dist/lib/local-encryption.d.ts.map +1 -1
- package/dist/lib/local-opt-in.d.ts +104 -0
- package/dist/lib/local-opt-in.d.ts.map +1 -0
- package/dist/lib/paths.d.ts +20 -1
- package/dist/lib/paths.d.ts.map +1 -1
- package/dist/lib/plan-artifacts.d.ts +1 -0
- package/dist/lib/plan-artifacts.d.ts.map +1 -1
- package/dist/lib/plan-client-boundary.d.ts +2 -0
- package/dist/lib/plan-client-boundary.d.ts.map +1 -0
- package/dist/lib/plan-schedule.d.ts +6 -0
- package/dist/lib/plan-schedule.d.ts.map +1 -0
- package/dist/lib/project-panel.d.ts +6 -0
- package/dist/lib/project-panel.d.ts.map +1 -1
- package/dist/lib/project-receipt.d.ts +3 -0
- package/dist/lib/project-receipt.d.ts.map +1 -0
- package/dist/lib/sandbox-profiles.d.ts.map +1 -1
- package/dist/lib/shared-plan-artifacts.d.ts +14 -0
- package/dist/lib/shared-plan-artifacts.d.ts.map +1 -0
- package/dist/lib/sync.d.ts.map +1 -1
- package/dist/lib/task-list-client-boundary.d.ts +3 -0
- package/dist/lib/task-list-client-boundary.d.ts.map +1 -0
- package/dist/lib/task-routing.d.ts.map +1 -1
- package/dist/lib/template-client-boundary.d.ts +2 -0
- package/dist/lib/template-client-boundary.d.ts.map +1 -0
- package/dist/mcp/index.d.ts +53 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +50124 -60838
- package/dist/mcp/plan-api.d.ts +6 -0
- package/dist/mcp/plan-api.d.ts.map +1 -0
- package/dist/mcp/remote-authority.d.ts +49 -0
- package/dist/mcp/remote-authority.d.ts.map +1 -0
- package/dist/mcp/task-coordination-api.d.ts +15 -0
- package/dist/mcp/task-coordination-api.d.ts.map +1 -0
- package/dist/mcp/task-list-api.d.ts +8 -0
- package/dist/mcp/task-list-api.d.ts.map +1 -0
- package/dist/mcp/token-utils.d.ts.map +1 -1
- package/dist/mcp/tools/agents.d.ts.map +1 -1
- package/dist/mcp/tools/environment-snapshots.d.ts.map +1 -1
- package/dist/mcp/tools/machines.d.ts.map +1 -1
- package/dist/mcp/tools/task-adv-tools.d.ts.map +1 -1
- package/dist/mcp/tools/task-auto-tools.d.ts.map +1 -1
- package/dist/mcp/tools/task-crud.d.ts.map +1 -1
- package/dist/mcp/tools/task-meta-tools.d.ts.map +1 -1
- package/dist/mcp/tools/task-project-tools.d.ts.map +1 -1
- package/dist/mcp/tools/task-resources.d.ts.map +1 -1
- package/dist/mcp/tools/templates.d.ts.map +1 -1
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +45 -19
- package/dist/project-registration.js +3349 -645
- package/dist/registry.js +909 -292
- package/dist/release-provenance.json +6 -6
- package/dist/sdk/client.d.ts +53 -4
- package/dist/sdk/client.d.ts.map +1 -1
- package/dist/sdk/index.d.ts +2 -0
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/index.js +1253 -1088
- package/dist/sdk/resolve.d.ts +101 -0
- package/dist/sdk/resolve.d.ts.map +1 -0
- package/dist/sdk/types.d.ts +17 -2
- package/dist/sdk/types.d.ts.map +1 -1
- package/dist/sdk/v1.generated.d.ts +334 -3
- package/dist/sdk/v1.generated.d.ts.map +1 -1
- package/dist/server/auth-posture.d.ts +66 -7
- package/dist/server/auth-posture.d.ts.map +1 -1
- package/dist/server/client-ip.d.ts +39 -0
- package/dist/server/client-ip.d.ts.map +1 -0
- package/dist/server/cloud.d.ts +2 -1
- package/dist/server/cloud.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +24758 -16687
- package/dist/server/openapi.d.ts +2514 -469
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/port.d.ts +2 -2
- package/dist/server/port.d.ts.map +1 -1
- package/dist/server/rate-limit-config.d.ts +6 -0
- package/dist/server/rate-limit-config.d.ts.map +1 -0
- package/dist/server/routes.d.ts +3 -6
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/serve.d.ts +2 -6
- package/dist/server/serve.d.ts.map +1 -1
- package/dist/server/v1.d.ts +3 -1
- package/dist/server/v1.d.ts.map +1 -1
- package/dist/storage/atomic-project-migration.d.ts +53 -0
- package/dist/storage/atomic-project-migration.d.ts.map +1 -0
- package/dist/storage/index.d.ts +4 -2
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/interfaces.d.ts +135 -3
- package/dist/storage/interfaces.d.ts.map +1 -1
- package/dist/storage/local-sqlite.d.ts.map +1 -1
- package/dist/storage/machine-registry.d.ts +36 -0
- package/dist/storage/machine-registry.d.ts.map +1 -0
- package/dist/storage/postgres-adapter.d.ts.map +1 -1
- package/dist/storage/postgres-sync.d.ts +2 -2
- package/dist/storage/postgres-sync.d.ts.map +1 -1
- package/dist/storage/run-artifact-creation-upload.d.ts +50 -0
- package/dist/storage/run-artifact-creation-upload.d.ts.map +1 -0
- package/dist/storage/s3-artifact-sync.d.ts +18 -0
- package/dist/storage/s3-artifact-sync.d.ts.map +1 -1
- package/dist/storage/sqlite-snapshot.d.ts +2 -0
- package/dist/storage/sqlite-snapshot.d.ts.map +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +3154 -350
- package/dist/task-manifest/postgres.d.ts +1 -1
- package/dist/task-manifest/sqlite.d.ts +1 -1
- package/dist/task-manifest.js +250 -73
- package/dist/task-subtree-transfer.js +198 -4
- package/dist/testing.d.ts +90 -29
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +34 -10
- package/dist/types/index.d.ts +43 -4
- package/dist/types/index.d.ts.map +1 -1
- package/docs/PLAN_API.md +93 -0
- package/docs/TASK_LIST_API.md +58 -0
- package/docs/TASK_QUERY_API.md +14 -0
- package/docs/TEMPLATE_API.md +18 -0
- package/docs/native-storage.md +405 -0
- package/package.json +18 -15
- package/postinstall.js +52 -1
- package/dashboard/dist/assets/index-BNQ4gJua.js +0 -342
- package/dashboard/dist/assets/index-DjzvHUWt.css +0 -1
- package/dashboard/dist/index.html +0 -13
- package/dashboard/dist/logo.jpg +0 -0
- package/dist/mcp/tools/code-tools.d.ts +0 -15
- package/dist/mcp/tools/code-tools.d.ts.map +0 -1
package/dist/sdk/index.js
CHANGED
|
@@ -52,1292 +52,1456 @@ class TodosTimeoutError extends Error {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
// src/
|
|
56
|
-
import {
|
|
57
|
-
|
|
55
|
+
// src/sdk/resolve.ts
|
|
56
|
+
import {
|
|
57
|
+
ClientTransportConfigurationError,
|
|
58
|
+
resolveClientTransport,
|
|
59
|
+
resolveCredential
|
|
60
|
+
} from "@hasna/contracts/client";
|
|
58
61
|
|
|
59
|
-
// src/
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// node_modules/.bun/@hasna+paths@0.1.0/node_modules/@hasna/paths/dist/index.js
|
|
69
|
-
import { homedir } from "os";
|
|
70
|
-
import { join } from "path";
|
|
71
|
-
var KIND_ENV = {
|
|
72
|
-
config: "HASNA_CONFIG_HOME",
|
|
73
|
-
data: "HASNA_DATA_HOME",
|
|
74
|
-
state: "HASNA_STATE_HOME",
|
|
75
|
-
cache: "HASNA_CACHE_HOME"
|
|
76
|
-
};
|
|
77
|
-
var APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
78
|
-
function assertApp(app) {
|
|
79
|
-
if (typeof app !== "string" || app.length === 0) {
|
|
80
|
-
throw new TypeError("paths: app must be a non-empty string");
|
|
81
|
-
}
|
|
82
|
-
if (!APP_SLUG_RE.test(app)) {
|
|
83
|
-
throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
function envOf(options) {
|
|
87
|
-
return options.env ?? process.env;
|
|
88
|
-
}
|
|
89
|
-
function envValue(options, kind) {
|
|
90
|
-
const value = envOf(options)[KIND_ENV[kind]];
|
|
91
|
-
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
92
|
-
}
|
|
93
|
-
function isMacOS(platform) {
|
|
94
|
-
return platform === "darwin";
|
|
95
|
-
}
|
|
96
|
-
function baseDir(kind, options) {
|
|
97
|
-
const override = envValue(options, kind);
|
|
98
|
-
if (override)
|
|
99
|
-
return override;
|
|
100
|
-
const home = options.home ?? homedir();
|
|
101
|
-
const platform = options.platform ?? process.platform;
|
|
102
|
-
if (isMacOS(platform)) {
|
|
103
|
-
switch (kind) {
|
|
104
|
-
case "config":
|
|
105
|
-
case "data":
|
|
106
|
-
return join(home, "Library", "Application Support", "Hasna");
|
|
107
|
-
case "cache":
|
|
108
|
-
return join(home, "Library", "Caches", "Hasna");
|
|
109
|
-
case "state":
|
|
110
|
-
return join(home, "Library", "Logs", "Hasna");
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
switch (kind) {
|
|
114
|
-
case "config":
|
|
115
|
-
return join(home, ".config", "hasna");
|
|
116
|
-
case "data":
|
|
117
|
-
return join(home, ".local", "share", "hasna");
|
|
118
|
-
case "state":
|
|
119
|
-
return join(home, ".local", "state", "hasna");
|
|
120
|
-
case "cache":
|
|
121
|
-
return join(home, ".cache", "hasna");
|
|
62
|
+
// src/project-registration/types.ts
|
|
63
|
+
class TodosProjectRegistrationError extends Error {
|
|
64
|
+
code;
|
|
65
|
+
details;
|
|
66
|
+
constructor(code, message, details = {}) {
|
|
67
|
+
super(message);
|
|
68
|
+
this.code = code;
|
|
69
|
+
this.details = details;
|
|
70
|
+
this.name = "TodosProjectRegistrationError";
|
|
122
71
|
}
|
|
123
72
|
}
|
|
124
|
-
function resolvePath(kind, options) {
|
|
125
|
-
assertApp(options.app);
|
|
126
|
-
const appSegment = options.internal === true ? join("internal", options.app) : options.app;
|
|
127
|
-
return join(baseDir(kind, options), appSegment);
|
|
128
|
-
}
|
|
129
|
-
function dataDir(options) {
|
|
130
|
-
return resolvePath("data", options);
|
|
131
|
-
}
|
|
132
73
|
|
|
133
|
-
// src/
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
return existsSync(join2(resolved, "todos.db")) || existsSync(join2(resolved, "config.json"));
|
|
74
|
+
// src/project-registration/adoption-validation.ts
|
|
75
|
+
var VALIDATION_KEYS = [
|
|
76
|
+
"valid",
|
|
77
|
+
"resource_kind",
|
|
78
|
+
"target_id",
|
|
79
|
+
"source_receipt_id",
|
|
80
|
+
"accepted_receipt_id",
|
|
81
|
+
"source_outcome",
|
|
82
|
+
"created_at",
|
|
83
|
+
"current_revision",
|
|
84
|
+
"accepted_result_digest"
|
|
85
|
+
];
|
|
86
|
+
function isRecord(value) {
|
|
87
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
148
88
|
}
|
|
149
|
-
function
|
|
150
|
-
|
|
151
|
-
return resolve(adoptResolverHome(resolved, env) ? resolved : legacyHomeDir(env));
|
|
89
|
+
function isNonEmptyString(value) {
|
|
90
|
+
return typeof value === "string" && value.length > 0;
|
|
152
91
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return
|
|
92
|
+
function hasExactKeys(value, expected) {
|
|
93
|
+
const actual = Object.keys(value).sort();
|
|
94
|
+
const wanted = [...expected].sort();
|
|
95
|
+
return actual.length === wanted.length && actual.every((key, index) => key === wanted[index]);
|
|
157
96
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
return getTodosDir();
|
|
97
|
+
function adoptionRejected(message) {
|
|
98
|
+
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_ADOPTION_REJECTED", `TODOS_PROJECT_REGISTRATION_ADOPTION_REJECTED: ${message}`);
|
|
161
99
|
}
|
|
162
|
-
function
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
100
|
+
function assertTodosPriorRegistrationAdoptionValidationEnvelope(value, input) {
|
|
101
|
+
if (!isRecord(input) || !hasExactKeys(input, [
|
|
102
|
+
"source_request",
|
|
103
|
+
"source_receipt",
|
|
104
|
+
"current_record"
|
|
105
|
+
])) {
|
|
106
|
+
adoptionRejected("prior-adoption validation input is incomplete");
|
|
167
107
|
}
|
|
108
|
+
const request = input["source_request"];
|
|
109
|
+
const receipt = input["source_receipt"];
|
|
110
|
+
const current = input["current_record"];
|
|
111
|
+
if (!isRecord(request) || !isRecord(receipt) || !isRecord(current)) {
|
|
112
|
+
adoptionRejected("prior-adoption validation input records are incomplete");
|
|
113
|
+
}
|
|
114
|
+
const resourceKind = request["resource_kind"];
|
|
115
|
+
const sourceOutcome = receipt["outcome"];
|
|
116
|
+
const acceptedReceiptId = sourceOutcome === "accepted" ? receipt["receipt_id"] : sourceOutcome === "duplicate_of_accepted" ? receipt["duplicate_of_receipt_id"] : null;
|
|
117
|
+
if (resourceKind !== "project" && resourceKind !== "task_list" || request["direction"] !== "forward" || sourceOutcome !== "accepted" && sourceOutcome !== "duplicate_of_accepted" || !isNonEmptyString(acceptedReceiptId) || !isNonEmptyString(receipt["receipt_id"]) || !isNonEmptyString(receipt["target_id"]) || !isNonEmptyString(receipt["result_revision"]) || !isNonEmptyString(receipt["result_digest"]) || !isNonEmptyString(current["id"]) || !isNonEmptyString(current["created_at"]) || !isNonEmptyString(current["updated_at"]) || receipt["authority"] !== "todos" || receipt["route"] !== request["authority_route"] || receipt["package_version"] !== request["package_version"] || receipt["authority_id"] !== request["authority_id"] || receipt["tenant_id"] !== request["tenant_id"] || receipt["corpus_id"] !== request["corpus_id"] || receipt["operation_id"] !== request["operation_id"] || receipt["step_id"] !== request["step_id"] || receipt["resource_kind"] !== resourceKind || receipt["direction"] !== "forward" || receipt["idempotency_key"] !== request["idempotency_key"] || receipt["request_digest"] !== request["request_digest"] || receipt["precondition_digest"] !== request["precondition_digest"] || receipt["accepted_receipt_id"] !== null || receipt["target_id"] !== current["id"] || receipt["result_revision"] !== current["created_at"]) {
|
|
118
|
+
adoptionRejected("prior-adoption validation input does not carry one complete accepted receipt and current target incarnation");
|
|
119
|
+
}
|
|
120
|
+
if (sourceOutcome === "accepted" && receipt["duplicate_of_receipt_id"] !== null || sourceOutcome === "duplicate_of_accepted" && receipt["duplicate_of_receipt_id"] !== acceptedReceiptId) {
|
|
121
|
+
adoptionRejected("prior-adoption validation source receipt lineage is incomplete");
|
|
122
|
+
}
|
|
123
|
+
if (!isRecord(value) || !hasExactKeys(value, ["validation"]) || !isRecord(value["validation"]) || !hasExactKeys(value["validation"], VALIDATION_KEYS)) {
|
|
124
|
+
adoptionRejected("prior-adoption validation response envelope is incomplete");
|
|
125
|
+
}
|
|
126
|
+
const validation = value["validation"];
|
|
127
|
+
if (validation["valid"] !== true || validation["resource_kind"] !== resourceKind || validation["target_id"] !== current["id"] || validation["source_receipt_id"] !== receipt["receipt_id"] || validation["accepted_receipt_id"] !== acceptedReceiptId || validation["source_outcome"] !== sourceOutcome || validation["created_at"] !== current["created_at"] || validation["current_revision"] !== current["updated_at"] || validation["accepted_result_digest"] !== receipt["result_digest"]) {
|
|
128
|
+
adoptionRejected("prior-adoption validation response does not prove the exact accepted receipt and current target");
|
|
129
|
+
}
|
|
130
|
+
return validation;
|
|
168
131
|
}
|
|
169
132
|
|
|
170
|
-
// src/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
cached = {};
|
|
180
|
-
return cached;
|
|
181
|
-
}
|
|
182
|
-
const config = readJsonFile(getConfigPath()) || {};
|
|
183
|
-
if (typeof config.sync_agents === "string") {
|
|
184
|
-
config.sync_agents = config.sync_agents.split(",").map((a) => a.trim()).filter(Boolean);
|
|
185
|
-
}
|
|
186
|
-
cached = config;
|
|
187
|
-
return cached;
|
|
188
|
-
}
|
|
189
|
-
function normalizeApiUrl(value) {
|
|
190
|
-
const trimmed = value?.trim();
|
|
191
|
-
if (!trimmed)
|
|
192
|
-
return null;
|
|
193
|
-
return trimmed.replace(/\/+$/, "");
|
|
194
|
-
}
|
|
195
|
-
function getLocalApiConfig(env = process.env) {
|
|
196
|
-
const config = loadConfig();
|
|
197
|
-
const envApiUrl = normalizeApiUrl(env["TODOS_URL"]);
|
|
198
|
-
const configApiUrl = normalizeApiUrl(config.apiUrl);
|
|
199
|
-
const apiUrl = envApiUrl ?? configApiUrl;
|
|
200
|
-
const apiKey = env["TODOS_API_KEY"] || config.apiKey || null;
|
|
201
|
-
return {
|
|
202
|
-
apiUrl,
|
|
203
|
-
apiKey,
|
|
204
|
-
source: {
|
|
205
|
-
apiUrl: envApiUrl ? "TODOS_URL" : configApiUrl ? "config" : "none",
|
|
206
|
-
apiKey: env["TODOS_API_KEY"] ? "TODOS_API_KEY" : config.apiKey ? "config" : "none"
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// src/sdk/client.ts
|
|
212
|
-
function buildQuery(params) {
|
|
213
|
-
const search = new URLSearchParams;
|
|
214
|
-
for (const [k, v] of Object.entries(params)) {
|
|
215
|
-
if (v !== undefined)
|
|
216
|
-
search.set(k, Array.isArray(v) ? v.join(",") : String(v));
|
|
133
|
+
// src/sdk/v1.generated.ts
|
|
134
|
+
class ApiError extends Error {
|
|
135
|
+
status;
|
|
136
|
+
body;
|
|
137
|
+
constructor(status, message, body) {
|
|
138
|
+
super(message);
|
|
139
|
+
this.status = status;
|
|
140
|
+
this.body = body;
|
|
141
|
+
this.name = "ApiError";
|
|
217
142
|
}
|
|
218
|
-
const s = search.toString();
|
|
219
|
-
return s ? `?${s}` : "";
|
|
220
143
|
}
|
|
221
144
|
|
|
222
|
-
class
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
145
|
+
class TodosV1Client {
|
|
146
|
+
baseUrl;
|
|
147
|
+
apiKey;
|
|
148
|
+
fetchImpl;
|
|
149
|
+
baseHeaders;
|
|
150
|
+
constructor(options) {
|
|
151
|
+
if (!options.baseUrl)
|
|
152
|
+
throw new Error("TodosV1Client requires a baseUrl.");
|
|
153
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
154
|
+
this.apiKey = options.apiKey;
|
|
155
|
+
this.fetchImpl = options.fetch ?? globalThis.fetch;
|
|
156
|
+
this.baseHeaders = options.headers ?? {};
|
|
226
157
|
}
|
|
227
|
-
async
|
|
228
|
-
|
|
158
|
+
async request(method, path, opts) {
|
|
159
|
+
const url = new URL(this.baseUrl + path);
|
|
160
|
+
if (opts.query) {
|
|
161
|
+
for (const [key, value] of Object.entries(opts.query)) {
|
|
162
|
+
if (value === undefined || value === null)
|
|
163
|
+
continue;
|
|
164
|
+
if (Array.isArray(value)) {
|
|
165
|
+
for (const item of value) {
|
|
166
|
+
if (item !== undefined && item !== null)
|
|
167
|
+
url.searchParams.append(key, String(item));
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
url.searchParams.set(key, String(value));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const headers = { Accept: "application/json", ...this.baseHeaders, ...opts.init?.headers };
|
|
175
|
+
if (this.apiKey)
|
|
176
|
+
headers["x-api-key"] = this.apiKey;
|
|
177
|
+
let payload;
|
|
178
|
+
if (opts.body !== undefined) {
|
|
179
|
+
headers["Content-Type"] = "application/json";
|
|
180
|
+
payload = JSON.stringify(opts.body);
|
|
181
|
+
}
|
|
182
|
+
const response = await this.fetchImpl(url.toString(), { ...opts.init, method, headers, body: payload });
|
|
183
|
+
const text = await response.text();
|
|
184
|
+
const data = text ? (() => {
|
|
185
|
+
try {
|
|
186
|
+
return JSON.parse(text);
|
|
187
|
+
} catch {
|
|
188
|
+
return text;
|
|
189
|
+
}
|
|
190
|
+
})() : undefined;
|
|
191
|
+
if (!response.ok) {
|
|
192
|
+
throw new ApiError(response.status, `${method} ${path} failed: ${response.status}`, data);
|
|
193
|
+
}
|
|
194
|
+
return data;
|
|
229
195
|
}
|
|
230
|
-
async
|
|
231
|
-
return this.
|
|
196
|
+
async listRecentActivity(query, init) {
|
|
197
|
+
return this.request("GET", `/v1/activity`, {
|
|
198
|
+
body: undefined,
|
|
199
|
+
query,
|
|
200
|
+
init
|
|
201
|
+
});
|
|
232
202
|
}
|
|
233
|
-
async
|
|
234
|
-
return this.
|
|
203
|
+
async listAgents(query, init) {
|
|
204
|
+
return this.request("GET", `/v1/agents`, {
|
|
205
|
+
body: undefined,
|
|
206
|
+
query,
|
|
207
|
+
init
|
|
208
|
+
});
|
|
235
209
|
}
|
|
236
|
-
async
|
|
237
|
-
return this.
|
|
210
|
+
async listDependencies(query, init) {
|
|
211
|
+
return this.request("GET", `/v1/dependencies`, {
|
|
212
|
+
body: undefined,
|
|
213
|
+
query,
|
|
214
|
+
init
|
|
215
|
+
});
|
|
238
216
|
}
|
|
239
|
-
async
|
|
240
|
-
|
|
217
|
+
async importSnapshot(body, init) {
|
|
218
|
+
if (body.machines !== undefined && !Array.isArray(body.machines))
|
|
219
|
+
throw new Error("Invalid machine snapshot array; no snapshot was posted");
|
|
220
|
+
if (body.machines?.length) {
|
|
221
|
+
let capability;
|
|
222
|
+
try {
|
|
223
|
+
capability = await this.listMachines(init);
|
|
224
|
+
} catch {
|
|
225
|
+
throw new Error("REMOTE_API_INCOMPATIBLE: machine import requires an upgraded Todos server; no snapshot was posted");
|
|
226
|
+
}
|
|
227
|
+
if (capability?.schema_version !== 2 || !Array.isArray(capability.machines) || !capability.authority || typeof capability.authority.tenant_id !== "string" || !capability.authority.tenant_id || typeof capability.authority.kid !== "string" || !capability.authority.kid)
|
|
228
|
+
throw new Error("REMOTE_API_INCOMPATIBLE: machine registry capability is missing; no snapshot was posted");
|
|
229
|
+
if (body.expected_machine_authority && (body.expected_machine_authority.kid !== capability.authority.kid || body.expected_machine_authority.tenant_id !== capability.authority.tenant_id))
|
|
230
|
+
throw new Error("Machine migration authority changed before POST; no snapshot was posted");
|
|
231
|
+
body = { ...body, expected_machine_authority: { ...capability.authority } };
|
|
232
|
+
}
|
|
233
|
+
const result = await this.request("POST", `/v1/import`, {
|
|
234
|
+
body,
|
|
235
|
+
query: undefined,
|
|
236
|
+
init
|
|
237
|
+
});
|
|
238
|
+
if (body.machines?.length && (result.machine_authority?.kid !== body.expected_machine_authority?.kid || result.machine_authority?.tenant_id !== body.expected_machine_authority?.tenant_id))
|
|
239
|
+
throw new Error("Machine receipt authority changed; preserve the source and inspect before retrying");
|
|
240
|
+
return result;
|
|
241
241
|
}
|
|
242
|
-
async
|
|
243
|
-
return this.
|
|
242
|
+
async listMachines(init) {
|
|
243
|
+
return this.request("GET", `/v1/machines`, {
|
|
244
|
+
body: undefined,
|
|
245
|
+
query: undefined,
|
|
246
|
+
init
|
|
247
|
+
});
|
|
244
248
|
}
|
|
245
|
-
async
|
|
246
|
-
return this.
|
|
249
|
+
async mutateMachineRegistry(body, init) {
|
|
250
|
+
return this.request("POST", `/v1/machines`, {
|
|
251
|
+
body,
|
|
252
|
+
query: undefined,
|
|
253
|
+
init
|
|
254
|
+
});
|
|
247
255
|
}
|
|
248
|
-
async
|
|
249
|
-
return this.
|
|
256
|
+
async listPlans(query, init) {
|
|
257
|
+
return this.request("GET", `/v1/plans`, {
|
|
258
|
+
body: undefined,
|
|
259
|
+
query,
|
|
260
|
+
init
|
|
261
|
+
});
|
|
250
262
|
}
|
|
251
|
-
async
|
|
252
|
-
return this.
|
|
263
|
+
async createPlan(body, init) {
|
|
264
|
+
return this.request("POST", `/v1/plans`, {
|
|
265
|
+
body,
|
|
266
|
+
query: undefined,
|
|
267
|
+
init
|
|
268
|
+
});
|
|
253
269
|
}
|
|
254
|
-
async
|
|
255
|
-
return this.
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
270
|
+
async getPlan(id, init) {
|
|
271
|
+
return this.request("GET", `/v1/plans/${encodeURIComponent(String(id))}`, {
|
|
272
|
+
body: undefined,
|
|
273
|
+
query: undefined,
|
|
274
|
+
init
|
|
259
275
|
});
|
|
260
276
|
}
|
|
261
|
-
async
|
|
262
|
-
return this.
|
|
277
|
+
async deletePlan(id, init) {
|
|
278
|
+
return this.request("DELETE", `/v1/plans/${encodeURIComponent(String(id))}`, {
|
|
279
|
+
body: undefined,
|
|
280
|
+
query: undefined,
|
|
281
|
+
init
|
|
282
|
+
});
|
|
263
283
|
}
|
|
264
|
-
async
|
|
265
|
-
return this.
|
|
284
|
+
async updatePlan(id, body, init) {
|
|
285
|
+
return this.request("PATCH", `/v1/plans/${encodeURIComponent(String(id))}`, {
|
|
286
|
+
body,
|
|
287
|
+
query: undefined,
|
|
288
|
+
init
|
|
289
|
+
});
|
|
266
290
|
}
|
|
267
|
-
async
|
|
268
|
-
return this.
|
|
291
|
+
async listPlanComments(id, query, init) {
|
|
292
|
+
return this.request("GET", `/v1/plans/${encodeURIComponent(String(id))}/comments`, {
|
|
293
|
+
body: undefined,
|
|
294
|
+
query,
|
|
295
|
+
init
|
|
296
|
+
});
|
|
269
297
|
}
|
|
270
|
-
async
|
|
271
|
-
return this.
|
|
298
|
+
async deletePlanPreserving(id, body, init) {
|
|
299
|
+
return this.request("POST", `/v1/plans/${encodeURIComponent(String(id))}/delete-preserving`, {
|
|
300
|
+
body,
|
|
301
|
+
query: undefined,
|
|
302
|
+
init
|
|
303
|
+
});
|
|
272
304
|
}
|
|
273
|
-
async
|
|
274
|
-
return this.
|
|
305
|
+
async planPlanProjectLink(id, query, init) {
|
|
306
|
+
return this.request("GET", `/v1/plans/${encodeURIComponent(String(id))}/project-link`, {
|
|
307
|
+
body: undefined,
|
|
308
|
+
query,
|
|
309
|
+
init
|
|
310
|
+
});
|
|
275
311
|
}
|
|
276
|
-
async
|
|
277
|
-
return this.
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
async changedSince(since, projectId, options) {
|
|
283
|
-
return this.client._get("/api/tasks/changed", buildQuery({ since, project_id: projectId, fields: options?.fields }));
|
|
312
|
+
async applyPlanProjectLink(id, body, init) {
|
|
313
|
+
return this.request("POST", `/v1/plans/${encodeURIComponent(String(id))}/project-link`, {
|
|
314
|
+
body,
|
|
315
|
+
query: undefined,
|
|
316
|
+
init
|
|
317
|
+
});
|
|
284
318
|
}
|
|
285
|
-
async
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
fields: options?.fields
|
|
319
|
+
async rollbackPlanProjectLink(id, body, init) {
|
|
320
|
+
return this.request("POST", `/v1/plans/${encodeURIComponent(String(id))}/project-link/rollback`, {
|
|
321
|
+
body,
|
|
322
|
+
query: undefined,
|
|
323
|
+
init
|
|
291
324
|
});
|
|
292
|
-
const url = `${this.client.baseUrl}/api/tasks/context${q}`;
|
|
293
|
-
const res = await this.client._fetchRaw(url);
|
|
294
|
-
if (!res.ok)
|
|
295
|
-
return options?.format === "json" ? {} : "";
|
|
296
|
-
if (options?.format === "json")
|
|
297
|
-
return res.json();
|
|
298
|
-
return res.text();
|
|
299
325
|
}
|
|
300
|
-
async
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if (options?.format === "csv")
|
|
307
|
-
return res.text();
|
|
308
|
-
return res.json();
|
|
326
|
+
async admitPrGroup(body, init) {
|
|
327
|
+
return this.request("POST", `/v1/pr-groups/admit`, {
|
|
328
|
+
body,
|
|
329
|
+
query: undefined,
|
|
330
|
+
init
|
|
331
|
+
});
|
|
309
332
|
}
|
|
310
|
-
async
|
|
311
|
-
return this.
|
|
333
|
+
async getPrGroupState(id, init) {
|
|
334
|
+
return this.request("GET", `/v1/pr-groups/${encodeURIComponent(String(id))}`, {
|
|
335
|
+
body: undefined,
|
|
336
|
+
query: undefined,
|
|
337
|
+
init
|
|
338
|
+
});
|
|
312
339
|
}
|
|
313
|
-
async
|
|
314
|
-
return this.
|
|
340
|
+
async getPrGroupEvents(id, query, init) {
|
|
341
|
+
return this.request("GET", `/v1/pr-groups/${encodeURIComponent(String(id))}/events`, {
|
|
342
|
+
body: undefined,
|
|
343
|
+
query,
|
|
344
|
+
init
|
|
345
|
+
});
|
|
315
346
|
}
|
|
316
|
-
async
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
347
|
+
async appendPrGroupEvent(id, body, init) {
|
|
348
|
+
return this.request("POST", `/v1/pr-groups/${encodeURIComponent(String(id))}/events`, {
|
|
349
|
+
body,
|
|
350
|
+
query: undefined,
|
|
351
|
+
init
|
|
321
352
|
});
|
|
322
|
-
const url = `${this.client.baseUrl}/api/tasks/stream${q}`;
|
|
323
|
-
const resp = await this.client._fetchRaw(url);
|
|
324
|
-
if (!resp.ok || !resp.body)
|
|
325
|
-
throw new Error(`SSE connection failed: ${resp.status}`);
|
|
326
|
-
const reader = resp.body.getReader();
|
|
327
|
-
const decoder = new TextDecoder;
|
|
328
|
-
let buffer = "";
|
|
329
|
-
try {
|
|
330
|
-
while (true) {
|
|
331
|
-
const { done, value } = await reader.read();
|
|
332
|
-
if (done)
|
|
333
|
-
break;
|
|
334
|
-
buffer += decoder.decode(value, { stream: true });
|
|
335
|
-
const lines = buffer.split(`
|
|
336
|
-
`);
|
|
337
|
-
buffer = lines.pop() || "";
|
|
338
|
-
for (const line of lines) {
|
|
339
|
-
if (line.startsWith("data: ")) {
|
|
340
|
-
try {
|
|
341
|
-
const data = JSON.parse(line.slice(6));
|
|
342
|
-
if (data.type !== "connected")
|
|
343
|
-
yield data;
|
|
344
|
-
} catch {}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
} finally {
|
|
349
|
-
reader.releaseLock();
|
|
350
|
-
}
|
|
351
353
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
354
|
+
async recoverPrGroup(id, body, init) {
|
|
355
|
+
return this.request("POST", `/v1/pr-groups/${encodeURIComponent(String(id))}/recover`, {
|
|
356
|
+
body,
|
|
357
|
+
query: undefined,
|
|
358
|
+
init
|
|
359
|
+
});
|
|
358
360
|
}
|
|
359
|
-
async
|
|
360
|
-
return this.
|
|
361
|
+
async getAtomicProjectMigrationCapability(init) {
|
|
362
|
+
return this.request("GET", `/v1/project-migrations`, {
|
|
363
|
+
body: undefined,
|
|
364
|
+
query: undefined,
|
|
365
|
+
init
|
|
366
|
+
});
|
|
361
367
|
}
|
|
362
|
-
async
|
|
363
|
-
return this.
|
|
368
|
+
async importAtomicProjectSnapshot(body, init) {
|
|
369
|
+
return this.request("POST", `/v1/project-migrations`, {
|
|
370
|
+
body,
|
|
371
|
+
query: undefined,
|
|
372
|
+
init
|
|
373
|
+
});
|
|
364
374
|
}
|
|
365
|
-
async
|
|
366
|
-
return this.
|
|
375
|
+
async getProjectRegistrationCapability(init) {
|
|
376
|
+
return this.request("GET", `/v1/project-registration/capability`, {
|
|
377
|
+
body: undefined,
|
|
378
|
+
query: undefined,
|
|
379
|
+
init
|
|
380
|
+
});
|
|
367
381
|
}
|
|
368
|
-
async
|
|
369
|
-
return this.
|
|
382
|
+
async compensateProjectRegistrationResource(body, init) {
|
|
383
|
+
return this.request("POST", `/v1/project-registration/compensate`, {
|
|
384
|
+
body,
|
|
385
|
+
query: undefined,
|
|
386
|
+
init
|
|
387
|
+
});
|
|
370
388
|
}
|
|
371
|
-
async
|
|
372
|
-
return this.
|
|
389
|
+
async createProjectRegistrationResource(body, init) {
|
|
390
|
+
return this.request("POST", `/v1/project-registration/create`, {
|
|
391
|
+
body,
|
|
392
|
+
query: undefined,
|
|
393
|
+
init
|
|
394
|
+
});
|
|
373
395
|
}
|
|
374
|
-
async
|
|
375
|
-
return this.
|
|
396
|
+
async readExactProjectRegistrationResource(body, init) {
|
|
397
|
+
return this.request("POST", `/v1/project-registration/read-exact`, {
|
|
398
|
+
body,
|
|
399
|
+
query: undefined,
|
|
400
|
+
init
|
|
401
|
+
});
|
|
376
402
|
}
|
|
377
|
-
async
|
|
378
|
-
return this.
|
|
403
|
+
async lookupProjectRegistrationReceipt(body, init) {
|
|
404
|
+
return this.request("POST", `/v1/project-registration/receipts/lookup`, {
|
|
405
|
+
body,
|
|
406
|
+
query: undefined,
|
|
407
|
+
init
|
|
408
|
+
});
|
|
379
409
|
}
|
|
380
|
-
async
|
|
381
|
-
return this.
|
|
410
|
+
async listProjectRegistrationResources(query, init) {
|
|
411
|
+
return this.request("GET", `/v1/project-registration/resources`, {
|
|
412
|
+
body: undefined,
|
|
413
|
+
query,
|
|
414
|
+
init
|
|
415
|
+
});
|
|
382
416
|
}
|
|
383
|
-
async
|
|
384
|
-
|
|
417
|
+
async validatePriorRegistrationAdoption(body, init) {
|
|
418
|
+
const response = await this.request("POST", `/v1/project-registration/validate-prior-adoption`, {
|
|
419
|
+
body,
|
|
420
|
+
query: undefined,
|
|
421
|
+
init
|
|
422
|
+
});
|
|
423
|
+
return {
|
|
424
|
+
validation: assertTodosPriorRegistrationAdoptionValidationEnvelope(response, body)
|
|
425
|
+
};
|
|
385
426
|
}
|
|
386
|
-
async
|
|
387
|
-
return this.
|
|
427
|
+
async verifyInverseProjectRegistrationResource(body, init) {
|
|
428
|
+
return this.request("POST", `/v1/project-registration/verify-inverse`, {
|
|
429
|
+
body,
|
|
430
|
+
query: undefined,
|
|
431
|
+
init
|
|
432
|
+
});
|
|
388
433
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
434
|
+
async listProjects(init) {
|
|
435
|
+
return this.request("GET", `/v1/projects`, {
|
|
436
|
+
body: undefined,
|
|
437
|
+
query: undefined,
|
|
438
|
+
init
|
|
439
|
+
});
|
|
395
440
|
}
|
|
396
|
-
async
|
|
397
|
-
return this.
|
|
441
|
+
async createProject(body, init) {
|
|
442
|
+
return this.request("POST", `/v1/projects`, {
|
|
443
|
+
body,
|
|
444
|
+
query: undefined,
|
|
445
|
+
init
|
|
446
|
+
});
|
|
398
447
|
}
|
|
399
|
-
async
|
|
400
|
-
return this.
|
|
448
|
+
async getProject(id, init) {
|
|
449
|
+
return this.request("GET", `/v1/projects/${encodeURIComponent(String(id))}`, {
|
|
450
|
+
body: undefined,
|
|
451
|
+
query: undefined,
|
|
452
|
+
init
|
|
453
|
+
});
|
|
401
454
|
}
|
|
402
|
-
async
|
|
403
|
-
return this.
|
|
455
|
+
async deleteProject(id, init) {
|
|
456
|
+
return this.request("DELETE", `/v1/projects/${encodeURIComponent(String(id))}`, {
|
|
457
|
+
body: undefined,
|
|
458
|
+
query: undefined,
|
|
459
|
+
init
|
|
460
|
+
});
|
|
404
461
|
}
|
|
405
|
-
async
|
|
406
|
-
return this.
|
|
462
|
+
async updateProject(id, body, init) {
|
|
463
|
+
return this.request("PATCH", `/v1/projects/${encodeURIComponent(String(id))}`, {
|
|
464
|
+
body,
|
|
465
|
+
query: undefined,
|
|
466
|
+
init
|
|
467
|
+
});
|
|
407
468
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
469
|
+
async deleteProjectPreserving(id, body, init) {
|
|
470
|
+
return this.request("POST", `/v1/projects/${encodeURIComponent(String(id))}/delete-preserving`, {
|
|
471
|
+
body,
|
|
472
|
+
query: undefined,
|
|
473
|
+
init
|
|
474
|
+
});
|
|
414
475
|
}
|
|
415
|
-
async
|
|
416
|
-
return this.
|
|
476
|
+
async renameProject(id, body, init) {
|
|
477
|
+
return this.request("POST", `/v1/projects/${encodeURIComponent(String(id))}/rename`, {
|
|
478
|
+
body,
|
|
479
|
+
query: undefined,
|
|
480
|
+
init
|
|
481
|
+
});
|
|
417
482
|
}
|
|
418
|
-
async
|
|
419
|
-
return this.
|
|
483
|
+
async planProjectTaskListEnsure(id, init) {
|
|
484
|
+
return this.request("GET", `/v1/projects/${encodeURIComponent(String(id))}/task-list/ensure`, {
|
|
485
|
+
body: undefined,
|
|
486
|
+
query: undefined,
|
|
487
|
+
init
|
|
488
|
+
});
|
|
420
489
|
}
|
|
421
|
-
async
|
|
422
|
-
return this.
|
|
490
|
+
async ensureProjectTaskList(id, body, init) {
|
|
491
|
+
return this.request("POST", `/v1/projects/${encodeURIComponent(String(id))}/task-list/ensure`, {
|
|
492
|
+
body,
|
|
493
|
+
query: undefined,
|
|
494
|
+
init
|
|
495
|
+
});
|
|
423
496
|
}
|
|
424
|
-
async
|
|
425
|
-
return this.
|
|
497
|
+
async rollbackProjectTaskListEnsure(id, body, init) {
|
|
498
|
+
return this.request("POST", `/v1/projects/${encodeURIComponent(String(id))}/task-list/rollback`, {
|
|
499
|
+
body,
|
|
500
|
+
query: undefined,
|
|
501
|
+
init
|
|
502
|
+
});
|
|
426
503
|
}
|
|
427
|
-
async
|
|
428
|
-
return this.
|
|
504
|
+
async findTaskGitRefs(ref, init) {
|
|
505
|
+
return this.request("GET", `/v1/refs/${encodeURIComponent(String(ref))}`, {
|
|
506
|
+
body: undefined,
|
|
507
|
+
query: undefined,
|
|
508
|
+
init
|
|
509
|
+
});
|
|
429
510
|
}
|
|
430
|
-
async
|
|
431
|
-
return this.
|
|
511
|
+
async getStats(init) {
|
|
512
|
+
return this.request("GET", `/v1/stats`, {
|
|
513
|
+
body: undefined,
|
|
514
|
+
query: undefined,
|
|
515
|
+
init
|
|
516
|
+
});
|
|
432
517
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
518
|
+
async listTaskLists(query, init) {
|
|
519
|
+
return this.request("GET", `/v1/task-lists`, {
|
|
520
|
+
body: undefined,
|
|
521
|
+
query,
|
|
522
|
+
init
|
|
523
|
+
});
|
|
439
524
|
}
|
|
440
|
-
async
|
|
441
|
-
return this.
|
|
525
|
+
async createTaskList(body, init) {
|
|
526
|
+
return this.request("POST", `/v1/task-lists`, {
|
|
527
|
+
body,
|
|
528
|
+
query: undefined,
|
|
529
|
+
init
|
|
530
|
+
});
|
|
442
531
|
}
|
|
443
|
-
async
|
|
444
|
-
return this.
|
|
532
|
+
async getTaskList(id, init) {
|
|
533
|
+
return this.request("GET", `/v1/task-lists/${encodeURIComponent(String(id))}`, {
|
|
534
|
+
body: undefined,
|
|
535
|
+
query: undefined,
|
|
536
|
+
init
|
|
537
|
+
});
|
|
445
538
|
}
|
|
446
|
-
async
|
|
447
|
-
return this.
|
|
539
|
+
async deleteTaskList(id, init) {
|
|
540
|
+
return this.request("DELETE", `/v1/task-lists/${encodeURIComponent(String(id))}`, {
|
|
541
|
+
body: undefined,
|
|
542
|
+
query: undefined,
|
|
543
|
+
init
|
|
544
|
+
});
|
|
448
545
|
}
|
|
449
|
-
async
|
|
450
|
-
return this.
|
|
546
|
+
async updateTaskList(id, body, init) {
|
|
547
|
+
return this.request("PATCH", `/v1/task-lists/${encodeURIComponent(String(id))}`, {
|
|
548
|
+
body,
|
|
549
|
+
query: undefined,
|
|
550
|
+
init
|
|
551
|
+
});
|
|
451
552
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
553
|
+
async deleteTaskListPreserving(id, body, init) {
|
|
554
|
+
return this.request("POST", `/v1/task-lists/${encodeURIComponent(String(id))}/delete-preserving`, {
|
|
555
|
+
body,
|
|
556
|
+
query: undefined,
|
|
557
|
+
init
|
|
558
|
+
});
|
|
458
559
|
}
|
|
459
|
-
async
|
|
460
|
-
return this.
|
|
560
|
+
async applyTaskManifest(body, init) {
|
|
561
|
+
return this.request("POST", `/v1/task-manifest/apply`, {
|
|
562
|
+
body,
|
|
563
|
+
query: undefined,
|
|
564
|
+
init
|
|
565
|
+
});
|
|
461
566
|
}
|
|
462
|
-
async
|
|
463
|
-
return this.
|
|
567
|
+
async lookupTaskManifestBinding(body, init) {
|
|
568
|
+
return this.request("POST", `/v1/task-manifest/bindings/lookup`, {
|
|
569
|
+
body,
|
|
570
|
+
query: undefined,
|
|
571
|
+
init
|
|
572
|
+
});
|
|
464
573
|
}
|
|
465
|
-
async
|
|
466
|
-
return this.
|
|
574
|
+
async getTaskManifestCapability(init) {
|
|
575
|
+
return this.request("GET", `/v1/task-manifest/capability`, {
|
|
576
|
+
body: undefined,
|
|
577
|
+
query: undefined,
|
|
578
|
+
init
|
|
579
|
+
});
|
|
467
580
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
581
|
+
async compensateTaskManifest(body, init) {
|
|
582
|
+
return this.request("POST", `/v1/task-manifest/compensate`, {
|
|
583
|
+
body,
|
|
584
|
+
query: undefined,
|
|
585
|
+
init
|
|
586
|
+
});
|
|
474
587
|
}
|
|
475
|
-
async
|
|
476
|
-
return this.
|
|
588
|
+
async readExactTaskManifest(body, init) {
|
|
589
|
+
return this.request("POST", `/v1/task-manifest/read-exact`, {
|
|
590
|
+
body,
|
|
591
|
+
query: undefined,
|
|
592
|
+
init
|
|
593
|
+
});
|
|
477
594
|
}
|
|
478
|
-
async
|
|
479
|
-
return this.
|
|
595
|
+
async applyTaskSubtreeTransfer(body, init) {
|
|
596
|
+
return this.request("POST", `/v1/task-subtree-transfer/apply`, {
|
|
597
|
+
body,
|
|
598
|
+
query: undefined,
|
|
599
|
+
init
|
|
600
|
+
});
|
|
480
601
|
}
|
|
481
|
-
async
|
|
482
|
-
return this.
|
|
602
|
+
async getTaskSubtreeTransferCapability(init) {
|
|
603
|
+
return this.request("GET", `/v1/task-subtree-transfer/capability`, {
|
|
604
|
+
body: undefined,
|
|
605
|
+
query: undefined,
|
|
606
|
+
init
|
|
607
|
+
});
|
|
483
608
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
609
|
+
async inspectTaskSubtreeTransfer(body, init) {
|
|
610
|
+
return this.request("POST", `/v1/task-subtree-transfer/inspect`, {
|
|
611
|
+
body,
|
|
612
|
+
query: undefined,
|
|
613
|
+
init
|
|
614
|
+
});
|
|
490
615
|
}
|
|
491
|
-
async
|
|
492
|
-
return this.
|
|
616
|
+
async readExactTaskSubtreeTransfer(body, init) {
|
|
617
|
+
return this.request("POST", `/v1/task-subtree-transfer/read-exact`, {
|
|
618
|
+
body,
|
|
619
|
+
query: undefined,
|
|
620
|
+
init
|
|
621
|
+
});
|
|
493
622
|
}
|
|
494
|
-
async
|
|
495
|
-
|
|
496
|
-
|
|
623
|
+
async rollbackTaskSubtreeTransfer(body, init) {
|
|
624
|
+
return this.request("POST", `/v1/task-subtree-transfer/rollback`, {
|
|
625
|
+
body,
|
|
626
|
+
query: undefined,
|
|
627
|
+
init
|
|
628
|
+
});
|
|
497
629
|
}
|
|
498
|
-
async
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
630
|
+
async listTasks(query, init) {
|
|
631
|
+
return this.request("GET", `/v1/tasks`, {
|
|
632
|
+
body: undefined,
|
|
633
|
+
query,
|
|
634
|
+
init
|
|
635
|
+
});
|
|
504
636
|
}
|
|
505
|
-
async
|
|
506
|
-
return this.
|
|
637
|
+
async createTask(body, init) {
|
|
638
|
+
return this.request("POST", `/v1/tasks`, {
|
|
639
|
+
body,
|
|
640
|
+
query: undefined,
|
|
641
|
+
init
|
|
642
|
+
});
|
|
507
643
|
}
|
|
508
|
-
async
|
|
509
|
-
return this.
|
|
644
|
+
async bulkCreateTasks(body, init) {
|
|
645
|
+
return this.request("POST", `/v1/tasks/bulk-create`, {
|
|
646
|
+
body,
|
|
647
|
+
query: undefined,
|
|
648
|
+
init
|
|
649
|
+
});
|
|
510
650
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
maxRetries;
|
|
518
|
-
retryDelay;
|
|
519
|
-
tasks;
|
|
520
|
-
agents;
|
|
521
|
-
projects;
|
|
522
|
-
plans;
|
|
523
|
-
orgs;
|
|
524
|
-
webhooks;
|
|
525
|
-
templates;
|
|
526
|
-
prGroups;
|
|
527
|
-
constructor(options = {}) {
|
|
528
|
-
const localConfig = getLocalApiConfig();
|
|
529
|
-
this.baseUrl = normalizeApiUrl(options.baseUrl) || localConfig.apiUrl || "http://localhost:19427";
|
|
530
|
-
this.timeout = options.timeout ?? 1e4;
|
|
531
|
-
this.apiKey = options.apiKey || localConfig.apiKey;
|
|
532
|
-
this.maxRetries = options.maxRetries ?? 0;
|
|
533
|
-
this.retryDelay = options.retryDelay ?? 1000;
|
|
534
|
-
this.tasks = new TasksResource(this);
|
|
535
|
-
this.agents = new AgentsResource(this);
|
|
536
|
-
this.projects = new ProjectsResource(this);
|
|
537
|
-
this.plans = new PlansResource(this);
|
|
538
|
-
this.orgs = new OrgsResource(this);
|
|
539
|
-
this.webhooks = new WebhooksResource(this);
|
|
540
|
-
this.templates = new TemplatesResource(this);
|
|
541
|
-
this.prGroups = new PrGroupsResource(this);
|
|
651
|
+
async bulkDeleteTasks(body, init) {
|
|
652
|
+
return this.request("POST", `/v1/tasks/bulk-delete`, {
|
|
653
|
+
body,
|
|
654
|
+
query: undefined,
|
|
655
|
+
init
|
|
656
|
+
});
|
|
542
657
|
}
|
|
543
|
-
|
|
544
|
-
return
|
|
658
|
+
async getTask(id, init) {
|
|
659
|
+
return this.request("GET", `/v1/tasks/${encodeURIComponent(String(id))}`, {
|
|
660
|
+
body: undefined,
|
|
661
|
+
query: undefined,
|
|
662
|
+
init
|
|
663
|
+
});
|
|
545
664
|
}
|
|
546
|
-
async
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
} finally {
|
|
553
|
-
clearTimeout(timer);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
_buildHeaders(existing) {
|
|
557
|
-
const headers = { "Content-Type": "application/json" };
|
|
558
|
-
if (this.apiKey)
|
|
559
|
-
headers["x-api-key"] = this.apiKey;
|
|
560
|
-
if (existing) {
|
|
561
|
-
if (existing instanceof Headers) {
|
|
562
|
-
existing.forEach((v, k) => {
|
|
563
|
-
headers[k] = v;
|
|
564
|
-
});
|
|
565
|
-
} else if (Array.isArray(existing)) {
|
|
566
|
-
for (const [k, v] of existing)
|
|
567
|
-
headers[k] = v;
|
|
568
|
-
} else {
|
|
569
|
-
Object.assign(headers, existing);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
return headers;
|
|
573
|
-
}
|
|
574
|
-
async _fetchWithRetry(path, init) {
|
|
575
|
-
let lastError = null;
|
|
576
|
-
const maxAttempts = this.maxRetries + 1;
|
|
577
|
-
for (let attempt = 0;attempt < maxAttempts; attempt++) {
|
|
578
|
-
try {
|
|
579
|
-
return await this._fetch(path, init);
|
|
580
|
-
} catch (e) {
|
|
581
|
-
lastError = e;
|
|
582
|
-
if (e instanceof TodosAPIError && e.status < 500 && e.status !== 429)
|
|
583
|
-
throw e;
|
|
584
|
-
if (e instanceof TodosUnauthorizedError || e instanceof TodosNotFoundError || e instanceof TodosConflictError)
|
|
585
|
-
throw e;
|
|
586
|
-
if (attempt < maxAttempts - 1) {
|
|
587
|
-
const delay = this.retryDelay * Math.pow(2, attempt);
|
|
588
|
-
if (e instanceof TodosRateLimitError) {
|
|
589
|
-
await this._sleep(e.retryAfter * 1000);
|
|
590
|
-
} else {
|
|
591
|
-
await this._sleep(delay);
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
throw lastError || new Error("Request failed after retries");
|
|
597
|
-
}
|
|
598
|
-
async _fetch(path, init) {
|
|
599
|
-
const controller = new AbortController;
|
|
600
|
-
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
601
|
-
try {
|
|
602
|
-
const url = `${this.baseUrl}${path}`;
|
|
603
|
-
const headers = this._buildHeaders(init?.headers);
|
|
604
|
-
const res = await fetch(url, { ...init, headers, signal: controller.signal });
|
|
605
|
-
if (!res.ok) {
|
|
606
|
-
const body = await res.json().catch(() => ({ error: res.statusText }));
|
|
607
|
-
const message = body.error || `HTTP ${res.status}: ${res.statusText}`;
|
|
608
|
-
if (res.status === 401)
|
|
609
|
-
throw new TodosUnauthorizedError(message, body);
|
|
610
|
-
if (res.status === 404)
|
|
611
|
-
throw new TodosNotFoundError(message, body);
|
|
612
|
-
if (res.status === 409)
|
|
613
|
-
throw new TodosConflictError(message, body);
|
|
614
|
-
if (res.status === 429) {
|
|
615
|
-
const retryAfter = parseInt(res.headers.get("retry-after") || "60", 10);
|
|
616
|
-
throw new TodosRateLimitError(message, retryAfter, body);
|
|
617
|
-
}
|
|
618
|
-
throw new TodosAPIError(message, res.status, res.statusText, body);
|
|
619
|
-
}
|
|
620
|
-
if (res.status === 204)
|
|
621
|
-
return null;
|
|
622
|
-
const text = await res.text();
|
|
623
|
-
if (text.length === 0)
|
|
624
|
-
return null;
|
|
625
|
-
return JSON.parse(text);
|
|
626
|
-
} catch (e) {
|
|
627
|
-
if (e instanceof DOMException && e.name === "AbortError") {
|
|
628
|
-
throw new TodosTimeoutError(this.timeout);
|
|
629
|
-
}
|
|
630
|
-
throw e;
|
|
631
|
-
} finally {
|
|
632
|
-
clearTimeout(timer);
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
async _get(path, query = "") {
|
|
636
|
-
return this._fetchWithRetry(`${path}${query}`);
|
|
665
|
+
async deleteTask(id, init) {
|
|
666
|
+
return this.request("DELETE", `/v1/tasks/${encodeURIComponent(String(id))}`, {
|
|
667
|
+
body: undefined,
|
|
668
|
+
query: undefined,
|
|
669
|
+
init
|
|
670
|
+
});
|
|
637
671
|
}
|
|
638
|
-
async
|
|
639
|
-
return this.
|
|
640
|
-
|
|
641
|
-
|
|
672
|
+
async updateTask(id, body, init) {
|
|
673
|
+
return this.request("PATCH", `/v1/tasks/${encodeURIComponent(String(id))}`, {
|
|
674
|
+
body,
|
|
675
|
+
query: undefined,
|
|
676
|
+
init
|
|
642
677
|
});
|
|
643
678
|
}
|
|
644
|
-
async
|
|
645
|
-
return this.
|
|
646
|
-
|
|
647
|
-
|
|
679
|
+
async listTaskComments(id, query, init) {
|
|
680
|
+
return this.request("GET", `/v1/tasks/${encodeURIComponent(String(id))}/comments`, {
|
|
681
|
+
body: undefined,
|
|
682
|
+
query,
|
|
683
|
+
init
|
|
648
684
|
});
|
|
649
685
|
}
|
|
650
|
-
async
|
|
651
|
-
return this.
|
|
686
|
+
async createTaskComment(id, body, init) {
|
|
687
|
+
return this.request("POST", `/v1/tasks/${encodeURIComponent(String(id))}/comments`, {
|
|
688
|
+
body,
|
|
689
|
+
query: undefined,
|
|
690
|
+
init
|
|
691
|
+
});
|
|
652
692
|
}
|
|
653
|
-
|
|
654
|
-
return
|
|
693
|
+
async completeTask(id, body, init) {
|
|
694
|
+
return this.request("POST", `/v1/tasks/${encodeURIComponent(String(id))}/complete`, {
|
|
695
|
+
body,
|
|
696
|
+
query: undefined,
|
|
697
|
+
init
|
|
698
|
+
});
|
|
655
699
|
}
|
|
656
|
-
async
|
|
657
|
-
return this.
|
|
700
|
+
async failTask(id, body, init) {
|
|
701
|
+
return this.request("POST", `/v1/tasks/${encodeURIComponent(String(id))}/fail`, {
|
|
702
|
+
body,
|
|
703
|
+
query: undefined,
|
|
704
|
+
init
|
|
705
|
+
});
|
|
658
706
|
}
|
|
659
|
-
async
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
}
|
|
707
|
+
async listTaskHistory(id, query, init) {
|
|
708
|
+
return this.request("GET", `/v1/tasks/${encodeURIComponent(String(id))}/history`, {
|
|
709
|
+
body: undefined,
|
|
710
|
+
query,
|
|
711
|
+
init
|
|
712
|
+
});
|
|
666
713
|
}
|
|
667
|
-
async
|
|
668
|
-
return this.
|
|
714
|
+
async listTaskGitRefs(id, init) {
|
|
715
|
+
return this.request("GET", `/v1/tasks/${encodeURIComponent(String(id))}/refs`, {
|
|
716
|
+
body: undefined,
|
|
717
|
+
query: undefined,
|
|
718
|
+
init
|
|
719
|
+
});
|
|
669
720
|
}
|
|
670
|
-
async
|
|
671
|
-
return this.
|
|
721
|
+
async linkTaskGitRef(id, body, init) {
|
|
722
|
+
return this.request("POST", `/v1/tasks/${encodeURIComponent(String(id))}/refs`, {
|
|
723
|
+
body,
|
|
724
|
+
query: undefined,
|
|
725
|
+
init
|
|
726
|
+
});
|
|
672
727
|
}
|
|
673
|
-
async
|
|
674
|
-
return this.
|
|
728
|
+
async handoffStaleTaskLock(id, body, init) {
|
|
729
|
+
return this.request("POST", `/v1/tasks/${encodeURIComponent(String(id))}/stale-lock-handoff`, {
|
|
730
|
+
body,
|
|
731
|
+
query: undefined,
|
|
732
|
+
init
|
|
733
|
+
});
|
|
675
734
|
}
|
|
676
|
-
async
|
|
677
|
-
return this.
|
|
735
|
+
async startTask(id, init) {
|
|
736
|
+
return this.request("POST", `/v1/tasks/${encodeURIComponent(String(id))}/start`, {
|
|
737
|
+
body: undefined,
|
|
738
|
+
query: undefined,
|
|
739
|
+
init
|
|
740
|
+
});
|
|
678
741
|
}
|
|
679
|
-
async
|
|
680
|
-
return this.
|
|
742
|
+
async listTemplates(query, init) {
|
|
743
|
+
return this.request("GET", `/v1/templates`, {
|
|
744
|
+
body: undefined,
|
|
745
|
+
query,
|
|
746
|
+
init
|
|
747
|
+
});
|
|
681
748
|
}
|
|
682
|
-
async
|
|
683
|
-
return this.
|
|
749
|
+
async createTemplate(body, init) {
|
|
750
|
+
return this.request("POST", `/v1/templates`, {
|
|
751
|
+
body,
|
|
752
|
+
query: undefined,
|
|
753
|
+
init
|
|
754
|
+
});
|
|
684
755
|
}
|
|
685
|
-
async
|
|
686
|
-
return this.
|
|
756
|
+
async initializeTemplates(body, init) {
|
|
757
|
+
return this.request("POST", `/v1/templates/initialize`, {
|
|
758
|
+
body,
|
|
759
|
+
query: undefined,
|
|
760
|
+
init
|
|
761
|
+
});
|
|
687
762
|
}
|
|
688
|
-
async
|
|
689
|
-
return this.
|
|
763
|
+
async getTemplate(id, init) {
|
|
764
|
+
return this.request("GET", `/v1/templates/${encodeURIComponent(String(id))}`, {
|
|
765
|
+
body: undefined,
|
|
766
|
+
query: undefined,
|
|
767
|
+
init
|
|
768
|
+
});
|
|
690
769
|
}
|
|
691
|
-
async
|
|
692
|
-
|
|
770
|
+
async deleteTemplate(id, init) {
|
|
771
|
+
return this.request("DELETE", `/v1/templates/${encodeURIComponent(String(id))}`, {
|
|
772
|
+
body: undefined,
|
|
773
|
+
query: undefined,
|
|
774
|
+
init
|
|
775
|
+
});
|
|
693
776
|
}
|
|
694
|
-
async
|
|
695
|
-
return this.
|
|
777
|
+
async updateTemplate(id, body, init) {
|
|
778
|
+
return this.request("PATCH", `/v1/templates/${encodeURIComponent(String(id))}`, {
|
|
779
|
+
body,
|
|
780
|
+
query: undefined,
|
|
781
|
+
init
|
|
782
|
+
});
|
|
696
783
|
}
|
|
697
|
-
async
|
|
698
|
-
return this.
|
|
784
|
+
async getTemplateHistory(id, init) {
|
|
785
|
+
return this.request("GET", `/v1/templates/${encodeURIComponent(String(id))}/history`, {
|
|
786
|
+
body: undefined,
|
|
787
|
+
query: undefined,
|
|
788
|
+
init
|
|
789
|
+
});
|
|
699
790
|
}
|
|
700
|
-
|
|
701
|
-
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// src/lib/local-opt-in.ts
|
|
794
|
+
import {
|
|
795
|
+
clientTransportEnvKeys,
|
|
796
|
+
credentialOverrideEnvKey,
|
|
797
|
+
credentialPointerEnvKey,
|
|
798
|
+
CREDENTIAL_PROFILE_ENV_KEY
|
|
799
|
+
} from "@hasna/contracts/client";
|
|
800
|
+
var TODOS_LOCAL_OPT_IN_ENV_KEYS = ["HASNA_TODOS_LOCAL", "TODOS_LOCAL"];
|
|
801
|
+
function isTodosLocalOptIn(env = process.env) {
|
|
802
|
+
return TODOS_LOCAL_OPT_IN_ENV_KEYS.some((key) => (env[key] ?? "").trim() !== "");
|
|
803
|
+
}
|
|
804
|
+
function todosAuthorityEnvKeys() {
|
|
805
|
+
const keys = clientTransportEnvKeys("todos");
|
|
806
|
+
return [
|
|
807
|
+
...keys.apiUrlKeys,
|
|
808
|
+
...keys.apiKeyKeys,
|
|
809
|
+
credentialOverrideEnvKey("todos"),
|
|
810
|
+
credentialPointerEnvKey("todos"),
|
|
811
|
+
CREDENTIAL_PROFILE_ENV_KEY
|
|
812
|
+
];
|
|
813
|
+
}
|
|
814
|
+
function hasTodosEnvAuthorityIntent(env = process.env) {
|
|
815
|
+
return todosAuthorityEnvKeys().some((key) => (env[key] ?? "").trim() !== "");
|
|
816
|
+
}
|
|
817
|
+
function selectsTodosLocalStore(env = process.env) {
|
|
818
|
+
return !hasTodosEnvAuthorityIntent(env) && isTodosLocalOptIn(env);
|
|
819
|
+
}
|
|
820
|
+
function todosResolverEnv(env) {
|
|
821
|
+
const blanks = todosAuthorityEnvKeys().filter((key) => (key in env) && (env[key] ?? "").trim() === "");
|
|
822
|
+
if (blanks.length === 0)
|
|
823
|
+
return env;
|
|
824
|
+
const next = { ...env };
|
|
825
|
+
for (const key of blanks)
|
|
826
|
+
delete next[key];
|
|
827
|
+
return next;
|
|
828
|
+
}
|
|
829
|
+
var CONTRACTS_AMBIENT_ENVIRONMENT = Symbol.for("hasna:contracts:ambientClientEnvironment");
|
|
830
|
+
function isAmbientTodosEnv(env) {
|
|
831
|
+
if (typeof process !== "undefined" && env === process.env)
|
|
832
|
+
return true;
|
|
833
|
+
return env[CONTRACTS_AMBIENT_ENVIRONMENT] === true;
|
|
834
|
+
}
|
|
835
|
+
function todosResolverInputs(env, credentials = {}) {
|
|
836
|
+
const normalised = todosResolverEnv(env);
|
|
837
|
+
if (normalised === env)
|
|
838
|
+
return { env: normalised, credentials };
|
|
839
|
+
const keychain = { ...credentials.keychain };
|
|
840
|
+
if (keychain.enabled === undefined && keychain.run === undefined) {
|
|
841
|
+
keychain.enabled = isAmbientTodosEnv(env);
|
|
842
|
+
}
|
|
843
|
+
return { env: normalised, credentials: { ...credentials, keychain } };
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// src/sdk/resolve.ts
|
|
847
|
+
var TODOS_LOCAL_SERVE_URL = "http://localhost:19427";
|
|
848
|
+
var TODOS_CREDENTIAL_MISSING_MESSAGE = "TODOS_CREDENTIAL_MISSING: no Hasna Todos credential resolved. Looked at " + "HASNA_TODOS_API_KEY_OVERRIDE / HASNA_PROFILE / HASNA_TODOS_API_KEY_REF, the Keychain item " + "hasna.credentials.todos.api-key, ~/.hasna/todos/config/credentials, then HASNA_TODOS_API_KEY. " + "There is no local fallback: the on-box todos-serve is opt-in only (HASNA_TODOS_LOCAL=1, alias " + "TODOS_LOCAL=1) and is disabled by default \u2014 failing closed.";
|
|
849
|
+
var localNoticePrinted = false;
|
|
850
|
+
function __resetTodosSdkLocalNotice() {
|
|
851
|
+
localNoticePrinted = false;
|
|
852
|
+
}
|
|
853
|
+
function stripV1(baseUrl) {
|
|
854
|
+
return baseUrl.replace(/\/+$/, "").replace(/\/v1$/, "");
|
|
855
|
+
}
|
|
856
|
+
function announceLocal(notice) {
|
|
857
|
+
if (localNoticePrinted)
|
|
858
|
+
return;
|
|
859
|
+
localNoticePrinted = true;
|
|
860
|
+
const line = `todos: LOCAL mode \u2014 HASNA_TODOS_LOCAL is set and nothing configures a Todos authority; reading and ` + `writing the local todos-serve at ${TODOS_LOCAL_SERVE_URL}, not the hosted fleet. Unset it, and ` + `provide a credential via the Keychain item hasna.credentials.todos.api-key, ` + `~/.hasna/todos/config/credentials, or HASNA_TODOS_API_KEY, to work against https://api.hasna.com/todos.`;
|
|
861
|
+
if (notice)
|
|
862
|
+
notice(line);
|
|
863
|
+
else if (typeof process !== "undefined")
|
|
864
|
+
process.stderr.write(`${line}
|
|
865
|
+
`);
|
|
866
|
+
}
|
|
867
|
+
function resolveTodosSdkTransport(options = {}) {
|
|
868
|
+
const rawEnv = options.env ?? (typeof process !== "undefined" ? process.env : {});
|
|
869
|
+
const requestedCredentials = {
|
|
870
|
+
...options.credentials,
|
|
871
|
+
...options.apiKey !== undefined ? { apiKey: options.apiKey } : {}
|
|
872
|
+
};
|
|
873
|
+
const { env, credentials } = todosResolverInputs(rawEnv, requestedCredentials);
|
|
874
|
+
if (options.baseUrl) {
|
|
875
|
+
return {
|
|
876
|
+
mode: "http",
|
|
877
|
+
baseUrl: stripV1(options.baseUrl),
|
|
878
|
+
apiKey: options.apiKey ?? null,
|
|
879
|
+
apiKeySource: options.apiKey ? "explicit apiKey argument" : null,
|
|
880
|
+
apiUrlSource: "explicit baseUrl argument"
|
|
881
|
+
};
|
|
702
882
|
}
|
|
703
|
-
|
|
704
|
-
|
|
883
|
+
if (selectsTodosLocalStore(env)) {
|
|
884
|
+
announceLocal(options.notice);
|
|
885
|
+
return {
|
|
886
|
+
mode: "local-serve",
|
|
887
|
+
baseUrl: TODOS_LOCAL_SERVE_URL,
|
|
888
|
+
apiKey: options.apiKey ?? null,
|
|
889
|
+
apiKeySource: options.apiKey ? "explicit apiKey argument" : null,
|
|
890
|
+
apiUrlSource: "local-serve"
|
|
891
|
+
};
|
|
705
892
|
}
|
|
706
|
-
|
|
707
|
-
|
|
893
|
+
const credential = resolveCredential("todos", env, credentials);
|
|
894
|
+
const chainOptions = {
|
|
895
|
+
credentials: credential ? { ...credentials, apiKey: credential.apiKey } : credentials
|
|
896
|
+
};
|
|
897
|
+
let resolution;
|
|
898
|
+
try {
|
|
899
|
+
resolution = resolveClientTransport("todos", env, chainOptions);
|
|
900
|
+
} catch (error) {
|
|
901
|
+
if (error instanceof ClientTransportConfigurationError && /is not set and no API key could be resolved/.test(error.message)) {
|
|
902
|
+
throw new Error(`${TODOS_CREDENTIAL_MISSING_MESSAGE} ${error.message}`, { cause: error });
|
|
903
|
+
}
|
|
904
|
+
throw error;
|
|
708
905
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
906
|
+
return {
|
|
907
|
+
mode: "http",
|
|
908
|
+
baseUrl: stripV1(resolution.baseUrl),
|
|
909
|
+
apiKey: credential ? credential.apiKey : null,
|
|
910
|
+
apiKeySource: credential ? credential.source : resolution.apiKeySource,
|
|
911
|
+
apiUrlSource: resolution.apiUrlSource ?? "default"
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
function createTodosV1Client(options = {}) {
|
|
915
|
+
const resolved = resolveTodosSdkTransport(options);
|
|
916
|
+
if (resolved.mode !== "http" || !resolved.apiKey) {
|
|
917
|
+
throw new Error(`${TODOS_CREDENTIAL_MISSING_MESSAGE} The /v1 client is hosted-only: the local opt-in does not apply to it.`);
|
|
918
|
+
}
|
|
919
|
+
const baseFetch = options.fetch ?? ((input, init) => fetch(input, init));
|
|
920
|
+
const refreshOptions = { ...options, notice: () => {} };
|
|
921
|
+
const fetchWithFreshCredential = (input, init) => {
|
|
922
|
+
const headers = {};
|
|
923
|
+
new Headers(init?.headers ?? {}).forEach((value, key) => {
|
|
924
|
+
headers[key] = value;
|
|
925
|
+
});
|
|
926
|
+
try {
|
|
927
|
+
const fresh = resolveTodosSdkTransport(refreshOptions).apiKey;
|
|
928
|
+
if (fresh)
|
|
929
|
+
headers["x-api-key"] = fresh;
|
|
930
|
+
} catch {}
|
|
931
|
+
return baseFetch(input, { ...init, headers });
|
|
932
|
+
};
|
|
933
|
+
return new TodosV1Client({
|
|
934
|
+
baseUrl: resolved.baseUrl,
|
|
935
|
+
apiKey: resolved.apiKey,
|
|
936
|
+
fetch: fetchWithFreshCredential,
|
|
937
|
+
...options.headers ? { headers: options.headers } : {}
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
// src/sdk/client.ts
|
|
942
|
+
function buildQuery(params) {
|
|
943
|
+
const search = new URLSearchParams;
|
|
944
|
+
for (const [k, v] of Object.entries(params)) {
|
|
945
|
+
if (v !== undefined)
|
|
946
|
+
search.set(k, Array.isArray(v) ? v.join(",") : String(v));
|
|
715
947
|
}
|
|
716
|
-
|
|
717
|
-
|
|
948
|
+
const s = search.toString();
|
|
949
|
+
return s ? `?${s}` : "";
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
class TasksResource {
|
|
953
|
+
client;
|
|
954
|
+
constructor(client) {
|
|
955
|
+
this.client = client;
|
|
718
956
|
}
|
|
719
|
-
async
|
|
720
|
-
return this.
|
|
957
|
+
async list(options) {
|
|
958
|
+
return this.client._get("/api/tasks", buildQuery(options || {}));
|
|
721
959
|
}
|
|
722
|
-
async
|
|
723
|
-
return this.
|
|
960
|
+
async get(id, options) {
|
|
961
|
+
return this.client._get(`/api/tasks/${id}`, buildQuery(options || {}));
|
|
724
962
|
}
|
|
725
|
-
async
|
|
726
|
-
return this.
|
|
963
|
+
async getWithRelations(id) {
|
|
964
|
+
return this.client._get(`/api/tasks/${id}`, buildQuery({ format: "full" }));
|
|
727
965
|
}
|
|
728
|
-
async
|
|
729
|
-
return this.
|
|
966
|
+
async create(data) {
|
|
967
|
+
return this.client._post("/api/tasks", data);
|
|
730
968
|
}
|
|
731
|
-
async
|
|
732
|
-
return this.
|
|
969
|
+
async update(id, data) {
|
|
970
|
+
return this.client._patch(`/api/tasks/${id}`, data);
|
|
733
971
|
}
|
|
734
|
-
async
|
|
735
|
-
return this.
|
|
972
|
+
async delete(id) {
|
|
973
|
+
return this.client._delete(`/api/tasks/${id}`);
|
|
736
974
|
}
|
|
737
|
-
async
|
|
738
|
-
|
|
975
|
+
async start(id, agentId) {
|
|
976
|
+
return this.client._post(`/api/tasks/${id}/start`, { agent_id: agentId });
|
|
739
977
|
}
|
|
740
|
-
async
|
|
741
|
-
return this.
|
|
978
|
+
async complete(id, agentId) {
|
|
979
|
+
return this.client._post(`/api/tasks/${id}/complete`, { agent_id: agentId });
|
|
742
980
|
}
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
return new TodosClient(options);
|
|
746
|
-
}
|
|
747
|
-
// src/project-registration/types.ts
|
|
748
|
-
class TodosProjectRegistrationError extends Error {
|
|
749
|
-
code;
|
|
750
|
-
details;
|
|
751
|
-
constructor(code, message, details = {}) {
|
|
752
|
-
super(message);
|
|
753
|
-
this.code = code;
|
|
754
|
-
this.details = details;
|
|
755
|
-
this.name = "TodosProjectRegistrationError";
|
|
981
|
+
async fail(id, options) {
|
|
982
|
+
return this.client._post(`/api/tasks/${id}/fail`, options || {});
|
|
756
983
|
}
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
"target_id",
|
|
764
|
-
"source_receipt_id",
|
|
765
|
-
"accepted_receipt_id",
|
|
766
|
-
"source_outcome",
|
|
767
|
-
"created_at",
|
|
768
|
-
"current_revision",
|
|
769
|
-
"accepted_result_digest"
|
|
770
|
-
];
|
|
771
|
-
function isRecord(value) {
|
|
772
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
773
|
-
}
|
|
774
|
-
function isNonEmptyString(value) {
|
|
775
|
-
return typeof value === "string" && value.length > 0;
|
|
776
|
-
}
|
|
777
|
-
function hasExactKeys(value, expected) {
|
|
778
|
-
const actual = Object.keys(value).sort();
|
|
779
|
-
const wanted = [...expected].sort();
|
|
780
|
-
return actual.length === wanted.length && actual.every((key, index) => key === wanted[index]);
|
|
781
|
-
}
|
|
782
|
-
function adoptionRejected(message) {
|
|
783
|
-
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_ADOPTION_REJECTED", `TODOS_PROJECT_REGISTRATION_ADOPTION_REJECTED: ${message}`);
|
|
784
|
-
}
|
|
785
|
-
function assertTodosPriorRegistrationAdoptionValidationEnvelope(value, input) {
|
|
786
|
-
if (!isRecord(input) || !hasExactKeys(input, [
|
|
787
|
-
"source_request",
|
|
788
|
-
"source_receipt",
|
|
789
|
-
"current_record"
|
|
790
|
-
])) {
|
|
791
|
-
adoptionRejected("prior-adoption validation input is incomplete");
|
|
984
|
+
async logProgress(taskId, message, pctComplete, agentId) {
|
|
985
|
+
return this.client._post(`/api/tasks/${taskId}/progress`, {
|
|
986
|
+
message,
|
|
987
|
+
pct_complete: pctComplete,
|
|
988
|
+
agent_id: agentId
|
|
989
|
+
});
|
|
792
990
|
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
const current = input["current_record"];
|
|
796
|
-
if (!isRecord(request) || !isRecord(receipt) || !isRecord(current)) {
|
|
797
|
-
adoptionRejected("prior-adoption validation input records are incomplete");
|
|
991
|
+
async getProgress(id, options) {
|
|
992
|
+
return this.client._get(`/api/tasks/${id}/progress`, buildQuery(options || {}));
|
|
798
993
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
const acceptedReceiptId = sourceOutcome === "accepted" ? receipt["receipt_id"] : sourceOutcome === "duplicate_of_accepted" ? receipt["duplicate_of_receipt_id"] : null;
|
|
802
|
-
if (resourceKind !== "project" && resourceKind !== "task_list" || request["direction"] !== "forward" || sourceOutcome !== "accepted" && sourceOutcome !== "duplicate_of_accepted" || !isNonEmptyString(acceptedReceiptId) || !isNonEmptyString(receipt["receipt_id"]) || !isNonEmptyString(receipt["target_id"]) || !isNonEmptyString(receipt["result_revision"]) || !isNonEmptyString(receipt["result_digest"]) || !isNonEmptyString(current["id"]) || !isNonEmptyString(current["created_at"]) || !isNonEmptyString(current["updated_at"]) || receipt["authority"] !== "todos" || receipt["route"] !== request["authority_route"] || receipt["package_version"] !== request["package_version"] || receipt["authority_id"] !== request["authority_id"] || receipt["tenant_id"] !== request["tenant_id"] || receipt["corpus_id"] !== request["corpus_id"] || receipt["operation_id"] !== request["operation_id"] || receipt["step_id"] !== request["step_id"] || receipt["resource_kind"] !== resourceKind || receipt["direction"] !== "forward" || receipt["idempotency_key"] !== request["idempotency_key"] || receipt["request_digest"] !== request["request_digest"] || receipt["precondition_digest"] !== request["precondition_digest"] || receipt["accepted_receipt_id"] !== null || receipt["target_id"] !== current["id"] || receipt["result_revision"] !== current["created_at"]) {
|
|
803
|
-
adoptionRejected("prior-adoption validation input does not carry one complete accepted receipt and current target incarnation");
|
|
994
|
+
async getHistory(id, options) {
|
|
995
|
+
return this.client._get(`/api/tasks/${id}/history`, buildQuery(options || {}));
|
|
804
996
|
}
|
|
805
|
-
|
|
806
|
-
|
|
997
|
+
async getAttachments(id) {
|
|
998
|
+
return this.client._get(`/api/tasks/${id}/attachments`);
|
|
807
999
|
}
|
|
808
|
-
|
|
809
|
-
|
|
1000
|
+
async status(options) {
|
|
1001
|
+
return this.client._get("/api/tasks/status", buildQuery(options || {}));
|
|
810
1002
|
}
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
adoptionRejected("prior-adoption validation response does not prove the exact accepted receipt and current target");
|
|
1003
|
+
async next(options) {
|
|
1004
|
+
return this.client._get("/api/tasks/next", buildQuery(options || {}));
|
|
814
1005
|
}
|
|
815
|
-
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
// src/sdk/v1.generated.ts
|
|
819
|
-
class ApiError extends Error {
|
|
820
|
-
status;
|
|
821
|
-
body;
|
|
822
|
-
constructor(status, message, body) {
|
|
823
|
-
super(message);
|
|
824
|
-
this.status = status;
|
|
825
|
-
this.body = body;
|
|
826
|
-
this.name = "ApiError";
|
|
1006
|
+
async active(projectId) {
|
|
1007
|
+
return this.client._get("/api/tasks/active", projectId ? `?project_id=${projectId}` : "");
|
|
827
1008
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
class TodosV1Client {
|
|
831
|
-
baseUrl;
|
|
832
|
-
apiKey;
|
|
833
|
-
fetchImpl;
|
|
834
|
-
baseHeaders;
|
|
835
|
-
constructor(options) {
|
|
836
|
-
if (!options.baseUrl)
|
|
837
|
-
throw new Error("TodosV1Client requires a baseUrl.");
|
|
838
|
-
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
839
|
-
this.apiKey = options.apiKey;
|
|
840
|
-
this.fetchImpl = options.fetch ?? globalThis.fetch;
|
|
841
|
-
this.baseHeaders = options.headers ?? {};
|
|
1009
|
+
async stale(options) {
|
|
1010
|
+
return this.client._get("/api/tasks/stale", buildQuery(options || {}));
|
|
842
1011
|
}
|
|
843
|
-
async
|
|
844
|
-
|
|
845
|
-
if (opts.query) {
|
|
846
|
-
for (const [key, value] of Object.entries(opts.query)) {
|
|
847
|
-
if (value !== undefined && value !== null)
|
|
848
|
-
url.searchParams.set(key, String(value));
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
const headers = { Accept: "application/json", ...this.baseHeaders, ...opts.init?.headers };
|
|
852
|
-
if (this.apiKey)
|
|
853
|
-
headers["x-api-key"] = this.apiKey;
|
|
854
|
-
let payload;
|
|
855
|
-
if (opts.body !== undefined) {
|
|
856
|
-
headers["Content-Type"] = "application/json";
|
|
857
|
-
payload = JSON.stringify(opts.body);
|
|
858
|
-
}
|
|
859
|
-
const response = await this.fetchImpl(url.toString(), { ...opts.init, method, headers, body: payload });
|
|
860
|
-
const text = await response.text();
|
|
861
|
-
const data = text ? (() => {
|
|
862
|
-
try {
|
|
863
|
-
return JSON.parse(text);
|
|
864
|
-
} catch {
|
|
865
|
-
return text;
|
|
866
|
-
}
|
|
867
|
-
})() : undefined;
|
|
868
|
-
if (!response.ok) {
|
|
869
|
-
throw new ApiError(response.status, `${method} ${path} failed: ${response.status}`, data);
|
|
870
|
-
}
|
|
871
|
-
return data;
|
|
1012
|
+
async changedSince(since, projectId, options) {
|
|
1013
|
+
return this.client._get("/api/tasks/changed", buildQuery({ since, project_id: projectId, fields: options?.fields }));
|
|
872
1014
|
}
|
|
873
|
-
async
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1015
|
+
async context(options) {
|
|
1016
|
+
const q = buildQuery({
|
|
1017
|
+
agent_id: options?.agentId,
|
|
1018
|
+
project_id: options?.projectId,
|
|
1019
|
+
format: options?.format,
|
|
1020
|
+
fields: options?.fields
|
|
878
1021
|
});
|
|
1022
|
+
const url = `${this.client.baseUrl}/api/tasks/context${q}`;
|
|
1023
|
+
const res = await this.client._fetchRaw(url);
|
|
1024
|
+
if (!res.ok)
|
|
1025
|
+
return options?.format === "json" ? {} : "";
|
|
1026
|
+
if (options?.format === "json")
|
|
1027
|
+
return res.json();
|
|
1028
|
+
return res.text();
|
|
879
1029
|
}
|
|
880
|
-
async
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
1030
|
+
async export(options) {
|
|
1031
|
+
const q = buildQuery(options || {});
|
|
1032
|
+
const url = `${this.client.baseUrl}/api/tasks/export${q}`;
|
|
1033
|
+
const res = await this.client._fetchRaw(url);
|
|
1034
|
+
if (!res.ok)
|
|
1035
|
+
throw new TodosAPIError("Export failed", res.status, res.statusText, null);
|
|
1036
|
+
if (options?.format === "csv")
|
|
1037
|
+
return res.text();
|
|
1038
|
+
return res.json();
|
|
886
1039
|
}
|
|
887
|
-
async
|
|
888
|
-
return this.
|
|
889
|
-
body,
|
|
890
|
-
query: undefined,
|
|
891
|
-
init
|
|
892
|
-
});
|
|
1040
|
+
async bulk(ids, action) {
|
|
1041
|
+
return this.client._post("/api/tasks/bulk", { ids, action });
|
|
893
1042
|
}
|
|
894
|
-
async
|
|
895
|
-
return this.
|
|
896
|
-
body: undefined,
|
|
897
|
-
query: undefined,
|
|
898
|
-
init
|
|
899
|
-
});
|
|
1043
|
+
async claim(agentId, projectId) {
|
|
1044
|
+
return this.client._post("/api/tasks/claim", { agent_id: agentId, project_id: projectId });
|
|
900
1045
|
}
|
|
901
|
-
async
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
});
|
|
907
|
-
}
|
|
908
|
-
async updatePlan(id, body, init) {
|
|
909
|
-
return this.request("PATCH", `/v1/plans/${encodeURIComponent(String(id))}`, {
|
|
910
|
-
body,
|
|
911
|
-
query: undefined,
|
|
912
|
-
init
|
|
1046
|
+
async* subscribe(options = {}) {
|
|
1047
|
+
const q = buildQuery({
|
|
1048
|
+
agent_id: options.agentId,
|
|
1049
|
+
project_id: options.projectId,
|
|
1050
|
+
events: options.events?.join(",")
|
|
913
1051
|
});
|
|
1052
|
+
const url = `${this.client.baseUrl}/api/tasks/stream${q}`;
|
|
1053
|
+
const resp = await this.client._fetchRaw(url);
|
|
1054
|
+
if (!resp.ok || !resp.body)
|
|
1055
|
+
throw new Error(`SSE connection failed: ${resp.status}`);
|
|
1056
|
+
const reader = resp.body.getReader();
|
|
1057
|
+
const decoder = new TextDecoder;
|
|
1058
|
+
let buffer = "";
|
|
1059
|
+
try {
|
|
1060
|
+
while (true) {
|
|
1061
|
+
const { done, value } = await reader.read();
|
|
1062
|
+
if (done)
|
|
1063
|
+
break;
|
|
1064
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1065
|
+
const lines = buffer.split(`
|
|
1066
|
+
`);
|
|
1067
|
+
buffer = lines.pop() || "";
|
|
1068
|
+
for (const line of lines) {
|
|
1069
|
+
if (line.startsWith("data: ")) {
|
|
1070
|
+
try {
|
|
1071
|
+
const data = JSON.parse(line.slice(6));
|
|
1072
|
+
if (data.type !== "connected")
|
|
1073
|
+
yield data;
|
|
1074
|
+
} catch {}
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
} finally {
|
|
1079
|
+
reader.releaseLock();
|
|
1080
|
+
}
|
|
914
1081
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
class AgentsResource {
|
|
1085
|
+
client;
|
|
1086
|
+
constructor(client) {
|
|
1087
|
+
this.client = client;
|
|
921
1088
|
}
|
|
922
|
-
async
|
|
923
|
-
return this.
|
|
924
|
-
body,
|
|
925
|
-
query: undefined,
|
|
926
|
-
init
|
|
927
|
-
});
|
|
1089
|
+
async list(options) {
|
|
1090
|
+
return this.client._get("/api/agents", buildQuery(options || {}));
|
|
928
1091
|
}
|
|
929
|
-
async
|
|
930
|
-
return this.
|
|
931
|
-
body,
|
|
932
|
-
query: undefined,
|
|
933
|
-
init
|
|
934
|
-
});
|
|
1092
|
+
async register(data) {
|
|
1093
|
+
return this.client._post("/api/agents", data);
|
|
935
1094
|
}
|
|
936
|
-
async
|
|
937
|
-
return this.
|
|
938
|
-
body,
|
|
939
|
-
query: undefined,
|
|
940
|
-
init
|
|
941
|
-
});
|
|
1095
|
+
async fullRegister(data) {
|
|
1096
|
+
return this.client._post("/api/agents", data);
|
|
942
1097
|
}
|
|
943
|
-
async
|
|
944
|
-
return this.
|
|
945
|
-
body: undefined,
|
|
946
|
-
query: undefined,
|
|
947
|
-
init
|
|
948
|
-
});
|
|
1098
|
+
async update(id, data) {
|
|
1099
|
+
return this.client._patch(`/api/agents/${id}`, data);
|
|
949
1100
|
}
|
|
950
|
-
async
|
|
951
|
-
return this.
|
|
952
|
-
body: undefined,
|
|
953
|
-
query,
|
|
954
|
-
init
|
|
955
|
-
});
|
|
1101
|
+
async delete(id) {
|
|
1102
|
+
return this.client._delete(`/api/agents/${id}`);
|
|
956
1103
|
}
|
|
957
|
-
async
|
|
958
|
-
return this.
|
|
959
|
-
body,
|
|
960
|
-
query: undefined,
|
|
961
|
-
init
|
|
962
|
-
});
|
|
1104
|
+
async bulkDelete(ids) {
|
|
1105
|
+
return this.client._post("/api/agents/bulk", { ids, action: "delete" });
|
|
963
1106
|
}
|
|
964
|
-
async
|
|
965
|
-
return this.
|
|
966
|
-
body,
|
|
967
|
-
query: undefined,
|
|
968
|
-
init
|
|
969
|
-
});
|
|
1107
|
+
async me(name) {
|
|
1108
|
+
return this.client._get("/api/agents/me", `?name=${encodeURIComponent(name)}`);
|
|
970
1109
|
}
|
|
971
|
-
async
|
|
972
|
-
return this.
|
|
973
|
-
body: undefined,
|
|
974
|
-
query: undefined,
|
|
975
|
-
init
|
|
976
|
-
});
|
|
1110
|
+
async queue(agentId) {
|
|
1111
|
+
return this.client._get(`/api/agents/${encodeURIComponent(agentId)}/queue`);
|
|
977
1112
|
}
|
|
978
|
-
async
|
|
979
|
-
return this.
|
|
980
|
-
body,
|
|
981
|
-
query: undefined,
|
|
982
|
-
init
|
|
983
|
-
});
|
|
1113
|
+
async team(agentId) {
|
|
1114
|
+
return this.client._get(`/api/agents/${encodeURIComponent(agentId)}/team`);
|
|
984
1115
|
}
|
|
985
|
-
async
|
|
986
|
-
return this.
|
|
987
|
-
body,
|
|
988
|
-
query: undefined,
|
|
989
|
-
init
|
|
990
|
-
});
|
|
1116
|
+
async orgChart() {
|
|
1117
|
+
return this.client._get("/api/org");
|
|
991
1118
|
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
class ProjectsResource {
|
|
1122
|
+
client;
|
|
1123
|
+
constructor(client) {
|
|
1124
|
+
this.client = client;
|
|
998
1125
|
}
|
|
999
|
-
async
|
|
1000
|
-
return this.
|
|
1001
|
-
body,
|
|
1002
|
-
query: undefined,
|
|
1003
|
-
init
|
|
1004
|
-
});
|
|
1126
|
+
async list(options) {
|
|
1127
|
+
return this.client._get("/api/projects", buildQuery(options || {}));
|
|
1005
1128
|
}
|
|
1006
|
-
async
|
|
1007
|
-
return this.
|
|
1008
|
-
body: undefined,
|
|
1009
|
-
query,
|
|
1010
|
-
init
|
|
1011
|
-
});
|
|
1129
|
+
async create(data) {
|
|
1130
|
+
return this.client._post("/api/projects", data);
|
|
1012
1131
|
}
|
|
1013
|
-
async
|
|
1014
|
-
|
|
1015
|
-
body,
|
|
1016
|
-
query: undefined,
|
|
1017
|
-
init
|
|
1018
|
-
});
|
|
1019
|
-
return {
|
|
1020
|
-
validation: assertTodosPriorRegistrationAdoptionValidationEnvelope(response, body)
|
|
1021
|
-
};
|
|
1132
|
+
async delete(id) {
|
|
1133
|
+
return this.client._delete(`/api/projects/${id}`);
|
|
1022
1134
|
}
|
|
1023
|
-
async
|
|
1024
|
-
return this.
|
|
1025
|
-
body,
|
|
1026
|
-
query: undefined,
|
|
1027
|
-
init
|
|
1028
|
-
});
|
|
1135
|
+
async bulkDelete(ids) {
|
|
1136
|
+
return this.client._post("/api/projects/bulk", { ids, action: "delete" });
|
|
1029
1137
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
class PlansResource {
|
|
1141
|
+
client;
|
|
1142
|
+
constructor(client) {
|
|
1143
|
+
this.client = client;
|
|
1036
1144
|
}
|
|
1037
|
-
async
|
|
1038
|
-
return this.
|
|
1039
|
-
body,
|
|
1040
|
-
query: undefined,
|
|
1041
|
-
init
|
|
1042
|
-
});
|
|
1145
|
+
async list(projectId) {
|
|
1146
|
+
return this.client._get("/api/plans", projectId ? `?project_id=${projectId}` : "");
|
|
1043
1147
|
}
|
|
1044
|
-
async
|
|
1045
|
-
return this.
|
|
1046
|
-
body: undefined,
|
|
1047
|
-
query: undefined,
|
|
1048
|
-
init
|
|
1049
|
-
});
|
|
1148
|
+
async create(data) {
|
|
1149
|
+
return this.client._post("/api/plans", data);
|
|
1050
1150
|
}
|
|
1051
|
-
async
|
|
1052
|
-
return this.
|
|
1053
|
-
body: undefined,
|
|
1054
|
-
query: undefined,
|
|
1055
|
-
init
|
|
1056
|
-
});
|
|
1151
|
+
async get(id) {
|
|
1152
|
+
return this.client._get(`/api/plans/${id}`);
|
|
1057
1153
|
}
|
|
1058
|
-
async
|
|
1059
|
-
return this.
|
|
1060
|
-
body,
|
|
1061
|
-
query: undefined,
|
|
1062
|
-
init
|
|
1063
|
-
});
|
|
1154
|
+
async update(id, data) {
|
|
1155
|
+
return this.client._patch(`/api/plans/${id}`, data);
|
|
1064
1156
|
}
|
|
1065
|
-
async
|
|
1066
|
-
return this.
|
|
1067
|
-
body,
|
|
1068
|
-
query: undefined,
|
|
1069
|
-
init
|
|
1070
|
-
});
|
|
1157
|
+
async delete(id) {
|
|
1158
|
+
return this.client._delete(`/api/plans/${id}`);
|
|
1071
1159
|
}
|
|
1072
|
-
async
|
|
1073
|
-
return this.
|
|
1074
|
-
body: undefined,
|
|
1075
|
-
query: undefined,
|
|
1076
|
-
init
|
|
1077
|
-
});
|
|
1160
|
+
async bulkDelete(ids) {
|
|
1161
|
+
return this.client._post("/api/plans/bulk", { ids, action: "delete" });
|
|
1078
1162
|
}
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
class OrgsResource {
|
|
1166
|
+
client;
|
|
1167
|
+
constructor(client) {
|
|
1168
|
+
this.client = client;
|
|
1085
1169
|
}
|
|
1086
|
-
async
|
|
1087
|
-
return this.
|
|
1088
|
-
body,
|
|
1089
|
-
query: undefined,
|
|
1090
|
-
init
|
|
1091
|
-
});
|
|
1170
|
+
async list() {
|
|
1171
|
+
return this.client._get("/api/orgs");
|
|
1092
1172
|
}
|
|
1093
|
-
async
|
|
1094
|
-
return this.
|
|
1095
|
-
body: undefined,
|
|
1096
|
-
query: undefined,
|
|
1097
|
-
init
|
|
1098
|
-
});
|
|
1173
|
+
async create(data) {
|
|
1174
|
+
return this.client._post("/api/orgs", data);
|
|
1099
1175
|
}
|
|
1100
|
-
async
|
|
1101
|
-
return this.
|
|
1102
|
-
body: undefined,
|
|
1103
|
-
query: undefined,
|
|
1104
|
-
init
|
|
1105
|
-
});
|
|
1176
|
+
async update(id, data) {
|
|
1177
|
+
return this.client._patch(`/api/orgs/${id}`, data);
|
|
1106
1178
|
}
|
|
1107
|
-
async
|
|
1108
|
-
return this.
|
|
1109
|
-
body: undefined,
|
|
1110
|
-
query,
|
|
1111
|
-
init
|
|
1112
|
-
});
|
|
1179
|
+
async delete(id) {
|
|
1180
|
+
return this.client._delete(`/api/orgs/${id}`);
|
|
1113
1181
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
class WebhooksResource {
|
|
1185
|
+
client;
|
|
1186
|
+
constructor(client) {
|
|
1187
|
+
this.client = client;
|
|
1120
1188
|
}
|
|
1121
|
-
async
|
|
1122
|
-
return this.
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1189
|
+
async list() {
|
|
1190
|
+
return this.client._get("/api/webhooks");
|
|
1191
|
+
}
|
|
1192
|
+
async create(data) {
|
|
1193
|
+
return this.client._post("/api/webhooks", data);
|
|
1194
|
+
}
|
|
1195
|
+
async delete(id) {
|
|
1196
|
+
return this.client._delete(`/api/webhooks/${id}`);
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
class TemplatesResource {
|
|
1201
|
+
client;
|
|
1202
|
+
constructor(client) {
|
|
1203
|
+
this.client = client;
|
|
1204
|
+
}
|
|
1205
|
+
async list() {
|
|
1206
|
+
return this.client._get("/api/templates");
|
|
1207
|
+
}
|
|
1208
|
+
async create(data) {
|
|
1209
|
+
return this.client._post("/api/templates", data);
|
|
1210
|
+
}
|
|
1211
|
+
async delete(id) {
|
|
1212
|
+
return this.client._delete(`/api/templates/${id}`);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
class PrGroupsResource {
|
|
1217
|
+
client;
|
|
1218
|
+
constructor(client) {
|
|
1219
|
+
this.client = client;
|
|
1220
|
+
}
|
|
1221
|
+
async admit(input) {
|
|
1222
|
+
return this.client._post("/api/pr-groups/admit", input);
|
|
1223
|
+
}
|
|
1224
|
+
async get(groupId) {
|
|
1225
|
+
const result = await this.client._get(`/api/pr-groups/${encodeURIComponent(groupId)}`);
|
|
1226
|
+
return result.view;
|
|
1227
|
+
}
|
|
1228
|
+
async events(groupId, options = {}) {
|
|
1229
|
+
const result = await this.client._get(`/api/pr-groups/${encodeURIComponent(groupId)}/events`, buildQuery({
|
|
1230
|
+
limit: options.limit,
|
|
1231
|
+
after_sequence: options.after_sequence
|
|
1232
|
+
}));
|
|
1233
|
+
return result.history;
|
|
1234
|
+
}
|
|
1235
|
+
async append(input) {
|
|
1236
|
+
return this.client._post(`/api/pr-groups/${encodeURIComponent(input.group_id)}/events`, input);
|
|
1237
|
+
}
|
|
1238
|
+
async recover(input) {
|
|
1239
|
+
return this.client._post(`/api/pr-groups/${encodeURIComponent(input.group_id)}/recover`, input);
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
class TodosClient {
|
|
1244
|
+
baseUrl;
|
|
1245
|
+
timeout;
|
|
1246
|
+
maxRetries;
|
|
1247
|
+
retryDelay;
|
|
1248
|
+
explicitApiKey;
|
|
1249
|
+
constructedApiKey;
|
|
1250
|
+
pinnedAuthority;
|
|
1251
|
+
tasks;
|
|
1252
|
+
agents;
|
|
1253
|
+
projects;
|
|
1254
|
+
plans;
|
|
1255
|
+
orgs;
|
|
1256
|
+
webhooks;
|
|
1257
|
+
templates;
|
|
1258
|
+
prGroups;
|
|
1259
|
+
constructor(options = {}) {
|
|
1260
|
+
const resolved = resolveTodosSdkTransport({
|
|
1261
|
+
...options.baseUrl !== undefined ? { baseUrl: options.baseUrl } : {},
|
|
1262
|
+
...options.apiKey !== undefined ? { apiKey: options.apiKey } : {}
|
|
1126
1263
|
});
|
|
1264
|
+
this.baseUrl = resolved.baseUrl;
|
|
1265
|
+
this.timeout = options.timeout ?? 1e4;
|
|
1266
|
+
this.explicitApiKey = options.apiKey;
|
|
1267
|
+
this.constructedApiKey = resolved.apiKey;
|
|
1268
|
+
this.pinnedAuthority = Boolean(options.baseUrl);
|
|
1269
|
+
this.maxRetries = options.maxRetries ?? 0;
|
|
1270
|
+
this.retryDelay = options.retryDelay ?? 1000;
|
|
1271
|
+
this.tasks = new TasksResource(this);
|
|
1272
|
+
this.agents = new AgentsResource(this);
|
|
1273
|
+
this.projects = new ProjectsResource(this);
|
|
1274
|
+
this.plans = new PlansResource(this);
|
|
1275
|
+
this.orgs = new OrgsResource(this);
|
|
1276
|
+
this.webhooks = new WebhooksResource(this);
|
|
1277
|
+
this.templates = new TemplatesResource(this);
|
|
1278
|
+
this.prGroups = new PrGroupsResource(this);
|
|
1279
|
+
}
|
|
1280
|
+
static fromEnv(apiKey) {
|
|
1281
|
+
return new TodosClient(apiKey === undefined ? {} : { apiKey });
|
|
1282
|
+
}
|
|
1283
|
+
async _fetchRaw(url, init) {
|
|
1284
|
+
const controller = new AbortController;
|
|
1285
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
1286
|
+
try {
|
|
1287
|
+
const headers = this._buildHeaders(init?.headers);
|
|
1288
|
+
return await fetch(url, { ...init, headers, signal: controller.signal });
|
|
1289
|
+
} finally {
|
|
1290
|
+
clearTimeout(timer);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
currentApiKey() {
|
|
1294
|
+
if (this.explicitApiKey !== undefined)
|
|
1295
|
+
return this.explicitApiKey;
|
|
1296
|
+
if (this.pinnedAuthority)
|
|
1297
|
+
return this.constructedApiKey;
|
|
1298
|
+
try {
|
|
1299
|
+
const fresh = resolveTodosSdkTransport({ notice: () => {} }).apiKey;
|
|
1300
|
+
if (fresh)
|
|
1301
|
+
return fresh;
|
|
1302
|
+
} catch {}
|
|
1303
|
+
return this.constructedApiKey;
|
|
1304
|
+
}
|
|
1305
|
+
get apiKey() {
|
|
1306
|
+
return this.currentApiKey();
|
|
1307
|
+
}
|
|
1308
|
+
_buildHeaders(existing) {
|
|
1309
|
+
const headers = { "Content-Type": "application/json" };
|
|
1310
|
+
const apiKey = this.currentApiKey();
|
|
1311
|
+
if (apiKey)
|
|
1312
|
+
headers["x-api-key"] = apiKey;
|
|
1313
|
+
if (existing) {
|
|
1314
|
+
if (existing instanceof Headers) {
|
|
1315
|
+
existing.forEach((v, k) => {
|
|
1316
|
+
headers[k] = v;
|
|
1317
|
+
});
|
|
1318
|
+
} else if (Array.isArray(existing)) {
|
|
1319
|
+
for (const [k, v] of existing)
|
|
1320
|
+
headers[k] = v;
|
|
1321
|
+
} else {
|
|
1322
|
+
Object.assign(headers, existing);
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
return headers;
|
|
1326
|
+
}
|
|
1327
|
+
async _fetchWithRetry(path, init) {
|
|
1328
|
+
let lastError = null;
|
|
1329
|
+
const maxAttempts = this.maxRetries + 1;
|
|
1330
|
+
for (let attempt = 0;attempt < maxAttempts; attempt++) {
|
|
1331
|
+
try {
|
|
1332
|
+
return await this._fetch(path, init);
|
|
1333
|
+
} catch (e) {
|
|
1334
|
+
lastError = e;
|
|
1335
|
+
if (e instanceof TodosAPIError && e.status < 500 && e.status !== 429)
|
|
1336
|
+
throw e;
|
|
1337
|
+
if (e instanceof TodosUnauthorizedError || e instanceof TodosNotFoundError || e instanceof TodosConflictError)
|
|
1338
|
+
throw e;
|
|
1339
|
+
if (attempt < maxAttempts - 1) {
|
|
1340
|
+
const delay = this.retryDelay * Math.pow(2, attempt);
|
|
1341
|
+
if (e instanceof TodosRateLimitError) {
|
|
1342
|
+
await this._sleep(e.retryAfter * 1000);
|
|
1343
|
+
} else {
|
|
1344
|
+
await this._sleep(delay);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
throw lastError || new Error("Request failed after retries");
|
|
1350
|
+
}
|
|
1351
|
+
async _fetch(path, init) {
|
|
1352
|
+
const controller = new AbortController;
|
|
1353
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
1354
|
+
try {
|
|
1355
|
+
const url = `${this.baseUrl}${path}`;
|
|
1356
|
+
const headers = this._buildHeaders(init?.headers);
|
|
1357
|
+
const res = await fetch(url, { ...init, headers, signal: controller.signal });
|
|
1358
|
+
if (!res.ok) {
|
|
1359
|
+
const body = await res.json().catch(() => ({ error: res.statusText }));
|
|
1360
|
+
const message = body.error || `HTTP ${res.status}: ${res.statusText}`;
|
|
1361
|
+
if (res.status === 401)
|
|
1362
|
+
throw new TodosUnauthorizedError(message, body);
|
|
1363
|
+
if (res.status === 404)
|
|
1364
|
+
throw new TodosNotFoundError(message, body);
|
|
1365
|
+
if (res.status === 409)
|
|
1366
|
+
throw new TodosConflictError(message, body);
|
|
1367
|
+
if (res.status === 429) {
|
|
1368
|
+
const retryAfter = parseInt(res.headers.get("retry-after") || "60", 10);
|
|
1369
|
+
throw new TodosRateLimitError(message, retryAfter, body);
|
|
1370
|
+
}
|
|
1371
|
+
throw new TodosAPIError(message, res.status, res.statusText, body);
|
|
1372
|
+
}
|
|
1373
|
+
if (res.status === 204)
|
|
1374
|
+
return null;
|
|
1375
|
+
const text = await res.text();
|
|
1376
|
+
if (text.length === 0)
|
|
1377
|
+
return null;
|
|
1378
|
+
return JSON.parse(text);
|
|
1379
|
+
} catch (e) {
|
|
1380
|
+
if (e instanceof DOMException && e.name === "AbortError") {
|
|
1381
|
+
throw new TodosTimeoutError(this.timeout);
|
|
1382
|
+
}
|
|
1383
|
+
throw e;
|
|
1384
|
+
} finally {
|
|
1385
|
+
clearTimeout(timer);
|
|
1386
|
+
}
|
|
1127
1387
|
}
|
|
1128
|
-
async
|
|
1129
|
-
return this.
|
|
1130
|
-
body: undefined,
|
|
1131
|
-
query: undefined,
|
|
1132
|
-
init
|
|
1133
|
-
});
|
|
1388
|
+
async _get(path, query = "") {
|
|
1389
|
+
return this._fetchWithRetry(`${path}${query}`);
|
|
1134
1390
|
}
|
|
1135
|
-
async
|
|
1136
|
-
return this.
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
init
|
|
1391
|
+
async _post(path, body) {
|
|
1392
|
+
return this._fetchWithRetry(path, {
|
|
1393
|
+
method: "POST",
|
|
1394
|
+
body: body ? JSON.stringify(body) : undefined
|
|
1140
1395
|
});
|
|
1141
1396
|
}
|
|
1142
|
-
async
|
|
1143
|
-
return this.
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
init
|
|
1397
|
+
async _patch(path, body) {
|
|
1398
|
+
return this._fetchWithRetry(path, {
|
|
1399
|
+
method: "PATCH",
|
|
1400
|
+
body: JSON.stringify(body)
|
|
1147
1401
|
});
|
|
1148
1402
|
}
|
|
1149
|
-
async
|
|
1150
|
-
return this.
|
|
1151
|
-
body,
|
|
1152
|
-
query: undefined,
|
|
1153
|
-
init
|
|
1154
|
-
});
|
|
1403
|
+
async _delete(path) {
|
|
1404
|
+
return this._fetchWithRetry(path, { method: "DELETE" });
|
|
1155
1405
|
}
|
|
1156
|
-
|
|
1157
|
-
return
|
|
1158
|
-
body: undefined,
|
|
1159
|
-
query: undefined,
|
|
1160
|
-
init
|
|
1161
|
-
});
|
|
1406
|
+
_sleep(ms) {
|
|
1407
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1162
1408
|
}
|
|
1163
|
-
async
|
|
1164
|
-
return this.
|
|
1165
|
-
body,
|
|
1166
|
-
query: undefined,
|
|
1167
|
-
init
|
|
1168
|
-
});
|
|
1409
|
+
async getHealth() {
|
|
1410
|
+
return this._get("/api/health");
|
|
1169
1411
|
}
|
|
1170
|
-
async
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1412
|
+
async isAlive() {
|
|
1413
|
+
try {
|
|
1414
|
+
await this._get("/api/stats");
|
|
1415
|
+
return true;
|
|
1416
|
+
} catch {
|
|
1417
|
+
return false;
|
|
1418
|
+
}
|
|
1176
1419
|
}
|
|
1177
|
-
async
|
|
1178
|
-
return this.
|
|
1179
|
-
body,
|
|
1180
|
-
query: undefined,
|
|
1181
|
-
init
|
|
1182
|
-
});
|
|
1420
|
+
async getStats() {
|
|
1421
|
+
return this._get("/api/stats");
|
|
1183
1422
|
}
|
|
1184
|
-
async
|
|
1185
|
-
return this.
|
|
1186
|
-
body: undefined,
|
|
1187
|
-
query: undefined,
|
|
1188
|
-
init
|
|
1189
|
-
});
|
|
1423
|
+
async getReport(options) {
|
|
1424
|
+
return this._get("/api/report", buildQuery({ days: options?.days, project_id: options?.projectId }));
|
|
1190
1425
|
}
|
|
1191
|
-
async
|
|
1192
|
-
return this.
|
|
1193
|
-
body,
|
|
1194
|
-
query: undefined,
|
|
1195
|
-
init
|
|
1196
|
-
});
|
|
1426
|
+
async doctor() {
|
|
1427
|
+
return this._get("/api/doctor");
|
|
1197
1428
|
}
|
|
1198
|
-
async
|
|
1199
|
-
return this.
|
|
1200
|
-
body,
|
|
1201
|
-
query: undefined,
|
|
1202
|
-
init
|
|
1203
|
-
});
|
|
1429
|
+
async activity(limit) {
|
|
1430
|
+
return this._get("/api/activity", limit ? `?limit=${limit}` : "");
|
|
1204
1431
|
}
|
|
1205
|
-
async
|
|
1206
|
-
return this.
|
|
1207
|
-
body,
|
|
1208
|
-
query: undefined,
|
|
1209
|
-
init
|
|
1210
|
-
});
|
|
1432
|
+
async listTasks(filter = {}) {
|
|
1433
|
+
return this.tasks.list(filter);
|
|
1211
1434
|
}
|
|
1212
|
-
async
|
|
1213
|
-
return this.
|
|
1214
|
-
body: undefined,
|
|
1215
|
-
query,
|
|
1216
|
-
init
|
|
1217
|
-
});
|
|
1435
|
+
async getTask(id, options) {
|
|
1436
|
+
return this.tasks.get(id, options);
|
|
1218
1437
|
}
|
|
1219
|
-
async createTask(
|
|
1220
|
-
return this.
|
|
1221
|
-
body,
|
|
1222
|
-
query: undefined,
|
|
1223
|
-
init
|
|
1224
|
-
});
|
|
1438
|
+
async createTask(data) {
|
|
1439
|
+
return this.tasks.create(data);
|
|
1225
1440
|
}
|
|
1226
|
-
async
|
|
1227
|
-
return this.
|
|
1228
|
-
body: undefined,
|
|
1229
|
-
query: undefined,
|
|
1230
|
-
init
|
|
1231
|
-
});
|
|
1441
|
+
async updateTask(id, data) {
|
|
1442
|
+
return this.tasks.update(id, data);
|
|
1232
1443
|
}
|
|
1233
|
-
async deleteTask(id
|
|
1234
|
-
|
|
1235
|
-
body: undefined,
|
|
1236
|
-
query: undefined,
|
|
1237
|
-
init
|
|
1238
|
-
});
|
|
1444
|
+
async deleteTask(id) {
|
|
1445
|
+
await this.tasks.delete(id);
|
|
1239
1446
|
}
|
|
1240
|
-
async
|
|
1241
|
-
return this.
|
|
1242
|
-
body,
|
|
1243
|
-
query: undefined,
|
|
1244
|
-
init
|
|
1245
|
-
});
|
|
1447
|
+
async startTask(id, agentId) {
|
|
1448
|
+
return this.tasks.start(id, agentId);
|
|
1246
1449
|
}
|
|
1247
|
-
async
|
|
1248
|
-
return this.
|
|
1249
|
-
body: undefined,
|
|
1250
|
-
query,
|
|
1251
|
-
init
|
|
1252
|
-
});
|
|
1450
|
+
async completeTask(id, agentId) {
|
|
1451
|
+
return this.tasks.complete(id, agentId);
|
|
1253
1452
|
}
|
|
1254
|
-
async
|
|
1255
|
-
return this.
|
|
1256
|
-
body,
|
|
1257
|
-
query: undefined,
|
|
1258
|
-
init
|
|
1259
|
-
});
|
|
1453
|
+
async failTask(id, options = {}) {
|
|
1454
|
+
return this.tasks.fail(id, options);
|
|
1260
1455
|
}
|
|
1261
|
-
async
|
|
1262
|
-
return this.
|
|
1263
|
-
body,
|
|
1264
|
-
query: undefined,
|
|
1265
|
-
init
|
|
1266
|
-
});
|
|
1456
|
+
async logProgress(taskId, message, pctComplete, agentId) {
|
|
1457
|
+
return this.tasks.logProgress(taskId, message, pctComplete, agentId);
|
|
1267
1458
|
}
|
|
1268
|
-
async
|
|
1269
|
-
return this.
|
|
1270
|
-
body,
|
|
1271
|
-
query: undefined,
|
|
1272
|
-
init
|
|
1273
|
-
});
|
|
1459
|
+
async getStatus(projectId, agentId) {
|
|
1460
|
+
return this.tasks.status({ project_id: projectId, agent_id: agentId });
|
|
1274
1461
|
}
|
|
1275
|
-
async
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
query: undefined,
|
|
1279
|
-
init
|
|
1280
|
-
});
|
|
1462
|
+
async getActiveWork(projectId) {
|
|
1463
|
+
const res = await this.tasks.active(projectId);
|
|
1464
|
+
return res.active;
|
|
1281
1465
|
}
|
|
1282
|
-
async
|
|
1283
|
-
return this.
|
|
1284
|
-
body,
|
|
1285
|
-
query: undefined,
|
|
1286
|
-
init
|
|
1287
|
-
});
|
|
1466
|
+
async getTasksChangedSince(since, projectId) {
|
|
1467
|
+
return this.tasks.changedSince(since, projectId);
|
|
1288
1468
|
}
|
|
1289
|
-
async
|
|
1290
|
-
return this.
|
|
1291
|
-
body,
|
|
1292
|
-
query: undefined,
|
|
1293
|
-
init
|
|
1294
|
-
});
|
|
1469
|
+
async getStaleTasks(minutes, projectId) {
|
|
1470
|
+
return this.tasks.stale({ minutes, project_id: projectId });
|
|
1295
1471
|
}
|
|
1296
|
-
async
|
|
1297
|
-
return this.
|
|
1298
|
-
body: undefined,
|
|
1299
|
-
query: undefined,
|
|
1300
|
-
init
|
|
1301
|
-
});
|
|
1472
|
+
async getContext(options = {}) {
|
|
1473
|
+
return this.tasks.context(options);
|
|
1302
1474
|
}
|
|
1303
|
-
async
|
|
1304
|
-
return this.
|
|
1305
|
-
body: undefined,
|
|
1306
|
-
query,
|
|
1307
|
-
init
|
|
1308
|
-
});
|
|
1475
|
+
async exportTasks(filter = {}) {
|
|
1476
|
+
return this.tasks.export(filter);
|
|
1309
1477
|
}
|
|
1310
|
-
async
|
|
1311
|
-
return this.
|
|
1312
|
-
body,
|
|
1313
|
-
query: undefined,
|
|
1314
|
-
init
|
|
1315
|
-
});
|
|
1478
|
+
async claimNextTask(agentId, projectId) {
|
|
1479
|
+
return this.tasks.claim(agentId, projectId);
|
|
1316
1480
|
}
|
|
1317
|
-
async
|
|
1318
|
-
return this.
|
|
1319
|
-
body: undefined,
|
|
1320
|
-
query: undefined,
|
|
1321
|
-
init
|
|
1322
|
-
});
|
|
1481
|
+
async getTaskHistory(id, options) {
|
|
1482
|
+
return this.tasks.getHistory(id, options);
|
|
1323
1483
|
}
|
|
1324
|
-
async
|
|
1325
|
-
return this.
|
|
1326
|
-
body: undefined,
|
|
1327
|
-
query: undefined,
|
|
1328
|
-
init
|
|
1329
|
-
});
|
|
1484
|
+
async getTaskAttachments(id) {
|
|
1485
|
+
return this.tasks.getAttachments(id);
|
|
1330
1486
|
}
|
|
1331
|
-
async
|
|
1332
|
-
return this.
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1487
|
+
async getTaskProgress(id, options) {
|
|
1488
|
+
return this.tasks.getProgress(id, options);
|
|
1489
|
+
}
|
|
1490
|
+
async* subscribeToStream(options = {}) {
|
|
1491
|
+
yield* this.tasks.subscribe(options);
|
|
1492
|
+
}
|
|
1493
|
+
async getProjects() {
|
|
1494
|
+
return this.projects.list();
|
|
1337
1495
|
}
|
|
1338
1496
|
}
|
|
1497
|
+
function createClient(options) {
|
|
1498
|
+
return new TodosClient(options);
|
|
1499
|
+
}
|
|
1339
1500
|
export {
|
|
1501
|
+
resolveTodosSdkTransport,
|
|
1502
|
+
createTodosV1Client,
|
|
1340
1503
|
createClient,
|
|
1504
|
+
__resetTodosSdkLocalNotice,
|
|
1341
1505
|
TodosV1Client,
|
|
1342
1506
|
ApiError as TodosV1ApiError,
|
|
1343
1507
|
TodosUnauthorizedError,
|
|
@@ -1346,5 +1510,6 @@ export {
|
|
|
1346
1510
|
TodosNotFoundError,
|
|
1347
1511
|
TodosConflictError,
|
|
1348
1512
|
TodosClient,
|
|
1349
|
-
TodosAPIError
|
|
1513
|
+
TodosAPIError,
|
|
1514
|
+
TODOS_LOCAL_SERVE_URL
|
|
1350
1515
|
};
|