@ascenda-one/agent-mcp 0.1.3

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,wEAAwE;IACxE,0EAA0E;IAC1E,0EAA0E;IAC1E,wBAAwB;IACxB,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,46 @@
1
+ import { defaultTokenFilePath, persistEventWriteToken, readTokenFile } from "@ascenda-one/tool-kit";
2
+ import { randomUUID } from "node:crypto";
3
+ /**
4
+ * Unlike the hook CLIs (one process per invocation, one tool type each),
5
+ * this server is long-lived and host-agnostic — the same binary runs under
6
+ * Claude Code, Cursor, or anything else that can launch an MCP server. It
7
+ * therefore does **not** mint a tool-type prefix the way
8
+ * `ascenda-claude-code-hooks`/`ascenda-codex-hooks` do: minting one here
9
+ * would pair this process as a *third* tool even when the same physical
10
+ * installation already paired through a hook or an IDE extension, silently
11
+ * fragmenting one person's telemetry across multiple tool identities.
12
+ *
13
+ * The user is expected to reuse the fully-qualified id already shown by
14
+ * their existing pairing (`ascenda-claude-hook doctor`-equivalent output,
15
+ * or the extension's "Ascenda: Show Status" command) — an id that already
16
+ * contains `:`. An unqualified value is refused rather than guessed.
17
+ */
18
+ export function loadConfigFromEnv() {
19
+ const apiBaseUrl = (process.env.ASCENDA_API_BASE_URL ?? "https://api.ascenda.one").replace(/\/$/, "");
20
+ const toolInstallationId = process.env.ASCENDA_TOOL_INSTALLATION_ID?.trim();
21
+ if (!toolInstallationId) {
22
+ throw new Error("Missing ASCENDA_TOOL_INSTALLATION_ID");
23
+ }
24
+ if (!toolInstallationId.includes(":")) {
25
+ throw new Error("ASCENDA_TOOL_INSTALLATION_ID must be the fully-qualified id from your existing pairing " +
26
+ '(e.g. "claude_code:abc123"), not a bare id. This server reuses an existing pairing rather ' +
27
+ "than minting a new one — copy the value your hook adapter or IDE extension already shows.");
28
+ }
29
+ const tokenFilePath = process.env.ASCENDA_EVENT_WRITE_TOKEN_FILE ?? defaultTokenFilePath(toolInstallationId);
30
+ const fileToken = readTokenFile(tokenFilePath);
31
+ const eventWriteToken = fileToken ?? process.env.ASCENDA_EVENT_WRITE_TOKEN;
32
+ if (!eventWriteToken) {
33
+ throw new Error("Missing ASCENDA_EVENT_WRITE_TOKEN (or token file) — pair this tool installation first.");
34
+ }
35
+ if (!fileToken)
36
+ persistEventWriteToken(tokenFilePath, eventWriteToken);
37
+ return {
38
+ apiBaseUrl,
39
+ toolInstallationId,
40
+ eventWriteToken,
41
+ tokenFilePath,
42
+ sessionId: process.env.ASCENDA_SESSION_ID ?? randomUUID(),
43
+ workspaceHash: process.env.ASCENDA_WORKSPACE_HASH ?? null
44
+ };
45
+ }
46
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACpG,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAgBzC;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,UAAU,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,yBAAyB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEtG,MAAM,kBAAkB,GAAG,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,IAAI,EAAE,CAAC;IAC5E,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CACb,yFAAyF;YACvF,4FAA4F;YAC5F,2FAA2F,CAC9F,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,8BAA8B,IAAI,oBAAoB,CAAC,kBAAkB,CAAC,CAAC;IAC7G,MAAM,SAAS,GAAG,aAAa,CAAC,aAAa,CAAC,CAAC;IAC/C,MAAM,eAAe,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;IAC3E,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,wFAAwF,CAAC,CAAC;IAC5G,CAAC;IACD,IAAI,CAAC,SAAS;QAAE,sBAAsB,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;IAEvE,OAAO;QACL,UAAU;QACV,kBAAkB;QAClB,eAAe;QACf,aAAa;QACb,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,UAAU,EAAE;QACzD,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,IAAI;KAC1D,CAAC;AACJ,CAAC"}
package/dist/server.js ADDED
@@ -0,0 +1,135 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { AscendaEventSender, bucketDurationMs } from "@ascenda-one/tool-kit";
3
+ import { SEMANTIC_WORK_SIGNAL_EVENT_TYPES } from "@ascenda-one/tool-contract";
4
+ import { z } from "zod";
5
+ /**
6
+ * Named {@link AscendaEventMetadata} keys — reserved, so a skill's free-form
7
+ * `evidenceCounts`/`evidenceFlags` keys can never collide with (and silently
8
+ * overwrite) a field the wire type gives specific meaning to.
9
+ */
10
+ const RESERVED_METADATA_KEYS = new Set([
11
+ "skillVersion",
12
+ "taskFingerprint",
13
+ "language",
14
+ "fileType",
15
+ "durationBucket",
16
+ "tokenPressureBucket",
17
+ "linesChangedBucket",
18
+ "commandClass",
19
+ "outcome",
20
+ "trigger",
21
+ "promptClass",
22
+ "reason",
23
+ "afterHours",
24
+ "activity",
25
+ "message",
26
+ "host",
27
+ "toolName",
28
+ "simulated",
29
+ "relatedEventType"
30
+ ]);
31
+ /**
32
+ * Bare identifiers only (`scopeChanges`, not `"the user said X"`). This is
33
+ * the structural half of "never raw content": the schema below has no field
34
+ * a skill could stuff a sentence into in the first place, and this pattern
35
+ * closes the one place a caller supplies its own keys.
36
+ */
37
+ const EVIDENCE_KEY_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;
38
+ const eventTypeSchema = z.enum(SEMANTIC_WORK_SIGNAL_EVENT_TYPES);
39
+ const evidenceKeySchema = z.string().regex(EVIDENCE_KEY_PATTERN, "must be a bare identifier, not free text");
40
+ const inputShape = {
41
+ eventType: eventTypeSchema.describe("Which semantic pattern was observed. One of the six work-signal types " +
42
+ "— see the ascenda-agent-skills package for what each one means and " +
43
+ "the evidence that should accompany it."),
44
+ skillVersion: z
45
+ .string()
46
+ .regex(/^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$/, "must be a semver version, e.g. 1.0.0")
47
+ .describe("The emitting skill's own version. Mandatory: emission depends on the " +
48
+ "model remembering to call this tool, which drifts across model and " +
49
+ "skill revisions — without a version stamp, a changed emission rate " +
50
+ "is indistinguishable from a changed work pattern."),
51
+ taskFingerprint: z
52
+ .string()
53
+ .regex(/^[a-f0-9]{16,64}$/i, "must be a hash (hex), never the task itself")
54
+ .optional()
55
+ .describe("A local hash identifying the task across attempts, if the skill computed one. Never raw task text."),
56
+ windowMinutes: z
57
+ .number()
58
+ .int()
59
+ .positive()
60
+ .max(1440)
61
+ .optional()
62
+ .describe("Roughly how many minutes the observed pattern spans. Bucketed before it leaves this process."),
63
+ evidenceCounts: z
64
+ .record(evidenceKeySchema, z.number().int())
65
+ .optional()
66
+ .describe('Named integer counts, e.g. { "scopeChanges": 4, "unresolvedDecisions": 3 }. No free text.'),
67
+ evidenceFlags: z
68
+ .record(evidenceKeySchema, z.boolean())
69
+ .optional()
70
+ .describe('Named booleans, e.g. { "originalGoalRetained": false }. No free text.')
71
+ };
72
+ export function buildServer(config) {
73
+ const server = new McpServer({ name: "ascenda-agent-mcp", version: "0.1.0" });
74
+ const sender = new AscendaEventSender({
75
+ apiBaseUrl: config.apiBaseUrl,
76
+ toolInstallationId: config.toolInstallationId,
77
+ source: "mcp_server",
78
+ eventWriteToken: config.eventWriteToken,
79
+ tokenFilePath: config.tokenFilePath,
80
+ sessionId: config.sessionId,
81
+ workspaceHash: config.workspaceHash,
82
+ timeoutMs: 5000
83
+ });
84
+ server.registerTool("ascenda_emit_work_signal", {
85
+ title: "Emit an Ascenda work-friction signal",
86
+ description: "Report an observable work pattern — repeated approach churn, drift from a " +
87
+ "declared goal, a stalled or recovered session, a declared intention or scope " +
88
+ "change. Report the pattern, not a diagnosis: never infer or state the user's " +
89
+ "emotional or mental state, and never assert severity — Ascenda evaluates that " +
90
+ "server-side against the person's own baseline. This tool never transmits " +
91
+ "prompt content, code, file names, or any other project content; the schema " +
92
+ "accepts only enumerated event types, a version stamp, an optional hash, and " +
93
+ "named counts/flags.",
94
+ inputSchema: inputShape
95
+ }, async (args) => {
96
+ for (const key of [...Object.keys(args.evidenceCounts ?? {}), ...Object.keys(args.evidenceFlags ?? {})]) {
97
+ if (RESERVED_METADATA_KEYS.has(key)) {
98
+ return errorResult(`"${key}" is a reserved metadata field name and cannot be used as an evidence key.`);
99
+ }
100
+ }
101
+ const durationBucket = args.windowMinutes ? bucketDurationMs(args.windowMinutes * 60_000) : undefined;
102
+ const metadata = {
103
+ skillVersion: args.skillVersion,
104
+ ...(args.taskFingerprint ? { taskFingerprint: args.taskFingerprint } : {}),
105
+ ...(durationBucket ? { durationBucket } : {}),
106
+ ...(args.evidenceCounts ?? {}),
107
+ ...(args.evidenceFlags ?? {})
108
+ };
109
+ try {
110
+ const result = await sender.sendSemanticSignal({
111
+ eventType: args.eventType,
112
+ metadata
113
+ });
114
+ if (result === "accepted") {
115
+ return { content: [{ type: "text", text: "accepted" }] };
116
+ }
117
+ if (result === "consent_missing") {
118
+ return errorResult("Ascenda rejected this: semantic-signal consent is missing or expired. " +
119
+ "Grant it in the Ascenda app before this tool can report patterns.");
120
+ }
121
+ if (result === "auth_failed") {
122
+ return errorResult("Ascenda rejected this: the event write token is invalid or revoked. Re-pair this tool.");
123
+ }
124
+ return errorResult(`Ascenda rejected this: ${result}.`);
125
+ }
126
+ catch (error) {
127
+ return errorResult(error instanceof Error ? error.message : String(error));
128
+ }
129
+ });
130
+ return server;
131
+ }
132
+ function errorResult(message) {
133
+ return { content: [{ type: "text", text: message }], isError: true };
134
+ }
135
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAmD,gCAAgC,EAAE,MAAM,4BAA4B,CAAC;AAC/H,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;GAIG;AACH,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC;IACrC,cAAc;IACd,iBAAiB;IACjB,UAAU;IACV,UAAU;IACV,gBAAgB;IAChB,qBAAqB;IACrB,oBAAoB;IACpB,cAAc;IACd,SAAS;IACT,SAAS;IACT,aAAa;IACb,QAAQ;IACR,YAAY;IACZ,UAAU;IACV,SAAS;IACT,MAAM;IACN,UAAU;IACV,WAAW;IACX,kBAAkB;CACnB,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG,wBAAwB,CAAC;AAEtD,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,CAC5B,gCAAoE,CACrE,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,oBAAoB,EAAE,0CAA0C,CAAC,CAAC;AAE7G,MAAM,UAAU,GAAG;IACjB,SAAS,EAAE,eAAe,CAAC,QAAQ,CACjC,wEAAwE;QACtE,qEAAqE;QACrE,wCAAwC,CAC3C;IACD,YAAY,EAAE,CAAC;SACZ,MAAM,EAAE;SACR,KAAK,CAAC,kCAAkC,EAAE,sCAAsC,CAAC;SACjF,QAAQ,CACP,uEAAuE;QACrE,qEAAqE;QACrE,qEAAqE;QACrE,mDAAmD,CACtD;IACH,eAAe,EAAE,CAAC;SACf,MAAM,EAAE;SACR,KAAK,CAAC,oBAAoB,EAAE,6CAA6C,CAAC;SAC1E,QAAQ,EAAE;SACV,QAAQ,CAAC,oGAAoG,CAAC;IACjH,aAAa,EAAE,CAAC;SACb,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,GAAG,CAAC,IAAI,CAAC;SACT,QAAQ,EAAE;SACV,QAAQ,CAAC,8FAA8F,CAAC;IAC3G,cAAc,EAAE,CAAC;SACd,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC;SAC3C,QAAQ,EAAE;SACV,QAAQ,CAAC,2FAA2F,CAAC;IACxG,aAAa,EAAE,CAAC;SACb,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;SACtC,QAAQ,EAAE;SACV,QAAQ,CAAC,uEAAuE,CAAC;CACrF,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,MAAwB;IAClD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9E,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC;QACpC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;QAC7C,MAAM,EAAE,YAAY;QACpB,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,SAAS,EAAE,IAAI;KAChB,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,CACjB,0BAA0B,EAC1B;QACE,KAAK,EAAE,sCAAsC;QAC7C,WAAW,EACT,4EAA4E;YAC5E,+EAA+E;YAC/E,+EAA+E;YAC/E,gFAAgF;YAChF,2EAA2E;YAC3E,6EAA6E;YAC7E,8EAA8E;YAC9E,qBAAqB;QACvB,WAAW,EAAE,UAAU;KACxB,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YACxG,IAAI,sBAAsB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpC,OAAO,WAAW,CAAC,IAAI,GAAG,4EAA4E,CAAC,CAAC;YAC1G,CAAC;QACH,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACtG,MAAM,QAAQ,GAAoD;YAChE,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1E,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7C,GAAG,CAAC,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC;YAC9B,GAAG,CAAC,IAAI,CAAC,aAAa,IAAI,EAAE,CAAC;SAC9B,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC;gBAC7C,SAAS,EAAE,IAAI,CAAC,SAAsC;gBACtD,QAAQ;aACT,CAAC,CAAC;YACH,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;gBAC1B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;YAC3D,CAAC;YACD,IAAI,MAAM,KAAK,iBAAiB,EAAE,CAAC;gBACjC,OAAO,WAAW,CAChB,wEAAwE;oBACtE,mEAAmE,CACtE,CAAC;YACJ,CAAC;YACD,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;gBAC7B,OAAO,WAAW,CAAC,wFAAwF,CAAC,CAAC;YAC/G,CAAC;YACD,OAAO,WAAW,CAAC,0BAA0B,MAAM,GAAG,CAAC,CAAC;QAC1D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,WAAW,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC,CACF,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACvE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "publishConfig": { "access": "public" },
3
+ "name": "@ascenda-one/agent-mcp",
4
+ "version": "0.1.3",
5
+ "description": "MCP server exposing ascenda_emit_work_signal — the one submission interface for agent-observed (semantic) work-friction signals.",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/ascendaone-com/ai-engineer-tools.git",
9
+ "directory": "ascenda-agent-mcp"
10
+ },
11
+ "type": "module",
12
+ "files": ["dist"],
13
+ "bin": {
14
+ "ascenda-agent-mcp": "./dist/cli.js"
15
+ },
16
+ "scripts": {
17
+ "build": "tsc -p ./ && npm run bundle",
18
+ "watch": "tsc -w -p ./",
19
+ "bundle": "esbuild src/cli.ts --bundle --platform=node --format=esm --banner:js=\"import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);\" --outfile=dist/cli.js",
20
+ "test": "npm run build && node --test tests/*.test.mjs"
21
+ },
22
+ "license": "Apache-2.0",
23
+ "engines": {
24
+ "node": ">=20"
25
+ },
26
+ "dependencies": {
27
+ "@modelcontextprotocol/sdk": "^1.30.0",
28
+ "zod": "^3.23.8"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^20.14.10",
32
+ "typescript": "^5.5.0",
33
+ "@ascenda-one/tool-contract": "*",
34
+ "@ascenda-one/tool-kit": "*"
35
+ }
36
+ }