agent-tempo 1.2.0 → 1.4.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/CLAUDE.md +253 -219
- package/LICENSE +21 -21
- package/README.md +293 -289
- package/assets/icon-dark.svg +9 -9
- package/assets/icon.svg +9 -9
- package/assets/logo-dark.svg +11 -11
- package/assets/logo-light.svg +11 -11
- package/dashboard/README.md +91 -91
- package/dashboard/dist/assets/{index-D6Xyje_n.js → index-jmYe6rmS.js} +2 -2
- package/dashboard/dist/assets/index-jmYe6rmS.js.map +1 -0
- package/dashboard/dist/index.html +20 -20
- package/dashboard/package.json +47 -47
- package/dist/activities/outbox.d.ts +30 -1
- package/dist/activities/outbox.js +96 -3
- package/dist/adapters/base.js +5 -0
- package/dist/adapters/copilot/adapter.js +12 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js +7 -0
- package/dist/adapters/pi/adapter.d.ts +2 -0
- package/dist/adapters/pi/adapter.js +43 -0
- package/dist/adapters/pi/index.d.ts +16 -0
- package/dist/adapters/pi/index.js +10 -0
- package/dist/cli/global-wrapper.d.ts +19 -0
- package/dist/cli/global-wrapper.js +169 -0
- package/dist/cli/help-text.js +97 -97
- package/dist/cli/startup.js +11 -0
- package/dist/cli/upgrade-command.js +81 -81
- package/dist/cli.js +12 -0
- package/dist/client/core.js +9 -2
- package/dist/client/interface.d.ts +6 -0
- package/dist/config.d.ts +79 -0
- package/dist/config.js +74 -0
- package/dist/daemon.js +37 -1
- package/dist/http/aggregate.d.ts +22 -1
- package/dist/http/aggregate.js +41 -0
- package/dist/http/auth.d.ts +94 -8
- package/dist/http/auth.js +93 -9
- package/dist/http/body.d.ts +4 -1
- package/dist/http/body.js +6 -3
- package/dist/http/event-bus.js +1 -0
- package/dist/http/event-types.d.ts +34 -2
- package/dist/http/event-types.js +1 -0
- package/dist/http/gate-audit.d.ts +12 -0
- package/dist/http/gate-audit.js +95 -0
- package/dist/http/gate-registry.d.ts +167 -0
- package/dist/http/gate-registry.js +163 -0
- package/dist/http/gate-routes.d.ts +48 -0
- package/dist/http/gate-routes.js +102 -0
- package/dist/http/ingest-registry.d.ts +30 -0
- package/dist/http/ingest-registry.js +108 -0
- package/dist/http/inner-loop-routes.d.ts +66 -0
- package/dist/http/inner-loop-routes.js +182 -0
- package/dist/http/inner-loop.d.ts +92 -0
- package/dist/http/inner-loop.js +155 -0
- package/dist/http/server.d.ts +38 -3
- package/dist/http/server.js +211 -6
- package/dist/http/snapshot.d.ts +6 -0
- package/dist/http/snapshot.js +6 -0
- package/dist/pi/cue-pump.d.ts +61 -0
- package/dist/pi/cue-pump.js +95 -0
- package/dist/pi/extension.d.ts +45 -0
- package/dist/pi/extension.js +407 -0
- package/dist/pi/gate-client.d.ts +54 -0
- package/dist/pi/gate-client.js +136 -0
- package/dist/pi/headless.d.ts +85 -0
- package/dist/pi/headless.js +224 -0
- package/dist/pi/index.d.ts +28 -0
- package/dist/pi/index.js +43 -0
- package/dist/pi/inner-loop-client.d.ts +67 -0
- package/dist/pi/inner-loop-client.js +164 -0
- package/dist/pi/inner-loop-publisher.d.ts +187 -0
- package/dist/pi/inner-loop-publisher.js +236 -0
- package/dist/pi/lazy-proxy.d.ts +37 -0
- package/dist/pi/lazy-proxy.js +55 -0
- package/dist/pi/mission-control/actions.d.ts +48 -0
- package/dist/pi/mission-control/actions.js +98 -0
- package/dist/pi/mission-control/board.d.ts +53 -0
- package/dist/pi/mission-control/board.js +104 -0
- package/dist/pi/mission-control/extension.d.ts +44 -0
- package/dist/pi/mission-control/extension.js +251 -0
- package/dist/pi/mission-control/index.d.ts +15 -0
- package/dist/pi/mission-control/index.js +32 -0
- package/dist/pi/mission-control/inner-tail.d.ts +48 -0
- package/dist/pi/mission-control/inner-tail.js +76 -0
- package/dist/pi/mission-control/pi-ui.d.ts +43 -0
- package/dist/pi/mission-control/pi-ui.js +10 -0
- package/dist/pi/mission-control/render.d.ts +6 -0
- package/dist/pi/mission-control/render.js +95 -0
- package/dist/pi/phase-driver.d.ts +74 -0
- package/dist/pi/phase-driver.js +122 -0
- package/dist/pi/pi-types.d.ts +208 -0
- package/dist/pi/pi-types.js +21 -0
- package/dist/pi/probe.d.ts +80 -0
- package/dist/pi/probe.js +154 -0
- package/dist/pi/render-tools.d.ts +17 -0
- package/dist/pi/render-tools.js +51 -0
- package/dist/pi/reset-pump.d.ts +47 -0
- package/dist/pi/reset-pump.js +85 -0
- package/dist/pi/tool-capability.d.ts +60 -0
- package/dist/pi/tool-capability.js +156 -0
- package/dist/pi/workflow-client.d.ts +158 -0
- package/dist/pi/workflow-client.js +289 -0
- package/dist/pi/zod-to-typebox.d.ts +74 -0
- package/dist/pi/zod-to-typebox.js +191 -0
- package/dist/scripts/verify-daemon-isolation-guard.js +24 -24
- package/dist/server-tools.d.ts +2 -0
- package/dist/server-tools.js +50 -46
- package/dist/server.js +4 -0
- package/dist/spawn.d.ts +55 -0
- package/dist/spawn.js +84 -12
- package/dist/tools/agent-types.d.ts +2 -2
- package/dist/tools/agent-types.js +22 -17
- package/dist/tools/attachment-info.d.ts +2 -2
- package/dist/tools/attachment-info.js +38 -33
- package/dist/tools/broadcast.d.ts +2 -2
- package/dist/tools/broadcast.js +69 -64
- package/dist/tools/cancel-stage.d.ts +2 -2
- package/dist/tools/cancel-stage.js +20 -15
- package/dist/tools/clear-state.d.ts +2 -2
- package/dist/tools/clear-state.js +25 -20
- package/dist/tools/coat-check-evict.d.ts +2 -2
- package/dist/tools/coat-check-evict.js +30 -25
- package/dist/tools/coat-check-get.d.ts +2 -2
- package/dist/tools/coat-check-get.js +39 -34
- package/dist/tools/coat-check-list.d.ts +2 -2
- package/dist/tools/coat-check-list.js +48 -43
- package/dist/tools/coat-check-put.d.ts +2 -2
- package/dist/tools/coat-check-put.js +41 -36
- package/dist/tools/cue.d.ts +2 -2
- package/dist/tools/cue.js +57 -52
- package/dist/tools/descriptor.d.ts +72 -0
- package/dist/tools/descriptor.js +39 -0
- package/dist/tools/destroy.d.ts +2 -2
- package/dist/tools/destroy.js +153 -148
- package/dist/tools/ensemble.d.ts +2 -2
- package/dist/tools/ensemble.js +71 -66
- package/dist/tools/evaluate-gate.d.ts +2 -2
- package/dist/tools/evaluate-gate.js +33 -27
- package/dist/tools/fetch-state.d.ts +2 -2
- package/dist/tools/fetch-state.js +43 -38
- package/dist/tools/gates.d.ts +2 -2
- package/dist/tools/gates.js +39 -34
- package/dist/tools/hosts.d.ts +2 -2
- package/dist/tools/hosts.js +25 -20
- package/dist/tools/listen.d.ts +2 -2
- package/dist/tools/listen.js +23 -18
- package/dist/tools/load-lineup.d.ts +2 -2
- package/dist/tools/load-lineup.js +324 -319
- package/dist/tools/migrate.d.ts +2 -2
- package/dist/tools/migrate.js +45 -40
- package/dist/tools/pause.d.ts +2 -2
- package/dist/tools/pause.js +34 -29
- package/dist/tools/play.d.ts +2 -2
- package/dist/tools/play.js +53 -48
- package/dist/tools/quality-gate.d.ts +2 -2
- package/dist/tools/quality-gate.js +26 -21
- package/dist/tools/recall.d.ts +2 -2
- package/dist/tools/recall.js +32 -27
- package/dist/tools/recruit.d.ts +2 -2
- package/dist/tools/recruit.js +325 -256
- package/dist/tools/release.d.ts +2 -2
- package/dist/tools/release.js +85 -80
- package/dist/tools/report.d.ts +2 -2
- package/dist/tools/report.js +28 -23
- package/dist/tools/reset.d.ts +3 -0
- package/dist/tools/reset.js +51 -0
- package/dist/tools/restart.d.ts +2 -2
- package/dist/tools/restart.js +51 -46
- package/dist/tools/restore.d.ts +2 -2
- package/dist/tools/restore.js +76 -71
- package/dist/tools/save-lineup.d.ts +2 -2
- package/dist/tools/save-lineup.js +32 -27
- package/dist/tools/save-state.d.ts +2 -2
- package/dist/tools/save-state.js +43 -38
- package/dist/tools/schedule.d.ts +2 -2
- package/dist/tools/schedule.js +133 -128
- package/dist/tools/schedules.d.ts +2 -2
- package/dist/tools/schedules.js +41 -36
- package/dist/tools/set-ensemble-description.d.ts +2 -2
- package/dist/tools/set-ensemble-description.js +26 -21
- package/dist/tools/set-name.d.ts +2 -2
- package/dist/tools/set-name.js +38 -33
- package/dist/tools/set-part.d.ts +2 -2
- package/dist/tools/set-part.js +20 -15
- package/dist/tools/shutdown.d.ts +2 -2
- package/dist/tools/shutdown.js +39 -34
- package/dist/tools/stage.d.ts +2 -2
- package/dist/tools/stage.js +28 -23
- package/dist/tools/stages.d.ts +2 -2
- package/dist/tools/stages.js +36 -31
- package/dist/tools/unschedule.d.ts +2 -2
- package/dist/tools/unschedule.js +30 -25
- package/dist/tools/who-am-i.d.ts +2 -2
- package/dist/tools/who-am-i.js +36 -31
- package/dist/tools/worktree.d.ts +2 -2
- package/dist/tools/worktree.js +134 -129
- package/dist/tui/index.js +6 -6
- package/dist/types.d.ts +47 -2
- package/dist/types.js +1 -1
- package/dist/utils/default-part.js +1 -0
- package/dist/utils/grpc-shutdown-guard.d.ts +52 -0
- package/dist/utils/grpc-shutdown-guard.js +88 -0
- package/dist/utils/sdk-probe.d.ts +23 -0
- package/dist/utils/sdk-probe.js +46 -7
- package/dist/worker.d.ts +3 -1
- package/dist/worker.js +6 -2
- package/dist/workflows/session.js +70 -2
- package/dist/workflows/signals.d.ts +32 -2
- package/dist/workflows/signals.js +25 -2
- package/examples/agents/tempo-composer.md +56 -56
- package/examples/agents/tempo-conductor.md +117 -117
- package/examples/agents/tempo-critic.md +73 -73
- package/examples/agents/tempo-improv.md +74 -74
- package/examples/agents/tempo-liner.md +75 -75
- package/examples/agents/tempo-roadie.md +61 -61
- package/examples/agents/tempo-soloist.md +71 -71
- package/examples/agents/tempo-tuner.md +94 -94
- package/examples/ensembles/tempo-big-band.yaml +146 -146
- package/examples/ensembles/tempo-dev-team.yaml +58 -58
- package/examples/ensembles/tempo-headless-jam.yaml +77 -77
- package/examples/ensembles/tempo-jam-session.yaml +41 -41
- package/examples/ensembles/tempo-mock-jam.yaml +79 -79
- package/examples/ensembles/tempo-review-squad.yaml +32 -32
- package/package.json +176 -173
- package/packaging/launchd/com.agent.tempo.plist +46 -46
- package/packaging/systemd/agent-tempo.service +32 -32
- package/packaging/windows/install-task.ps1 +71 -71
- package/scenarios/conductor-recruit-mock.yaml +33 -33
- package/scenarios/echo-roundtrip.yaml +15 -15
- package/scenarios/multi-player-handoff.yaml +38 -38
- package/scenarios/recruit-cascade.yaml +38 -38
- package/scenarios/two-player-conversation.yaml +33 -33
- package/workflow-bundle.js +97 -6
- package/dashboard/dist/assets/index-D6Xyje_n.js.map +0 -1
- package/dist/activities/claude-stop.d.ts +0 -21
- package/dist/activities/claude-stop.js +0 -94
- package/dist/channel.d.ts +0 -3
- package/dist/channel.js +0 -48
- package/dist/copilot-bridge.d.ts +0 -22
- package/dist/copilot-bridge.js +0 -565
- package/dist/scripts/258-spotcheck.js +0 -303
- package/dist/tools/detach.d.ts +0 -4
- package/dist/tools/detach.js +0 -45
- package/dist/tools/encore.d.ts +0 -4
- package/dist/tools/encore.js +0 -31
- package/dist/tools/helpers.d.ts +0 -21
- package/dist/tools/helpers.js +0 -25
- package/dist/tools/pause-ensemble.d.ts +0 -4
- package/dist/tools/pause-ensemble.js +0 -58
- package/dist/tools/resume-ensemble.d.ts +0 -4
- package/dist/tools/resume-ensemble.js +0 -79
- package/dist/tools/stop.d.ts +0 -4
- package/dist/tools/stop.js +0 -29
- package/dist/tui/client.d.ts +0 -6
- package/dist/tui/client.js +0 -9
- package/dist/tui/components/ActivityLog.d.ts +0 -16
- package/dist/tui/components/ActivityLog.js +0 -36
- package/dist/tui/components/CommandOverlay.d.ts +0 -15
- package/dist/tui/components/CommandOverlay.js +0 -34
- package/dist/tui/components/ConductorChat.d.ts +0 -16
- package/dist/tui/components/ConductorChat.js +0 -32
- package/dist/tui/components/EnsembleListView.d.ts +0 -14
- package/dist/tui/components/EnsembleListView.js +0 -32
- package/dist/tui/components/EnsemblePanel.d.ts +0 -12
- package/dist/tui/components/EnsemblePanel.js +0 -40
- package/dist/tui/components/InputBar.d.ts +0 -13
- package/dist/tui/components/InputBar.js +0 -58
- package/dist/tui/components/ScheduleOverlay.d.ts +0 -13
- package/dist/tui/components/ScheduleOverlay.js +0 -113
- package/dist/tui/components/TopBar.d.ts +0 -12
- package/dist/tui/components/TopBar.js +0 -15
- package/dist/tui/core-api.d.ts +0 -26
- package/dist/tui/core-api.js +0 -67
- package/dist/tui/hooks/useEnsembleDiscovery.d.ts +0 -3
- package/dist/tui/hooks/useEnsembleDiscovery.js +0 -30
- package/dist/tui/hooks/useMaestroPoller.d.ts +0 -3
- package/dist/tui/hooks/useMaestroPoller.js +0 -36
- package/dist/tui/hooks/useSendCommand.d.ts +0 -7
- package/dist/tui/hooks/useSendCommand.js +0 -29
- package/dist/utils/bg-preflight.d.ts +0 -25
- package/dist/utils/bg-preflight.js +0 -154
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
1
|
import { Client } from '@temporalio/client';
|
|
3
2
|
import { Config } from '../config';
|
|
4
|
-
|
|
3
|
+
import { type TempoToolDescriptor } from './descriptor';
|
|
4
|
+
export declare function buildCoatCheckGetTool(client: Client, config: Config, getPlayerId: () => string): TempoToolDescriptor;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.buildCoatCheckGetTool = buildCoatCheckGetTool;
|
|
4
4
|
/**
|
|
5
5
|
* `coat_check_get` — redeem a coat-check ticket and pull the stashed content
|
|
6
6
|
* (#318, ADR 0008). Returns the entry's summary, content body, and audit
|
|
@@ -18,39 +18,44 @@ exports.registerCoatCheckGetTool = registerCoatCheckGetTool;
|
|
|
18
18
|
const zod_1 = require("zod");
|
|
19
19
|
const config_1 = require("../config");
|
|
20
20
|
const maestro_signals_1 = require("../workflows/maestro-signals");
|
|
21
|
-
const
|
|
21
|
+
const descriptor_1 = require("./descriptor");
|
|
22
22
|
const validation_1 = require("../utils/validation");
|
|
23
|
-
function
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
23
|
+
function buildCoatCheckGetTool(client, config, getPlayerId) {
|
|
24
|
+
return {
|
|
25
|
+
name: 'coat_check_get',
|
|
26
|
+
description: `Redeem a coat-check ticket (#318) and pull the stashed content. Returns the entry's summary, content body, and audit info — or "not found" when the ticket is missing / expired / evicted (no error, just empty).
|
|
27
|
+
|
|
28
|
+
Successful redemptions bump the entry's fetch-audit counters (\`lastFetchedAt\` / \`lastFetchedBy\` / \`fetchCount\`) so the putter can later see whether anyone has redeemed. \`coat_check_list\` won't bump these — only an actual redemption counts.`,
|
|
29
|
+
params: {
|
|
30
|
+
ticket: zod_1.z.string().regex(validation_1.COAT_CHECK_TICKET_REGEX).max(validation_1.COAT_CHECK_TICKET_MAX).describe(`The ticket id returned by an earlier \`coat_check_put\` (≤${validation_1.COAT_CHECK_TICKET_MAX} chars).`),
|
|
31
|
+
},
|
|
32
|
+
handler: async (args) => {
|
|
33
|
+
const { ticket } = args;
|
|
34
|
+
const fetchedBy = getPlayerId();
|
|
35
|
+
try {
|
|
36
|
+
const handle = client.workflow.getHandle((0, config_1.maestroWorkflowId)(config.ensemble));
|
|
37
|
+
const entry = await handle.executeUpdate(maestro_signals_1.coatCheckGetUpdate, {
|
|
38
|
+
args: [{ ticket, fetchedBy }],
|
|
39
|
+
});
|
|
40
|
+
if (!entry) {
|
|
41
|
+
return (0, descriptor_1.ok)(`Ticket **${ticket}** is not found (missing, expired, or evicted).`);
|
|
42
|
+
}
|
|
43
|
+
const lines = [
|
|
44
|
+
`**Ticket ${ticket}** — stashed by ${entry.putBy} at ${entry.putAt}, expires ${entry.expiresAt}`,
|
|
45
|
+
`Summary: ${entry.summary}`,
|
|
46
|
+
];
|
|
47
|
+
if (entry.contentType)
|
|
48
|
+
lines.push(`Content-Type: ${entry.contentType}`);
|
|
49
|
+
lines.push(`Size: ${entry.size} bytes`);
|
|
50
|
+
lines.push(`Fetches: ${entry.fetchCount}${entry.lastFetchedBy ? ` (last by ${entry.lastFetchedBy} at ${entry.lastFetchedAt})` : ''}`);
|
|
51
|
+
lines.push('');
|
|
52
|
+
lines.push('---');
|
|
53
|
+
lines.push(entry.content);
|
|
54
|
+
return (0, descriptor_1.ok)(lines.join('\n'));
|
|
38
55
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
lines.push(`Content-Type: ${entry.contentType}`);
|
|
45
|
-
lines.push(`Size: ${entry.size} bytes`);
|
|
46
|
-
lines.push(`Fetches: ${entry.fetchCount}${entry.lastFetchedBy ? ` (last by ${entry.lastFetchedBy} at ${entry.lastFetchedAt})` : ''}`);
|
|
47
|
-
lines.push('');
|
|
48
|
-
lines.push('---');
|
|
49
|
-
lines.push(entry.content);
|
|
50
|
-
return (0, helpers_1.ok)(lines.join('\n'));
|
|
51
|
-
}
|
|
52
|
-
catch (err) {
|
|
53
|
-
return (0, helpers_1.fail)(`Failed to redeem ticket: ${(0, helpers_1.formatError)(err)}`);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
+
catch (err) {
|
|
57
|
+
return (0, descriptor_1.fail)(`Failed to redeem ticket: ${(0, descriptor_1.formatError)(err)}`);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
};
|
|
56
61
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
1
|
import { Client } from '@temporalio/client';
|
|
3
2
|
import { Config } from '../config';
|
|
4
|
-
|
|
3
|
+
import { type TempoToolDescriptor } from './descriptor';
|
|
4
|
+
export declare function buildCoatCheckListTool(client: Client, config: Config): TempoToolDescriptor;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.buildCoatCheckListTool = buildCoatCheckListTool;
|
|
4
4
|
/**
|
|
5
5
|
* `coat_check_list` — list coat-check entry headers (#318, ADR 0008) for
|
|
6
6
|
* the calling player's ensemble. Read-only — does NOT bump fetch-audit
|
|
@@ -12,49 +12,54 @@ exports.registerCoatCheckListTool = registerCoatCheckListTool;
|
|
|
12
12
|
const zod_1 = require("zod");
|
|
13
13
|
const config_1 = require("../config");
|
|
14
14
|
const maestro_signals_1 = require("../workflows/maestro-signals");
|
|
15
|
-
const
|
|
15
|
+
const descriptor_1 = require("./descriptor");
|
|
16
16
|
const validation_1 = require("../utils/validation");
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (
|
|
37
|
-
filters
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
17
|
+
function buildCoatCheckListTool(client, config) {
|
|
18
|
+
return {
|
|
19
|
+
name: 'coat_check_list',
|
|
20
|
+
description: `List coat-check entries (#318) for this ensemble. Read-only — does NOT bump fetch-audit counters; only \`coat_check_get\` does. Sorted newest-first. Pass \`unfetchedOnly: true\` to surface entries nobody has redeemed yet — useful for an owner cleaning up stale stashes.`,
|
|
21
|
+
params: {
|
|
22
|
+
putBy: zod_1.z.string().max(validation_1.PLAYER_NAME_MAX).optional().describe('Optional filter — only entries stashed by this player.'),
|
|
23
|
+
prefix: zod_1.z.string().max(validation_1.COAT_CHECK_SUMMARY_MAX).optional().describe('Optional summary-prefix filter — narrows the listing to entries whose summary starts with this string.'),
|
|
24
|
+
unfetchedOnly: zod_1.z.boolean().optional().describe('When true, only return entries with fetchCount=0 (never redeemed). Default false.'),
|
|
25
|
+
},
|
|
26
|
+
handler: async (args) => {
|
|
27
|
+
const { putBy, prefix, unfetchedOnly } = args;
|
|
28
|
+
try {
|
|
29
|
+
const handle = client.workflow.getHandle((0, config_1.maestroWorkflowId)(config.ensemble));
|
|
30
|
+
const filter = {
|
|
31
|
+
...(putBy !== undefined ? { putBy } : {}),
|
|
32
|
+
...(prefix !== undefined ? { prefix } : {}),
|
|
33
|
+
...(unfetchedOnly !== undefined ? { unfetchedOnly } : {}),
|
|
34
|
+
};
|
|
35
|
+
const headers = await handle.query(maestro_signals_1.coatCheckListQuery, filter);
|
|
36
|
+
if (headers.length === 0) {
|
|
37
|
+
const filters = [];
|
|
38
|
+
if (putBy)
|
|
39
|
+
filters.push(`putBy="${putBy}"`);
|
|
40
|
+
if (prefix)
|
|
41
|
+
filters.push(`prefix="${prefix}"`);
|
|
42
|
+
if (unfetchedOnly)
|
|
43
|
+
filters.push('unfetchedOnly=true');
|
|
44
|
+
const suffix = filters.length > 0 ? ` (filter: ${filters.join(', ')})` : '';
|
|
45
|
+
return (0, descriptor_1.ok)(`No coat-check entries in this ensemble${suffix}.`);
|
|
46
|
+
}
|
|
47
|
+
const lines = [];
|
|
48
|
+
lines.push(`${headers.length}/${validation_1.COAT_CHECK_SLOTS_MAX} coat-check ${headers.length === 1 ? 'entry' : 'entries'}:`);
|
|
49
|
+
lines.push('');
|
|
50
|
+
for (const h of headers) {
|
|
51
|
+
const fetchTag = h.fetchCount === 0
|
|
52
|
+
? ' (unfetched)'
|
|
53
|
+
: ` (fetched ${h.fetchCount}× by ${h.lastFetchedBy ?? '(unknown)'} at ${h.lastFetchedAt ?? '(unknown)'})`;
|
|
54
|
+
const typeTag = h.contentType ? ` [${h.contentType}]` : '';
|
|
55
|
+
lines.push(`- **${h.ticket}** ${typeTag}— ${h.summary}`);
|
|
56
|
+
lines.push(` putBy=${h.putBy} · putAt=${h.putAt} · expires=${h.expiresAt} · ${h.size} bytes${fetchTag}`);
|
|
57
|
+
}
|
|
58
|
+
return (0, descriptor_1.ok)(lines.join('\n'));
|
|
42
59
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
lines.push('');
|
|
46
|
-
for (const h of headers) {
|
|
47
|
-
const fetchTag = h.fetchCount === 0
|
|
48
|
-
? ' (unfetched)'
|
|
49
|
-
: ` (fetched ${h.fetchCount}× by ${h.lastFetchedBy ?? '(unknown)'} at ${h.lastFetchedAt ?? '(unknown)'})`;
|
|
50
|
-
const typeTag = h.contentType ? ` [${h.contentType}]` : '';
|
|
51
|
-
lines.push(`- **${h.ticket}** ${typeTag}— ${h.summary}`);
|
|
52
|
-
lines.push(` putBy=${h.putBy} · putAt=${h.putAt} · expires=${h.expiresAt} · ${h.size} bytes${fetchTag}`);
|
|
60
|
+
catch (err) {
|
|
61
|
+
return (0, descriptor_1.fail)(`Failed to list coat-check entries: ${(0, descriptor_1.formatError)(err)}`);
|
|
53
62
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
catch (err) {
|
|
57
|
-
return (0, helpers_1.fail)(`Failed to list coat-check entries: ${(0, helpers_1.formatError)(err)}`);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
63
|
+
},
|
|
64
|
+
};
|
|
60
65
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
1
|
import { Client } from '@temporalio/client';
|
|
3
2
|
import { Config } from '../config';
|
|
4
|
-
|
|
3
|
+
import { type TempoToolDescriptor } from './descriptor';
|
|
4
|
+
export declare function buildCoatCheckPutTool(client: Client, config: Config, getPlayerId: () => string): TempoToolDescriptor;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.buildCoatCheckPutTool = buildCoatCheckPutTool;
|
|
4
4
|
/**
|
|
5
5
|
* `coat_check_put` — stash a large content body on per-ensemble Maestro state
|
|
6
6
|
* (#318, ADR 0008). Returns a ticket id that any player in the ensemble can
|
|
@@ -14,40 +14,45 @@ exports.registerCoatCheckPutTool = registerCoatCheckPutTool;
|
|
|
14
14
|
const zod_1 = require("zod");
|
|
15
15
|
const config_1 = require("../config");
|
|
16
16
|
const maestro_signals_1 = require("../workflows/maestro-signals");
|
|
17
|
-
const
|
|
17
|
+
const descriptor_1 = require("./descriptor");
|
|
18
18
|
const validation_1 = require("../utils/validation");
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
19
|
+
function buildCoatCheckPutTool(client, config, getPlayerId) {
|
|
20
|
+
return {
|
|
21
|
+
name: 'coat_check_put',
|
|
22
|
+
description: `Stash a large content body on this ensemble's coat-check (#318). Returns a ticket id any player can redeem later via \`coat_check_get\`. Pass the ticket on a \`cue\`'s \`attachmentTicket\` field so the recipient knows what to fetch.
|
|
23
|
+
|
|
24
|
+
Use this when your message body would otherwise exceed the cue's 100 KB cap — researcher reports, review-item dumps, etc. The cue body should carry a short summary; the coat-check entry holds the full artifact.
|
|
25
|
+
|
|
26
|
+
Limits: ${validation_1.COAT_CHECK_CONTENT_MAX} bytes (UTF-8) per entry, max ${validation_1.COAT_CHECK_SLOTS_MAX} live entries per ensemble. Saturation rejects with \`CoatCheckSlotsFull\` — wait for TTL or \`coat_check_evict\` an entry you own. TTL defaults to 7 days (configurable per put within [1h, 30d]).`,
|
|
27
|
+
params: {
|
|
28
|
+
summary: zod_1.z.string().min(1).max(validation_1.COAT_CHECK_SUMMARY_MAX).describe(`Short preamble surfaced in \`coat_check_list\` and on dashboards (≤${validation_1.COAT_CHECK_SUMMARY_MAX} chars). 1-2 sentences describing what the recipient gets if they redeem.`),
|
|
29
|
+
content: zod_1.z.string().min(1).max(validation_1.COAT_CHECK_CONTENT_MAX).describe(`The full content body — markdown encouraged, opaque to the system. Max ${validation_1.COAT_CHECK_CONTENT_MAX} bytes (UTF-8).`),
|
|
30
|
+
contentType: zod_1.z.string().max(validation_1.COAT_CHECK_CONTENT_TYPE_MAX).optional().describe(`Optional MIME-shaped hint (e.g. "text/markdown"). Free-form; ≤${validation_1.COAT_CHECK_CONTENT_TYPE_MAX} chars.`),
|
|
31
|
+
ttlMs: zod_1.z.number().int().min(validation_1.COAT_CHECK_TTL_MIN_MS).max(validation_1.COAT_CHECK_TTL_MAX_MS).optional().describe(`Time-to-live in milliseconds. Default ${validation_1.COAT_CHECK_TTL_DEFAULT_MS} (7 days). Range [${validation_1.COAT_CHECK_TTL_MIN_MS}, ${validation_1.COAT_CHECK_TTL_MAX_MS}] (1h to 30d).`),
|
|
32
|
+
},
|
|
33
|
+
handler: async (args) => {
|
|
34
|
+
const { summary, content, contentType, ttlMs } = args;
|
|
35
|
+
const putBy = getPlayerId();
|
|
36
|
+
try {
|
|
37
|
+
const handle = client.workflow.getHandle((0, config_1.maestroWorkflowId)(config.ensemble));
|
|
38
|
+
const result = await handle.executeUpdate(maestro_signals_1.coatCheckPutUpdate, {
|
|
39
|
+
args: [{
|
|
40
|
+
summary,
|
|
41
|
+
content,
|
|
42
|
+
...(contentType !== undefined ? { contentType } : {}),
|
|
43
|
+
...(ttlMs !== undefined ? { ttlMs } : {}),
|
|
44
|
+
putBy,
|
|
45
|
+
}],
|
|
46
|
+
});
|
|
47
|
+
return (0, descriptor_1.ok)(`Stashed as ticket **${result.ticket}** (expires ${result.expiresAt}). Slots: ${result.slotsUsed}/${result.slotsTotal}.`);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
// The workflow validator surfaces structured ApplicationFailure
|
|
51
|
+
// errors (`CoatCheckSlotsFull`, `CoatCheckEntryTooLarge`, …). The
|
|
52
|
+
// `formatError` message preserves the workflow text so the LLM
|
|
53
|
+
// sees the oldest-3 ticket list and can pick which to evict.
|
|
54
|
+
return (0, descriptor_1.fail)(`Failed to stash content: ${(0, descriptor_1.formatError)(err)}`);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
};
|
|
53
58
|
}
|
package/dist/tools/cue.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
1
|
import { Client, WorkflowHandle } from '@temporalio/client';
|
|
3
2
|
import { Config } from '../config';
|
|
4
3
|
import type { AttachmentPhase } from '../types';
|
|
4
|
+
import { type TempoToolDescriptor } from './descriptor';
|
|
5
5
|
/**
|
|
6
6
|
* Build the operator-facing error message when the cue target is in an
|
|
7
7
|
* undeliverable phase. Lists three actionable next steps per the issue
|
|
@@ -10,7 +10,7 @@ import type { AttachmentPhase } from '../types';
|
|
|
10
10
|
* Exported for unit testing.
|
|
11
11
|
*/
|
|
12
12
|
export declare function formatDetachedDeliveryError(playerId: string, phase: AttachmentPhase): string;
|
|
13
|
-
export declare function
|
|
13
|
+
export declare function buildCueTool(client: Client, config: Config, getPlayerId: () => string, handle: WorkflowHandle): TempoToolDescriptor;
|
|
14
14
|
/**
|
|
15
15
|
* Format the cue tool's "unknown player" error with actionable suggestions.
|
|
16
16
|
* Exported for direct unit testing — the production path passes the active
|
package/dist/tools/cue.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.formatDetachedDeliveryError = formatDetachedDeliveryError;
|
|
4
|
-
exports.
|
|
4
|
+
exports.buildCueTool = buildCueTool;
|
|
5
5
|
exports.formatUnknownPlayerError = formatUnknownPlayerError;
|
|
6
6
|
exports.findClosestPlayers = findClosestPlayers;
|
|
7
7
|
exports.levenshtein = levenshtein;
|
|
@@ -10,7 +10,7 @@ const resolve_1 = require("./resolve");
|
|
|
10
10
|
const resolve_2 = require("../activities/resolve");
|
|
11
11
|
const signals_1 = require("../workflows/signals");
|
|
12
12
|
const query_timeout_1 = require("../utils/query-timeout");
|
|
13
|
-
const
|
|
13
|
+
const descriptor_1 = require("./descriptor");
|
|
14
14
|
const validation_1 = require("../utils/validation");
|
|
15
15
|
/**
|
|
16
16
|
* Max Levenshtein distance for a fuzzy-match candidate to surface in the
|
|
@@ -55,60 +55,65 @@ function formatDetachedDeliveryError(playerId, phase) {
|
|
|
55
55
|
`(2) 'restart' to re-attach the session and retry the cue, ` +
|
|
56
56
|
`(3) the workflow inbox queues the signal and auto-delivers on re-attach.`);
|
|
57
57
|
}
|
|
58
|
-
function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
// actionable error — active-player list + fuzzy-match suggestion
|
|
73
|
-
// + Agent-tool surface hint. We pay the extra `scanEnsembleSessions`
|
|
74
|
-
// round-trip ONLY on the error path, so the success path is
|
|
75
|
-
// unchanged.
|
|
76
|
-
const sessions = await (0, resolve_2.scanEnsembleSessions)(client, config.ensemble);
|
|
77
|
-
const activePlayers = sessions.map((s) => s.playerId).sort();
|
|
78
|
-
return (0, helpers_1.fail)(formatUnknownPlayerError(playerId, activePlayers));
|
|
79
|
-
}
|
|
80
|
-
// #562: phase pre-flight. Resolves the gap where `cue` to a
|
|
81
|
-
// detached/gone player returns "Message sent" — wire-truthful (the
|
|
82
|
-
// signal IS delivered to the workflow inbox), but operator-
|
|
83
|
-
// misleading because no live adapter surfaces the message.
|
|
84
|
-
let phase;
|
|
58
|
+
function buildCueTool(client, config, getPlayerId, handle) {
|
|
59
|
+
return {
|
|
60
|
+
name: 'cue',
|
|
61
|
+
description: 'Send a message to another Claude Code session by player name. Delivered instantly via Temporal signal. For content larger than ~100 KB, use `coat_check_put` to stash the body and pass the returned ticket via `attachmentTicket` — the cue body itself should carry a short summary the recipient can act on without fetching.',
|
|
62
|
+
params: {
|
|
63
|
+
playerId: zod_1.z.string().max(validation_1.PLAYER_NAME_MAX).describe('The player name of the target session'),
|
|
64
|
+
message: zod_1.z.string().max(validation_1.MESSAGE_MAX).describe('The message to send'),
|
|
65
|
+
attachmentTicket: zod_1.z.string().regex(validation_1.COAT_CHECK_TICKET_REGEX).max(validation_1.COAT_CHECK_TICKET_MAX).optional().describe('Optional coat-check ticket (#318). Reference content stashed via `coat_check_put`; the receiver sees the ticket on their `recall` message and can pull the body via `coat_check_get`. Backward-compatible — omit for normal cues.'),
|
|
66
|
+
},
|
|
67
|
+
handler: async (args) => {
|
|
68
|
+
const { playerId, message, attachmentTicket } = args;
|
|
69
|
+
const nameError = (0, validation_1.validatePlayerName)(playerId);
|
|
70
|
+
if (nameError)
|
|
71
|
+
return (0, descriptor_1.fail)(nameError);
|
|
85
72
|
try {
|
|
86
|
-
const
|
|
87
|
-
|
|
73
|
+
const resolved = await (0, resolve_1.resolveSession)(client, config.ensemble, playerId);
|
|
74
|
+
if (!resolved) {
|
|
75
|
+
// #560: replace the generic "no active session found" with an
|
|
76
|
+
// actionable error — active-player list + fuzzy-match suggestion
|
|
77
|
+
// + Agent-tool surface hint. We pay the extra `scanEnsembleSessions`
|
|
78
|
+
// round-trip ONLY on the error path, so the success path is
|
|
79
|
+
// unchanged.
|
|
80
|
+
const sessions = await (0, resolve_2.scanEnsembleSessions)(client, config.ensemble);
|
|
81
|
+
const activePlayers = sessions.map((s) => s.playerId).sort();
|
|
82
|
+
return (0, descriptor_1.fail)(formatUnknownPlayerError(playerId, activePlayers));
|
|
83
|
+
}
|
|
84
|
+
// #562: phase pre-flight. Resolves the gap where `cue` to a
|
|
85
|
+
// detached/gone player returns "Message sent" — wire-truthful (the
|
|
86
|
+
// signal IS delivered to the workflow inbox), but operator-
|
|
87
|
+
// misleading because no live adapter surfaces the message.
|
|
88
|
+
let phase;
|
|
89
|
+
try {
|
|
90
|
+
const info = await (0, query_timeout_1.queryHandleWithTimeout)(resolved, signals_1.attachmentInfoQuery, { timeoutMs: CUE_PHASE_PREFLIGHT_TIMEOUT_MS });
|
|
91
|
+
phase = info.phase;
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
// Query timed out or threw — workflow may be wedged. Don't
|
|
95
|
+
// penalize the operator: fall through to best-effort submit.
|
|
96
|
+
// Auto-redelivery on re-attach still applies. Stderr log keeps
|
|
97
|
+
// the observability trail without surfacing noise to the user.
|
|
98
|
+
console.error(`[agent-tempo:cue] phase pre-flight failed for "${playerId}" — proceeding best-effort:`, err instanceof Error ? err.message : err);
|
|
99
|
+
}
|
|
100
|
+
if (phase && UNDELIVERABLE_PHASES.has(phase)) {
|
|
101
|
+
return (0, descriptor_1.fail)(formatDetachedDeliveryError(playerId, phase));
|
|
102
|
+
}
|
|
103
|
+
const entry = {
|
|
104
|
+
type: 'cue',
|
|
105
|
+
targetPlayerId: playerId,
|
|
106
|
+
message,
|
|
107
|
+
...(attachmentTicket !== undefined ? { attachmentTicket } : {}),
|
|
108
|
+
};
|
|
109
|
+
const entryId = await handle.executeUpdate(signals_1.submitOutboxUpdate, { args: [entry] });
|
|
110
|
+
return (0, descriptor_1.ok)(`Message sent to ${playerId}. (outbox: ${entryId})`);
|
|
88
111
|
}
|
|
89
112
|
catch (err) {
|
|
90
|
-
|
|
91
|
-
// penalize the operator: fall through to best-effort submit.
|
|
92
|
-
// Auto-redelivery on re-attach still applies. Stderr log keeps
|
|
93
|
-
// the observability trail without surfacing noise to the user.
|
|
94
|
-
console.error(`[agent-tempo:cue] phase pre-flight failed for "${playerId}" — proceeding best-effort:`, err instanceof Error ? err.message : err);
|
|
95
|
-
}
|
|
96
|
-
if (phase && UNDELIVERABLE_PHASES.has(phase)) {
|
|
97
|
-
return (0, helpers_1.fail)(formatDetachedDeliveryError(playerId, phase));
|
|
113
|
+
return (0, descriptor_1.fail)(`Failed to send message to ${playerId}: ${(0, descriptor_1.formatError)(err)}`);
|
|
98
114
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
targetPlayerId: playerId,
|
|
102
|
-
message,
|
|
103
|
-
...(attachmentTicket !== undefined ? { attachmentTicket } : {}),
|
|
104
|
-
};
|
|
105
|
-
const entryId = await handle.executeUpdate(signals_1.submitOutboxUpdate, { args: [entry] });
|
|
106
|
-
return (0, helpers_1.ok)(`Message sent to ${playerId}. (outbox: ${entryId})`);
|
|
107
|
-
}
|
|
108
|
-
catch (err) {
|
|
109
|
-
return (0, helpers_1.fail)(`Failed to send message to ${playerId}: ${(0, helpers_1.formatError)(err)}`);
|
|
110
|
-
}
|
|
111
|
-
});
|
|
115
|
+
},
|
|
116
|
+
};
|
|
112
117
|
}
|
|
113
118
|
/**
|
|
114
119
|
* Format the cue tool's "unknown player" error with actionable suggestions.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport-neutral tool descriptor (MD-B seam, Phase 1).
|
|
3
|
+
*
|
|
4
|
+
* agent-tempo tools used to be defined directly against an `McpServer`
|
|
5
|
+
* (`defineTool` → `server.tool(...)`). MD-B splits that into:
|
|
6
|
+
*
|
|
7
|
+
* 1. A neutral **descriptor** — `{ name, description, params, handler }` —
|
|
8
|
+
* with NO MCP or Pi coupling. zod is the single source of truth for
|
|
9
|
+
* params; the handler returns neutral `{ text, isError? }`.
|
|
10
|
+
* 2. Per-front-end **renderers** — `renderToMcp` (here) and `renderToPi`
|
|
11
|
+
* (`src/pi/render-tools.ts`). MCP consumes the zod shape raw; Pi derives
|
|
12
|
+
* a TypeBox schema from it. No dual-define, no drift.
|
|
13
|
+
*
|
|
14
|
+
* Backward-compat is load-bearing: `renderToMcp` reproduces the EXACT output
|
|
15
|
+
* of the old `defineTool` so `src/server.ts` and the claude-api in-process MCP
|
|
16
|
+
* bridge keep byte-identical behavior. `registerAllTempoTools` stays a thin
|
|
17
|
+
* wrapper over `renderToMcp(server, buildAllTempoTools(opts))` — its callers
|
|
18
|
+
* never change.
|
|
19
|
+
*
|
|
20
|
+
* Determinism note: this module is client-side (src/tools). `src/pi/` imports
|
|
21
|
+
* the descriptor type FROM here; this module never imports `src/pi/`.
|
|
22
|
+
*
|
|
23
|
+
* Design reference: architect's MD-B implementation spec (Phase 1).
|
|
24
|
+
*/
|
|
25
|
+
import type { z } from 'zod';
|
|
26
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
27
|
+
/**
|
|
28
|
+
* Neutral tool result. Every current tool returns a single text block via
|
|
29
|
+
* `ok()` / `fail()`. Richer multi-block / structured output is an ADDITIVE
|
|
30
|
+
* future extension (e.g. an optional `data?`) — intentionally not modeled now.
|
|
31
|
+
*/
|
|
32
|
+
export interface TempoToolResult {
|
|
33
|
+
text: string;
|
|
34
|
+
isError?: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A transport-neutral tool definition. Each tool module exports a
|
|
38
|
+
* `build<X>Tool(...deps): TempoToolDescriptor` factory that closes over its
|
|
39
|
+
* existing dependencies (client, config, handle, getPlayerId, …) exactly as
|
|
40
|
+
* the old `register<X>Tool` did.
|
|
41
|
+
*/
|
|
42
|
+
export interface TempoToolDescriptor {
|
|
43
|
+
name: string;
|
|
44
|
+
description: string;
|
|
45
|
+
/**
|
|
46
|
+
* zod is the SINGLE SOURCE OF TRUTH for parameters. The MCP renderer passes
|
|
47
|
+
* this shape straight to `server.tool`; the Pi renderer derives a TypeBox
|
|
48
|
+
* schema from it via the zod→TypeBox converter. `z.ZodRawShape` is
|
|
49
|
+
* `Record<string, z.ZodTypeAny>` — the same shape `defineTool` accepted.
|
|
50
|
+
*/
|
|
51
|
+
params: z.ZodRawShape;
|
|
52
|
+
/** Neutral handler. No MCP `extra` param (zero tools use it). */
|
|
53
|
+
handler: (args: Record<string, unknown>) => Promise<TempoToolResult>;
|
|
54
|
+
}
|
|
55
|
+
/** Return a successful tool result. (Neutral replacement for the old MCP `ok`.) */
|
|
56
|
+
export declare function ok(text: string): TempoToolResult;
|
|
57
|
+
/** Return an error tool result. (Neutral replacement for the old MCP `fail`.) */
|
|
58
|
+
export declare function fail(text: string): TempoToolResult;
|
|
59
|
+
/** Extract a human-readable message from an unknown error. */
|
|
60
|
+
export declare function formatError(err: unknown): string;
|
|
61
|
+
/**
|
|
62
|
+
* Render descriptors onto an MCP server — the backward-compatible path.
|
|
63
|
+
*
|
|
64
|
+
* Reproduces the old `defineTool` EXACTLY (see the removed `helpers.ts`):
|
|
65
|
+
* - `(server.tool as Function)(name, description, paramsSchema, handler)` —
|
|
66
|
+
* the `as Function` cast is the TS2589 deep-instantiation workaround for
|
|
67
|
+
* Zod 3.25 + MCP SDK type inference; preserve it.
|
|
68
|
+
* - The handler wraps the neutral `{ text, isError? }` back into MCP's
|
|
69
|
+
* `{ content: [{ type: 'text', text }], isError? }` — byte-identical to
|
|
70
|
+
* what `ok()` / `fail()` produced before MD-B.
|
|
71
|
+
*/
|
|
72
|
+
export declare function renderToMcp(server: McpServer, descriptors: TempoToolDescriptor[]): void;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ok = ok;
|
|
4
|
+
exports.fail = fail;
|
|
5
|
+
exports.formatError = formatError;
|
|
6
|
+
exports.renderToMcp = renderToMcp;
|
|
7
|
+
/** Return a successful tool result. (Neutral replacement for the old MCP `ok`.) */
|
|
8
|
+
function ok(text) {
|
|
9
|
+
return { text };
|
|
10
|
+
}
|
|
11
|
+
/** Return an error tool result. (Neutral replacement for the old MCP `fail`.) */
|
|
12
|
+
function fail(text) {
|
|
13
|
+
return { text, isError: true };
|
|
14
|
+
}
|
|
15
|
+
/** Extract a human-readable message from an unknown error. */
|
|
16
|
+
function formatError(err) {
|
|
17
|
+
return err instanceof Error ? err.message : String(err);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Render descriptors onto an MCP server — the backward-compatible path.
|
|
21
|
+
*
|
|
22
|
+
* Reproduces the old `defineTool` EXACTLY (see the removed `helpers.ts`):
|
|
23
|
+
* - `(server.tool as Function)(name, description, paramsSchema, handler)` —
|
|
24
|
+
* the `as Function` cast is the TS2589 deep-instantiation workaround for
|
|
25
|
+
* Zod 3.25 + MCP SDK type inference; preserve it.
|
|
26
|
+
* - The handler wraps the neutral `{ text, isError? }` back into MCP's
|
|
27
|
+
* `{ content: [{ type: 'text', text }], isError? }` — byte-identical to
|
|
28
|
+
* what `ok()` / `fail()` produced before MD-B.
|
|
29
|
+
*/
|
|
30
|
+
function renderToMcp(server, descriptors) {
|
|
31
|
+
for (const d of descriptors) {
|
|
32
|
+
server.tool(d.name, d.description, d.params, async (args) => {
|
|
33
|
+
const r = await d.handler(args);
|
|
34
|
+
return r.isError
|
|
35
|
+
? { content: [{ type: 'text', text: r.text }], isError: true }
|
|
36
|
+
: { content: [{ type: 'text', text: r.text }] };
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
package/dist/tools/destroy.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
1
|
import { Client, WorkflowHandle } from '@temporalio/client';
|
|
3
2
|
import { Config } from '../config';
|
|
4
|
-
|
|
3
|
+
import { type TempoToolDescriptor } from './descriptor';
|
|
4
|
+
export declare function buildDestroyTool(client: Client, config: Config, getPlayerId: () => string, handle: WorkflowHandle): TempoToolDescriptor;
|