@getdial/cli 0.33.1 → 0.33.3
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/cli.js +1 -3
- package/dist/commands/call/list.js +5 -1
- package/dist/commands/listen/index.js +17 -3
- package/dist/commands/listen/install.js +7 -2
- package/dist/commands/listen/status.js +11 -7
- package/dist/commands/message/list.js +5 -1
- package/dist/commands/message/reply.js +5 -1
- package/dist/commands/number/set.js +6 -2
- package/dist/commands/onboard.js +17 -5
- package/dist/commands/signup.js +7 -1
- package/dist/commands/typing/start.js +5 -1
- package/dist/commands/typing/stop.js +5 -1
- package/dist/commands/uninstall.js +3 -1
- package/dist/commands/wait-for.js +2 -2
- package/dist/lib/api.js +24 -5
- package/dist/lib/cli-error.js +6 -1
- package/dist/lib/fanout.js +5 -3
- package/dist/lib/log-tail.js +5 -2
- package/dist/lib/log.js +2 -2
- package/dist/lib/ops/account.js +20 -7
- package/dist/lib/ops/calls.js +3 -1
- package/dist/lib/ops/events.js +6 -1
- package/dist/lib/ops/listen.js +8 -1
- package/dist/lib/ops/uninstall.js +9 -3
- package/dist/lib/pubnub.js +47 -9
- package/dist/lib/ref-params.js +37 -0
- package/dist/lib/skill-install.js +1 -1
- package/dist/lib/supervisor/index.js +6 -3
- package/dist/lib/supervisor/launchd.js +13 -4
- package/dist/lib/supervisor/systemd.js +3 -1
- package/dist/lib/versioned-file.js +1 -1
- package/dist/mcp/schemas.js +22 -5
- package/dist/mcp/server.js +1 -3
- package/dist/mcp/tools/add-command-target.js +14 -3
- package/dist/mcp/tools/add-url-target.js +22 -5
- package/dist/mcp/tools/get-account-status.js +3 -1
- package/dist/mcp/tools/onboard.js +26 -7
- package/dist/mcp/tools/place-call.js +34 -8
- package/dist/mcp/tools/purchase-number.js +21 -5
- package/dist/mcp/tools/reply-to-message.js +4 -1
- package/dist/mcp/tools/send-message.js +8 -2
- package/dist/mcp/tools/set-number-properties.js +34 -8
- package/dist/mcp/tools/wait-for-event.js +12 -3
- package/package.json +5 -1
- package/skills.tar.gz +0 -0
package/dist/cli.js
CHANGED
|
@@ -99,9 +99,7 @@ if (!sandbox) {
|
|
|
99
99
|
.option("--json", "machine-readable output")
|
|
100
100
|
.action(async (opts) => process.exit(await runListenStatus({ json: !!opts.json })));
|
|
101
101
|
}
|
|
102
|
-
const number = program
|
|
103
|
-
.command("number")
|
|
104
|
-
.description("Manage your Dial phone numbers.");
|
|
102
|
+
const number = program.command("number").description("Manage your Dial phone numbers.");
|
|
105
103
|
number
|
|
106
104
|
.command("list")
|
|
107
105
|
.description("List the numbers on your account. GET /api/v1/numbers.")
|
|
@@ -3,7 +3,11 @@ import { isDialError } from "../../lib/ops/errors.js";
|
|
|
3
3
|
import { printDialError } from "../../lib/cli-error.js";
|
|
4
4
|
export async function runCallList(opts) {
|
|
5
5
|
try {
|
|
6
|
-
const calls = await listCalls({
|
|
6
|
+
const calls = await listCalls({
|
|
7
|
+
numberId: opts.numberId,
|
|
8
|
+
direction: opts.direction,
|
|
9
|
+
since: opts.since,
|
|
10
|
+
});
|
|
7
11
|
if (opts.json) {
|
|
8
12
|
console.log(JSON.stringify({ ok: true, calls }));
|
|
9
13
|
return 0;
|
|
@@ -11,17 +11,31 @@ function isSupervised() {
|
|
|
11
11
|
export async function runListen() {
|
|
12
12
|
const auth = readAuth();
|
|
13
13
|
if (!auth) {
|
|
14
|
-
appendJsonl(paths().listenLog, {
|
|
14
|
+
appendJsonl(paths().listenLog, {
|
|
15
|
+
ts: new Date().toISOString(),
|
|
16
|
+
lifecycle: "startup",
|
|
17
|
+
ok: false,
|
|
18
|
+
error: "no saved auth",
|
|
19
|
+
});
|
|
15
20
|
if (isSupervised()) {
|
|
16
21
|
await delay(30_000);
|
|
17
22
|
}
|
|
18
23
|
return 1;
|
|
19
24
|
}
|
|
20
|
-
appendJsonl(paths().listenLog, {
|
|
25
|
+
appendJsonl(paths().listenLog, {
|
|
26
|
+
ts: new Date().toISOString(),
|
|
27
|
+
lifecycle: "startup",
|
|
28
|
+
ok: true,
|
|
29
|
+
accountId: auth.accountId,
|
|
30
|
+
});
|
|
21
31
|
recordListenVersion();
|
|
22
32
|
const ctrl = startWorker(auth.apiKey, auth.accountId);
|
|
23
33
|
const onSignal = async (sig) => {
|
|
24
|
-
appendJsonl(paths().listenLog, {
|
|
34
|
+
appendJsonl(paths().listenLog, {
|
|
35
|
+
ts: new Date().toISOString(),
|
|
36
|
+
lifecycle: "shutdown",
|
|
37
|
+
signal: sig,
|
|
38
|
+
});
|
|
25
39
|
await ctrl.stop();
|
|
26
40
|
};
|
|
27
41
|
process.on("SIGTERM", onSignal);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readAuth } from "../../lib/state.js";
|
|
2
|
-
import { installSupervised, resolveListenCommand, supervisorAvailability } from "../../lib/supervisor/index.js";
|
|
2
|
+
import { installSupervised, resolveListenCommand, supervisorAvailability, } from "../../lib/supervisor/index.js";
|
|
3
3
|
export async function runListenInstall(opts) {
|
|
4
4
|
const auth = readAuth();
|
|
5
5
|
if (!auth) {
|
|
@@ -20,7 +20,12 @@ export async function runListenInstall(opts) {
|
|
|
20
20
|
try {
|
|
21
21
|
const result = installSupervised(resolveListenCommand());
|
|
22
22
|
if (opts.json)
|
|
23
|
-
console.log(JSON.stringify({
|
|
23
|
+
console.log(JSON.stringify({
|
|
24
|
+
ok: true,
|
|
25
|
+
changed: result.changed,
|
|
26
|
+
unit_path: result.unitPath,
|
|
27
|
+
warnings: result.warnings,
|
|
28
|
+
}));
|
|
24
29
|
else {
|
|
25
30
|
console.log(`listen service installed${result.changed ? "" : " (no change)"}.`);
|
|
26
31
|
console.log(` unit: ${result.unitPath}`);
|
|
@@ -8,14 +8,18 @@ export async function runListenStatus(opts) {
|
|
|
8
8
|
try {
|
|
9
9
|
const raw = readFileSync(paths().listenLog, "utf8");
|
|
10
10
|
const lines = raw.trim().split("\n").filter(Boolean);
|
|
11
|
-
lastEvents = lines.slice(-5).map((l) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
lastEvents = lines.slice(-5).map((l) => {
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(l);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return l;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
/* ignore */
|
|
17
22
|
}
|
|
18
|
-
catch { /* ignore */ }
|
|
19
23
|
const out = {
|
|
20
24
|
installed: s.installed,
|
|
21
25
|
running: s.running,
|
|
@@ -3,7 +3,11 @@ import { isDialError } from "../../lib/ops/errors.js";
|
|
|
3
3
|
import { printDialError } from "../../lib/cli-error.js";
|
|
4
4
|
export async function runMessageList(opts) {
|
|
5
5
|
try {
|
|
6
|
-
const messages = await listMessages({
|
|
6
|
+
const messages = await listMessages({
|
|
7
|
+
numberId: opts.numberId,
|
|
8
|
+
direction: opts.direction,
|
|
9
|
+
since: opts.since,
|
|
10
|
+
});
|
|
7
11
|
if (opts.json) {
|
|
8
12
|
console.log(JSON.stringify({ ok: true, messages }));
|
|
9
13
|
return 0;
|
|
@@ -3,7 +3,11 @@ import { isDialError } from "../../lib/ops/errors.js";
|
|
|
3
3
|
import { printDialError } from "../../lib/cli-error.js";
|
|
4
4
|
export async function runMessageReply(opts) {
|
|
5
5
|
try {
|
|
6
|
-
const m = await replyToMessage({
|
|
6
|
+
const m = await replyToMessage({
|
|
7
|
+
messageId: opts.messageId,
|
|
8
|
+
body: opts.body,
|
|
9
|
+
reaction: opts.react,
|
|
10
|
+
});
|
|
7
11
|
if (opts.json) {
|
|
8
12
|
console.log(JSON.stringify({ ok: true, message: m }));
|
|
9
13
|
}
|
|
@@ -6,10 +6,14 @@ export async function runNumberSet(opts) {
|
|
|
6
6
|
const n = await setNumberProperties({
|
|
7
7
|
number: opts.number,
|
|
8
8
|
inboundInstruction: opts.inboundInstruction,
|
|
9
|
-
...(opts.inboundVoiceGender !== undefined
|
|
9
|
+
...(opts.inboundVoiceGender !== undefined
|
|
10
|
+
? { inboundVoiceGender: opts.inboundVoiceGender }
|
|
11
|
+
: {}),
|
|
10
12
|
...(opts.inboundLanguage !== undefined ? { inboundLanguage: opts.inboundLanguage } : {}),
|
|
11
13
|
...(opts.nickname !== undefined ? { nickname: opts.nickname } : {}),
|
|
12
|
-
...(opts.maxCallDurationSeconds !== undefined
|
|
14
|
+
...(opts.maxCallDurationSeconds !== undefined
|
|
15
|
+
? { maxCallDurationSeconds: opts.maxCallDurationSeconds }
|
|
16
|
+
: {}),
|
|
13
17
|
});
|
|
14
18
|
if (opts.json) {
|
|
15
19
|
console.log(JSON.stringify({ ok: true, number: n }));
|
package/dist/commands/onboard.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { onboard } from "../lib/ops/account.js";
|
|
2
2
|
import { isDialError } from "../lib/ops/errors.js";
|
|
3
3
|
import { readAuth, authFilePath } from "../lib/state.js";
|
|
4
|
-
import { installSkill, isSupportedAgent, SUPPORTED_AGENTS } from "../lib/skill-install.js";
|
|
4
|
+
import { installSkill, isSupportedAgent, SUPPORTED_AGENTS, } from "../lib/skill-install.js";
|
|
5
5
|
import { supervisorAvailability } from "../lib/supervisor/index.js";
|
|
6
6
|
function maskApiKey(key) {
|
|
7
7
|
return key.length >= 4 ? `sk_live_***${key.slice(-4)}` : "sk_live_***";
|
|
@@ -13,7 +13,10 @@ function installAgentSkills(agents) {
|
|
|
13
13
|
const skills = [];
|
|
14
14
|
for (const requested of agents) {
|
|
15
15
|
if (!isSupportedAgent(requested)) {
|
|
16
|
-
skills.push({
|
|
16
|
+
skills.push({
|
|
17
|
+
agent: requested,
|
|
18
|
+
error: `unknown agent "${requested}". Supported: ${SUPPORTED_AGENTS.join(", ")}.`,
|
|
19
|
+
});
|
|
17
20
|
continue;
|
|
18
21
|
}
|
|
19
22
|
try {
|
|
@@ -30,7 +33,7 @@ const LISTEN_RATIONALE = "The background notification listening service runs on
|
|
|
30
33
|
"Without it the agent is send-only: it can place outbound calls and send messages, but it has no way to know when something arrives at your Dial number. " +
|
|
31
34
|
"It can always be installed later with `dial listen install`.";
|
|
32
35
|
const PRESENTATION_HINT = "When you ask the user, describe it as \"the background notification listening service.\" Don't expose technical details (launchd, plists, daemons, systemd units) — that's not how to talk about it to a non-technical user.";
|
|
33
|
-
const FINALIZATION_HINT =
|
|
36
|
+
const FINALIZATION_HINT = 'To finalize onboarding, ask the user this question before continuing with any other task. If the user\'s original request was something else (e.g. "call X", "send Y"), briefly pause that task, ask the question, get an answer, then resume.';
|
|
34
37
|
export async function runOnboard(opts) {
|
|
35
38
|
// Skill-install-only branch: when --code isn't supplied, we can't (and shouldn't)
|
|
36
39
|
// re-verify — but if the machine is already signed in, the useful thing to do
|
|
@@ -59,9 +62,18 @@ export async function runOnboard(opts) {
|
|
|
59
62
|
accountId: auth.accountId,
|
|
60
63
|
phoneNumber: auth.phoneNumber ?? null,
|
|
61
64
|
phoneNumberId: auth.phoneNumberId ?? null,
|
|
62
|
-
listen: {
|
|
65
|
+
listen: {
|
|
66
|
+
installed: false,
|
|
67
|
+
autoInstalled: false,
|
|
68
|
+
canInstall: supervisor.available,
|
|
69
|
+
unavailableReason: supervisor.available ? null : supervisor.reason,
|
|
70
|
+
},
|
|
63
71
|
skills,
|
|
64
|
-
agentHint: {
|
|
72
|
+
agentHint: {
|
|
73
|
+
action: "skip",
|
|
74
|
+
kind: "already_signed_in",
|
|
75
|
+
note: "Account is already signed in; verification was skipped and only the requested --agent skills were installed.",
|
|
76
|
+
},
|
|
65
77
|
}));
|
|
66
78
|
}
|
|
67
79
|
else {
|
package/dist/commands/signup.js
CHANGED
|
@@ -18,7 +18,13 @@ export async function runSignup(email, opts) {
|
|
|
18
18
|
if (e.code === "pending_exists") {
|
|
19
19
|
const d = e.data ?? {};
|
|
20
20
|
if (opts.json) {
|
|
21
|
-
console.log(JSON.stringify({
|
|
21
|
+
console.log(JSON.stringify({
|
|
22
|
+
ok: false,
|
|
23
|
+
code: "pending_exists",
|
|
24
|
+
verificationId: d.verificationId,
|
|
25
|
+
email: d.email,
|
|
26
|
+
ageSeconds: d.ageSeconds,
|
|
27
|
+
}));
|
|
22
28
|
}
|
|
23
29
|
else {
|
|
24
30
|
console.error(e.message);
|
|
@@ -3,7 +3,11 @@ import { isDialError } from "../../lib/ops/errors.js";
|
|
|
3
3
|
import { printDialError } from "../../lib/cli-error.js";
|
|
4
4
|
export async function runTypingStart(opts) {
|
|
5
5
|
try {
|
|
6
|
-
const result = await setTyping({
|
|
6
|
+
const result = await setTyping({
|
|
7
|
+
toNumber: opts.toNumber,
|
|
8
|
+
value: true,
|
|
9
|
+
fromNumber: opts.fromNumber,
|
|
10
|
+
});
|
|
7
11
|
if (opts.json) {
|
|
8
12
|
console.log(JSON.stringify(result));
|
|
9
13
|
}
|
|
@@ -3,7 +3,11 @@ import { isDialError } from "../../lib/ops/errors.js";
|
|
|
3
3
|
import { printDialError } from "../../lib/cli-error.js";
|
|
4
4
|
export async function runTypingStop(opts) {
|
|
5
5
|
try {
|
|
6
|
-
const result = await setTyping({
|
|
6
|
+
const result = await setTyping({
|
|
7
|
+
toNumber: opts.toNumber,
|
|
8
|
+
value: false,
|
|
9
|
+
fromNumber: opts.fromNumber,
|
|
10
|
+
});
|
|
7
11
|
if (opts.json) {
|
|
8
12
|
console.log(JSON.stringify(result));
|
|
9
13
|
}
|
|
@@ -16,7 +16,9 @@ export async function runUninstall(opts) {
|
|
|
16
16
|
? `agent skills: removed from ${removedSkills.map((s) => s.agent).join(", ")}`
|
|
17
17
|
: "agent skills: none installed");
|
|
18
18
|
const removedDirs = report.dirs.filter((d) => d.removed);
|
|
19
|
-
console.log(removedDirs.length
|
|
19
|
+
console.log(removedDirs.length
|
|
20
|
+
? `state dirs: removed ${removedDirs.map((d) => d.path).join(", ")}`
|
|
21
|
+
: "state dirs: none present");
|
|
20
22
|
for (const e of report.errors) {
|
|
21
23
|
console.error(`error in ${e.step}: ${e.message}`);
|
|
22
24
|
}
|
|
@@ -19,7 +19,7 @@ export async function runWaitFor(opts) {
|
|
|
19
19
|
}
|
|
20
20
|
// Hit: print the raw line and succeed.
|
|
21
21
|
if (!r.timedOut && r.line != null) {
|
|
22
|
-
process.stdout.write(r.line
|
|
22
|
+
process.stdout.write(`${r.line}\n`);
|
|
23
23
|
return 0;
|
|
24
24
|
}
|
|
25
25
|
// Timed out tailing the log, but there was an earlier matching entry.
|
|
@@ -29,7 +29,7 @@ export async function runWaitFor(opts) {
|
|
|
29
29
|
}
|
|
30
30
|
else {
|
|
31
31
|
console.error(`timed out after ${opts.timeoutSeconds}s; latest matching entry in log:`);
|
|
32
|
-
process.stdout.write(r.line
|
|
32
|
+
process.stdout.write(`${r.line}\n`);
|
|
33
33
|
}
|
|
34
34
|
return 1;
|
|
35
35
|
}
|
package/dist/lib/api.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { request, fetch as undiciFetch, FormData as UndiciFormData, setGlobalDispatcher, EnvHttpProxyAgent } from "undici";
|
|
1
|
+
import { request, fetch as undiciFetch, FormData as UndiciFormData, setGlobalDispatcher, EnvHttpProxyAgent, } from "undici";
|
|
2
2
|
import { logger } from "./log.js";
|
|
3
3
|
import { VERSION } from "./version.js";
|
|
4
|
+
import { refParamsHeader } from "./ref-params.js";
|
|
4
5
|
// Route this package's undici requests through HTTP(S)_PROXY when one is set.
|
|
5
6
|
// The `undici` npm package keeps its OWN global dispatcher, which — unlike
|
|
6
7
|
// Node's built-in fetch (wired by NODE_USE_ENV_PROXY) — ignores the proxy env
|
|
@@ -8,7 +9,10 @@ import { VERSION } from "./version.js";
|
|
|
8
9
|
// OneCLI gateway sits on HTTPS_PROXY and injects the Authorization header for
|
|
9
10
|
// api.getdial.ai) our `request()`/`fetch()` calls would otherwise bypass the
|
|
10
11
|
// gateway entirely and go out UNAUTHENTICATED → 401. Opt in explicitly.
|
|
11
|
-
if (process.env.HTTPS_PROXY ||
|
|
12
|
+
if (process.env.HTTPS_PROXY ||
|
|
13
|
+
process.env.https_proxy ||
|
|
14
|
+
process.env.HTTP_PROXY ||
|
|
15
|
+
process.env.http_proxy) {
|
|
12
16
|
setGlobalDispatcher(new EnvHttpProxyAgent());
|
|
13
17
|
}
|
|
14
18
|
// The bundled undici only multipart-encodes its own FormData class (realm
|
|
@@ -21,6 +25,15 @@ const USER_AGENT = `@getdial/cli/${VERSION}`;
|
|
|
21
25
|
export function baseUrl() {
|
|
22
26
|
return process.env.DIAL_API_URL ?? DEFAULT_BASE;
|
|
23
27
|
}
|
|
28
|
+
// Attach the attribution ref params (base64 of the install-time ref-params.txt)
|
|
29
|
+
// so the server can tie this machine's requests to how the user originally
|
|
30
|
+
// arrived. No-op when the user never went through an attributed install.
|
|
31
|
+
export function applyRefParamsHeader(headers) {
|
|
32
|
+
const ref = refParamsHeader();
|
|
33
|
+
if (ref)
|
|
34
|
+
headers["x-dial-ref-params"] = ref;
|
|
35
|
+
return headers;
|
|
36
|
+
}
|
|
24
37
|
export async function apiPost(path, body, apiKey, extraHeaders) {
|
|
25
38
|
return apiRequest("POST", path, body, apiKey, extraHeaders);
|
|
26
39
|
}
|
|
@@ -35,7 +48,9 @@ function toResult(statusCode, text) {
|
|
|
35
48
|
try {
|
|
36
49
|
parsed = text ? JSON.parse(text) : null;
|
|
37
50
|
}
|
|
38
|
-
catch {
|
|
51
|
+
catch {
|
|
52
|
+
/* keep raw */
|
|
53
|
+
}
|
|
39
54
|
if (statusCode >= 200 && statusCode < 300) {
|
|
40
55
|
return { ok: true, status: statusCode, data: parsed };
|
|
41
56
|
}
|
|
@@ -52,7 +67,11 @@ function toResult(statusCode, text) {
|
|
|
52
67
|
}
|
|
53
68
|
async function apiRequest(method, path, body, apiKey, extraHeaders) {
|
|
54
69
|
const url = `${baseUrl()}${path}`;
|
|
55
|
-
const headers =
|
|
70
|
+
const headers = applyRefParamsHeader({
|
|
71
|
+
"content-type": "application/json",
|
|
72
|
+
"user-agent": USER_AGENT,
|
|
73
|
+
...(extraHeaders ?? {}),
|
|
74
|
+
});
|
|
56
75
|
if (apiKey)
|
|
57
76
|
headers.authorization = `Bearer ${apiKey}`;
|
|
58
77
|
try {
|
|
@@ -70,7 +89,7 @@ async function apiRequest(method, path, body, apiKey, extraHeaders) {
|
|
|
70
89
|
/** POST a multipart/form-data body (file uploads). fetch sets the boundary header itself. */
|
|
71
90
|
export async function apiPostMultipart(path, form, apiKey) {
|
|
72
91
|
const url = `${baseUrl()}${path}`;
|
|
73
|
-
const headers = {};
|
|
92
|
+
const headers = applyRefParamsHeader({});
|
|
74
93
|
if (apiKey)
|
|
75
94
|
headers.authorization = `Bearer ${apiKey}`;
|
|
76
95
|
try {
|
package/dist/lib/cli-error.js
CHANGED
|
@@ -16,7 +16,12 @@ const EXIT_1_CODES = new Set([
|
|
|
16
16
|
*/
|
|
17
17
|
export function printDialError(json, e) {
|
|
18
18
|
if (json) {
|
|
19
|
-
console.log(JSON.stringify({
|
|
19
|
+
console.log(JSON.stringify({
|
|
20
|
+
ok: false,
|
|
21
|
+
code: e.code,
|
|
22
|
+
message: e.message,
|
|
23
|
+
...(e.status ? { status: e.status } : {}),
|
|
24
|
+
}));
|
|
20
25
|
}
|
|
21
26
|
else {
|
|
22
27
|
console.error(e.message);
|
package/dist/lib/fanout.js
CHANGED
|
@@ -7,12 +7,12 @@ function clipCapture(buf) {
|
|
|
7
7
|
const s = typeof buf === "string" ? buf : buf.toString("utf8");
|
|
8
8
|
if (s.length <= MAX_CAPTURE_BYTES)
|
|
9
9
|
return s;
|
|
10
|
-
return s.slice(0, MAX_CAPTURE_BYTES)
|
|
10
|
+
return `${s.slice(0, MAX_CAPTURE_BYTES)}…[truncated, total ${s.length} chars]`;
|
|
11
11
|
}
|
|
12
12
|
async function attemptUrl(target, body) {
|
|
13
13
|
const headers = { "Content-Type": "application/json" };
|
|
14
14
|
if (target.bearer)
|
|
15
|
-
headers
|
|
15
|
+
headers.Authorization = `Bearer ${target.bearer}`;
|
|
16
16
|
if (target.secret) {
|
|
17
17
|
const sig = createHmac("sha256", target.secret).update(body).digest("hex");
|
|
18
18
|
headers[target.signatureHeader ?? DEFAULT_SIGNATURE_HEADER] = sig;
|
|
@@ -65,7 +65,9 @@ async function attemptCmd(target, eventJson) {
|
|
|
65
65
|
try {
|
|
66
66
|
child.kill("SIGKILL");
|
|
67
67
|
}
|
|
68
|
-
catch {
|
|
68
|
+
catch {
|
|
69
|
+
/* already exited */
|
|
70
|
+
}
|
|
69
71
|
resolve({
|
|
70
72
|
ok: false,
|
|
71
73
|
timedOut: true,
|
package/dist/lib/log-tail.js
CHANGED
|
@@ -43,7 +43,7 @@ export function findLatestMatch(file, spec) {
|
|
|
43
43
|
return { line: lines[i], obj };
|
|
44
44
|
}
|
|
45
45
|
catch {
|
|
46
|
-
|
|
46
|
+
// skip unparsable lines
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
return null;
|
|
@@ -68,7 +68,10 @@ function readRange(file, offset, length) {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
function parseLines(chunk) {
|
|
71
|
-
return chunk
|
|
71
|
+
return chunk
|
|
72
|
+
.split("\n")
|
|
73
|
+
.filter(Boolean)
|
|
74
|
+
.map((line) => {
|
|
72
75
|
try {
|
|
73
76
|
return { line, obj: JSON.parse(line) };
|
|
74
77
|
}
|
package/dist/lib/log.js
CHANGED
|
@@ -3,7 +3,7 @@ import { dirname } from "node:path";
|
|
|
3
3
|
import pino from "pino";
|
|
4
4
|
export function appendJsonl(file, obj) {
|
|
5
5
|
mkdirSync(dirname(file), { recursive: true });
|
|
6
|
-
appendFileSync(file, JSON.stringify(obj)
|
|
6
|
+
appendFileSync(file, `${JSON.stringify(obj)}\n`);
|
|
7
7
|
}
|
|
8
8
|
export const logger = pino({
|
|
9
9
|
level: process.env.DIAL_LOG_LEVEL ?? "warn",
|
|
@@ -30,5 +30,5 @@ export function rotateIfLarge(file, maxBytes) {
|
|
|
30
30
|
const raw = readFileSync(file, "utf8");
|
|
31
31
|
const lines = raw.split("\n").filter(Boolean);
|
|
32
32
|
const keep = lines.slice(Math.floor(lines.length / 2));
|
|
33
|
-
writeFileSync(file, keep.join("\n")
|
|
33
|
+
writeFileSync(file, `${keep.join("\n")}\n`);
|
|
34
34
|
}
|
package/dist/lib/ops/account.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { readAuth, readPendingSignup, writePendingSignup, clearPendingSignup, writeAuth, authFilePath } from "../state.js";
|
|
1
|
+
import { readAuth, readPendingSignup, writePendingSignup, clearPendingSignup, writeAuth, authFilePath, } from "../state.js";
|
|
2
2
|
import { apiGet, apiPost, baseUrl, pingBackend } from "../api.js";
|
|
3
|
-
import { supervisorStatus, lastEventAtFromLog, supervisorAvailability } from "../supervisor/index.js";
|
|
3
|
+
import { supervisorStatus, lastEventAtFromLog, supervisorAvailability, } from "../supervisor/index.js";
|
|
4
4
|
import { paths } from "../paths.js";
|
|
5
5
|
import { VERSION } from "../version.js";
|
|
6
|
-
import { installSkill, isSupportedAgent, SUPPORTED_AGENTS } from "../skill-install.js";
|
|
6
|
+
import { installSkill, isSupportedAgent, SUPPORTED_AGENTS, } from "../skill-install.js";
|
|
7
7
|
import { isSandbox } from "../sandbox.js";
|
|
8
8
|
import { DialError } from "./errors.js";
|
|
9
9
|
const OTP_EXPIRY_MS = 10 * 60 * 1000;
|
|
@@ -46,7 +46,11 @@ export async function accountStatus() {
|
|
|
46
46
|
let listenState = { installed: false, running: false, lastEventAt: null };
|
|
47
47
|
try {
|
|
48
48
|
const s = supervisorStatus();
|
|
49
|
-
listenState = {
|
|
49
|
+
listenState = {
|
|
50
|
+
installed: s.installed,
|
|
51
|
+
running: s.running,
|
|
52
|
+
lastEventAt: lastEventAtFromLog(paths().listenLog),
|
|
53
|
+
};
|
|
50
54
|
}
|
|
51
55
|
catch {
|
|
52
56
|
// unsupported platform — leave defaults
|
|
@@ -100,10 +104,16 @@ export async function signup(opts) {
|
|
|
100
104
|
throw new DialError("pending_exists", `A pending OTP for ${existing.email} is still fresh (${ageSeconds}s old). Use \`dial onboard --code <code>\` or re-run with --force to start a new one.`, undefined, { verificationId: existing.verificationId, email: existing.email, ageSeconds });
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
|
-
const res = await apiPost("/api/v1/auth/signup", {
|
|
107
|
+
const res = await apiPost("/api/v1/auth/signup", {
|
|
108
|
+
email: opts.email,
|
|
109
|
+
});
|
|
104
110
|
if (!res.ok)
|
|
105
111
|
throw new DialError("signup_failed", res.error, res.status);
|
|
106
|
-
writePendingSignup({
|
|
112
|
+
writePendingSignup({
|
|
113
|
+
verificationId: res.data.verificationId,
|
|
114
|
+
email: opts.email,
|
|
115
|
+
createdAt: new Date().toISOString(),
|
|
116
|
+
});
|
|
107
117
|
return { verificationId: res.data.verificationId, email: opts.email };
|
|
108
118
|
}
|
|
109
119
|
export async function onboard(opts) {
|
|
@@ -139,7 +149,10 @@ export async function onboard(opts) {
|
|
|
139
149
|
const skills = [];
|
|
140
150
|
for (const requested of opts.agents ?? []) {
|
|
141
151
|
if (!isSupportedAgent(requested)) {
|
|
142
|
-
skills.push({
|
|
152
|
+
skills.push({
|
|
153
|
+
agent: requested,
|
|
154
|
+
error: `unknown agent "${requested}". Supported: ${SUPPORTED_AGENTS.join(", ")}.`,
|
|
155
|
+
});
|
|
143
156
|
continue;
|
|
144
157
|
}
|
|
145
158
|
try {
|
package/dist/lib/ops/calls.js
CHANGED
|
@@ -12,7 +12,9 @@ export async function placeCall(opts) {
|
|
|
12
12
|
// Omitted → the server uses the default voice gender (female).
|
|
13
13
|
...(opts.voiceGender ? { voiceGender: opts.voiceGender } : {}),
|
|
14
14
|
...(opts.transferTo ? { transferTo: opts.transferTo } : {}),
|
|
15
|
-
...(opts.maxCallDurationSeconds !== undefined
|
|
15
|
+
...(opts.maxCallDurationSeconds !== undefined
|
|
16
|
+
? { maxCallDurationSeconds: opts.maxCallDurationSeconds }
|
|
17
|
+
: {}),
|
|
16
18
|
}, auth?.apiKey, opts.idempotencyKey ? { "idempotency-key": opts.idempotencyKey } : undefined);
|
|
17
19
|
if (!res.ok)
|
|
18
20
|
throw new DialError("call_failed", res.error, res.status);
|
package/dist/lib/ops/events.js
CHANGED
|
@@ -52,7 +52,12 @@ async function waitFromApi(spec, opts) {
|
|
|
52
52
|
timeout,
|
|
53
53
|
}, auth?.apiKey);
|
|
54
54
|
if (res.ok && res.data?.event) {
|
|
55
|
-
return {
|
|
55
|
+
return {
|
|
56
|
+
source: "api",
|
|
57
|
+
timedOut: false,
|
|
58
|
+
event: res.data.event,
|
|
59
|
+
line: JSON.stringify(res.data.event),
|
|
60
|
+
};
|
|
56
61
|
}
|
|
57
62
|
if (res.ok === false && res.status === 408)
|
|
58
63
|
continue;
|
package/dist/lib/ops/listen.js
CHANGED
|
@@ -44,5 +44,12 @@ export function listenStatus() {
|
|
|
44
44
|
catch {
|
|
45
45
|
// no log yet — leave empty
|
|
46
46
|
}
|
|
47
|
-
return {
|
|
47
|
+
return {
|
|
48
|
+
installed: s.installed,
|
|
49
|
+
running: s.running,
|
|
50
|
+
pid: s.pid,
|
|
51
|
+
unitPath: s.unitPath,
|
|
52
|
+
lastEventAt,
|
|
53
|
+
lastEvents,
|
|
54
|
+
};
|
|
48
55
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, rmSync } from "node:fs";
|
|
2
2
|
import { paths } from "../paths.js";
|
|
3
3
|
import { SUPPORTED_AGENTS, uninstallSkill } from "../skill-install.js";
|
|
4
|
-
import { supervisorAvailability, uninstallSupervised } from "../supervisor/index.js";
|
|
4
|
+
import { supervisorAvailability, uninstallSupervised, } from "../supervisor/index.js";
|
|
5
5
|
export const UNINSTALL_HINT = "npm uninstall -g @getdial/cli";
|
|
6
6
|
/**
|
|
7
7
|
* Full local teardown, best-effort: every step runs even if an earlier one
|
|
@@ -33,7 +33,10 @@ export function uninstallEverything(deps = {}) {
|
|
|
33
33
|
skills.push(uninstallSkill(agent, { home: deps.home, cwd: deps.cwd }));
|
|
34
34
|
}
|
|
35
35
|
catch (err) {
|
|
36
|
-
errors.push({
|
|
36
|
+
errors.push({
|
|
37
|
+
step: `skill:${agent}`,
|
|
38
|
+
message: err instanceof Error ? err.message : String(err),
|
|
39
|
+
});
|
|
37
40
|
}
|
|
38
41
|
}
|
|
39
42
|
const p = paths();
|
|
@@ -47,7 +50,10 @@ export function uninstallEverything(deps = {}) {
|
|
|
47
50
|
}
|
|
48
51
|
catch (err) {
|
|
49
52
|
dirs.push({ path: dir, removed: false });
|
|
50
|
-
errors.push({
|
|
53
|
+
errors.push({
|
|
54
|
+
step: `dir:${dir}`,
|
|
55
|
+
message: err instanceof Error ? err.message : String(err),
|
|
56
|
+
});
|
|
51
57
|
}
|
|
52
58
|
}
|
|
53
59
|
return { ok: errors.length === 0, daemon, skills, dirs, hint: UNINSTALL_HINT, errors };
|