@stage-labs/metro 0.1.0-beta.141 → 0.1.0-beta.142
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/api.js +1 -6
- package/dist/cli.js +1 -14
- package/dist/local.js +0 -13
- package/package.json +1 -1
- package/runtime/marketplace/plugin/.claude-plugin/plugin.json +2 -2
- package/runtime/marketplace/plugin/bin/metro-plugin.mjs +24 -111
- package/runtime/node_modules/@metro-labs/daemon/src/boot/boot.ts +3 -13
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/api.ts +5 -7
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/config.ts +2 -20
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/health.ts +18 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/model.ts +1 -9
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/plugin-sync.ts +8 -8
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay.ts +6 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/store.ts +2 -7
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/url.ts +0 -11
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/verify.ts +42 -273
- package/runtime/node_modules/@metro-labs/daemon/src/routes/local-mode.ts +6 -16
- package/runtime/node_modules/@metro-labs/daemon/src/routes/session-apis.ts +0 -3
- package/runtime/runtime.json +1 -1
- package/dist/plugin.js +0 -120
- package/runtime/marketplace/plugin/skills/refresh/SKILL.md +0 -15
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/cli-api.ts +0 -63
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/json.ts +0 -21
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/tools.ts +0 -98
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/watch.ts +0 -54
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { isRecord } from '@metro-labs/core/is-record';
|
|
2
|
-
|
|
3
|
-
export const TOOL_KINDS = ['read', 'write'] as const;
|
|
4
|
-
|
|
5
|
-
export type ToolKind = (typeof TOOL_KINDS)[number];
|
|
6
|
-
|
|
7
|
-
export interface ToolInfo {
|
|
8
|
-
name: string;
|
|
9
|
-
title: string;
|
|
10
|
-
description: string;
|
|
11
|
-
kind: ToolKind;
|
|
12
|
-
annotated: boolean;
|
|
13
|
-
destructive: boolean;
|
|
14
|
-
idempotent: boolean;
|
|
15
|
-
openWorld: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const MAX_TOOLS = 500;
|
|
19
|
-
const MAX_DESCRIPTION = 400;
|
|
20
|
-
|
|
21
|
-
const str = (value: unknown, cap: number): string =>
|
|
22
|
-
typeof value === 'string' ? value.slice(0, cap) : '';
|
|
23
|
-
|
|
24
|
-
const flag = (value: unknown, fallback: boolean): boolean =>
|
|
25
|
-
typeof value === 'boolean' ? value : fallback;
|
|
26
|
-
|
|
27
|
-
export function classifyTool(annotations: unknown): ToolKind {
|
|
28
|
-
return isRecord(annotations) && annotations.readOnlyHint === true
|
|
29
|
-
? 'read'
|
|
30
|
-
: 'write';
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function isDestructive(annotations: unknown): boolean {
|
|
34
|
-
if (!isRecord(annotations)) return true;
|
|
35
|
-
if (annotations.readOnlyHint === true) return false;
|
|
36
|
-
return annotations.destructiveHint !== false;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function toToolInfo(raw: unknown): ToolInfo | null {
|
|
40
|
-
if (!isRecord(raw)) return null;
|
|
41
|
-
const name = str(raw.name, 200);
|
|
42
|
-
if (name === '') return null;
|
|
43
|
-
const annotations = isRecord(raw.annotations) ? raw.annotations : undefined;
|
|
44
|
-
return {
|
|
45
|
-
name,
|
|
46
|
-
title: str(annotations?.title ?? raw.title, 200),
|
|
47
|
-
description: str(raw.description, MAX_DESCRIPTION),
|
|
48
|
-
kind: classifyTool(raw.annotations),
|
|
49
|
-
annotated: annotations !== undefined,
|
|
50
|
-
destructive: isDestructive(raw.annotations),
|
|
51
|
-
idempotent: flag(annotations?.idempotentHint, false),
|
|
52
|
-
openWorld: flag(annotations?.openWorldHint, true),
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function toToolList(raw: unknown): ToolInfo[] {
|
|
57
|
-
if (!Array.isArray(raw)) return [];
|
|
58
|
-
const out: ToolInfo[] = [];
|
|
59
|
-
for (const entry of raw) {
|
|
60
|
-
if (out.length >= MAX_TOOLS) break;
|
|
61
|
-
const tool = toToolInfo(entry);
|
|
62
|
-
if (tool !== null) out.push(tool);
|
|
63
|
-
}
|
|
64
|
-
return out;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function toStoredTool(raw: unknown): ToolInfo | null {
|
|
68
|
-
if (!isRecord(raw)) return null;
|
|
69
|
-
const name = str(raw.name, 200);
|
|
70
|
-
if (name === '') return null;
|
|
71
|
-
return {
|
|
72
|
-
name,
|
|
73
|
-
title: str(raw.title, 200),
|
|
74
|
-
description: str(raw.description, MAX_DESCRIPTION),
|
|
75
|
-
kind: raw.kind === 'read' ? 'read' : 'write',
|
|
76
|
-
annotated: raw.annotated === true,
|
|
77
|
-
destructive: raw.destructive !== false,
|
|
78
|
-
idempotent: raw.idempotent === true,
|
|
79
|
-
openWorld: raw.openWorld !== false,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function readStoredTools(raw: unknown): ToolInfo[] {
|
|
84
|
-
if (!Array.isArray(raw)) return [];
|
|
85
|
-
const out: ToolInfo[] = [];
|
|
86
|
-
for (const entry of raw) {
|
|
87
|
-
if (out.length >= MAX_TOOLS) break;
|
|
88
|
-
const tool = toStoredTool(entry);
|
|
89
|
-
if (tool !== null) out.push(tool);
|
|
90
|
-
}
|
|
91
|
-
return out;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export function countByKind(tools: ToolInfo[]): Record<ToolKind, number> {
|
|
95
|
-
const counts: Record<ToolKind, number> = { read: 0, write: 0 };
|
|
96
|
-
for (const tool of tools) counts[tool.kind] += 1;
|
|
97
|
-
return counts;
|
|
98
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { watch, type FSWatcher } from 'node:fs';
|
|
2
|
-
import { errMsg, log } from '@metro-labs/core/log';
|
|
3
|
-
|
|
4
|
-
const DEBOUNCE_MS = 300;
|
|
5
|
-
const FILE = 'connectors.json';
|
|
6
|
-
|
|
7
|
-
export class ConnectorWatch {
|
|
8
|
-
private watcher: FSWatcher | null = null;
|
|
9
|
-
private timer: ReturnType<typeof setTimeout> | null = null;
|
|
10
|
-
|
|
11
|
-
constructor(
|
|
12
|
-
private readonly dir: string,
|
|
13
|
-
private readonly onChange: () => void,
|
|
14
|
-
) {}
|
|
15
|
-
|
|
16
|
-
start(): void {
|
|
17
|
-
try {
|
|
18
|
-
this.watcher = watch(this.dir, (_event, file) => {
|
|
19
|
-
if (file === null || file === FILE) this.schedule();
|
|
20
|
-
});
|
|
21
|
-
this.watcher.on('error', (err: unknown) => {
|
|
22
|
-
log.warn({ err: errMsg(err) }, 'connectors: watcher failed; the plugin list refreshes at the next start');
|
|
23
|
-
});
|
|
24
|
-
this.watcher.unref();
|
|
25
|
-
} catch (err) {
|
|
26
|
-
log.warn({ err: errMsg(err) }, 'connectors: could not watch the agents dir');
|
|
27
|
-
}
|
|
28
|
-
this.fire();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
stop(): void {
|
|
32
|
-
this.watcher?.close();
|
|
33
|
-
this.watcher = null;
|
|
34
|
-
if (this.timer !== null) clearTimeout(this.timer);
|
|
35
|
-
this.timer = null;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
private schedule(): void {
|
|
39
|
-
if (this.timer !== null) clearTimeout(this.timer);
|
|
40
|
-
this.timer = setTimeout(() => {
|
|
41
|
-
this.timer = null;
|
|
42
|
-
this.fire();
|
|
43
|
-
}, DEBOUNCE_MS);
|
|
44
|
-
this.timer.unref();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
private fire(): void {
|
|
48
|
-
try {
|
|
49
|
-
this.onChange();
|
|
50
|
-
} catch (err) {
|
|
51
|
-
log.warn({ err: errMsg(err) }, 'connectors: change handler failed');
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|