owenkaplinsky commited on
Commit
7660e27
Β·
1 Parent(s): 1e62dc6

Make user message block; infinite

Browse files
{hello-world β†’ project}/.npmignore RENAMED
File without changes
{hello-world β†’ project}/app.py RENAMED
File without changes
{hello-world β†’ project}/package-lock.json RENAMED
@@ -9,6 +9,7 @@
9
  "version": "1.0.0",
10
  "license": "Apache-2.0",
11
  "dependencies": {
 
12
  "blockly": "^11.0.0"
13
  },
14
  "devDependencies": {
@@ -33,6 +34,14 @@
33
  "lru-cache": "^10.4.3"
34
  }
35
  },
 
 
 
 
 
 
 
 
36
  "node_modules/@csstools/color-helpers": {
37
  "version": "5.1.0",
38
  "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz",
 
9
  "version": "1.0.0",
10
  "license": "Apache-2.0",
11
  "dependencies": {
12
+ "@blockly/toolbox-search": "^3.0.2",
13
  "blockly": "^11.0.0"
14
  },
15
  "devDependencies": {
 
34
  "lru-cache": "^10.4.3"
35
  }
36
  },
37
+ "node_modules/@blockly/toolbox-search": {
38
+ "version": "3.0.2",
39
+ "resolved": "https://registry.npmjs.org/@blockly/toolbox-search/-/toolbox-search-3.0.2.tgz",
40
+ "integrity": "sha512-NnwK9hjyxhCOmCuF1FGH8Ca+wiZ7E7LWFdx+X8Bi4szZkPBLd9ZY3lp8bWi9WlmQax3sXQ3QAMC9/bq2OXAkdw==",
41
+ "peerDependencies": {
42
+ "blockly": "^12.0.0"
43
+ }
44
+ },
45
  "node_modules/@csstools/color-helpers": {
46
  "version": "5.1.0",
47
  "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz",
{hello-world β†’ project}/package.json RENAMED
@@ -24,6 +24,7 @@
24
  "webpack-dev-server": "^4.11.1"
25
  },
26
  "dependencies": {
 
27
  "blockly": "^11.0.0"
28
  }
29
- }
 
24
  "webpack-dev-server": "^4.11.1"
25
  },
26
  "dependencies": {
27
+ "@blockly/toolbox-search": "^3.0.2",
28
  "blockly": "^11.0.0"
29
  }
