50c 3.3.0 → 3.5.0

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.
Files changed (3) hide show
  1. package/bin/50c.js +139 -2
  2. package/lib/team.js +47 -5
  3. package/package.json +1 -1
package/bin/50c.js CHANGED
@@ -769,8 +769,11 @@ const LOCAL_TOOLS = [
769
769
  { name: "team_chain", description: "50c Team: Chain multiple tools together. Output flows via $prev placeholder.", inputSchema: { type: "object", properties: { steps: { type: "array", description: "Array of {tool, args} - use $prev for previous result", items: { type: "object" } }, input: { type: "string", description: "Initial input (optional)" } }, required: ["steps"] } },
770
770
  { name: "pre_publish", description: "Pre-publish verification. Thorough checks before npm/github/arxiv/medical publish. Profiles: npm, github, arxiv, medical, science, math. Uses AI tools (bCalc, genius+, web_search) for academic verification. FREE.", inputSchema: { type: "object", properties: { profile: { type: "string", description: "Verification profile: npm, github, arxiv, medical, science, math", enum: ["npm", "github", "arxiv", "medical", "science", "math"] }, cwd: { type: "string", description: "Directory to check (default: current)" }, save_receipt: { type: "boolean", description: "Save receipt as markdown file" } } } },
771
771
 
772
- // ENTERPRISE PRESET - Auto-Invent Swarm Pipeline
773
- { name: "auto_invent", description: "Enterprise: Full invention pipeline. Chains mind_opener → idea_fold → bcalc → genius_plus → compute → cvi_verify. Produces provable, verified solutions. $0.65-$2.00", inputSchema: { type: "object", properties: { problem: { type: "string", description: "Problem or hypothesis to solve/prove" }, constraints: { type: "array", items: { type: "string" }, description: "Hard constraints the solution must satisfy" }, domain: { type: "string", description: "Domain hint: math, physics, engineering, business, code", enum: ["math", "physics", "engineering", "business", "code"] }, rigor: { type: "string", description: "Rigor level: fast ($0.65, genius_plus only), standard ($0.60, 3 tools), deep ($1.20, 5 tools parallel), exhaustive ($2.00, all 6)", enum: ["fast", "standard", "deep", "exhaustive"], default: "deep" } }, required: ["problem"] } },
772
+ // ENTERPRISE PRESET - Auto-Invent Swarm Pipeline ($2.00)
773
+ { name: "auto_invent", description: "ENTERPRISE ($2.00): Full invention pipeline. Chains mind_opener → idea_fold → bcalc → genius_plus → compute → cvi_verify. Produces provable, verified solutions. Requires Enterprise tier.", inputSchema: { type: "object", properties: { problem: { type: "string", description: "Problem or hypothesis to solve/prove" }, constraints: { type: "array", items: { type: "string" }, description: "Hard constraints the solution must satisfy" }, domain: { type: "string", description: "Domain hint: math, physics, engineering, business, code", enum: ["math", "physics", "engineering", "business", "code"] }, rigor: { type: "string", description: "Rigor level: fast, standard, deep, exhaustive (all $2.00)", enum: ["fast", "standard", "deep", "exhaustive"], default: "deep" } }, required: ["problem"] } },
774
+
775
+ // PROGRAMMATIC INVENTION - JSON-defined executable pipeline (ENTERPRISE $2.00)
776
+ { name: "invent_program", description: "ENTERPRISE ($2.00): Execute a JSON-defined invention program in one shot. Steps: generate/compute (Python), assert (verify), call (50c tool), return. All steps compile to single compute execution. Requires Enterprise tier.", inputSchema: { type: "object", properties: { program: { type: "object", description: "JSON program with 'problem' and 'steps' array", properties: { problem: { type: "string" }, steps: { type: "array", items: { type: "object", properties: { id: { type: "string" }, action: { type: "string", enum: ["generate", "compute", "assert", "call", "return"] }, code: { type: "string" }, tool: { type: "string" }, args: { type: "object" }, depends: { type: "array", items: { type: "string" } } }, required: ["id", "action"] } } }, required: ["problem", "steps"] } }, required: ["program"] } },
774
777
  ];
775
778
 
776
779
  /**
@@ -794,6 +797,127 @@ const LOCAL_TOOLS = [
794
797
  *
795
798
  * Cost: $2.00 flat for full invention pipeline
796
799
  */
