vellum 0.2.7 → 0.2.9
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/bun.lock +4 -4
- package/package.json +4 -3
- package/src/__tests__/asset-materialize-tool.test.ts +2 -2
- package/src/__tests__/checker.test.ts +104 -0
- package/src/__tests__/config-schema.test.ts +0 -6
- package/src/__tests__/forbidden-legacy-symbols.test.ts +69 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +538 -0
- package/src/__tests__/ingress-url-consistency.test.ts +214 -0
- package/src/__tests__/ipc-snapshot.test.ts +17 -5
- package/src/__tests__/oauth-callback-registry.test.ts +85 -0
- package/src/__tests__/oauth2-gateway-transport.test.ts +304 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +51 -12
- package/src/__tests__/public-ingress-urls.test.ts +222 -0
- package/src/__tests__/runtime-events-sse-parity.test.ts +343 -0
- package/src/__tests__/runtime-events-sse.test.ts +162 -0
- package/src/__tests__/tool-executor.test.ts +88 -0
- package/src/__tests__/turn-commit.test.ts +64 -0
- package/src/__tests__/twilio-provider.test.ts +1 -1
- package/src/__tests__/twilio-routes.test.ts +4 -4
- package/src/__tests__/twitter-auth-handler.test.ts +87 -2
- package/src/calls/call-domain.ts +8 -6
- package/src/calls/twilio-config.ts +18 -3
- package/src/calls/twilio-routes.ts +10 -2
- package/src/config/bundled-skills/tasks/TOOLS.json +25 -0
- package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +9 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +25 -0
- package/src/config/bundled-skills/transcribe/TOOLS.json +32 -0
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +370 -0
- package/src/config/defaults.ts +4 -1
- package/src/config/schema.ts +30 -6
- package/src/config/system-prompt.ts +1 -1
- package/src/config/types.ts +1 -0
- package/src/config/vellum-skills/google-oauth-setup/SKILL.md +5 -4
- package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +4 -2
- package/src/config/vellum-skills/telegram-setup/SKILL.md +3 -3
- package/src/daemon/computer-use-session.ts +2 -1
- package/src/daemon/handlers/config.ts +49 -17
- package/src/daemon/handlers/sessions.ts +2 -2
- package/src/daemon/handlers/shared.ts +1 -0
- package/src/daemon/handlers/subagents.ts +85 -2
- package/src/daemon/handlers/twitter-auth.ts +31 -2
- package/src/daemon/handlers/work-items.ts +1 -1
- package/src/daemon/ipc-contract-inventory.json +8 -4
- package/src/daemon/ipc-contract.ts +34 -15
- package/src/daemon/lifecycle.ts +9 -4
- package/src/daemon/server.ts +7 -0
- package/src/daemon/session-tool-setup.ts +8 -1
- package/src/inbound/public-ingress-urls.ts +112 -0
- package/src/memory/attachments-store.ts +0 -1
- package/src/memory/channel-delivery-store.ts +0 -1
- package/src/memory/conversation-key-store.ts +0 -1
- package/src/memory/db.ts +472 -148
- package/src/memory/llm-usage-store.ts +0 -1
- package/src/memory/runs-store.ts +51 -6
- package/src/memory/schema.ts +2 -6
- package/src/runtime/gateway-client.ts +7 -1
- package/src/runtime/http-server.ts +174 -7
- package/src/runtime/routes/channel-routes.ts +7 -2
- package/src/runtime/routes/events-routes.ts +79 -0
- package/src/runtime/routes/run-routes.ts +43 -0
- package/src/runtime/run-orchestrator.ts +64 -7
- package/src/security/oauth-callback-registry.ts +66 -0
- package/src/security/oauth2.ts +208 -58
- package/src/subagent/manager.ts +3 -1
- package/src/swarm/backend-claude-code.ts +1 -1
- package/src/tools/assets/search.ts +1 -36
- package/src/tools/claude-code/claude-code.ts +3 -3
- package/src/tools/tasks/work-item-list.ts +16 -2
- package/src/tools/tasks/work-item-run.ts +78 -0
- package/src/util/platform.ts +1 -1
- package/src/work-items/work-item-runner.ts +171 -0
- package/src/workspace/provider-commit-message-generator.ts +39 -23
- package/src/workspace/turn-commit.ts +6 -2
- package/src/__tests__/handlers-twilio-config.test.ts +0 -221
- package/src/calls/__tests__/twilio-webhook-urls.test.ts +0 -162
- package/src/calls/twilio-webhook-urls.ts +0 -50
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, beforeEach, afterEach, mock } from 'bun:test';
|
|
2
|
-
|
|
3
|
-
// ---------------------------------------------------------------------------
|
|
4
|
-
// Mocks — silence logger output during tests
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
|
-
|
|
7
|
-
function makeLoggerStub(): Record<string, unknown> {
|
|
8
|
-
const stub: Record<string, unknown> = {};
|
|
9
|
-
for (const m of ['info', 'warn', 'error', 'debug', 'trace', 'fatal', 'silent', 'child']) {
|
|
10
|
-
stub[m] = m === 'child' ? () => makeLoggerStub() : () => {};
|
|
11
|
-
}
|
|
12
|
-
return stub;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
mock.module('../../util/logger.js', () => ({
|
|
16
|
-
getLogger: () => makeLoggerStub(),
|
|
17
|
-
}));
|
|
18
|
-
|
|
19
|
-
import {
|
|
20
|
-
normalizeBaseUrl,
|
|
21
|
-
buildTwilioVoiceWebhookUrl,
|
|
22
|
-
buildTwilioStatusCallbackUrl,
|
|
23
|
-
getWebhookBaseUrl,
|
|
24
|
-
} from '../twilio-webhook-urls.js';
|
|
25
|
-
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
// normalizeBaseUrl
|
|
28
|
-
// ---------------------------------------------------------------------------
|
|
29
|
-
|
|
30
|
-
describe('normalizeBaseUrl', () => {
|
|
31
|
-
test('returns already-clean URL unchanged', () => {
|
|
32
|
-
expect(normalizeBaseUrl('https://example.com')).toBe('https://example.com');
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test('strips trailing slash', () => {
|
|
36
|
-
expect(normalizeBaseUrl('https://example.com/')).toBe('https://example.com');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test('strips multiple trailing slashes', () => {
|
|
40
|
-
expect(normalizeBaseUrl('https://example.com///')).toBe('https://example.com');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('trims leading and trailing whitespace', () => {
|
|
44
|
-
expect(normalizeBaseUrl(' https://example.com ')).toBe('https://example.com');
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test('trims whitespace and strips trailing slash together', () => {
|
|
48
|
-
expect(normalizeBaseUrl(' https://example.com/ ')).toBe('https://example.com');
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
|
-
// buildTwilioVoiceWebhookUrl
|
|
54
|
-
// ---------------------------------------------------------------------------
|
|
55
|
-
|
|
56
|
-
describe('buildTwilioVoiceWebhookUrl', () => {
|
|
57
|
-
test('returns correct URL with callSessionId', () => {
|
|
58
|
-
const url = buildTwilioVoiceWebhookUrl('https://example.com', 'session-123');
|
|
59
|
-
expect(url).toBe('https://example.com/webhooks/twilio/voice?callSessionId=session-123');
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test('normalizes base URL before composing', () => {
|
|
63
|
-
const url = buildTwilioVoiceWebhookUrl('https://example.com/', 'abc');
|
|
64
|
-
expect(url).toBe('https://example.com/webhooks/twilio/voice?callSessionId=abc');
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// ---------------------------------------------------------------------------
|
|
69
|
-
// buildTwilioStatusCallbackUrl
|
|
70
|
-
// ---------------------------------------------------------------------------
|
|
71
|
-
|
|
72
|
-
describe('buildTwilioStatusCallbackUrl', () => {
|
|
73
|
-
test('returns correct URL', () => {
|
|
74
|
-
const url = buildTwilioStatusCallbackUrl('https://example.com');
|
|
75
|
-
expect(url).toBe('https://example.com/webhooks/twilio/status');
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test('normalizes base URL before composing', () => {
|
|
79
|
-
const url = buildTwilioStatusCallbackUrl('https://example.com/');
|
|
80
|
-
expect(url).toBe('https://example.com/webhooks/twilio/status');
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
// ---------------------------------------------------------------------------
|
|
85
|
-
// getWebhookBaseUrl
|
|
86
|
-
// ---------------------------------------------------------------------------
|
|
87
|
-
|
|
88
|
-
describe('getWebhookBaseUrl', () => {
|
|
89
|
-
let savedEnv: string | undefined;
|
|
90
|
-
|
|
91
|
-
beforeEach(() => {
|
|
92
|
-
savedEnv = process.env.TWILIO_WEBHOOK_BASE_URL;
|
|
93
|
-
delete process.env.TWILIO_WEBHOOK_BASE_URL;
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
afterEach(() => {
|
|
97
|
-
if (savedEnv !== undefined) {
|
|
98
|
-
process.env.TWILIO_WEBHOOK_BASE_URL = savedEnv;
|
|
99
|
-
} else {
|
|
100
|
-
delete process.env.TWILIO_WEBHOOK_BASE_URL;
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
test('uses config value when set', () => {
|
|
105
|
-
const result = getWebhookBaseUrl({ calls: { webhookBaseUrl: 'https://config.example.com/' } });
|
|
106
|
-
expect(result).toBe('https://config.example.com');
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
test('falls back to env var when config value is empty', () => {
|
|
110
|
-
process.env.TWILIO_WEBHOOK_BASE_URL = 'https://env.example.com/';
|
|
111
|
-
const result = getWebhookBaseUrl({ calls: { webhookBaseUrl: '' } });
|
|
112
|
-
expect(result).toBe('https://env.example.com');
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test('falls back to env var when config value is undefined', () => {
|
|
116
|
-
process.env.TWILIO_WEBHOOK_BASE_URL = 'https://env.example.com';
|
|
117
|
-
const result = getWebhookBaseUrl({ calls: {} });
|
|
118
|
-
expect(result).toBe('https://env.example.com');
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
test('throws when neither config nor env var is set', () => {
|
|
122
|
-
expect(() => getWebhookBaseUrl({ calls: { webhookBaseUrl: '' } })).toThrow(
|
|
123
|
-
/No webhook base URL configured/,
|
|
124
|
-
);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test('throws when config is undefined and env var is unset', () => {
|
|
128
|
-
expect(() => getWebhookBaseUrl({ calls: {} })).toThrow(
|
|
129
|
-
/No webhook base URL configured/,
|
|
130
|
-
);
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
test('normalizes the returned URL', () => {
|
|
134
|
-
const result = getWebhookBaseUrl({ calls: { webhookBaseUrl: ' https://example.com/ ' } });
|
|
135
|
-
expect(result).toBe('https://example.com');
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
test('falls through when config value is whitespace-only', () => {
|
|
139
|
-
process.env.TWILIO_WEBHOOK_BASE_URL = 'https://env.example.com';
|
|
140
|
-
const result = getWebhookBaseUrl({ calls: { webhookBaseUrl: ' ' } });
|
|
141
|
-
expect(result).toBe('https://env.example.com');
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
test('falls through when config value is slash-only', () => {
|
|
145
|
-
process.env.TWILIO_WEBHOOK_BASE_URL = 'https://env.example.com';
|
|
146
|
-
const result = getWebhookBaseUrl({ calls: { webhookBaseUrl: '///' } });
|
|
147
|
-
expect(result).toBe('https://env.example.com');
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
test('throws when config is whitespace-only and env var is unset', () => {
|
|
151
|
-
expect(() => getWebhookBaseUrl({ calls: { webhookBaseUrl: ' ' } })).toThrow(
|
|
152
|
-
/No webhook base URL configured/,
|
|
153
|
-
);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
test('throws when env var is whitespace-only and config is empty', () => {
|
|
157
|
-
process.env.TWILIO_WEBHOOK_BASE_URL = ' ';
|
|
158
|
-
expect(() => getWebhookBaseUrl({ calls: {} })).toThrow(
|
|
159
|
-
/No webhook base URL configured/,
|
|
160
|
-
);
|
|
161
|
-
});
|
|
162
|
-
});
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { getLogger } from '../util/logger.js';
|
|
2
|
-
|
|
3
|
-
const log = getLogger('twilio-webhook-urls');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Resolve the webhook base URL from config, falling back to the
|
|
7
|
-
* TWILIO_WEBHOOK_BASE_URL environment variable with a deprecation warning.
|
|
8
|
-
* Throws if neither source provides a value.
|
|
9
|
-
*/
|
|
10
|
-
export function getWebhookBaseUrl(config: { calls: { webhookBaseUrl?: string } }): string {
|
|
11
|
-
const configValue = config.calls.webhookBaseUrl;
|
|
12
|
-
if (configValue) {
|
|
13
|
-
const normalized = normalizeBaseUrl(configValue);
|
|
14
|
-
if (normalized) return normalized;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const envValue = process.env.TWILIO_WEBHOOK_BASE_URL;
|
|
18
|
-
if (envValue) {
|
|
19
|
-
log.warn(
|
|
20
|
-
'TWILIO_WEBHOOK_BASE_URL env var is deprecated — set calls.webhookBaseUrl in config instead.',
|
|
21
|
-
);
|
|
22
|
-
const normalized = normalizeBaseUrl(envValue);
|
|
23
|
-
if (normalized) return normalized;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
throw new Error(
|
|
27
|
-
'No webhook base URL configured. Set calls.webhookBaseUrl in config or TWILIO_WEBHOOK_BASE_URL env var.',
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Trim whitespace and strip trailing slash from a URL string.
|
|
33
|
-
*/
|
|
34
|
-
export function normalizeBaseUrl(url: string): string {
|
|
35
|
-
return url.trim().replace(/\/+$/, '');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Build the Twilio voice webhook URL for a given call session.
|
|
40
|
-
*/
|
|
41
|
-
export function buildTwilioVoiceWebhookUrl(baseUrl: string, callSessionId: string): string {
|
|
42
|
-
return `${normalizeBaseUrl(baseUrl)}/webhooks/twilio/voice?callSessionId=${callSessionId}`;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Build the Twilio status callback URL.
|
|
47
|
-
*/
|
|
48
|
-
export function buildTwilioStatusCallbackUrl(baseUrl: string): string {
|
|
49
|
-
return `${normalizeBaseUrl(baseUrl)}/webhooks/twilio/status`;
|
|
50
|
-
}
|