Skip to content

Commit 1ec10cc

Browse files
renal128cursoragent
andcommitted
feat: add minimal ElevenLabsWidget target and DemoApp example
ChatWidget renders a floating launcher and a drawer with transcript, composer, mic toggle and a placeholder orb, driven by a trimmed ChatWidgetViewModel over ConversationClient. ChatWidgetController is the host control surface from the start. Examples/DemoApp exercises it end to end with a client tool. WidgetConversationMode says how the user can reach the agent — text only, voice only, voice with a composer, or either — and carries the credentials each kind of session needs, so a widget can't be configured for a session it has no way to authenticate. Credentials are minted per start. The drawer is a bottom sheet with a compact and an expanded detent: drag or tap the grabber to move between them, fling down to dismiss, and the compact height adapts to landscape. Voice drawers open as a peek and grow once there is a transcript to read. Failures land in a banner across the top of the drawer — start and send errors auto-dismiss, while denied microphone access stays until it is acted on and offers Settings, since the SDK connects muted rather than failing there. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 57cc551 commit 1ec10cc

28 files changed

Lines changed: 1979 additions & 0 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ xcuserdata/
77
xcshareddata/
88
Package.resolved
99
*.bak
10+
DerivedData/
11+
*.xcuserstate
Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
// !$*UTF8*$!
2+
{
3+
archiveVersion = 1;
4+
classes = {
5+
};
6+
objectVersion = 77;
7+
objects = {
8+
9+
/* Begin PBXBuildFile section */
10+
E1000101000000000000A001 /* ElevenLabs in Frameworks */ = {isa = PBXBuildFile; productRef = E1000201000000000000A001 /* ElevenLabs */; };
11+
E1000102000000000000A001 /* ElevenLabsWidget in Frameworks */ = {isa = PBXBuildFile; productRef = E1000202000000000000A001 /* ElevenLabsWidget */; };
12+
/* End PBXBuildFile section */
13+
14+
/* Begin PBXFileReference section */
15+
E1000301000000000000A001 /* DemoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DemoApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
16+
/* End PBXFileReference section */
17+
18+
/* Begin PBXFileSystemSynchronizedRootGroup section */
19+
E1000401000000000000A001 /* DemoApp */ = {
20+
isa = PBXFileSystemSynchronizedRootGroup;
21+
path = DemoApp;
22+
sourceTree = "<group>";
23+
};
24+
/* End PBXFileSystemSynchronizedRootGroup section */
25+
26+
/* Begin PBXFrameworksBuildPhase section */
27+
E1000501000000000000A001 /* Frameworks */ = {
28+
isa = PBXFrameworksBuildPhase;
29+
buildActionMask = 2147483647;
30+
files = (
31+
E1000101000000000000A001 /* ElevenLabs in Frameworks */,
32+
E1000102000000000000A001 /* ElevenLabsWidget in Frameworks */,
33+
);
34+
runOnlyForDeploymentPostprocessing = 0;
35+
};
36+
/* End PBXFrameworksBuildPhase section */
37+
38+
/* Begin PBXGroup section */
39+
E1000601000000000000A001 = {
40+
isa = PBXGroup;
41+
children = (
42+
E1000401000000000000A001 /* DemoApp */,
43+
E1000602000000000000A001 /* Products */,
44+
);
45+
sourceTree = "<group>";
46+
};
47+
E1000602000000000000A001 /* Products */ = {
48+
isa = PBXGroup;
49+
children = (
50+
E1000301000000000000A001 /* DemoApp.app */,
51+
);
52+
name = Products;
53+
sourceTree = "<group>";
54+
};
55+
/* End PBXGroup section */
56+
57+
/* Begin PBXNativeTarget section */
58+
E1000701000000000000A001 /* DemoApp */ = {
59+
isa = PBXNativeTarget;
60+
buildConfigurationList = E1000901000000000000A001 /* Build configuration list for PBXNativeTarget "DemoApp" */;
61+
buildPhases = (
62+
E1000801000000000000A001 /* Sources */,
63+
E1000501000000000000A001 /* Frameworks */,
64+
E1000802000000000000A001 /* Resources */,
65+
);
66+
buildRules = (
67+
);
68+
dependencies = (
69+
);
70+
fileSystemSynchronizedGroups = (
71+
E1000401000000000000A001 /* DemoApp */,
72+
);
73+
name = DemoApp;
74+
packageProductDependencies = (
75+
E1000201000000000000A001 /* ElevenLabs */,
76+
E1000202000000000000A001 /* ElevenLabsWidget */,
77+
);
78+
productName = DemoApp;
79+
productReference = E1000301000000000000A001 /* DemoApp.app */;
80+
productType = "com.apple.product-type.application";
81+
};
82+
/* End PBXNativeTarget section */
83+
84+
/* Begin PBXProject section */
85+
E1000001000000000000A001 /* Project object */ = {
86+
isa = PBXProject;
87+
attributes = {
88+
BuildIndependentTargetsInParallel = 1;
89+
LastSwiftUpdateCheck = 2640;
90+
LastUpgradeCheck = 2640;
91+
};
92+
buildConfigurationList = E1000902000000000000A001 /* Build configuration list for PBXProject "DemoApp" */;
93+
developmentRegion = en;
94+
hasScannedForEncodings = 0;
95+
knownRegions = (
96+
en,
97+
Base,
98+
);
99+
mainGroup = E1000601000000000000A001;
100+
minimizedProjectReferenceProxies = 1;
101+
packageReferences = (
102+
E1000A01000000000000A001 /* XCLocalSwiftPackageReference "../.." */,
103+
);
104+
preferredProjectObjectVersion = 77;
105+
productRefGroup = E1000602000000000000A001 /* Products */;
106+
projectDirPath = "";
107+
projectRoot = "";
108+
targets = (
109+
E1000701000000000000A001 /* DemoApp */,
110+
);
111+
};
112+
/* End PBXProject section */
113+
114+
/* Begin PBXResourcesBuildPhase section */
115+
E1000802000000000000A001 /* Resources */ = {
116+
isa = PBXResourcesBuildPhase;
117+
buildActionMask = 2147483647;
118+
files = (
119+
);
120+
runOnlyForDeploymentPostprocessing = 0;
121+
};
122+
/* End PBXResourcesBuildPhase section */
123+
124+
/* Begin PBXSourcesBuildPhase section */
125+
E1000801000000000000A001 /* Sources */ = {
126+
isa = PBXSourcesBuildPhase;
127+
buildActionMask = 2147483647;
128+
files = (
129+
);
130+
runOnlyForDeploymentPostprocessing = 0;
131+
};
132+
/* End PBXSourcesBuildPhase section */
133+
134+
/* Begin XCBuildConfiguration section */
135+
E1000B01000000000000A001 /* Debug */ = {
136+
isa = XCBuildConfiguration;
137+
buildSettings = {
138+
ALWAYS_SEARCH_USER_PATHS = NO;
139+
CLANG_ENABLE_MODULES = YES;
140+
CLANG_ENABLE_OBJC_ARC = YES;
141+
COPY_PHASE_STRIP = NO;
142+
DEBUG_INFORMATION_FORMAT = dwarf;
143+
ENABLE_STRICT_OBJC_MSGSEND = YES;
144+
ENABLE_TESTABILITY = YES;
145+
ENABLE_USER_SCRIPT_SANDBOXING = YES;
146+
GCC_C_LANGUAGE_STANDARD = gnu17;
147+
GCC_OPTIMIZATION_LEVEL = 0;
148+
GCC_PREPROCESSOR_DEFINITIONS = (
149+
"DEBUG=1",
150+
"$(inherited)",
151+
);
152+
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
153+
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
154+
MTL_FAST_MATH = YES;
155+
ONLY_ACTIVE_ARCH = YES;
156+
SDKROOT = iphoneos;
157+
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
158+
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
159+
};
160+
name = Debug;
161+
};
162+
E1000B02000000000000A001 /* Release */ = {
163+
isa = XCBuildConfiguration;
164+
buildSettings = {
165+
ALWAYS_SEARCH_USER_PATHS = NO;
166+
CLANG_ENABLE_MODULES = YES;
167+
CLANG_ENABLE_OBJC_ARC = YES;
168+
COPY_PHASE_STRIP = NO;
169+
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
170+
ENABLE_NS_ASSERTIONS = NO;
171+
ENABLE_STRICT_OBJC_MSGSEND = YES;
172+
ENABLE_USER_SCRIPT_SANDBOXING = YES;
173+
GCC_C_LANGUAGE_STANDARD = gnu17;
174+
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
175+
MTL_ENABLE_DEBUG_INFO = NO;
176+
MTL_FAST_MATH = YES;
177+
SDKROOT = iphoneos;
178+
SWIFT_COMPILATION_MODE = wholemodule;
179+
VALIDATE_PRODUCT = YES;
180+
};
181+
name = Release;
182+
};
183+
E1000B03000000000000A001 /* Debug */ = {
184+
isa = XCBuildConfiguration;
185+
buildSettings = {
186+
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
187+
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
188+
CODE_SIGN_STYLE = Automatic;
189+
CURRENT_PROJECT_VERSION = 1;
190+
ENABLE_PREVIEWS = YES;
191+
GENERATE_INFOPLIST_FILE = YES;
192+
INFOPLIST_KEY_NSMicrophoneUsageDescription = "The demo uses the microphone for voice conversations.";
193+
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
194+
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
195+
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
196+
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
197+
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
198+
LD_RUNPATH_SEARCH_PATHS = (
199+
"$(inherited)",
200+
"@executable_path/Frameworks",
201+
);
202+
MARKETING_VERSION = 1.0;
203+
PRODUCT_BUNDLE_IDENTIFIER = io.elevenlabs.example.DemoApp;
204+
PRODUCT_NAME = "$(TARGET_NAME)";
205+
SWIFT_EMIT_LOC_STRINGS = YES;
206+
SWIFT_VERSION = 5.0;
207+
TARGETED_DEVICE_FAMILY = "1,2";
208+
};
209+
name = Debug;
210+
};
211+
E1000B04000000000000A001 /* Release */ = {
212+
isa = XCBuildConfiguration;
213+
buildSettings = {
214+
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
215+
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
216+
CODE_SIGN_STYLE = Automatic;
217+
CURRENT_PROJECT_VERSION = 1;
218+
ENABLE_PREVIEWS = YES;
219+
GENERATE_INFOPLIST_FILE = YES;
220+
INFOPLIST_KEY_NSMicrophoneUsageDescription = "The demo uses the microphone for voice conversations.";
221+
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
222+
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
223+
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
224+
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
225+
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
226+
LD_RUNPATH_SEARCH_PATHS = (
227+
"$(inherited)",
228+
"@executable_path/Frameworks",
229+
);
230+
MARKETING_VERSION = 1.0;
231+
PRODUCT_BUNDLE_IDENTIFIER = io.elevenlabs.example.DemoApp;
232+
PRODUCT_NAME = "$(TARGET_NAME)";
233+
SWIFT_EMIT_LOC_STRINGS = YES;
234+
SWIFT_VERSION = 5.0;
235+
TARGETED_DEVICE_FAMILY = "1,2";
236+
};
237+
name = Release;
238+
};
239+
/* End XCBuildConfiguration section */
240+
241+
/* Begin XCConfigurationList section */
242+
E1000901000000000000A001 /* Build configuration list for PBXNativeTarget "DemoApp" */ = {
243+
isa = XCConfigurationList;
244+
buildConfigurations = (
245+
E1000B03000000000000A001 /* Debug */,
246+
E1000B04000000000000A001 /* Release */,
247+
);
248+
defaultConfigurationIsVisible = 0;
249+
defaultConfigurationName = Release;
250+
};
251+
E1000902000000000000A001 /* Build configuration list for PBXProject "DemoApp" */ = {
252+
isa = XCConfigurationList;
253+
buildConfigurations = (
254+
E1000B01000000000000A001 /* Debug */,
255+
E1000B02000000000000A001 /* Release */,
256+
);
257+
defaultConfigurationIsVisible = 0;
258+
defaultConfigurationName = Release;
259+
};
260+
/* End XCConfigurationList section */
261+
262+
/* Begin XCLocalSwiftPackageReference section */
263+
E1000A01000000000000A001 /* XCLocalSwiftPackageReference "../.." */ = {
264+
isa = XCLocalSwiftPackageReference;
265+
relativePath = "../..";
266+
};
267+
/* End XCLocalSwiftPackageReference section */
268+
269+
/* Begin XCSwiftPackageProductDependency section */
270+
E1000201000000000000A001 /* ElevenLabs */ = {
271+
isa = XCSwiftPackageProductDependency;
272+
productName = ElevenLabs;
273+
};
274+
E1000202000000000000A001 /* ElevenLabsWidget */ = {
275+
isa = XCSwiftPackageProductDependency;
276+
productName = ElevenLabsWidget;
277+
};
278+
/* End XCSwiftPackageProductDependency section */
279+
};
280+
rootObject = E1000001000000000000A001 /* Project object */;
281+
}