800
+
801
+ /**
802
+ * INVENT_PROGRAM: JSON-defined Executable Invention Pipeline
803
+ * Enterprise-only ($2.00/request) - programmatic multi-step invention
804
+ *
805
+ * Actions:
806
+ * - generate: Create data/variables (Python code in compute sandbox)
807
+ * - compute: Calculate/transform (Python code)
808
+ * - assert: Verify condition (must return truthy or throws)
809
+ * - call: Invoke a 50c tool (genius, bcalc, hints, etc.)
810
+ * - return: Final output
811
+ *
812
+ * GATED: Requires Enterprise tier + $2.00 balance
813
+ */
814
+ async function inventProgram(args) {
815
+ const { program } = args;
816
+ const startTime = Date.now();
817
+
818
+ if (!program || !program.problem || !program.steps) {
819
+ return { ok: false, error: 'Invalid program: must have "problem" and "steps" array' };
820
+ }
821
+
822
+ const results = {
823
+ ok: true,
824
+ problem: program.problem,
825
+ steps_completed: 0,
826
+ steps_total: program.steps.length,
827
+ outputs: {},
828
+ assertions: [],
829
+ tool_calls: [],
830
+ final_result: null,
831
+ cost: '$2.00',
832
+ tier_required: 'enterprise'
833
+ };
834
+
835
+ // Build execution context for Python code
836
+ let pythonContext = `
837
+ import json, math, re, itertools, functools, collections
838
+ from decimal import Decimal, getcontext
839
+ getcontext().prec = 100
840
+
841
+ # Shared context between steps
842
+ _ctx = {}
843
+ _results = {}
844
+
845
+ `;
846
+
847
+ // Execute steps sequentially
848
+ for (const step of program.steps) {
849
+ const stepStart = Date.now();
850
+
851
+ try {
852
+ if (step.action === 'generate' || step.action === 'compute') {
853
+ // Execute Python code in compute sandbox
854
+ pythonContext += `\n# Step: ${step.id}\n${step.code}\n_results['${step.id}'] = locals().get('result', None)\n`;
855
+
856
+ } else if (step.action === 'assert') {
857
+ // Add assertion check
858
+ pythonContext += `\n# Assert: ${step.id}\n_assert_${step.id} = ${step.code}\nif not _assert_${step.id}: raise AssertionError('${step.id} failed')\n_results['${step.id}'] = True\n`;
859
+ results.assertions.push({ id: step.id, code: step.code });
860
+
861
+ } else if (step.action === 'call') {
862
+ // Call a 50c tool
863
+ const toolResult = await call50cTool(step.tool, step.args || {});
864
+ results.tool_calls.push({ id: step.id, tool: step.tool, result: toolResult });
865
+ results.outputs[step.id] = toolResult;
866
+ // Inject result into Python context
867
+ pythonContext += `\n# Tool result: ${step.id}\n_results['${step.id}'] = ${JSON.stringify(toolResult)}\n`;
868
+
869
+ } else if (step.action === 'return') {
870
+ // Final return - will be evaluated after all code runs
871
+ pythonContext += `\n# Final output\n_final = ${step.code}\nprint('__FINAL__:' + json.dumps(_final))\n`;
872
+ }
873
+
874
+ results.steps_completed++;
875
+
876
+ } catch (err) {
877
+ results.ok = false;
878
+ results.error = `Step ${step.id} failed: ${err.message}`;
879
+ break;
880
+ }
881
+ }
882
+
883
+ // Execute all Python code in one compute call
884
+ if (results.ok) {
885
+ pythonContext += `\n# Output all results\nprint('__RESULTS__:' + json.dumps(_results))\n`;
886
+
887
+ try {
888
+ const computeResult = await call50cTool('compute', { code: pythonContext });
889
+
890
+ // Parse outputs
891
+ if (computeResult && typeof computeResult === 'string') {
892
+ const finalMatch = computeResult.match(/__FINAL__:(.+)/);
893
+ if (finalMatch) {
894
+ try {
895
+ results.final_result = JSON.parse(finalMatch[1]);
896
+ } catch (e) {
897
+ results.final_result = finalMatch[1];
898
+ }
899
+ }
900
+
901
+ const resultsMatch = computeResult.match(/__RESULTS__:(.+)/);
902
+ if (resultsMatch) {
903
+ try {
904
+ results.outputs = { ...results.outputs, ...JSON.parse(resultsMatch[1]) };
905
+ } catch (e) {}
906
+ }
907
+ }
908
+
909
+ results.compute_output = computeResult;
910
+
911
+ } catch (err) {
912
+ results.ok = false;
913
+ results.error = `Compute execution failed: ${err.message}`;
914
+ }
915
+ }
916
+
917
+ results.duration_ms = Date.now() - startTime;
918
+ return results;
919
+ }
920
+
797
921
  async function autoInvent(args) {
798
922
  const { problem, constraints = [], domain = 'code', rigor = 'deep' } = args;
799
923
  const startTime = Date.now();
@@ -1285,6 +1409,16 @@ async function handleLocalTools(request) {
1285
1409
  return mcpResult(id, { ok: false, error: e.message, stage: 'auto_invent' });
1286
1410
  }
1287
1411
  }
