ft-scout 9.4.4 → 9.4.6
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/.firebase/hosting.d2Vi.cache +7 -7
- package/README.md +2 -2
- package/bin/src/engine/agentEngine.d.ts.map +1 -1
- package/bin/src/engine/agentEngine.js +90 -21
- package/bin/src/engine/agentEngine.js.map +1 -1
- package/bin/src/engine/computer/computerController.d.ts.map +1 -1
- package/bin/src/engine/computer/computerController.js +35 -1
- package/bin/src/engine/computer/computerController.js.map +1 -1
- package/bin/src/engine/computer/scoutDriver.cs +20 -1
- package/bin/src/engine/computer/scout_driver.exe +0 -0
- package/bin/src/engine/llm.d.ts.map +1 -1
- package/bin/src/engine/llm.js +81 -36
- package/bin/src/engine/llm.js.map +1 -1
- package/bin/src/engine/runtime/agentRuntime.d.ts.map +1 -1
- package/bin/src/engine/runtime/agentRuntime.js +51 -16
- package/bin/src/engine/runtime/agentRuntime.js.map +1 -1
- package/bin/src/index.js +4 -4
- package/bin/src/mcp/client.js +1 -1
- package/bin/src/mcp/toolRouter.d.ts.map +1 -1
- package/bin/src/mcp/toolRouter.js +27 -26
- package/bin/src/mcp/toolRouter.js.map +1 -1
- package/bin/src/utils/branding.js +1 -1
- package/bin/src/utils/qrBridge.js +1 -1
- package/package.json +2 -1
- package/web/app.js +2 -2
- package/web/styles.css +2 -2
- package/artifacts/scout_drone_3d.glb +0 -0
- package/artifacts/scout_drone_3d_render.png +0 -0
- package/scripts/build_3d_drone.js +0 -130
- package/scripts/export_and_capture.js +0 -48
- package/scripts/render_and_export_drone.js +0 -94
- package/scripts/render_front_view.js +0 -76
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { getMCPManager } from '../bin/src/mcp/index.js';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
async function main() {
|
|
6
|
-
const mgr = getMCPManager();
|
|
7
|
-
|
|
8
|
-
const pyCode = `
|
|
9
|
-
import bpy
|
|
10
|
-
import math
|
|
11
|
-
|
|
12
|
-
# 1. Clean up default objects except camera/light
|
|
13
|
-
for obj in list(bpy.data.objects):
|
|
14
|
-
if obj.type == 'MESH':
|
|
15
|
-
bpy.data.objects.remove(obj, do_unlink=True)
|
|
16
|
-
|
|
17
|
-
# Helper to create PBR material
|
|
18
|
-
def make_mat(name, base_color, metallic=0.0, roughness=0.5, emission=None, emission_strength=1.0):
|
|
19
|
-
mat = bpy.data.materials.new(name=name)
|
|
20
|
-
mat.use_nodes = True
|
|
21
|
-
nodes = mat.node_tree.nodes
|
|
22
|
-
bsdf = nodes.get('Principled BSDF')
|
|
23
|
-
if bsdf:
|
|
24
|
-
bsdf.inputs['Base Color'].default_value = base_color
|
|
25
|
-
bsdf.inputs['Metallic'].default_value = metallic
|
|
26
|
-
bsdf.inputs['Roughness'].default_value = roughness
|
|
27
|
-
if emission:
|
|
28
|
-
if 'Emission Color' in bsdf.inputs:
|
|
29
|
-
bsdf.inputs['Emission Color'].default_value = emission
|
|
30
|
-
bsdf.inputs['Emission Strength'].default_value = emission_strength
|
|
31
|
-
elif 'Emission' in bsdf.inputs:
|
|
32
|
-
bsdf.inputs['Emission'].default_value = emission
|
|
33
|
-
if 'Emission Strength' in bsdf.inputs:
|
|
34
|
-
bsdf.inputs['Emission Strength'].default_value = emission_strength
|
|
35
|
-
return mat
|
|
36
|
-
|
|
37
|
-
mat_hull = make_mat('Hull_Obsidian', (0.05, 0.06, 0.08, 1.0), metallic=0.92, roughness=0.22)
|
|
38
|
-
mat_gold = make_mat('Accent_Gold', (0.95, 0.72, 0.18, 1.0), metallic=0.98, roughness=0.18)
|
|
39
|
-
mat_cyan_glow = make_mat('Core_CyanGlow', (0.0, 0.9, 1.0, 1.0), emission=(0.0, 0.9, 1.0, 1.0), emission_strength=12.0)
|
|
40
|
-
mat_plasma = make_mat('Thruster_Plasma', (0.65, 0.1, 1.0, 1.0), emission=(0.65, 0.1, 1.0, 1.0), emission_strength=16.0)
|
|
41
|
-
|
|
42
|
-
# 2. Main Aerodynamic Chassis
|
|
43
|
-
bpy.ops.mesh.primitive_uv_sphere_add(segments=32, ring_count=24, radius=1.0, location=(0, 0, 0))
|
|
44
|
-
body = bpy.context.active_object
|
|
45
|
-
body.name = 'Scout_Chassis'
|
|
46
|
-
body.scale = (1.35, 1.65, 0.62)
|
|
47
|
-
bpy.ops.object.transform_apply(scale=True)
|
|
48
|
-
body.data.materials.append(mat_hull)
|
|
49
|
-
|
|
50
|
-
# 3. Cockpit Sensor Eye (Front Core)
|
|
51
|
-
bpy.ops.mesh.primitive_uv_sphere_add(segments=24, ring_count=16, radius=0.38, location=(0, 1.5, 0.08))
|
|
52
|
-
eye = bpy.context.active_object
|
|
53
|
-
eye.name = 'Scout_SensorEye'
|
|
54
|
-
eye.scale = (1.1, 0.5, 0.6)
|
|
55
|
-
bpy.ops.object.transform_apply(scale=True)
|
|
56
|
-
eye.data.materials.append(mat_cyan_glow)
|
|
57
|
-
|
|
58
|
-
# 4. Center Power Ring
|
|
59
|
-
bpy.ops.mesh.primitive_torus_add(major_radius=0.78, minor_radius=0.08, location=(0, 0, 0.35))
|
|
60
|
-
ring = bpy.context.active_object
|
|
61
|
-
ring.name = 'Scout_PowerRing'
|
|
62
|
-
ring.scale = (1.15, 1.3, 0.8)
|
|
63
|
-
bpy.ops.object.transform_apply(scale=True)
|
|
64
|
-
ring.data.materials.append(mat_gold)
|
|
65
|
-
|
|
66
|
-
# 5. Four Thruster Arms & Turbine Pods
|
|
67
|
-
angles = [45, 135, 225, 315]
|
|
68
|
-
for i, deg in enumerate(angles):
|
|
69
|
-
rad = math.radians(deg)
|
|
70
|
-
arm_x = math.cos(rad) * 1.6
|
|
71
|
-
arm_y = math.sin(rad) * 1.8
|
|
72
|
-
|
|
73
|
-
# Arm strut
|
|
74
|
-
bpy.ops.mesh.primitive_cube_add(size=0.18, location=(arm_x * 0.55, arm_y * 0.55, 0))
|
|
75
|
-
arm = bpy.context.active_object
|
|
76
|
-
arm.name = f'Scout_Arm_{i+1}'
|
|
77
|
-
arm.scale = (2.2, 0.5, 0.4)
|
|
78
|
-
arm.rotation_euler = (0, 0, rad)
|
|
79
|
-
arm.data.materials.append(mat_gold)
|
|
80
|
-
|
|
81
|
-
# Thruster outer nacelle
|
|
82
|
-
bpy.ops.mesh.primitive_cylinder_add(radius=0.45, depth=0.8, location=(arm_x, arm_y, 0))
|
|
83
|
-
thruster = bpy.context.active_object
|
|
84
|
-
thruster.name = f'Scout_Thruster_{i+1}'
|
|
85
|
-
thruster.rotation_euler = (math.radians(15) if arm_y > 0 else math.radians(-15), 0, 0)
|
|
86
|
-
thruster.data.materials.append(mat_hull)
|
|
87
|
-
|
|
88
|
-
# Inner plasma exhaust
|
|
89
|
-
bpy.ops.mesh.primitive_cylinder_add(radius=0.32, depth=0.15, location=(arm_x, arm_y, -0.35))
|
|
90
|
-
plasma = bpy.context.active_object
|
|
91
|
-
plasma.name = f'Scout_Plasma_{i+1}'
|
|
92
|
-
plasma.data.materials.append(mat_plasma)
|
|
93
|
-
|
|
94
|
-
# 6. Twin High-Gain Communication Antennas (Rear)
|
|
95
|
-
for side in [-0.4, 0.4]:
|
|
96
|
-
bpy.ops.mesh.primitive_cylinder_add(radius=0.025, depth=0.9, location=(side, -1.3, 0.5))
|
|
97
|
-
ant = bpy.context.active_object
|
|
98
|
-
ant.name = f'Scout_Antenna_{"L" if side < 0 else "R"}'
|
|
99
|
-
ant.rotation_euler = (math.radians(-25), math.radians(side * 15), 0)
|
|
100
|
-
ant.data.materials.append(mat_gold)
|
|
101
|
-
|
|
102
|
-
# Antenna LED tip
|
|
103
|
-
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.06, location=(side * 1.25, -1.65, 0.9))
|
|
104
|
-
tip = bpy.context.active_object
|
|
105
|
-
tip.name = f'Scout_AntennaTip_{"L" if side < 0 else "R"}'
|
|
106
|
-
tip.data.materials.append(mat_cyan_glow)
|
|
107
|
-
|
|
108
|
-
# Smooth shading across all meshes
|
|
109
|
-
for obj in bpy.data.objects:
|
|
110
|
-
if obj.type == 'MESH':
|
|
111
|
-
for poly in obj.data.polygons:
|
|
112
|
-
poly.use_smooth = True
|
|
113
|
-
|
|
114
|
-
print('SCOUT_3D_DRONE_CREATED_SUCCESSFULLY')
|
|
115
|
-
`;
|
|
116
|
-
|
|
117
|
-
console.log('Sending 3D Model Python code to Blender MCP...');
|
|
118
|
-
const result = await mgr.executeTool('execute_blender_code', {
|
|
119
|
-
code: pyCode,
|
|
120
|
-
user_prompt: 'Generate a 3D Sci-Fi Autonomous Scout Drone model with PBR metallic hull and glowing cyan core'
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
console.log('Status:', result.status);
|
|
124
|
-
console.log('Output Summary:', result.outputSummary);
|
|
125
|
-
if (result.error) {
|
|
126
|
-
console.error('Error:', result.error);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
main().catch(console.error);
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { getMCPManager } from '../bin/src/mcp/index.js';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
async function main() {
|
|
6
|
-
const mgr = getMCPManager();
|
|
7
|
-
|
|
8
|
-
console.log('1. Querying updated Blender scene...');
|
|
9
|
-
const sceneInfo = await mgr.executeTool('get_scene_info', {});
|
|
10
|
-
console.log('Scene Info:', sceneInfo.result);
|
|
11
|
-
|
|
12
|
-
const artifactsDir = path.resolve('artifacts');
|
|
13
|
-
if (!fs.existsSync(artifactsDir)) {
|
|
14
|
-
fs.mkdirSync(artifactsDir, { recursive: true });
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const glbPath = path.resolve('artifacts', 'scout_drone_3d.glb');
|
|
18
|
-
console.log('\n2. Exporting 3D Drone Scene to GLB at:', glbPath);
|
|
19
|
-
const exportRes = await mgr.executeTool('export_scene', {
|
|
20
|
-
filepath: glbPath,
|
|
21
|
-
format: 'glb',
|
|
22
|
-
apply_modifiers: true,
|
|
23
|
-
user_prompt: 'Export the complete Scout 3D Drone model to GLB format'
|
|
24
|
-
});
|
|
25
|
-
console.log('Export Result:', exportRes.outputSummary);
|
|
26
|
-
|
|
27
|
-
console.log('\n3. Capturing Viewport Screenshot from Blender...');
|
|
28
|
-
const shotRes = await mgr.executeTool('get_viewport_screenshot', {
|
|
29
|
-
user_prompt: 'Capture high-res viewport screenshot of Scout 3D Drone'
|
|
30
|
-
});
|
|
31
|
-
console.log('Screenshot Status:', shotRes.status);
|
|
32
|
-
if (shotRes.result) {
|
|
33
|
-
try {
|
|
34
|
-
const parsed = typeof shotRes.result === 'string' ? JSON.parse(shotRes.result) : shotRes.result;
|
|
35
|
-
if (parsed && parsed.image_base64) {
|
|
36
|
-
const imgPath = path.resolve('artifacts', 'scout_drone_3d_render.png');
|
|
37
|
-
fs.writeFileSync(imgPath, Buffer.from(parsed.image_base64, 'base64'));
|
|
38
|
-
console.log('Saved 3D render to:', imgPath);
|
|
39
|
-
}
|
|
40
|
-
} catch (e) {
|
|
41
|
-
console.log('Screenshot raw result snippet:', String(shotRes.result).slice(0, 200));
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
console.log('\nAll 3D modeling and export steps complete!');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
main().catch(console.error);
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { getMCPManager } from '../bin/src/mcp/index.js';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
async function main() {
|
|
6
|
-
const mgr = getMCPManager();
|
|
7
|
-
|
|
8
|
-
const artifactsDir = path.resolve('artifacts');
|
|
9
|
-
if (!fs.existsSync(artifactsDir)) {
|
|
10
|
-
fs.mkdirSync(artifactsDir, { recursive: true });
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const glbPath = path.resolve(artifactsDir, 'scout_drone_3d.glb').replace(/\\/g, '/');
|
|
14
|
-
const renderPath = path.resolve(artifactsDir, 'scout_drone_3d_render.png').replace(/\\/g, '/');
|
|
15
|
-
|
|
16
|
-
const pyCode = `
|
|
17
|
-
import bpy
|
|
18
|
-
import math
|
|
19
|
-
|
|
20
|
-
# 1. Setup Camera for dramatic isometric perspective
|
|
21
|
-
cam = bpy.data.objects.get('Camera')
|
|
22
|
-
if not cam:
|
|
23
|
-
bpy.ops.object.camera_add(location=(4.5, -4.5, 3.2))
|
|
24
|
-
cam = bpy.context.active_object
|
|
25
|
-
else:
|
|
26
|
-
cam.location = (4.5, -4.5, 3.2)
|
|
27
|
-
|
|
28
|
-
# Point camera at drone center (0, 0, 0.2)
|
|
29
|
-
cam.rotation_euler = (math.radians(62), 0, math.radians(45))
|
|
30
|
-
bpy.context.scene.camera = cam
|
|
31
|
-
|
|
32
|
-
# 2. Studio Lighting Setup
|
|
33
|
-
# Key Light (Warm gold rim)
|
|
34
|
-
light_key = bpy.data.objects.get('Light')
|
|
35
|
-
if not light_key:
|
|
36
|
-
bpy.ops.object.light_add(type='POINT', location=(3.5, 2.5, 4.0))
|
|
37
|
-
light_key = bpy.context.active_object
|
|
38
|
-
light_key.location = (3.5, 2.5, 4.0)
|
|
39
|
-
light_key.data.energy = 800
|
|
40
|
-
light_key.data.color = (1.0, 0.85, 0.6)
|
|
41
|
-
|
|
42
|
-
# Fill Light (Cool cyan accent)
|
|
43
|
-
bpy.ops.object.light_add(type='POINT', location=(-3.5, -2.5, 2.5))
|
|
44
|
-
light_fill = bpy.context.active_object
|
|
45
|
-
light_fill.name = 'Light_Fill'
|
|
46
|
-
light_fill.data.energy = 500
|
|
47
|
-
light_fill.data.color = (0.2, 0.8, 1.0)
|
|
48
|
-
|
|
49
|
-
# Underglow Rim Light (Purple/Violet rim)
|
|
50
|
-
bpy.ops.object.light_add(type='POINT', location=(0, 0, -2.0))
|
|
51
|
-
light_under = bpy.context.active_object
|
|
52
|
-
light_under.name = 'Light_Underglow'
|
|
53
|
-
light_under.data.energy = 400
|
|
54
|
-
light_under.data.color = (0.7, 0.2, 1.0)
|
|
55
|
-
|
|
56
|
-
# 3. Export to GLB
|
|
57
|
-
bpy.ops.export_scene.gltf(
|
|
58
|
-
filepath='${glbPath}',
|
|
59
|
-
export_format='GLB',
|
|
60
|
-
use_selection=False,
|
|
61
|
-
export_apply=True
|
|
62
|
-
)
|
|
63
|
-
print('EXPORTED_GLB_TO: ${glbPath}')
|
|
64
|
-
|
|
65
|
-
# 4. Render Still Screenshot to PNG
|
|
66
|
-
bpy.context.scene.render.resolution_x = 1280
|
|
67
|
-
bpy.context.scene.render.resolution_y = 720
|
|
68
|
-
bpy.context.scene.render.image_settings.file_format = 'PNG'
|
|
69
|
-
bpy.context.scene.render.filepath = '${renderPath}'
|
|
70
|
-
bpy.ops.render.render(write_still=True)
|
|
71
|
-
print('RENDERED_PNG_TO: ${renderPath}')
|
|
72
|
-
`;
|
|
73
|
-
|
|
74
|
-
console.log('Running GLB Export and Camera Render in Blender via MCP...');
|
|
75
|
-
const result = await mgr.executeTool('execute_blender_code', {
|
|
76
|
-
code: pyCode,
|
|
77
|
-
user_prompt: 'Export 3D Scout Drone to GLB and render studio PNG image'
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
console.log('Result Status:', result.status);
|
|
81
|
-
console.log('Result Output:', result.outputSummary);
|
|
82
|
-
|
|
83
|
-
if (fs.existsSync(glbPath)) {
|
|
84
|
-
const stats = fs.statSync(glbPath);
|
|
85
|
-
console.log(`\n Verified GLB file: ${glbPath} (${stats.size} bytes)`);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (fs.existsSync(renderPath)) {
|
|
89
|
-
const stats = fs.statSync(renderPath);
|
|
90
|
-
console.log(` Verified Render Image: ${renderPath} (${stats.size} bytes)`);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
main().catch(console.error);
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { getMCPManager } from '../bin/src/mcp/index.js';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
async function main() {
|
|
6
|
-
const mgr = getMCPManager();
|
|
7
|
-
|
|
8
|
-
const artifactsDir = path.resolve('artifacts');
|
|
9
|
-
const glbPath = path.resolve(artifactsDir, 'scout_drone_3d.glb').replace(/\\/g, '/');
|
|
10
|
-
const renderPath = path.resolve(artifactsDir, 'scout_drone_3d_render.png').replace(/\\/g, '/');
|
|
11
|
-
|
|
12
|
-
const pyCode = `
|
|
13
|
-
import bpy
|
|
14
|
-
import math
|
|
15
|
-
|
|
16
|
-
# Position camera in front-three-quarter view (looking directly at the glowing front cockpit eye)
|
|
17
|
-
cam = bpy.data.objects.get('Camera')
|
|
18
|
-
if not cam:
|
|
19
|
-
bpy.ops.object.camera_add(location=(3.6, 3.8, 2.4))
|
|
20
|
-
cam = bpy.context.active_object
|
|
21
|
-
else:
|
|
22
|
-
cam.location = (3.6, 3.8, 2.4)
|
|
23
|
-
|
|
24
|
-
cam.rotation_euler = (math.radians(64), 0, math.radians(138))
|
|
25
|
-
bpy.context.scene.camera = cam
|
|
26
|
-
|
|
27
|
-
# Adjust lights for cinematic drama
|
|
28
|
-
# Front Key light on the glowing eye and gold ring
|
|
29
|
-
light_key = bpy.data.objects.get('Light')
|
|
30
|
-
if light_key:
|
|
31
|
-
light_key.location = (2.5, 4.0, 3.5)
|
|
32
|
-
light_key.data.energy = 900
|
|
33
|
-
light_key.data.color = (1.0, 0.92, 0.8)
|
|
34
|
-
|
|
35
|
-
# Cool cyan rim fill on the opposite flank
|
|
36
|
-
light_fill = bpy.data.objects.get('Light_Fill')
|
|
37
|
-
if light_fill:
|
|
38
|
-
light_fill.location = (-4.0, 2.0, 2.8)
|
|
39
|
-
light_fill.data.energy = 650
|
|
40
|
-
light_fill.data.color = (0.0, 0.85, 1.0)
|
|
41
|
-
|
|
42
|
-
# Back rim light for separation
|
|
43
|
-
light_under = bpy.data.objects.get('Light_Underglow')
|
|
44
|
-
if light_under:
|
|
45
|
-
light_under.location = (-1.0, -3.5, 3.0)
|
|
46
|
-
light_under.data.energy = 700
|
|
47
|
-
light_under.data.color = (0.9, 0.4, 1.0)
|
|
48
|
-
|
|
49
|
-
# Export updated GLB with all materials
|
|
50
|
-
bpy.ops.export_scene.gltf(
|
|
51
|
-
filepath='${glbPath}',
|
|
52
|
-
export_format='GLB',
|
|
53
|
-
use_selection=False,
|
|
54
|
-
export_apply=True
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
# Render cinematic 1280x720 still
|
|
58
|
-
bpy.context.scene.render.resolution_x = 1280
|
|
59
|
-
bpy.context.scene.render.resolution_y = 720
|
|
60
|
-
bpy.context.scene.render.image_settings.file_format = 'PNG'
|
|
61
|
-
bpy.context.scene.render.filepath = '${renderPath}'
|
|
62
|
-
bpy.ops.render.render(write_still=True)
|
|
63
|
-
print('FRONT_CINEMATIC_RENDER_COMPLETE')
|
|
64
|
-
`;
|
|
65
|
-
|
|
66
|
-
console.log('Rendering front cinematic view in Blender...');
|
|
67
|
-
const result = await mgr.executeTool('execute_blender_code', {
|
|
68
|
-
code: pyCode,
|
|
69
|
-
user_prompt: 'Render front cinematic camera angle of 3D Scout Drone'
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
console.log('Result Status:', result.status);
|
|
73
|
-
console.log('Output Summary:', result.outputSummary);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
main().catch(console.error);
|