Examples/DemoApp/DemoApp/App.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import SwiftUI
2+
3+
@main
4+
struct DemoApp: App {
5+
var body: some Scene {
6+
WindowGroup {
7+
ContentView()
8+
}
9+
}
10+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"colors" : [
3+
{
4+
"idiom" : "universal"
5+
}
6+
],
7+
"info" : {
8+
"author" : "xcode",
9+
"version" : 1
10+
}
11+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"images" : [
3+
{
4+
"idiom" : "universal",
5+
"platform" : "ios",
6+
"size" : "1024x1024"
7+
},
8+
{
9+
"appearances" : [
10+
{
11+
"appearance" : "luminosity",
12+
"value" : "dark"
13+
}
14+
],
15+
"idiom" : "universal",
16+
"platform" : "ios",
17+
"size" : "1024x1024"
18+
},
19+
{
20+
"appearances" : [
21+
{
22+
"appearance" : "luminosity",
23+
"value" : "tinted"
24+
}
25+
],
26+
"idiom" : "universal",
27+
"platform" : "ios",
28+
"size" : "1024x1024"
29+
}
30+
],
31+
"info" : {
32+
"author" : "xcode",
33+
"version" : 1
34+
}
35+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"info" : {
3+
"author" : "xcode",
4+
"version" : 1
5+
}
6+
}

0 commit comments

Comments
 (0)