claude-tempo 0.3.0-beta.1 → 0.3.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -25
- package/dist/cli/config-command.js +16 -12
- package/dist/config.d.ts +10 -0
- package/dist/config.js +45 -0
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -4,31 +4,7 @@ Multi-session [Claude Code](https://claude.ai/code) coordination via [Temporal](
|
|
|
4
4
|
|
|
5
5
|
Multiple Claude Code sessions discover each other, exchange messages in real time, and coordinate work — across machines, not just localhost.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
You (CLI / Discord / Telegram / Claude Code)
|
|
9
|
-
│
|
|
10
|
-
▼
|
|
11
|
-
┌─────────────────────────────────────────────┐
|
|
12
|
-
│ Temporal Server │
|
|
13
|
-
│ │
|
|
14
|
-
│ ┌───────────┐ │
|
|
15
|
-
│ │ Conductor │──cue──┬──────┬──────┐ │
|
|
16
|
-
│ └───────────┘ │ │ │ │
|
|
17
|
-
│ ▼ ▼ ▼ │
|
|
18
|
-
│ ┌────┐ ┌────┐ ┌────┐ │
|
|
19
|
-
│ │ A │ │ B │ │ C │ │
|
|
20
|
-
│ └──┬─┘ └──┬─┘ └──┬─┘ │
|
|
21
|
-
│ │ │ │ │
|
|
22
|
-
└──────────────────────┼──────┼──────┼────────┘
|
|
23
|
-
│ │ │
|
|
24
|
-
┌────────┘ │ └────────┐
|
|
25
|
-
▼ ▼ ▼
|
|
26
|
-
┌─────────┐ ┌─────────┐ ┌─────────┐
|
|
27
|
-
│ Host 1 │ │ Host 1 │ │ Host 2 │
|
|
28
|
-
│ Claude │ │ Claude │ │ Claude │
|
|
29
|
-
│ Session │ │ Session │ │ Session │
|
|
30
|
-
└─────────┘ └─────────┘ └─────────┘
|
|
31
|
-
```
|
|
7
|
+
Each Claude Code session registers as a **player** in Temporal. Players discover each other with `ensemble`, exchange messages with `cue`, and coordinate work — across machines, not just localhost. An optional **conductor** orchestrates the group and connects to external interfaces like Discord, Telegram, or a dashboard.
|
|
32
8
|
|
|
33
9
|
## Installation
|
|
34
10
|
|
|
@@ -42,6 +42,7 @@ const config_1 = require("../config");
|
|
|
42
42
|
const connection_1 = require("../connection");
|
|
43
43
|
const config_2 = require("../config");
|
|
44
44
|
const out = __importStar(require("./output"));
|
|
45
|
+
const SECRET_KEYS = new Set(['temporalApiKey']);
|
|
45
46
|
/** Read a line from stdin with a prompt and optional default value. */
|
|
46
47
|
function ask(prompt, defaultVal, mask = false) {
|
|
47
48
|
return new Promise((resolve) => {
|
|
@@ -178,21 +179,24 @@ function configSet(key, value) {
|
|
|
178
179
|
/** Show current config: `claude-tempo config show` */
|
|
179
180
|
function configShow() {
|
|
180
181
|
out.heading('claude-tempo config');
|
|
181
|
-
const config = (0, config_1.
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
['temporalTlsKeyPath', resolved.temporalTlsKeyPath || '(not set)', config.temporalTlsKeyPath || ''],
|
|
182
|
+
const { config, sources } = (0, config_1.getConfigWithSources)();
|
|
183
|
+
const keys = [
|
|
184
|
+
{ key: 'temporalAddress', configKey: 'temporalAddress' },
|
|
185
|
+
{ key: 'temporalNamespace', configKey: 'temporalNamespace' },
|
|
186
|
+
{ key: 'temporalApiKey', configKey: 'temporalApiKey' },
|
|
187
|
+
{ key: 'temporalTlsCertPath', configKey: 'temporalTlsCertPath' },
|
|
188
|
+
{ key: 'temporalTlsKeyPath', configKey: 'temporalTlsKeyPath' },
|
|
189
189
|
];
|
|
190
190
|
out.log(` Config file: ${out.dim(config_1.CONFIG_FILE_PATH)}`);
|
|
191
191
|
console.log();
|
|
192
|
-
out.log(` ${'Key'.padEnd(22)} ${'
|
|
193
|
-
out.log(` ${'─'.repeat(22)} ${'─'.repeat(
|
|
194
|
-
for (const
|
|
195
|
-
|
|
192
|
+
out.log(` ${'Key'.padEnd(22)} ${'Value'.padEnd(30)} ${out.dim('Source')}`);
|
|
193
|
+
out.log(` ${'─'.repeat(22)} ${'─'.repeat(30)} ${'─'.repeat(15)}`);
|
|
194
|
+
for (const { key, configKey } of keys) {
|
|
195
|
+
const value = config[configKey];
|
|
196
|
+
const source = sources[configKey];
|
|
197
|
+
const isSecret = SECRET_KEYS.has(key);
|
|
198
|
+
const display = !value ? '(not set)' : isSecret ? '****' : value;
|
|
199
|
+
out.log(` ${key.padEnd(22)} ${display.padEnd(30)} ${out.dim(source)}`);
|
|
196
200
|
}
|
|
197
201
|
console.log();
|
|
198
202
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -70,6 +70,16 @@ export interface CliOverrides {
|
|
|
70
70
|
* CLI flag > env var > claude-tempo config file > temporal CLI config > defaults
|
|
71
71
|
*/
|
|
72
72
|
export declare function getConfig(overrides?: CliOverrides): Config;
|
|
73
|
+
export type ConfigSource = 'flag' | 'env' | 'config' | 'temporal-cli' | 'default' | 'none';
|
|
74
|
+
export interface ConfigWithSources {
|
|
75
|
+
config: Config;
|
|
76
|
+
sources: Record<string, ConfigSource>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Like getConfig(), but also returns which source each value came from.
|
|
80
|
+
* Used by `claude-tempo config show` to help users debug.
|
|
81
|
+
*/
|
|
82
|
+
export declare function getConfigWithSources(overrides?: CliOverrides): ConfigWithSources;
|
|
73
83
|
/** Build a workflow ID for a player session: claude-session-{ensemble}-{playerId} */
|
|
74
84
|
export declare function sessionWorkflowId(ensemble: string, playerId: string): string;
|
|
75
85
|
/** Build a workflow ID for a conductor: claude-session-{ensemble}-conductor */
|
package/dist/config.js
CHANGED
|
@@ -6,6 +6,7 @@ exports.saveConfigFile = saveConfigFile;
|
|
|
6
6
|
exports.loadTemporalCliConfig = loadTemporalCliConfig;
|
|
7
7
|
exports.parseTemporalYaml = parseTemporalYaml;
|
|
8
8
|
exports.getConfig = getConfig;
|
|
9
|
+
exports.getConfigWithSources = getConfigWithSources;
|
|
9
10
|
exports.sessionWorkflowId = sessionWorkflowId;
|
|
10
11
|
exports.conductorWorkflowId = conductorWorkflowId;
|
|
11
12
|
const fs_1 = require("fs");
|
|
@@ -182,6 +183,50 @@ function getConfig(overrides = {}) {
|
|
|
182
183
|
ensemble: process.env[exports.ENV.ENSEMBLE] ?? 'default',
|
|
183
184
|
};
|
|
184
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Like getConfig(), but also returns which source each value came from.
|
|
188
|
+
* Used by `claude-tempo config show` to help users debug.
|
|
189
|
+
*/
|
|
190
|
+
function getConfigWithSources(overrides = {}) {
|
|
191
|
+
const temporalCli = loadTemporalCliConfig();
|
|
192
|
+
const configFile = loadConfigFile();
|
|
193
|
+
function resolveWithSource(key, cliVal, envKey, fileVal, temporalCliVal, defaultVal) {
|
|
194
|
+
if (cliVal)
|
|
195
|
+
return { value: cliVal, source: 'flag' };
|
|
196
|
+
if (process.env[envKey])
|
|
197
|
+
return { value: process.env[envKey], source: 'env' };
|
|
198
|
+
if (fileVal)
|
|
199
|
+
return { value: fileVal, source: 'config' };
|
|
200
|
+
if (temporalCliVal)
|
|
201
|
+
return { value: temporalCliVal, source: 'temporal-cli' };
|
|
202
|
+
if (defaultVal)
|
|
203
|
+
return { value: defaultVal, source: 'default' };
|
|
204
|
+
return { value: undefined, source: 'none' };
|
|
205
|
+
}
|
|
206
|
+
const address = resolveWithSource('temporalAddress', overrides.temporalAddress, exports.ENV.TEMPORAL_ADDRESS, configFile.temporalAddress, temporalCli.temporalAddress, 'localhost:7233');
|
|
207
|
+
const namespace = resolveWithSource('temporalNamespace', overrides.temporalNamespace, exports.ENV.TEMPORAL_NAMESPACE, configFile.temporalNamespace, temporalCli.temporalNamespace, 'default');
|
|
208
|
+
const apiKey = resolveWithSource('temporalApiKey', overrides.temporalApiKey, exports.ENV.TEMPORAL_API_KEY, configFile.temporalApiKey, temporalCli.temporalApiKey);
|
|
209
|
+
const tlsCert = resolveWithSource('temporalTlsCertPath', overrides.temporalTlsCertPath, exports.ENV.TEMPORAL_TLS_CERT_PATH, configFile.temporalTlsCertPath, temporalCli.temporalTlsCertPath);
|
|
210
|
+
const tlsKey = resolveWithSource('temporalTlsKeyPath', overrides.temporalTlsKeyPath, exports.ENV.TEMPORAL_TLS_KEY_PATH, configFile.temporalTlsKeyPath, temporalCli.temporalTlsKeyPath);
|
|
211
|
+
return {
|
|
212
|
+
config: {
|
|
213
|
+
temporalAddress: address.value,
|
|
214
|
+
temporalNamespace: namespace.value,
|
|
215
|
+
temporalApiKey: apiKey.value,
|
|
216
|
+
temporalTlsCertPath: tlsCert.value,
|
|
217
|
+
temporalTlsKeyPath: tlsKey.value,
|
|
218
|
+
taskQueue: process.env[exports.ENV.TASK_QUEUE] ?? 'claude-tempo',
|
|
219
|
+
ensemble: process.env[exports.ENV.ENSEMBLE] ?? 'default',
|
|
220
|
+
},
|
|
221
|
+
sources: {
|
|
222
|
+
temporalAddress: address.source,
|
|
223
|
+
temporalNamespace: namespace.source,
|
|
224
|
+
temporalApiKey: apiKey.source,
|
|
225
|
+
temporalTlsCertPath: tlsCert.source,
|
|
226
|
+
temporalTlsKeyPath: tlsKey.source,
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
185
230
|
/** Build a workflow ID for a player session: claude-session-{ensemble}-{playerId} */
|
|
186
231
|
function sessionWorkflowId(ensemble, playerId) {
|
|
187
232
|
return `claude-session-${ensemble}-${playerId}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-tempo",
|
|
3
|
-
"version": "0.3.0-beta.
|
|
3
|
+
"version": "0.3.0-beta.2",
|
|
4
4
|
"description": "MCP server for multi-session Claude Code coordination via Temporal",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,6 +26,10 @@
|
|
|
26
26
|
"types": "./dist/workflows/signals.d.ts",
|
|
27
27
|
"default": "./dist/workflows/signals.js"
|
|
28
28
|
},
|
|
29
|
+
"./connection": {
|
|
30
|
+
"types": "./dist/connection.d.ts",
|
|
31
|
+
"default": "./dist/connection.js"
|
|
32
|
+
},
|
|
29
33
|
"./workflow-bundle": "./workflow-bundle.js",
|
|
30
34
|
"./package.json": "./package.json"
|
|
31
35
|
},
|
|
@@ -60,7 +64,8 @@
|
|
|
60
64
|
"types": ["dist/types.d.ts"],
|
|
61
65
|
"config": ["dist/config.d.ts"],
|
|
62
66
|
"spawn": ["dist/spawn.d.ts"],
|
|
63
|
-
"signals": ["dist/workflows/signals.d.ts"]
|
|
67
|
+
"signals": ["dist/workflows/signals.d.ts"],
|
|
68
|
+
"connection": ["dist/connection.d.ts"]
|
|
64
69
|
}
|
|
65
70
|
},
|
|
66
71
|
"files": [
|