sidekick-docker 0.2.4 → 0.2.6
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/sidekick-docker.mjs +223 -80
- package/package.json +1 -1
package/dist/sidekick-docker.mjs
CHANGED
|
@@ -55711,7 +55711,7 @@ var require_DockerClient = __commonJS({
|
|
|
55711
55711
|
const validated = schemas_1.ContainerInspectEnvSchema.parse(info);
|
|
55712
55712
|
return validated.Config.Env ?? [];
|
|
55713
55713
|
}
|
|
55714
|
-
async *streamLogs(id, opts = {}) {
|
|
55714
|
+
async *streamLogs(id, opts = {}, signal) {
|
|
55715
55715
|
const container = this.docker.getContainer(id);
|
|
55716
55716
|
const logOpts = {
|
|
55717
55717
|
follow: true,
|
|
@@ -55732,32 +55732,42 @@ var require_DockerClient = __commonJS({
|
|
|
55732
55732
|
return;
|
|
55733
55733
|
}
|
|
55734
55734
|
const readable = stream;
|
|
55735
|
+
const destroy = () => readable.destroy?.();
|
|
55736
|
+
if (signal) {
|
|
55737
|
+
signal.addEventListener("abort", destroy, { once: true });
|
|
55738
|
+
}
|
|
55735
55739
|
const buffer = [];
|
|
55736
|
-
|
|
55737
|
-
|
|
55738
|
-
|
|
55739
|
-
const combined = Buffer.concat(buffer);
|
|
55740
|
-
buffer.length = 0;
|
|
55741
|
-
let offset = 0;
|
|
55742
|
-
while (offset + 8 <= combined.length) {
|
|
55743
|
-
const streamType = combined[offset];
|
|
55744
|
-
const size = combined.readUInt32BE(offset + 4);
|
|
55745
|
-
if (offset + 8 + size > combined.length) {
|
|
55746
|
-
buffer.push(combined.subarray(offset));
|
|
55740
|
+
try {
|
|
55741
|
+
for await (const chunk of readable) {
|
|
55742
|
+
if (signal?.aborted)
|
|
55747
55743
|
break;
|
|
55748
|
-
|
|
55749
|
-
|
|
55750
|
-
const
|
|
55751
|
-
|
|
55752
|
-
|
|
55753
|
-
|
|
55744
|
+
const data = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
55745
|
+
buffer.push(data);
|
|
55746
|
+
const combined = Buffer.concat(buffer);
|
|
55747
|
+
buffer.length = 0;
|
|
55748
|
+
let offset = 0;
|
|
55749
|
+
while (offset + 8 <= combined.length) {
|
|
55750
|
+
const streamType = combined[offset];
|
|
55751
|
+
const size = combined.readUInt32BE(offset + 4);
|
|
55752
|
+
if (offset + 8 + size > combined.length) {
|
|
55753
|
+
buffer.push(Buffer.from(combined.subarray(offset)));
|
|
55754
|
+
break;
|
|
55755
|
+
}
|
|
55756
|
+
const payload = combined.subarray(offset + 8, offset + 8 + size).toString("utf8");
|
|
55757
|
+
const streamName = streamType === 2 ? "stderr" : "stdout";
|
|
55758
|
+
for (const line of payload.split("\n")) {
|
|
55759
|
+
if (line.trim()) {
|
|
55760
|
+
yield parseLogLine(line, streamName);
|
|
55761
|
+
}
|
|
55754
55762
|
}
|
|
55763
|
+
offset += 8 + size;
|
|
55764
|
+
}
|
|
55765
|
+
if (offset < combined.length && buffer.length === 0) {
|
|
55766
|
+
buffer.push(Buffer.from(combined.subarray(offset)));
|
|
55755
55767
|
}
|
|
55756
|
-
offset += 8 + size;
|
|
55757
|
-
}
|
|
55758
|
-
if (offset < combined.length && buffer.length === 0) {
|
|
55759
|
-
buffer.push(combined.subarray(offset));
|
|
55760
55768
|
}
|
|
55769
|
+
} finally {
|
|
55770
|
+
destroy();
|
|
55761
55771
|
}
|
|
55762
55772
|
}
|
|
55763
55773
|
parseStats(validated, prevCpu, prevSystem) {
|
|
@@ -55813,7 +55823,7 @@ var require_DockerClient = __commonJS({
|
|
|
55813
55823
|
systemTotal: systemUsage
|
|
55814
55824
|
};
|
|
55815
55825
|
}
|
|
55816
|
-
async *streamStats(id) {
|
|
55826
|
+
async *streamStats(id, signal) {
|
|
55817
55827
|
const container = this.docker.getContainer(id);
|
|
55818
55828
|
let prevCpu = 0;
|
|
55819
55829
|
let prevSystem = 0;
|
|
@@ -55826,21 +55836,33 @@ var require_DockerClient = __commonJS({
|
|
|
55826
55836
|
yield first;
|
|
55827
55837
|
} catch {
|
|
55828
55838
|
}
|
|
55839
|
+
if (signal?.aborted)
|
|
55840
|
+
return;
|
|
55829
55841
|
const stream = await container.stats({ stream: true });
|
|
55830
|
-
|
|
55831
|
-
|
|
55832
|
-
|
|
55833
|
-
|
|
55834
|
-
|
|
55835
|
-
|
|
55836
|
-
|
|
55837
|
-
|
|
55838
|
-
|
|
55839
|
-
|
|
55840
|
-
|
|
55841
|
-
|
|
55842
|
+
const destroy = () => stream.destroy?.();
|
|
55843
|
+
if (signal) {
|
|
55844
|
+
signal.addEventListener("abort", destroy, { once: true });
|
|
55845
|
+
}
|
|
55846
|
+
try {
|
|
55847
|
+
for await (const chunk of stream) {
|
|
55848
|
+
if (signal?.aborted)
|
|
55849
|
+
break;
|
|
55850
|
+
const lines = chunk.toString("utf8").split("\n").filter(Boolean);
|
|
55851
|
+
for (const line of lines) {
|
|
55852
|
+
try {
|
|
55853
|
+
const raw = JSON.parse(line);
|
|
55854
|
+
const validated = schemas_1.DockerStatsRawSchema.parse(raw);
|
|
55855
|
+
const { stats, cpuTotal, systemTotal } = this.parseStats(validated, prevCpu, prevSystem);
|
|
55856
|
+
prevCpu = cpuTotal;
|
|
55857
|
+
prevSystem = systemTotal;
|
|
55858
|
+
yield stats;
|
|
55859
|
+
} catch {
|
|
55860
|
+
continue;
|
|
55861
|
+
}
|
|
55842
55862
|
}
|
|
55843
55863
|
}
|
|
55864
|
+
} finally {
|
|
55865
|
+
destroy();
|
|
55844
55866
|
}
|
|
55845
55867
|
}
|
|
55846
55868
|
async listImages(all = false) {
|
|
@@ -56140,7 +56162,7 @@ var require_ComposeClient = __commonJS({
|
|
|
56140
56162
|
async ps(project) {
|
|
56141
56163
|
return this.exec(["-p", project, "ps", "--format", "json"]);
|
|
56142
56164
|
}
|
|
56143
|
-
async *streamLogs(project, service, tail = 100) {
|
|
56165
|
+
async *streamLogs(project, service, tail = 100, signal) {
|
|
56144
56166
|
const args = ["-p", project, "logs", "--follow", "--tail", String(tail), "--timestamps"];
|
|
56145
56167
|
if (service)
|
|
56146
56168
|
args.push(service);
|
|
@@ -56173,12 +56195,23 @@ var require_ComposeClient = __commonJS({
|
|
|
56173
56195
|
let stdoutBuffer = "";
|
|
56174
56196
|
let stderrBuffer = "";
|
|
56175
56197
|
let done = false;
|
|
56198
|
+
const MAX_QUEUE = 1e3;
|
|
56176
56199
|
const entries = [];
|
|
56177
56200
|
let resolve = null;
|
|
56178
56201
|
const push = (entry) => {
|
|
56179
56202
|
entries.push(entry);
|
|
56203
|
+
if (entries.length > MAX_QUEUE)
|
|
56204
|
+
entries.shift();
|
|
56180
56205
|
resolve?.();
|
|
56181
56206
|
};
|
|
56207
|
+
const kill = () => {
|
|
56208
|
+
done = true;
|
|
56209
|
+
resolve?.();
|
|
56210
|
+
proc.kill();
|
|
56211
|
+
};
|
|
56212
|
+
if (signal) {
|
|
56213
|
+
signal.addEventListener("abort", kill, { once: true });
|
|
56214
|
+
}
|
|
56182
56215
|
proc.stdout.on("data", (data) => {
|
|
56183
56216
|
stdoutBuffer += data.toString();
|
|
56184
56217
|
const lines = stdoutBuffer.split("\n");
|
|
@@ -56220,6 +56253,9 @@ var require_ComposeClient = __commonJS({
|
|
|
56220
56253
|
}
|
|
56221
56254
|
}
|
|
56222
56255
|
} finally {
|
|
56256
|
+
proc.stdout.removeAllListeners();
|
|
56257
|
+
proc.stderr.removeAllListeners();
|
|
56258
|
+
proc.removeAllListeners();
|
|
56223
56259
|
proc.kill();
|
|
56224
56260
|
}
|
|
56225
56261
|
}
|
|
@@ -56399,6 +56435,14 @@ var require_StatsCollector = __commonJS({
|
|
|
56399
56435
|
remove(containerId) {
|
|
56400
56436
|
this.histories.delete(containerId);
|
|
56401
56437
|
}
|
|
56438
|
+
/** Remove history entries for containers not in the active set. */
|
|
56439
|
+
prune(activeContainerIds) {
|
|
56440
|
+
for (const id of this.histories.keys()) {
|
|
56441
|
+
if (!activeContainerIds.has(id)) {
|
|
56442
|
+
this.histories.delete(id);
|
|
56443
|
+
}
|
|
56444
|
+
}
|
|
56445
|
+
}
|
|
56402
56446
|
clear() {
|
|
56403
56447
|
this.histories.clear();
|
|
56404
56448
|
}
|
|
@@ -56801,10 +56845,17 @@ var require_LogTemplateEngine = __commonJS({
|
|
|
56801
56845
|
function isVariable(token) {
|
|
56802
56846
|
return VARIABLE_PATTERNS.some((p) => p.test(token));
|
|
56803
56847
|
}
|
|
56848
|
+
var DEFAULT_MAX_GROUPS = 500;
|
|
56804
56849
|
var LogTemplateEngine2 = class {
|
|
56805
56850
|
// Group templates by token count for efficient lookup
|
|
56806
56851
|
groups = /* @__PURE__ */ new Map();
|
|
56807
56852
|
totalLines = 0;
|
|
56853
|
+
groupCount = 0;
|
|
56854
|
+
droppedGroups = 0;
|
|
56855
|
+
maxGroups;
|
|
56856
|
+
constructor(maxGroups = DEFAULT_MAX_GROUPS) {
|
|
56857
|
+
this.maxGroups = maxGroups;
|
|
56858
|
+
}
|
|
56808
56859
|
/**
|
|
56809
56860
|
* Process a log line and update templates.
|
|
56810
56861
|
*/
|
|
@@ -56815,7 +56866,12 @@ var require_LogTemplateEngine = __commonJS({
|
|
|
56815
56866
|
return;
|
|
56816
56867
|
const groups = this.groups.get(tokens.length);
|
|
56817
56868
|
if (!groups) {
|
|
56869
|
+
if (this.groupCount >= this.maxGroups) {
|
|
56870
|
+
this.droppedGroups++;
|
|
56871
|
+
return;
|
|
56872
|
+
}
|
|
56818
56873
|
this.groups.set(tokens.length, [{ tokens: tokens.map((t) => isVariable(t) ? "<*>" : t), count: 1 }]);
|
|
56874
|
+
this.groupCount++;
|
|
56819
56875
|
return;
|
|
56820
56876
|
}
|
|
56821
56877
|
let bestMatch = null;
|
|
@@ -56840,8 +56896,11 @@ var require_LogTemplateEngine = __commonJS({
|
|
|
56840
56896
|
bestMatch.tokens[i] = "<*>";
|
|
56841
56897
|
}
|
|
56842
56898
|
}
|
|
56843
|
-
} else {
|
|
56899
|
+
} else if (this.groupCount < this.maxGroups) {
|
|
56844
56900
|
groups.push({ tokens: tokens.map((t) => isVariable(t) ? "<*>" : t), count: 1 });
|
|
56901
|
+
this.groupCount++;
|
|
56902
|
+
} else {
|
|
56903
|
+
this.droppedGroups++;
|
|
56845
56904
|
}
|
|
56846
56905
|
}
|
|
56847
56906
|
/**
|
|
@@ -56864,9 +56923,18 @@ var require_LogTemplateEngine = __commonJS({
|
|
|
56864
56923
|
getTotalLines() {
|
|
56865
56924
|
return this.totalLines;
|
|
56866
56925
|
}
|
|
56926
|
+
getDiagnostics() {
|
|
56927
|
+
return {
|
|
56928
|
+
groupCount: this.groupCount,
|
|
56929
|
+
droppedGroups: this.droppedGroups,
|
|
56930
|
+
totalLines: this.totalLines
|
|
56931
|
+
};
|
|
56932
|
+
}
|
|
56867
56933
|
reset() {
|
|
56868
56934
|
this.groups.clear();
|
|
56869
56935
|
this.totalLines = 0;
|
|
56936
|
+
this.groupCount = 0;
|
|
56937
|
+
this.droppedGroups = 0;
|
|
56870
56938
|
}
|
|
56871
56939
|
};
|
|
56872
56940
|
exports2.LogTemplateEngine = LogTemplateEngine2;
|
|
@@ -94298,10 +94366,25 @@ var DockerState = class {
|
|
|
94298
94366
|
lastRefresh = null;
|
|
94299
94367
|
daemonConnected = false;
|
|
94300
94368
|
cachedFileConfig = null;
|
|
94369
|
+
refreshTimer = null;
|
|
94301
94370
|
constructor(client, cwd2) {
|
|
94302
94371
|
this.client = client;
|
|
94303
94372
|
this.cwd = cwd2;
|
|
94304
94373
|
}
|
|
94374
|
+
/** Debounced refresh — coalesces rapid event-driven refreshes into a single call. */
|
|
94375
|
+
scheduleRefresh() {
|
|
94376
|
+
if (this.refreshTimer) return;
|
|
94377
|
+
this.refreshTimer = setTimeout(() => {
|
|
94378
|
+
this.refreshTimer = null;
|
|
94379
|
+
this.refresh().catch((e) => console.debug("refresh failed:", e));
|
|
94380
|
+
}, 500);
|
|
94381
|
+
}
|
|
94382
|
+
dispose() {
|
|
94383
|
+
if (this.refreshTimer) {
|
|
94384
|
+
clearTimeout(this.refreshTimer);
|
|
94385
|
+
this.refreshTimer = null;
|
|
94386
|
+
}
|
|
94387
|
+
}
|
|
94305
94388
|
async refresh() {
|
|
94306
94389
|
try {
|
|
94307
94390
|
const promises = [
|
|
@@ -94320,6 +94403,19 @@ var DockerState = class {
|
|
|
94320
94403
|
this.composeProjects = this.composeDetector.detect(containers, fileConfig);
|
|
94321
94404
|
this.lastRefresh = /* @__PURE__ */ new Date();
|
|
94322
94405
|
this.daemonConnected = true;
|
|
94406
|
+
const currentContainerIds = new Set(containers.map((c) => c.id));
|
|
94407
|
+
for (const id of this.inspectedEnv.keys()) {
|
|
94408
|
+
if (!currentContainerIds.has(id)) this.inspectedEnv.delete(id);
|
|
94409
|
+
}
|
|
94410
|
+
for (const id of this.containerChanges.keys()) {
|
|
94411
|
+
if (!currentContainerIds.has(id)) this.containerChanges.delete(id);
|
|
94412
|
+
}
|
|
94413
|
+
const currentImageIds = new Set(images.map((i) => i.id));
|
|
94414
|
+
for (const id of this.imageLayers.keys()) {
|
|
94415
|
+
if (!currentImageIds.has(id)) this.imageLayers.delete(id);
|
|
94416
|
+
}
|
|
94417
|
+
const runningIds = new Set(containers.filter((c) => c.state === "running").map((c) => c.id));
|
|
94418
|
+
this.statsCollector.prune(runningIds);
|
|
94323
94419
|
} catch {
|
|
94324
94420
|
this.daemonConnected = false;
|
|
94325
94421
|
}
|
|
@@ -94332,7 +94428,7 @@ var DockerState = class {
|
|
|
94332
94428
|
case "image":
|
|
94333
94429
|
case "volume":
|
|
94334
94430
|
case "network":
|
|
94335
|
-
this.
|
|
94431
|
+
this.scheduleRefresh();
|
|
94336
94432
|
break;
|
|
94337
94433
|
}
|
|
94338
94434
|
}
|
|
@@ -94347,7 +94443,7 @@ var DockerState = class {
|
|
|
94347
94443
|
existing.state = "running";
|
|
94348
94444
|
existing.status = "Up just now";
|
|
94349
94445
|
}
|
|
94350
|
-
this.
|
|
94446
|
+
this.scheduleRefresh();
|
|
94351
94447
|
break;
|
|
94352
94448
|
}
|
|
94353
94449
|
case "stop":
|
|
@@ -94369,13 +94465,15 @@ var DockerState = class {
|
|
|
94369
94465
|
case "destroy":
|
|
94370
94466
|
this.containers = this.containers.filter((c) => c.id !== resourceId);
|
|
94371
94467
|
this.statsCollector.remove(resourceId);
|
|
94468
|
+
this.inspectedEnv.delete(resourceId);
|
|
94469
|
+
this.containerChanges.delete(resourceId);
|
|
94372
94470
|
break;
|
|
94373
94471
|
case "create":
|
|
94374
|
-
this.
|
|
94472
|
+
this.scheduleRefresh();
|
|
94375
94473
|
break;
|
|
94376
94474
|
default:
|
|
94377
94475
|
if (name) {
|
|
94378
|
-
this.
|
|
94476
|
+
this.scheduleRefresh();
|
|
94379
94477
|
}
|
|
94380
94478
|
break;
|
|
94381
94479
|
}
|
|
@@ -94437,19 +94535,19 @@ var DockerState = class {
|
|
|
94437
94535
|
}
|
|
94438
94536
|
getMetrics() {
|
|
94439
94537
|
return {
|
|
94440
|
-
containers:
|
|
94441
|
-
images:
|
|
94442
|
-
volumes:
|
|
94443
|
-
networks:
|
|
94444
|
-
composeProjects:
|
|
94538
|
+
containers: this.containers,
|
|
94539
|
+
images: this.images,
|
|
94540
|
+
volumes: this.volumes,
|
|
94541
|
+
networks: this.networks,
|
|
94542
|
+
composeProjects: this.composeProjects,
|
|
94445
94543
|
statsCollector: this.statsCollector,
|
|
94446
94544
|
inspectedEnv: this.inspectedEnv,
|
|
94447
94545
|
containerChanges: this.containerChanges,
|
|
94448
94546
|
imageLayers: this.imageLayers,
|
|
94449
|
-
selectedContainerLogs:
|
|
94450
|
-
selectedComposeLogs:
|
|
94451
|
-
secondaryContainerLogs:
|
|
94452
|
-
secondaryComposeLogs:
|
|
94547
|
+
selectedContainerLogs: this.selectedLogs,
|
|
94548
|
+
selectedComposeLogs: this.selectedComposeLogs,
|
|
94549
|
+
secondaryContainerLogs: this.secondaryLogs,
|
|
94550
|
+
secondaryComposeLogs: this.secondaryComposeLogs,
|
|
94453
94551
|
lastRefresh: this.lastRefresh,
|
|
94454
94552
|
daemonConnected: this.daemonConnected,
|
|
94455
94553
|
logFilterString: "",
|
|
@@ -94593,17 +94691,27 @@ function colorizeTokens(message) {
|
|
|
94593
94691
|
return colorFn ? colorFn(t.text) : t.text;
|
|
94594
94692
|
}).join("");
|
|
94595
94693
|
}
|
|
94694
|
+
var colorizedCache = /* @__PURE__ */ new WeakMap();
|
|
94596
94695
|
function colorizeLogEntry(entry, filterMatches) {
|
|
94696
|
+
if (!filterMatches) {
|
|
94697
|
+
const cached = colorizedCache.get(entry);
|
|
94698
|
+
if (cached !== void 0) return cached;
|
|
94699
|
+
}
|
|
94597
94700
|
const ts = entry.timestamp ? (0, import_sidekick_docker_shared2.formatTimestampTime)(entry.timestamp) : "";
|
|
94598
94701
|
const tsColored = ts ? ansi.dim(ansi.gray(ts)) + " " : "";
|
|
94702
|
+
let result;
|
|
94599
94703
|
if (entry.stream === "stderr") {
|
|
94600
94704
|
const msg = filterMatches ? highlightMatches(entry.message, filterMatches, ansi.red) : ansi.red(entry.message);
|
|
94601
|
-
|
|
94705
|
+
result = tsColored + msg;
|
|
94706
|
+
} else if (filterMatches && filterMatches.length > 0) {
|
|
94707
|
+
result = tsColored + highlightMatches(entry.message, filterMatches);
|
|
94708
|
+
} else {
|
|
94709
|
+
result = tsColored + colorizeTokens(entry.message);
|
|
94602
94710
|
}
|
|
94603
|
-
if (filterMatches
|
|
94604
|
-
|
|
94711
|
+
if (!filterMatches) {
|
|
94712
|
+
colorizedCache.set(entry, result);
|
|
94605
94713
|
}
|
|
94606
|
-
return
|
|
94714
|
+
return result;
|
|
94607
94715
|
}
|
|
94608
94716
|
function highlightMatches(text, matches, baseFn) {
|
|
94609
94717
|
if (matches.length === 0) return baseFn ? baseFn(text) : colorizeTokens(text);
|
|
@@ -94765,8 +94873,8 @@ var ContainersPanel = class {
|
|
|
94765
94873
|
label: "Logs",
|
|
94766
94874
|
render: (_item, metrics) => {
|
|
94767
94875
|
const logs = metrics.selectedContainerLogs;
|
|
94768
|
-
if (logs.length === 0) return "No logs available. Select a container to view logs.";
|
|
94769
|
-
return renderLogLines(logs, metrics.logFilterString, metrics.logFilterMode, metrics.logSeverityCounts)
|
|
94876
|
+
if (logs.length === 0) return ["No logs available. Select a container to view logs."];
|
|
94877
|
+
return renderLogLines(logs, metrics.logFilterString, metrics.logFilterMode, metrics.logSeverityCounts);
|
|
94770
94878
|
},
|
|
94771
94879
|
autoScrollBottom: true
|
|
94772
94880
|
},
|
|
@@ -95065,8 +95173,8 @@ var ServicesPanel = class {
|
|
|
95065
95173
|
label: "Logs",
|
|
95066
95174
|
render: (_item, metrics) => {
|
|
95067
95175
|
const logs = metrics.selectedComposeLogs;
|
|
95068
|
-
if (logs.length === 0) return "No compose logs. Logs will appear when a service produces output.";
|
|
95069
|
-
return renderLogLines(logs, metrics.logFilterString, metrics.logFilterMode)
|
|
95176
|
+
if (logs.length === 0) return ["No compose logs. Logs will appear when a service produces output."];
|
|
95177
|
+
return renderLogLines(logs, metrics.logFilterString, metrics.logFilterMode);
|
|
95070
95178
|
},
|
|
95071
95179
|
autoScrollBottom: true
|
|
95072
95180
|
}
|
|
@@ -95479,6 +95587,8 @@ var BaseStreamManager = class {
|
|
|
95479
95587
|
streamPromise = null;
|
|
95480
95588
|
reconnect = new import_sidekick_docker_shared6.ReconnectScheduler();
|
|
95481
95589
|
onChange;
|
|
95590
|
+
streamController = null;
|
|
95591
|
+
streamGeneration = 0;
|
|
95482
95592
|
constructor(onChange) {
|
|
95483
95593
|
this.onChange = onChange;
|
|
95484
95594
|
this.currentId = this.emptyId();
|
|
@@ -95492,25 +95602,29 @@ var BaseStreamManager = class {
|
|
|
95492
95602
|
if (!this.isValidId(id)) return;
|
|
95493
95603
|
this.aborted = false;
|
|
95494
95604
|
this.reconnect.reset();
|
|
95605
|
+
this.streamController = new AbortController();
|
|
95606
|
+
this.streamGeneration++;
|
|
95495
95607
|
this.onBeforeStream();
|
|
95496
|
-
this.streamPromise = this.runStream(id);
|
|
95608
|
+
this.streamPromise = this.runStream(id, this.streamController.signal, this.streamGeneration);
|
|
95497
95609
|
}
|
|
95498
|
-
async runStream(id) {
|
|
95610
|
+
async runStream(id, signal, generation) {
|
|
95499
95611
|
try {
|
|
95500
|
-
for await (const item of this.createStream(id)) {
|
|
95501
|
-
if (this.aborted || !this.isSameId(id, this.currentId)) break;
|
|
95612
|
+
for await (const item of this.createStream(id, signal)) {
|
|
95613
|
+
if (signal.aborted || this.aborted || !this.isSameId(id, this.currentId)) break;
|
|
95502
95614
|
this.processItem(id, item);
|
|
95503
95615
|
this.onChange();
|
|
95504
95616
|
}
|
|
95505
95617
|
this.reconnect.reset();
|
|
95506
95618
|
} catch (err) {
|
|
95619
|
+
if (signal.aborted) return;
|
|
95507
95620
|
console.debug(`${this.streamLabel} stream error:`, (0, import_sidekick_docker_shared6.errorMessage)(err));
|
|
95508
95621
|
}
|
|
95509
|
-
if (!this.aborted && this.isSameId(id, this.currentId)) {
|
|
95622
|
+
if (!signal.aborted && !this.aborted && this.isSameId(id, this.currentId) && generation === this.streamGeneration) {
|
|
95510
95623
|
const scheduled = this.reconnect.schedule(() => {
|
|
95511
|
-
if (!this.aborted && this.isSameId(id, this.currentId)) {
|
|
95624
|
+
if (!this.aborted && this.isSameId(id, this.currentId) && generation === this.streamGeneration) {
|
|
95625
|
+
this.streamController = new AbortController();
|
|
95512
95626
|
this.onBeforeStream();
|
|
95513
|
-
this.streamPromise = this.runStream(id);
|
|
95627
|
+
this.streamPromise = this.runStream(id, this.streamController.signal, generation);
|
|
95514
95628
|
}
|
|
95515
95629
|
});
|
|
95516
95630
|
if (!scheduled) {
|
|
@@ -95521,6 +95635,8 @@ var BaseStreamManager = class {
|
|
|
95521
95635
|
stop() {
|
|
95522
95636
|
this.aborted = true;
|
|
95523
95637
|
this.currentId = this.emptyId();
|
|
95638
|
+
this.streamController?.abort();
|
|
95639
|
+
this.streamController = null;
|
|
95524
95640
|
this.streamPromise = null;
|
|
95525
95641
|
this.reconnect.clear();
|
|
95526
95642
|
this.onStop();
|
|
@@ -95561,8 +95677,8 @@ var LogStreamManager = class extends BaseStreamManager {
|
|
|
95561
95677
|
idLabel(id) {
|
|
95562
95678
|
return id ?? "(none)";
|
|
95563
95679
|
}
|
|
95564
|
-
createStream(id) {
|
|
95565
|
-
return this.client.streamLogs(id, { follow: true, tail: 100 });
|
|
95680
|
+
createStream(id, signal) {
|
|
95681
|
+
return this.client.streamLogs(id, { follow: true, tail: 100 }, signal);
|
|
95566
95682
|
}
|
|
95567
95683
|
processItem(_id, entry) {
|
|
95568
95684
|
this.logs.push(entry);
|
|
@@ -95594,6 +95710,9 @@ var LogStreamManager = class extends BaseStreamManager {
|
|
|
95594
95710
|
getCurrentContainerId() {
|
|
95595
95711
|
return this.currentId;
|
|
95596
95712
|
}
|
|
95713
|
+
getTemplateDiagnostics() {
|
|
95714
|
+
return this.templateEngine.getDiagnostics();
|
|
95715
|
+
}
|
|
95597
95716
|
};
|
|
95598
95717
|
|
|
95599
95718
|
// src/dashboard/StatsStreamManager.ts
|
|
@@ -95618,8 +95737,8 @@ var StatsStreamManager = class extends BaseStreamManager {
|
|
|
95618
95737
|
idLabel(id) {
|
|
95619
95738
|
return id ?? "(none)";
|
|
95620
95739
|
}
|
|
95621
|
-
createStream(id) {
|
|
95622
|
-
return this.client.streamStats(id);
|
|
95740
|
+
createStream(id, signal) {
|
|
95741
|
+
return this.client.streamStats(id, signal);
|
|
95623
95742
|
}
|
|
95624
95743
|
processItem(id, stats) {
|
|
95625
95744
|
this.collector.push(id, stats);
|
|
@@ -95659,8 +95778,8 @@ var ComposeLogStreamManager = class extends BaseStreamManager {
|
|
|
95659
95778
|
idLabel(id) {
|
|
95660
95779
|
return id.project ?? "(none)";
|
|
95661
95780
|
}
|
|
95662
|
-
createStream(id) {
|
|
95663
|
-
return this.composeClient.streamLogs(id.project, id.service ?? void 0);
|
|
95781
|
+
createStream(id, signal) {
|
|
95782
|
+
return this.composeClient.streamLogs(id.project, id.service ?? void 0, 100, signal);
|
|
95664
95783
|
}
|
|
95665
95784
|
processItem(_id, entry) {
|
|
95666
95785
|
this.logs.push(entry);
|
|
@@ -97222,13 +97341,13 @@ function Dashboard({ panels, metrics, onViewStateChange, execTriggerRef, onExecF
|
|
|
97222
97341
|
logFilterString: state.logFilterString,
|
|
97223
97342
|
logFilterMode: state.logFilterMode
|
|
97224
97343
|
};
|
|
97225
|
-
let
|
|
97344
|
+
let detailLines = [];
|
|
97226
97345
|
if (selectedItem && detailTabs.length > 0 && tabIdx >= 0) {
|
|
97227
|
-
|
|
97346
|
+
const result = detailTabs[tabIdx].render(selectedItem, enrichedMetrics);
|
|
97347
|
+
detailLines = Array.isArray(result) ? result : result.split("\n");
|
|
97228
97348
|
} else if (!selectedItem) {
|
|
97229
|
-
|
|
97349
|
+
detailLines = ["(no item selected)"];
|
|
97230
97350
|
}
|
|
97231
|
-
const detailLines = detailContent.split("\n");
|
|
97232
97351
|
const detailViewportHeight = Math.max(1, rows - RESERVED_UI_ROWS);
|
|
97233
97352
|
const activeTab = detailTabs[tabIdx];
|
|
97234
97353
|
const shouldAutoScroll = activeTab?.autoScrollBottom ?? false;
|
|
@@ -97380,8 +97499,8 @@ function Dashboard({ panels, metrics, onViewStateChange, execTriggerRef, onExecF
|
|
|
97380
97499
|
)
|
|
97381
97500
|
] })
|
|
97382
97501
|
] }),
|
|
97383
|
-
state.overlay === "help" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(HelpOverlay, { panels, activePanelIndex: state.activePanelIndex, version: "0.2.
|
|
97384
|
-
state.overlay === "version" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VersionOverlay, { version: "0.2.
|
|
97502
|
+
state.overlay === "help" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(HelpOverlay, { panels, activePanelIndex: state.activePanelIndex, version: "0.2.6" }),
|
|
97503
|
+
state.overlay === "version" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VersionOverlay, { version: "0.2.6" }),
|
|
97385
97504
|
state.overlay === "exec" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
97386
97505
|
ExecOverlay,
|
|
97387
97506
|
{
|
|
@@ -97398,7 +97517,7 @@ function Dashboard({ panels, metrics, onViewStateChange, execTriggerRef, onExecF
|
|
|
97398
97517
|
filterString: state.filterString,
|
|
97399
97518
|
containerCount: metrics.containers.length,
|
|
97400
97519
|
runningCount,
|
|
97401
|
-
version: "0.2.
|
|
97520
|
+
version: "0.2.6",
|
|
97402
97521
|
matchCount: state.filterString ? currentItems.length : void 0,
|
|
97403
97522
|
totalCount: state.filterString ? totalItemCount : void 0,
|
|
97404
97523
|
lastRefresh: metrics.lastRefresh,
|
|
@@ -97468,6 +97587,7 @@ async function dashboardAction(_opts, cmd) {
|
|
|
97468
97587
|
if (renderTimer) return;
|
|
97469
97588
|
renderTimer = setTimeout(() => {
|
|
97470
97589
|
renderTimer = null;
|
|
97590
|
+
if (process.stdout.writableLength > process.stdout.writableHighWaterMark) return;
|
|
97471
97591
|
instance.rerender(
|
|
97472
97592
|
import_react37.default.createElement(Dashboard, {
|
|
97473
97593
|
panels,
|
|
@@ -97477,7 +97597,7 @@ async function dashboardAction(_opts, cmd) {
|
|
|
97477
97597
|
onExecFallback
|
|
97478
97598
|
})
|
|
97479
97599
|
);
|
|
97480
|
-
},
|
|
97600
|
+
}, 200);
|
|
97481
97601
|
}
|
|
97482
97602
|
const logManager = new LogStreamManager(client, () => {
|
|
97483
97603
|
if (logFlushTimer) return;
|
|
@@ -97660,6 +97780,21 @@ async function dashboardAction(_opts, cmd) {
|
|
|
97660
97780
|
const refreshInterval = setInterval(() => {
|
|
97661
97781
|
state.refresh().then(() => scheduleRender()).catch((e) => console.debug("periodic refresh failed:", e));
|
|
97662
97782
|
}, 3e4);
|
|
97783
|
+
let debugInterval = null;
|
|
97784
|
+
if (process.env.SIDEKICK_DEBUG_STREAMS === "1") {
|
|
97785
|
+
debugInterval = setInterval(() => {
|
|
97786
|
+
const mem = process.memoryUsage();
|
|
97787
|
+
const heapMB = (mem.heapUsed / 1024 / 1024).toFixed(1);
|
|
97788
|
+
const rssMB = (mem.rss / 1024 / 1024).toFixed(1);
|
|
97789
|
+
const extMB = (mem.external / 1024 / 1024).toFixed(1);
|
|
97790
|
+
const bufMB = (mem.arrayBuffers / 1024 / 1024).toFixed(1);
|
|
97791
|
+
const stdoutBuf = process.stdout.writableLength;
|
|
97792
|
+
const stdoutHWM = process.stdout.writableHighWaterMark;
|
|
97793
|
+
const templateDiag = logManager.getTemplateDiagnostics();
|
|
97794
|
+
const secondaryDiag = secondaryLogManager.getTemplateDiagnostics();
|
|
97795
|
+
console.debug(`[sidekick-debug] heap=${heapMB}MB rss=${rssMB}MB ext=${extMB}MB bufs=${bufMB}MB stdout=${stdoutBuf}/${stdoutHWM} templates=${JSON.stringify(templateDiag)} secondary=${JSON.stringify(secondaryDiag)}`);
|
|
97796
|
+
}, 6e4);
|
|
97797
|
+
}
|
|
97663
97798
|
const execTriggerRef = { current: null };
|
|
97664
97799
|
const onExecFallback = (containerId) => {
|
|
97665
97800
|
instance.clear();
|
|
@@ -97759,10 +97894,18 @@ async function dashboardAction(_opts, cmd) {
|
|
|
97759
97894
|
clearInterval(refreshInterval);
|
|
97760
97895
|
} catch {
|
|
97761
97896
|
}
|
|
97897
|
+
try {
|
|
97898
|
+
if (debugInterval) clearInterval(debugInterval);
|
|
97899
|
+
} catch {
|
|
97900
|
+
}
|
|
97762
97901
|
try {
|
|
97763
97902
|
watcher.stop();
|
|
97764
97903
|
} catch {
|
|
97765
97904
|
}
|
|
97905
|
+
try {
|
|
97906
|
+
state.dispose();
|
|
97907
|
+
} catch {
|
|
97908
|
+
}
|
|
97766
97909
|
try {
|
|
97767
97910
|
client.dispose();
|
|
97768
97911
|
} catch {
|
|
@@ -97839,7 +97982,7 @@ async function logsAction(container, opts) {
|
|
|
97839
97982
|
|
|
97840
97983
|
// src/cli.ts
|
|
97841
97984
|
var program2 = new Command();
|
|
97842
|
-
program2.name("sidekick-docker").description("Docker management TUI dashboard").version("0.2.
|
|
97985
|
+
program2.name("sidekick-docker").description("Docker management TUI dashboard").version("0.2.6").option("--socket <path>", "Docker socket path").action(async (_opts, cmd) => {
|
|
97843
97986
|
await dashboardAction(_opts, cmd);
|
|
97844
97987
|
});
|
|
97845
97988
|
program2.command("ps").description("List containers").option("-a, --all", "Show all containers (default: running only)", false).action(async (opts) => {
|