@scout9/admin 1.0.0-alpha.0.0.7 → 1.0.0-alpha.0.0.71

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 CHANGED
@@ -1,252 +1,222 @@
1
- # Scout9's Pocket Scout API
1
+ # Scout9's PMT Admin API
2
2
 
3
- Pocket Scout Node.js API for [Scout9](https://pocket-guide.vercel.app/) - mimics you over your personal phone and email
4
- for common tasks like scheduling meetings, answering questions, and more.
5
-
6
- **⚠️ Danger**: Avoid using a Pocket Scout to autopilot your job and personal relationships, this tool is designed for
7
- workplace productivity and not a substitute for human interaction.
3
+ PMT Node.js API for [Scout9](https://scout9.vercel.app/).
8
4
 
9
5
  ## Setup
10
6
 
11
- 1. Register and grab an API key from [Scout9](https://pocket-guide.vercel.app/)
12
- 2. (Optional) [Purchase](https://pocket-guide.vercel.app/) a Scout9 email or phone number if you prefer
7
+ 1. Register and grab an API key from [Scout9](https://scout9.com/)
8
+ 2. (Optional) [Purchase](https://scout9.com/) a Scout9 email or phone number if you prefer
13
9
 
14
10
  ```bash
15
11
  npm install @scout9/admin --save
16
12
  ```
17
13
 
18
14
  ```typescript
19
- import { Configuration, PocketScoutApi } from '@scout9/admin';
15
+ import Scout9Admin from '@scout9/admin';
16
+
17
+ const scout9 = Scout9Admin('s9_api_key');
18
+ ```
19
+ ## Example: Start a conversation
20
20
 
21
- const configuration = new Configuration({
22
- apiKey: '', // Your API key
21
+ ```typescript
22
+ await scout9.message.send({
23
+ to: '+12345678900',
24
+ message: 'Hey, bob, do you need that ladder?'
23
25
  });
26
+ ```
27
+
28
+ ## Example: Programmatically register an agent
29
+
30
+ ```typescript
31
+ const {id: agentId} = await scout9.agents.create({
32
+ firstName: 'Tony',
33
+ lastName: 'Soprano',
34
+ forwardPhone: '+14327650098'
35
+ });
36
+
37
+ // Use Tony instead of the default agent (owner of account)
38
+ await scout9.message({
39
+ to: '+12345678900',
40
+ from: agentId,
41
+ message: 'Hey, bob, do you need that ladder?'
42
+ });
43
+
44
+
45
+ ```
46
+
47
+ ## Example: Programmatically purchase a phone number
24
48
 
25
- const pocketScout = new PocketScoutApi(configuration);
49
+ You can purchase and assign a masked phone number to your agent entity. You will have to have a [default payment method attached](https://scout9.com/b) to your account.
50
+
51
+ ```typescript
52
+ // Purchase a phone - assuming I have a payment method at https://scout9.com/b
53
+ const {phoneNumber} = await scout9.agents.purchasePhone(agentId, {areaCode: 206});
54
+ console.log(`Purchased phone number: ${phoneNumber}`);
26
55
  ```
27
56
 
28
- ## Step 1: Register yourself as an agent
57
+ Purchasing a phone number will assign your phone number and its aid to your agent's `.programmablePhoneNumber`.
58
+
59
+ ## Example: Programmatically add agent audio and conversation files
60
+
61
+ You can programmatically upload audio and text files to your agent registry to improve Persona Model Transformer (PMT) performance (responses sound more like you).
29
62
 
30
63
  ```typescript
31
64
  import fs from 'fs/promises';
32
65
  import path from 'path';
33
66
 
34
- // Registered your self as an agent within the Pocket Scout context
35
- const agentId = await pocketScout
36
- .agentRegister({
37
- firstName: 'Tony',
38
- lastName: 'Sopranos',
39
- title: 'Boss',
40
-
41
- // A brief description of yourself to set the tone
42
- context: 'I\'m Tony. Look, this life, it ain\'t for the faint-hearted. I got responsibilities - to my family and my crew. Loyalty, respect, that\'s everything. When I deal with my associates, I\'m direct. I expect them to come to me straight, no BS. Some might call me tough, even ruthless, but it\'s the world we\'re in. You show weakness, you\'re done. I\'ve got a code, though. If you\'re loyal to me, I\'ll have your back. But cross me? That\'s something you\'ll regret. It\'s business, but it\'s also personal. We\'re a family.',
43
-
44
- // Must provide one of the following...
45
- forwardPhone: '+15555555544', // my personal phone number to get notified of in coming messages
46
- forwardEmail: 'tonyboss@gmail.com', // my personal email to get notified of in coming messages
47
-
48
-
49
- /**
50
- * (optional) either a provided Scout9 phone number or your personal
51
- * ⚠️ Note: If a personal number, you'll be asked to download the Pocket Scout app to enable Pocket Scout auto responses
52
- */
53
- programmablePhoneNumber: '+15555555555',
54
-
55
- /**
56
- * (optional) either a provided Scout9 email or your personal
57
- * ⚠️ Note: If a personal email, you'll be asked to authenticate your Pocket Scout onto your email account
58
- */
59
- programmableEmail: `tonyboss@gmail.com`,
60
-
61
-
62
- /**
63
- * Optional conversation data to help your Pocket Scout capture your tone
64
- * See ../examples/samples to see coversation text format or enter JSON manually
65
- */
66
- conversations: [
67
- await pocketScout.fileCreate(await fs.readFile('./conversation1.txt'), 'conversation with Chris')
68
- .then(res => res.data.id),
69
- await pocketScout.fileCreate(await fs.readFile('./conversation2.txt'), 'conversation with Paulie')
70
- .then(res => res.data.id),
71
- ],
72
-
73
- /**
74
- * (optional) audio data to help your Pocket Scout capture your tone
75
- * (Eventually your Pocket Scout can use this to generate voice responses, but for now its more of a way to capture your tone/character)
76
- */
77
- audio: [
78
- await pocketScout.fileCreate(await fs.readFile('./audio.mp3'),
79
- 'Secret Audio of me talking to Dr. Melfi (no one can know about this)').then(res => res.data.id),
80
- ]
81
- })
82
- .then((res) => res.data.id);
67
+ const textConvo1 = await scout9.agents.transcripts.upload(
68
+ agentId,
69
+ await fs.readFile('./conversation1.txt'),
70
+ 'conversation with Chris'
71
+ );
72
+ const textConvo2 = await scout9.agents.transcripts.upload(
73
+ agentId,
74
+ await fs.readFile('./conversation2.txt'),
75
+ 'conversation with Paulie'
76
+ );
77
+ const audioConvo1 = await scout9.agents.audio.upload(
78
+ agentId,
79
+ await fs.readFile('./audio.mp3'),
80
+ 'Secret Audio of me talking to Dr. Melfi (no one can know about this)'
81
+ );
83
82
  ```
84
83
 
85
- ## Step 2: Register customers
86
84
 
87
- You can register customers by adding their email or phone.
88
85
 
89
- **⚠️ Note:** If you are using a provided Scout9 email or phone number, customers must opt-in to receive messages or
90
- initiate conversations with you.
86
+ ## Step 2: Register customers
87
+
88
+ Customers are automatically added in your account when they contact any of your masked contacts. However, you can programmatically register customers by adding their email or phone.
91
89
 
92
90
  ```typescript
93
- // Create 1 customer
94
- const customerId = await pocketScout.createCustomer({
91
+ await scout9.customers.create({
95
92
  firstName: 'Hi',
96
93
  lastName: 'Jack',
97
94
  email: 'hi@example.com',
98
- phone: '+15555555555',
99
- })
100
- .then((res) => res.data.id);
101
-
102
- // Or create multiple customers
103
- const customers: Customer[] = [
104
- {
105
- // scout9 internal values
106
- name: 'Tony Soprano',
107
- phone: null,
108
- email: null,
109
-
110
- // customer properties
111
- role: 'boss',
112
- customId: 'tony-soprano',
113
- fun_fact: 'I love my ducks'
114
- },
115
- {
116
- // scout9 internal values
117
- name: 'Carmela Soprano',
118
- phone: null,
119
- email: null,
120
-
121
- // customer properties
122
- favorite_drink: 'lillet blanc',
123
- },
124
- {
125
- name: 'Salvatore Bonpensiero',
126
- firstName: 'Salvatore',
127
- phone: null,
128
- email: null,
129
- $agent: 'skip_lipari', // agent id
130
-
131
- // customer properties
132
- rat: true,
133
- location: 'New Jersey coast',
134
- nickname: 'Big 🐈',
135
- lastSeason: 'season 1'
136
- }
137
- ];
138
- await pocketScout.customersCreate({customers});
95
+ phone: '+15555555555'
96
+ });
139
97
  ```
140
98
 
141
- ## Step 3: Initiate a conversation
142
-
143
- Initiate a default generic conversation with an existing customer, use the optional **initialMessage** to provide some
144
- guidance.
99
+ You can also add multiple customers
100
+ ```typescript
101
+ // Add multiple customers
102
+ await scout9.customers.bulkCreate(
103
+ [
104
+ {
105
+ // scout9 internal values
106
+ name: 'Tony Soprano',
107
+ phone: null,
108
+ email: null,
109
+
110
+ // customer properties
111
+ role: 'boss',
112
+ customId: 'tony-soprano',
113
+ fun_fact: 'I love my ducks'
114
+ },
115
+ {
116
+ // scout9 internal values
117
+ name: 'Carmela Soprano',
118
+ phone: null,
119
+ email: null,
120
+
121
+ // customer properties
122
+ favorite_drink: 'lillet blanc'
123
+ },
124
+ {
125
+ name: 'Salvatore Bonpensiero',
126
+ firstName: 'Salvatore',
127
+ phone: null,
128
+ email: null,
129
+ $agent: 'skip_lipari', // agent id
130
+
131
+ // customer properties
132
+ rat: true,
133
+ location: 'New Jersey coast',
134
+ nickname: 'Big 🐈',
135
+ lastSeason: 'season 1'
136
+ }
137
+ ]
138
+ );
139
+ ```
145
140
 
141
+ ## Example: Schedule a conversation
146
142
  ```typescript
147
- const initialMessage = `Hey there, would you like a free pizza?`;
143
+ import moment from 'moment';
148
144
 
149
- const conversation = await pocketScout.conversationCreate({
150
- customer: customerId,
151
- agent: agentId,
152
- environment: 'phone', // This will attempt to contact via SMS
153
- // Add some initial contexts to the conversation to help the agent get started
154
- initialContexts: [
155
- 'We are offering free pizzas to the first 100 hundred customers for today only',
156
- 'We have pepperoni, cheese, meat lovers, and vegan pizzas available',
157
- 'We do not have gluten free pizzas available at this time',
158
- 'We are only offering free pizzas, nothing else',
159
- 'You must pick up the free pizza at 255 W Alameda St, Tucson, AZ 85701',
160
- 'We close at 10pm tonight',
161
- 'If the customer is not interested or serious in receiving a free pizza, disengage and direct them to our website (https://azpizzatime.com) for future orders'
162
- ]
163
- });
164
145
 
165
- // Send a message
166
- await pocketScout.message({convo: conversation.data.id, message: initialMessage});
167
- ```
146
+ // Schedule a new conversation with Bob at 9:00am tomorrow
147
+ await scout9.message({
148
+ to: '+12345678900',
149
+ message: 'Hey, Bob, good morning!',
150
+ scheduled: moment()
151
+ .add(1, 'day')
152
+ .set({hour: 9, minutes: 0, seconds: 0})
153
+ .unix()
154
+ });
168
155
 
169
- ## Step 4: Test your conversation
170
156
 
171
- Test your conversation before you send a message.
157
+ // Schedule a message to an existing conversation with Bob at 9:00am tomorrow
158
+ scout9.message({
159
+ convo: 'convo_122343332',
160
+ message: 'Hey, Bob, good morning!',
161
+ scheduled: moment()
162
+ .add(1, 'day')
163
+ .set({hour: 9, minutes: 0, seconds: 0})
164
+ .unix()
165
+ });
172
166
 
173
- ```typescript
174
- const initialMessage = `Hey there, would you like a free pizza?`;
175
167
 
176
- const conversationId = await pocketScout.conversationCreate({
177
- customer: customerId,
178
- agent: agentId,
179
- environment: 'phone', // This will attempt to contact via SMS
180
- // Add some initial contexts to the conversation to help the agent get started
181
- initialContexts: [
182
- 'We are offering free pizzas to the first 100 hundred customers for today only',
183
- 'We have pepperoni, cheese, meat lovers, and vegan pizzas available',
184
- 'We do not have gluten free pizzas available at this time',
185
- 'We are only offering free pizzas, nothing else',
186
- 'You must pick up the free pizza at 255 W Alameda St, Tucson, AZ 85701',
187
- 'We close at 10pm tonight',
188
- 'If the customer is not interested or serious in receiving a free pizza, disengage and direct them to our website (https://azpizzatime.com) for future orders'
189
- ]
190
- }).then((res) => res.data.id);
191
-
192
- const anticipatedCustomerResponses = [
193
- 'Yes please!',
194
- 'No thanks',
195
- 'What kind of pizza are we talking about?',
196
- 'I\'m vegan, do you have vegan pizza?',
197
- 'I hate you, stop texting me',
198
- 'I love you, keep texting me',
199
- ];
200
- for (const customerResponse of anticipatedCustomerResponses) {
201
- const generatedResponse = await pocketScout.generate({
202
- convo: conversationId,
203
- mocks: {
204
- messages: [
205
- {
206
- role: 'customer',
207
- content: customerResponse
208
- }
209
- ]
210
- }
211
- })
212
- .then((res) => res.data.content);
213
-
214
- console.log(`\n\tCustomer: "${customerResponse}"\n\tAgent: "${generatedResponse}"\n`);
215
- }
216
-
217
- console.log(`Looks good 👍 - sending messing to customer`);
218
- await pocketScout.message({convo: conversation.data.id, message: initialMessage});
168
+ // Or delay a message to an existing conversation with Bob 1 minute from now
169
+ scout9.message({
170
+ convo: 'convo_122343332',
171
+ message: 'Hey, Bob, good morning!',
172
+ secondsDelay: 60
173
+ });
219
174
  ```
220
175
 
221
- ## Step 5: View your conversation
176
+ ## Example view messages
222
177
 
223
- Messages and customer responses can be viewed in the [Scout9 UI](https://pocket-guide.vercel.app/). You can also
178
+ Messages and customer responses can be viewed in the [Scout9 UI](https://scout9.vercel.app/). You can also
224
179
  configure webhooks in the account portal to listen to incoming messages on your own server.
225
180
 
226
181
  ```typescript
227
- const messages = await pocketScout.messages(conversationId);
182
+ const conversationId = 'convo_122343332';
183
+ const messages = await scout9.conversation.messages(conversationId);
228
184
  console.log(`Retrieved ${messages.data.length} messages from the conversation`);
229
185
 
230
186
  for (const message of messages.data) {
231
187
  console.log(`\t${message.role}: ${message.content}`);
232
188
  }
233
189
  ```
190
+ ```json
191
+ [
192
+ {
193
+ "role": "customer",
194
+ "content": "Hey, Tony, good morning! I need that 'ladder' you mentioned."
195
+ },
196
+ {
197
+ "role": "agent",
198
+ "content": "Hey, Paulie, I know exactly what you mean... Chris will have that ladder for you. Standby for his call."
199
+ },
200
+ {
201
+ "role": "customer",
202
+ "content": "Yeah, thanks Ton"
203
+ }
204
+ ]
205
+ ```
234
206
 
235
- ## Advanced Examples
236
-
237
- ### Schedule a conversation
207
+ ## Example: Schedule an advanced conversation
238
208
 
239
- See [simple-schedule-conversation.ts](../../examples/simple-schedule-conversation.ts) on how to test a conversation before its
240
- created.
209
+ If you need the conversation to have some additional context, you can add initial contexts to a newly created conversation. Otherwise sending the message and automatically creating a conversation to the default context.
241
210
 
242
211
  ```typescript
243
- const initialMessage = `Hey there, would you like a free pizza?`;
244
-
245
- const conversation = await pocketScout.scheduleConversation({
246
- customer: customerId,
247
- agent: agentId,
248
- environment: 'phone', // This will attempt to contact via SMS
249
- // Add some initial contexts to the conversation to help the agent get started
212
+ const customerId = '1233993';
213
+ const agentId = '10029292';
214
+
215
+ // Create a conversation with some additional context to drive the conversation
216
+ const {id: convoId} = await scout9.conversation.create({
217
+ $customer: customerId,
218
+ $agent: agentId,
219
+ environment: "phone",
250
220
  initialContexts: [
251
221
  'We are offering free pizzas to the first 100 hundred customers for today only',
252
222
  'We have pepperoni, cheese, meat lovers, and vegan pizzas available',
@@ -257,118 +227,55 @@ const conversation = await pocketScout.scheduleConversation({
257
227
  'If the customer is not interested or serious in receiving a free pizza, disengage and direct them to our website (https://azpizzatime.com) for future orders'
258
228
  ]
259
229
  });
260
- ```
261
230
 
262
- ### Define workflows
231
+ // Schedule message to 9:00 am tomorrow
232
+ await scout9.message({
233
+ convo: convoId,
234
+ message: 'Hey Bob, would you like a free pizza?',
235
+ scheduled: moment()
236
+ .add(1, 'day')
237
+ .set({hour: 9, minutes: 0, seconds: 0})
238
+ .unix()
239
+ });
240
+ ```
263
241
 
264
- Conversations by default use a generic **workflow** procedure that has a stated goal to guide your Pocket Scout in a
265
- conversation. Initiate a conversation with a clear specific objective using the **workflow** api.
242
+ ## Example: Respond to a customer
266
243
 
267
- See [full workflow example](../../examples/create-workflow.ts)
244
+ If a customer triggers one of your active **workflows**, then by default your application will respond to the customer.
245
+ If you respond manually, then the Application will stop responding to the customer for the entire conversation.
268
246
 
269
247
  ```typescript
270
- const workflow: CreateWorkflowRequest = {
271
- name: 'Order Pizza',
248
+ await scout9.message.send({convo: conversationId, message: 'Hey there, would you like a free pizza?'});
249
+ ```
272
250
 
273
- // Define the goal of the workflow
274
- context: 'When a customer wants to order a pizza, I will determine what pizza they need and when, then determine if it needs to be picked up or delivered to their address.',
251
+ [//]: # (## Available Platforms)
275
252
 
276
- // fields follow this boolean structure -> (a || b) && (c || d), if true then the context will be inserted into the conversation.
277
- fields: contextFields,
253
+ [//]: # ()
254
+ [//]: # (Customers can interact with you on any of the connected platforms)
278
255
 
279
- // Custom context and how this workflow will be triggered from a customer conversation
280
- initiators: {
281
- // We need to describe the fields that we want to collect from the customer in this workflow
282
- // entity fields such as firstName, address, location, etc are built in and will be provided by default
283
- entities: customEntities,
284
- documents: workflowTriggerStatements
285
- },
286
- };
256
+ [//]: # ()
257
+ [//]: # (| Platforms | Supported | |)
287
258
 
288
- const workflowId = await pocketScout.workflowCreate(workflow).then(res => res.data.id);
259
+ [//]: # (|--------------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------|)
289
260
 
290
- console.log(`Created workflow with id: ${workflowId}`);
291
- ```
261
+ [//]: # (| Android | ⚠️ (pending) | (free) An android app is in development to enable your Pocket Scout to respond to SMS text |)
292
262
 
293
- Use the `.fields` property to guide the conversation to accomplish the goal. In this example we ask the user for the
294
- pizza size, sauce, toppings, when, delivery or take out, and if delivery then the address.
263
+ [//]: # (| iOS | ⚠️ (pending) | (free) An ios app is in development to enable your Pocket Scout to respond to iMessages |)
295
264
 
296
- ```typescript
297
- const contextFields: ConversationContextField[] = [
298
- {
299
- id: 'determineSize',
300
- context: 'Determine what size pizza the customer wants, we have small, medium, and large',
301
- conditions: [
302
- {
303
- conditions: [
304
- {
305
- key: 'pizzaSize', // If we don't know the pizzaSize, then insert this context
306
- operator: 'notExists',
307
- value: true
308
- }
309
- ]
310
- }
311
- ]
312
- },
313
- // ... other field definitions
314
- ]
315
- ```
316
-
317
- In the `.initiators.entities` we can define custom fields that the Pocket Scout can search for and store in the
318
- conversation
265
+ [//]: # (| Web | ✅ | (free) We generate conversation links for you and your customers to quickly connect, conversations expire in 1 day |)
319
266
 
320
- In this example we include a custom entity field `pizzaSize` which can be described as a small or personal pizza.
267
+ [//]: # (| Gmail | ✅ | (free) Provide Scout9 authorization access to your gmail account for read/write capabilities so your Pocket Scout can respond to emails |)
321
268
 
322
- ```typescript
323
- const customEntities = [
324
- {
325
- utteranceId: 'pizzaSize',
326
- option: 'small',
327
- languages: ['en'],
328
- text: [
329
- 'small',
330
- 'personal',
331
- 'individual',
332
- '6-inch',
333
- '8-inch',
334
- ]
335
- },
336
- // ... other custom entities or pizza sizes
337
- ]
338
- ```
269
+ [//]: # (| Outlook | ⚠️ (pending) | (free) Provide Scout9 authorization access to your outlook account for read/write capabilities so your Pocket Scout can respond to emails |)
339
270
 
340
- Then we need some statements that can trigger the workflow and context fields that get stored in `.initiators.documents`.
271
+ [//]: # (| Native Email | ❌ | For security and privacy concerns we currently cannot support native email systems at this time |)
341
272
 
342
- ```typescript
343
- const workflowTriggerStatements = [
344
- {text: 'I would like to order a %pizzaSize% %pizzaType%', id: 'request'},
345
- // ... more examples that might trigger the workflow
346
- ];
347
- ```
273
+ [//]: # (| Discord | ⚠️ (pending) | (free) Download the Pocket Scout Discord bot and configure workflows to respond to messages accordingly |)
348
274
 
349
- ### Respond to a customer
275
+ [//]: # (| Slack | ⚠️ (pending) | (free) Download the Pocket Scout Slack agent and configure workflows to respond to messages accordingly |)
350
276
 
351
- If a customer triggers one of your active **workflows**, then by default your Pocket Scout will respond to the customer.
352
- If you respond manually, then the Pocket Scout will stop responding to the customer for the entire conversation.
277
+ [//]: # (| Teams | ⚠️ (pending) | (free) Download the Pocket Scout Teams add-on |)
353
278
 
354
- ```typescript
355
- await pocketScout.message({convo: conversationId, message: 'Hey there, would you like a free pizza?'});
356
- ```
279
+ [//]: # (| Scout9 Phone | ✅ | $5/month we provide a generated phone number you can use for your Pocket Scout to text, messages will be relayed back to your personal phone number |)
357
280
 
358
- ## Available Platforms
359
-
360
- Customers can interact with you (and your Pocket Scout) on any of the connected platforms
361
-
362
- | Platforms | Supported | |
363
- |--------------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
364
- | Android | ⚠️ (pending) | (free) An android app is in development to enable your Pocket Scout to respond to SMS text |
365
- | iOS | ⚠️ (pending) | (free) An ios app is in development to enable your Pocket Scout to respond to iMessages |
366
- | Web | ✅ | (free) We generate conversation links for you and your customers to quickly connect, conversations expire in 1 day |
367
- | Gmail | ✅ | (free) Provide Scout9 authorization access to your gmail account for read/write capabilities so your Pocket Scout can respond to emails |
368
- | Outlook | ⚠️ (pending) | (free) Provide Scout9 authorization access to your outlook account for read/write capabilities so your Pocket Scout can respond to emails |
369
- | Native Email | ❌ | For security and privacy concerns we currently cannot support native email systems at this time |
370
- | Discord | ⚠️ (pending) | (free) Download the Pocket Scout Discord bot and configure workflows to respond to messages accordingly |
371
- | Slack | ⚠️ (pending) | (free) Download the Pocket Scout Slack agent and configure workflows to respond to messages accordingly |
372
- | Teams | ⚠️ (pending) | (free) Download the Pocket Scout Teams add-on |
373
- | Scout9 Phone | ✅ | $5/month we provide a generated phone number you can use for your Pocket Scout to text, messages will be relayed back to your personal phone number |
374
- | Scout9 Email | ✅ | $5/month We provide a generated email with your name (e.g. patrick.opie@scout9.com) you can use for your Pocket Scout |
281
+ [//]: # (| Scout9 Email | ✅ | $5/month We provide a generated email with your name (e.g. patrick.opie@scout9.com) you can use for your Pocket Scout |)