30
+ }
{hello-world β†’ project}/src/blocks/text.js RENAMED
@@ -1,21 +1,19 @@
1
- /**
2
- * @license
3
- * Copyright 2023 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
  import * as Blockly from 'blockly/core';
8
 
9
  const whenUserSends = {
10
  type: 'when_user_sends',
11
- message0: 'when user sends message do %1 %2',
12
  args0: [
 
 
 
 
13
  {
14
  "type": "input_dummy"
15
  },
16
  {
17
  "type": "input_statement",
18
- "name": "code"
19
  }
20
  ],
21
  inputsInline: true,
@@ -43,7 +41,7 @@ const assistantReply = {
43
 
44
  const getAssistantResponse = {
45
  type: 'get_assistant_response',
46
- message0: 'call model %1 with prompt %2 with %3',
47
  args0: [
48
  {
49
  type: 'field_dropdown',
@@ -62,8 +60,8 @@ const getAssistantResponse = {
62
  type: 'field_dropdown',
63
  name: 'HISTORY',
64
  options: [
65
- ["history", "True"],
66
- ["no history", "False"]
67
  ]
68
  },
69
  ],
@@ -74,8 +72,18 @@ const getAssistantResponse = {
74
  helpUrl: '',
75
  };
76
 
 
 
 
 
 
 
 
 
 
77
  export const blocks = Blockly.common.createBlockDefinitionsFromJsonArray([
78
  whenUserSends,
79
  assistantReply,
80
  getAssistantResponse,
 
81
  ]);
 
 
 
 
 
 
 
1
  import * as Blockly from 'blockly/core';
2
 
3
  const whenUserSends = {
4
  type: 'when_user_sends',
5
+ message0: 'when user sends %1 do %2 %3',
6
  args0: [
7
+ {
8
+ "type": "input_value",
9
+ "name": "DUPLICATE"
10
+ },
11
  {
12
  "type": "input_dummy"
13
  },
14
  {
15
  "type": "input_statement",
16
+ "name": "CODE"
17
  }
18
  ],
19
  inputsInline: true,
 
41
 
42
  const getAssistantResponse = {
43
  type: 'get_assistant_response',
44
+ message0: 'call model %1 with prompt %2 %3 history',
45
  args0: [
46
  {
47
  type: 'field_dropdown',
 
60
  type: 'field_dropdown',
61
  name: 'HISTORY',
62
  options: [
63
+ ["with", "True"],
64
+ ["without", "False"]
65
  ]
66
  },
67
  ],
 
72
  helpUrl: '',
73
  };
74
 
75
+ const user_message = {
76
+ type: "user_message",
77
+ message0: "user message",
78
+ output: "String",
79
+ colour: "#47A8D1",
80
+ tooltip: "",
81
+ helpUrl: "",
82
+ };
83
+
84
  export const blocks = Blockly.common.createBlockDefinitionsFromJsonArray([
85
  whenUserSends,
86
  assistantReply,
87
  getAssistantResponse,
88
+ user_message
89
  ]);
{hello-world β†’ project}/src/generators/python.js RENAMED
@@ -4,7 +4,7 @@ export const forBlock = Object.create(null);
4
 
5
  // Generates a Python function that runs when the user sends a message
6
  forBlock['when_user_sends'] = function (block, generator) {
7
- const body = generator.statementToCode(block, 'code') || "";
8
  const code = `def on_user_send(user_message):\n${body} return\n`;
9
  return code;
10
  };
@@ -23,4 +23,9 @@ forBlock['get_assistant_response'] = function (block, generator) {
23
 
24
  const code = `get_assistant_response(${prompt}, model="${model}", use_history=${history})`;
25
  return [code, Order.NONE];
 
 
 
 
 
26
  };
 
4
 
5
  // Generates a Python function that runs when the user sends a message
6
  forBlock['when_user_sends'] = function (block, generator) {
7
+ const body = generator.statementToCode(block, 'CODE') || "";
8
  const code = `def on_user_send(user_message):\n${body} return\n`;
9
  return code;
10
  };
 
23
 
24
  const code = `get_assistant_response(${prompt}, model="${model}", use_history=${history})`;
25
  return [code, Order.NONE];
26
+ };
27
+
28
+ forBlock['user_message'] = function (block, generator) {
29
+ const code = `user_message`;
30
+ return [code, generator.ORDER_NONE];
31
  };
{hello-world β†’ project}/src/index.css RENAMED
File without changes
{hello-world β†’ project}/src/index.html RENAMED
File without changes
{hello-world β†’ project}/src/index.js RENAMED
@@ -1,15 +1,10 @@
1
- /**
2
- * @license
3
- * Copyright 2023 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
  import * as Blockly from 'blockly';
8
  import { blocks } from './blocks/text';
9
  import { forBlock } from './generators/python';
10
  import { pythonGenerator } from 'blockly/python';
11
  import { save, load } from './serialization';
12
  import { toolbox } from './toolbox';
 
13
  import './index.css';
14
 
15
  // Register the blocks and generator with Blockly
@@ -48,21 +43,16 @@ const myTheme = Blockly.Theme.defineTheme('myScratchTheme', {
48
  // Inject Blockly with theme + renderer
49
  const ws = Blockly.inject(blocklyDiv, {
50
  toolbox,
 
 
 
 
 
 
51
  renderer: 'zelos',
52
  theme: myTheme,
53
  });
54
 
55
- if (!ws.getVariable('user_message')) {
56
- ws.createVariable('user_message');
57
- }
58
-
59
- ws.updateUserMessage = (message) => {
60
- let variable = ws.getVariable('user_message');
61
- if (!variable) ws.createVariable('user_message');
62
- ws.variableValues = ws.variableValues || {};
63
- ws.variableValues['user_message'] = message;
64
- };
65
-
66
  const updateCode = () => {
67
  let code = pythonGenerator.workspaceToCode(ws);
68
  const codeEl = document.querySelector('#generatedCode code');
@@ -120,8 +110,45 @@ updateCode();
120
  ws.addChangeListener((e) => {
121
  if (e.isUiEvent) return;
122
 
123
- if (!ws.getVariable('user_message')) {
124
- ws.createVariable('user_message');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
126
 
127
  save(ws);
@@ -141,16 +168,14 @@ window.addEventListener("message", (event) => {
141
  });
142
 
143
  function handleUserMessage(message) {
144
- if (window.Blockly && window.ws) {
145
- let v = ws.getVariable('user_message') || ws.createVariable('user_message');
146
- ws.variableValues = ws.variableValues || {};
147
- ws.variableValues['user_message'] = message;
 
148
  }
149
 
150
  if (typeof window.userSendHandler === "function") {
151
- console.log("[PARENT] userSendHandler exists, invoking it");
152
  window.userSendHandler(message);
153
- } else {
154
- console.warn("[PARENT] userSendHandler is undefined!");
155
  }
156
- }
 
 
 
 
 
 
 
1
  import * as Blockly from 'blockly';
2
  import { blocks } from './blocks/text';
3
  import { forBlock } from './generators/python';
4
  import { pythonGenerator } from 'blockly/python';
5
  import { save, load } from './serialization';
6
  import { toolbox } from './toolbox';
7
+ import '@blockly/toolbox-search';
8
  import './index.css';
9
 
10
  // Register the blocks and generator with Blockly
 
43
  // Inject Blockly with theme + renderer
44
  const ws = Blockly.inject(blocklyDiv, {
45
  toolbox,
46
+ grid: {
47
+ spacing: 35,
48
+ length: 3,
49
+ colour: '#ccc',
50
+ snap: false
51
+ },
52
  renderer: 'zelos',
53
  theme: myTheme,
54
  });
55
 
 
 
 
 
 
 
 
 
 
 
 
56
  const updateCode = () => {
57
  let code = pythonGenerator.workspaceToCode(ws);
58
  const codeEl = document.querySelector('#generatedCode code');
 
110
  ws.addChangeListener((e) => {
111
  if (e.isUiEvent) return;
112
 
113
+ save(ws);
114
+ });
115
+
116
+ ws.addChangeListener((event) => {
117
+ if (event.isUiEvent) return;
118
+
119
+ if (event.type === Blockly.Events.BLOCK_MOVE) {
120
+ if (event.oldParentId && !event.newParentId) {
121
+ const removedBlock = ws.getBlockById(event.blockId);
122
+ const oldParent = ws.getBlockById(event.oldParentId);
123
+
124
+ if (
125
+ removedBlock &&
126
+ oldParent &&
127
+ removedBlock.type === 'user_message' &&
128
+ oldParent.type === 'when_user_sends'
129
+ ) {
130
+ console.log('[DISCONNECT] user_message removed from when_user_sends');
131
+
132
+ if (event.oldInputName) {
133
+ Blockly.Events.disable();
134
+ try {
135
+ const newMsgBlock = ws.newBlock('user_message');
136
+ newMsgBlock.initSvg();
137
+ newMsgBlock.render();
138
+
139
+ const input = oldParent.getInput(event.oldInputName);
140
+ if (input) {
141
+ input.connection.connect(newMsgBlock.outputConnection);
142
+ console.log('[REPLACE] user_message restored instantly (no blink)');
143
+ }
144
+
145
+ ws.render(); // ensure workspace updates immediately
146
+ } finally {
147
+ Blockly.Events.enable();
148
+ }
149
+ }
150
+ }
151
+ }
152
  }
153
 
154
  save(ws);
 
168
  });
169
 
170
  function handleUserMessage(message) {
171
+ const blocks = ws.getAllBlocks();
172
+ const msgBlock = blocks.find(b => b.type === 'user_message');
173
+ if (msgBlock) {
174
+ msgBlock.setFieldValue(message, 'TEXT');
175
+ console.log(`[Blockly] Updated user_message with: ${message}`);
176
  }
177
 
178
  if (typeof window.userSendHandler === "function") {
 
179
  window.userSendHandler(message);
 
 
180
  }
181
+ }
{hello-world β†’ project}/src/serialization.js RENAMED
File without changes
{hello-world β†’ project}/src/toolbox.js RENAMED
@@ -1,20 +1,14 @@
1
- /**
2
- * @license
3
- * Copyright 2023 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- /*
8
- This toolbox contains nearly every single built-in block that Blockly offers,
9
- in addition to the custom block 'add_text' this sample app adds.
10
- You probably don't need every single block, and should consider either rewriting
11
- your toolbox from scratch, or carefully choosing whether you need each block
12
- listed here.
13
- */
14
-
15
  export const toolbox = {
16
  kind: 'categoryToolbox',
17
  contents: [
 
 
 
 
 
 
 
 
18
  {
19
  kind: 'category',
20
  name: 'Custom',
@@ -23,6 +17,14 @@ export const toolbox = {
23
  {
24
  kind: 'block',
25
  type: 'when_user_sends',
 
 
 
 
 
 
 
 
26
  },
27
  {
28
  kind: 'block',
@@ -34,17 +36,16 @@ export const toolbox = {
34
  inputs: {
35
  PROMPT: {
36
  shadow: {
37
- type: "variables_get",
38
- fields: {
39
- VAR: {
40
- name: "user_message",
41
- type: "String"
42
- }
43
- }
44
  }
45
  },
46
  },
47
  },
 
 
 
 
48
  ]
49
  },
50
  {
@@ -497,24 +498,6 @@ export const toolbox = {
497
  kind: 'block',
498
  type: 'lists_create_with',
499
  },
500
- {
501
- kind: 'block',
502
- type: 'lists_create_with',
503
- },
504
- {
505
- kind: 'block',
506
- type: 'lists_repeat',
507
- inputs: {
508
- NUM: {
509
- shadow: {
510
- type: 'math_number',
511
- fields: {
512
- NUM: 5,
513
- },
514
- },
515
- },
516
- },
517
- },
518
  {
519
  kind: 'block',
520
  type: 'lists_length',
@@ -567,20 +550,6 @@ export const toolbox = {
567
  },
568
  },
569
  },
570
- {
571
- kind: 'block',
572
- type: 'lists_split',
573
- inputs: {
574
- DELIM: {
575
- shadow: {
576
- type: 'text',
577
- fields: {
578
- TEXT: ',',
579
- },
580
- },
581
- },
582
- },
583
- },
584
  {
585
  kind: 'block',
586
  type: 'lists_sort',
@@ -602,7 +571,7 @@ export const toolbox = {
602
  },
603
  {
604
  kind: 'category',
605
- name: 'Functions',
606
  categorystyle: 'procedure_category',
607
  custom: 'PROCEDURE',
608
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  export const toolbox = {
2
  kind: 'categoryToolbox',
3
  contents: [
4
+ {
5
+ 'kind': 'search',
6
+ 'name': 'Search',
7
+ 'contents': [],
8
+ },
9
+ {
10
+ 'kind': 'sep',
11
+ },
12
  {
13
  kind: 'category',
14
  name: 'Custom',
 
17
  {
18
  kind: 'block',
19
  type: 'when_user_sends',
20
+ inputs: {
21
+ DUPLICATE: {
22
+ block: {
23
+ kind: "block",
24
+ type: "user_message"
25
+ }
26
+ },
27
+ },
28
  },
29
  {
30
  kind: 'block',
 
36
  inputs: {
37
  PROMPT: {
38
  shadow: {
39
+ kind: "block",
40
+ type: "user_message"
 
 
 
 
 
41
  }
42
  },
43
  },
44
  },
45
+ {
46
+ kind: 'block',
47
+ type: 'user_message',
48
+ },
49
  ]
50
  },
51
  {
 
498
  kind: 'block',
499
  type: 'lists_create_with',
500
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
501
  {
502
  kind: 'block',
503
  type: 'lists_length',
 
550
  },
551
  },
552
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
553
  {
554
  kind: 'block',
555
  type: 'lists_sort',
 
571
  },
572
  {
573
  kind: 'category',
574
+ name: 'Tools',
575
  categorystyle: 'procedure_category',
576
  custom: 'PROCEDURE',
577
  },
{hello-world β†’ project}/webpack.config.js RENAMED
File without changes