@sentry/junior 0.21.0 → 0.22.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/dist/app.js +1069 -307
- package/dist/{chunk-NRSP2MLC.js → chunk-JWBWBJYJ.js} +9 -4
- package/dist/{chunk-N4ICA2BC.js → chunk-MCJJKEB3.js} +523 -95
- package/dist/{chunk-Z43DS7XN.js → chunk-THPM7NSG.js} +1 -1
- package/dist/cli/check.js +2 -2
- package/dist/cli/snapshot-warmup.js +2 -2
- package/package.json +5 -4
|
@@ -8,6 +8,14 @@ import {
|
|
|
8
8
|
|
|
9
9
|
// src/chat/logging.ts
|
|
10
10
|
import { AsyncLocalStorage } from "async_hooks";
|
|
11
|
+
import path from "path";
|
|
12
|
+
import { styleText } from "util";
|
|
13
|
+
import {
|
|
14
|
+
ConfigError,
|
|
15
|
+
configureSync,
|
|
16
|
+
getConfig,
|
|
17
|
+
getLogger
|
|
18
|
+
} from "@logtape/logtape";
|
|
11
19
|
|
|
12
20
|
// src/chat/coerce.ts
|
|
13
21
|
function toOptionalString(value) {
|
|
@@ -58,20 +66,13 @@ var LEGACY_KEY_MAP = {
|
|
|
58
66
|
};
|
|
59
67
|
var contextStorage = new AsyncLocalStorage();
|
|
60
68
|
var logRecordSinks = /* @__PURE__ */ new Set();
|
|
61
|
-
var
|
|
62
|
-
|
|
63
|
-
faint: "\x1B[2m",
|
|
64
|
-
red: "\x1B[31m",
|
|
65
|
-
yellow: "\x1B[33m",
|
|
66
|
-
green: "\x1B[32m",
|
|
67
|
-
blue: "\x1B[34m",
|
|
68
|
-
cyan: "\x1B[36m",
|
|
69
|
-
gray: "\x1B[90m"
|
|
70
|
-
};
|
|
69
|
+
var LOGTAPE_BODY_KEY = "__logtape_body";
|
|
70
|
+
var ROOT_LOGGER_CATEGORY = ["junior"];
|
|
71
71
|
var CONSOLE_PRIORITY_KEYS = [
|
|
72
72
|
"gen_ai.conversation.id",
|
|
73
73
|
"app.turn.id",
|
|
74
74
|
"event.name",
|
|
75
|
+
"app.log.source",
|
|
75
76
|
"error.message",
|
|
76
77
|
"messaging.message.id",
|
|
77
78
|
"app.trace_id",
|
|
@@ -119,6 +120,42 @@ function shouldEmitConsole(level) {
|
|
|
119
120
|
}
|
|
120
121
|
return true;
|
|
121
122
|
}
|
|
123
|
+
function isDevelopmentLoggingMode() {
|
|
124
|
+
if (process.env.NODE_ENV !== "development") {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
if (process.env.CI) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
function shouldUseDevelopmentConsoleFormat() {
|
|
133
|
+
if (!isDevelopmentLoggingMode()) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
return process.env.JUNIOR_LOG_FORMAT?.trim().toLowerCase() !== "structured";
|
|
137
|
+
}
|
|
138
|
+
function shouldUsePrettyConsole(level) {
|
|
139
|
+
if (level === "warn" || level === "error") {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
return shouldUseDevelopmentConsoleFormat();
|
|
143
|
+
}
|
|
144
|
+
function shouldUseConsoleColor() {
|
|
145
|
+
if (!shouldUseDevelopmentConsoleFormat()) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
if (process.env.NO_COLOR) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
return process.env.FORCE_COLOR?.trim() === "1" || Boolean(process.stdout?.isTTY) || Boolean(process.stderr?.isTTY);
|
|
152
|
+
}
|
|
153
|
+
function formatConsoleTimestamp(timestamp) {
|
|
154
|
+
if (shouldUseDevelopmentConsoleFormat()) {
|
|
155
|
+
return timestamp.toTimeString().slice(0, 8);
|
|
156
|
+
}
|
|
157
|
+
return timestamp.toISOString();
|
|
158
|
+
}
|
|
122
159
|
function findNextBlankLineBoundary(input, start) {
|
|
123
160
|
const lfBoundary = input.indexOf("\n\n", start);
|
|
124
161
|
const crlfBoundary = input.indexOf("\r\n\r\n", start);
|
|
@@ -311,6 +348,126 @@ function mergeAttributes(...maps) {
|
|
|
311
348
|
}
|
|
312
349
|
return merged;
|
|
313
350
|
}
|
|
351
|
+
function fromLogTapeLevel(level) {
|
|
352
|
+
if (level === "warning") {
|
|
353
|
+
return "warn";
|
|
354
|
+
}
|
|
355
|
+
if (level === "fatal") {
|
|
356
|
+
return "error";
|
|
357
|
+
}
|
|
358
|
+
if (level === "trace") {
|
|
359
|
+
return "debug";
|
|
360
|
+
}
|
|
361
|
+
return level;
|
|
362
|
+
}
|
|
363
|
+
function getLogSource(category) {
|
|
364
|
+
if (category.length <= ROOT_LOGGER_CATEGORY.length) {
|
|
365
|
+
return void 0;
|
|
366
|
+
}
|
|
367
|
+
const sourceParts = category.slice(ROOT_LOGGER_CATEGORY.length);
|
|
368
|
+
return sourceParts.length > 0 ? sourceParts.join(".") : void 0;
|
|
369
|
+
}
|
|
370
|
+
function toEmittedLogRecord(record) {
|
|
371
|
+
const properties = { ...record.properties };
|
|
372
|
+
const rawBody = properties[LOGTAPE_BODY_KEY];
|
|
373
|
+
delete properties[LOGTAPE_BODY_KEY];
|
|
374
|
+
const attributes = mergeAttributes(properties);
|
|
375
|
+
const source = getLogSource(record.category);
|
|
376
|
+
if (source && attributes["app.log.source"] === void 0) {
|
|
377
|
+
attributes["app.log.source"] = source;
|
|
378
|
+
}
|
|
379
|
+
const body = toOptionalString(rawBody) ?? record.message.map(
|
|
380
|
+
(segment) => typeof segment === "string" ? segment : String(segment ?? "")
|
|
381
|
+
).join("");
|
|
382
|
+
const eventName = toOptionalString(attributes["event.name"]) ?? "log_record_emitted";
|
|
383
|
+
return {
|
|
384
|
+
level: fromLogTapeLevel(record.level),
|
|
385
|
+
eventName,
|
|
386
|
+
body,
|
|
387
|
+
attributes
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
function createConsoleSink() {
|
|
391
|
+
return (record) => {
|
|
392
|
+
const emitted = toEmittedLogRecord(record);
|
|
393
|
+
emitConsole(
|
|
394
|
+
emitted.level,
|
|
395
|
+
emitted.eventName,
|
|
396
|
+
emitted.body,
|
|
397
|
+
emitted.attributes
|
|
398
|
+
);
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
function createSentrySink() {
|
|
402
|
+
return (record) => {
|
|
403
|
+
const emitted = toEmittedLogRecord(record);
|
|
404
|
+
emitSentry(emitted.level, emitted.body, emitted.attributes);
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
function createRecordSink() {
|
|
408
|
+
return (record) => {
|
|
409
|
+
const emitted = toEmittedLogRecord(record);
|
|
410
|
+
for (const sink of logRecordSinks) {
|
|
411
|
+
try {
|
|
412
|
+
sink(emitted);
|
|
413
|
+
} catch {
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
var rootLogger;
|
|
419
|
+
var ownsLogTapeBackend = false;
|
|
420
|
+
var usesDirectEmissionFallback = false;
|
|
421
|
+
function ensureLoggerBackend() {
|
|
422
|
+
if (rootLogger || usesDirectEmissionFallback) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
if (getConfig() !== null) {
|
|
426
|
+
usesDirectEmissionFallback = true;
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
try {
|
|
430
|
+
configureSync({
|
|
431
|
+
sinks: {
|
|
432
|
+
console: createConsoleSink(),
|
|
433
|
+
sentry: createSentrySink(),
|
|
434
|
+
records: createRecordSink()
|
|
435
|
+
},
|
|
436
|
+
loggers: [
|
|
437
|
+
{
|
|
438
|
+
category: [...ROOT_LOGGER_CATEGORY],
|
|
439
|
+
sinks: ["console", "sentry", "records"],
|
|
440
|
+
lowestLevel: "debug"
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
category: ["logtape"],
|
|
444
|
+
sinks: ["console"],
|
|
445
|
+
lowestLevel: "error"
|
|
446
|
+
}
|
|
447
|
+
],
|
|
448
|
+
contextLocalStorage: contextStorage
|
|
449
|
+
});
|
|
450
|
+
ownsLogTapeBackend = true;
|
|
451
|
+
rootLogger = getLogger([...ROOT_LOGGER_CATEGORY]);
|
|
452
|
+
} catch (error) {
|
|
453
|
+
if (error instanceof ConfigError && getConfig() !== null) {
|
|
454
|
+
usesDirectEmissionFallback = true;
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
throw error;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
function getLogTapeLogger(category = []) {
|
|
461
|
+
ensureLoggerBackend();
|
|
462
|
+
if (!rootLogger) {
|
|
463
|
+
throw new Error("LogTape backend is unavailable");
|
|
464
|
+
}
|
|
465
|
+
let logger = rootLogger;
|
|
466
|
+
for (const part of category) {
|
|
467
|
+
logger = logger.getChild(part);
|
|
468
|
+
}
|
|
469
|
+
return logger;
|
|
470
|
+
}
|
|
314
471
|
function emitSentry(level, body, attributes) {
|
|
315
472
|
if (shouldSuppressInfoLog(level)) {
|
|
316
473
|
return;
|
|
@@ -343,11 +500,11 @@ function formatConsoleLevel(level) {
|
|
|
343
500
|
if (level === "warn") return "WRN";
|
|
344
501
|
return "ERR";
|
|
345
502
|
}
|
|
346
|
-
function
|
|
347
|
-
if (level === "error") return
|
|
348
|
-
if (level === "warn") return
|
|
349
|
-
if (level === "info") return
|
|
350
|
-
return
|
|
503
|
+
function consoleLevelStyle(level) {
|
|
504
|
+
if (level === "error") return "red";
|
|
505
|
+
if (level === "warn") return "yellow";
|
|
506
|
+
if (level === "info") return "green";
|
|
507
|
+
return "blue";
|
|
351
508
|
}
|
|
352
509
|
function quoteConsoleValue(value) {
|
|
353
510
|
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
@@ -412,6 +569,119 @@ function summarizeConsoleString(value, maxChars) {
|
|
|
412
569
|
}
|
|
413
570
|
return `${collapsed.slice(0, maxChars)}... [${collapsed.length} chars]`;
|
|
414
571
|
}
|
|
572
|
+
function abbreviateConsoleId(value) {
|
|
573
|
+
if (value.length <= 20) {
|
|
574
|
+
return value;
|
|
575
|
+
}
|
|
576
|
+
return `${value.slice(0, 12)}...${value.slice(-4)}`;
|
|
577
|
+
}
|
|
578
|
+
function toRelativeConsolePath(value) {
|
|
579
|
+
const normalized = value.trim();
|
|
580
|
+
if (!normalized) {
|
|
581
|
+
return normalized;
|
|
582
|
+
}
|
|
583
|
+
try {
|
|
584
|
+
const relative = path.relative(process.cwd(), normalized);
|
|
585
|
+
if (relative.length > 0 && !relative.startsWith("..") && !path.isAbsolute(relative)) {
|
|
586
|
+
return relative;
|
|
587
|
+
}
|
|
588
|
+
} catch {
|
|
589
|
+
}
|
|
590
|
+
return normalized;
|
|
591
|
+
}
|
|
592
|
+
function pushPrettyConsoleToken(tokens, token) {
|
|
593
|
+
if (!token || tokens.includes(token)) {
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
tokens.push(token);
|
|
597
|
+
}
|
|
598
|
+
function numericConsoleToken(label, value) {
|
|
599
|
+
return typeof value === "number" ? `${label}=${value}` : void 0;
|
|
600
|
+
}
|
|
601
|
+
function booleanConsoleToken(label, value) {
|
|
602
|
+
return typeof value === "boolean" ? `${label}=${value ? "yes" : "no"}` : void 0;
|
|
603
|
+
}
|
|
604
|
+
function shouldShowPrettyCorrelation(eventName) {
|
|
605
|
+
return !(eventName === "plugin_loaded" || eventName === "startup_discovery_summary" || eventName === "capability_catalog_loaded" || eventName.endsWith("_loaded"));
|
|
606
|
+
}
|
|
607
|
+
function getPrettyConsoleSummaryTokens(level, eventName, attributes) {
|
|
608
|
+
const tokens = [];
|
|
609
|
+
pushPrettyConsoleToken(
|
|
610
|
+
tokens,
|
|
611
|
+
toOptionalString(attributes["app.log.source"]) ?? void 0
|
|
612
|
+
);
|
|
613
|
+
pushPrettyConsoleToken(
|
|
614
|
+
tokens,
|
|
615
|
+
toOptionalString(attributes["app.plugin.name"]) ?? void 0
|
|
616
|
+
);
|
|
617
|
+
pushPrettyConsoleToken(
|
|
618
|
+
tokens,
|
|
619
|
+
numericConsoleToken("caps", attributes["app.plugin.capability_count"])
|
|
620
|
+
);
|
|
621
|
+
pushPrettyConsoleToken(
|
|
622
|
+
tokens,
|
|
623
|
+
numericConsoleToken("config", attributes["app.plugin.config_key_count"])
|
|
624
|
+
);
|
|
625
|
+
pushPrettyConsoleToken(
|
|
626
|
+
tokens,
|
|
627
|
+
booleanConsoleToken("mcp", attributes["app.plugin.has_mcp"])
|
|
628
|
+
);
|
|
629
|
+
pushPrettyConsoleToken(
|
|
630
|
+
tokens,
|
|
631
|
+
numericConsoleToken("plugins", attributes["app.plugin.count"])
|
|
632
|
+
);
|
|
633
|
+
pushPrettyConsoleToken(
|
|
634
|
+
tokens,
|
|
635
|
+
numericConsoleToken("skills", attributes["app.skill.count"])
|
|
636
|
+
);
|
|
637
|
+
pushPrettyConsoleToken(
|
|
638
|
+
tokens,
|
|
639
|
+
numericConsoleToken("capabilities", attributes["app.capability.count"])
|
|
640
|
+
);
|
|
641
|
+
pushPrettyConsoleToken(
|
|
642
|
+
tokens,
|
|
643
|
+
numericConsoleToken("config", attributes["app.config.key_count"])
|
|
644
|
+
);
|
|
645
|
+
pushPrettyConsoleToken(
|
|
646
|
+
tokens,
|
|
647
|
+
numericConsoleToken("chars", attributes["app.message.length"])
|
|
648
|
+
);
|
|
649
|
+
pushPrettyConsoleToken(
|
|
650
|
+
tokens,
|
|
651
|
+
numericConsoleToken(
|
|
652
|
+
"attachments",
|
|
653
|
+
attributes["app.message.attachment_count"]
|
|
654
|
+
)
|
|
655
|
+
);
|
|
656
|
+
const filePath = toOptionalString(attributes["file.path"]);
|
|
657
|
+
if (filePath && eventName.endsWith("_loaded")) {
|
|
658
|
+
pushPrettyConsoleToken(tokens, toRelativeConsolePath(filePath));
|
|
659
|
+
}
|
|
660
|
+
if (shouldShowPrettyCorrelation(eventName)) {
|
|
661
|
+
const conversationId = toOptionalString(
|
|
662
|
+
attributes["gen_ai.conversation.id"]
|
|
663
|
+
);
|
|
664
|
+
const turnId = toOptionalString(attributes["app.turn.id"]);
|
|
665
|
+
const messageId = toOptionalString(attributes["messaging.message.id"]);
|
|
666
|
+
if (conversationId) {
|
|
667
|
+
pushPrettyConsoleToken(
|
|
668
|
+
tokens,
|
|
669
|
+
`conv=${abbreviateConsoleId(conversationId)}`
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
if (turnId) {
|
|
673
|
+
pushPrettyConsoleToken(tokens, `turn=${abbreviateConsoleId(turnId)}`);
|
|
674
|
+
}
|
|
675
|
+
if (messageId) {
|
|
676
|
+
pushPrettyConsoleToken(tokens, `msg=${abbreviateConsoleId(messageId)}`);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
const model = toOptionalString(attributes["gen_ai.request.model"]);
|
|
680
|
+
if (model && shouldShowConsoleModel(level, eventName)) {
|
|
681
|
+
pushPrettyConsoleToken(tokens, `model=${model}`);
|
|
682
|
+
}
|
|
683
|
+
return tokens;
|
|
684
|
+
}
|
|
415
685
|
function projectConsoleValue(level, key, value) {
|
|
416
686
|
if ((level === "debug" || level === "info") && CONSOLE_PREVIEW_KEYS.has(key) && typeof value === "string") {
|
|
417
687
|
return summarizeConsoleString(
|
|
@@ -435,12 +705,25 @@ function projectConsoleAttributes(level, eventName, attributes) {
|
|
|
435
705
|
return projected;
|
|
436
706
|
}
|
|
437
707
|
function formatConsoleLine(level, eventName, body, attributes) {
|
|
438
|
-
const timestamp =
|
|
439
|
-
const useColor =
|
|
440
|
-
const
|
|
441
|
-
const colorize = (text,
|
|
708
|
+
const timestamp = /* @__PURE__ */ new Date();
|
|
709
|
+
const useColor = shouldUseConsoleColor();
|
|
710
|
+
const levelStyle = consoleLevelStyle(level);
|
|
711
|
+
const colorize = (text, style) => useColor ? styleText(style, text) : text;
|
|
712
|
+
if (shouldUsePrettyConsole(level)) {
|
|
713
|
+
const summaryTokens = getPrettyConsoleSummaryTokens(
|
|
714
|
+
level,
|
|
715
|
+
eventName,
|
|
716
|
+
attributes
|
|
717
|
+
);
|
|
718
|
+
const summary = [body, ...summaryTokens].join(" ");
|
|
719
|
+
return [
|
|
720
|
+
colorize(formatConsoleTimestamp(timestamp), "gray"),
|
|
721
|
+
colorize(formatConsoleLevel(level), levelStyle),
|
|
722
|
+
summary
|
|
723
|
+
].join(" ");
|
|
724
|
+
}
|
|
442
725
|
const parts = [
|
|
443
|
-
`${colorize(timestamp,
|
|
726
|
+
`${colorize(formatConsoleTimestamp(timestamp), "gray")} ${colorize(formatConsoleLevel(level), levelStyle)} ${body}`
|
|
444
727
|
];
|
|
445
728
|
const projectedAttributes = projectConsoleAttributes(
|
|
446
729
|
level,
|
|
@@ -460,7 +743,7 @@ function formatConsoleLine(level, eventName, body, attributes) {
|
|
|
460
743
|
}
|
|
461
744
|
);
|
|
462
745
|
for (const [key, value] of sortedAttributes) {
|
|
463
|
-
const rendered = `${colorize(key,
|
|
746
|
+
const rendered = `${colorize(key, "cyan")}=${colorize(formatConsoleValue(value), "dim")}`;
|
|
464
747
|
parts.push(rendered);
|
|
465
748
|
}
|
|
466
749
|
return parts.join(" ");
|
|
@@ -484,28 +767,58 @@ function emitConsole(level, eventName, body, attributes) {
|
|
|
484
767
|
}
|
|
485
768
|
console.debug(line);
|
|
486
769
|
}
|
|
487
|
-
function
|
|
488
|
-
const contextAttributes = contextStorage.getStore() ?? {};
|
|
489
|
-
const traceAttributes = getTraceCorrelationAttributes();
|
|
490
|
-
const normalizedEventName = toSnakeCase(eventName);
|
|
491
|
-
const message = body ? redactSecrets(body) : normalizedEventName;
|
|
492
|
-
const attributes = mergeAttributes(contextAttributes, traceAttributes, {
|
|
493
|
-
"event.name": normalizedEventName,
|
|
494
|
-
...attrs
|
|
495
|
-
});
|
|
770
|
+
function emitDirect(level, eventName, body, attributes) {
|
|
496
771
|
for (const sink of logRecordSinks) {
|
|
497
772
|
try {
|
|
498
773
|
sink({
|
|
499
774
|
level,
|
|
500
|
-
eventName
|
|
501
|
-
body
|
|
775
|
+
eventName,
|
|
776
|
+
body,
|
|
502
777
|
attributes
|
|
503
778
|
});
|
|
504
779
|
} catch {
|
|
505
780
|
}
|
|
506
781
|
}
|
|
507
|
-
emitConsole(level,
|
|
508
|
-
emitSentry(level,
|
|
782
|
+
emitConsole(level, eventName, body, attributes);
|
|
783
|
+
emitSentry(level, body, attributes);
|
|
784
|
+
}
|
|
785
|
+
function emitRecord(category, level, eventName, attrs = {}, body) {
|
|
786
|
+
ensureLoggerBackend();
|
|
787
|
+
const traceAttributes = getTraceCorrelationAttributes();
|
|
788
|
+
const normalizedEventName = toSnakeCase(eventName);
|
|
789
|
+
const message = body ? redactSecrets(body) : normalizedEventName;
|
|
790
|
+
const source = getLogSource([...ROOT_LOGGER_CATEGORY, ...category]);
|
|
791
|
+
const contextAttributes = ownsLogTapeBackend ? void 0 : contextStorage.getStore();
|
|
792
|
+
const attributes = mergeAttributes(contextAttributes, traceAttributes, {
|
|
793
|
+
"event.name": normalizedEventName,
|
|
794
|
+
...source ? { "app.log.source": source } : {},
|
|
795
|
+
...attrs
|
|
796
|
+
});
|
|
797
|
+
if (usesDirectEmissionFallback) {
|
|
798
|
+
emitDirect(level, normalizedEventName, message, attributes);
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
const logger = getLogTapeLogger(category);
|
|
802
|
+
const properties = {
|
|
803
|
+
[LOGTAPE_BODY_KEY]: message,
|
|
804
|
+
...attributes
|
|
805
|
+
};
|
|
806
|
+
if (level === "error") {
|
|
807
|
+
logger.error(`{${LOGTAPE_BODY_KEY}}`, properties);
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
if (level === "warn") {
|
|
811
|
+
logger.warn(`{${LOGTAPE_BODY_KEY}}`, properties);
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
if (level === "info") {
|
|
815
|
+
logger.info(`{${LOGTAPE_BODY_KEY}}`, properties);
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
logger.debug(`{${LOGTAPE_BODY_KEY}}`, properties);
|
|
819
|
+
}
|
|
820
|
+
function emit(level, eventName, attrs = {}, body) {
|
|
821
|
+
emitRecord([], level, eventName, attrs, body);
|
|
509
822
|
}
|
|
510
823
|
var log = {
|
|
511
824
|
debug(eventName, attrs = {}, body) {
|
|
@@ -555,6 +868,83 @@ var log = {
|
|
|
555
868
|
return eventId;
|
|
556
869
|
}
|
|
557
870
|
};
|
|
871
|
+
var CHAT_SDK_LEVEL_PRIORITY = {
|
|
872
|
+
debug: 10,
|
|
873
|
+
info: 20,
|
|
874
|
+
warn: 30,
|
|
875
|
+
error: 40
|
|
876
|
+
};
|
|
877
|
+
function resolveChatSdkLogLevel() {
|
|
878
|
+
if (isDevelopmentLoggingMode()) {
|
|
879
|
+
return "warn";
|
|
880
|
+
}
|
|
881
|
+
return "info";
|
|
882
|
+
}
|
|
883
|
+
function shouldEmitChatSdkLevel(level, minimumLevel) {
|
|
884
|
+
if (minimumLevel === "silent") {
|
|
885
|
+
return false;
|
|
886
|
+
}
|
|
887
|
+
return CHAT_SDK_LEVEL_PRIORITY[level] >= CHAT_SDK_LEVEL_PRIORITY[minimumLevel];
|
|
888
|
+
}
|
|
889
|
+
function renderChatSdkArgument(value) {
|
|
890
|
+
if (value === null || value === void 0) {
|
|
891
|
+
return "";
|
|
892
|
+
}
|
|
893
|
+
if (typeof value === "string") {
|
|
894
|
+
return value;
|
|
895
|
+
}
|
|
896
|
+
if (value instanceof Error) {
|
|
897
|
+
return value.message;
|
|
898
|
+
}
|
|
899
|
+
try {
|
|
900
|
+
return JSON.stringify(value);
|
|
901
|
+
} catch {
|
|
902
|
+
return String(value);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
function formatChatSdkBody(message, args) {
|
|
906
|
+
const renderedArgs = args.map((arg) => renderChatSdkArgument(arg).trim()).filter((arg) => arg.length > 0);
|
|
907
|
+
if (renderedArgs.length === 0) {
|
|
908
|
+
return message;
|
|
909
|
+
}
|
|
910
|
+
return `${message} ${renderedArgs.join(" ")}`;
|
|
911
|
+
}
|
|
912
|
+
function createChatSdkLoggerImpl(category, minimumLevel) {
|
|
913
|
+
const emitChatSdkLog = (level, message, args) => {
|
|
914
|
+
if (!shouldEmitChatSdkLevel(level, minimumLevel)) {
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
emitRecord(
|
|
918
|
+
category,
|
|
919
|
+
level === "warn" ? "warn" : level,
|
|
920
|
+
level === "error" ? "chat_sdk_error" : level === "warn" ? "chat_sdk_warning" : "chat_sdk_log",
|
|
921
|
+
args.length > 0 ? {
|
|
922
|
+
"app.log.args": args.length === 1 ? args[0] : args
|
|
923
|
+
} : {},
|
|
924
|
+
formatChatSdkBody(message, args)
|
|
925
|
+
);
|
|
926
|
+
};
|
|
927
|
+
return {
|
|
928
|
+
child(prefix) {
|
|
929
|
+
return createChatSdkLoggerImpl([...category, prefix], minimumLevel);
|
|
930
|
+
},
|
|
931
|
+
debug(message, ...args) {
|
|
932
|
+
emitChatSdkLog("debug", message, args);
|
|
933
|
+
},
|
|
934
|
+
info(message, ...args) {
|
|
935
|
+
emitChatSdkLog("info", message, args);
|
|
936
|
+
},
|
|
937
|
+
warn(message, ...args) {
|
|
938
|
+
emitChatSdkLog("warn", message, args);
|
|
939
|
+
},
|
|
940
|
+
error(message, ...args) {
|
|
941
|
+
emitChatSdkLog("error", message, args);
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
function createChatSdkLogger() {
|
|
946
|
+
return createChatSdkLoggerImpl(["chat-sdk"], resolveChatSdkLogLevel());
|
|
947
|
+
}
|
|
558
948
|
function withLogContext(context, callback) {
|
|
559
949
|
const next = mergeAttributes(
|
|
560
950
|
contextStorage.getStore(),
|
|
@@ -871,6 +1261,7 @@ import { parse as parseYaml } from "yaml";
|
|
|
871
1261
|
var PLUGIN_NAME_RE = /^[a-z][a-z0-9-]*$/;
|
|
872
1262
|
var SHORT_CAPABILITY_RE = /^[a-z0-9-]+(\.[a-z0-9-]+)*$/;
|
|
873
1263
|
var SHORT_CONFIG_KEY_RE = /^[a-z0-9]+(\.[a-z0-9-]+)*$/;
|
|
1264
|
+
var TARGET_FLAG_RE = /^-{1,2}[A-Za-z0-9][A-Za-z0-9-]*$/;
|
|
874
1265
|
var AUTH_TOKEN_ENV_RE = /^[A-Z][A-Z0-9_]*$/;
|
|
875
1266
|
var API_DOMAIN_RE = /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
876
1267
|
var RUNTIME_POSTINSTALL_CMD_RE = /^[A-Za-z0-9._/-]+$/;
|
|
@@ -1036,16 +1427,17 @@ var oauthSourceSchema = z.object({
|
|
|
1036
1427
|
var mcpSourceSchema = z.object({
|
|
1037
1428
|
transport: nonEmptyTrimmedString.refine((value) => value === "http", {
|
|
1038
1429
|
error: 'must be "http"'
|
|
1039
|
-
}),
|
|
1430
|
+
}).optional(),
|
|
1040
1431
|
url: httpsUrlString,
|
|
1041
1432
|
headers: stringMapSchema.optional(),
|
|
1042
1433
|
"allowed-tools": nonEmptyStringArraySchema("allowed-tools").optional()
|
|
1043
1434
|
}).passthrough();
|
|
1044
1435
|
var targetSourceSchema = z.object({
|
|
1045
|
-
type:
|
|
1046
|
-
error:
|
|
1436
|
+
type: nonEmptyTrimmedString.refine((value) => PLUGIN_NAME_RE.test(value), {
|
|
1437
|
+
error: "type must be a lowercase target identifier"
|
|
1047
1438
|
}),
|
|
1048
|
-
"config-key": nonEmptyTrimmedString
|
|
1439
|
+
"config-key": nonEmptyTrimmedString,
|
|
1440
|
+
"command-flags": nonEmptyStringArraySchema("command-flags").optional()
|
|
1049
1441
|
}).passthrough();
|
|
1050
1442
|
var manifestSourceSchema = z.object({
|
|
1051
1443
|
name: z.string().refine((value) => PLUGIN_NAME_RE.test(value), {
|
|
@@ -1077,8 +1469,8 @@ var manifestSourceSchema = z.object({
|
|
|
1077
1469
|
error: "must be an object"
|
|
1078
1470
|
}).optional()
|
|
1079
1471
|
}).passthrough();
|
|
1080
|
-
function formatPath(
|
|
1081
|
-
return
|
|
1472
|
+
function formatPath(path3) {
|
|
1473
|
+
return path3.map((segment) => String(segment)).join(".");
|
|
1082
1474
|
}
|
|
1083
1475
|
function issueMessage(error, prefix) {
|
|
1084
1476
|
const issue = error.issues[0];
|
|
@@ -1305,51 +1697,51 @@ function parsePluginManifest(raw, dir) {
|
|
|
1305
1697
|
const sourceResult = manifestSourceSchema.safeParse(parsedYaml);
|
|
1306
1698
|
if (!sourceResult.success) {
|
|
1307
1699
|
const issue = sourceResult.error.issues[0];
|
|
1308
|
-
const
|
|
1309
|
-
if (
|
|
1700
|
+
const path3 = formatPath(issue?.path ?? []);
|
|
1701
|
+
if (path3 === "name") {
|
|
1310
1702
|
throw new Error(
|
|
1311
1703
|
`Invalid plugin name in ${dir}: "${parsedYaml.name}"`
|
|
1312
1704
|
);
|
|
1313
1705
|
}
|
|
1314
|
-
if (
|
|
1706
|
+
if (path3 === "description") {
|
|
1315
1707
|
throw new Error(`Invalid plugin description in ${dir}`);
|
|
1316
1708
|
}
|
|
1317
|
-
if (
|
|
1709
|
+
if (path3 === "capabilities") {
|
|
1318
1710
|
throw new Error(
|
|
1319
1711
|
`Plugin ${parsedYaml.name ?? "unknown"} capabilities must be an array when provided`
|
|
1320
1712
|
);
|
|
1321
1713
|
}
|
|
1322
|
-
if (
|
|
1714
|
+
if (path3 === "config-keys") {
|
|
1323
1715
|
throw new Error(
|
|
1324
1716
|
`Plugin ${parsedYaml.name ?? "unknown"} config-keys must be an array when provided`
|
|
1325
1717
|
);
|
|
1326
1718
|
}
|
|
1327
|
-
if (
|
|
1719
|
+
if (path3 === "credentials") {
|
|
1328
1720
|
throw new Error(
|
|
1329
1721
|
`Plugin ${parsedYaml.name ?? "unknown"} credentials must be an object when provided`
|
|
1330
1722
|
);
|
|
1331
1723
|
}
|
|
1332
|
-
if (
|
|
1724
|
+
if (path3 === "runtime-dependencies") {
|
|
1333
1725
|
throw new Error(
|
|
1334
1726
|
`Plugin ${parsedYaml.name ?? "unknown"} runtime-dependencies must be an array`
|
|
1335
1727
|
);
|
|
1336
1728
|
}
|
|
1337
|
-
if (
|
|
1729
|
+
if (path3 === "runtime-postinstall") {
|
|
1338
1730
|
throw new Error(
|
|
1339
1731
|
`Plugin ${parsedYaml.name ?? "unknown"} runtime-postinstall must be an array`
|
|
1340
1732
|
);
|
|
1341
1733
|
}
|
|
1342
|
-
if (
|
|
1734
|
+
if (path3 === "mcp") {
|
|
1343
1735
|
throw new Error(
|
|
1344
1736
|
`Plugin ${parsedYaml.name ?? "unknown"} mcp must be an object`
|
|
1345
1737
|
);
|
|
1346
1738
|
}
|
|
1347
|
-
if (
|
|
1739
|
+
if (path3 === "oauth") {
|
|
1348
1740
|
throw new Error(
|
|
1349
1741
|
`Plugin ${parsedYaml.name ?? "unknown"} oauth must be an object`
|
|
1350
1742
|
);
|
|
1351
1743
|
}
|
|
1352
|
-
if (
|
|
1744
|
+
if (path3 === "target") {
|
|
1353
1745
|
throw new Error(
|
|
1354
1746
|
`Plugin ${parsedYaml.name ?? "unknown"} target must be an object`
|
|
1355
1747
|
);
|
|
@@ -1439,14 +1831,24 @@ function parsePluginManifest(raw, dir) {
|
|
|
1439
1831
|
`Plugin ${data.name} target.config-key "${result.data["config-key"]}" must be listed in config-keys`
|
|
1440
1832
|
);
|
|
1441
1833
|
}
|
|
1442
|
-
|
|
1834
|
+
const commandFlags = result.data["command-flags"];
|
|
1835
|
+
if (commandFlags && commandFlags.some((flag) => !TARGET_FLAG_RE.test(flag))) {
|
|
1836
|
+
throw new Error(
|
|
1837
|
+
`Plugin ${data.name} target.command-flags must contain CLI flags like --repo or -R`
|
|
1838
|
+
);
|
|
1839
|
+
}
|
|
1840
|
+
manifest.target = {
|
|
1841
|
+
type: result.data.type,
|
|
1842
|
+
configKey: qualifiedKey,
|
|
1843
|
+
...commandFlags ? { commandFlags } : {}
|
|
1844
|
+
};
|
|
1443
1845
|
}
|
|
1444
1846
|
return manifest;
|
|
1445
1847
|
}
|
|
1446
1848
|
|
|
1447
1849
|
// src/chat/plugins/registry.ts
|
|
1448
1850
|
import { readFileSync, readdirSync, statSync } from "fs";
|
|
1449
|
-
import
|
|
1851
|
+
import path2 from "path";
|
|
1450
1852
|
|
|
1451
1853
|
// src/chat/plugins/auth/github-app-broker.ts
|
|
1452
1854
|
import { createPrivateKey, createSign, randomUUID } from "crypto";
|
|
@@ -1462,13 +1864,26 @@ function resolveAuthTokenPlaceholder(credentials) {
|
|
|
1462
1864
|
|
|
1463
1865
|
// src/chat/plugins/auth/github-app-broker.ts
|
|
1464
1866
|
var MAX_LEASE_MS = 60 * 60 * 1e3;
|
|
1465
|
-
function
|
|
1466
|
-
const
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1867
|
+
function parseRepoTarget(value) {
|
|
1868
|
+
const trimmed = value.trim();
|
|
1869
|
+
if (!trimmed) {
|
|
1870
|
+
return void 0;
|
|
1871
|
+
}
|
|
1872
|
+
const [repoRef] = trimmed.split("#");
|
|
1873
|
+
const [owner, repo, extra] = repoRef.split("/");
|
|
1874
|
+
if (!owner || !repo || extra) {
|
|
1875
|
+
return void 0;
|
|
1470
1876
|
}
|
|
1471
|
-
return
|
|
1877
|
+
return {
|
|
1878
|
+
owner: owner.toLowerCase(),
|
|
1879
|
+
repo: repo.toLowerCase()
|
|
1880
|
+
};
|
|
1881
|
+
}
|
|
1882
|
+
function getRepoTarget(target) {
|
|
1883
|
+
if (!target || target.type !== "repo") {
|
|
1884
|
+
return void 0;
|
|
1885
|
+
}
|
|
1886
|
+
return parseRepoTarget(target.value);
|
|
1472
1887
|
}
|
|
1473
1888
|
function base64Url(input) {
|
|
1474
1889
|
return Buffer.from(input).toString("base64").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
@@ -1527,8 +1942,8 @@ function createAppJwt(appId, privateKeyEnv) {
|
|
|
1527
1942
|
const signature = signer.sign(getPrivateKey(privateKeyEnv)).toString("base64").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
1528
1943
|
return `${signingInput}.${signature}`;
|
|
1529
1944
|
}
|
|
1530
|
-
async function githubRequest(apiBase,
|
|
1531
|
-
const response = await fetch(`${apiBase}${
|
|
1945
|
+
async function githubRequest(apiBase, path3, params) {
|
|
1946
|
+
const response = await fetch(`${apiBase}${path3}`, {
|
|
1532
1947
|
method: params.method ?? "GET",
|
|
1533
1948
|
headers: {
|
|
1534
1949
|
Accept: "application/vnd.github+json",
|
|
@@ -1553,10 +1968,6 @@ async function githubRequest(apiBase, path2, params) {
|
|
|
1553
1968
|
}
|
|
1554
1969
|
return parsed;
|
|
1555
1970
|
}
|
|
1556
|
-
var CAPABILITY_ALIASES = {
|
|
1557
|
-
"issues.comment": { permission: "issues", level: "write" },
|
|
1558
|
-
"labels.write": { permission: "issues", level: "write" }
|
|
1559
|
-
};
|
|
1560
1971
|
var KNOWN_SCOPES = /* @__PURE__ */ new Set([
|
|
1561
1972
|
"actions",
|
|
1562
1973
|
"administration",
|
|
@@ -1585,10 +1996,6 @@ function capabilityToPermissions(capability, pluginName) {
|
|
|
1585
1996
|
throw new Error(`Unsupported GitHub capability: ${capability}`);
|
|
1586
1997
|
}
|
|
1587
1998
|
const suffix = capability.slice(prefix.length);
|
|
1588
|
-
const alias = CAPABILITY_ALIASES[suffix];
|
|
1589
|
-
if (alias) {
|
|
1590
|
-
return { [alias.permission]: alias.level };
|
|
1591
|
-
}
|
|
1592
1999
|
const lastDot = suffix.lastIndexOf(".");
|
|
1593
2000
|
if (lastDot === -1) {
|
|
1594
2001
|
throw new Error(`Unsupported GitHub capability: ${capability}`);
|
|
@@ -1632,6 +2039,17 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
1632
2039
|
return `Bearer ${token}`;
|
|
1633
2040
|
}
|
|
1634
2041
|
const supportedCapabilities = new Set(manifest.capabilities);
|
|
2042
|
+
function resolveInstallationId() {
|
|
2043
|
+
const installationIdRaw = process.env[installationIdEnv]?.trim();
|
|
2044
|
+
if (!installationIdRaw) {
|
|
2045
|
+
throw new Error(`Missing ${installationIdEnv}`);
|
|
2046
|
+
}
|
|
2047
|
+
const installationId = Number(installationIdRaw);
|
|
2048
|
+
if (!Number.isFinite(installationId)) {
|
|
2049
|
+
throw new Error(`Invalid ${installationIdEnv}`);
|
|
2050
|
+
}
|
|
2051
|
+
return installationId;
|
|
2052
|
+
}
|
|
1635
2053
|
return {
|
|
1636
2054
|
async issue(input) {
|
|
1637
2055
|
if (!supportedCapabilities.has(input.capability)) {
|
|
@@ -1640,19 +2058,20 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
1640
2058
|
);
|
|
1641
2059
|
}
|
|
1642
2060
|
const permissions = capabilityToPermissions(input.capability, provider);
|
|
1643
|
-
const
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
2061
|
+
const installationId = resolveInstallationId();
|
|
2062
|
+
let repoTarget;
|
|
2063
|
+
if (input.target) {
|
|
2064
|
+
if (input.target.type !== "repo") {
|
|
2065
|
+
throw new Error(
|
|
2066
|
+
`Unsupported github target type: ${input.target.type}`
|
|
2067
|
+
);
|
|
2068
|
+
}
|
|
2069
|
+
repoTarget = getRepoTarget(input.target);
|
|
2070
|
+
if (!repoTarget) {
|
|
2071
|
+
throw new Error("Invalid github repo target: expected owner/repo");
|
|
2072
|
+
}
|
|
1654
2073
|
}
|
|
1655
|
-
const targetScope =
|
|
2074
|
+
const targetScope = repoTarget ? `${repoTarget.owner}/${repoTarget.repo}` : "all";
|
|
1656
2075
|
const cacheKey = `${installationId}:${input.capability}:${targetScope}`;
|
|
1657
2076
|
const cached = tokenCache.get(cacheKey);
|
|
1658
2077
|
const now = Date.now();
|
|
@@ -1678,14 +2097,17 @@ function createGitHubAppBroker(manifest, credentials) {
|
|
|
1678
2097
|
}
|
|
1679
2098
|
};
|
|
1680
2099
|
}
|
|
1681
|
-
const appJwt = createAppJwt(appId, privateKeyEnv);
|
|
1682
|
-
const repositoryName = input.target?.repo?.trim().toLowerCase();
|
|
1683
2100
|
const tokenRequestBody = {
|
|
1684
2101
|
permissions
|
|
1685
2102
|
};
|
|
1686
|
-
if (
|
|
1687
|
-
tokenRequestBody.repositories = [
|
|
2103
|
+
if (repoTarget) {
|
|
2104
|
+
tokenRequestBody.repositories = [repoTarget.repo];
|
|
1688
2105
|
}
|
|
2106
|
+
const appId = process.env[appIdEnv];
|
|
2107
|
+
if (!appId) {
|
|
2108
|
+
throw new Error(`Missing ${appIdEnv}`);
|
|
2109
|
+
}
|
|
2110
|
+
const appJwt = createAppJwt(appId, privateKeyEnv);
|
|
1689
2111
|
const accessTokenResponse = await githubRequest(apiBase, `/app/installations/${installationId}/access_tokens`, {
|
|
1690
2112
|
method: "POST",
|
|
1691
2113
|
token: appJwt,
|
|
@@ -2034,7 +2456,7 @@ function registerPluginManifest(state, raw, pluginDir) {
|
|
|
2034
2456
|
const definition = {
|
|
2035
2457
|
manifest,
|
|
2036
2458
|
dir: pluginDir,
|
|
2037
|
-
skillsDir:
|
|
2459
|
+
skillsDir: path2.join(pluginDir, "skills")
|
|
2038
2460
|
};
|
|
2039
2461
|
state.pluginDefinitions.push(definition);
|
|
2040
2462
|
state.pluginsByName.set(manifest.name, definition);
|
|
@@ -2049,7 +2471,7 @@ function normalizePluginRoots(roots) {
|
|
|
2049
2471
|
const resolved = [];
|
|
2050
2472
|
const seen = /* @__PURE__ */ new Set();
|
|
2051
2473
|
for (const root of roots) {
|
|
2052
|
-
const normalized =
|
|
2474
|
+
const normalized = path2.resolve(root);
|
|
2053
2475
|
if (seen.has(normalized)) {
|
|
2054
2476
|
continue;
|
|
2055
2477
|
}
|
|
@@ -2076,7 +2498,7 @@ function getExtraPluginRoots() {
|
|
|
2076
2498
|
}
|
|
2077
2499
|
}
|
|
2078
2500
|
return normalizePluginRoots(
|
|
2079
|
-
raw.split(
|
|
2501
|
+
raw.split(path2.delimiter).map((entry) => entry.trim()).filter((entry) => entry.length > 0)
|
|
2080
2502
|
);
|
|
2081
2503
|
}
|
|
2082
2504
|
function getPluginCatalogSource() {
|
|
@@ -2124,7 +2546,7 @@ function buildLoadedPluginState(source) {
|
|
|
2124
2546
|
continue;
|
|
2125
2547
|
}
|
|
2126
2548
|
if (rootStat.isDirectory()) {
|
|
2127
|
-
const manifestPath =
|
|
2549
|
+
const manifestPath = path2.join(pluginsRoot, "plugin.yaml");
|
|
2128
2550
|
let hasRootManifest = false;
|
|
2129
2551
|
try {
|
|
2130
2552
|
hasRootManifest = statSync(manifestPath).isFile();
|
|
@@ -2152,14 +2574,14 @@ function buildLoadedPluginState(source) {
|
|
|
2152
2574
|
continue;
|
|
2153
2575
|
}
|
|
2154
2576
|
for (const entry of entries.sort()) {
|
|
2155
|
-
const pluginDir =
|
|
2577
|
+
const pluginDir = path2.join(pluginsRoot, entry);
|
|
2156
2578
|
try {
|
|
2157
2579
|
const stat = statSync(pluginDir);
|
|
2158
2580
|
if (!stat.isDirectory()) continue;
|
|
2159
2581
|
} catch {
|
|
2160
2582
|
continue;
|
|
2161
2583
|
}
|
|
2162
|
-
const manifestPath =
|
|
2584
|
+
const manifestPath = path2.join(pluginDir, "plugin.yaml");
|
|
2163
2585
|
let raw;
|
|
2164
2586
|
try {
|
|
2165
2587
|
raw = readFileSync(manifestPath, "utf8");
|
|
@@ -2214,7 +2636,12 @@ function getPluginCapabilityProviders() {
|
|
|
2214
2636
|
provider: plugin.manifest.name,
|
|
2215
2637
|
capabilities: [...plugin.manifest.capabilities],
|
|
2216
2638
|
configKeys: [...plugin.manifest.configKeys],
|
|
2217
|
-
...plugin.manifest.target ? {
|
|
2639
|
+
...plugin.manifest.target ? {
|
|
2640
|
+
target: {
|
|
2641
|
+
...plugin.manifest.target,
|
|
2642
|
+
...plugin.manifest.target.commandFlags ? { commandFlags: [...plugin.manifest.target.commandFlags] } : {}
|
|
2643
|
+
}
|
|
2644
|
+
} : {}
|
|
2218
2645
|
}));
|
|
2219
2646
|
}
|
|
2220
2647
|
function getPluginProviders() {
|
|
@@ -2295,10 +2722,10 @@ function getPluginSkillRoots() {
|
|
|
2295
2722
|
}
|
|
2296
2723
|
function getPluginForSkillPath(skillPath) {
|
|
2297
2724
|
const state = ensurePluginsLoaded();
|
|
2298
|
-
const resolvedSkillPath =
|
|
2725
|
+
const resolvedSkillPath = path2.resolve(skillPath);
|
|
2299
2726
|
return state.pluginDefinitions.find((plugin) => {
|
|
2300
|
-
const resolvedSkillsDir =
|
|
2301
|
-
return resolvedSkillPath === resolvedSkillsDir || resolvedSkillPath.startsWith(`${resolvedSkillsDir}${
|
|
2727
|
+
const resolvedSkillsDir = path2.resolve(plugin.skillsDir);
|
|
2728
|
+
return resolvedSkillPath === resolvedSkillsDir || resolvedSkillPath.startsWith(`${resolvedSkillsDir}${path2.sep}`);
|
|
2302
2729
|
});
|
|
2303
2730
|
}
|
|
2304
2731
|
function getPluginDefinition(provider) {
|
|
@@ -2336,6 +2763,7 @@ export {
|
|
|
2336
2763
|
toOptionalString,
|
|
2337
2764
|
toOptionalNumber,
|
|
2338
2765
|
isRecord,
|
|
2766
|
+
createChatSdkLogger,
|
|
2339
2767
|
logInfo,
|
|
2340
2768
|
logWarn,
|
|
2341
2769
|
logError,
|