@audienti/cli 0.2.0-exora.21 → 0.2.0-exora.23
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/cli/account-reply-operations.mjs +1 -1
- package/cli/audienti.mjs +2 -1
- package/cli/intent.mjs +46 -3
- package/cli/playbook-help.mjs +4 -0
- package/cli/playbook-operations.mjs +2 -1
- package/cli/progress.mjs +8 -7
- package/cli/tools-operations.mjs +1 -0
- package/cli/tools.mjs +2 -2
- package/package.json +1 -1
- package/skills/getting-started/references/replies.md +8 -2
- package/skills/playbook-design/SKILL.md +4 -0
- package/skills/playbook-design/references/fields.md +2 -2
- package/source-manifest.json +13 -13
|
@@ -5,7 +5,7 @@ const item = { ...scope, evidenceId: uuid };
|
|
|
5
5
|
const status = z.enum(['needs_handling', 'handled', 'not_reply']);
|
|
6
6
|
const outcome = z.enum(['response_recorded', 'closed_without_response', 'suppressed']);
|
|
7
7
|
const limit = z.number().int().min(1).max(100);
|
|
8
|
-
const classification = z.enum(['interested', 'question', 'later', 'out_of_office', 'stop', 'bounce', 'referral', 'wrong_person']);
|
|
8
|
+
const classification = z.enum(['interested', 'question', 'later', 'not_interested', 'out_of_office', 'stop', 'bounce', 'referral', 'wrong_person']);
|
|
9
9
|
const slot = z.object({ start: z.string().describe('UTC start, ending in Z.'), end: z.string().describe('UTC end, ending in Z.'), timeZone: z.string().describe("The user's IANA time zone, for display.") }).strict();
|
|
10
10
|
const draft = z.object({
|
|
11
11
|
type: z.enum(['email.send', 'linkedin.send']),
|
package/cli/audienti.mjs
CHANGED
|
@@ -81,6 +81,7 @@ Discovery: prospects list|get ID|timeline ID [--limit N]|observation create|cita
|
|
|
81
81
|
usage breakdown [--workspace ID] [--since month|7d|30d|90d] [--by tool|provider|model|caller|day] [--format json|csv]
|
|
82
82
|
workspace usage summary|callers|calls [--after ID] [--caller user:ID|agent:ID|key:ID] [--status all|succeeded|failed|pending]|call ID [--workspace ID] (paid tool use, last 30 days, and single calls)
|
|
83
83
|
intent list [--workspace ID] (the closed set of message labels: name, direction, event, channels, typed detail; output is JSON)
|
|
84
|
+
intent suggest (--text TEXT | --text-file PATH) --channel email|linkedin [--direction inbound|outbound] [--context TEXT] [--request-id UUID] [--workspace ID] (paid: what a message may mean, read by a model; prints the price per 1M input tokens first; suggests labels with a quote and reason, records nothing; keep one with intent record)
|
|
84
85
|
intent record --person ID --evidence ID --label NAME --quote TEXT --reason TEXT [--confidence high|medium|low] [--request-id UUID] [--participation ID] [--workspace ID] (what a stored message means; get EVIDENCE from prospects conversation append|list; --file LABELS.json for several labels or a typed detail such as a stop result or a meeting time; every label is checked and a refusal says what to fix; a message you sent that asks for a meeting takes --label meeting_requested on its outbound evidence)
|
|
85
86
|
audit list [--workspace ID] [--since 7d] [--actor agent|person] [--category NAME] [--format json|csv]
|
|
86
87
|
budgets set --workspace ID [--agent ID --cap N|none] [--new-agent-cap N|none] [--at-limit pause|ask] [--alert80 on|off] (alert80 covers Operator and email at 80%)
|
|
@@ -90,7 +91,7 @@ Find prospects: campaign find CAMPAIGN_ID --count N --max-credits C (searches w
|
|
|
90
91
|
campaign check CAMPAIGN_ID --url LINKEDIN_URL [--request-id UUID] (checks one person the same way; reuse the request ID after an interruption)
|
|
91
92
|
Target companies: campaign targets CAMPAIGN_ID [--limit N --after CURSOR] (reads the companies people must work at to join)
|
|
92
93
|
campaign targets CAMPAIGN_ID --add acme.com,linkedin.com/company/globex [--remove old.com] | --set FILE|- (one company per line; saves a new revision)
|
|
93
|
-
Playbooks: playbook list [--archived] [--limit N --cursor ID]|actions|show ID [--revision N]|save --file REQUEST.json|archive ID|restore ID|draft show ID|save ID --file REQUEST.json|discard ID [--expected-updated-at T]|publish ID [--request-id UUID]|delete ID|progress PARTICIPATION_ID|record --file REQUEST.json (audienti playbook SUBCOMMAND --help for the request shape)
|
|
94
|
+
Playbooks: playbook list [--archived] [--limit N --cursor ID]|actions|show ID [--revision N]|save --file REQUEST.json|archive ID|restore ID|draft show ID|save ID --file REQUEST.json|discard ID [--expected-updated-at T]|publish ID [--request-id UUID]|delete ID|progress PARTICIPATION_ID|record --file REQUEST.json|event PARTICIPATION_ID --kind KIND --reason TEXT (audienti playbook SUBCOMMAND --help for the request shape)
|
|
94
95
|
Analytics: analytics show --from ISO --to ISO [--campaign ID] [--playbook-version ID] [--format json|csv]
|
|
95
96
|
analytics outbound [--workspace ID] [--days N | --from ISO --to ISO] [--by sender|action|day] [--format json|csv]
|
|
96
97
|
analytics activity [--workspace ID] [--days N | --from ISO --to ISO] [--format json|csv]
|
package/cli/intent.mjs
CHANGED
|
@@ -1,9 +1,50 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { callWorkspace, configuration } from './workspaces.mjs';
|
|
3
|
+
import { readFileSync, statSync } from 'node:fs';
|
|
3
4
|
import { readJsonFile } from './json-file.mjs';
|
|
5
|
+
import { printPaid } from './tools.mjs';
|
|
4
6
|
|
|
5
|
-
const RECORD_FLAGS = ['workspace', 'profile', 'person', 'evidence', 'label', 'quote', 'reason', 'confidence', 'request-id', 'participation', 'file'];
|
|
6
|
-
const
|
|
7
|
+
const RECORD_FLAGS = ['workspace', 'profile', 'person', 'evidence', 'label', 'quote', 'reason', 'confidence', 'request-id', 'participation', 'file', 'text', 'text-file', 'direction', 'channel', 'context'];
|
|
8
|
+
const SUGGEST_FLAGS = ['workspace', 'profile', 'text', 'text-file', 'direction', 'channel', 'context', 'request-id'];
|
|
9
|
+
const TEXT_MAX_BYTES = 16384;
|
|
10
|
+
const TEXT_MAX_CHARACTERS = 4000;
|
|
11
|
+
const CONTEXT_MAX_CHARACTERS = 2000;
|
|
12
|
+
const RECORD_ONLY_OK = ['workspace', 'profile', 'person', 'evidence', 'label', 'quote', 'reason', 'confidence', 'request-id', 'participation', 'file'];
|
|
13
|
+
|
|
14
|
+
function readText(path) {
|
|
15
|
+
let stat;
|
|
16
|
+
try { stat = statSync(path); } catch { throw Error(`Cannot read the message file ${path}. Check the path and try again.`); }
|
|
17
|
+
if (!stat.isFile() || stat.size > TEXT_MAX_BYTES) throw Error(`The message file must be a regular text file no larger than ${TEXT_MAX_BYTES / 1024} KiB: ${path}`);
|
|
18
|
+
try { return new TextDecoder('utf-8', { fatal: true }).decode(readFileSync(path)); } catch { throw Error(`The message file must be UTF-8 text: ${path}`); }
|
|
19
|
+
}
|
|
20
|
+
/** What the person should do after a call that did not give suggestions, in plain words. The JSON above it is for programs. */
|
|
21
|
+
const explain = requestId => result => result?.status === 'rejected'
|
|
22
|
+
? 'Nothing was charged. The call was not accepted. If the reason above is insufficient_credits, add credits in the app under Settings, then Billing, and run the command again.'
|
|
23
|
+
: `The model did not answer, so there are no suggestions. The charge is not settled yet. Run the same command again with --request-id ${requestId} to check or retry: the same request ID is never charged twice.`;
|
|
24
|
+
const money = value => value >= 1 ? value.toFixed(2) : value.toPrecision(2);
|
|
25
|
+
|
|
26
|
+
/** Suggest labels for a message. Paid: shows the price per million input tokens first, then makes the call. Records nothing. */
|
|
27
|
+
async function suggest(flags) {
|
|
28
|
+
if (Object.keys(flags).some(key => !SUGGEST_FLAGS.includes(key))) throw Error('Option does not apply to intent suggest.');
|
|
29
|
+
if ((flags.text === undefined) === (flags['text-file'] === undefined)) throw Error(`Give the message once: --text TEXT or --text-file PATH. ${SUGGEST_USAGE}`);
|
|
30
|
+
if (!flags.channel) throw Error(`--channel is required (for example email or linkedin). ${SUGGEST_USAGE}`);
|
|
31
|
+
const direction = flags.direction ?? 'inbound';
|
|
32
|
+
if (!['inbound', 'outbound'].includes(direction)) throw Error(`--direction must be inbound (a message they sent) or outbound (one we sent). ${SUGGEST_USAGE}`);
|
|
33
|
+
const text = flags.text ?? readText(flags['text-file']);
|
|
34
|
+
if (!text.trim()) throw Error('The message has no words. Give the text of one message.');
|
|
35
|
+
if (Array.from(text).length > TEXT_MAX_CHARACTERS) throw Error(`The message is ${Array.from(text).length} characters; the most is ${TEXT_MAX_CHARACTERS}. Send only the new message, without the quoted thread.`);
|
|
36
|
+
if (flags.context !== undefined && Array.from(flags.context).length > CONTEXT_MAX_CHARACTERS) throw Error(`--context is too long; the most is ${CONTEXT_MAX_CHARACTERS} characters.`);
|
|
37
|
+
const config = configuration(flags.profile);
|
|
38
|
+
const entry = await callWorkspace('tools_get', { workspaceId: flags.workspace, tool: 'audienti.intent.label' }, config);
|
|
39
|
+
const price = entry?.data?.tokenPrice;
|
|
40
|
+
if (!price || typeof price.usd !== 'number') throw Error('Could not read the price of intent suggest. Nothing was charged.');
|
|
41
|
+
process.stderr.write(`Price: ${money(price.credits)} credits (about $${money(price.usd)}) per 1M input tokens. You pay for the tokens measured, so one short message costs a small part of a credit (for example, about ${money(price.credits * 3000 / 1e6)} credits for a 1,000-character message). Output is free. Nothing is recorded.\n`);
|
|
42
|
+
const requestId = flags['request-id'] ?? randomUUID();
|
|
43
|
+
if (!flags['request-id']) process.stderr.write(`request-id: ${requestId}\n`);
|
|
44
|
+
await printPaid('tools_intent_label', { workspaceId: flags.workspace, requestId, input: { text, direction, channel: flags.channel, ...(flags.context ? { context: flags.context } : {}) } }, { profile: flags.profile, explain: explain(requestId) });
|
|
45
|
+
}
|
|
46
|
+
const SUGGEST_USAGE = 'Use: intent suggest (--text TEXT | --text-file PATH) --channel email|linkedin [--direction inbound|outbound] [--context TEXT] [--request-id UUID] [--workspace ID].';
|
|
47
|
+
const USAGE = 'Use intent list [--workspace ID], intent suggest (--text TEXT | --text-file PATH) --channel email|linkedin [--direction inbound|outbound] [--context TEXT] [--request-id UUID] [--workspace ID], or intent record --person ID --evidence ID (--label NAME --quote TEXT --reason TEXT [--confidence high|medium|low] | --file LABELS.json) [--request-id UUID] [--participation ID] [--workspace ID].';
|
|
7
48
|
|
|
8
49
|
export async function intentCli(args) {
|
|
9
50
|
const flags = {}, positions = [];
|
|
@@ -16,12 +57,14 @@ export async function intentCli(args) {
|
|
|
16
57
|
flags[key] = args[++i];
|
|
17
58
|
}
|
|
18
59
|
const command = positions[1];
|
|
19
|
-
if (positions.length !== 2 || positions[0] !== 'intent' || !['list', 'record'].includes(command)) throw Error(USAGE);
|
|
60
|
+
if (positions.length !== 2 || positions[0] !== 'intent' || !['list', 'suggest', 'record'].includes(command)) throw Error(USAGE);
|
|
20
61
|
if (command === 'list') {
|
|
21
62
|
if (Object.keys(flags).some(key => !['workspace', 'profile'].includes(key))) throw Error('Option does not apply to intent list.');
|
|
22
63
|
console.log(JSON.stringify(await callWorkspace('intent_labels_list', { workspaceId: flags.workspace }, configuration(flags.profile))));
|
|
23
64
|
return;
|
|
24
65
|
}
|
|
66
|
+
if (command === 'suggest') { await suggest(flags); return; }
|
|
67
|
+
if (Object.keys(flags).some(key => !RECORD_ONLY_OK.includes(key))) throw Error('Option does not apply to intent record.');
|
|
25
68
|
if (!flags.person || !flags.evidence) throw Error(`--person ID and --evidence ID are required. ${USAGE}`);
|
|
26
69
|
const single = ['label', 'quote', 'reason', 'confidence'].filter(key => flags[key] !== undefined);
|
|
27
70
|
if (flags.file && single.length) throw Error('Give the labels in --file, or one label with --label, --quote and --reason. Not both.');
|
package/cli/playbook-help.mjs
CHANGED
|
@@ -67,6 +67,10 @@ export const playbookCommands = {
|
|
|
67
67
|
record: {
|
|
68
68
|
usage: 'playbook record --file REQUEST.json [--workspace ID] [--profile PATH]',
|
|
69
69
|
about: 'Report that a person moved to a stage or off-ramp, or finished the current stage play. The file has participationId, expectedVersion (the version from playbook progress), requestId (a fresh UUID), exactly one of stageKey, offRampKey or finishStage true, reason, and evidence (a list of {kind: observation|conversation, id}).'
|
|
70
|
+
},
|
|
71
|
+
event: {
|
|
72
|
+
usage: 'playbook event PARTICIPATION_ID --kind KIND --reason TEXT [--evidence conversation:ID|observation:ID ...] [--at ISO] [--request-id UUID] [--file REQUEST.json] [--workspace ID] [--profile PATH]',
|
|
73
|
+
about: 'Record one event for a person, then let the playbook settle. KIND is meeting_requested (a meeting was asked for), meeting_accepted (agreed to, no time yet), meeting_declined, meeting_booked (a meeting has a time), not_a_fit (the person is not a fit) or steps_done (the steps of the current stage are done). A stage that lists the event as an entry event takes the person forward; the playbook rules decide the rest. not_a_fit ends the person in the not_fit off-ramp when the playbook has one, and otherwise only shows in the history. steps_done applies the current stage completion (next stage, stay or off-ramp). REASON is 1 to 300 characters and shows in the history. --evidence names stored evidence about this person: conversation:ID is a message id (the conversation ids in the person timeline, audienti prospects timeline), observation:ID a profile observation id. Repeat it for each piece, up to 20. --at is an ISO time with a timezone offset, for example 2026-11-06T14:30:00Z. Left out, the time is now; a future time counts as now, and a time before the person entered the stage counts as just after it. --request-id is made for you when left out; pass the same UUID to retry safely. Only the person\'s assignee or a workspace Admin may record. A repeat writes nothing and answers recorded false. A person who has left the campaign is refused with participation_ended, with two exceptions: meeting_booked is still recorded, and a repeat of meeting_booked or not_a_fit answers recorded false with the eventId already recorded.'
|
|
70
74
|
}
|
|
71
75
|
};
|
|
72
76
|
const lines = Object.values(playbookCommands).map(command => command.usage);
|
|
@@ -9,7 +9,7 @@ const eventRule=z.object({key:z.string().uuid(),when:z.string().min(1).max(60).d
|
|
|
9
9
|
const stepRoutes=z.object({accept:routeTarget.optional(),reply:routeTarget.optional(),meeting:routeTarget.optional(),timeout:routeTarget.optional()}).strict().describe("Where an event that reaches the person after this step ran sends them. A route wins over the stage's jump list; an event with no route follows the stage. Going to an earlier stage needs rules.allowBackward.");
|
|
10
10
|
const playbookStepSchema=z.object({key:z.string().uuid(),channel:z.enum(['LinkedIn','Email','Custom']),action:label,condition:z.enum(['Always','Only if viable','Only if connected']).optional().describe('Left out: Only if connected for a LinkedIn message (it can only reach a connection), Always for everything else. Only if connected skips the step for a person who was asked to connect and has not accepted. Only if viable needs viability.'),viability:text.optional(),instructions:text.optional().describe('What the agent should write or do. Left out, one coaching sentence for the kind of action.'),wait:z.object({until:z.enum(['accept','reply','meeting','timeout','event']),days:z.number().int().min(1).max(60),event:label.optional().describe('Custom steps only, with until event: the name of the event a person records to end the wait, for example Gift delivered.'),followUps:z.number().int().min(0).max(10).optional().describe('Meeting waits only: how many follow-ups your agent writes, one after each wait, before the meeting is marked No answer. Default 3.')}).strict().nullable().optional().describe('How long the step waits and for what. Left out on a new step that sends: a reply wait of 3 days (a connection request waits 7 days for the accept). null means no wait. A step the playbook already has keeps what it has.'),waitDays:z.number().int().min(1).max(60).optional().describe('Older form of wait: the same as wait {until: timeout, days}.'),side:z.boolean().optional(),onTimeout:z.enum(['next','off_ramp']).optional(),humanize:z.boolean().optional().describe('Email only. Rewrite the email text before approval so it reads as written by a person. On by default; set false to send the text as written.'),actionId:z.string().max(80).optional().describe('An action id from the outreach rulebook, for example linkedin.message.send.'),routes:stepRoutes.optional(),eventRules:z.array(eventRule).max(10).optional()}).strict();
|
|
11
11
|
const completion=z.discriminatedUnion('kind',[z.object({kind:z.literal('next')}).strict(),z.object({kind:z.literal('stay')}).strict(),z.object({kind:z.literal('off_ramp'),offRampKey:z.string().uuid()}).strict()]);
|
|
12
|
-
const stageFields=identity.extend({owner:z.enum(['Agent','Assignee']).optional(),goalDays:z.number().int().min(0).max(365).optional().describe('Days a person should take in this stage. Left out: the waits of its steps plus 2 days, at least 3.'),enabled:z.boolean().optional().describe('false skips the stage: people are never moved into it. The first stage and the goal stage cannot be skipped.'),steps:z.array(playbookStepSchema).max(20).optional(),completion:completion.optional(),on:z.array(z.enum(['accept','reply','meeting'])).max(
|
|
12
|
+
const stageFields=identity.extend({owner:z.enum(['Agent','Assignee']).optional(),goalDays:z.number().int().min(0).max(365).optional().describe('Days a person should take in this stage. Left out: the waits of its steps plus 2 days, at least 3.'),enabled:z.boolean().optional().describe('false skips the stage: people are never moved into it. The first stage and the goal stage cannot be skipped.'),steps:z.array(playbookStepSchema).max(20).optional(),completion:completion.optional(),on:z.array(z.enum(['accept','reply','meeting_requested','meeting_accepted','meeting_declined','meeting'])).max(6).optional().describe('The events that jump a person forward to this stage: accept, reply, meeting_requested (a meeting was asked for), meeting_accepted (agreed to, no time yet), meeting_declined, meeting (a booked meeting). A person who has one of these events moves to the furthest later stage that lists it, and the stages passed over are recorded as skipped. Leave it out for a stage people reach when the stage before it finishes, or when a person moves them. Not for the first stage.'),eventRules:z.array(eventRule).max(10).optional()});
|
|
13
13
|
// Settings the product no longer asks for (#457). An older request may still carry them: they are accepted, ignored and left out of the new version.
|
|
14
14
|
// autoMove: conflict 20, approval lives on the account. flagOverdue, emailWindow, nurtureDays: no code read them. optional (stage): use enabled. movesInWhen (words) and 'manual' in on: the stage's events say when a person enters it.
|
|
15
15
|
const dropKeys=keys=>value=>{if(!value||typeof value!=='object'||Array.isArray(value)||!keys.some(key=>key in value))return value;return Object.fromEntries(Object.entries(value).filter(([key])=>!keys.includes(key)));};
|
|
@@ -34,5 +34,6 @@ export const playbookOperations={
|
|
|
34
34
|
workspace_pipeline_get:{schema:z.object({...scope,campaignId:uuid.optional(),pinId:uuid.optional()}).strict(),method:'GET',path:a=>`${base(a)}/pipeline?${query(a)}`,scoped:true,description:'Read the pipeline board: stages of one playbook version, the people currently in each stage, and counts of people closed out through each off-ramp. Free CRM read.'},
|
|
35
35
|
playbook_progress_get:{schema:z.object({...scope,participationId:uuid.describe('A participation ID (one person in one campaign, from the pipeline), not a playbook ID.')}).strict(),method:'GET',path:a=>`${base(a)}/participations/${a.participationId}/progress`,scoped:true,description:'Read the participation’s admitted playbook pin and recorded stage/outcome history. Takes a participation ID (a person in a campaign; each person in the pipeline has one), not a playbook ID.'},
|
|
36
36
|
playbook_progress_record:{schema:z.object({...scope,participationId:uuid,expectedVersion:z.number().int().nonnegative(),requestId:uuid,stageKey:uuid.optional(),offRampKey:uuid.optional(),finishStage:z.literal(true).optional(),reason:z.string().trim().min(1).max(2000),evidence:z.array(z.object({kind:z.enum(['observation','conversation']),id:uuid}).strict()).max(20)}).strict(),method:'POST',path:a=>`${base(a)}/participations/${a.participationId}/progress`,body:({workspaceId,participationId,...a})=>a,scoped:true,description:'Report a stage, off-ramp, or finishStage:true after externally completing the current play and waits. Finish resolves next/stay/off-ramp from the admitted version. Stored evidence required for agents; human-review and backward-move rules apply. Assigned owner/Admin only. Goal ends prospecting; post-goal forward reporting never reactivates. No send or provider call.'},
|
|
37
|
+
playbook_event_record:{schema:z.object({...scope,participationId:uuid.describe('A participation ID (one person in one campaign, from the pipeline), not a playbook ID.'),requestId:uuid,kind:z.enum(['meeting_requested','meeting_accepted','meeting_declined','meeting_booked','not_a_fit','steps_done']).describe('meeting_requested: a meeting was asked for. meeting_accepted: agreed to, no time yet. meeting_declined: turned down. meeting_booked: a meeting has a time. not_a_fit: the person is not a fit. steps_done: the steps of the current stage are done.'),reason:z.string().trim().min(1).max(300).describe('Why, in one or two sentences. It shows in the person’s history.'),evidence:z.array(z.object({kind:z.enum(['observation','conversation']),id:uuid}).strict()).max(20).optional(),at:z.string().datetime({offset:true}).optional().describe('When it happened, ISO 8601. Defaults to now and is never later than now.')}).strict(),method:'POST',path:a=>`${base(a)}/participations/${a.participationId}/events`,body:({workspaceId,participationId,...a})=>a,scoped:true,description:'Record one event for a person: a meeting asked for, agreed to, turned down or booked, not a fit, or the steps of the current stage done. The playbook then settles: stages that list the event as an entry event take the person forward, and the rules decide the rest (not_a_fit ends the person in the not_fit off-ramp when the playbook has one). Safe to repeat: a second call writes nothing and answers recorded false. Ended participation is refused with participation_ended. Assigned owner/Admin only. No send or provider call.'},
|
|
37
38
|
workspace_analytics_get:{schema:z.object({...scope,campaignId:uuid.optional(),ownerUserId:uuid.optional(),offerId:uuid.optional(),audienceId:uuid.optional(),tag:z.string().min(1).max(64).optional(),pinId:uuid.optional(),from:z.string().datetime(),to:z.string().datetime()}).strict(),method:'GET',path:a=>`${base(a)}/analytics?${query(a)}`,scoped:true,description:'Read UTC-period distinct outcomes and explicit stage events. Missing activity or cost attribution is not tracked, never fabricated zero. Optional filters: campaignId, ownerUserId (campaign owner), offerId, audienceId, tag (campaign tag); list the values with workspace_analytics_filters. Maximum 366 days; narrow large scopes.'}
|
|
38
39
|
};
|
package/cli/progress.mjs
CHANGED
|
@@ -3,22 +3,23 @@ import {callWorkspace,configuration} from './workspaces.mjs';
|
|
|
3
3
|
import {readJsonFile} from './json-file.mjs';
|
|
4
4
|
import {playbookUsageError,playbookCommands} from './playbook-help.mjs';
|
|
5
5
|
export async function progressCli(args){
|
|
6
|
-
const positions=[],flags={};for(let i=0;i<args.length;i++){const arg=args[i];if(!arg.startsWith('--')){positions.push(arg);continue;}const key=arg.slice(2);if(!['profile','workspace','file','cursor','limit','revision','from','to','campaign','playbook-version','kind','user','format','owner','offer','audience','tag','archived','request-id','expected-updated-at'].includes(key)||(key!=='archived'&&(!args[i+1]||args[i+1].startsWith('--')))||Object.hasOwn(flags,key))throw new Error(`Unknown or incomplete option --${key}.${args[0]==='playbook'?' Run audienti playbook SUBCOMMAND --help.':''}`);flags[key]=key==='archived'&&(!args[i+1]||args[i+1].startsWith('--'))?'true':args[++i];}
|
|
7
|
-
const names={playbook:{list:'playbook_list',actions:'playbook_actions_list',show:'playbook_get',save:'playbook_save',archive:'playbook_archive',restore:'playbook_restore',draft_show:'playbook_draft_get',draft_save:'playbook_draft_save',draft_discard:'playbook_draft_discard',draft_publish:'playbook_draft_publish',delete:'playbook_delete',progress:'playbook_progress_get',record:'playbook_progress_record'},analytics:{show:'workspace_analytics_get'},pipeline:{show:'workspace_pipeline_get'},connections:{list:'workspace_connections_list',register:'workspace_connection_register',report:'workspace_connection_report',disconnect:'workspace_connection_disconnect'}};
|
|
6
|
+
const positions=[],flags={};for(let i=0;i<args.length;i++){const arg=args[i];if(!arg.startsWith('--')){positions.push(arg);continue;}const key=arg.slice(2);if(!['profile','workspace','file','cursor','limit','revision','from','to','campaign','playbook-version','kind','user','format','owner','offer','audience','tag','archived','request-id','expected-updated-at','reason','evidence','at'].includes(key)||(key!=='archived'&&(!args[i+1]||args[i+1].startsWith('--')))||(key!=='evidence'&&Object.hasOwn(flags,key)))throw new Error(`Unknown or incomplete option --${key}.${args[0]==='playbook'?' Run audienti playbook SUBCOMMAND --help.':''}`);if(key==='evidence'){(flags.evidence??=[]).push(args[++i]);continue;}flags[key]=key==='archived'&&(!args[i+1]||args[i+1].startsWith('--'))?'true':args[++i];}
|
|
7
|
+
const names={playbook:{list:'playbook_list',actions:'playbook_actions_list',show:'playbook_get',save:'playbook_save',archive:'playbook_archive',restore:'playbook_restore',draft_show:'playbook_draft_get',draft_save:'playbook_draft_save',draft_discard:'playbook_draft_discard',draft_publish:'playbook_draft_publish',delete:'playbook_delete',progress:'playbook_progress_get',record:'playbook_progress_record',event:'playbook_event_record'},analytics:{show:'workspace_analytics_get'},pipeline:{show:'workspace_pipeline_get'},connections:{list:'workspace_connections_list',register:'workspace_connection_register',report:'workspace_connection_report',disconnect:'workspace_connection_disconnect'}};
|
|
8
8
|
// playbook draft show|save|discard|publish ID is one command name in two words.
|
|
9
9
|
if(positions[0]==='playbook'&&positions[1]==='draft'&&['show','save','discard','publish'].includes(positions[2]))positions.splice(1,2,`draft_${positions[2]}`);
|
|
10
10
|
const name=names[positions[0]]?.[positions[1]];if(!name)throw new Error(positions[0]==='playbook'?playbookUsageError:'Use analytics show --from ISO --to ISO; pipeline show; connections list|register --file PATH|report --file PATH|disconnect --file PATH.');
|
|
11
11
|
if(flags.format&&(name!=='workspace_analytics_get'||!['json','csv'].includes(flags.format)))throw new Error('--format json|csv is only accepted for analytics show.');
|
|
12
|
-
const fileNames=['playbook_save','playbook_draft_save','playbook_progress_record','workspace_connection_register','workspace_connection_report','workspace_connection_disconnect'];const withId=['playbook_get','playbook_progress_get','playbook_archive','playbook_restore','playbook_delete','playbook_draft_get','playbook_draft_save','playbook_draft_discard','playbook_draft_publish'].includes(name);if(positions.length!==(withId?3:2))throw new Error(positions[0]==='playbook'?`Unexpected arguments. Usage: audienti ${playbookCommands[positions[1]].usage}`:'Unexpected arguments.');
|
|
13
|
-
if(fileNames.includes(name)&&!flags.file)throw new Error('Supply a JSON request with --file PATH.');if(!
|
|
14
|
-
const input=
|
|
15
|
-
if(flags['request-id']!==undefined
|
|
12
|
+
const fileNames=['playbook_save','playbook_draft_save','playbook_progress_record','workspace_connection_register','workspace_connection_report','workspace_connection_disconnect'];const withId=['playbook_get','playbook_progress_get','playbook_archive','playbook_restore','playbook_delete','playbook_draft_get','playbook_draft_save','playbook_draft_discard','playbook_draft_publish','playbook_event_record'].includes(name);if(positions.length!==(withId?3:2))throw new Error(positions[0]==='playbook'?`Unexpected arguments. Usage: audienti ${playbookCommands[positions[1]].usage}`:'Unexpected arguments.');
|
|
13
|
+
const takesFile=fileNames.includes(name)||name==='playbook_event_record';if(fileNames.includes(name)&&!flags.file)throw new Error('Supply a JSON request with --file PATH.');if(!takesFile&&flags.file)throw new Error('--file is only accepted for mutations.');
|
|
14
|
+
const input=takesFile&&flags.file?readJsonFile(flags.file,65536,'Request file'):{};if(!input||typeof input!=='object'||Array.isArray(input))throw new Error('Request must be an object.');if(flags.workspace)input.workspaceId=flags.workspace;if(withId)input[['playbook_progress_get','playbook_event_record'].includes(name)?'participationId':'id']=positions[2];
|
|
15
|
+
if(flags['request-id']!==undefined&&!['playbook_draft_publish','playbook_event_record'].includes(name))throw new Error('--request-id is only accepted for playbook draft publish and playbook event.');
|
|
16
|
+
if(name==='playbook_event_record')input.requestId=flags['request-id']??input.requestId??randomUUID();else if(flags.reason!==undefined||flags.evidence!==undefined||flags.at!==undefined)throw new Error('--reason, --evidence and --at are only accepted for playbook event.');
|
|
16
17
|
if(flags['expected-updated-at']!==undefined&&name!=='playbook_draft_discard')throw new Error('--expected-updated-at is only accepted for playbook draft discard.');
|
|
17
18
|
if(flags['expected-updated-at']!==undefined)input.expectedUpdatedAt=flags['expected-updated-at'];
|
|
18
19
|
// A generated request ID is printed, so a retry of a call that may have worked can use the same one.
|
|
19
20
|
if(name==='playbook_draft_publish'){input.requestId=flags['request-id']??randomUUID();if(flags['request-id']===undefined)console.error(`requestId ${input.requestId} (retry with --request-id ${input.requestId} if this call may have worked)`);}
|
|
20
21
|
if(flags.archived!==undefined&&(name!=='playbook_list'||!['true','false'].includes(flags.archived)))throw new Error(name==='playbook_list'?'--archived takes true or false, or no value.':'--archived is only accepted for playbook list.');
|
|
21
|
-
for(const[key,value]of Object.entries(flags)){if(['workspace','profile','file','format','request-id','expected-updated-at'].includes(key))continue;if(key==='archived'){input.archived=value==='true';continue;}const field={campaign:'campaignId','playbook-version':'pinId',user:'userId',owner:'ownerUserId',offer:'offerId',audience:'audienceId'}[key]??key;input[field]=['limit','revision'].includes(key)?Number(value):value;}
|
|
22
|
+
for(const[key,value]of Object.entries(flags)){if(['workspace','profile','file','format','request-id','expected-updated-at'].includes(key))continue;if(key==='evidence'){input.evidence=value.map(item=>{const [kind,id,...extra]=item.split(':');if(extra.length||!['observation','conversation'].includes(kind)||!id)throw new Error('--evidence takes conversation:ID or observation:ID.');return{kind,id};});continue;}if(key==='archived'){input.archived=value==='true';continue;}const field={campaign:'campaignId','playbook-version':'pinId',user:'userId',owner:'ownerUserId',offer:'offerId',audience:'audienceId'}[key]??key;input[field]=['limit','revision'].includes(key)?Number(value):value;}
|
|
22
23
|
const result=await callWorkspace(name,input,configuration(flags.profile));
|
|
23
24
|
if(flags.format==='csv'){process.stdout.write(analyticsCsv(result?.data??result));return;}
|
|
24
25
|
console.log(JSON.stringify(result));
|
package/cli/tools-operations.mjs
CHANGED
|
@@ -43,6 +43,7 @@ export const hostedToolOperations = {
|
|
|
43
43
|
tools_proxy_sessions_create:{tool:'proxy.sessions.create',paid:true,limits:{maxSeconds:3600,concurrentWorkspaceConnections:32,meter:'upstream_tcp_payload_bytes'},schema:z.object({...workspace,requestId:uuid,input:z.object({ttlSeconds:z.number().int().min(60).max(3600).optional(),parentOperationId:uuid.optional()}).strict()}).strict(),method:'POST',path:a=>root(a)+'/proxy.sessions.create',body:a=>({requestId:a.requestId,input:a.input}),scoped:true,timeoutMs:30000},
|
|
44
44
|
tools_proxy_sessions_close:{tool:'proxy.sessions.close',schema:z.object({...workspace,operationId:uuid}).strict(),method:'POST',path:a=>root(a)+'/proxy.sessions.close',body:a=>({operationId:a.operationId}),scoped:true},
|
|
45
45
|
tools_decide:{tool:'decide',paid:true,schema:z.object({...workspace,requestId:uuid,input:z.object({state:z.union([z.string(),z.record(z.string(),z.unknown()),z.array(z.unknown())]),questions:z.record(key,question).refine(v=>Object.keys(v).length>=1&&Object.keys(v).length<=16)}).strict()}).strict(),method:'POST',path:a=>root(a)+'/decide',body:a=>({requestId:a.requestId,input:a.input}),scoped:true,timeoutMs:30000},
|
|
46
|
+
tools_intent_label:{tool:'intent.label',paid:true,limits:{textCharacters:4000,contextCharacters:2000,suggestions:2},description:'Suggest what a message means. Paid: built on decide, billed on the input tokens the provider measures at the decide price (read it first with tools_get audienti.intent.label: tokenPrice). Give the message text, direction (inbound or outbound) and channel, and optionally context. Returns up to two suggestions from the intent label list (one reading, one meeting label), each with a quote that is words of the message, a plain reason, a confidence and any typed detail still to add (needs). Records nothing and sends nothing: record a suggestion you keep with intent_record, which runs every check again. Reuse requestId after any interruption; a replay is free.',schema:z.object({...workspace,requestId:uuid,input:z.object({text:z.string().min(1).max(4000),direction:z.enum(['inbound','outbound']),channel:z.enum(['email','linkedin']),context:z.string().trim().min(1).max(2000).optional()}).strict()}).strict(),method:'POST',path:a=>root(a)+'/intent.label',body:a=>({requestId:a.requestId,input:a.input}),scoped:true,timeoutMs:30000},
|
|
46
47
|
tools_profiles_fetch:{tool:'profiles.fetch',paid:true,schema:z.object({...workspace,requestId:uuid,input:z.object({url:z.string().min(1).max(1024),refresh:z.boolean().optional(),cached:z.boolean().optional(),fields:z.array(z.enum(['name','headline','about','location','experience','currentPositions','education','skills','websites','photo','connections','followers','certifications','languages','industries','employeeCount','employeeCountRange','founded','specialities','locations','companyType'])).min(1).max(20).optional()}).strict()}).strict(),method:'POST',path:a=>root(a)+'/profiles.fetch',body:a=>({requestId:a.requestId,input:a.input}),scoped:true,timeoutMs:30000},
|
|
47
48
|
tools_runs_get:{schema:z.object({...workspace,operationId:uuid,attemptAfter:z.number().int().min(0).max(2147483647).optional(),entryAfter:uuid.optional()}).strict(),method:'GET',path:a=>root(a)+`/runs/${a.operationId}`+((a.attemptAfter!==undefined||a.entryAfter)?`?${new URLSearchParams({...a.attemptAfter!==undefined?{attemptAfter:String(a.attemptAfter)}:{},...a.entryAfter?{entryAfter:a.entryAfter}:{}})}`:''),scoped:true},
|
|
48
49
|
tools_runs_list:{schema:z.object({...workspace,cursor:uuid.optional()}).strict(),method:'GET',path:a=>root(a)+'/runs'+(a.cursor?`?cursor=${encodeURIComponent(a.cursor)}`:''),scoped:true},
|
package/cli/tools.mjs
CHANGED
|
@@ -54,12 +54,12 @@ async function readStdin() {
|
|
|
54
54
|
try{return JSON.parse(new TextDecoder('utf-8',{fatal:true}).decode(Buffer.concat(chunks)));}catch{throw new Error('Tool input must be valid UTF-8 JSON.');}
|
|
55
55
|
}
|
|
56
56
|
const asJson=value=>{try{return JSON.parse(value);}catch{throw new Error('Tool input must be valid JSON.');}};
|
|
57
|
-
async function printPaid(name,args,values){
|
|
57
|
+
export async function printPaid(name,args,values){
|
|
58
58
|
try{
|
|
59
59
|
const result=await callWorkspace(name,args,configuration(values.profile));
|
|
60
60
|
const paidResult=paidToolResult(name,result?.data,args);
|
|
61
61
|
if(['failed','uncertain','rejected'].includes(paidResult?.status)){
|
|
62
|
-
process.stderr.write(JSON.stringify({error:{code:paidResult.error?.code??'tool_incomplete'},operationId:paidResult.operationId,requestId:args.requestId,billing:paidResult.billing,...(paidResult.result?.persistence?{result:paidResult.result}:{}),requestTraceId:result.requestTraceId,recovery:paidResult.status==='rejected'?'resolve_rejection_then_new_request_id':paidResult.result?.persistence?.recovery??'retry_same_request_id'})+'\n');process.exitCode=1;return;
|
|
62
|
+
process.stderr.write(JSON.stringify({error:{code:paidResult.error?.code??'tool_incomplete'},operationId:paidResult.operationId,requestId:args.requestId,billing:paidResult.billing,...(paidResult.result?.persistence?{result:paidResult.result}:{}),requestTraceId:result.requestTraceId,recovery:paidResult.status==='rejected'?'resolve_rejection_then_new_request_id':paidResult.result?.persistence?.recovery??'retry_same_request_id'})+'\n');if(values.explain)process.stderr.write(values.explain(paidResult)+'\n');process.exitCode=1;return;
|
|
63
63
|
}
|
|
64
64
|
console.log(JSON.stringify(result));
|
|
65
65
|
}catch(error){
|
package/package.json
CHANGED
|
@@ -6,8 +6,8 @@ approved: inbound wins, and you record it. What the user approves is your answer
|
|
|
6
6
|
## What to do
|
|
7
7
|
|
|
8
8
|
1. Read the conversation: `audienti prospects conversation list PERSON --workspace ID`.
|
|
9
|
-
2. Classify the reply as one of `interested`, `question`, `later`, `
|
|
10
|
-
`stop`, `bounce`, `referral` or `wrong_person` (the prospect is the wrong person and
|
|
9
|
+
2. Classify the reply as one of `interested`, `question`, `later`, `not_interested` (a clear no thanks),
|
|
10
|
+
`out_of_office`, `stop`, `bounce`, `referral` or `wrong_person` (the prospect is the wrong person and
|
|
11
11
|
names no one else). A stop, a bounce or a referral must carry its typed
|
|
12
12
|
`result`, or the report is refused; see [Stop, bounce and referral](#stop-bounce-and-referral).
|
|
13
13
|
3. Draft the answer from the mailbox or LinkedIn account the reply came to (the assignee's).
|
|
@@ -113,6 +113,12 @@ values and the `next` step. The checks:
|
|
|
113
113
|
reply and at most one meeting label.
|
|
114
114
|
- The typed detail is present: a `stop`, `bounce` or `referral` needs its `result`; `meeting_booked` needs `meeting`.
|
|
115
115
|
|
|
116
|
+
To get a second reading before you record, `audienti intent suggest --channel email --text "..."` asks a model
|
|
117
|
+
to suggest labels. It costs credits: the call prints the price per million input tokens first, and a message
|
|
118
|
+
uses a small part of that. It returns up to two suggestions, each with a `quote`, a `reason`, a `confidence` and
|
|
119
|
+
`needs` (the typed detail to add, for example the `scope` of a stop). It records nothing. Keep, change or drop
|
|
120
|
+
a suggestion, then record it with `intent record`, which runs every check above again.
|
|
121
|
+
|
|
116
122
|
`replies set` records the same labels. Add `"intent": {"quote": "...", "reason": "..."}` next to `classification`
|
|
117
123
|
or `meetingState` and it runs the same checks and stores the words on the event. Without `intent` it works as before.
|
|
118
124
|
|
|
@@ -30,6 +30,10 @@ Use this skill when:
|
|
|
30
30
|
playbook, so the two can be compared in Analytics.
|
|
31
31
|
- Saving a playbook never changes campaigns already pinned to it. Pin the new
|
|
32
32
|
revision on purpose.
|
|
33
|
+
- Give the playbook an off-ramp with reason `rejected` and one with reason `not_fit`. The default
|
|
34
|
+
rules use them: a reply that says no thanks ends the person in the first, and a `not_a_fit` event
|
|
35
|
+
ends the person in the second. Without them the event only shows in the history. The guide
|
|
36
|
+
`docs/guides/playbook-agent-guide.md` (Events and rules) lists every event.
|
|
33
37
|
- Never invent results or proof points for the voice. Use the user's words.
|
|
34
38
|
- Every first email ends with one plain sentence that lets the prospect opt out, such
|
|
35
39
|
as "If this is not for you, reply and I will not write again." Say so in the first
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
| `name` | 1 to 120 characters. Name the strategy, not the campaign. |
|
|
17
17
|
| `stages` | 2 to 30 stages, in order. Leave it out for the default skeleton (see Defaults). |
|
|
18
18
|
| `goalKey` | The `key` of the goal stage. Not the first stage. Left out, it is the last stage (with `stages` left out too, the skeleton's last stage). |
|
|
19
|
-
| `offRamps` | Up to 30 ways out: `{ key, name, reason }`. `reason` is `rejected`, `not_fit`, `nurture`, `unresponsive` or `other`. The system sets `taken_over`, `bounced` and `skipped` itself; do not choose them. "Bad data" and "repair" are not off-ramps. |
|
|
19
|
+
| `offRamps` | Up to 30 ways out: `{ key, name, reason }`. `reason` is `rejected`, `not_fit`, `nurture`, `unresponsive` or `other`. The default rules end a person in the off-ramp with reason `rejected` when the reply says no thanks (`not_interested`), and in the one with reason `not_fit` when you record `not_a_fit`. A playbook without that off-ramp keeps the person where they are. The system sets `taken_over`, `bounced` and `skipped` itself; do not choose them. "Bad data" and "repair" are not off-ramps. |
|
|
20
20
|
| `voice` | How messages should sound, in the user's style. |
|
|
21
21
|
| `eventRules` | Optional: what happens when an event reaches a person, for any stage and step. A new playbook starts with three (below); leave the field out to keep them, or send the whole list to replace it. See Event rules. |
|
|
22
22
|
| `rules` | Optional: `allowBackward` (boolean, default false): let a move go to an earlier stage. Approval of a move is a setting on the account, not a playbook rule. |
|
|
@@ -61,7 +61,7 @@ The other items are warnings; read them after each save and clear them:
|
|
|
61
61
|
| --- | --- |
|
|
62
62
|
| `key` | A UUID, unique in the playbook. Keep it across revisions. |
|
|
63
63
|
| `name` | Unique in the playbook. |
|
|
64
|
-
| `on` | The events that jump a prospect forward to this stage: `accept` (they accept your LinkedIn connection request, not a meeting invite), `reply` or `meeting` (a booked meeting). Do not list `accept` or `reply` on the goal stage unless a reply or an accept should count as a win. An event moves the prospect to the furthest later stage that lists it; the stages passed over are recorded as skipped, never as done. Leave it out for a stage people reach when the stage before it finishes, or when a person moves them. Do not set it on the first stage. People and the pipeline read "Starts when they reply" from it. The older `movesInWhen` text and the value `manual` are accepted and ignored. |
|
|
64
|
+
| `on` | The events that jump a prospect forward to this stage: `accept` (they accept your LinkedIn connection request, not a meeting invite), `reply`, `meeting_requested` (a meeting was asked for), `meeting_accepted` (they said yes, no time yet), `meeting_declined` or `meeting` (a booked meeting). Do not list `accept` or `reply` on the goal stage unless a reply or an accept should count as a win. An event moves the prospect to the furthest later stage that lists it; the stages passed over are recorded as skipped, never as done. Leave it out for a stage people reach when the stage before it finishes, or when a person moves them. Do not set it on the first stage. People and the pipeline read "Starts when they reply" from it. The older `movesInWhen` text and the value `manual` are accepted and ignored. |
|
|
65
65
|
| `owner` | `Agent` or `Assignee` (the person assigned to the prospect). |
|
|
66
66
|
| `goalDays` | 0 to 365. The days after which a prospect in this stage is overdue (the pipeline card turns orange). 0 means never overdue. |
|
|
67
67
|
| `enabled` | Defaults to true. `false` skips the stage: no one is moved into it. The first stage and the goal stage cannot be skipped. |
|
package/source-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"repository": "https://github.com/omalab/exora",
|
|
3
|
-
"sourceCommit": "
|
|
3
|
+
"sourceCommit": "5baa5f3af7b95f75d8e8f9d7467f85b98a1029f2",
|
|
4
4
|
"files": {
|
|
5
5
|
"LICENSE": "220f297cfcd5c38eb64e6b4b4a77cab4ebc7f4686d4d99c6260a475d02ca11e5",
|
|
6
6
|
"README.md": "7ff32cc8ac89dd54b64d7b39c0b41b1f37e154b7ea10ad5a7bceefc3df77d87f",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"cli/account-intake-operations.mjs": "b43d764c628beabafad753d711ddb2af2c64276e4a6506ed0b854839091ea5db",
|
|
9
9
|
"cli/account-intake.mjs": "aa77f2f96fd030f8830d6de278932186aea7c82cfda086a5a6cf569202feebc8",
|
|
10
10
|
"cli/account-replies.mjs": "699e34e5c736ba316df8f164b4c50f82a7e4e2d5e51303e6b13944c3f2c854ab",
|
|
11
|
-
"cli/account-reply-operations.mjs": "
|
|
11
|
+
"cli/account-reply-operations.mjs": "08cf9642f040d2ef577ad704b893bde4a5b97d4930d3fadac24f2aebcb87ae24",
|
|
12
12
|
"cli/agents.mjs": "e311dd08d1dc09648881a37eb9765bf6d155786f0b713204f51de29bc8134293",
|
|
13
13
|
"cli/assignment-operations.mjs": "fc74e3fd79975cfcbac14891d5dec5f25e662777050fc46a8ad3aae5cf361c59",
|
|
14
14
|
"cli/assignment.mjs": "90cb85e0df8aadca2ff8391c99e778b41261183b5f38e8c6c32afee2f98f871a",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"cli/attachments.mjs": "2fee6b4abbf82da9847d4a927a3d4d3ca947a198a903a78927596a2ea858cbf4",
|
|
17
17
|
"cli/audience-operations.mjs": "133b72dc6b9e3a6b4f173ce28f1524163f9c7b049505b885115f83b9e4af7170",
|
|
18
18
|
"cli/audiences.mjs": "3c377346efc1a8bdde432a16c2d19a3f51f34f3333d344d3a2bfa94c188a017d",
|
|
19
|
-
"cli/audienti.mjs": "
|
|
19
|
+
"cli/audienti.mjs": "4e9e93e9a9ded80f5de70c9566f0699e8c16cf4887eb8614d13aff89aebe7b6c",
|
|
20
20
|
"cli/audit-operations.mjs": "afaf87d592a1e5f6bff2a8649a6a64a8f471950b7d99e98995d9205aa5910398",
|
|
21
21
|
"cli/audit.mjs": "a7becaed67c58b063e668b5e66844b6dc15c11a63b428faa171b542ad922c001",
|
|
22
22
|
"cli/budget-operations.mjs": "d74916551ef393e29734c6e13cf9021251e0ed126eeaa529e18cf2332146e1e0",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"cli/hand-task-operations.mjs": "473473fe95324c8c8733e037feab5ac468c07b0658fabd739cfd7d400a7faa83",
|
|
38
38
|
"cli/hand-tasks.mjs": "2c895cf6b30c594a7e27cc4ec4b7eddeb39f941cd195b9255c6e0d6b4a56371f",
|
|
39
39
|
"cli/intent-operations.mjs": "97b08e7474cf0fd8201650f08fa5ca5a2be2b0ddf5ea2079eb644e21aa2a0153",
|
|
40
|
-
"cli/intent.mjs": "
|
|
40
|
+
"cli/intent.mjs": "5aa62593f65f58f2714bb402365624005ae17f73f65da3952b06f45e3c109450",
|
|
41
41
|
"cli/json-file.mjs": "96431b18215834c2531f5901e2526875c634dd2e85a9465fcffc937fbec52150",
|
|
42
42
|
"cli/kv-operations.mjs": "505d79d0d535d3441883f8a37817c30c73367216a35dddb07181f0f0e799df79",
|
|
43
43
|
"cli/kv.mjs": "05783610001dd002af07a4bb8f26e64d74aa4981bbe38a2100552b810cb3bc72",
|
|
@@ -50,10 +50,10 @@
|
|
|
50
50
|
"cli/outcome-operations.mjs": "cf133097799f240a006264a38a4c6bd4094078d6dec78a71679700ac3bdeacd5",
|
|
51
51
|
"cli/outcomes.mjs": "765ccb112a90fc4d228b2a41e5e19c5e1f3e2fe14bc1d8128b0090fc95cdbf3f",
|
|
52
52
|
"cli/owner-account-client.mjs": "91ab4d9b4b93c7feea668e5a3087cd9aa0766cf4cc657b7cac34e606d3a4b7a5",
|
|
53
|
-
"cli/playbook-help.mjs": "
|
|
54
|
-
"cli/playbook-operations.mjs": "
|
|
53
|
+
"cli/playbook-help.mjs": "dad00cae19eb107f84c7934812800431535c6cf1dbcdcdd22c16522cfaddadf3",
|
|
54
|
+
"cli/playbook-operations.mjs": "431738b47b56091e10f0466f03673c602ae00653f8b455a20d39a8242d845e21",
|
|
55
55
|
"cli/profiles.mjs": "45929b224ffc916b6dbd7a94e06ac09a1ff7feec430633b10d160c1608fc2d32",
|
|
56
|
-
"cli/progress.mjs": "
|
|
56
|
+
"cli/progress.mjs": "6908f2937adb87a83ebefc1f4324ed18adac65228547b0524a474ac3513b5c67",
|
|
57
57
|
"cli/prospecting-settings-operations.mjs": "1829eb2fe7208f58601988143756072429adbfe00f8deb5a52613bf650a9eacc",
|
|
58
58
|
"cli/prospecting-settings.mjs": "b09f47c84416d9892d7d5b17dcf684cbb560e1cacb25513826ff04ef9307626e",
|
|
59
59
|
"cli/question-operations.mjs": "c7070dd1b5ec9c5b0df93012ef08d0d6b4d6e5c8da267a37beb1acc5c3cf4ea1",
|
|
@@ -73,8 +73,8 @@
|
|
|
73
73
|
"cli/skills.mjs": "ea8dfef32664714f9c63251d9a6bbdb44d77d41e272df46bb102ebfcd8df8b66",
|
|
74
74
|
"cli/suppression-operations.mjs": "d1f827a785670fc6e44d87b18e4cfb6596b09e5be7c4f84c4b9a75ed13a962c6",
|
|
75
75
|
"cli/suppression.mjs": "2b10be67e290deec9ed915139c3d98d45d7d10fd41abb67b5a35a630d636a4ed",
|
|
76
|
-
"cli/tools-operations.mjs": "
|
|
77
|
-
"cli/tools.mjs": "
|
|
76
|
+
"cli/tools-operations.mjs": "f64e58f75ef0c02b9317c6b6e07ccc7b9891464cf29824cee75f0fcae9026eb2",
|
|
77
|
+
"cli/tools.mjs": "16967f23a2b2460d28e766c827721a254e83d34b2df5195981cc9f899f6a5ed0",
|
|
78
78
|
"cli/usage-operations.mjs": "64dd1ae850f52bb72c7648be78a8ab2dfab986afba2d2d2cd08034c4f7b3ace6",
|
|
79
79
|
"cli/usage.mjs": "cd582c061f83ca4f220ddd3cd2a174a1a3a3c0ee308b3d5a5f47752a501e322e",
|
|
80
80
|
"cli/work-execution-operations.mjs": "842d706b36bb035aa54e1dee8bf950f0619c495bcae84faa1926fbb05f6842bc",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"cli/work-operations.mjs": "8b3a84ca15e8e4ad79ef92ced4c5adaffd5129f630e3bfc2c74a844a90867600",
|
|
85
85
|
"cli/work.mjs": "751107ecc3de5a6be9db4a068cddc41f3ad8e77c87e59686eaf522862caf9e9f",
|
|
86
86
|
"cli/workspaces.mjs": "eebe2c4bfc6ddedb2fb0dd551d5fa348eeda2fdf2105babd514b29a97f4d6225",
|
|
87
|
-
"package.json": "
|
|
87
|
+
"package.json": "7083b89b9b44dd81b5d32685dd59728564d3c5193a1ef98bbbf0a5bd5ab9b606",
|
|
88
88
|
"skills/agent-rooms/SKILL.md": "08f917ff85fee1d23499a4499056ce845b39ce6727029b104819dad41ee87cc2",
|
|
89
89
|
"skills/agent-rooms/references/commands.md": "ef5afa5543ca9da967a147f638774647998ea1c1a2a821959f3bf87d54c292bd",
|
|
90
90
|
"skills/audienti/SKILL.md": "8f2124065bfc3a005b44e194e7dcce9bbf14062ab332e7db66d441eeccb518ed",
|
|
@@ -100,9 +100,9 @@
|
|
|
100
100
|
"skills/getting-started/references/capabilities.md": "982e3583a47ba4ac832efae2f6af3a4d8c0c18cace159c76b2a4ad1a8d8e910e",
|
|
101
101
|
"skills/getting-started/references/mailbox-check.md": "113574bb5a573125620dcde4e65ebf44164f7b0727cc936fb41234f5d57bba73",
|
|
102
102
|
"skills/getting-started/references/outcome-checks.md": "094d09d231b38d4935aa9eb8ac089e46ba8e698489852fa97040e6b5eac77a9b",
|
|
103
|
-
"skills/getting-started/references/replies.md": "
|
|
103
|
+
"skills/getting-started/references/replies.md": "acb5b77833cd9272ffeb05c27c24f9f2a8b1723da4e9a25cd6e8e6e666db2865",
|
|
104
104
|
"skills/getting-started/references/reply-checks.md": "85fe692ad6b7bc73e204de313b27d225be3da1a0af71e8e7bb9945ae511a0dc3",
|
|
105
|
-
"skills/playbook-design/SKILL.md": "
|
|
106
|
-
"skills/playbook-design/references/fields.md": "
|
|
105
|
+
"skills/playbook-design/SKILL.md": "56aa5692c1bbe3843f11819f0f9270988ddd0424b16f38db72a854864155407f",
|
|
106
|
+
"skills/playbook-design/references/fields.md": "7af0c8a2ad7b2ee83ff006fe4707a90c3edacdb8ccf83c09fa17f692b5fa2c81"
|
|
107
107
|
}
|
|
108
108
|
}
|