@cbxss/tack-sdk 2.2.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/README.md +222 -0
- package/dist/client.d.ts +15 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +264 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +18 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +40 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/tools.d.ts +4 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +29 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +76 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/examples/dynamic.ts +13 -0
- package/examples/inline.ts +17 -0
- package/examples/tack.config.json +5 -0
- package/examples/tools.ts +11 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# @cbxss/tack-sdk
|
|
2
|
+
|
|
3
|
+
Call configured MCP, module, and plugin tools from a normal Node TypeScript script.
|
|
4
|
+
No Tack service, sandbox, or generation is required to execute tools.
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
npm install @cbxss/tack-sdk
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { Tack } from "@cbxss/tack-sdk";
|
|
12
|
+
|
|
13
|
+
const tack = new Tack({ configPath: "./tack.config.json" });
|
|
14
|
+
try {
|
|
15
|
+
const result = await tack.tools.kibana.kubelogs.search({
|
|
16
|
+
namespace: "xservice",
|
|
17
|
+
query: "level:error"
|
|
18
|
+
});
|
|
19
|
+
console.log(result.data);
|
|
20
|
+
} finally {
|
|
21
|
+
await tack.close();
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Paths and arguments above come from your configured tools, not a built-in Kibana
|
|
26
|
+
API. Node **22.18+** is required; Node 24 is the reference runtime. For
|
|
27
|
+
Node-compatible TypeScript, run `node script.ts` or compile with
|
|
28
|
+
`module: "NodeNext"`. **The SDK is ESM-only.** Compiling these `.ts` examples requires
|
|
29
|
+
`"type": "module"` in your project's `package.json`. For a new ESM project, use
|
|
30
|
+
`npm pkg set type=module`. In an existing CommonJS project, use `.mts` scripts
|
|
31
|
+
(emitted as `.mjs`) instead of changing the whole package's module mode.
|
|
32
|
+
Native Node TypeScript syntax detection is different from TypeScript compilation;
|
|
33
|
+
it does not make CommonJS `require("@cbxss/tack-sdk")` supported.
|
|
34
|
+
Browser and Bun runtime support are not promised.
|
|
35
|
+
|
|
36
|
+
## Strong typing with the same import
|
|
37
|
+
|
|
38
|
+
Enable project declarations once, using the separately installed Tack CLI:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
npm install -D typescript @types/node
|
|
42
|
+
npm pkg set type=module # for the .ts examples; use .mts instead in a CommonJS project
|
|
43
|
+
npx @cbxss/tack init --sdk
|
|
44
|
+
# Configure servers in tack.config.json, if not already configured.
|
|
45
|
+
npx @cbxss/tack build
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`init --sdk` preserves an existing config's servers and adds:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{ "sdk": { "tsconfig": "./tsconfig.json" } }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`build` discovers the configured servers, writes a schema snapshot under
|
|
55
|
+
`.tack/types/`, and explicitly includes its declaration file in the TypeScript
|
|
56
|
+
project. It preserves existing compiler options, comments, source inclusion, and
|
|
57
|
+
inherited settings. If necessary, it creates a minimal Node `tsconfig.json` with
|
|
58
|
+
`types: ["node"]` and source inclusion covering `.ts`, `.mts`, `.cts`, and `.tsx`.
|
|
59
|
+
Existing projects must already include the Node types their scripts need; build
|
|
60
|
+
never replaces their compiler type selections. It refuses to replace manual
|
|
61
|
+
declarations or follow symlinked declaration targets.
|
|
62
|
+
|
|
63
|
+
**Your script does not change.** Import `Tack` from `@cbxss/tack-sdk` as above;
|
|
64
|
+
there is no generated client to import and no `<TackTools>` parameter to supply.
|
|
65
|
+
Within that project, TypeScript checks known tool paths, required arguments,
|
|
66
|
+
argument types, and output types when the server provides an output schema.
|
|
67
|
+
|
|
68
|
+
Run `tack build` again after changing servers or their schemas. This is an explicit
|
|
69
|
+
network discovery step; importing or constructing `Tack` never generates files.
|
|
70
|
+
Generated types are a snapshot, not a guarantee that the live server still matches.
|
|
71
|
+
Input validation and policy checks remain live; advisory output-schema mismatches
|
|
72
|
+
never suppress a successful result. Missing output schemas produce `unknown`.
|
|
73
|
+
|
|
74
|
+
### Config and project boundaries
|
|
75
|
+
|
|
76
|
+
- Run scripts from the TypeScript project's directory. Config strings are still
|
|
77
|
+
resolved relative to the construction-time working directory, not the script file.
|
|
78
|
+
- Literal config paths acquire only their own catalog. For a root config, both
|
|
79
|
+
`"./tack.config.json"` and `"tack.config.json"` work; `new Tack()` uses this default.
|
|
80
|
+
- Other registered config files can coexist without merging their tool trees.
|
|
81
|
+
Each must be inside the project's directory tree. Enable and build each using
|
|
82
|
+
`--config`; use `init --sdk --tsconfig <path>` to select their shared project.
|
|
83
|
+
The tsconfig setting resolves relative to each Tack config file.
|
|
84
|
+
- Arbitrary string variables, absolute paths, unregistered configs, inline configs,
|
|
85
|
+
and supplied empty/erased options (`{}`) stay dynamic. Only absent options
|
|
86
|
+
(`new Tack()` or `new Tack(undefined)`) select the default binding implicitly.
|
|
87
|
+
Use a literal path (or a `const` preserving its literal type) for another binding.
|
|
88
|
+
- The compiler/editor must load the configured tsconfig. `tsc -p tsconfig.json`
|
|
89
|
+
does; `tsc script.ts` bypasses it. A loose script outside the project can still
|
|
90
|
+
run, but does not automatically inherit project declarations.
|
|
91
|
+
- For monorepos, select the tsconfig that actually owns the scripts. Project
|
|
92
|
+
references do not propagate declaration inclusion into referenced projects.
|
|
93
|
+
- To disable a binding, remove its entry from the tsconfig's `files` list and
|
|
94
|
+
delete the corresponding generated declaration. Removing `sdk` from Tack config
|
|
95
|
+
stops future refreshes; it does not edit existing TypeScript bindings.
|
|
96
|
+
|
|
97
|
+
Without a loaded binding, paths are dynamic, inputs are object-shaped, and `.data`
|
|
98
|
+
is `unknown`. With `noUncheckedIndexedAccess`, dynamic segments require
|
|
99
|
+
narrowing/non-null assertions; registered paths have known properties instead.
|
|
100
|
+
|
|
101
|
+
Plain `Tack` annotations work for variables, collections, and factory returns.
|
|
102
|
+
They describe the default config's tool tree (dynamic when unbound); retain the
|
|
103
|
+
inferred instance type when working with a different registered catalog.
|
|
104
|
+
|
|
105
|
+
Legacy `tack generate` is unchanged: it emits the static `createTackClient` API
|
|
106
|
+
and code-mode declarations. `tack build` does the same in projects without the
|
|
107
|
+
`sdk` setting. Static-only consumers need no live SDK dependency. Don't include
|
|
108
|
+
legacy ambient `tools.d.ts` in a direct-SDK script project.
|
|
109
|
+
|
|
110
|
+
## Configuration and discovery
|
|
111
|
+
|
|
112
|
+
`new Tack()` uses `tack.config.json` in the construction-time working directory.
|
|
113
|
+
A config file's source entries, plugin paths, and stdio `cwd` resolve relative to
|
|
114
|
+
that file. Module `entry` strings are runtime paths, not TypeScript imports: when
|
|
115
|
+
compiling a module, point at its emitted `.js` file. The runnable inline example
|
|
116
|
+
handles native `.ts`/`.mts` and compiled `.js`/`.mjs` fixture paths. Alternatively, supply inline
|
|
117
|
+
config (dynamic typing):
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
const tack = new Tack({
|
|
121
|
+
config: { servers: { local: { transport: "module", entry: "./tools.ts" } } },
|
|
122
|
+
configDir: import.meta.dirname
|
|
123
|
+
});
|
|
124
|
+
try {
|
|
125
|
+
await tack.ready(); // optional: first call otherwise initializes lazily
|
|
126
|
+
const matches = await tack.search({ query: "echo" });
|
|
127
|
+
const description = await tack.describe("local.echo");
|
|
128
|
+
const result = await tack.call("local.echo", { message: "hello" });
|
|
129
|
+
} finally {
|
|
130
|
+
await tack.close();
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Do not combine `config` and `configPath`. Configuration selectors (`config`,
|
|
135
|
+
`configPath`, `configDir`) must be own data properties: accessors and inherited
|
|
136
|
+
selectors are rejected with `invalid_options`, never evaluated or silently ignored.
|
|
137
|
+
`configDir` defaults to the construction-time cwd. The client snapshots its config and catalog, shares
|
|
138
|
+
initialization between callers, and reuses transports. There is no automatic
|
|
139
|
+
refresh or retry; create another client after a config change or initialization
|
|
140
|
+
failure. Discovery uses temporary connections separate from invocation, so a
|
|
141
|
+
stdio server may start more than once per client.
|
|
142
|
+
|
|
143
|
+
Reflection-sensitive paths (such as `name`, `length`, `call`, `constructor`,
|
|
144
|
+
`then`, or `toJSON`) are not exposed through the dot tree. Use the canonical
|
|
145
|
+
path with `tack.call(path, args)` instead; it retains the same validation and policy
|
|
146
|
+
checks and deliberately returns unknown data. Find canonical paths with `search`.
|
|
147
|
+
|
|
148
|
+
## Results, errors, and cancellation
|
|
149
|
+
|
|
150
|
+
Successful calls return `{ ok: true, data, dataShape, upstreamOutcome: "succeeded",
|
|
151
|
+
responseId: null }`. Data uses structured content first, otherwise parsed JSON
|
|
152
|
+
text (including `null`), otherwise plain text. There is no durable response store
|
|
153
|
+
or sandbox truncation. Configured response whitespace normalization remains
|
|
154
|
+
opt-in; outgoing arguments are never rewritten.
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import { Tack, TackError } from "@cbxss/tack-sdk";
|
|
158
|
+
|
|
159
|
+
const tack = new Tack({ configPath: "./tack.config.json" });
|
|
160
|
+
try {
|
|
161
|
+
const result = await tack.call("kibana.kubelogs.search", { query: "error" }, {
|
|
162
|
+
signal: AbortSignal.timeout(10_000),
|
|
163
|
+
timeoutMs: 5_000
|
|
164
|
+
});
|
|
165
|
+
console.log(result.data);
|
|
166
|
+
} catch (error) {
|
|
167
|
+
if (!(error instanceof TackError)) throw error;
|
|
168
|
+
console.error(error.code, error.path, error.upstreamOutcome, error.message);
|
|
169
|
+
// Never automatically replay a write with an unknown upstream outcome.
|
|
170
|
+
} finally {
|
|
171
|
+
await tack.close();
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Dot methods accept the same optional second argument. For an optional-input tool,
|
|
176
|
+
use `method(undefined, { timeoutMs: 5000 })`. A caller timeout covers its wait for
|
|
177
|
+
initialization plus execution without cancelling another caller's discovery.
|
|
178
|
+
`runtime.toolTimeoutMs` remains the default downstream timeout if no per-call
|
|
179
|
+
override is supplied. Timeouts must be integer milliseconds from 1 to 2147483647.
|
|
180
|
+
Search and describe also accept call options.
|
|
181
|
+
|
|
182
|
+
Invalid inputs, policy denials, unknown operations, upstream failures, cancellation,
|
|
183
|
+
and timeouts reject with `TackError`; `code`, `path`, `upstreamOutcome`, and an
|
|
184
|
+
available `cause` explain the failure. There are no automatic retries.
|
|
185
|
+
|
|
186
|
+
Always close your client. `close()` is idempotent, prevents new calls, cancels
|
|
187
|
+
active callers, and closes owned transports, including resources allocated during
|
|
188
|
+
initialization. Local handlers must cooperate with cancellation; close waits for
|
|
189
|
+
in-flight discovery. Cancelling an already-dispatched stdio request can retire its
|
|
190
|
+
shared connection and affect other active calls. There are no global signal
|
|
191
|
+
handlers. `[Symbol.asyncDispose]()` aliases `close()` for runtimes supporting
|
|
192
|
+
`await using`.
|
|
193
|
+
|
|
194
|
+
## Examples and package verification
|
|
195
|
+
|
|
196
|
+
See [`examples/`](./examples/) for a fixture-only config, module, and direct-import
|
|
197
|
+
scripts. Copy them into your project (outside `node_modules`) and install
|
|
198
|
+
`@cbxss/tack-sdk` plus `@cbxss/tack-sources` for module authoring:
|
|
199
|
+
|
|
200
|
+
```sh
|
|
201
|
+
node dynamic.ts
|
|
202
|
+
node inline.ts
|
|
203
|
+
# Optional project typing and compilation, using the same scripts:
|
|
204
|
+
npm install -D typescript @types/node
|
|
205
|
+
npm pkg set type=module
|
|
206
|
+
npx @cbxss/tack init --sdk
|
|
207
|
+
npx @cbxss/tack build
|
|
208
|
+
npx tsc -p tsconfig.json --noEmit
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Repository maintainers can validate a clean tarball consumer without publishing:
|
|
212
|
+
|
|
213
|
+
```sh
|
|
214
|
+
bun run build
|
|
215
|
+
bun run --cwd packages/sdk test:consumer
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
This packs the SDK and its internal dependencies, installs them into a disposable
|
|
219
|
+
npm project without workspace links, checks strict TypeScript 5.9 and 7 consumers
|
|
220
|
+
with and without config bindings, and runs fixture calls with forbidden-import
|
|
221
|
+
guards. It also checks legacy generation without the live SDK. It needs registry
|
|
222
|
+
access for external dependencies. No live user MCP servers are contacted.
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TackArgs, TackCallOptions, TackDescription, TackOptions, TackResponse, TackSearchInput, TackSearchResult } from "./types.js";
|
|
2
|
+
/** Internal implementation: instance compatibility depends on tools, not options.
|
|
3
|
+
* The public constructor in index.ts binds these tools to runtime config options. */
|
|
4
|
+
export declare class Tack<Tools> {
|
|
5
|
+
#private;
|
|
6
|
+
readonly tools: Tools;
|
|
7
|
+
constructor(options?: TackOptions);
|
|
8
|
+
ready(): Promise<void>;
|
|
9
|
+
call(path: string, args?: TackArgs, options?: TackCallOptions): Promise<TackResponse>;
|
|
10
|
+
search(input?: TackSearchInput, options?: TackCallOptions): Promise<TackSearchResult>;
|
|
11
|
+
describe(path: string, options?: TackCallOptions): Promise<TackDescription>;
|
|
12
|
+
close(): Promise<void>;
|
|
13
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,QAAQ,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EACvD,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAChD,MAAM,YAAY,CAAC;AAgCpB;qFACqF;AACrF,qBAAa,IAAI,CAAC,KAAK;;IACrB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAWtB,YAAY,OAAO,CAAC,EAAE,WAAW,EAiBhC;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAG3B;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,QAAa,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,YAAY,CAAC,CAW5F;IAED,MAAM,CAAC,KAAK,GAAE,eAA+B,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CASvG;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,eAAe,CAAC,CAW9E;IAED,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBrB;IAED,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAyB;CAkHhE"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { dirname, resolve } from "node:path";
|
|
2
|
+
import { DEFAULT_CONFIG_PATH, listOperations, loadConfigPromise, ownField, parseConfig, resolveConfigPaths, sanitizeData, snapshotManifest } from "@cbxss/tack-core";
|
|
3
|
+
import { CodeRuntimeTimeoutError, createAuditSink, createOperationPolicy, createTackToolInvoker, describeTool, isOperationAllowed, searchOperations, withAbort } from "@cbxss/tack-codemode";
|
|
4
|
+
import { resolvePluginsIntoConfig } from "@cbxss/tack-plugin";
|
|
5
|
+
import { createRuntime, discoverManifest, SOURCE_KINDS } from "@cbxss/tack-sources";
|
|
6
|
+
import { invocationError, responseOrThrow, TackError } from "./errors.js";
|
|
7
|
+
import { createTools } from "./tools.js";
|
|
8
|
+
/** Selectors must be own data properties: skipping a getter/inherited selector
|
|
9
|
+
* would silently change the config being selected. Never invoke accessors. */
|
|
10
|
+
function readConfigSelectors(options) {
|
|
11
|
+
if (options === undefined)
|
|
12
|
+
return {};
|
|
13
|
+
try {
|
|
14
|
+
if (typeof options !== "object" || options === null || Array.isArray(options)) {
|
|
15
|
+
throw new Error("Tack options must be an object");
|
|
16
|
+
}
|
|
17
|
+
const selectors = {};
|
|
18
|
+
for (const key of ["config", "configPath", "configDir"]) {
|
|
19
|
+
const descriptor = Object.getOwnPropertyDescriptor(options, key);
|
|
20
|
+
if (descriptor) {
|
|
21
|
+
if (!("value" in descriptor))
|
|
22
|
+
throw new Error(`${key} must be an own data property, not an accessor`);
|
|
23
|
+
selectors[key] = descriptor.value;
|
|
24
|
+
}
|
|
25
|
+
else if (key in options) {
|
|
26
|
+
throw new Error(`${key} must be an own data property, not inherited`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return selectors;
|
|
30
|
+
}
|
|
31
|
+
catch (cause) {
|
|
32
|
+
throw new TackError("Invalid Tack configuration selectors", { code: "invalid_options", cause });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Internal implementation: instance compatibility depends on tools, not options.
|
|
36
|
+
* The public constructor in index.ts binds these tools to runtime config options. */
|
|
37
|
+
export class Tack {
|
|
38
|
+
tools;
|
|
39
|
+
#configPath;
|
|
40
|
+
#inlineConfig;
|
|
41
|
+
#configDir;
|
|
42
|
+
#cwd;
|
|
43
|
+
#initialization;
|
|
44
|
+
#runtime;
|
|
45
|
+
#closed = false;
|
|
46
|
+
#closing;
|
|
47
|
+
#calls = new Map();
|
|
48
|
+
constructor(options) {
|
|
49
|
+
this.#cwd = process.cwd();
|
|
50
|
+
const { config, configPath, configDir } = readConfigSelectors(options);
|
|
51
|
+
if ((config !== undefined && configPath !== undefined)
|
|
52
|
+
|| (config === undefined && configDir !== undefined)
|
|
53
|
+
|| (configPath !== undefined && (typeof configPath !== "string" || !configPath))
|
|
54
|
+
|| (configDir !== undefined && (typeof configDir !== "string" || !configDir))) {
|
|
55
|
+
throw new TackError("Use configPath or inline config with configDir, not both", { code: "invalid_options" });
|
|
56
|
+
}
|
|
57
|
+
this.#configPath = config === undefined ? resolve(this.#cwd, configPath ?? DEFAULT_CONFIG_PATH) : undefined;
|
|
58
|
+
this.#configDir = this.#configPath ? dirname(this.#configPath) : resolve(this.#cwd, configDir ?? ".");
|
|
59
|
+
try {
|
|
60
|
+
this.#inlineConfig = sanitizeData(config, { onCycle: "Cyclic Tack config data is not supported" });
|
|
61
|
+
}
|
|
62
|
+
catch (cause) {
|
|
63
|
+
throw new TackError("Invalid inline Tack config", { code: "invalid_options", cause });
|
|
64
|
+
}
|
|
65
|
+
this.tools = createTools((path, args, callOptions) => this.call(path, args, callOptions));
|
|
66
|
+
}
|
|
67
|
+
async ready() {
|
|
68
|
+
await this.#ensureInitialized();
|
|
69
|
+
this.#assertOpen();
|
|
70
|
+
}
|
|
71
|
+
call(path, args = {}, options = {}) {
|
|
72
|
+
let snapshot;
|
|
73
|
+
try {
|
|
74
|
+
snapshot = sanitizeData(args, { onCycle: "Cyclic tool arguments are not supported" });
|
|
75
|
+
}
|
|
76
|
+
catch (cause) {
|
|
77
|
+
return Promise.reject(new TackError("Invalid tool arguments", { code: "input_validation_failed", path, cause }));
|
|
78
|
+
}
|
|
79
|
+
return this.#run(path, options, async (signal, timeoutMs) => {
|
|
80
|
+
const state = await this.#waitForInitialization(signal, path);
|
|
81
|
+
try {
|
|
82
|
+
const output = await state.invoker.invoke({ path, args: snapshot, signal, timeoutMs: timeoutMs === undefined ? undefined : null });
|
|
83
|
+
return responseOrThrow(output, path);
|
|
84
|
+
}
|
|
85
|
+
catch (cause) {
|
|
86
|
+
throw invocationError(cause, path);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
search(input = { query: "" }, options = {}) {
|
|
91
|
+
let snapshot;
|
|
92
|
+
try {
|
|
93
|
+
snapshot = sanitizeData(input, {});
|
|
94
|
+
}
|
|
95
|
+
catch (cause) {
|
|
96
|
+
return Promise.reject(new TackError("Invalid search input", { code: "invalid_options", cause }));
|
|
97
|
+
}
|
|
98
|
+
return this.#run(undefined, options, async (signal) => {
|
|
99
|
+
const state = await this.#waitForInitialization(signal);
|
|
100
|
+
// Discovery metadata shares the invoker's cached operation graph; never expose it.
|
|
101
|
+
return sanitizeData(searchOperations(state.manifest, snapshot, state.policy), {});
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
describe(path, options = {}) {
|
|
105
|
+
return this.#run(path, options, async (signal) => {
|
|
106
|
+
const state = await this.#waitForInitialization(signal, path);
|
|
107
|
+
const operation = listOperations(state.manifest).find(operation => operation.fullPathString === path);
|
|
108
|
+
if (!operation)
|
|
109
|
+
throw new TackError(`Unknown Tack operation: ${path}`, { code: "unknown_operation", path });
|
|
110
|
+
const decision = isOperationAllowed(operation, state.policy);
|
|
111
|
+
if (!decision.allowed)
|
|
112
|
+
throw new TackError(decision.reason ?? `Operation denied: ${path}`, { code: "operation_denied", path });
|
|
113
|
+
const result = await withAbort(describeTool(state.manifest, { path }, state.policy), signal);
|
|
114
|
+
if ("error" in result)
|
|
115
|
+
throw new TackError(result.error.message, { code: "unknown_operation", path });
|
|
116
|
+
return sanitizeData(result, {});
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
close() {
|
|
120
|
+
if (this.#closing)
|
|
121
|
+
return this.#closing;
|
|
122
|
+
this.#closed = true;
|
|
123
|
+
for (const controller of this.#calls.keys())
|
|
124
|
+
controller.abort(new Error("Tack client is closed"));
|
|
125
|
+
this.#closing = (async () => {
|
|
126
|
+
// Initialization owns temporary discovery connections; never abandon it.
|
|
127
|
+
await this.#initialization?.catch(() => undefined);
|
|
128
|
+
try {
|
|
129
|
+
await this.#runtime?.close();
|
|
130
|
+
}
|
|
131
|
+
catch (cause) {
|
|
132
|
+
throw new TackError("Failed to close Tack transports", { code: "internal_error", cause });
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
await Promise.allSettled([...this.#calls.values()]);
|
|
136
|
+
}
|
|
137
|
+
})();
|
|
138
|
+
return this.#closing;
|
|
139
|
+
}
|
|
140
|
+
[Symbol.asyncDispose]() { return this.close(); }
|
|
141
|
+
#assertOpen(path) {
|
|
142
|
+
if (this.#closed)
|
|
143
|
+
throw new TackError("Tack client is closed", { code: "client_closed", path });
|
|
144
|
+
}
|
|
145
|
+
#ensureInitialized() {
|
|
146
|
+
this.#assertOpen();
|
|
147
|
+
return this.#initialization ??= this.#initialize();
|
|
148
|
+
}
|
|
149
|
+
async #initialize() {
|
|
150
|
+
try {
|
|
151
|
+
const loaded = this.#configPath
|
|
152
|
+
? await loadConfigPromise(this.#configPath, SOURCE_KINDS)
|
|
153
|
+
: resolveConfigPaths(parseConfig(this.#inlineConfig, SOURCE_KINDS), this.#configDir, SOURCE_KINDS);
|
|
154
|
+
this.#assertOpen();
|
|
155
|
+
const config = await resolvePluginsIntoConfig(loaded, { configDir: this.#configDir });
|
|
156
|
+
this.#assertOpen();
|
|
157
|
+
const manifest = snapshotManifest(await discoverManifest(config, { configDir: this.#configDir }));
|
|
158
|
+
this.#assertOpen();
|
|
159
|
+
this.#runtime = await createRuntime({ config, manifest, configDir: this.#configDir });
|
|
160
|
+
this.#assertOpen();
|
|
161
|
+
const policy = createOperationPolicy(config);
|
|
162
|
+
// Audit paths historically use cwd, unlike source paths. Anchor that cwd
|
|
163
|
+
// at construction so later chdir cannot redirect configured evidence.
|
|
164
|
+
const auditPath = config.security?.auditLog?.path;
|
|
165
|
+
const auditConfig = auditPath ? {
|
|
166
|
+
...config, security: { ...config.security, auditLog: { path: resolve(this.#cwd, auditPath) } }
|
|
167
|
+
} : config;
|
|
168
|
+
const invoker = createTackToolInvoker({
|
|
169
|
+
manifest, runtime: this.#runtime, policy, canonicalOperationsOnly: true,
|
|
170
|
+
toolTimeoutMs: config.runtime?.toolTimeoutMs,
|
|
171
|
+
normalizeWhitespace: config.runtime?.normalizeWhitespace,
|
|
172
|
+
onAuditEvent: createAuditSink(auditConfig)
|
|
173
|
+
});
|
|
174
|
+
return { manifest, invoker, policy };
|
|
175
|
+
}
|
|
176
|
+
catch (cause) {
|
|
177
|
+
// Keep a stable initialization failure; cleanup must not replace its cause.
|
|
178
|
+
await this.#runtime?.close().catch(() => undefined);
|
|
179
|
+
this.#runtime = undefined;
|
|
180
|
+
if (cause instanceof TackError)
|
|
181
|
+
throw cause;
|
|
182
|
+
throw new TackError("Failed to initialize Tack", { code: "initialization_failed", cause });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async #waitForInitialization(signal, path) {
|
|
186
|
+
if (signal.aborted)
|
|
187
|
+
throw this.#cancelled(signal, path);
|
|
188
|
+
// A caller may stop waiting, but cannot cancel another caller's discovery.
|
|
189
|
+
let state;
|
|
190
|
+
try {
|
|
191
|
+
state = await withAbort(this.#ensureInitialized(), signal);
|
|
192
|
+
}
|
|
193
|
+
catch (cause) {
|
|
194
|
+
if (cause instanceof TackError && path !== undefined && cause.path === undefined) {
|
|
195
|
+
throw new TackError(cause.message, { code: cause.code, path, upstreamOutcome: cause.upstreamOutcome, cause });
|
|
196
|
+
}
|
|
197
|
+
throw cause;
|
|
198
|
+
}
|
|
199
|
+
this.#assertOpen(path);
|
|
200
|
+
signal.throwIfAborted();
|
|
201
|
+
return state;
|
|
202
|
+
}
|
|
203
|
+
#cancelled(signal, path) {
|
|
204
|
+
return new TackError("Tack call cancelled", { code: "cancelled", path, cause: signal.reason });
|
|
205
|
+
}
|
|
206
|
+
#run(path, options, run) {
|
|
207
|
+
try {
|
|
208
|
+
this.#assertOpen(path);
|
|
209
|
+
const timeoutMs = ownField(options, "timeoutMs");
|
|
210
|
+
if (timeoutMs !== undefined && (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2_147_483_647)) {
|
|
211
|
+
throw new TackError("timeoutMs must be an integer between 1 and 2147483647", { code: "invalid_options", path });
|
|
212
|
+
}
|
|
213
|
+
const external = ownField(options, "signal");
|
|
214
|
+
if (external !== undefined && !(external instanceof AbortSignal)) {
|
|
215
|
+
throw new TackError("signal must be an AbortSignal", { code: "invalid_options", path });
|
|
216
|
+
}
|
|
217
|
+
const controller = new AbortController();
|
|
218
|
+
const abort = () => controller.abort(external?.reason);
|
|
219
|
+
if (external?.aborted)
|
|
220
|
+
abort();
|
|
221
|
+
else
|
|
222
|
+
external?.addEventListener("abort", abort, { once: true });
|
|
223
|
+
// One caller deadline spans discovery waiting and downstream work. Shared
|
|
224
|
+
// initialization itself is never aborted by this controller.
|
|
225
|
+
let timedOut = false;
|
|
226
|
+
const timer = timeoutMs === undefined ? undefined : setTimeout(() => {
|
|
227
|
+
if (controller.signal.aborted)
|
|
228
|
+
return;
|
|
229
|
+
timedOut = true;
|
|
230
|
+
controller.abort(new CodeRuntimeTimeoutError(`Tack request timed out after ${timeoutMs}ms`));
|
|
231
|
+
}, timeoutMs);
|
|
232
|
+
// Defer work until registered so close() sees even synchronous call starts.
|
|
233
|
+
const pending = Promise.resolve().then(() => run(controller.signal, timeoutMs)).then(value => {
|
|
234
|
+
if (controller.signal.aborted)
|
|
235
|
+
throw new TackError("Tack call cancelled", {
|
|
236
|
+
code: "cancelled", path, cause: controller.signal.reason,
|
|
237
|
+
upstreamOutcome: ownField(value, "upstreamOutcome") ?? "not_started"
|
|
238
|
+
});
|
|
239
|
+
return value;
|
|
240
|
+
}).catch((cause) => {
|
|
241
|
+
if (timedOut)
|
|
242
|
+
throw new TackError(`Tack request timed out after ${timeoutMs}ms`, {
|
|
243
|
+
code: "tool_timeout", path, cause,
|
|
244
|
+
upstreamOutcome: cause instanceof TackError ? cause.upstreamOutcome : "not_started"
|
|
245
|
+
});
|
|
246
|
+
if (cause instanceof TackError)
|
|
247
|
+
throw cause;
|
|
248
|
+
if (controller.signal.aborted)
|
|
249
|
+
throw this.#cancelled(controller.signal, path);
|
|
250
|
+
throw new TackError(cause instanceof Error ? cause.message : "Tack request failed", { code: "internal_error", path, cause });
|
|
251
|
+
}).finally(() => {
|
|
252
|
+
clearTimeout(timer);
|
|
253
|
+
external?.removeEventListener("abort", abort);
|
|
254
|
+
this.#calls.delete(controller);
|
|
255
|
+
});
|
|
256
|
+
this.#calls.set(controller, pending);
|
|
257
|
+
return pending;
|
|
258
|
+
}
|
|
259
|
+
catch (cause) {
|
|
260
|
+
return Promise.reject(cause);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EACL,mBAAmB,EAAE,cAAc,EAAE,iBAAiB,EAAE,QAAQ,EAAE,WAAW,EAC7E,kBAAkB,EAAE,YAAY,EAAE,gBAAgB,EAEnD,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,uBAAuB,EAAE,eAAe,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,YAAY,EACpG,kBAAkB,EAAE,gBAAgB,EAAE,SAAS,EAEhD,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAMzC;8EAC8E;AAC9E,SAAS,mBAAmB,CAAC,OAAgB;IAC3C,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9E,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;QACD,MAAM,SAAS,GAAoE,EAAE,CAAC;QACtF,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,WAAW,CAAU,EAAE,CAAC;YACjE,MAAM,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACjE,IAAI,UAAU,EAAE,CAAC;gBACf,IAAI,CAAC,CAAC,OAAO,IAAI,UAAU,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,gDAAgD,CAAC,CAAC;gBACtG,SAAS,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC;YACpC,CAAC;iBAAM,IAAI,GAAG,IAAI,OAAO,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,8CAA8C,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,sCAAsC,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC,CAAC;IAClG,CAAC;AACH,CAAC;AAQD;qFACqF;AACrF,MAAM,OAAO,IAAI;IACN,KAAK,CAAQ;IACtB,WAAW,CAAqB;IAChC,aAAa,CAAU;IACvB,UAAU,CAAS;IACnB,IAAI,CAAS;IACb,eAAe,CAAmC;IAClD,QAAQ,CAA0B;IAClC,OAAO,GAAG,KAAK,CAAC;IAChB,QAAQ,CAA4B;IACpC,MAAM,GAAG,IAAI,GAAG,EAAqC,CAAC;IAEtD,YAAY,OAAqB;QAC/B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1B,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,CAAC;eACjD,CAAC,MAAM,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS,CAAC;eACjD,CAAC,UAAU,KAAK,SAAS,IAAI,CAAC,OAAO,UAAU,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,CAAC;eAC7E,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;YAChF,MAAM,IAAI,SAAS,CAAC,0DAA0D,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAC/G,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,UAAoB,IAAI,mBAAmB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACtH,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,SAAmB,IAAI,GAAG,CAAC,CAAC;QAChH,IAAI,CAAC;YACH,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,0CAA0C,EAAE,CAAC,CAAC;QACrG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,SAAS,CAAC,4BAA4B,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC,CAAC;QACxF,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAU,CAAC;IACrG,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAChC,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,CAAC,IAAY,EAAE,IAAI,GAAa,EAAE,EAAE,OAAO,GAAoB,EAAE;QACnE,IAAI,QAAiB,CAAC;QACtB,IAAI,CAAC;YAAC,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,yCAAyC,EAAE,CAAC,CAAC;QAAC,CAAC;QAC9F,OAAO,KAAK,EAAE,CAAC;YAAC,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,wBAAwB,EAAE,EAAE,IAAI,EAAE,yBAAyB,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QAAC,CAAC;QACnI,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE;YAC1D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC9D,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBACnI,OAAO,eAAe,CAAC,MAAwB,EAAE,IAAI,CAAC,CAAC;YACzD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAAC,MAAM,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAAC,CAAC;QACzD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,KAAK,GAAoB,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,GAAoB,EAAE;QAC1E,IAAI,QAAyB,CAAC;QAC9B,IAAI,CAAC;YAAC,QAAQ,GAAG,YAAY,CAAC,KAAK,EAAE,EAAE,CAAoB,CAAC;QAAC,CAAC;QAC9D,OAAO,KAAK,EAAE,CAAC;YAAC,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QAAC,CAAC;QACnH,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;YAClD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;YACxD,mFAAmF;YACnF,OAAO,YAAY,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,CAAqB,CAAC;QACxG,CAAC,CAAC,CAAC;IACL,CAAC;IAED,QAAQ,CAAC,IAAY,EAAE,OAAO,GAAoB,EAAE;QAClD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;YAC7C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC9D,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,cAAc,KAAK,IAAI,CAAC,CAAC;YACtG,IAAI,CAAC,SAAS;gBAAE,MAAM,IAAI,SAAS,CAAC,2BAA2B,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5G,MAAM,QAAQ,GAAG,kBAAkB,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YAC7D,IAAI,CAAC,QAAQ,CAAC,OAAO;gBAAE,MAAM,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,IAAI,qBAAqB,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/H,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;YAC7F,IAAI,OAAO,IAAI,MAAM;gBAAE,MAAM,IAAI,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;YACtG,OAAO,YAAY,CAAC,MAAM,EAAE,EAAE,CAAoB,CAAC;QACrD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC,QAAQ,CAAC;QACxC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;YAAE,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC;QAClG,IAAI,CAAC,QAAQ,GAAG,CAAC,KAAK,IAAI,EAAE;YAC1B,yEAAyE;YACzE,MAAM,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACnD,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC;YAC/B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,SAAS,CAAC,iCAAiC,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,CAAC;YAC5F,CAAC;oBAAS,CAAC;gBACT,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACtD,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QACL,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,CAAC,MAAM,CAAC,YAAY,CAAC,KAAoB,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAE/D,WAAW,CAAC,IAAa;QACvB,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,SAAS,CAAC,uBAAuB,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;IAClG,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC,eAAe,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW;gBAC7B,CAAC,CAAC,MAAM,iBAAiB,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC;gBACzD,CAAC,CAAC,kBAAkB,CAAC,WAAW,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;YACrG,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YACtF,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,gBAAgB,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;YAClG,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,GAAG,MAAM,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YACtF,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;YAC7C,yEAAyE;YACzE,sEAAsE;YACtE,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC;YAClD,MAAM,WAAW,GAAe,SAAS,CAAC,CAAC,CAAC;gBAC1C,GAAG,MAAM,EAAE,QAAQ,EAAE,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE;aAC/F,CAAC,CAAC,CAAC,MAAM,CAAC;YACX,MAAM,OAAO,GAAG,qBAAqB,CAAC;gBACpC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,uBAAuB,EAAE,IAAI;gBACvE,aAAa,EAAE,MAAM,CAAC,OAAO,EAAE,aAAa;gBAC5C,mBAAmB,EAAE,MAAM,CAAC,OAAO,EAAE,mBAAmB;gBACxD,YAAY,EAAE,eAAe,CAAC,WAAW,CAAC;aAC3C,CAAC,CAAC;YACH,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QACvC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,4EAA4E;YAC5E,MAAM,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACpD,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;YAC1B,IAAI,KAAK,YAAY,SAAS;gBAAE,MAAM,KAAK,CAAC;YAC5C,MAAM,IAAI,SAAS,CAAC,2BAA2B,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,MAAmB,EAAE,IAAa;QAC7D,IAAI,MAAM,CAAC,OAAO;YAAE,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACxD,2EAA2E;QAC3E,IAAI,KAAkB,CAAC;QACvB,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,MAAM,CAAC,CAAC;QAC7D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,SAAS,IAAI,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACjF,MAAM,IAAI,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;YAChH,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACvB,MAAM,CAAC,cAAc,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,UAAU,CAAC,MAAmB,EAAE,IAAa;QAC3C,OAAO,IAAI,SAAS,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACjG,CAAC;IAED,IAAI,CAAI,IAAwB,EAAE,OAAwB,EAAE,GAAuE;QACjI,IAAI,CAAC;YACH,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YACvB,MAAM,SAAS,GAAG,QAAQ,CAAS,OAAO,EAAE,WAAW,CAAC,CAAC;YACzD,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC,IAAI,SAAS,GAAG,aAAa,CAAC,EAAE,CAAC;gBACjH,MAAM,IAAI,SAAS,CAAC,uDAAuD,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC;YAClH,CAAC;YACD,MAAM,QAAQ,GAAG,QAAQ,CAAc,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC1D,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,YAAY,WAAW,CAAC,EAAE,CAAC;gBACjE,MAAM,IAAI,SAAS,CAAC,+BAA+B,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1F,CAAC;YACD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACvD,IAAI,QAAQ,EAAE,OAAO;gBAAE,KAAK,EAAE,CAAC;;gBAC1B,QAAQ,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,0EAA0E;YAC1E,6DAA6D;YAC7D,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,MAAM,KAAK,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE;gBAClE,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;oBAAE,OAAO;gBACtC,QAAQ,GAAG,IAAI,CAAC;gBAChB,UAAU,CAAC,KAAK,CAAC,IAAI,uBAAuB,CAAC,gCAAgC,SAAS,IAAI,CAAC,CAAC,CAAC;YAC/F,CAAC,EAAE,SAAS,CAAC,CAAC;YACd,4EAA4E;YAC5E,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;gBAC3F,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;oBAAE,MAAM,IAAI,SAAS,CAAC,qBAAqB,EAAE;wBACxE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM;wBACxD,eAAe,EAAE,QAAQ,CAAkB,KAAK,EAAE,iBAAiB,CAAC,IAAI,aAAa;qBACtF,CAAC,CAAC;gBACH,OAAO,KAAK,CAAC;YACf,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBAC1B,IAAI,QAAQ;oBAAE,MAAM,IAAI,SAAS,CAAC,gCAAgC,SAAS,IAAI,EAAE;wBAC/E,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK;wBACjC,eAAe,EAAE,KAAK,YAAY,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,aAAa;qBACpF,CAAC,CAAC;gBACH,IAAI,KAAK,YAAY,SAAS;oBAAE,MAAM,KAAK,CAAC;gBAC5C,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;oBAAE,MAAM,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBAC9E,MAAM,IAAI,SAAS,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC/H,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;gBACd,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,QAAQ,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBAC9C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACjC,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACrC,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;IACnD,CAAC;CACF"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { UpstreamOutcome } from "@cbxss/tack-core";
|
|
2
|
+
import { type ToolCallOutput, type ToolErrorCode } from "@cbxss/tack-codemode";
|
|
3
|
+
import type { TackResponse } from "./types.js";
|
|
4
|
+
export type TackErrorCode = ToolErrorCode | "invalid_options" | "initialization_failed" | "client_closed";
|
|
5
|
+
export declare class TackError extends Error {
|
|
6
|
+
readonly code: TackErrorCode;
|
|
7
|
+
readonly path: string | undefined;
|
|
8
|
+
readonly upstreamOutcome: UpstreamOutcome;
|
|
9
|
+
constructor(message: string, options: {
|
|
10
|
+
readonly code: TackErrorCode;
|
|
11
|
+
readonly path?: string | undefined;
|
|
12
|
+
readonly upstreamOutcome?: UpstreamOutcome;
|
|
13
|
+
readonly cause?: unknown;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export declare function invocationError(cause: unknown, path: string): TackError;
|
|
17
|
+
export declare function responseOrThrow(output: ToolCallOutput, path: string): TackResponse;
|
|
18
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAqB,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAClG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,iBAAiB,GAAG,uBAAuB,GAAG,eAAe,CAAC;AAE1G,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAE1C,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;QACpC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACnC,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;QAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;KAC1B,EAMA;CACF;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAQvE;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAelF"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ToolDispatchError } from "@cbxss/tack-codemode";
|
|
2
|
+
export class TackError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
path;
|
|
5
|
+
upstreamOutcome;
|
|
6
|
+
constructor(message, options) {
|
|
7
|
+
super(message, options.cause === undefined ? undefined : { cause: options.cause });
|
|
8
|
+
this.name = "TackError";
|
|
9
|
+
this.code = options.code;
|
|
10
|
+
this.path = options.path;
|
|
11
|
+
this.upstreamOutcome = options.upstreamOutcome ?? "not_started";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function invocationError(cause, path) {
|
|
15
|
+
if (cause instanceof TackError)
|
|
16
|
+
return cause;
|
|
17
|
+
return new TackError(cause instanceof Error ? cause.message : "Tool invocation failed", {
|
|
18
|
+
code: cause instanceof ToolDispatchError ? cause.code : "downstream_error",
|
|
19
|
+
path,
|
|
20
|
+
upstreamOutcome: cause instanceof ToolDispatchError ? cause.upstreamOutcome : "unknown",
|
|
21
|
+
cause
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export function responseOrThrow(output, path) {
|
|
25
|
+
if (!output.ok) {
|
|
26
|
+
throw new TackError(output.error?.message ?? "Tool invocation failed", {
|
|
27
|
+
code: output.error?.code ?? "internal_error",
|
|
28
|
+
path,
|
|
29
|
+
upstreamOutcome: output.upstreamOutcome ?? "unknown"
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
ok: true,
|
|
34
|
+
data: output.data,
|
|
35
|
+
dataShape: output.dataShape,
|
|
36
|
+
upstreamOutcome: "succeeded",
|
|
37
|
+
responseId: output.responseId ?? null
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAA2C,MAAM,sBAAsB,CAAC;AAKlG,MAAM,OAAO,SAAU,SAAQ,KAAK;IACzB,IAAI,CAAgB;IACpB,IAAI,CAAqB;IACzB,eAAe,CAAkB;IAE1C,YAAY,OAAe,EAAE,OAK5B;QACC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,aAAa,CAAC;IAClE,CAAC;CACF;AAED,MAAM,UAAU,eAAe,CAAC,KAAc,EAAE,IAAY;IAC1D,IAAI,KAAK,YAAY,SAAS;QAAE,OAAO,KAAK,CAAC;IAC7C,OAAO,IAAI,SAAS,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,EAAE;QACtF,IAAI,EAAE,KAAK,YAAY,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,kBAAkB;QAC1E,IAAI;QACJ,eAAe,EAAE,KAAK,YAAY,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS;QACvF,KAAK;KACN,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAsB,EAAE,IAAY;IAClE,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,IAAI,wBAAwB,EAAE;YACrE,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,IAAI,gBAAgB;YAC5C,IAAI;YACJ,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,SAAS;SACrD,CAAC,CAAC;IACL,CAAC;IACD,OAAO;QACL,EAAE,EAAE,IAAI;QACR,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,eAAe,EAAE,WAAW;QAC5B,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,IAAI;KACtC,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Tack as TackInstance } from "./client.js";
|
|
2
|
+
import type { TackOptions, TackToolsFor } from "./types.js";
|
|
3
|
+
/** An instance follows the selected tool tree, defaulting to the default config's
|
|
4
|
+
* binding (dynamic when unregistered). Constructor selectors are not its identity. */
|
|
5
|
+
export type Tack<Options extends TackOptions | undefined = undefined> = TackInstance<TackToolsFor<Options>>;
|
|
6
|
+
/** Direct live client; infer project tool types without user-supplied generics. */
|
|
7
|
+
export declare const Tack: {
|
|
8
|
+
new <const Options extends TackOptions | undefined = undefined>(...args: undefined extends Options ? [] : never): Tack<Options>;
|
|
9
|
+
new <const Options extends TackOptions | undefined>(options: Options): Tack<Options>;
|
|
10
|
+
};
|
|
11
|
+
export { TackError, type TackErrorCode } from "./errors.js";
|
|
12
|
+
export type * from "./types.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,YAAY,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE5D;sFACsF;AACtF,MAAM,MAAM,IAAI,CAAC,OAAO,SAAS,WAAW,GAAG,SAAS,GAAG,SAAS,IAAI,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;AAE5G,mFAAmF;AACnF,eAAO,MAAM,IAAI,EAAE;IAEjB,KAAI,KAAK,CAAC,OAAO,SAAS,WAAW,GAAG,SAAS,GAAG,SAAS,EAAE,GAAG,IAAI,EAAE,SAAS,SAAS,OAAO,GAAG,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/H,KAAI,KAAK,CAAC,OAAO,SAAS,WAAW,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;CACtE,CAAC;AAEjB,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5D,mBAAmB,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,YAAY,EAAE,MAAM,aAAa,CAAC;AAOnD,mFAAmF;AACnF,MAAM,CAAC,MAAM,IAAI,GAIb,YAAY,CAAC;AAEjB,OAAO,EAAE,SAAS,EAAsB,MAAM,aAAa,CAAC"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DynamicTools, TackArgs, TackCallOptions, TackResponse } from "./types.js";
|
|
2
|
+
/** Only an explicit function call dispatches; reflection never discovers tools. */
|
|
3
|
+
export declare function createTools(invoke: (path: string, args?: TackArgs, options?: TackCallOptions) => Promise<TackResponse>): DynamicTools;
|
|
4
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAErG,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,CAoBrI"}
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { isSafeToolProxySegment } from "@cbxss/tack-core";
|
|
2
|
+
/** Only an explicit function call dispatches; reflection never discovers tools. */
|
|
3
|
+
export function createTools(invoke) {
|
|
4
|
+
function node(segments) {
|
|
5
|
+
const children = new Map();
|
|
6
|
+
const target = (args, options) => invoke(segments.join("."), args, options);
|
|
7
|
+
// No prototype or non-configurable callable properties to leak into paths.
|
|
8
|
+
Reflect.deleteProperty(target, "name");
|
|
9
|
+
Reflect.deleteProperty(target, "length");
|
|
10
|
+
Object.setPrototypeOf(target, null);
|
|
11
|
+
Object.freeze(target);
|
|
12
|
+
return new Proxy(target, {
|
|
13
|
+
get(_target, key) {
|
|
14
|
+
if (key === Symbol.toPrimitive)
|
|
15
|
+
return () => `[Tack tools${segments.length ? `.${segments.join(".")}` : ""}]`;
|
|
16
|
+
if (typeof key !== "string" || !isSafeToolProxySegment(key))
|
|
17
|
+
return undefined;
|
|
18
|
+
let child = children.get(key);
|
|
19
|
+
if (!child) {
|
|
20
|
+
child = node([...segments, key]);
|
|
21
|
+
children.set(key, child);
|
|
22
|
+
}
|
|
23
|
+
return child;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return node([]);
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,mFAAmF;AACnF,MAAM,UAAU,WAAW,CAAC,MAA2F;IACrH,SAAS,IAAI,CAAC,QAA2B;QACvC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;QAChD,MAAM,MAAM,GAAG,CAAC,IAAe,EAAE,OAAyB,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACzG,2EAA2E;QAC3E,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACvC,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACzC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACtB,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE;YACvB,GAAG,CAAC,OAAO,EAAE,GAAG;gBACd,IAAI,GAAG,KAAK,MAAM,CAAC,WAAW;oBAAE,OAAO,GAAG,EAAE,CAAC,cAAc,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;gBAC9G,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC;oBAAE,OAAO,SAAS,CAAC;gBAC9E,IAAI,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;oBAAC,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC;oBAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;gBAAC,CAAC;gBAC3E,OAAO,KAAK,CAAC;YACf,CAAC;SACF,CAAgB,CAAC;IACpB,CAAC;IACD,OAAO,IAAI,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { TackConfig } from "@cbxss/tack-core";
|
|
2
|
+
import type { SearchInput, SearchResult, DescribedTool } from "@cbxss/tack-codemode";
|
|
3
|
+
export type TackOptions = {
|
|
4
|
+
readonly configPath?: string;
|
|
5
|
+
readonly config?: never;
|
|
6
|
+
readonly configDir?: never;
|
|
7
|
+
} | {
|
|
8
|
+
readonly config: TackConfig;
|
|
9
|
+
readonly configDir?: string;
|
|
10
|
+
readonly configPath?: never;
|
|
11
|
+
};
|
|
12
|
+
export interface TackCallOptions {
|
|
13
|
+
readonly signal?: AbortSignal | undefined;
|
|
14
|
+
/** Deadline for this request, including its wait for shared initialization. */
|
|
15
|
+
readonly timeoutMs?: number | undefined;
|
|
16
|
+
}
|
|
17
|
+
export interface TackResponse<T = unknown> {
|
|
18
|
+
readonly ok: true;
|
|
19
|
+
readonly data: T;
|
|
20
|
+
readonly dataShape: unknown;
|
|
21
|
+
readonly upstreamOutcome: "succeeded";
|
|
22
|
+
/** Null in the direct SDK, which does not create a durable response store. */
|
|
23
|
+
readonly responseId: string | null;
|
|
24
|
+
}
|
|
25
|
+
/** Project declarations augment this registry with config-path → tool-tree bindings. */
|
|
26
|
+
export interface TackConfigRegistry {
|
|
27
|
+
}
|
|
28
|
+
type ToolsForPath<Path extends string> = string extends Path ? DynamicTools : [Path] extends [keyof TackConfigRegistry] ? TackConfigRegistry[Path & keyof TackConfigRegistry] : DynamicTools;
|
|
29
|
+
/** Only absent options or literal, registered paths acquire schema-specific types.
|
|
30
|
+
* A supplied {} type can hide runtime selectors, so it must remain dynamic. */
|
|
31
|
+
export type TackToolsFor<Options extends TackOptions | undefined> = Options extends undefined ? ToolsForPath<"tack.config.json"> : Options extends {
|
|
32
|
+
readonly config: TackConfig;
|
|
33
|
+
} ? DynamicTools : Options extends {
|
|
34
|
+
readonly configPath: infer Path extends string;
|
|
35
|
+
} ? ToolsForPath<Path> : DynamicTools;
|
|
36
|
+
export type TackArgs = Readonly<Record<string, unknown>>;
|
|
37
|
+
/** Null-prototype tool proxies expose no Object/Function or serialization members. */
|
|
38
|
+
export interface TackToolNamespace {
|
|
39
|
+
readonly constructor: never;
|
|
40
|
+
readonly toString: never;
|
|
41
|
+
readonly toLocaleString: never;
|
|
42
|
+
readonly valueOf: never;
|
|
43
|
+
readonly hasOwnProperty: never;
|
|
44
|
+
readonly isPrototypeOf: never;
|
|
45
|
+
readonly propertyIsEnumerable: never;
|
|
46
|
+
readonly __defineGetter__: never;
|
|
47
|
+
readonly __defineSetter__: never;
|
|
48
|
+
readonly __lookupGetter__: never;
|
|
49
|
+
readonly __lookupSetter__: never;
|
|
50
|
+
readonly __proto__: never;
|
|
51
|
+
readonly bind: never;
|
|
52
|
+
readonly call: never;
|
|
53
|
+
readonly apply: never;
|
|
54
|
+
readonly name: never;
|
|
55
|
+
readonly length: never;
|
|
56
|
+
readonly arguments: never;
|
|
57
|
+
readonly caller: never;
|
|
58
|
+
readonly prototype: never;
|
|
59
|
+
readonly then: never;
|
|
60
|
+
readonly toJSON: never;
|
|
61
|
+
}
|
|
62
|
+
/** A live callable keeps its signature without inheriting Function members. */
|
|
63
|
+
export type TackTool<Call extends (...args: never[]) => unknown> = Call & TackToolNamespace;
|
|
64
|
+
/** Dynamic paths are validated live. Returned data is deliberately unknown. */
|
|
65
|
+
export interface DynamicTool extends TackToolNamespace {
|
|
66
|
+
(args?: TackArgs, options?: TackCallOptions): Promise<TackResponse>;
|
|
67
|
+
readonly [segment: string]: DynamicTool;
|
|
68
|
+
}
|
|
69
|
+
export interface DynamicTools extends TackToolNamespace {
|
|
70
|
+
readonly [namespace: string]: DynamicTool;
|
|
71
|
+
}
|
|
72
|
+
export type TackSearchInput = Omit<SearchInput, "types">;
|
|
73
|
+
export type TackSearchResult = SearchResult;
|
|
74
|
+
export type TackDescription = DescribedTool;
|
|
75
|
+
export type { TackConfig, UpstreamOutcome } from "@cbxss/tack-core";
|
|
76
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Tack, TackError } from "@cbxss/tack-sdk";
|
|
2
|
+
|
|
3
|
+
const tack = new Tack({ configPath: "./tack.config.json" });
|
|
4
|
+
try {
|
|
5
|
+
const result = await tack.tools.local.echo({ message: "Hello from Tack" });
|
|
6
|
+
console.log(result.data); // unknown until narrowed, or use generated types
|
|
7
|
+
} catch (error) {
|
|
8
|
+
if (!(error instanceof TackError)) throw error;
|
|
9
|
+
console.error(error.code, error.path, error.upstreamOutcome);
|
|
10
|
+
process.exitCode = 1;
|
|
11
|
+
} finally {
|
|
12
|
+
await tack.close();
|
|
13
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Tack } from "@cbxss/tack-sdk";
|
|
2
|
+
|
|
3
|
+
// Use the source fixture for native .ts/.mts, or its emitted file after compilation.
|
|
4
|
+
const entry = /\.m?ts$/u.test(import.meta.url) ? "./tools.ts" : "./tools.js";
|
|
5
|
+
const tack = new Tack({
|
|
6
|
+
config: { servers: { local: { transport: "module", entry } } },
|
|
7
|
+
configDir: import.meta.dirname
|
|
8
|
+
});
|
|
9
|
+
try {
|
|
10
|
+
await tack.ready();
|
|
11
|
+
const result = await tack.call("local.echo", { message: "Inline config" }, {
|
|
12
|
+
signal: AbortSignal.timeout(5000), timeoutMs: 3000
|
|
13
|
+
});
|
|
14
|
+
console.log(result.data);
|
|
15
|
+
} finally {
|
|
16
|
+
await tack.close();
|
|
17
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { defineTool } from "@cbxss/tack-sources";
|
|
2
|
+
|
|
3
|
+
export const echo = defineTool({
|
|
4
|
+
name: "echo",
|
|
5
|
+
input: {
|
|
6
|
+
type: "object", properties: { message: { type: "string" } },
|
|
7
|
+
required: ["message"], additionalProperties: false
|
|
8
|
+
},
|
|
9
|
+
output: { type: "string" },
|
|
10
|
+
handler: ({ message }: { message: string }) => message
|
|
11
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cbxss/tack-sdk",
|
|
3
|
+
"version": "2.2.0",
|
|
4
|
+
"description": "A live, config-driven TypeScript client for Tack tools.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": { "node": ">=22.18.0" },
|
|
7
|
+
"exports": {
|
|
8
|
+
".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" }
|
|
9
|
+
},
|
|
10
|
+
"files": ["dist", "examples"],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "rm -rf dist && tsc -p tsconfig.json",
|
|
13
|
+
"typecheck": "tsc -p tsconfig.test.json",
|
|
14
|
+
"test": "vitest run --passWithNoTests",
|
|
15
|
+
"test:consumer": "node test/packed-consumer.mjs"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@cbxss/tack-core": "2.2.0",
|
|
19
|
+
"@cbxss/tack-codemode": "2.2.0",
|
|
20
|
+
"@cbxss/tack-plugin": "2.2.0",
|
|
21
|
+
"@cbxss/tack-sources": "2.2.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"typescript": "^7.0.2",
|
|
25
|
+
"vitest": "^4.1.10"
|
|
26
|
+
},
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"repository": { "type": "git", "url": "git+https://github.com/shrimp-software/tack.git" },
|
|
29
|
+
"homepage": "https://github.com/shrimp-software/tack#readme",
|
|
30
|
+
"bugs": { "url": "https://github.com/shrimp-software/tack/issues" }
|
|
31
|
+
}
|