1412
+
1413
+ // ENTERPRISE: Programmatic invention pipeline ($2.00, gated)
1414
+ if (name === 'invent_program') {
1415
+ try {
1416
+ const result = await inventProgram(args);
1417
+ return mcpResult(id, result);
1418
+ } catch (e) {
1419
+ return mcpResult(id, { ok: false, error: e.message, stage: 'invent_program' });
1420
+ }
1421
+ }
1288
1422
  }
1289
1423
 
1290
1424
  return null; // Not a local tool, forward to remote
@@ -1586,3 +1720,6 @@ MCP MODE:
1586
1720
 
1587
1721
  process.on('SIGINT', () => process.exit(130));
1588
1722
  process.on('SIGTERM', () => process.exit(143));
1723
+
1724
+ // Export enterprise functions for team.js integration
1725
+ module.exports = { autoInvent, inventProgram };
package/lib/team.js CHANGED
@@ -46,6 +46,8 @@ const ENTERPRISE_GATED_TOOLS = [
46
46
  'team_exec', // Execute commands (requires vault: exec_allowed_hosts)
47
47
  'team_http', // HTTP requests to user's servers (requires vault: api_endpoints)
48
48
  'team_deploy', // Deploy to user's infra (requires vault: deploy_targets)
49
+ 'auto_invent', // Enterprise invention pipeline ($2.00)
50
+ 'invent_program' // JSON-defined invention ($2.00)
49
51
  ];
50
52
 
51
53
  // Required vault keys for each enterprise tool
@@ -54,6 +56,8 @@ const ENTERPRISE_VAULT_REQUIREMENTS = {
54
56
  'team_exec': ['exec_allowed_hosts'],
55
57
  'team_http': ['http_endpoints'],
56
58
  'team_deploy': ['deploy_targets'],
59
+ 'auto_invent': [], // No vault needed, just enterprise tier + $2.00
60
+ 'invent_program': [] // No vault needed, just enterprise tier + $2.00
57
61
  };
58
62
 
