@hasna/todos 0.11.75 → 0.11.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/cli/cloud-router.d.ts +71 -0
- package/dist/cli/cloud-router.d.ts.map +1 -0
- package/dist/cli/commands/project-commands.d.ts.map +1 -1
- package/dist/cli/commands/storage-commands.d.ts.map +1 -1
- package/dist/cli/commands/task-commands.d.ts.map +1 -1
- package/dist/cli/helpers.d.ts +22 -0
- package/dist/cli/helpers.d.ts.map +1 -1
- package/dist/cli/index.js +72374 -62374
- package/dist/contracts.js +314 -14
- package/dist/db/database.d.ts.map +1 -1
- package/dist/index.js +1158 -236
- package/dist/lib/shadow-status.d.ts +38 -0
- package/dist/lib/shadow-status.d.ts.map +1 -0
- package/dist/mcp/index.js +10249 -340
- package/dist/mcp/tools/task-adv-tools.d.ts.map +1 -1
- package/dist/mcp/tools/task-crud.d.ts.map +1 -1
- package/dist/mcp/tools/task-project-tools.d.ts.map +1 -1
- package/dist/mcp/tools/task-workflow-tools.d.ts.map +1 -1
- package/dist/registry.js +314 -14
- package/dist/release-provenance.json +3 -3
- package/dist/sdk/index.d.ts +2 -0
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/index.js +135 -0
- package/dist/sdk/v1.generated.d.ts +124 -0
- package/dist/sdk/v1.generated.d.ts.map +1 -0
- package/dist/server/cloud.d.ts +50 -0
- package/dist/server/cloud.d.ts.map +1 -0
- package/dist/server/index.js +11944 -2012
- package/dist/server/openapi.d.ts +628 -0
- package/dist/server/openapi.d.ts.map +1 -0
- package/dist/server/serve.d.ts.map +1 -1
- package/dist/server/v1.d.ts +19 -0
- package/dist/server/v1.d.ts.map +1 -0
- package/dist/storage/cloud-client.d.ts +30 -0
- package/dist/storage/cloud-client.d.ts.map +1 -0
- package/dist/storage/config.d.ts +12 -0
- package/dist/storage/config.d.ts.map +1 -1
- package/dist/storage/factory.d.ts +2 -0
- package/dist/storage/factory.d.ts.map +1 -1
- package/dist/storage/index.d.ts +8 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/postgres-adapter.d.ts.map +1 -1
- package/dist/storage/postgres-sync.d.ts.map +1 -1
- package/dist/storage/shadow-outbox-schema.d.ts +21 -0
- package/dist/storage/shadow-outbox-schema.d.ts.map +1 -0
- package/dist/storage/shadow-outbox.d.ts +125 -0
- package/dist/storage/shadow-outbox.d.ts.map +1 -0
- package/dist/storage/shadow-runtime.d.ts +29 -0
- package/dist/storage/shadow-runtime.d.ts.map +1 -0
- package/dist/storage/shadow.d.ts +118 -0
- package/dist/storage/shadow.d.ts.map +1 -0
- package/dist/storage.d.ts +2 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +1157 -220
- package/package.json +6 -2
- package/vendor/hasna-contracts-0.5.1.tgz +0 -0
package/README.md
CHANGED
|
@@ -477,6 +477,14 @@ version, compact workflow pointers, and an `automation` object containing only
|
|
|
477
477
|
boolean routing gates such as `no_auto`, `manual_required`,
|
|
478
478
|
`requires_approval`, and `approval_required`.
|
|
479
479
|
|
|
480
|
+
When running route smokes or tests with an explicit temp/in-memory task database
|
|
481
|
+
through `TODOS_DB_PATH` or `HASNA_TODOS_DB_PATH`, also set `HASNA_EVENTS_DIR` or
|
|
482
|
+
`HASNA_EVENTS_HOME` to a temp event store. Without an explicit event directory,
|
|
483
|
+
Todos suppresses shared event emission for temp task databases so route-enabled
|
|
484
|
+
scratch tasks cannot trigger global OpenLoops workers. Set
|
|
485
|
+
`HASNA_TODOS_ALLOW_GLOBAL_EVENTS_FROM_TEMP_DB=1` only for deliberate integration
|
|
486
|
+
tests that must exercise the global event bus.
|
|
487
|
+
|
|
480
488
|
Production task-created routes should fail closed:
|
|
481
489
|
|
|
482
490
|
- Require one explicit opt-in, either task metadata `route_enabled=true` or an
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side self_hosted cloud routing for the `todos` CLI.
|
|
3
|
+
*
|
|
4
|
+
* THE MISSING PIECE (B2): historically the CLI always read/wrote the local
|
|
5
|
+
* SQLite store even when a machine was flipped to `self_hosted` — there was
|
|
6
|
+
* ZERO `/v1` / bearer / API-URL code on the client, so `HASNA_TODOS_*` env had
|
|
7
|
+
* no effect. This module wires the CLI's task data path to the cloud HTTP API
|
|
8
|
+
* (`https://todos.hasna.xyz/v1`) via the LOCKED `@hasna/contracts` HTTP storage
|
|
9
|
+
* client whenever the client-flip contract resolves to `cloud-http`:
|
|
10
|
+
*
|
|
11
|
+
* mode = self_hosted (or cloud) AND HASNA_TODOS_API_URL AND HASNA_TODOS_API_KEY
|
|
12
|
+
*
|
|
13
|
+
* When those are set, ALL task reads and writes go to the cloud with the bearer
|
|
14
|
+
* key — NOT local, NOT a DSN. When they are unset, the client falls straight
|
|
15
|
+
* back to the local SQLite store. Misconfigured cloud (mode set but URL/key
|
|
16
|
+
* missing) THROWS via the contracts resolver so we never silently drift back to
|
|
17
|
+
* the wrong dataset.
|
|
18
|
+
*
|
|
19
|
+
* SAFETY: reversible by construction (unset the two env vars -> local). Never
|
|
20
|
+
* logs or embeds the API key (it lives only inside the transport). No DSN, no
|
|
21
|
+
* subnet routing — pure API-client path per the locked architecture.
|
|
22
|
+
*/
|
|
23
|
+
import { type HasnaStorageClient } from "@hasna/contracts/client/storage";
|
|
24
|
+
import type { Task, TaskFilter } from "../types/index.js";
|
|
25
|
+
type Env = Record<string, string | undefined>;
|
|
26
|
+
/**
|
|
27
|
+
* Resolve the todos cloud storage client from the environment. Returns a ready
|
|
28
|
+
* client when the flip resolves to `cloud-http`, or `null` for local. Throws
|
|
29
|
+
* when cloud is requested (mode=self_hosted/cloud) but the URL or key is missing
|
|
30
|
+
* — no silent local fallback for a misconfigured cloud request.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getTodosCloudClient(env?: Env): HasnaStorageClient | null;
|
|
33
|
+
/** True when the CLI should route task reads/writes to the cloud API. */
|
|
34
|
+
export declare function isCloudRouting(env?: Env): boolean;
|
|
35
|
+
/** Test hook: clear the memoized client (e.g. after mutating env in a test). */
|
|
36
|
+
export declare function resetTodosCloudClient(): void;
|
|
37
|
+
/** List tasks from the cloud (`GET /v1/tasks`). Returns the `tasks` array. */
|
|
38
|
+
export declare function cloudListTasks(client: HasnaStorageClient, filter?: TaskFilter): Promise<Task[]>;
|
|
39
|
+
/** Fetch one task by id (`GET /v1/tasks/:id`); `null` on 404. */
|
|
40
|
+
export declare function cloudGetTask(client: HasnaStorageClient, id: string): Promise<Task | null>;
|
|
41
|
+
/** Create a task (`POST /v1/tasks`, retry-safe idempotency key). */
|
|
42
|
+
export declare function cloudCreateTask(client: HasnaStorageClient, input: Record<string, unknown>): Promise<Task>;
|
|
43
|
+
/** Update a task (`PATCH /v1/tasks/:id`). */
|
|
44
|
+
export declare function cloudUpdateTask(client: HasnaStorageClient, id: string, patch: Record<string, unknown>): Promise<Task>;
|
|
45
|
+
/** Delete a task (`DELETE /v1/tasks/:id`); resolves for 2xx and 404. */
|
|
46
|
+
export declare function cloudDeleteTask(client: HasnaStorageClient, id: string): Promise<boolean>;
|
|
47
|
+
/** Run a task lifecycle action (`POST /v1/tasks/:id/{start|complete|fail|claim}`). */
|
|
48
|
+
export declare function cloudTaskAction(client: HasnaStorageClient, id: string, action: "start" | "complete" | "fail" | "claim", body?: Record<string, unknown>): Promise<Task>;
|
|
49
|
+
/** Queue status summary from the cloud (`GET /v1/stats`). */
|
|
50
|
+
export interface CloudStats {
|
|
51
|
+
tasks: number;
|
|
52
|
+
tasks_all?: number;
|
|
53
|
+
subtasks?: number;
|
|
54
|
+
projects?: number;
|
|
55
|
+
[key: string]: unknown;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Fetch the cloud queue summary (`GET /v1/stats`). Used by the MCP `get_status`
|
|
59
|
+
* tool so a flipped machine reports the shared cloud totals rather than its
|
|
60
|
+
* local SQLite island.
|
|
61
|
+
*/
|
|
62
|
+
export declare function cloudGetStats(client: HasnaStorageClient): Promise<CloudStats>;
|
|
63
|
+
/**
|
|
64
|
+
* Count tasks matching a filter. The `/v1/tasks` list response now returns a
|
|
65
|
+
* SQL-side `total` (full match count, independent of limit/offset), so we ask for
|
|
66
|
+
* a single row and read `total` instead of pulling the whole result set into the
|
|
67
|
+
* client (which previously loaded every matching task over HTTP just to count).
|
|
68
|
+
*/
|
|
69
|
+
export declare function cloudCountTasks(client: HasnaStorageClient, filter?: TaskFilter): Promise<number>;
|
|
70
|
+
export {};
|
|
71
|
+
//# sourceMappingURL=cloud-router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud-router.d.ts","sourceRoot":"","sources":["../../src/cli/cloud-router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAwB,KAAK,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAChG,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE1D,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAI9C;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,GAAwB,GAAG,kBAAkB,GAAG,IAAI,CAiB5F;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,GAAG,GAAE,GAAwB,GAAG,OAAO,CAErE;AAED,gFAAgF;AAChF,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAwBD,8EAA8E;AAC9E,wBAAsB,cAAc,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAIzG;AAED,iEAAiE;AACjE,wBAAsB,YAAY,CAAC,MAAM,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAG/F;AAED,oEAAoE;AACpE,wBAAsB,eAAe,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/G;AAED,6CAA6C;AAC7C,wBAAsB,eAAe,CAAC,MAAM,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3H;AAED,wEAAwE;AACxE,wBAAsB,eAAe,CAAC,MAAM,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG9F;AAED,sFAAsF;AACtF,wBAAsB,eAAe,CACnC,MAAM,EAAE,kBAAkB,EAC1B,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,EAC/C,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACjC,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAGnF;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAE,UAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ1G"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/project-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"project-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/project-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoJzC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QA24BvD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/storage-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"storage-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/storage-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2HzC,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe;;;;EAazF;AAYD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QA6LvD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/task-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"task-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/task-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwMzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QA+jCpD"}
|
package/dist/cli/helpers.d.ts
CHANGED
|
@@ -2,8 +2,30 @@ import { getPackageVersion } from "../lib/package-version.js";
|
|
|
2
2
|
import type { Project, Task } from "../types/index.js";
|
|
3
3
|
export { getPackageVersion };
|
|
4
4
|
export declare function handleError(e: unknown): never;
|
|
5
|
+
/**
|
|
6
|
+
* Resolve a user-supplied task reference (full UUID, id prefix, or short_id) to a
|
|
7
|
+
* canonical task id, CONSISTENTLY across every `todos` subcommand.
|
|
8
|
+
*
|
|
9
|
+
* Two rules make this safe whether the machine is `local` or flipped to the shared
|
|
10
|
+
* `self_hosted` cloud store:
|
|
11
|
+
*
|
|
12
|
+
* 1. A full task UUID is authoritative on its own — it is returned verbatim and is
|
|
13
|
+
* NEVER required to exist in this box's local SQLite mirror. On a flipped
|
|
14
|
+
* machine the task lives in the cloud and may have never synced down; the
|
|
15
|
+
* downstream read/write (cloud `GET/PATCH/POST /v1/tasks/:id` or a local query)
|
|
16
|
+
* is the single source of truth for existence and reports a precise not-found.
|
|
17
|
+
* This is what previously broke: resolver-based commands (comment, inspect,
|
|
18
|
+
* lock, deps, …) demanded the row be present locally, so they failed on
|
|
19
|
+
* cloud-only tasks even with a valid full UUID, while raw-id commands (show,
|
|
20
|
+
* update, start, done) worked — the reported inconsistency.
|
|
21
|
+
*
|
|
22
|
+
* 2. A short prefix / short_id is expanded against the local mirror, the only
|
|
23
|
+
* prefix index available client-side (the `/v1` API has no prefix lookup).
|
|
24
|
+
* Ambiguous or unknown prefixes fail loudly with actionable guidance.
|
|
25
|
+
*/
|
|
5
26
|
export declare function resolveTaskId(partialId: string): string;
|
|
6
27
|
export declare function detectGitRoot(): string | null;
|
|
28
|
+
export declare function shouldSkipAutoProjectForGitRoot(gitRoot: string): boolean;
|
|
7
29
|
/**
|
|
8
30
|
* Resolve an explicitly provided project reference by registered path, exact or
|
|
9
31
|
* partial ID, task list ID, slug, or name. An unresolvable reference is a hard
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/cli/helpers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/cli/helpers.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAK7B,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,KAAK,CAG7C;AAKD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CA8BvD;AAED,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAM7C;AAQD,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAMxE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAgC7D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,GAAG,SAAS,CAWjF;AAMD,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAE1E;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAUjD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,CAGlF;AA0BD,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAE7C;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAI7D;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAM9D,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAKhE,CAAC;AAEF,wBAAgB,cAAc,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAQ9C"}
|