@picahq/cli 1.9.0 → 1.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +75 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -37,9 +37,49 @@ function writeConfig(config) {
|
|
|
37
37
|
}
|
|
38
38
|
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 384 });
|
|
39
39
|
}
|
|
40
|
+
function readPicaRc() {
|
|
41
|
+
const rcPath = path.join(process.cwd(), ".picarc");
|
|
42
|
+
if (!fs.existsSync(rcPath)) return {};
|
|
43
|
+
try {
|
|
44
|
+
const content = fs.readFileSync(rcPath, "utf-8");
|
|
45
|
+
const result = {};
|
|
46
|
+
for (const line of content.split("\n")) {
|
|
47
|
+
const trimmed = line.trim();
|
|
48
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
49
|
+
const eqIndex = trimmed.indexOf("=");
|
|
50
|
+
if (eqIndex === -1) continue;
|
|
51
|
+
const key = trimmed.slice(0, eqIndex).trim();
|
|
52
|
+
const value = trimmed.slice(eqIndex + 1).trim();
|
|
53
|
+
result[key] = value;
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
} catch {
|
|
57
|
+
return {};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
40
60
|
function getApiKey() {
|
|
41
|
-
|
|
42
|
-
|
|
61
|
+
if (process.env.PICA_SECRET) return process.env.PICA_SECRET;
|
|
62
|
+
const rc = readPicaRc();
|
|
63
|
+
if (rc.PICA_SECRET) return rc.PICA_SECRET;
|
|
64
|
+
return readConfig()?.apiKey ?? null;
|
|
65
|
+
}
|
|
66
|
+
function getAccessControlFromAllSources() {
|
|
67
|
+
const rc = readPicaRc();
|
|
68
|
+
const fileAc = getAccessControl();
|
|
69
|
+
const merged = { ...fileAc };
|
|
70
|
+
if (rc.PICA_PERMISSIONS) {
|
|
71
|
+
merged.permissions = rc.PICA_PERMISSIONS;
|
|
72
|
+
}
|
|
73
|
+
if (rc.PICA_CONNECTION_KEYS) {
|
|
74
|
+
merged.connectionKeys = rc.PICA_CONNECTION_KEYS.split(",").map((s) => s.trim()).filter(Boolean);
|
|
75
|
+
}
|
|
76
|
+
if (rc.PICA_ACTION_IDS) {
|
|
77
|
+
merged.actionIds = rc.PICA_ACTION_IDS.split(",").map((s) => s.trim()).filter(Boolean);
|
|
78
|
+
}
|
|
79
|
+
if (rc.PICA_KNOWLEDGE_AGENT) {
|
|
80
|
+
merged.knowledgeAgent = rc.PICA_KNOWLEDGE_AGENT === "true";
|
|
81
|
+
}
|
|
82
|
+
return merged;
|
|
43
83
|
}
|
|
44
84
|
function getAccessControl() {
|
|
45
85
|
return readConfig()?.accessControl ?? {};
|
|
@@ -1568,7 +1608,7 @@ function getConfig() {
|
|
|
1568
1608
|
p5.cancel("Not configured. Run `pica init` first.");
|
|
1569
1609
|
process.exit(1);
|
|
1570
1610
|
}
|
|
1571
|
-
const ac =
|
|
1611
|
+
const ac = getAccessControlFromAllSources();
|
|
1572
1612
|
const permissions = ac.permissions || "admin";
|
|
1573
1613
|
const connectionKeys = ac.connectionKeys || ["*"];
|
|
1574
1614
|
const actionIds = ac.actionIds || ["*"];
|
|
@@ -1797,7 +1837,34 @@ function colorMethod(method) {
|
|
|
1797
1837
|
var require2 = createRequire(import.meta.url);
|
|
1798
1838
|
var { version } = require2("../package.json");
|
|
1799
1839
|
var program = new Command();
|
|
1800
|
-
program.name("pica").description(
|
|
1840
|
+
program.name("pica").description(`Pica CLI \u2014 Connect AI agents to 200+ platforms through one interface.
|
|
1841
|
+
|
|
1842
|
+
Setup:
|
|
1843
|
+
pica init Set up API key and install MCP server
|
|
1844
|
+
pica add <platform> Connect a platform via OAuth (e.g. gmail, slack, shopify)
|
|
1845
|
+
pica config Configure access control (permissions, scoping)
|
|
1846
|
+
|
|
1847
|
+
Workflow (use these in order):
|
|
1848
|
+
1. pica list List your connected platforms and connection keys
|
|
1849
|
+
2. pica actions search <platform> <q> Search for actions using natural language
|
|
1850
|
+
3. pica actions knowledge <plat> <id> Get full docs for an action (ALWAYS do this before execute)
|
|
1851
|
+
4. pica actions execute <p> <id> <key> Execute the action
|
|
1852
|
+
|
|
1853
|
+
Example \u2014 send an email through Gmail:
|
|
1854
|
+
$ pica list
|
|
1855
|
+
# Find: gmail operational live::gmail::default::abc123
|
|
1856
|
+
|
|
1857
|
+
$ pica actions search gmail "send email" -t execute
|
|
1858
|
+
# Find: POST Send Email conn_mod_def::xxx::yyy
|
|
1859
|
+
|
|
1860
|
+
$ pica actions knowledge gmail conn_mod_def::xxx::yyy
|
|
1861
|
+
# Read the docs: required fields are to, subject, body, connectionKey
|
|
1862
|
+
|
|
1863
|
+
$ pica actions execute gmail conn_mod_def::xxx::yyy live::gmail::default::abc123 \\
|
|
1864
|
+
-d '{"to":"j@example.com","subject":"Hello","body":"Hi!","connectionKey":"live::gmail::default::abc123"}'
|
|
1865
|
+
|
|
1866
|
+
Platform names are always kebab-case (e.g. hub-spot, ship-station, google-calendar).
|
|
1867
|
+
Run 'pica platforms' to browse all 200+ available platforms.`).version(version);
|
|
1801
1868
|
program.command("init").description("Set up Pica and install MCP to your AI agents").option("-y, --yes", "Skip confirmations").option("-g, --global", "Install MCP globally (available in all projects)").option("-p, --project", "Install MCP for this project only (creates .mcp.json)").action(async (options) => {
|
|
1802
1869
|
await initCommand(options);
|
|
1803
1870
|
});
|
|
@@ -1814,14 +1881,14 @@ connection.command("list").alias("ls").description("List your connections").acti
|
|
|
1814
1881
|
program.command("platforms").alias("p").description("List available platforms").option("-c, --category <category>", "Filter by category").option("--json", "Output as JSON").action(async (options) => {
|
|
1815
1882
|
await platformsCommand(options);
|
|
1816
1883
|
});
|
|
1817
|
-
var actions = program.command("actions").alias("a").description("Search, explore, and execute platform actions");
|
|
1818
|
-
actions.command("search <platform> <query>").description(
|
|
1884
|
+
var actions = program.command("actions").alias("a").description("Search, explore, and execute platform actions (workflow: search \u2192 knowledge \u2192 execute)");
|
|
1885
|
+
actions.command("search <platform> <query>").description('Search for actions on a platform (e.g. pica actions search gmail "send email")').option("-t, --type <type>", "execute (to run it) or knowledge (to learn about it). Default: knowledge").action(async (platform, query, options) => {
|
|
1819
1886
|
await actionsSearchCommand(platform, query, options);
|
|
1820
1887
|
});
|
|
1821
|
-
actions.command("knowledge <platform> <actionId>").alias("k").description("Get
|
|
1888
|
+
actions.command("knowledge <platform> <actionId>").alias("k").description("Get full docs for an action \u2014 MUST call before execute to know required params").action(async (platform, actionId) => {
|
|
1822
1889
|
await actionsKnowledgeCommand(platform, actionId);
|
|
1823
1890
|
});
|
|
1824
|
-
actions.command("execute <platform> <actionId> <connectionKey>").alias("x").description(
|
|
1891
|
+
actions.command("execute <platform> <actionId> <connectionKey>").alias("x").description('Execute an action \u2014 pass connectionKey from "pica list", actionId from "actions search"').option("-d, --data <json>", "Request body as JSON").option("--path-vars <json>", "Path variables as JSON").option("--query-params <json>", "Query parameters as JSON").option("--headers <json>", "Additional headers as JSON").option("--form-data", "Send as multipart/form-data").option("--form-url-encoded", "Send as application/x-www-form-urlencoded").action(async (platform, actionId, connectionKey, options) => {
|
|
1825
1892
|
await actionsExecuteCommand(platform, actionId, connectionKey, {
|
|
1826
1893
|
data: options.data,
|
|
1827
1894
|
pathVars: options.pathVars,
|