implto-tos-axi 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +255 -0
- package/dist/bin/implto-tos-axi.d.ts +2 -0
- package/dist/bin/implto-tos-axi.js +16 -0
- package/dist/bin/implto-tos-axi.js.map +1 -0
- package/dist/src/auth/loopback.d.ts +29 -0
- package/dist/src/auth/loopback.js +110 -0
- package/dist/src/auth/loopback.js.map +1 -0
- package/dist/src/auth/open-browser.d.ts +9 -0
- package/dist/src/auth/open-browser.js +24 -0
- package/dist/src/auth/open-browser.js.map +1 -0
- package/dist/src/auth/provider.d.ts +39 -0
- package/dist/src/auth/provider.js +106 -0
- package/dist/src/auth/provider.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +183 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commands/components.d.ts +40 -0
- package/dist/src/commands/components.js +417 -0
- package/dist/src/commands/components.js.map +1 -0
- package/dist/src/commands/context.d.ts +10 -0
- package/dist/src/commands/context.js +46 -0
- package/dist/src/commands/context.js.map +1 -0
- package/dist/src/commands/guide.d.ts +16 -0
- package/dist/src/commands/guide.js +203 -0
- package/dist/src/commands/guide.js.map +1 -0
- package/dist/src/commands/home.d.ts +9 -0
- package/dist/src/commands/home.js +33 -0
- package/dist/src/commands/home.js.map +1 -0
- package/dist/src/commands/init.d.ts +12 -0
- package/dist/src/commands/init.js +65 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/login.d.ts +13 -0
- package/dist/src/commands/login.js +137 -0
- package/dist/src/commands/login.js.map +1 -0
- package/dist/src/commands/tasks.d.ts +8 -0
- package/dist/src/commands/tasks.js +344 -0
- package/dist/src/commands/tasks.js.map +1 -0
- package/dist/src/commands/tools.d.ts +66 -0
- package/dist/src/commands/tools.js +401 -0
- package/dist/src/commands/tools.js.map +1 -0
- package/dist/src/commands/whoami.d.ts +5 -0
- package/dist/src/commands/whoami.js +66 -0
- package/dist/src/commands/whoami.js.map +1 -0
- package/dist/src/config/binding.d.ts +29 -0
- package/dist/src/config/binding.js +42 -0
- package/dist/src/config/binding.js.map +1 -0
- package/dist/src/config/credentials.d.ts +39 -0
- package/dist/src/config/credentials.js +62 -0
- package/dist/src/config/credentials.js.map +1 -0
- package/dist/src/config/profiles.d.ts +24 -0
- package/dist/src/config/profiles.js +64 -0
- package/dist/src/config/profiles.js.map +1 -0
- package/dist/src/errors.d.ts +21 -0
- package/dist/src/errors.js +40 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/flags.d.ts +50 -0
- package/dist/src/flags.js +143 -0
- package/dist/src/flags.js.map +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +7 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/mcp/client.d.ts +85 -0
- package/dist/src/mcp/client.js +130 -0
- package/dist/src/mcp/client.js.map +1 -0
- package/dist/src/output.d.ts +8 -0
- package/dist/src/output.js +2 -0
- package/dist/src/output.js.map +1 -0
- package/dist/src/resolve.d.ts +16 -0
- package/dist/src/resolve.js +48 -0
- package/dist/src/resolve.js.map +1 -0
- package/dist/src/scopes.d.ts +9 -0
- package/dist/src/scopes.js +16 -0
- package/dist/src/scopes.js.map +1 -0
- package/dist/src/session.d.ts +40 -0
- package/dist/src/session.js +75 -0
- package/dist/src/session.js.map +1 -0
- package/dist/src/skill.d.ts +32 -0
- package/dist/src/skill.js +149 -0
- package/dist/src/skill.js.map +1 -0
- package/dist/src/version.d.ts +5 -0
- package/dist/src/version.js +6 -0
- package/dist/src/version.js.map +1 -0
- package/package.json +70 -0
- package/skills/implto-tos-delivery/SKILL.md +45 -0
- package/skills/implto-tos-tasks/SKILL.md +48 -0
- package/skills/implto-tos-workspace/SKILL.md +45 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
3
|
+
import { TosError, credentialRejected } from "../errors.js";
|
|
4
|
+
import { VERSION } from "../version.js";
|
|
5
|
+
/**
|
|
6
|
+
* Where the server publishes its domain catalog. A constant rather than a
|
|
7
|
+
* lookup through `resources/list`: one name, and a server that does not serve
|
|
8
|
+
* it answers with an error we turn into `null`.
|
|
9
|
+
*/
|
|
10
|
+
export const TOOL_DOMAINS_URI = "transformation-os://tool-domains";
|
|
11
|
+
async function withClient(options, run) {
|
|
12
|
+
const client = new Client({ name: "implto-tos-axi", version: VERSION }, { capabilities: {} });
|
|
13
|
+
const transport = new StreamableHTTPClientTransport(new URL(options.mcpUrl), {
|
|
14
|
+
...(options.authProvider ? { authProvider: options.authProvider } : {}),
|
|
15
|
+
...(options.token
|
|
16
|
+
? { requestInit: { headers: { Authorization: `Bearer ${options.token}` } } }
|
|
17
|
+
: {}),
|
|
18
|
+
});
|
|
19
|
+
try {
|
|
20
|
+
// The SDK's `Transport` declares `sessionId: string` while the streamable
|
|
21
|
+
// transport's is optional, which `exactOptionalPropertyTypes` will not
|
|
22
|
+
// reconcile. The cast is at the boundary and says why rather than turning
|
|
23
|
+
// the flag off for the whole package.
|
|
24
|
+
await client.connect(transport);
|
|
25
|
+
return await run(client);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
throw translate(error, options.profile);
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
await client.close().catch(() => undefined);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export async function callTool(options, name, args = {}) {
|
|
35
|
+
return withClient(options, async (client) => {
|
|
36
|
+
const result = (await client.callTool({ name, arguments: args }));
|
|
37
|
+
const text = (result.content ?? [])
|
|
38
|
+
.filter((c) => c.type === "text")
|
|
39
|
+
.map((c) => c.text ?? "")
|
|
40
|
+
.join("\n");
|
|
41
|
+
if (result.isError)
|
|
42
|
+
throw toolFailure(name, text);
|
|
43
|
+
if (!text)
|
|
44
|
+
return null;
|
|
45
|
+
try {
|
|
46
|
+
return JSON.parse(text);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Some tools answer with a sentence rather than a document.
|
|
50
|
+
return text;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The tools this credential may call.
|
|
56
|
+
*
|
|
57
|
+
* Already narrowed by the server to the domains the credential was granted, so
|
|
58
|
+
* what comes back is what will actually run - not a catalog with holes in it
|
|
59
|
+
* that only show up as a refusal.
|
|
60
|
+
*/
|
|
61
|
+
export async function listTools(options) {
|
|
62
|
+
return withClient(options, async (client) => {
|
|
63
|
+
const { tools } = (await client.listTools());
|
|
64
|
+
return tools;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The domain catalog, or null when this server does not group its tools.
|
|
69
|
+
*
|
|
70
|
+
* Unlike `tools/list` the catalog is not narrowed by the grant, which is what
|
|
71
|
+
* lets `tools domains` say "this exists and you do not have it" rather than
|
|
72
|
+
* leaving a credential's holder wondering where an area went.
|
|
73
|
+
*/
|
|
74
|
+
export async function readDomains(options) {
|
|
75
|
+
return withClient(options, async (client) => {
|
|
76
|
+
try {
|
|
77
|
+
const result = (await client.readResource({ uri: TOOL_DOMAINS_URI }));
|
|
78
|
+
const text = result.contents?.[0]?.text;
|
|
79
|
+
return text ? JSON.parse(text) : null;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* A tool's own refusal, mapped to a code a script can branch on.
|
|
88
|
+
*
|
|
89
|
+
* The server says "forbidden", "not found" or nothing in particular; the
|
|
90
|
+
* difference matters because only one of them is worth retrying.
|
|
91
|
+
*/
|
|
92
|
+
function toolFailure(tool, text) {
|
|
93
|
+
const message = text.replace(/^Error(\s*\([a-z]+\))?:\s*/i, "").trim();
|
|
94
|
+
// A refusal for a missing scope and a refusal for a workspace are fixed in
|
|
95
|
+
// different places - signing in again versus asking somebody for access - so
|
|
96
|
+
// they do not get the same suggestion.
|
|
97
|
+
const scope = /does not carry the '([a-z_]+)' scope/i.exec(text);
|
|
98
|
+
if (scope) {
|
|
99
|
+
return new TosError(message, "FORBIDDEN", [
|
|
100
|
+
`implto-tos-axi login --scopes ${scope[1]} # or add it to the ones you have`,
|
|
101
|
+
"implto-tos-axi tools domains # which areas this credential holds",
|
|
102
|
+
]);
|
|
103
|
+
}
|
|
104
|
+
if (/forbidden|access denied|not carry the/i.test(text)) {
|
|
105
|
+
return new TosError(message, "FORBIDDEN", [
|
|
106
|
+
"Ask for access to that workspace, or authorize again with the scope it needs.",
|
|
107
|
+
"implto-tos-axi tools domains # which areas this credential holds",
|
|
108
|
+
]);
|
|
109
|
+
}
|
|
110
|
+
if (/not found/i.test(text))
|
|
111
|
+
return new TosError(message, "NOT_FOUND");
|
|
112
|
+
if (/matches \d+ tasks/i.test(text)) {
|
|
113
|
+
return new TosError(message, "AMBIGUOUS", ["Pass --project to say which."]);
|
|
114
|
+
}
|
|
115
|
+
return new TosError(message || `${tool} failed.`, "API_ERROR");
|
|
116
|
+
}
|
|
117
|
+
function translate(error, profile) {
|
|
118
|
+
if (error instanceof TosError)
|
|
119
|
+
return error;
|
|
120
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
121
|
+
if (/401|unauthor/i.test(message))
|
|
122
|
+
return credentialRejected(profile);
|
|
123
|
+
if (/fetch failed|ECONNREFUSED|ENOTFOUND|network/i.test(message)) {
|
|
124
|
+
return new TosError(`Could not reach the server: ${message}`, "NETWORK_ERROR", [
|
|
125
|
+
"Check the address with `implto-tos-axi whoami`, or pass --url.",
|
|
126
|
+
]);
|
|
127
|
+
}
|
|
128
|
+
return new TosError(message, "API_ERROR");
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/mcp/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural mirror of the SDK's `AxiRenderable`.
|
|
3
|
+
*
|
|
4
|
+
* `axi-sdk-js` does not export its `output` module, so the renderable type is
|
|
5
|
+
* restated here rather than reached for through a deep import.
|
|
6
|
+
*/
|
|
7
|
+
export type AxiStructuredOutput = Record<string, unknown>;
|
|
8
|
+
export type AxiRenderable = string | AxiStructuredOutput;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/output.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Names in, ids out.
|
|
3
|
+
*
|
|
4
|
+
* Every command takes the names a person would use and resolves them against
|
|
5
|
+
* what the server just returned, so nothing has to carry a UUID around. The
|
|
6
|
+
* rules are the same everywhere, which is why they are here rather than in
|
|
7
|
+
* each command: an exact id or key wins outright, then a case-insensitive
|
|
8
|
+
* name, then a unique substring. Two matches is the caller's to fix, and the
|
|
9
|
+
* error names both rather than guessing.
|
|
10
|
+
*/
|
|
11
|
+
export declare function pick<T>(items: readonly T[], wanted: string, keysOf: (item: T) => (string | undefined | null)[], what?: string): T;
|
|
12
|
+
/** A UUID, which the server hands out and a person never types. */
|
|
13
|
+
export declare const looksLikeId: (value: string) => boolean;
|
|
14
|
+
/** `none` and `null` both mean "clear this link", which is not the same as leaving it. */
|
|
15
|
+
export declare const CLEARING: Set<string>;
|
|
16
|
+
export declare const isClearing: (value: string) => boolean;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { TosError, ambiguous } from "./errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* Names in, ids out.
|
|
4
|
+
*
|
|
5
|
+
* Every command takes the names a person would use and resolves them against
|
|
6
|
+
* what the server just returned, so nothing has to carry a UUID around. The
|
|
7
|
+
* rules are the same everywhere, which is why they are here rather than in
|
|
8
|
+
* each command: an exact id or key wins outright, then a case-insensitive
|
|
9
|
+
* name, then a unique substring. Two matches is the caller's to fix, and the
|
|
10
|
+
* error names both rather than guessing.
|
|
11
|
+
*/
|
|
12
|
+
export function pick(items, wanted, keysOf, what = "Nothing here") {
|
|
13
|
+
const needle = wanted.trim().toLowerCase();
|
|
14
|
+
const label = (item) => String(keysOf(item)[1] ?? keysOf(item)[0]);
|
|
15
|
+
/**
|
|
16
|
+
* The candidates, told apart.
|
|
17
|
+
*
|
|
18
|
+
* Two components may legitimately carry one name in different parts of the
|
|
19
|
+
* tree, and "matches more than one: Docs, Docs" tells the caller nothing it
|
|
20
|
+
* can act on. When the labels repeat, the id goes beside them - which is
|
|
21
|
+
* also what the suggestion tells them to pass.
|
|
22
|
+
*/
|
|
23
|
+
const candidates = (matches) => {
|
|
24
|
+
const labels = matches.map(label);
|
|
25
|
+
if (new Set(labels).size === labels.length)
|
|
26
|
+
return labels;
|
|
27
|
+
return matches.map((item) => `${label(item)} (${String(keysOf(item)[0])})`);
|
|
28
|
+
};
|
|
29
|
+
const exact = items.filter((item) => keysOf(item).some((k) => k && k.toLowerCase() === needle));
|
|
30
|
+
if (exact.length === 1)
|
|
31
|
+
return exact[0];
|
|
32
|
+
if (exact.length > 1)
|
|
33
|
+
throw ambiguous(wanted, candidates(exact));
|
|
34
|
+
const partial = items.filter((item) => keysOf(item).some((k) => k && k.toLowerCase().includes(needle)));
|
|
35
|
+
if (partial.length === 1)
|
|
36
|
+
return partial[0];
|
|
37
|
+
if (partial.length > 1)
|
|
38
|
+
throw ambiguous(wanted, candidates(partial));
|
|
39
|
+
throw new TosError(`${what} is called "${wanted}".`, "NOT_FOUND", [
|
|
40
|
+
`Available: ${items.map(label).join(", ") || "(none)"}`,
|
|
41
|
+
]);
|
|
42
|
+
}
|
|
43
|
+
/** A UUID, which the server hands out and a person never types. */
|
|
44
|
+
export const looksLikeId = (value) => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
45
|
+
/** `none` and `null` both mean "clear this link", which is not the same as leaving it. */
|
|
46
|
+
export const CLEARING = new Set(["none", "null", ""]);
|
|
47
|
+
export const isClearing = (value) => CLEARING.has(value.trim().toLowerCase());
|
|
48
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;;;;;GASG;AACH,MAAM,UAAU,IAAI,CAClB,KAAmB,EACnB,MAAc,EACd,MAAkD,EAClD,IAAI,GAAG,cAAc;IAErB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAG,CAAC,IAAO,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtE;;;;;;;OAOG;IACH,MAAM,UAAU,GAAG,CAAC,OAAY,EAAY,EAAE;QAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM;YAAE,OAAO,MAAM,CAAC;QAC1D,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC9E,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC;IAChG,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAM,CAAC;IAC7C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAEjE,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CACpC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAChE,CAAC;IACF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC,CAAC,CAAM,CAAC;IACjD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IAErE,MAAM,IAAI,QAAQ,CAAC,GAAG,IAAI,eAAe,MAAM,IAAI,EAAE,WAAW,EAAE;QAChE,cAAc,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE;KACxD,CAAC,CAAC;AACL,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAa,EAAW,EAAE,CACpD,iEAAiE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAEhF,0FAA0F;AAC1F,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;AACtD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAW,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tool domains a credential can be narrowed to.
|
|
3
|
+
*
|
|
4
|
+
* A copy of the server's list rather than an import: this package ships to npm
|
|
5
|
+
* on its own and cannot depend on the monorepo. The server is the authority -
|
|
6
|
+
* it refuses anything it does not recognise - so the cost of drift is a clear
|
|
7
|
+
* error at sign-in rather than a wrong grant.
|
|
8
|
+
*/
|
|
9
|
+
export declare const MCP_SCOPES: readonly ["tasks", "delivery_planning", "communications", "process_maps", "organization"];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tool domains a credential can be narrowed to.
|
|
3
|
+
*
|
|
4
|
+
* A copy of the server's list rather than an import: this package ships to npm
|
|
5
|
+
* on its own and cannot depend on the monorepo. The server is the authority -
|
|
6
|
+
* it refuses anything it does not recognise - so the cost of drift is a clear
|
|
7
|
+
* error at sign-in rather than a wrong grant.
|
|
8
|
+
*/
|
|
9
|
+
export const MCP_SCOPES = [
|
|
10
|
+
"tasks",
|
|
11
|
+
"delivery_planning",
|
|
12
|
+
"communications",
|
|
13
|
+
"process_maps",
|
|
14
|
+
"organization",
|
|
15
|
+
];
|
|
16
|
+
//# sourceMappingURL=scopes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../src/scopes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,OAAO;IACP,mBAAmB;IACnB,gBAAgB;IAChB,cAAc;IACd,cAAc;CACN,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type Binding } from "./config/binding.js";
|
|
2
|
+
import { type Profile } from "./config/profiles.js";
|
|
3
|
+
import { type DomainCatalog, type McpTool } from "./mcp/client.js";
|
|
4
|
+
/**
|
|
5
|
+
* Everything a command needs to make one call: which deployment, which
|
|
6
|
+
* credential, and which project this directory belongs to.
|
|
7
|
+
*
|
|
8
|
+
* The order the credential is resolved in is the contract: `TOS_TOKEN` beats
|
|
9
|
+
* the file, an explicit `--profile` beats the binding, and the binding beats
|
|
10
|
+
* the default. A machine that sets the environment variable means it.
|
|
11
|
+
*/
|
|
12
|
+
export interface Session {
|
|
13
|
+
profile: Profile;
|
|
14
|
+
call(tool: string, args?: Record<string, unknown>): Promise<unknown>;
|
|
15
|
+
/** The tools this credential may call, already narrowed to its domains. */
|
|
16
|
+
tools(): Promise<McpTool[]>;
|
|
17
|
+
/** Every domain the server has, granted or not. Null if it groups nothing. */
|
|
18
|
+
domains(): Promise<DomainCatalog | null>;
|
|
19
|
+
/** Where the credential came from, which `whoami` reports. */
|
|
20
|
+
source: "env" | "file";
|
|
21
|
+
binding: Binding | null;
|
|
22
|
+
bindingPath: string | null;
|
|
23
|
+
}
|
|
24
|
+
export interface SessionFlags {
|
|
25
|
+
profile?: string | undefined;
|
|
26
|
+
url?: string | undefined;
|
|
27
|
+
mcpUrl?: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
export declare function openSession(flags?: SessionFlags): Session;
|
|
30
|
+
/** The binding, or the error that says how to make one. */
|
|
31
|
+
export declare function requireBinding(session: Session): Binding;
|
|
32
|
+
/**
|
|
33
|
+
* Which workspace a call acts in.
|
|
34
|
+
*
|
|
35
|
+
* A user credential reaches several workspaces, so unlike a workspace token it
|
|
36
|
+
* has to say which one every time. The binding answers for a repository that
|
|
37
|
+
* has one; `--workspace` answers anywhere else, by name or by id, so the tool
|
|
38
|
+
* is usable from a directory that is not a bound checkout at all.
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveWorkspaceId(session: Session, wanted?: string): Promise<string>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { envToken, readCredential } from "./config/credentials.js";
|
|
2
|
+
import { findBinding } from "./config/binding.js";
|
|
3
|
+
import { resolveProfile } from "./config/profiles.js";
|
|
4
|
+
import { callTool, listTools, readDomains, } from "./mcp/client.js";
|
|
5
|
+
import { FileAuthProvider } from "./auth/provider.js";
|
|
6
|
+
import { TosError, noBinding, noWorkspace, notSignedIn } from "./errors.js";
|
|
7
|
+
import { looksLikeId, pick } from "./resolve.js";
|
|
8
|
+
export function openSession(flags = {}) {
|
|
9
|
+
const found = findBinding();
|
|
10
|
+
const profileName = flags.profile ?? found?.binding.profile;
|
|
11
|
+
const stored = profileName ? readCredential(profileName) : null;
|
|
12
|
+
const profile = resolveProfile({
|
|
13
|
+
profile: profileName,
|
|
14
|
+
url: flags.url,
|
|
15
|
+
mcpUrl: flags.mcpUrl ?? stored?.mcpUrl,
|
|
16
|
+
});
|
|
17
|
+
const credential = readCredential(profile.name);
|
|
18
|
+
const fromEnv = envToken();
|
|
19
|
+
let options;
|
|
20
|
+
if (fromEnv) {
|
|
21
|
+
options = { mcpUrl: profile.mcpUrl, token: fromEnv, profile: profile.name };
|
|
22
|
+
}
|
|
23
|
+
else if (credential?.staticToken) {
|
|
24
|
+
options = { mcpUrl: profile.mcpUrl, token: credential.staticToken, profile: profile.name };
|
|
25
|
+
}
|
|
26
|
+
else if (credential?.tokens?.access_token) {
|
|
27
|
+
// Through the provider rather than as a bare header, so a token whose hour
|
|
28
|
+
// is up is renewed against its refresh token without anybody present -
|
|
29
|
+
// which is the whole reason an OAuth grant is worth having over a key.
|
|
30
|
+
const provider = new FileAuthProvider(profile, "http://127.0.0.1:0/callback", "", "", () => {
|
|
31
|
+
throw new TosError("This credential needs a browser to be renewed.", "NEEDS_HUMAN", [
|
|
32
|
+
`implto-tos-axi login --profile ${profile.name}`,
|
|
33
|
+
]);
|
|
34
|
+
});
|
|
35
|
+
options = { mcpUrl: profile.mcpUrl, authProvider: provider, profile: profile.name };
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
throw notSignedIn(profile.name);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
profile,
|
|
42
|
+
source: fromEnv ? "env" : "file",
|
|
43
|
+
binding: found?.binding ?? null,
|
|
44
|
+
bindingPath: found?.path ?? null,
|
|
45
|
+
call: (tool, args) => callTool(options, tool, args),
|
|
46
|
+
tools: () => listTools(options),
|
|
47
|
+
domains: () => readDomains(options),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** The binding, or the error that says how to make one. */
|
|
51
|
+
export function requireBinding(session) {
|
|
52
|
+
if (!session.binding)
|
|
53
|
+
throw noBinding();
|
|
54
|
+
return session.binding;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Which workspace a call acts in.
|
|
58
|
+
*
|
|
59
|
+
* A user credential reaches several workspaces, so unlike a workspace token it
|
|
60
|
+
* has to say which one every time. The binding answers for a repository that
|
|
61
|
+
* has one; `--workspace` answers anywhere else, by name or by id, so the tool
|
|
62
|
+
* is usable from a directory that is not a bound checkout at all.
|
|
63
|
+
*/
|
|
64
|
+
export async function resolveWorkspaceId(session, wanted) {
|
|
65
|
+
if (!wanted) {
|
|
66
|
+
if (!session.binding)
|
|
67
|
+
throw noWorkspace();
|
|
68
|
+
return session.binding.workspaceId;
|
|
69
|
+
}
|
|
70
|
+
if (looksLikeId(wanted))
|
|
71
|
+
return wanted;
|
|
72
|
+
const me = (await session.call("get_current_user"));
|
|
73
|
+
return pick(me.workspaces ?? [], wanted, (w) => [w.id, w.name], "No workspace you can reach").id;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The stubs that ship with the package.
|
|
3
|
+
*
|
|
4
|
+
* Three rather than one, because a skill's description is loaded whether or
|
|
5
|
+
* not the task needs it while its body is loaded only when the description
|
|
6
|
+
* matched. One stub covering tasks, components and everything else would put
|
|
7
|
+
* the whole product in front of a model that only wanted to file a ticket.
|
|
8
|
+
* Split by the question being asked, each body is pulled on its own.
|
|
9
|
+
*
|
|
10
|
+
* All three are discovery stubs, not manuals: they say when to reach for the
|
|
11
|
+
* CLI and send the reader to `--help` and `guide` for anything that can go
|
|
12
|
+
* stale. Installed copies do go stale - that is the whole reason for the cap.
|
|
13
|
+
*/
|
|
14
|
+
export interface SkillDefinition {
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
tags: string[];
|
|
18
|
+
category: string;
|
|
19
|
+
body: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Hard cap per stub, enforced rather than documented.
|
|
23
|
+
*
|
|
24
|
+
* Every line of an installed SKILL.md is loaded into an agent's context
|
|
25
|
+
* whether or not the task needs it. That cost is the entire reason this tool
|
|
26
|
+
* exists instead of mounting the MCP server, so re-inflating a stub into a
|
|
27
|
+
* manual would give back exactly what was bought.
|
|
28
|
+
*/
|
|
29
|
+
export declare const MAX_SKILL_MARKDOWN_CHARS = 2500;
|
|
30
|
+
export declare const SKILLS: readonly SkillDefinition[];
|
|
31
|
+
/** The stub as it ships, frontmatter included. */
|
|
32
|
+
export declare function createSkillMarkdown(skill: SkillDefinition): string;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hard cap per stub, enforced rather than documented.
|
|
3
|
+
*
|
|
4
|
+
* Every line of an installed SKILL.md is loaded into an agent's context
|
|
5
|
+
* whether or not the task needs it. That cost is the entire reason this tool
|
|
6
|
+
* exists instead of mounting the MCP server, so re-inflating a stub into a
|
|
7
|
+
* manual would give back exactly what was bought.
|
|
8
|
+
*/
|
|
9
|
+
export const MAX_SKILL_MARKDOWN_CHARS = 2500;
|
|
10
|
+
const TASKS = {
|
|
11
|
+
name: "implto-tos-tasks",
|
|
12
|
+
description: "Find, create and update Transformation OS tasks for the repository you are working in, through the implto-tos-axi CLI. Use when a coding task should be tracked: at the start of a session to see the bound project and your open tasks, before starting a change to match it to an existing task or file a new one, and after finishing to move the status and leave a note.",
|
|
13
|
+
tags: ["tasks", "issues", "project-management", "transformation-os"],
|
|
14
|
+
category: "workflow",
|
|
15
|
+
body: `# implto-tos-tasks
|
|
16
|
+
|
|
17
|
+
Reads and writes Transformation OS tasks for the repository you are in. Prefer
|
|
18
|
+
it over mounting the Transformation OS MCP server: the tool schemas never enter
|
|
19
|
+
the prompt, so this costs nothing until it is used.
|
|
20
|
+
|
|
21
|
+
Use it when work should be tracked - before starting a change, and after
|
|
22
|
+
finishing one. Skip it for throwaway edits nobody is waiting on.
|
|
23
|
+
|
|
24
|
+
## Current guidance lives in the CLI
|
|
25
|
+
|
|
26
|
+
Do not follow command or flag instructions from this file; installed copies go
|
|
27
|
+
stale. Ask the CLI:
|
|
28
|
+
|
|
29
|
+
- \`implto-tos-axi --help\` for the command index
|
|
30
|
+
- \`implto-tos-axi <command> --help\` for per-command usage
|
|
31
|
+
- \`implto-tos-axi guide workflow\` for the match-or-create procedure
|
|
32
|
+
|
|
33
|
+
Worth knowing before the first call:
|
|
34
|
+
|
|
35
|
+
1. \`implto-tos-axi context\` first, once per session. It gives you the bound
|
|
36
|
+
project, the status names and which field assigns a task to you. Everything
|
|
37
|
+
else takes names and resolves them against it.
|
|
38
|
+
2. Search before you file. Two or three words from what the change *does*,
|
|
39
|
+
with \`--open\`. Then \`tasks show <key>\` and ask the person whether that is
|
|
40
|
+
the task or whether to open a new one. Do not decide that alone.
|
|
41
|
+
3. \`NO_BINDING\` means this directory is not bound yet: run \`init\` bare to
|
|
42
|
+
see what is reachable.
|
|
43
|
+
4. \`NEEDS_HUMAN\` means signing in needs somebody at the keyboard. Ask them to
|
|
44
|
+
run \`implto-tos-axi login\`; do not try to work around it.
|
|
45
|
+
|
|
46
|
+
Exit 2 is your mistake - a bad flag, a name matching nothing or several. Every
|
|
47
|
+
error names the command that fixes it.
|
|
48
|
+
|
|
49
|
+
Deliverables are \`implto-tos-delivery\`; everything else in the workspace is
|
|
50
|
+
\`implto-tos-workspace\`.
|
|
51
|
+
`,
|
|
52
|
+
};
|
|
53
|
+
const DELIVERY = {
|
|
54
|
+
name: "implto-tos-delivery",
|
|
55
|
+
description: "Read and change what a Transformation OS workspace is delivering, through the implto-tos-axi CLI: the component tree (services, modules, APIs and the rest of the deliverables), what each component is linked to, its estimate, and the delivery phases. Use when a change introduces a deliverable that is not recorded yet, when a component is missing or sits under the wrong parent, or when asked what is being built and for how much effort.",
|
|
56
|
+
tags: ["components", "deliverables", "estimates", "phases", "transformation-os"],
|
|
57
|
+
category: "workflow",
|
|
58
|
+
body: `# implto-tos-delivery
|
|
59
|
+
|
|
60
|
+
Components are the deliverables of a workspace, in a tree: the services,
|
|
61
|
+
modules and APIs work is filed under. Tasks hang off them, so a component that
|
|
62
|
+
does not exist is a task with nowhere to go.
|
|
63
|
+
|
|
64
|
+
Use it when a change introduces something the tree does not have yet, when a
|
|
65
|
+
component is under the wrong parent, or to answer what is being built.
|
|
66
|
+
|
|
67
|
+
## Current guidance lives in the CLI
|
|
68
|
+
|
|
69
|
+
Do not follow command or flag instructions from this file; installed copies go
|
|
70
|
+
stale. Ask the CLI:
|
|
71
|
+
|
|
72
|
+
- \`implto-tos-axi components --help\`
|
|
73
|
+
- \`implto-tos-axi guide components\`
|
|
74
|
+
|
|
75
|
+
Worth knowing before the first call:
|
|
76
|
+
|
|
77
|
+
1. \`implto-tos-axi components list --tree\` first. It is the only way to see
|
|
78
|
+
where a new component belongs, and it is how you find out the one you were
|
|
79
|
+
about to create is already there under another name.
|
|
80
|
+
2. Names, not ids, everywhere: \`--parent "Platform"\`. Two matches is an
|
|
81
|
+
error naming both rather than a guess.
|
|
82
|
+
3. \`--parent none\` moves a component to the top level; omitting \`--parent\`
|
|
83
|
+
leaves it where it is. The same holds for \`--project\` and \`--system\`.
|
|
84
|
+
4. A component created in a bound checkout is linked to that checkout's
|
|
85
|
+
project unless you pass \`--project none\`.
|
|
86
|
+
5. Phases and per-phase estimates have no command of their own - reach them
|
|
87
|
+
with \`implto-tos-axi tools call list_phases\`.
|
|
88
|
+
|
|
89
|
+
Ask before creating. A deliverable somebody else named is worse than one
|
|
90
|
+
missing.
|
|
91
|
+
`,
|
|
92
|
+
};
|
|
93
|
+
const WORKSPACE = {
|
|
94
|
+
name: "implto-tos-workspace",
|
|
95
|
+
description: "Reach the rest of a Transformation OS workspace from the command line through implto-tos-axi: process maps, the people, departments and organizational roles in it, the systems they use, and the client message threads. Discover what the server offers with `implto-tos-axi tools`, then call one tool directly. Use when a task needs workspace data that is not a task or a deliverable.",
|
|
96
|
+
tags: ["process-maps", "people", "systems", "communications", "transformation-os"],
|
|
97
|
+
category: "workflow",
|
|
98
|
+
body: `# implto-tos-workspace
|
|
99
|
+
|
|
100
|
+
Everything in Transformation OS that is not a task or a component: process
|
|
101
|
+
maps, people, departments, organizational roles, the systems a workspace uses,
|
|
102
|
+
and the client conversation.
|
|
103
|
+
|
|
104
|
+
There is no command per area. Instead the CLI asks the server what it offers
|
|
105
|
+
and calls it, so one tool's schema is loaded when a task needs it rather than
|
|
106
|
+
fifty of them in every request.
|
|
107
|
+
|
|
108
|
+
## Current guidance lives in the CLI
|
|
109
|
+
|
|
110
|
+
Do not follow tool names or argument lists from this file; the server adds
|
|
111
|
+
tools without releasing this package. Ask it:
|
|
112
|
+
|
|
113
|
+
- \`implto-tos-axi tools\` - the areas, and which ones this credential holds
|
|
114
|
+
- \`implto-tos-axi tools domains <id>\` - what an area covers, and its rules
|
|
115
|
+
- \`implto-tos-axi tools list --domain <id>\` - the tools in it
|
|
116
|
+
- \`implto-tos-axi tools show <name>\` - one tool's arguments
|
|
117
|
+
- \`implto-tos-axi tools call <name> key=value\`
|
|
118
|
+
|
|
119
|
+
Worth knowing before the first call:
|
|
120
|
+
|
|
121
|
+
1. Read the area's rules before writing. They say which lookup to run first,
|
|
122
|
+
and an id from one workspace is never valid in another.
|
|
123
|
+
2. \`workspaceId\` is filled in from the repository binding, or from
|
|
124
|
+
\`--workspace <name>\`. You rarely pass it.
|
|
125
|
+
3. \`key=@file\` reads a value from a file, \`key=@-\` from stdin, and
|
|
126
|
+
\`--json '{…}'\` passes a nested argument whole.
|
|
127
|
+
4. A misspelled argument is refused here, naming the real ones - it is not
|
|
128
|
+
sent and quietly ignored.
|
|
129
|
+
5. \`FORBIDDEN\` on a whole area means the credential was not granted it. Ask
|
|
130
|
+
the person to sign in again with that area.
|
|
131
|
+
`,
|
|
132
|
+
};
|
|
133
|
+
export const SKILLS = [TASKS, DELIVERY, WORKSPACE];
|
|
134
|
+
/** The stub as it ships, frontmatter included. */
|
|
135
|
+
export function createSkillMarkdown(skill) {
|
|
136
|
+
const frontmatter = `---
|
|
137
|
+
name: ${skill.name}
|
|
138
|
+
description: "${skill.description}"
|
|
139
|
+
user-invocable: false
|
|
140
|
+
author: Valentyn Morenko
|
|
141
|
+
license: MIT
|
|
142
|
+
metadata:
|
|
143
|
+
hermes:
|
|
144
|
+
tags: [${skill.tags.join(", ")}]
|
|
145
|
+
category: ${skill.category}
|
|
146
|
+
---`;
|
|
147
|
+
return `${frontmatter}\n\n${skill.body}`;
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/skill.ts"],"names":[],"mappings":"AAqBA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAE7C,MAAM,KAAK,GAAoB;IAC7B,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,+WAA+W;IACjX,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,mBAAmB,CAAC;IACpE,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCP;CACA,CAAC;AAEF,MAAM,QAAQ,GAAoB;IAChC,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EACT,ubAAub;IACzb,IAAI,EAAE,CAAC,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,mBAAmB,CAAC;IAChF,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCP;CACA,CAAC;AAEF,MAAM,SAAS,GAAoB;IACjC,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EACT,+XAA+X;IACjY,IAAI,EAAE,CAAC,cAAc,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,mBAAmB,CAAC;IAClF,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCP;CACA,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAA+B,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;AAE/E,kDAAkD;AAClD,MAAM,UAAU,mBAAmB,CAAC,KAAsB;IACxD,MAAM,WAAW,GAAG;QACd,KAAK,CAAC,IAAI;gBACF,KAAK,CAAC,WAAW;;;;;;aAMpB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAClB,KAAK,CAAC,QAAQ;IAC1B,CAAC;IACH,OAAO,GAAG,WAAW,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kept in its own leaf module so `--version` costs no module graph: the binary
|
|
3
|
+
* answers it before importing anything else. release-please rewrites the line.
|
|
4
|
+
*/
|
|
5
|
+
export const VERSION = "0.1.1"; // x-release-please-version
|
|
6
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,2BAA2B"}
|