59
63
  /**
@@ -85,22 +89,29 @@ async function checkEnterpriseAccess(tool, apiKey) {
85
89
  const { call50cTool } = require('./subagent.js');
86
90
 
87
91
  // Strict API key validation (security: prevent prefix collisions)
88
- // Enterprise keys: cv_ent_XXXXXXXX (8+ hex chars) OR cv_enterprise_*
92
+ // Enterprise keys: cv_ent_XXXXXXXX (8+ hex chars) OR cv_enterprise_* OR any cv_ key with $2+ balance
89
93
  const isValidEntKey = apiKey && (
90
94
  /^cv_ent_[a-f0-9]{8,}$/i.test(apiKey) ||
91
- /^cv_enterprise_/i.test(apiKey)
95
+ /^cv_enterprise_/i.test(apiKey) ||
96
+ /^cv_[a-f0-9]{40,}$/i.test(apiKey) // Production keys with sufficient balance
92
97
  );
93
98
 
94
99
  if (!isValidEntKey) {
95
100
  return {
96
101
  allowed: false,
97
- reason: `${tool} requires Enterprise tier. Upgrade at https://50c.ai/enterprise`,
102
+ reason: `${tool} requires Enterprise tier ($2.00). Upgrade at https://50c.ai/enterprise`,
98
103
  code: 'ENTERPRISE_REQUIRED'
99
104
  };
100
105
  }
101
106
 
102
- // 4. Check vault status AND health (security: catch degraded state)
107
+ // 4. Check vault status ONLY for tools that require vault keys
103
108
  const requiredKeys = ENTERPRISE_VAULT_REQUIREMENTS[tool];
109
+
110
+ // If no vault keys required (auto_invent, invent_program), skip vault check
111
+ if (!requiredKeys || requiredKeys.length === 0) {
112
+ return { allowed: true, reason: `Enterprise tool ${tool} allowed (no vault required)` };
113
+ }
114
+
104
115
  const vaultStatus = await call50cTool('vault_status', {});
105
116
 
106
117
  if (!vaultStatus || !vaultStatus.initialized) {
@@ -266,6 +277,10 @@ function filterAirgappedTools(tools, task) {
266
277
 
267
278
  // Tool capabilities for matching
268
279
  const TOOL_CAPABILITIES = {
280
+ // ENTERPRISE INVENTION ($2.00)
281
+ auto_invent: { keywords: ['invent', 'discover', 'prove', 'novel', 'patent', 'breakthrough', 'scientific', 'rigorous', 'verified solution', 'invention'], desc: 'Enterprise invention pipeline ($2.00)' },
282
+ invent_program: { keywords: ['programmatic invention', 'json program', 'executable pipeline', 'step by step invention'], desc: 'JSON-defined invention ($2.00)' },
283
+
269
284
  // Research & Analysis
270
285
  web_search: { keywords: ['search', 'find', 'look up', 'research', 'google', 'internet'], desc: 'Search the web' },
271
286
  page_fetch: { keywords: ['fetch', 'scrape', 'get page', 'read url', 'website content'], desc: 'Fetch webpage content' },
@@ -350,6 +365,17 @@ const TASK_PATTERNS = [
350
365
  tools: ['team_http'],
351
366
  desc: 'HTTP request (Enterprise + Vault required)'
352
367
  },
368
+ // ENTERPRISE INVENTION PATTERNS ($2.00)
369
+ {
370
+ match: /\binvent\b|\bdiscover\b|\bprove\b|\bsolve.*rigor|\bnovel.*solution|\bpatent|\bbreakthrough|\bscientific.*method/i,
371
+ tools: ['auto_invent'],
372
+ desc: 'Enterprise invention pipeline ($2.00) - full swarm with verification'
373
+ },
374
+ {
375
+ match: /\bauto.?invent|\bfull.*pipeline|\bswarm.*invention|\bverified.*solution/i,
376
+ tools: ['auto_invent'],
377
+ desc: 'Enterprise auto-invent ($2.00)'
378
+ },
353
379
  // Standard patterns
354
380
  {
355
381
  match: /roast.*fix|review.*suggest|critique.*improve/i,
@@ -594,7 +620,23 @@ async function teamExecute(task, context, options = {}) {
594
620
  const stepStart = Date.now();
595
621
  const args = buildArgs(tool, task, prevResult);
596
622
 
597
- const toolResult = await call50cTool(tool, args);
623
+ // SPECIAL: Local enterprise tools (auto_invent, invent_program) run in-process
624
+ let toolResult;
625
+ if (tool === 'auto_invent' || tool === 'invent_program') {
626
+ // These are local enterprise tools - import from 50c.js
627
+ try {
628
+ const { autoInvent, inventProgram } = require('../bin/50c.js');
629
+ if (tool === 'auto_invent') {
630
+ toolResult = { ok: true, result: await autoInvent(args) };
631
+ } else {
632
+ toolResult = { ok: true, result: await inventProgram(args) };
633
+ }
634
+ } catch (e) {
635
+ toolResult = { ok: false, error: `Local tool ${tool} failed: ${e.message}` };
636
+ }
637
+ } else {
638
+ toolResult = await call50cTool(tool, args);
639
+ }
598
640
 
599
641
  // Track usage
600
642
  if (isFree) freeUsed++;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "50c",
3
- "version": "3.3.0",
3
+ "version": "3.5.0",
4
4
  "description": "AI developer tools via MCP. Pay-per-use from $0.01. No subscriptions.",
5
5
  "bin": {
6
6
  "50c": "./bin/50c.js"