@ascenda-one/agent-mcp 0.1.12 → 0.1.13
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 +1 -1
- package/dist/cli.js +427 -89
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ Agent (Claude Code / Cursor / other MCP host)
|
|
|
23
23
|
-> AscendaEventSender.sendSemanticSignal (@ascenda-one/tool-kit)
|
|
24
24
|
-> Ascenda backend (POST /v1/tool-events, consentScope: semantic_work_signals)
|
|
25
25
|
-> paired anonymous Ascenda user
|
|
26
|
-
-> Weekly Loop trigger evaluation / work-map (
|
|
26
|
+
-> Weekly Loop trigger evaluation / work-map (backend)
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
Reuses the same pairing model as the hooks and IDE extensions — same `toolInstallationId` + `eventWriteToken`, same token file convention — but **does not mint its own tool type**. See `src/config.ts`: this process is host-agnostic (the same binary runs under Claude Code or Cursor), so it refuses to guess a prefix the way `ascenda-claude-hook`/`ascenda-codex-hook` do. Passing an id that already contains `:` (i.e. the exact value your existing pairing shows) reuses that pairing's token file; a bare id is rejected rather than silently minting a second, unpaired tool identity.
|
package/dist/cli.js
CHANGED
|
@@ -246,9 +246,28 @@ var require_afterHours = __commonJS({
|
|
|
246
246
|
"../packages/tool-kit/out/afterHours.js"(exports) {
|
|
247
247
|
"use strict";
|
|
248
248
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
249
|
+
exports.BUSINESS_DAY = void 0;
|
|
250
|
+
exports.isOutsideBusinessHours = isOutsideBusinessHours;
|
|
249
251
|
exports.isAfterHours = isAfterHours;
|
|
250
252
|
exports.utcOffsetMinutesAt = utcOffsetMinutesAt;
|
|
251
253
|
exports.localHourAt = localHourAt;
|
|
254
|
+
exports.BUSINESS_DAY = {
|
|
255
|
+
/** 0 = Sunday … 6 = Saturday. */
|
|
256
|
+
days: [1, 2, 3, 4, 5],
|
|
257
|
+
start: "09:00",
|
|
258
|
+
end: "17:00"
|
|
259
|
+
};
|
|
260
|
+
function isOutsideBusinessHours(at = /* @__PURE__ */ new Date(), opts = {}) {
|
|
261
|
+
const days = opts.days ?? exports.BUSINESS_DAY.days;
|
|
262
|
+
if (!days.includes(at.getDay()))
|
|
263
|
+
return true;
|
|
264
|
+
const minutes = at.getHours() * 60 + at.getMinutes();
|
|
265
|
+
const start = parseTimeToMinutes(opts.start ?? exports.BUSINESS_DAY.start, 9 * 60);
|
|
266
|
+
const end = parseTimeToMinutes(opts.end ?? exports.BUSINESS_DAY.end, 17 * 60);
|
|
267
|
+
if (start >= end)
|
|
268
|
+
return false;
|
|
269
|
+
return minutes < start || minutes >= end;
|
|
270
|
+
}
|
|
252
271
|
function isAfterHours(now = /* @__PURE__ */ new Date(), start = "19:00", end = "07:00") {
|
|
253
272
|
const currentMinutes = now.getHours() * 60 + now.getMinutes();
|
|
254
273
|
const startMinutes = parseTimeToMinutes(start, 19 * 60);
|
|
@@ -851,6 +870,7 @@ var require_eventSender = __commonJS({
|
|
|
851
870
|
utcOffsetMinutes: (0, afterHours_1.utcOffsetMinutesAt)(/* @__PURE__ */ new Date()),
|
|
852
871
|
sessionId: identity.sessionId ?? void 0,
|
|
853
872
|
workspaceHash: identity.workspaceHash ?? void 0,
|
|
873
|
+
projectHash: identity.projectHash ?? void 0,
|
|
854
874
|
consentScope: tool_contract_1.ASCENDA_CONSENT_SCOPE,
|
|
855
875
|
provenance: tool_contract_1.ASCENDA_PROVENANCE,
|
|
856
876
|
privacyMode: "metadata_only",
|
|
@@ -906,6 +926,7 @@ var require_eventSender = __commonJS({
|
|
|
906
926
|
severity: "low",
|
|
907
927
|
sessionId: this.config.sessionId ?? void 0,
|
|
908
928
|
workspaceHash: this.config.workspaceHash ?? void 0,
|
|
929
|
+
projectHash: this.config.projectHash ?? void 0,
|
|
909
930
|
consentScope: tool_contract_1.ASCENDA_SEMANTIC_CONSENT_SCOPE,
|
|
910
931
|
provenance: tool_contract_1.ASCENDA_SEMANTIC_PROVENANCE,
|
|
911
932
|
privacyMode: "metadata_only",
|
|
@@ -935,6 +956,7 @@ var require_eventSender = __commonJS({
|
|
|
935
956
|
severity: "low",
|
|
936
957
|
sessionId: this.config.sessionId ?? void 0,
|
|
937
958
|
workspaceHash: this.config.workspaceHash ?? void 0,
|
|
959
|
+
projectHash: this.config.projectHash ?? void 0,
|
|
938
960
|
consentScope: tool_contract_1.ASCENDA_COLLABORATION_CONSENT_SCOPE,
|
|
939
961
|
provenance: tool_contract_1.ASCENDA_PROVENANCE,
|
|
940
962
|
privacyMode: "metadata_only",
|
|
@@ -1025,19 +1047,387 @@ var require_eventSender = __commonJS({
|
|
|
1025
1047
|
}
|
|
1026
1048
|
});
|
|
1027
1049
|
|
|
1050
|
+
// ../packages/tool-kit/out/contextRegistry.js
|
|
1051
|
+
var require_contextRegistry = __commonJS({
|
|
1052
|
+
"../packages/tool-kit/out/contextRegistry.js"(exports) {
|
|
1053
|
+
"use strict";
|
|
1054
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
1055
|
+
if (k2 === void 0) k2 = k;
|
|
1056
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
1057
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
1058
|
+
desc = { enumerable: true, get: function() {
|
|
1059
|
+
return m[k];
|
|
1060
|
+
} };
|
|
1061
|
+
}
|
|
1062
|
+
Object.defineProperty(o, k2, desc);
|
|
1063
|
+
} : function(o, m, k, k2) {
|
|
1064
|
+
if (k2 === void 0) k2 = k;
|
|
1065
|
+
o[k2] = m[k];
|
|
1066
|
+
});
|
|
1067
|
+
var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
|
|
1068
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
1069
|
+
} : function(o, v) {
|
|
1070
|
+
o["default"] = v;
|
|
1071
|
+
});
|
|
1072
|
+
var __importStar = exports && exports.__importStar || /* @__PURE__ */ function() {
|
|
1073
|
+
var ownKeys = function(o) {
|
|
1074
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
1075
|
+
var ar = [];
|
|
1076
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
1077
|
+
return ar;
|
|
1078
|
+
};
|
|
1079
|
+
return ownKeys(o);
|
|
1080
|
+
};
|
|
1081
|
+
return function(mod) {
|
|
1082
|
+
if (mod && mod.__esModule) return mod;
|
|
1083
|
+
var result = {};
|
|
1084
|
+
if (mod != null) {
|
|
1085
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
1086
|
+
}
|
|
1087
|
+
__setModuleDefault(result, mod);
|
|
1088
|
+
return result;
|
|
1089
|
+
};
|
|
1090
|
+
}();
|
|
1091
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1092
|
+
exports.workContextRegistryFilePath = workContextRegistryFilePath;
|
|
1093
|
+
exports.readWorkContextRegistry = readWorkContextRegistry;
|
|
1094
|
+
exports.recordWorkContext = recordWorkContext;
|
|
1095
|
+
exports.recordWorkContextAlias = recordWorkContextAlias;
|
|
1096
|
+
var fs = __importStar(__require("fs"));
|
|
1097
|
+
var os = __importStar(__require("os"));
|
|
1098
|
+
var path = __importStar(__require("path"));
|
|
1099
|
+
var MAX_PATHS_PER_ENTRY = 8;
|
|
1100
|
+
function workContextRegistryFilePath() {
|
|
1101
|
+
return path.join(os.homedir(), ".ascenda", "work-contexts.json");
|
|
1102
|
+
}
|
|
1103
|
+
function readWorkContextRegistry(registryFilePath = workContextRegistryFilePath()) {
|
|
1104
|
+
try {
|
|
1105
|
+
const parsed = JSON.parse(fs.readFileSync(registryFilePath, "utf8"));
|
|
1106
|
+
if (parsed && parsed.version === 1 && parsed.contexts && typeof parsed.contexts === "object") {
|
|
1107
|
+
return parsed;
|
|
1108
|
+
}
|
|
1109
|
+
} catch {
|
|
1110
|
+
}
|
|
1111
|
+
return { version: 1, contexts: {} };
|
|
1112
|
+
}
|
|
1113
|
+
function recordWorkContext(context, options) {
|
|
1114
|
+
if (!context)
|
|
1115
|
+
return false;
|
|
1116
|
+
const updates = [];
|
|
1117
|
+
if (context.projectHash && context.projectLabel) {
|
|
1118
|
+
updates.push({ hash: context.projectHash, kind: "project", label: context.projectLabel, observedPath: context.projectPath ?? context.workspacePath });
|
|
1119
|
+
}
|
|
1120
|
+
if (context.workspaceHash && context.workspaceLabel && context.workspaceHash !== context.projectHash) {
|
|
1121
|
+
updates.push({ hash: context.workspaceHash, kind: "workspace", label: context.workspaceLabel, observedPath: context.workspacePath });
|
|
1122
|
+
}
|
|
1123
|
+
return upsert(updates, options);
|
|
1124
|
+
}
|
|
1125
|
+
function recordWorkContextAlias(hash, label, observedPath, options) {
|
|
1126
|
+
if (!hash || !label)
|
|
1127
|
+
return false;
|
|
1128
|
+
return upsert([{ hash, kind: "alias", label, observedPath: observedPath ?? null }], options);
|
|
1129
|
+
}
|
|
1130
|
+
function upsert(updates, options) {
|
|
1131
|
+
if (updates.length === 0)
|
|
1132
|
+
return false;
|
|
1133
|
+
try {
|
|
1134
|
+
const registryFilePath = options?.registryFilePath ?? workContextRegistryFilePath();
|
|
1135
|
+
const nowIso = (options?.now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
1136
|
+
const registry2 = readWorkContextRegistry(registryFilePath);
|
|
1137
|
+
let dirty = false;
|
|
1138
|
+
for (const update of updates) {
|
|
1139
|
+
const existing = registry2.contexts[update.hash];
|
|
1140
|
+
if (!existing) {
|
|
1141
|
+
registry2.contexts[update.hash] = {
|
|
1142
|
+
kind: update.kind,
|
|
1143
|
+
label: update.label,
|
|
1144
|
+
paths: update.observedPath ? [update.observedPath] : [],
|
|
1145
|
+
firstSeenAt: nowIso,
|
|
1146
|
+
lastSeenAt: nowIso
|
|
1147
|
+
};
|
|
1148
|
+
dirty = true;
|
|
1149
|
+
continue;
|
|
1150
|
+
}
|
|
1151
|
+
if (existing.kind === "alias" && update.kind !== "alias") {
|
|
1152
|
+
existing.kind = update.kind;
|
|
1153
|
+
dirty = true;
|
|
1154
|
+
}
|
|
1155
|
+
if (existing.label !== update.label && update.kind !== "alias") {
|
|
1156
|
+
existing.label = update.label;
|
|
1157
|
+
dirty = true;
|
|
1158
|
+
}
|
|
1159
|
+
if (update.observedPath && !existing.paths.includes(update.observedPath)) {
|
|
1160
|
+
if (existing.paths.length < MAX_PATHS_PER_ENTRY)
|
|
1161
|
+
existing.paths.push(update.observedPath);
|
|
1162
|
+
dirty = true;
|
|
1163
|
+
}
|
|
1164
|
+
if (dayOf(existing.lastSeenAt) !== dayOf(nowIso)) {
|
|
1165
|
+
existing.lastSeenAt = nowIso;
|
|
1166
|
+
dirty = true;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
if (!dirty)
|
|
1170
|
+
return false;
|
|
1171
|
+
writeRegistry(registryFilePath, registry2);
|
|
1172
|
+
return true;
|
|
1173
|
+
} catch {
|
|
1174
|
+
return false;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
function dayOf(iso) {
|
|
1178
|
+
return iso.slice(0, 10);
|
|
1179
|
+
}
|
|
1180
|
+
function writeRegistry(registryFilePath, registry2) {
|
|
1181
|
+
const dir = path.dirname(registryFilePath);
|
|
1182
|
+
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
1183
|
+
const tmp = `${registryFilePath}.${process.pid}.tmp`;
|
|
1184
|
+
fs.writeFileSync(tmp, `${JSON.stringify(registry2, null, 2)}
|
|
1185
|
+
`, { encoding: "utf8", mode: 384 });
|
|
1186
|
+
fs.renameSync(tmp, registryFilePath);
|
|
1187
|
+
if (process.platform !== "win32") {
|
|
1188
|
+
fs.chmodSync(registryFilePath, 384);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
});
|
|
1193
|
+
|
|
1194
|
+
// ../packages/tool-kit/out/salt.js
|
|
1195
|
+
var require_salt = __commonJS({
|
|
1196
|
+
"../packages/tool-kit/out/salt.js"(exports) {
|
|
1197
|
+
"use strict";
|
|
1198
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
1199
|
+
if (k2 === void 0) k2 = k;
|
|
1200
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
1201
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
1202
|
+
desc = { enumerable: true, get: function() {
|
|
1203
|
+
return m[k];
|
|
1204
|
+
} };
|
|
1205
|
+
}
|
|
1206
|
+
Object.defineProperty(o, k2, desc);
|
|
1207
|
+
} : function(o, m, k, k2) {
|
|
1208
|
+
if (k2 === void 0) k2 = k;
|
|
1209
|
+
o[k2] = m[k];
|
|
1210
|
+
});
|
|
1211
|
+
var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
|
|
1212
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
1213
|
+
} : function(o, v) {
|
|
1214
|
+
o["default"] = v;
|
|
1215
|
+
});
|
|
1216
|
+
var __importStar = exports && exports.__importStar || /* @__PURE__ */ function() {
|
|
1217
|
+
var ownKeys = function(o) {
|
|
1218
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
1219
|
+
var ar = [];
|
|
1220
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
1221
|
+
return ar;
|
|
1222
|
+
};
|
|
1223
|
+
return ownKeys(o);
|
|
1224
|
+
};
|
|
1225
|
+
return function(mod) {
|
|
1226
|
+
if (mod && mod.__esModule) return mod;
|
|
1227
|
+
var result = {};
|
|
1228
|
+
if (mod != null) {
|
|
1229
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
1230
|
+
}
|
|
1231
|
+
__setModuleDefault(result, mod);
|
|
1232
|
+
return result;
|
|
1233
|
+
};
|
|
1234
|
+
}();
|
|
1235
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1236
|
+
exports.machineSaltFilePath = machineSaltFilePath;
|
|
1237
|
+
exports.readOrCreateMachineSalt = readOrCreateMachineSalt;
|
|
1238
|
+
exports.hashWithMachineSalt = hashWithMachineSalt;
|
|
1239
|
+
var crypto = __importStar(__require("crypto"));
|
|
1240
|
+
var fs = __importStar(__require("fs"));
|
|
1241
|
+
var os = __importStar(__require("os"));
|
|
1242
|
+
var path = __importStar(__require("path"));
|
|
1243
|
+
function machineSaltFilePath() {
|
|
1244
|
+
return path.join(os.homedir(), ".ascenda", "salt");
|
|
1245
|
+
}
|
|
1246
|
+
var cache = /* @__PURE__ */ new Map();
|
|
1247
|
+
function readOrCreateMachineSalt(saltFilePath = machineSaltFilePath()) {
|
|
1248
|
+
const hit = cache.get(saltFilePath);
|
|
1249
|
+
if (hit)
|
|
1250
|
+
return hit;
|
|
1251
|
+
const dir = path.dirname(saltFilePath);
|
|
1252
|
+
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
1253
|
+
let salt;
|
|
1254
|
+
try {
|
|
1255
|
+
salt = crypto.randomBytes(32).toString("hex");
|
|
1256
|
+
fs.writeFileSync(saltFilePath, salt, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
1257
|
+
} catch (error2) {
|
|
1258
|
+
if (error2.code !== "EEXIST")
|
|
1259
|
+
throw error2;
|
|
1260
|
+
salt = fs.readFileSync(saltFilePath, "utf8").trim();
|
|
1261
|
+
}
|
|
1262
|
+
if (process.platform !== "win32") {
|
|
1263
|
+
fs.chmodSync(dir, 448);
|
|
1264
|
+
fs.chmodSync(saltFilePath, 384);
|
|
1265
|
+
}
|
|
1266
|
+
cache.set(saltFilePath, salt);
|
|
1267
|
+
return salt;
|
|
1268
|
+
}
|
|
1269
|
+
function hashWithMachineSalt(value, saltFilePath) {
|
|
1270
|
+
if (!value)
|
|
1271
|
+
return null;
|
|
1272
|
+
return crypto.createHash("sha256").update(readOrCreateMachineSalt(saltFilePath)).update("\0").update(value).digest("hex").slice(0, 16);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
});
|
|
1276
|
+
|
|
1277
|
+
// ../packages/tool-kit/out/workContext.js
|
|
1278
|
+
var require_workContext = __commonJS({
|
|
1279
|
+
"../packages/tool-kit/out/workContext.js"(exports) {
|
|
1280
|
+
"use strict";
|
|
1281
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
1282
|
+
if (k2 === void 0) k2 = k;
|
|
1283
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
1284
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
1285
|
+
desc = { enumerable: true, get: function() {
|
|
1286
|
+
return m[k];
|
|
1287
|
+
} };
|
|
1288
|
+
}
|
|
1289
|
+
Object.defineProperty(o, k2, desc);
|
|
1290
|
+
} : function(o, m, k, k2) {
|
|
1291
|
+
if (k2 === void 0) k2 = k;
|
|
1292
|
+
o[k2] = m[k];
|
|
1293
|
+
});
|
|
1294
|
+
var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
|
|
1295
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
1296
|
+
} : function(o, v) {
|
|
1297
|
+
o["default"] = v;
|
|
1298
|
+
});
|
|
1299
|
+
var __importStar = exports && exports.__importStar || /* @__PURE__ */ function() {
|
|
1300
|
+
var ownKeys = function(o) {
|
|
1301
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
1302
|
+
var ar = [];
|
|
1303
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
1304
|
+
return ar;
|
|
1305
|
+
};
|
|
1306
|
+
return ownKeys(o);
|
|
1307
|
+
};
|
|
1308
|
+
return function(mod) {
|
|
1309
|
+
if (mod && mod.__esModule) return mod;
|
|
1310
|
+
var result = {};
|
|
1311
|
+
if (mod != null) {
|
|
1312
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
1313
|
+
}
|
|
1314
|
+
__setModuleDefault(result, mod);
|
|
1315
|
+
return result;
|
|
1316
|
+
};
|
|
1317
|
+
}();
|
|
1318
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1319
|
+
exports.deriveWorkContext = deriveWorkContext;
|
|
1320
|
+
var fs = __importStar(__require("fs"));
|
|
1321
|
+
var path = __importStar(__require("path"));
|
|
1322
|
+
var salt_1 = require_salt();
|
|
1323
|
+
var MAX_WALK_DEPTH = 64;
|
|
1324
|
+
function deriveWorkContext(cwd, saltFilePath) {
|
|
1325
|
+
if (!cwd || !cwd.trim())
|
|
1326
|
+
return null;
|
|
1327
|
+
const startPath = stripTrailingSeparators(cwd.trim());
|
|
1328
|
+
let roots = null;
|
|
1329
|
+
try {
|
|
1330
|
+
roots = resolveRepositoryRoots(startPath);
|
|
1331
|
+
} catch {
|
|
1332
|
+
roots = null;
|
|
1333
|
+
}
|
|
1334
|
+
const workspacePath = roots?.checkoutRoot ?? startPath;
|
|
1335
|
+
const workspaceLabel = basenameOf(workspacePath);
|
|
1336
|
+
if (!workspaceLabel)
|
|
1337
|
+
return null;
|
|
1338
|
+
const projectPath = roots?.canonicalRoot ?? null;
|
|
1339
|
+
const projectLabel = (projectPath ? basenameOf(projectPath) : null) ?? workspaceLabel;
|
|
1340
|
+
return {
|
|
1341
|
+
workspaceLabel,
|
|
1342
|
+
projectLabel,
|
|
1343
|
+
workspaceHash: (0, salt_1.hashWithMachineSalt)(workspaceLabel, saltFilePath),
|
|
1344
|
+
projectHash: (0, salt_1.hashWithMachineSalt)(projectLabel, saltFilePath),
|
|
1345
|
+
workspacePath,
|
|
1346
|
+
projectPath
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
function resolveRepositoryRoots(startDir) {
|
|
1350
|
+
if (!fs.existsSync(startDir))
|
|
1351
|
+
return null;
|
|
1352
|
+
let dir = startDir;
|
|
1353
|
+
for (let depth = 0; depth < MAX_WALK_DEPTH; depth++) {
|
|
1354
|
+
const dotGit = path.join(dir, ".git");
|
|
1355
|
+
let stat = null;
|
|
1356
|
+
try {
|
|
1357
|
+
stat = fs.statSync(dotGit);
|
|
1358
|
+
} catch {
|
|
1359
|
+
stat = null;
|
|
1360
|
+
}
|
|
1361
|
+
if (stat?.isDirectory())
|
|
1362
|
+
return { checkoutRoot: dir, canonicalRoot: dir };
|
|
1363
|
+
if (stat?.isFile())
|
|
1364
|
+
return { checkoutRoot: dir, canonicalRoot: worktreeParentRoot(dotGit, dir) ?? dir };
|
|
1365
|
+
const parent = path.dirname(dir);
|
|
1366
|
+
if (parent === dir)
|
|
1367
|
+
return null;
|
|
1368
|
+
dir = parent;
|
|
1369
|
+
}
|
|
1370
|
+
return null;
|
|
1371
|
+
}
|
|
1372
|
+
function worktreeParentRoot(dotGitFile, containingDir) {
|
|
1373
|
+
let gitdir;
|
|
1374
|
+
try {
|
|
1375
|
+
const match = /^gitdir:\s*(.+)\s*$/m.exec(fs.readFileSync(dotGitFile, "utf8"));
|
|
1376
|
+
if (!match)
|
|
1377
|
+
return null;
|
|
1378
|
+
gitdir = match[1].trim();
|
|
1379
|
+
} catch {
|
|
1380
|
+
return null;
|
|
1381
|
+
}
|
|
1382
|
+
const resolved = path.resolve(containingDir, gitdir);
|
|
1383
|
+
const marker = `${path.sep}.git${path.sep}worktrees${path.sep}`;
|
|
1384
|
+
const idx = resolved.indexOf(marker);
|
|
1385
|
+
if (idx === -1)
|
|
1386
|
+
return null;
|
|
1387
|
+
return resolved.slice(0, idx);
|
|
1388
|
+
}
|
|
1389
|
+
function stripTrailingSeparators(value) {
|
|
1390
|
+
let end = value.length;
|
|
1391
|
+
while (end > 1 && (value[end - 1] === "/" || value[end - 1] === "\\"))
|
|
1392
|
+
end--;
|
|
1393
|
+
return value.slice(0, end);
|
|
1394
|
+
}
|
|
1395
|
+
function basenameOf(value) {
|
|
1396
|
+
const segment = value.split(/[\\/]/).filter(Boolean).pop() ?? null;
|
|
1397
|
+
return segment && segment.length > 0 ? segment : null;
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
});
|
|
1401
|
+
|
|
1028
1402
|
// ../packages/tool-kit/out/hookAdapter.js
|
|
1029
1403
|
var require_hookAdapter = __commonJS({
|
|
1030
1404
|
"../packages/tool-kit/out/hookAdapter.js"(exports) {
|
|
1031
1405
|
"use strict";
|
|
1032
1406
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1033
1407
|
exports.DEFAULT_API_BASE_URL = void 0;
|
|
1408
|
+
exports.resolveContextHashes = resolveContextHashes;
|
|
1034
1409
|
exports.loadCliAgentConfig = loadCliAgentConfig;
|
|
1035
1410
|
exports.deliverHookEvents = deliverHookEvents;
|
|
1411
|
+
var contextRegistry_1 = require_contextRegistry();
|
|
1036
1412
|
var eventLog_1 = require_eventLog();
|
|
1037
1413
|
var eventSender_1 = require_eventSender();
|
|
1038
1414
|
var tokenStore_1 = require_tokenStore();
|
|
1415
|
+
var workContext_1 = require_workContext();
|
|
1039
1416
|
exports.DEFAULT_API_BASE_URL = "https://api.ascenda.one";
|
|
1040
|
-
function
|
|
1417
|
+
function resolveContextHashes(cwd) {
|
|
1418
|
+
const workspaceOverride = process.env.ASCENDA_WORKSPACE_HASH?.trim() || null;
|
|
1419
|
+
const projectOverride = process.env.ASCENDA_PROJECT_HASH?.trim() || null;
|
|
1420
|
+
if (workspaceOverride && projectOverride)
|
|
1421
|
+
return { workspaceHash: workspaceOverride, projectHash: projectOverride };
|
|
1422
|
+
const context = (0, workContext_1.deriveWorkContext)(cwd ?? process.cwd());
|
|
1423
|
+
if (context)
|
|
1424
|
+
(0, contextRegistry_1.recordWorkContext)(context);
|
|
1425
|
+
return {
|
|
1426
|
+
workspaceHash: workspaceOverride ?? context?.workspaceHash ?? null,
|
|
1427
|
+
projectHash: projectOverride ?? context?.projectHash ?? null
|
|
1428
|
+
};
|
|
1429
|
+
}
|
|
1430
|
+
function loadCliAgentConfig(toolType, sessionIdFromHook, cwd) {
|
|
1041
1431
|
const apiBaseUrl = (process.env.ASCENDA_API_BASE_URL ?? exports.DEFAULT_API_BASE_URL).replace(/\/$/, "");
|
|
1042
1432
|
const toolInstallationIdRaw = process.env.ASCENDA_TOOL_INSTALLATION_ID;
|
|
1043
1433
|
if (!toolInstallationIdRaw)
|
|
@@ -1050,13 +1440,15 @@ var require_hookAdapter = __commonJS({
|
|
|
1050
1440
|
throw new Error("Missing ASCENDA_EVENT_WRITE_TOKEN (or token file)");
|
|
1051
1441
|
if (!fileToken)
|
|
1052
1442
|
(0, tokenStore_1.persistEventWriteToken)(tokenFilePath, eventWriteToken);
|
|
1443
|
+
const contextHashes = resolveContextHashes(cwd);
|
|
1053
1444
|
return {
|
|
1054
1445
|
apiBaseUrl,
|
|
1055
1446
|
toolInstallationId,
|
|
1056
1447
|
eventWriteToken,
|
|
1057
1448
|
tokenFilePath,
|
|
1058
1449
|
sessionId: process.env.ASCENDA_SESSION_ID ?? sessionIdFromHook ?? null,
|
|
1059
|
-
workspaceHash:
|
|
1450
|
+
workspaceHash: contextHashes.workspaceHash,
|
|
1451
|
+
projectHash: contextHashes.projectHash,
|
|
1060
1452
|
// Agents await command hooks; fail fast rather than stall the user's turn.
|
|
1061
1453
|
timeoutMs: parsePositiveInt(process.env.ASCENDA_HTTP_TIMEOUT_MS) ?? 3e3
|
|
1062
1454
|
};
|
|
@@ -1067,11 +1459,12 @@ var require_hookAdapter = __commonJS({
|
|
|
1067
1459
|
const notice = options.onNotice ?? ((message) => console.error(message));
|
|
1068
1460
|
let config2;
|
|
1069
1461
|
try {
|
|
1070
|
-
config2 = loadCliAgentConfig(options.toolType, options.sessionId);
|
|
1462
|
+
config2 = loadCliAgentConfig(options.toolType, options.sessionId, options.cwd);
|
|
1071
1463
|
} catch (error2) {
|
|
1072
1464
|
const logFile = (0, eventLog_1.resolveEventLogPath)();
|
|
1073
1465
|
if (!logFile)
|
|
1074
1466
|
throw error2;
|
|
1467
|
+
const contextHashes = resolveContextHashes(options.cwd);
|
|
1075
1468
|
for (const event of events) {
|
|
1076
1469
|
(0, eventLog_1.appendEventLog)(logFile, {
|
|
1077
1470
|
loggedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -1080,7 +1473,8 @@ var require_hookAdapter = __commonJS({
|
|
|
1080
1473
|
toolInstallationId: `${options.toolType}:unpaired`,
|
|
1081
1474
|
source: options.source,
|
|
1082
1475
|
sessionId: options.sessionId ?? null,
|
|
1083
|
-
workspaceHash:
|
|
1476
|
+
workspaceHash: contextHashes.workspaceHash,
|
|
1477
|
+
projectHash: contextHashes.projectHash
|
|
1084
1478
|
}, event)
|
|
1085
1479
|
});
|
|
1086
1480
|
}
|
|
@@ -1094,6 +1488,7 @@ var require_hookAdapter = __commonJS({
|
|
|
1094
1488
|
tokenFilePath: config2.tokenFilePath,
|
|
1095
1489
|
sessionId: config2.sessionId,
|
|
1096
1490
|
workspaceHash: config2.workspaceHash,
|
|
1491
|
+
projectHash: config2.projectHash,
|
|
1097
1492
|
timeoutMs: config2.timeoutMs
|
|
1098
1493
|
});
|
|
1099
1494
|
for (const event of events) {
|
|
@@ -1199,89 +1594,6 @@ var require_turnState = __commonJS({
|
|
|
1199
1594
|
}
|
|
1200
1595
|
});
|
|
1201
1596
|
|
|
1202
|
-
// ../packages/tool-kit/out/salt.js
|
|
1203
|
-
var require_salt = __commonJS({
|
|
1204
|
-
"../packages/tool-kit/out/salt.js"(exports) {
|
|
1205
|
-
"use strict";
|
|
1206
|
-
var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
1207
|
-
if (k2 === void 0) k2 = k;
|
|
1208
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
1209
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
1210
|
-
desc = { enumerable: true, get: function() {
|
|
1211
|
-
return m[k];
|
|
1212
|
-
} };
|
|
1213
|
-
}
|
|
1214
|
-
Object.defineProperty(o, k2, desc);
|
|
1215
|
-
} : function(o, m, k, k2) {
|
|
1216
|
-
if (k2 === void 0) k2 = k;
|
|
1217
|
-
o[k2] = m[k];
|
|
1218
|
-
});
|
|
1219
|
-
var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
|
|
1220
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
1221
|
-
} : function(o, v) {
|
|
1222
|
-
o["default"] = v;
|
|
1223
|
-
});
|
|
1224
|
-
var __importStar = exports && exports.__importStar || /* @__PURE__ */ function() {
|
|
1225
|
-
var ownKeys = function(o) {
|
|
1226
|
-
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
1227
|
-
var ar = [];
|
|
1228
|
-
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
1229
|
-
return ar;
|
|
1230
|
-
};
|
|
1231
|
-
return ownKeys(o);
|
|
1232
|
-
};
|
|
1233
|
-
return function(mod) {
|
|
1234
|
-
if (mod && mod.__esModule) return mod;
|
|
1235
|
-
var result = {};
|
|
1236
|
-
if (mod != null) {
|
|
1237
|
-
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
1238
|
-
}
|
|
1239
|
-
__setModuleDefault(result, mod);
|
|
1240
|
-
return result;
|
|
1241
|
-
};
|
|
1242
|
-
}();
|
|
1243
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1244
|
-
exports.machineSaltFilePath = machineSaltFilePath;
|
|
1245
|
-
exports.readOrCreateMachineSalt = readOrCreateMachineSalt;
|
|
1246
|
-
exports.hashWithMachineSalt = hashWithMachineSalt;
|
|
1247
|
-
var crypto = __importStar(__require("crypto"));
|
|
1248
|
-
var fs = __importStar(__require("fs"));
|
|
1249
|
-
var os = __importStar(__require("os"));
|
|
1250
|
-
var path = __importStar(__require("path"));
|
|
1251
|
-
function machineSaltFilePath() {
|
|
1252
|
-
return path.join(os.homedir(), ".ascenda", "salt");
|
|
1253
|
-
}
|
|
1254
|
-
var cache = /* @__PURE__ */ new Map();
|
|
1255
|
-
function readOrCreateMachineSalt(saltFilePath = machineSaltFilePath()) {
|
|
1256
|
-
const hit = cache.get(saltFilePath);
|
|
1257
|
-
if (hit)
|
|
1258
|
-
return hit;
|
|
1259
|
-
const dir = path.dirname(saltFilePath);
|
|
1260
|
-
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
1261
|
-
let salt;
|
|
1262
|
-
try {
|
|
1263
|
-
salt = crypto.randomBytes(32).toString("hex");
|
|
1264
|
-
fs.writeFileSync(saltFilePath, salt, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
1265
|
-
} catch (error2) {
|
|
1266
|
-
if (error2.code !== "EEXIST")
|
|
1267
|
-
throw error2;
|
|
1268
|
-
salt = fs.readFileSync(saltFilePath, "utf8").trim();
|
|
1269
|
-
}
|
|
1270
|
-
if (process.platform !== "win32") {
|
|
1271
|
-
fs.chmodSync(dir, 448);
|
|
1272
|
-
fs.chmodSync(saltFilePath, 384);
|
|
1273
|
-
}
|
|
1274
|
-
cache.set(saltFilePath, salt);
|
|
1275
|
-
return salt;
|
|
1276
|
-
}
|
|
1277
|
-
function hashWithMachineSalt(value, saltFilePath) {
|
|
1278
|
-
if (!value)
|
|
1279
|
-
return null;
|
|
1280
|
-
return crypto.createHash("sha256").update(readOrCreateMachineSalt(saltFilePath)).update("\0").update(value).digest("hex").slice(0, 16);
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
});
|
|
1284
|
-
|
|
1285
1597
|
// ../packages/tool-kit/out/liveBus.js
|
|
1286
1598
|
var require_liveBus = __commonJS({
|
|
1287
1599
|
"../packages/tool-kit/out/liveBus.js"(exports) {
|
|
@@ -1413,8 +1725,8 @@ var require_out2 = __commonJS({
|
|
|
1413
1725
|
"../packages/tool-kit/out/index.js"(exports) {
|
|
1414
1726
|
"use strict";
|
|
1415
1727
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1416
|
-
exports.
|
|
1417
|
-
exports.isRetryableStatus = exports.parseIngestResponse = exports.postToolEventsBatch = exports.postToolEvent = void 0;
|
|
1728
|
+
exports.workContextRegistryFilePath = exports.readWorkContextRegistry = exports.recordWorkContextAlias = exports.recordWorkContext = exports.deriveWorkContext = exports.hashWithMachineSalt = exports.readOrCreateMachineSalt = exports.machineSaltFilePath = exports.markFailureNotified = exports.shouldAnnounceFailure = exports.recordSendOutcome = exports.readCollectorState = exports.defaultStateFilePath = exports.readTokenFile = exports.persistEventWriteToken = exports.defaultTokenFilePath = exports.recordTurnStart = exports.consumeTurnDurationMs = exports.resolveContextHashes = exports.loadCliAgentConfig = exports.deliverHookEvents = exports.DEFAULT_API_BASE_URL = exports.resolveEventLogPath = exports.expandUserPath = exports.appendEventLog = exports.EVENT_LOG_ENV_VAR = exports.buildEventPayload = exports.AscendaSemanticEventError = exports.AscendaEventSender = exports.looksLikeCorrection = exports.outcomeForHook = exports.inferOutcome = exports.getNestedNumber = exports.getNestedString = exports.getNested = exports.getNumber = exports.getString = exports.localHourAt = exports.utcOffsetMinutesAt = exports.BUSINESS_DAY = exports.isOutsideBusinessHours = exports.isAfterHours = exports.bucketDurationMs = exports.bucketLinesChanged = exports.invitesDebrief = exports.classifyWorkMilestone = exports.isReworkGitAction = exports.classifyGitAction = exports.isVerificationCommand = exports.classifyCommand = void 0;
|
|
1729
|
+
exports.isRetryableStatus = exports.parseIngestResponse = exports.postToolEventsBatch = exports.postToolEvent = exports.renewToolToken = exports.getPairingStatus = exports.createPairingSession = exports.AscendaApiError = exports.liveBusSocketCandidates = exports.liveBusSocketPath = exports.bucketPromptSize = exports.emitLiveSignal = void 0;
|
|
1418
1730
|
var commandClassifier_1 = require_commandClassifier();
|
|
1419
1731
|
Object.defineProperty(exports, "classifyCommand", { enumerable: true, get: function() {
|
|
1420
1732
|
return commandClassifier_1.classifyCommand;
|
|
@@ -1447,6 +1759,12 @@ var require_out2 = __commonJS({
|
|
|
1447
1759
|
Object.defineProperty(exports, "isAfterHours", { enumerable: true, get: function() {
|
|
1448
1760
|
return afterHours_1.isAfterHours;
|
|
1449
1761
|
} });
|
|
1762
|
+
Object.defineProperty(exports, "isOutsideBusinessHours", { enumerable: true, get: function() {
|
|
1763
|
+
return afterHours_1.isOutsideBusinessHours;
|
|
1764
|
+
} });
|
|
1765
|
+
Object.defineProperty(exports, "BUSINESS_DAY", { enumerable: true, get: function() {
|
|
1766
|
+
return afterHours_1.BUSINESS_DAY;
|
|
1767
|
+
} });
|
|
1450
1768
|
Object.defineProperty(exports, "utcOffsetMinutesAt", { enumerable: true, get: function() {
|
|
1451
1769
|
return afterHours_1.utcOffsetMinutesAt;
|
|
1452
1770
|
} });
|
|
@@ -1511,6 +1829,9 @@ var require_out2 = __commonJS({
|
|
|
1511
1829
|
Object.defineProperty(exports, "loadCliAgentConfig", { enumerable: true, get: function() {
|
|
1512
1830
|
return hookAdapter_1.loadCliAgentConfig;
|
|
1513
1831
|
} });
|
|
1832
|
+
Object.defineProperty(exports, "resolveContextHashes", { enumerable: true, get: function() {
|
|
1833
|
+
return hookAdapter_1.resolveContextHashes;
|
|
1834
|
+
} });
|
|
1514
1835
|
var turnState_1 = require_turnState();
|
|
1515
1836
|
Object.defineProperty(exports, "consumeTurnDurationMs", { enumerable: true, get: function() {
|
|
1516
1837
|
return turnState_1.consumeTurnDurationMs;
|
|
@@ -1554,6 +1875,23 @@ var require_out2 = __commonJS({
|
|
|
1554
1875
|
Object.defineProperty(exports, "hashWithMachineSalt", { enumerable: true, get: function() {
|
|
1555
1876
|
return salt_1.hashWithMachineSalt;
|
|
1556
1877
|
} });
|
|
1878
|
+
var workContext_1 = require_workContext();
|
|
1879
|
+
Object.defineProperty(exports, "deriveWorkContext", { enumerable: true, get: function() {
|
|
1880
|
+
return workContext_1.deriveWorkContext;
|
|
1881
|
+
} });
|
|
1882
|
+
var contextRegistry_1 = require_contextRegistry();
|
|
1883
|
+
Object.defineProperty(exports, "recordWorkContext", { enumerable: true, get: function() {
|
|
1884
|
+
return contextRegistry_1.recordWorkContext;
|
|
1885
|
+
} });
|
|
1886
|
+
Object.defineProperty(exports, "recordWorkContextAlias", { enumerable: true, get: function() {
|
|
1887
|
+
return contextRegistry_1.recordWorkContextAlias;
|
|
1888
|
+
} });
|
|
1889
|
+
Object.defineProperty(exports, "readWorkContextRegistry", { enumerable: true, get: function() {
|
|
1890
|
+
return contextRegistry_1.readWorkContextRegistry;
|
|
1891
|
+
} });
|
|
1892
|
+
Object.defineProperty(exports, "workContextRegistryFilePath", { enumerable: true, get: function() {
|
|
1893
|
+
return contextRegistry_1.workContextRegistryFilePath;
|
|
1894
|
+
} });
|
|
1557
1895
|
var liveBus_1 = require_liveBus();
|
|
1558
1896
|
Object.defineProperty(exports, "emitLiveSignal", { enumerable: true, get: function() {
|
|
1559
1897
|
return liveBus_1.emitLiveSignal;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"publishConfig": { "access": "public" },
|
|
3
3
|
"name": "@ascenda-one/agent-mcp",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.13",
|
|
5
5
|
"description": "MCP server exposing ascenda_emit_work_signal — the one submission interface for agent-observed (semantic) work-friction signals.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|